I'm trying to set up health points for an enemy using healthpoint.lua

Need help with any SMBX game-related issues? Ask your questions here.

Moderator: Userbase Moderators

PixelPest
Link
Link
Posts: 7111
Joined: Sun Jul 12, 2015 5:38 pm
Flair: Tamer of Boom Booms
Contact:

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby PixelPest » Wed Aug 17, 2016 6:40 pm

You should probably not wrap the NPC unless it is ID 168 since otherwise you don't do anything with all of those wrapped NPCs that now have unneeded data assigned to them

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

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby Emral » Wed Aug 17, 2016 7:10 pm

dragon3025 wrote:
Enjl wrote:You have to wrap killedNPC and start doing stuff with it in a scope where it's actually defined. I suggest after the killedNPC.id check. Also I noticed that your HP only counts down on killReason 9 which is equivalent to despawn or being collected.
You posted eariler to make sure to also allow death by reason 9 if you want despawning to be possible. I was using 3 to make it so stomping on it 3 times kills it, did you mean use 9 along with 3? My code is now:

Code: Select all

local pnpc = loadSharedAPI("pnpc")

function onNPCKill(killObj, killedNPC, killReason)

	w = pnpc.wrap(killedNPC)

	if w.data.hp == nil then
	  w.data.hp = 0
	end

	if killedNPC.id == 168 then
		if killReason == 9 then
			if w.data.hp < 2 then
				w.data.hp = w.data.hp + 1
			else
				killObj.cancelled=true
			end
		end
	end
end
I didn't get any errors, but I still couldn't kill it by jumping on it and hitting it with a hammer killed it in one hit.
Sorry for confusing you with the killReason==9 thing earlier, time to get this resolved.
The check "if killReason == 9 then" makes it so that everything until the "end" which closes the condition will only run when an enemy is despawned or collected. Your code checks for all despawning npc with ID 168 and executes the code for those.
My previous mention of killReason == 9 was to cover an edge-case where your NPC would be immortal when trying to despawn. Typing this made me remember another edge-case, lava.
So what you want is to not execute ANY code on your NPC if it dies by lava or despawn (killReasons 6 and 9). Furthermore, killReason 1 is the default kill. Reason 3's "squish" refers to NPCs getting crushed by moving layers.
All this condition jumble can look like this:

Code: Select all

if killReason == 1 and w.data.hp < 2 then
	w.data.hp = w.data.hp + 1
else
	if killReason ~= 6 and killReason ~= 9 and w.data.hp < 2 then --don't kill the NPC unless it touches lava, despawns or was bonked three times.
		killObj.cancelled = true
	end
end
Your NPC will, in this case, still be vulnerable to other types of harm, such as tail swipe, spinjump or shells. To make your NPC immune to them, all you need is to expand your killReason checks. If you want to check for death by specific npcs, things get more complicated.

underFlo
Wart
Wart
Posts: 4456
Joined: Mon Jul 14, 2014 10:44 am
Flair: sup im lesbiab
Pronouns: They/She
Contact:

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby underFlo » Wed Aug 17, 2016 7:27 pm

Wouldn't you want to not cancel it in the latter case? You'd need killObj.cancelled = false in that case and set it to true in every other case.

dragon3025
Bot
Bot
Posts: 55
Joined: Fri Aug 07, 2015 5:02 pm

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby dragon3025 » Wed Aug 17, 2016 9:01 pm

PixelPest wrote:You should probably not wrap the NPC unless it is ID 168 since otherwise you don't do anything with all of those wrapped NPCs that now have unneeded data assigned to them
I think I see what you mean, I changed that part to:

Code: Select all

	if killedNPC.id == 168 then
		w = pnpc.wrap(killedNPC)
		if w.data.hp == nil then
			w.data.hp = 0
		end
	end
Enjl wrote:
dragon3025 wrote:
Enjl wrote:You have to wrap killedNPC and start doing stuff with it in a scope where it's actually defined. I suggest after the killedNPC.id check. Also I noticed that your HP only counts down on killReason 9 which is equivalent to despawn or being collected.
You posted eariler to make sure to also allow death by reason 9 if you want despawning to be possible. I was using 3 to make it so stomping on it 3 times kills it, did you mean use 9 along with 3? My code is now:

Code: Select all

local pnpc = loadSharedAPI("pnpc")

function onNPCKill(killObj, killedNPC, killReason)

	w = pnpc.wrap(killedNPC)

	if w.data.hp == nil then
	  w.data.hp = 0
	end

	if killedNPC.id == 168 then
		if killReason == 9 then
			if w.data.hp < 2 then
				w.data.hp = w.data.hp + 1
			else
				killObj.cancelled=true
			end
		end
	end
end
I didn't get any errors, but I still couldn't kill it by jumping on it and hitting it with a hammer killed it in one hit.
Sorry for confusing you with the killReason==9 thing earlier, time to get this resolved.
The check "if killReason == 9 then" makes it so that everything until the "end" which closes the condition will only run when an enemy is despawned or collected. Your code checks for all despawning npc with ID 168 and executes the code for those.
My previous mention of killReason == 9 was to cover an edge-case where your NPC would be immortal when trying to despawn. Typing this made me remember another edge-case, lava.
So what you want is to not execute ANY code on your NPC if it dies by lava or despawn (killReasons 6 and 9). Furthermore, killReason 1 is the default kill. Reason 3's "squish" refers to NPCs getting crushed by moving layers.
All this condition jumble can look like this:

Code: Select all

if killReason == 1 and w.data.hp < 2 then
	w.data.hp = w.data.hp + 1
else
	if killReason ~= 6 and killReason ~= 9 and w.data.hp < 2 then --don't kill the NPC unless it touches lava, despawns or was bonked three times.
		killObj.cancelled = true
	end
end
Your NPC will, in this case, still be vulnerable to other types of harm, such as tail swipe, spinjump or shells. To make your NPC immune to them, all you need is to expand your killReason checks. If you want to check for death by specific npcs, things get more complicated.
The code didn't work for bully (I couldn't damage it by jumping on it), but I changed the id to Goomba and it worked for Goomba but it needed killObj.cancelled after "if killReason == 1 and w.data.hp < 2 then".

My code looks like this:

Code: Select all

local pnpc = loadSharedAPI("pnpc")

function onNPCKill(killObj, killedNPC, killReason)

	if killedNPC.id == 168 then
		w = pnpc.wrap(killedNPC)
		if w.data.hp == nil then
			w.data.hp = 0
		end
	end

	if killedNPC.id == 168 then
		if killReason == 1 and w.data.hp < 2 then
			w.data.hp = w.data.hp + 1
			killObj.cancelled = true
		else
			if killReason ~= 6 and killReason ~= 9 and w.data.hp < 2 then --don't kill the NPC unless it touches lava, despawns or was bonked three times.
				killObj.cancelled = true
			end
		end
	end
end
So I think it's because Bully doesn't get damage by jumping on it. If is there a way to make Bully jump-able or is possible to make a Goomba chase mario (should I make another topic for this?). I also noticed that when throwing a hammer at it, it hits it multiple times without killing allowing me to get very easy 1ups (should I make a topic for this too?).

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

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby Emral » Wed Aug 17, 2016 9:17 pm

Turns out I was tired all day and completely forgot about a better way to handle things, so that the bully will work. God damnit I'm stupid. I apologize >.<

Alright so.
Here's the good solution.
NPCs have AI. http://wohlsoft.ru/pgewiki/SMBX_NPC_AI# ... ID:_168.29
This is the bully's AI.
Ignoring onNPCKill and using onTick you can check for when a bully is kicked off by the player (check for the first frame of it specifically) and incriment the hp counter that way.

Code: Select all

function onTick()
	for k,v in pairs(NPC.get(168, player.section)) do --for all bullies in the player section
		w = pnpc.wrap(v) --v is index k of the table in the brackets returned by NPC.get. It's identical to onNPCKill's killedNPC except not only when dying.
		if w.data.hp == nil then
         		w.data.hp = 0
         		w.data.previousAIState = 0 --helps keeping track of the AI state switching
     		end
     		if v.ai2 == 1 then
     			if w.data.previousAIState == 0 then
     				w.data.hp = w.data.hp + 1
     				if w.data.hp == 3 then
     					w:kill(3) --kills with shell kick effect
     				end
     			end
     		end
     		w.data.previousAIState = v.ai2 --stores ai2 of previous frame
	end
end
That should do it for what you want. The comments are to help understand what is happening. For the most part, however, I just converted the stuff from onNPCKill into onTick.

dragon3025
Bot
Bot
Posts: 55
Joined: Fri Aug 07, 2015 5:02 pm

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby dragon3025 » Wed Aug 17, 2016 10:12 pm

Enjl wrote:Turns out I was tired all day and completely forgot about a better way to handle things, so that the bully will work. God damnit I'm stupid. I apologize >.<

Alright so.
Here's the good solution.
NPCs have AI. http://wohlsoft.ru/pgewiki/SMBX_NPC_AI# ... ID:_168.29
This is the bully's AI.
Ignoring onNPCKill and using onTick you can check for when a bully is kicked off by the player (check for the first frame of it specifically) and incriment the hp counter that way.

Code: Select all

function onTick()
	for k,v in pairs(NPC.get(168, player.section)) do --for all bullies in the player section
		w = pnpc.wrap(v) --v is index k of the table in the brackets returned by NPC.get. It's identical to onNPCKill's killedNPC except not only when dying.
		if w.data.hp == nil then
         		w.data.hp = 0
         		w.data.previousAIState = 0 --helps keeping track of the AI state switching
     		end
     		if v.ai2 == 1 then
     			if w.data.previousAIState == 0 then
     				w.data.hp = w.data.hp + 1
     				if w.data.hp == 3 then
     					w:kill(3) --kills with shell kick effect
     				end
     			end
     		end
     		w.data.previousAIState = v.ai2 --stores ai2 of previous frame
	end
end
That should do it for what you want. The comments are to help understand what is happening. For the most part, however, I just converted the stuff from onNPCKill into onTick.
That's okay, I'm just glad I'm getting responses, I've recently had sites ignore my post for weeks when I needed help with a plugin for another program.

I used that code, it didn't work. I was able to jump on it way more than 3 times, and it doesn't die. I was able to to stop the hammer from getting easy one ups by giving the npc's txt file "score=0".

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

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby Emral » Wed Aug 17, 2016 10:17 pm

The code likely doesn't work if you still have onNPCKill in your lua file. Wrap it into comments like so:

Code: Select all

--[[
code
code
code
]]
If that doesn't do it, try debugging some values with Text.print(message, x, y) to figure out where things go wrong. It might be a dumb error on my part.
To see what value w.data.hp is doing for example, you add this line into your for loop:

Code: Select all

Text.print(w.data.hp,0,0)
which will print it in the upper left corner of the screen. Make sure you only have one bully when doing this. For multiple bullies, use the key of the table to modify the position at which the text is drawn:

Code: Select all

Text.print(w.data.hp,0,0 + 20 * k)

dragon3025
Bot
Bot
Posts: 55
Joined: Fri Aug 07, 2015 5:02 pm

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby dragon3025 » Thu Aug 18, 2016 12:16 am

Enjl wrote:The code likely doesn't work if you still have onNPCKill in your lua file. Wrap it into comments like so:

Code: Select all

--[[
code
code
code
]]
If that doesn't do it, try debugging some values with Text.print(message, x, y) to figure out where things go wrong. It might be a dumb error on my part.
To see what value w.data.hp is doing for example, you add this line into your for loop:

Code: Select all

Text.print(w.data.hp,0,0)
which will print it in the upper left corner of the screen. Make sure you only have one bully when doing this. For multiple bullies, use the key of the table to modify the position at which the text is drawn:

Code: Select all

Text.print(w.data.hp,0,0 + 20 * k)
Oh okay, I wasn't sure if I should keep that in or not, but keeping it in does make sense. It's not working that way either though, the enemy doesn't die from hammers, but doesn't die from any amount of jumping.

The printing code:

Code: Select all

Text.print(w.data.hp,0,0)
Isn't printing anything out while in "function onTick()" though. I even tested it by using tostring() and I also tried using Text.print("Test",0,0) and nothing shows up.

My code at this point:

Code: Select all

local pnpc = loadSharedAPI("pnpc")

function onNPCKill(killObj, killedNPC, killReason)

	if killedNPC.id == 168 then
		w = pnpc.wrap(killedNPC)
		if w.data.hp == nil then
			w.data.hp = 0
		end
	end

	if killedNPC.id == 168 then
		if killReason == 1 and w.data.hp < 2 then
			w.data.hp = w.data.hp + 1
			killObj.cancelled = true
		else
			if killReason ~= 6 and killReason ~= 9 and w.data.hp < 2 then --don't kill the NPC unless it touches lava, despawns or was bonked three times.
				killObj.cancelled = true
			end
		end
	end
end

function onTick()
	for k,v in pairs(NPC.get(168, player.section)) do --for all bullies in the player section
		w = pnpc.wrap(v) --v is index k of the table in the brackets returned by NPC.get. It's identical to onNPCKill's killedNPC except not only when dying.
		if w.data.hp == nil then
			w.data.hp = 0
			w.data.previousAIState = 0 --helps keeping track of the AI state switching
		end
		Text.print(w.data.hp,0,0)
		if v.ai2 == 1 then
			if w.data.previousAIState == 0 then
				w.data.hp = w.data.hp + 1
				if w.data.hp == 3 then
					w:kill(3) --kills with shell kick effect
				end
			end
		end
		w.data.previousAIState = v.ai2 --stores ai2 of previous frame
	end
end

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

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby Emral » Thu Aug 18, 2016 2:52 pm

Rename onTick to onLoop. I forgot that old SMBX from the last 2.0 beta didn't have onTick yet. The code works for me.
Alternatively update your LunaLua. You're on 2.0 if I recall, which means that after downloading "Latest" from here http://wohlsoft.ru/LunaLua/ you should extract lunadll.dll and LuaScriptsLib into your SMBX folder. The rest messes with the 2.0 installation.

dragon3025
Bot
Bot
Posts: 55
Joined: Fri Aug 07, 2015 5:02 pm

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby dragon3025 » Thu Aug 18, 2016 3:28 pm

Enjl wrote:Rename onTick to onLoop. I forgot that old SMBX from the last 2.0 beta didn't have onTick yet. The code works for me.
Alternatively update your LunaLua. You're on 2.0 if I recall, which means that after downloading "Latest" from here http://wohlsoft.ru/LunaLua/ you should extract lunadll.dll and LuaScriptsLib into your SMBX folder. The rest messes with the 2.0 installation.
Well it works and it doesn't. When I use onLoop, and I jump on it rapidly it takes 5 hits, but if I jump on it and hold down the jump button to jump on it slower, it takes 3. The w.data.previousAIState isn't setting it self back to 0 fast enough. I tried extracting the updated lunadll.dll and LuaScriptsLib into my SMBX folder and it caused it to not work with onLoop or onTick, so I copied the outdated versions of the files back into the folder for now.

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

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby Emral » Thu Aug 18, 2016 3:34 pm

That's... weird. I have no idea what's going on, to be honest.

dragon3025
Bot
Bot
Posts: 55
Joined: Fri Aug 07, 2015 5:02 pm

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby dragon3025 » Thu Aug 18, 2016 5:33 pm

Enjl wrote:That's... weird. I have no idea what's going on, to be honest.
Okay, well at least it takes multiple hits which is pretty close. Thanks for helping me, I wouldn't of gotten my code anywhere close to this if you hadn't.

If you or anyone else ever comes up with an idea on how to get w.data.previousAIState to set back to 0 faster, then please post it. Right now I'll lower its health at 2 since it makes it so 3 rapid hits knocks it out.

timocomsmbx2345
Foo
Foo
Posts: 853
Joined: Sat Feb 06, 2016 1:44 pm
Contact:

Re: I'm trying to set up health points for an enemy using healthpoint.lua

Postby timocomsmbx2345 » Sun Sep 25, 2016 6:19 pm

dragon3025 wrote:I only need it to effect a single level in my episode. So do I place the healthpoint.lua file in my level folder, then make a lunadll.lua file in the same level folder, then in the lunadll.lua file I put in:

Code: Select all

HealthPoint.setNPCHealth(168, 5)
do you mean like a health bar?


Return to “Help and Support”

Who is online

Users browsing this forum: No registered users and 1 guest

SMWCentralTalkhausMario Fan Games GalaxyKafukaMarioWikiSMBXEquipoEstelari