Toggle-able Lava or Poison Water, Disappearing Boos etc.

Share and discuss custom LunaLua code and content packs for SMBX2.

Moderator: Userbase Moderators

BroccoliRampage
Hoopster
Hoopster
Posts: 49
Joined: Fri Jan 31, 2020 7:39 pm
Flair: Moop!

Toggle-able Lava or Poison Water, Disappearing Boos etc.

Postby BroccoliRampage » Sun Mar 08, 2020 12:58 pm

I'd like to share one of my first significant custom creations using Luna Lua code!

This is a layer which can be switched on and off, or set to vanish and reappear after a set time, and is perfect for that "water that turns back into lava or poison" seen in levels like Donkey Kong Country 2's "Lava Lagoon". It can also be used to create your own "vanishing Boo" effect which is what I had originally created it for. Or the "ghost ropes" NPC of Donkey Kong Country. It also includes a handy "warn" event that is activated by a timer variable created in the code.

I owe thanks to: MrDoubleA, InfernoGuy and Cedur for helping me to iron out some snafus with the code and generally for being tolerant of a noob.

Images Code
Spoiler: show
Code:
```
local timer = 1280


function onStart()
startlayer = Layer.get("Toxic")
end


-- Run code every frame (~1/65 second)
-- (code will be executed before game logic will be processed)

function onTick()
if timer <=0 then
triggerEvent("comeback");
timer = 1280
end
if timer == 496 then
triggerEvent("warn")
end
if timer == 378 then
triggerEvent("warn")
end
if timer == 256 then
triggerEvent("warn")
end
if timer == 128 then
triggerEvent("warn")
end


if startlayer.isHidden then
timer = timer-1
end
end

-- Run code when internal event of the SMBX Engine has been triggered
-- eventName - name of triggered event

function onEvent(eventName)

if eventName == "goaway" then
timer = 1280
end

end

function onDraw()
Text.print(timer, 100, 100)
end```
Tips & Explanation
Spoiler: show

Events:
goaway
comeback
Toxic
warn

1. Important - In my attempts, I have only found one block that works well with this. That's block 673 the "Instant Kill Block". Simply replace the graphic with your own (preferably 75% opacity) eerie neon color. I tried other kill blocks like lava but these have a weird glow effect that does strange things.
2. Make sure all the blocks you place are on a dedicated layer (here, it's layer "Toxic"). Set up a switch block to toggle the event called "goaway".
3) Here's why you need Lua code. You'll need to create a timer to specify when the Toxic layer reappears. Technically, you can do this through the editor using an event, but keep in mind that if/when a player hits the next "goaway" switch, the previous instance of that event will still be counting down. Also, if you have a timer/warning sound, it would be tied to that event and continue to go off even if you've hit the next switch. Use code to create a timer variable, and to trigger the "comeback" event at 0.
4) Another stumbling block: Be sure that in your code to trigger the event "comeback" you also tell it to reset the timer to 1260. Reason is if you don't, the code will loop, since you're timer is stuck at 0 it'll spam activate the "comeback" event and bog down the game significantly. This is going to be crucial because if you maintain any areas in the level where the Toxic layer is not present (tunnels, safe areas etc) once that timer goes down to 0 the code will basically become an infinite loop of doom.
5) Be judicious in placement of the "toxic" blocks. If you can't reach a distant area before dying, don't place blocks in it. You have a limit of 16k blocks per section, which doesn't go as far as you'd think. You'll probably need to plan this kind of level in multiple smaller sections.
6) The temptation will be to make the timer correspond to seconds & simply alter the countdown factor in the code. I used 1260 which is 64 frames x 20 seconds. Unless better minds than mine know of a way, be advised that using a factor such as .01 will turn your timer into a decimal and wreak havoc with your encoded warning timers. I tried various workarounds but ended up deciding that seeing 1260 count down over 20 seconds was better than not being able to have a "warn" sound for the player.
Have fun!

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9890
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Toggle-able Lava or Poison Water, Disappearing Boos etc.

Postby Emral » Sun Mar 08, 2020 1:15 pm

Few improvement suggestions:

As it stands, this is not a library. It's part of luna.lua. Consider following this tutorial to modify it as a library that can be loaded with require(libraryname), exposing things that can be modified as fields in the library table (myLibraryTable.maxDisappearTimer = 1280, for example). The benefits of having it as a library would be that users wouldn't have to manually merge this with their existing luna.lua file and wouldn't have to worry about file conflicts.

It's generally good practice to keep all variables defined local at the library scope (or in a more contained scope if you don't need it across functions). This is so that other scripts don't also have access to the variable without explicitly requesting it.

Enforcing layer and event names seems a little iffy. To reduce the amount of work the user has to do to get this to work, consider removing the use of events except for the goaway and comeback events and exposing the layer name and goaway/comeback event name to seek as a variable (myLibraryTable.layerName = "Toxic"). If you want to provide an optional default behaviour for the events (in case someone would want them to do nothing in the editor) you can easily show/hide layers with the layer reference (myLayer:toggle(true) for a toggle without smoke). Just an idea.
The warning would need to be offloaded to lua too, which is fairly easy to do, considering all SMBX-internal sounds can be played simply with SFX.play(index), where index is the internal numerical index of the sound file. You can find all sound indices in data/_templates/sounds.ini, and also expose this as a configurable variable to the user (myLibraryTable.warnSound = 24). Alternatively, making the name of this configurable follows the same procedure as the other two.

Just a few things to consider if you intend to iterate upon this idea. I think for a first script this is pretty awesome! Layer loops are very common and I hope you're learning a lot from this exercise. I'll briefly mention this advanced idea that might pique your interest as well:
Something events cannot do but lua can is explicitly stop an "event loop". Maybe such a feature would be useful ;p

Looking forward to more from you!

BroccoliRampage
Hoopster
Hoopster
Posts: 49
Joined: Fri Jan 31, 2020 7:39 pm
Flair: Moop!

Re: Toggle-able Lava or Poison Water, Disappearing Boos etc.

Postby BroccoliRampage » Sun Mar 08, 2020 1:23 pm

Enjl wrote:
Sun Mar 08, 2020 1:15 pm
Few improvement suggestions:

As it stands, this is not a library. It's part of luna.lua. Consider following this tutorial to modify it as a library that can be loaded with require(libraryname), exposing things that can be modified as fields in the library table (myLibraryTable.maxDisappearTimer = 1280, for example). The benefits of having it as a library would be that users wouldn't have to manually merge this with their existing luna.lua file and wouldn't have to worry about file conflicts.

It's generally good practice to keep all variables defined local at the library scope (or in a more contained scope if you don't need it across functions). This is so that other scripts don't also have access to the variable without explicitly requesting it.

Enforcing layer and event names seems a little iffy. To reduce the amount of work the user has to do to get this to work, consider removing the use of events except for the goaway and comeback events and exposing the layer name and goaway/comeback event name to seek as a variable (myLibraryTable.layerName = "Toxic"). If you want to provide an optional default behaviour for the events (in case someone would want them to do nothing in the editor) you can easily show/hide layers with the layer reference (myLayer:toggle(true) for a toggle without smoke). Just an idea.
The warning would need to be offloaded to lua too, which is fairly easy to do, considering all SMBX-internal sounds can be played simply with SFX.play(index), where index is the internal numerical index of the sound file. You can find all sound indices in data/_templates/sounds.ini, and also expose this as a configurable variable to the user (myLibraryTable.warnSound = 24). Alternatively, making the name of this configurable follows the same procedure as the other two.

Just a few things to consider if you intend to iterate upon this idea. I think for a first script this is pretty awesome! Layer loops are very common and I hope you're learning a lot from this exercise. I'll briefly mention this advanced idea that might pique your interest as well:
Something events cannot do but lua can is explicitly stop an "event loop". Maybe such a feature would be useful ;p

Looking forward to more from you!
Thanks! I will look into all this and improve my coding practices. For myself, I'm literally just learning how the basic code works and I'm sure others can implement this same technique much more eloquently. I literally spent hours trying to figure out what was bogging down the gameplay, before I realized there was a logic loop going on under the hood. I need to learn about libraries and that's the next logical step.

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9890
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Toggle-able Lava or Poison Water, Disappearing Boos etc.

Postby Emral » Sun Mar 08, 2020 1:32 pm

Yeah sometimes you just run into loops where you're blind to an (in hindsight) obvious mistake. Happened to me just yesterday, too, hah.
When learning about libraries, it might help to also take a look at lua's concept of tables. They're these things denoted with {} and are lua's substitute for lists, arrays, as well as classes. If those terms are familiar to you. Basically you can, on one side, put numbers/strings/anything in {1,2,3,4,5,6} and have a list of things you put in. On the other side you can put ANYTHING in. And that's also how libraries work. They can also be indexed with any data type. Here's the general idea:
----
local myLibrary = {}
myLibrary.myExposedValue = false -- this is the same as myLibrary["myExposedValue"] = true (string index)
myLibrary[false] = Graphics.loadImage("falseImage.png") -- boolean index
myLibrary[1] = 2
return myLibrary
---- This is also the same as:
return {
myExposedValue = false,
[false] = Graphics.loadImage("falseImage.png"),
[1] = 2
}
----
You might see libraries sometimes mentioned as "the library table", and this is why. I encourage you to experiment a bit with them and see what they're capable of. For this library, maybe it might be fun to index a table with a number from the timer, and assign a value as a sound effect ID, to play specific sounds at specific timer values.


Return to “LunaLua”

Who is online

Users browsing this forum: No registered users and 3 guests

SMWCentralTalkhausMario Fan Games GalaxyKafukaMarioWikiSMBXEquipoEstelari