Goal roulette customization

Post here for help and support regarding LunaLua and SMBX2's libraries and features.

Moderator: Userbase Moderators

BrokenAce
Bot
Bot
Posts: 51
Joined: Sat Feb 06, 2016 11:48 am

Goal roulette customization

Postby BrokenAce » Mon Aug 15, 2022 8:38 pm

As I am very new to LunaLua, trying to figure out how it works in relation to the existing pre-coded aspects of SMBX can be a real pain. Specifically, I'm trying to modify the SMB3 goal roulette so that the mushroom and flower give out coins instead of points. This sounds like it should be simple to do, but I've had no luck with even getting started, since the goal roulette does not exist in lua form to edit or study. I'm aware of Defines.smb3RouletteScore, but the values for this only allow for alternative scores.

Any ideas on how to implement this? I am open to unconventional methods, such as modifying the 4000 and 8000 points values to give coins as well as or instead of points (though I'm not sure how to do this either).

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

Re: Goal roulette customization

Postby Emral » Mon Aug 15, 2022 8:56 pm

Easiest way would be to make a new goal roulette npc from scratch.
- copy the npc-n stuff from the templates folder into your level or episode folder and rename n to an id in the custom range (example: npc-751.lua)
- change the npc-751.png to look like what you want
- change the npc-751.ini to point to your image file instead of Dummy.png
- in the lua file, make sure to set the following configs in the npc settings section: isinteractable = true, iscollectablegoal = true, nogravity = true, score = 0
- put this line at the top of the lua file: "local npcManager=require("npcManager")
- in onInitAPI, register the handler for an onPostNPCKill event. There is a commented out one for onNPCKill which you can alter and comment back in
- Get rid of onTickNPC and the registration for it
- add a function onPostNPCKill(killedNPC, killReason)
- in that function, the logic looks like this:
-- filter for collecting the NPC: if killedNPC.id == NPC_ID and npcManager.collected(killedNPC, killReason) then
-- when that filter passes, you can do a second if-else over the NPC's killedNPC.animationFrame variable. If it's 0, it's a mushroom. if it's 1, it's a flower. if it's 2, it's a a star. In the if-else you can then put whatever you want.
-- I haven't used iscollectablegoal before but you might have to put Level.winState(LEVEL_END_STATE_ROULETTE) into the filter-if statement as well to make sure the game ends with the roulette goal type.

BrokenAce
Bot
Bot
Posts: 51
Joined: Sat Feb 06, 2016 11:48 am

Re: Goal roulette customization

Postby BrokenAce » Tue Aug 16, 2022 7:00 am

Enjl wrote:
Mon Aug 15, 2022 8:56 pm
Easiest way would be to make a new goal roulette npc from scratch.
- copy the npc-n stuff from the templates folder into your level or episode folder and rename n to an id in the custom range (example: npc-751.lua)
- change the npc-751.png to look like what you want
- change the npc-751.ini to point to your image file instead of Dummy.png
- in the lua file, make sure to set the following configs in the npc settings section: isinteractable = true, iscollectablegoal = true, nogravity = true, score = 0
- put this line at the top of the lua file: "local npcManager=require("npcManager")
- in onInitAPI, register the handler for an onPostNPCKill event. There is a commented out one for onNPCKill which you can alter and comment back in
- Get rid of onTickNPC and the registration for it
- add a function onPostNPCKill(killedNPC, killReason)
- in that function, the logic looks like this:
-- filter for collecting the NPC: if killedNPC.id == NPC_ID and npcManager.collected(killedNPC, killReason) then
-- when that filter passes, you can do a second if-else over the NPC's killedNPC.animationFrame variable. If it's 0, it's a mushroom. if it's 1, it's a flower. if it's 2, it's a a star. In the if-else you can then put whatever you want.
-- I haven't used iscollectablegoal before but you might have to put Level.winState(LEVEL_END_STATE_ROULETTE) into the filter-if statement as well to make sure the game ends with the roulette goal type.

Thanks for the help, but I'm having absolutely no luck getting this set up. It just spits out multiple error messages and refuses to run the code. Here's what I've got for my Register events, in case it helps (the NPC:toCoin is just a placeholder for now):

Code: Select all

--Register events
function sampleNPC.onInitAPI()
	registerEvent(sampleNPC, "onNPCKill")
	onPostNPCKill(killedNPC, killReason)
	if killedNPC.id == NPC_ID and npcManager.collected(killedNPC, killReason) then
	if-else killedNPC.animationFrame = 0, then NPC:toCoin(),
	if-else killedNPC.animationFrame = 1, then NPC:toCoin(),
	if-else killedNPC.animationFrame = 2, then NPC:toCoin(),
end

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

Re: Goal roulette customization

Postby Emral » Tue Aug 16, 2022 8:08 am

BrokenAce wrote:
Tue Aug 16, 2022 7:00 am


Thanks for the help, but I'm having absolutely no luck getting this set up. It just spits out multiple error messages and refuses to run the code. Here's what I've got for my Register events, in case it helps (the NPC:toCoin is just a placeholder for now):

Code: Select all

--Register events
function sampleNPC.onInitAPI()
	registerEvent(sampleNPC, "onNPCKill")
	onPostNPCKill(killedNPC, killReason)
	if killedNPC.id == NPC_ID and npcManager.collected(killedNPC, killReason) then
	if-else killedNPC.animationFrame = 0, then NPC:toCoin(),
	if-else killedNPC.animationFrame = 1, then NPC:toCoin(),
	if-else killedNPC.animationFrame = 2, then NPC:toCoin(),
end
right, nah, the bullet points dont translate to literal lines of code. they were more just a guide assuming some familiarity with programming. i underestimated "very new", sorry

Code: Select all

local npcManager = require("npcManager")

function sampleNPC.onInitAPI()
	registerEvent(sampleNPC, "onPostNPCKill")
end

function sampleNPC.onPostNPCKill(killedNPC, killReason)
	if killedNPC.id == NPC_ID and npcManager.collected(killedNPC, killReason) then
		if killedNPC.animationFrame == 0 then
			Misc.coins(1) -- gives 1 coin to the player
		elseif killedNPC.animationFrame == 1 then
			Misc.coins(2) -- gives 2 coins to the player
		elseif killedNPC.animationFrame == 2 then
			Misc.coins(3) -- gives 3 coins to the player
		end
		Misc.npcToCoins() -- turn all onscreen npcs into coins
		Level.winState(LEVEL_END_STATE_ROULETTE) --win the level
	end
end
Lot to unpack, but the main differences are:
- onPostNPCKill is a function https://docs.codehaus.moe/#/types/function https://docs.codehaus.moe/#/reference/lunalua-events
- The registerEvent call to register lunalua event functions needs to be given the name of the function
- General syntax, like elseif, and not using commas
- = is assignment, == is comparison

BrokenAce
Bot
Bot
Posts: 51
Joined: Sat Feb 06, 2016 11:48 am

Re: Goal roulette customization

Postby BrokenAce » Tue Aug 16, 2022 10:09 am

Enjl wrote:
Tue Aug 16, 2022 8:08 am

Code: Select all

local npcManager = require("npcManager")

function sampleNPC.onInitAPI()
	registerEvent(sampleNPC, "onPostNPCKill")
end

function sampleNPC.onPostNPCKill(killedNPC, killReason)
	if killedNPC.id == NPC_ID and npcManager.collected(killedNPC, killReason) then
		if killedNPC.animationFrame == 0 then
			Misc.coins(1) -- gives 1 coin to the player
		elseif killedNPC.animationFrame == 1 then
			Misc.coins(2) -- gives 2 coins to the player
		elseif killedNPC.animationFrame == 2 then
			Misc.coins(3) -- gives 3 coins to the player
		end
		Misc.npcToCoins() -- turn all onscreen npcs into coins
		Level.winState(LEVEL_END_STATE_ROULETTE) --win the level
	end
end
Lot to unpack, but the main differences are:
- onPostNPCKill is a function https://docs.codehaus.moe/#/types/function https://docs.codehaus.moe/#/reference/lunalua-events
- The registerEvent call to register lunalua event functions needs to be given the name of the function
- General syntax, like elseif, and not using commas
- = is assignment, == is comparison

Thanks, this is very informative and I'll keep it in mind next time I do some tinkering. I've only dipped my toes in coding in the past and wasn't aware of just how different the syntax can be between languages.

As for the actual code though, even after applying it, it still does not work as it should. The NPC does not trigger a goal (despite having followed the steps on listing it as a goal), and can be jumped on like a Goomba. I'm getting the feeling custom goals are somewhat of a blind spot in SMBX2's documentation, so I think I'll just stick with one of the vanilla goal types for the time being.

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

Re: Goal roulette customization

Postby Emral » Tue Aug 16, 2022 10:12 am

nah chances are i just forgot stuff because i never made a goal before. but other people have
in the registerHarmTypes section, make sure HARM_TYPE_OFFSCREEN is the only harm type that is registered. I think it's

Code: Select all

npcManager.registerHarmTypes(NPC_ID, {HARM_TYPE_OFFSCREEN}, {})
in the npc config section, make sure spinjumpsafe = false, nohurt = true and jumphurt = true are all set as described

if that still doesnt work, it may be the case that the code doesnt run. is there an error? what happens if you put Misc.dialog("hi") into the onPostNPCKill or the if statements? Is there a case where it doesnt open a debug displaying hi?

BrokenAce
Bot
Bot
Posts: 51
Joined: Sat Feb 06, 2016 11:48 am

Re: Goal roulette customization

Postby BrokenAce » Tue Aug 16, 2022 10:46 am

Ah, never mind. I figured out the issue; I'd forgotten to remove the -- from the identity flags. :oops:
As for being able to be jumped on, setting spinjumpsafe to false does the trick. It now all works as intended, and should be good to go once I hook up the audio cues, which I should (hopefully) be able to do myself with a little help from the wiki.

Edit: Okay actually maybe not. The wiki seems to be incredibly outdated as it doesn't even have Misc.coins() listed. Is there better documentation anywhere?

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

Re: Goal roulette customization

Postby Emral » Tue Aug 16, 2022 11:15 am

BrokenAce wrote:
Tue Aug 16, 2022 10:46 am
Ah, never mind. I figured out the issue; I'd forgotten to remove the -- from the identity flags. :oops:
As for being able to be jumped on, setting spinjumpsafe to false does the trick. It now all works as intended, and should be good to go once I hook up the audio cues, which I should (hopefully) be able to do myself with a little help from the wiki.

Edit: Okay actually maybe not. The wiki seems to be incredibly outdated as it doesn't even have Misc.coins() listed. Is there better documentation anywhere?
https://docs.codehaus.moe/#/

For audio stuff, https://docs.codehaus.moe/#/reference/SFX

BrokenAce
Bot
Bot
Posts: 51
Joined: Sat Feb 06, 2016 11:48 am

Re: Goal roulette customization

Postby BrokenAce » Tue Aug 16, 2022 1:00 pm

Enjl wrote:
Tue Aug 16, 2022 11:15 am
https://docs.codehaus.moe/#/

For audio stuff, https://docs.codehaus.moe/#/reference/SFX

Some incredibly useful stuff here. I managed to get the sound effects working fine, and I also managed to get one of the goal frames to give a 1up (though I haven't managed to get the 1up icon on-screen, but that's more of a nitpick).

One problem still remains though: music. The custom goal does not mute music by default, and I can't figure out how to code it in. I found this: https://docs.codehaus.moe/#/handbook/lu ... -and-music, but it's very different from anything I've seen before, and I honestly have no idea what I'm even looking at here.

Edit: I've just found a major problem: the SMB3 goal roulette AI does not account for multiplayer. Is there any way to destroy Player 2 upon triggering the NPC, like how the SMB3 goal roulette does?

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

Re: Goal roulette customization

Postby Emral » Tue Aug 16, 2022 7:50 pm

For music: Audio.MusicFadeOut(-1, 0) should do I thiiink?

For multiplayer, I don't actually know what SMBX usually does. You can permanently disable player controls and make them invincible like this though (if it's in the npc-n.lua, it needs to be sampleNPC.onTick and needs to have a registerEvent(sampleNPC, "onTick") in onInitAPI:

Code: Select all

function onTick()
	if Level.winState() > 0 then
		for k,p in ipairs(Player.get()) do
			for key, _ in ipairs(p.keys) do
				p.keys[key] = false -- disable all input keys
			end
			
			p:mem(0x140, FIELD_WORD, 3) -- Set powerup invulnerability to 3 frames every frame
		end
	end
end
If it also does some camera stuff you might find a solution on the camera docs page.


Return to “LunaLua Help”

Who is online

Users browsing this forum: No registered users and 0 guests

SMWCentralTalkhausMario Fan Games GalaxyKafukaMarioWikiSMBXEquipoEstelari