(shouting)

LunaDLL/LunaLUA help thread

The second SMBX collab!
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: LunaDLL/LunaLUA help thread

Post by Rednaxela »

SAJewers wrote:ping
Kev was talking about something different, if you want to trigger a p-switch effect from Lua code.

Anyway, here you go.
  1. Update LuaScriptsLib\core\defines.lua from this version (will be included in future LunaLua updates)
  2. Unzip the pSwitchTicking library into LuaScriptsLib
    pSwitchTicking.zip
    (22.8 KiB) Downloaded 104 times
    (will be included in future LunaLua updates)
  3. Put the line

    Code: Select all

    loadSharedAPI("pSwitchTicking")
    in the lunadll.lua or lunaworld.lua where you want it to apply. I assume probably lunaworld.lua for A2XT usage.
(Technical details: I used the .wav file provided as the basis, but cropped it down to a single repetition (precisely 1.066 seconds) and set it to auto-loop, so that the audio file could be super small.

The defines.lua update contains that capability of applying an asm patch to disable normal SMBX p-switch music effects. The pSwitchTicking.lua API activates this, and then listens for "P Switch - Start" and "P Switch - End" SMBX events to trigger start/stop of an auto-looping sound)
User avatar
SAJewers
ASMBXT Level Wrangler/A2XT Project Coordinator /AAT Level Designer
Posts: 4200
Joined: 11 years ago
Location: Nova Scotia

Re: LunaDLL/LunaLUA help thread

Post by SAJewers »

Thanks. However, it's missing the sound effect near the end that's supposed to signal the end of the p-switch effect (something that's also in SMW's original jingle): https://onedrive.live.com/redir?resid=A ... file%2cogg
Start also isn't exactly right, but that can probably be rectified by replacing the "hit p-switch sound effect".




Also, this doesn't work with the SMB3 P-Switch or stopwatches; it'd be nice if it did (though I'm not worrying about it).

EDIT: For comparison, if you need it, here's how it sounds/works in A2MT:


ImageImageImageImageImage | Image | Image
Sharenite | RetroAchievements | NameMC | IGDB
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: LunaDLL/LunaLUA help thread

Post by Rednaxela »

SAJewers wrote:Thanks. However, it's missing the sound effect near the end that's supposed to signal the end of the p-switch effect (something that's also in SMW's original jingle): https://onedrive.live.com/redir?resid=A ... file%2cogg
Ahh right, that there's an easy fix, and thanks for linking that sound file, that helps. I'll add that.
SAJewers wrote:Start also isn't exactly right, but that can probably be rectified by replacing the "hit p-switch sound effect".
Are you referring to the stuttery double-beat at the start? I had interpreted that as a glitch rather than an intended aspect of it.
SAJewers wrote:Also, this doesn't work with the SMB3 P-Switch or stopwatches; it'd be nice if it did (though I'm not worrying about it).
Would you want the same chime for the timestop ones as normal SMW P-Switch really? I'd tend to think it would be better to use a different 'ticking' for that case, as it's quite a distinctly different mechanical effect.
User avatar
SAJewers
ASMBXT Level Wrangler/A2XT Project Coordinator /AAT Level Designer
Posts: 4200
Joined: 11 years ago
Location: Nova Scotia

Re: LunaDLL/LunaLUA help thread

Post by SAJewers »

We can probably come up with a different sound effect for it.

As for the "double beat", I believe that might just be the sound effect for hitting the P-switch being changed, and overlaying ontop.
ImageImageImageImageImage | Image | Image
Sharenite | RetroAchievements | NameMC | IGDB
User avatar
ztarwuff
What the heck is a flair and why am I being asked to write one for my profile?
Posts: 550
Joined: 10 years ago
Location: Within 2 miles of the Imperial Crypt of Napoleon III

Re: LunaDLL/LunaLUA help thread

Post by ztarwuff »

I was just wondering, how exactly does the OnEvent function work? I ask, because no matter what event I trigger in the engine, it seems to call up the same code. I have multiple events in my level, but only three LunaLua event codes:

Code: Select all

function onEvent(UpDownRaoEv)
playMusic(18)
--Filter to raocow
	if (player.isValid) then
    player:mem(0xF0, FIELD_WORD, 4)
	end
end

function onEvent(MonoPrinceEv)
playMusic(19)
end

function onEvent(ANMT)
playMusic(20)
end
I've set up a whole load of invisible axes throughout the level which trigger events upon death. My understanding is that when I collect an axe set to trigger UpDownRaoEV, it will play music from section 19 and will then filter to raocow. Except it doesn't. For some reason, every event I trigger activates function onEvent(ANMT), presumably because ANMT comes first alphabetically evne though UpDownRaoEV was placed first in the Lunalua file.

Any help would be greatly appreciated.
User avatar
SAJewers
ASMBXT Level Wrangler/A2XT Project Coordinator /AAT Level Designer
Posts: 4200
Joined: 11 years ago
Location: Nova Scotia

Re: LunaDLL/LunaLUA help thread

Post by SAJewers »

You need If Statements to check the name of the event. The thing in brackets is not the name of the event the function checks for; the name of the event is passed to the function (as a string) and stored in the thing in brackets.

Code: Select all

function onEvent(canada)
if canada == "UpDownRaoEv" then
playMusic(18)
--Filter to raocow
   if (player.isValid) then
    player:mem(0xF0, FIELD_WORD, 4)
   end
end
elseif canada == "MonoPrinceEv" then
playMusic(19)

end
elseif canada== "ANMT" then
playMusic(20)
ImageImageImageImageImage | Image | Image
Sharenite | RetroAchievements | NameMC | IGDB
User avatar
ztarwuff
What the heck is a flair and why am I being asked to write one for my profile?
Posts: 550
Joined: 10 years ago
Location: Within 2 miles of the Imperial Crypt of Napoleon III

Re: LunaDLL/LunaLUA help thread

Post by ztarwuff »

SAJewers wrote:You need If Statements to check the name of the event. The thing in brackets is not the name of the event the function checks for; the name of the event is passed to the function (as a string) and stored in the thing in brackets.

Code: Select all

function onEvent(canada)
if canada == "UpDownRaoEv" then
playMusic(18)
--Filter to raocow
   if (player.isValid) then
    player:mem(0xF0, FIELD_WORD, 4)
   end
end
elseif canada == "MonoPrinceEv" then
playMusic(19)

end
elseif canada== "ANMT" then
playMusic(20)
Oh, I see. Thanks for the help. The wiki didn't really make that clear.
User avatar
Holy
Posts: 133
Joined: 12 years ago

Re: LunaDLL/LunaLUA help thread

Post by Holy »

Is it possible to get lunadll to stop drawing an image within a specified area? Like, it still draws the image, but it leaves out the parts that fall within certain x and y coordinates?
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: LunaDLL/LunaLUA help thread

Post by Hoeloe »

Holy wrote:Is it possible to get lunadll to stop drawing an image within a specified area? Like, it still draws the image, but it leaves out the parts that fall within certain x and y coordinates?
There are ways to do that, but not easily. Either you can draw the image with width and height values several times around the area you want to cut out, or you can use OpenGL to create a mesh that surrounds that area. Either one is pretty complex to do, but depends exactly what you're trying to do with it.
Image
Image
Image
Image
Image
S1eth
Posts: 291
Joined: 9 years ago

Re: LunaDLL/LunaLUA help thread

Post by S1eth »

Hoeloe wrote:
Holy wrote:Is it possible to get lunadll to stop drawing an image within a specified area? Like, it still draws the image, but it leaves out the parts that fall within certain x and y coordinates?
There are ways to do that, but not easily. Either you can draw the image with width and height values several times around the area you want to cut out, or you can use OpenGL to create a mesh that surrounds that area. Either one is pretty complex to do, but depends exactly what you're trying to do with it.
What exactly are the contents of a luaImageResource? Is it just a table or RGBA values? Could you edit (a copy of) that at runtime to make certain parts of it invisible/transparent (change alpha)? (like applying a mask)
Image
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: LunaDLL/LunaLUA help thread

Post by Hoeloe »

S1eth wrote:
Hoeloe wrote:
Holy wrote:Is it possible to get lunadll to stop drawing an image within a specified area? Like, it still draws the image, but it leaves out the parts that fall within certain x and y coordinates?
There are ways to do that, but not easily. Either you can draw the image with width and height values several times around the area you want to cut out, or you can use OpenGL to create a mesh that surrounds that area. Either one is pretty complex to do, but depends exactly what you're trying to do with it.
What exactly are the contents of a luaImageResource? Is it just a table or RGBA values? Could you edit (a copy of) that at runtime to make certain parts of it invisible/transparent (change alpha)? (like applying a mask)
You technically can I think, but only if you want to shoot your framerate in the foot.
Image
Image
Image
Image
Image
User avatar
Holy
Posts: 133
Joined: 12 years ago

Re: LunaDLL/LunaLUA help thread

Post by Holy »

Hmm, alright. I actually have one idea for this I'll try when I get the chance, but yeah, I don't think it's worth getting super complex in this case.
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: LunaDLL/LunaLUA help thread

Post by Rednaxela »

Hoeloe wrote:
S1eth wrote:What exactly are the contents of a luaImageResource? Is it just a table or RGBA values? Could you edit (a copy of) that at runtime to make certain parts of it invisible/transparent (change alpha)? (like applying a mask)
You technically can I think, but only if you want to shoot your framerate in the foot.
Nah, you can't. LuaImageResource does give a method that can translate the contents into a big Lua table of RGBA values, but there is no method to get altered pixels back into it.
If I were to make a way to get altered pixels back into it though... I would take measures that would allow it to be *far* faster than the current stuff for getting pixels out of it into Lua tables (by which I mean LuaJIT FFI methods to allow direct highly optimized access)
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: LunaDLL/LunaLUA help thread

Post by Hoeloe »

Rednaxela wrote:I would take measures that would allow it to be *far* faster than the current stuff for getting pixels out of it into Lua tables (by which I mean LuaJIT FFI methods to allow direct highly optimized access)
Even then, this is really a job for pixel shaders.
Image
Image
Image
Image
Image
User avatar
7NameSam
hey
Posts: 248
Joined: 9 years ago
Pronouns: they/them

Re: LunaDLL/LunaLUA help thread

Post by 7NameSam »

How Do you use PNPC?
User avatar
Rednaxela
Maker of Shenanigans
Posts: 897
Joined: 10 years ago
Pronouns: they/them
https://rednaxela.talkhaus.com

Re: LunaDLL/LunaLUA help thread

Post by Rednaxela »

7NameSam wrote:How Do you use PNPC?
The documentation is here

Basically, NPC instances can normally only be trusted to be valid on the same tick you retrieved it. An example of usage is like:

Code: Select all

local pnpc = loadSharedAPI("pnpc")

local myNpc = nil

function onStart()
	-- Get the first npc-42 that exists in the level
	local npc = NPC.get(42)[1]
	
	-- it's not valid across multiple ticks, so let's wrap it in a pnpc object and
	-- store it in the myNpc variable
	myNpc = pnpc.wrap(npc)
end

function onTick()
	-- We can now do anything we want with myNpc here, even on later ticks.
	-- You may be want to check myNpc.isValid though, to check if the NPC
	-- has died. After all, if it's dead and gone you can't use it anymore.
	
	if myNpc.isValid then
		-- the NPC is still valid, so we can trust to be able to use it here
		Text.print(myNpc.x, 100, 100)
	end
end
User avatar
SAJewers
ASMBXT Level Wrangler/A2XT Project Coordinator /AAT Level Designer
Posts: 4200
Joined: 11 years ago
Location: Nova Scotia

Re: LunaDLL/LunaLUA help thread

Post by SAJewers »

Rednaxela wrote:
SAJewers wrote:ping
Kev was talking about something different, if you want to trigger a p-switch effect from Lua code.

Anyway, here you go.
  1. Update LuaScriptsLib\core\defines.lua from this version (will be included in future LunaLua updates)
  2. Unzip the pSwitchTicking library into LuaScriptsLib
    pSwitchTicking.zip
    (will be included in future LunaLua updates)
  3. Put the line

    Code: Select all

    loadSharedAPI("pSwitchTicking")
    in the lunadll.lua or lunaworld.lua where you want it to apply. I assume probably lunaworld.lua for A2XT usage.
(Technical details: I used the .wav file provided as the basis, but cropped it down to a single repetition (precisely 1.066 seconds) and set it to auto-loop, so that the audio file could be super small.

The defines.lua update contains that capability of applying an asm patch to disable normal SMBX p-switch music effects. The pSwitchTicking.lua API activates this, and then listens for "P Switch - Start" and "P Switch - End" SMBX events to trigger start/stop of an auto-looping sound)
Bug Report: If you die while a P-Switch is active, it'll continue to tick even after you die.
ImageImageImageImageImage | Image | Image
Sharenite | RetroAchievements | NameMC | IGDB
User avatar
7NameSam
hey
Posts: 248
Joined: 9 years ago
Pronouns: they/them

Re: LunaDLL/LunaLUA help thread

Post by 7NameSam »

How would you go around making it so a player could break a kind of block just by touching it?
cramps-man
Posts: 14
Joined: 9 years ago

Re: LunaDLL/LunaLUA help thread

Post by cramps-man »

7NameSam wrote:How would you go around making it so a player could break a kind of block just by touching it?
Step 1. Find out how to check the player is colliding with a block/blocks.
Step 2. Destroy said block.

For step 1 just use block.get to get all of a single type of block you want, then check for collisions. The block class should have a method to check for collisions.

Step 2 should be easy as the block class should have a method to destroy block.
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: LunaDLL/LunaLUA help thread

Post by Hoeloe »

cramps-man wrote: For step 1 just use block.get to get all of a single type of block you want, then check for collisions. The block class should have a method to check for collisions.
That's debatable. It doesn't have a very robust one, for sure. The colliders library does though.
Image
Image
Image
Image
Image
User avatar
7NameSam
hey
Posts: 248
Joined: 9 years ago
Pronouns: they/them

Re: LunaDLL/LunaLUA help thread

Post by 7NameSam »

So, In this code, I want to exit the level when I touch a block with an ID of 1

Code: Select all

local colliders = loadAPI("colliders");
 
function onLoop()
    for k,v in pairs(Block.get(1)) do
        if (colliders.collideBlock(player, 1)) then
            Level.exit();
        end
    end
end
Am I heading in the right direction?
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: LunaDLL/LunaLUA help thread

Post by Hoeloe »

7NameSam wrote:So, In this code, I want to exit the level when I touch a block with an ID of 1

Code: Select all

local colliders = loadAPI("colliders");
 
function onLoop()
    for k,v in pairs(Block.get(1)) do
        if (colliders.collideBlock(player, 1)) then
            Level.exit();
        end
    end
end
Am I heading in the right direction?
Almost. The benefit of "collideBlock" is that you don't need to grab the list of blocks first, as colliders manages that for you. The hint to that is that, when you run your loop, you arent using the k or v variables you define for it. That's a clue that maybe a loop isn't necessary. Currently you're checking if the player is touching any block with ID 1 multiple times, which isn't necessary and will be very slow.
Image
Image
Image
Image
Image
User avatar
7NameSam
hey
Posts: 248
Joined: 9 years ago
Pronouns: they/them

Re: LunaDLL/LunaLUA help thread

Post by 7NameSam »

I'm unsure what I'm doing wrong?
Do I not have the latest version of colliders?

Code: Select all

local colliders = loadAPI("colliders");
 
function onLoop()
	if (colliders.collideBlock(player,1)) then
		player.speedY = -10
	end
end
User avatar
Hoeloe
A2XT person
Posts: 1016
Joined: 12 years ago
Pronouns: she/her
Location: Spaaace

Re: LunaDLL/LunaLUA help thread

Post by Hoeloe »

7NameSam wrote:I'm unsure what I'm doing wrong?
Do I not have the latest version of colliders?

Code: Select all

local colliders = loadAPI("colliders");
 
function onLoop()
	if (colliders.collideBlock(player,1)) then
		player.speedY = -10
	end
end
What's happening that's wrong? This should push the player up when they touch a block with ID 1.
Image
Image
Image
Image
Image
User avatar
7NameSam
hey
Posts: 248
Joined: 9 years ago
Pronouns: they/them

Re: LunaDLL/LunaLUA help thread

Post by 7NameSam »

Hoeloe wrote:
7NameSam wrote:I'm unsure what I'm doing wrong?
Do I not have the latest version of colliders?

Code: Select all

local colliders = loadAPI("colliders");
 
function onLoop()
	if (colliders.collideBlock(player,1)) then
		player.speedY = -10
	end
end
What's happening that's wrong? This should push the player up when they touch a block with ID 1.
Nothing happens if I touch the block,
Attachments
WONTWORK2.gif
WONTWORK2.gif (106.74 KiB) Viewed 7564 times
Post Reply