Page 2 of 2

Re: LunaLua Help

Posted: 24 May 2019, 15:35
by Nimono
Hoeloe wrote: 4 years ago You might find this easier to do with vectors.

From what it looks like, you're trying to spawn an NPC part way between the player and some other object, right?

Doing this with vectors is pretty simple:

Code: Select all

local direction = vector(player.x-ax, player.y-ay):normalize()

NPC.spawn(id, player.x + dist*direction.x, player.y + dist*direction.y, player.section)
Is the basic gist.
Wow, that worked immediately. Thanks, Hoeloe! To be honest, I wasn't wanting this to actually spawn an NPC... I want to use it to check for tiles between an NPC and the player, as a kind of vision thing. Like in that MaGLX2 Snake demo.

Re: LunaLua Help

Posted: 25 May 2019, 09:57
by Hoeloe
Ah. Well there's actually a library for that which is the one Snake uses.

Re: LunaLua Help

Posted: 28 May 2019, 02:19
by Joseph Staleknight
Is there a way to extend the health of a non-boss enemy in Lua? For example, if I wanted an unusually tough Goomba, how would I make its health more than 1 HP?

E: And to clarify, Trying to do so on the NPC Config text doc doesn't work. I've tried that.

Re: LunaLua Help

Posted: 28 May 2019, 09:54
by Emral
Joseph Staleknight wrote: 4 years ago Is there a way to extend the health of a non-boss enemy in Lua? For example, if I wanted an unusually tough Goomba, how would I make its health more than 1 HP?

E: And to clarify, Trying to do so on the NPC Config text doc doesn't work. I've tried that.
NPC code guide specifies that the health variable only works on bosses I believe, yeah. Thing is, those are the only NPCs that make use of the hp offset, so it makes sense.
You can add more HP to regular enemies using pnpc and onNPCHarm. When an NPC is hit in onNPCHarm you can check if it has the ID you want and then save a variable after wrapping the npc. It looks something like this:

Code: Select all

local pnpc = require("pnpc")

function onNPCHarm(eventObj, killedNPC, killReason, culpritOrNil)
	-- ID CHECK
	-- KILL REASON CHECK
	killedNPC = pnpc.wrap(killedNPC)
	if killedNPC.data.hp == nil then
		killedNPC.data.hp = 5
	end
	killedNPC.data.hp = killedNPC.data.hp - 1
	if killedNPC.data.hp > 0 then
		eventObj.cancelled = true
	end
end

Re: LunaLua Help

Posted: 28 May 2019, 11:52
by Joseph Staleknight
Yep, that did the trick. Thank you!

EDIT: I just found a problem with the code--apparently, NPCs frozen by the Ice Flower disregard the HP of the toughened NPC. I set the NPC in question to be vulnerable to only other NPCs, so when I throw a different NPC at it, it decrements health as it should. However, when I throw a frozen NPC it completely bypasses the hit NPC's health! How does that even work?

Re: LunaLua Help

Posted: 28 May 2019, 13:05
by Emral
Frozen NPCs are a different ID and the act of freezing an NPC is an ID change. The NPC will return to obeying the laws of its HP once thawed. You could add HP for ice cubes by checking them in onNPCHarm and then decrementing HP only if the NPC's ai1 value is a valid multi-hp ID.

Re: LunaLua Help

Posted: 28 May 2019, 13:54
by Joseph Staleknight
I do agree about frozen NPCs being a different ID entirely. However, I think I was a bit unclear on the actual question I had. What I meant to say was:
  • I have a toughened non-boss enemy I'm going to call "Target".
  • And I have an NPC to throw at Target to damage him. I'll call that one "Projectile".
  • If Projectile is a regular NPC, then Target takes damage according to the code, which I want.
  • On the other hand, if Projectile is a frozen NPC, then Projectile insta-kills Target, which I don't want.
  • Instead, I want Projectile to damage Target equally whether or not Projectile's frozen.

Re: LunaLua Help

Posted: 28 May 2019, 14:03
by Emral
Joseph Staleknight wrote: 4 years ago I do agree about frozen NPCs being a different ID entirely. However, I think I was a bit unclear on the actual question I had. What I meant to say was:
  • I have a toughened non-boss enemy I'm going to call "Target".
  • And I have an NPC to throw at Target to damage him. I'll call that one "Projectile".
  • If Projectile is a regular NPC, then Target takes damage according to the code, which I want.
  • On the other hand, if Projectile is a frozen NPC, then Projectile insta-kills Target, which I don't want.
  • Instead, I want Projectile to damage Target equally whether or not Projectile's frozen.
The ice block doesn't die so it damages target every frame. You need to store a 2nd varaible for an invincibility timer, or kill the culprit if it exists and is an ice block npc. (if culpritOrNil and culpritOrNil.__type == "NPC" and culpritOrNil.id == ICEBLOCKIDREPLACETHIS)

Re: LunaLua Help

Posted: 29 May 2019, 01:13
by Joseph Staleknight
Cool, got it to work. Thanks so much!

Re: LunaLua Help

Posted: 17 Jul 2019, 00:43
by ItsFuntime
Okay, imagine when you're trying to make a bonus room where you get one shot and you have to toss an ice block to one of the question blocks, and you want to a sound to play when the ice block successfully hits a question block. How do know when the ice block successfully hits that question block?

Here's the code for the scenario:

Code: Select all

function onEvent(eventName)
    if eventName == "Bonus Ice Dies" then
      bonusBlocks.iceShattered = true

      if bonusBlocks.allDone then
        if bonusBlocks.getPrize then
          Audio.playSFX(Misc.resolveFile("hoopla/foodcourt-tada.ogg"))
        else
          Audio.playSFX(Misc.resolveFile("hoopla/foodcourt-lose.ogg"))
        end
      end
    end
end

function onLoadSection4()
  local rng = require("rng")
  bonusBlocks = {
    Contents = {1090,1248,1170},
    getBlocks = Block.get(224),
    getGround = Block.get(52,1007), -- "-ed grounded grounded for 1000 years.  No LunaLua.  No SMBX2.  No computer.  Go to your room and never come back out."
    iceShattered = false,
    getPrize = false,
    allDone = false
  }

  for index,myBonusBlock in ipairs(bonusBlocks.getBlocks) do
    myBonusBlock.contentID = bonusBlocks.Contents[index]
  end
end

function onLoopSection4()
  if not bonusBlocks.allDone then
    if bonusBlocks.iceShattered then
      -- Bonus game is done!
      --if bonusBlocks.getGround:collideswith(player) then
      --  bonusBlocks.allDone = true
      --end

      -- Get a cool prize!
      --if bonusBlocks.getBlocks:collideswith(player) then
      --  bonusBlocks.getPrize = true
      --end
      for index,myBonusBlock in ipairs(bonusBlocks.getBlocks) do
        if mybonusBlock:collideswith(player) == 3 then
          bonusBlocks.getPrize = true
        end
      end

      for index,myGroundBlock in ipairs(bonusBlocks.getGround) do
        if myGroundBlock:collideswith(player) == 1 then
          bonusBlocks.allDone = true
        end
      end
    end
  end
end
Edit: Here is an image of the debug I encountered:
Image

Re: LunaLua Help

Posted: 19 Jul 2019, 02:27
by ItsFuntime
ItsFuntime wrote: 4 years ago Okay, imagine when you're trying to make a bonus room where you get one shot and you have to toss an ice block to one of the question blocks, and you want to a sound to play when the ice block successfully hits a question block. How do know when the ice block successfully hits that question block?

Here's the code for the scenario:

Code: Select all

function onEvent(eventName)
    if eventName == "Bonus Ice Dies" then
      bonusBlocks.iceShattered = true

      if bonusBlocks.allDone then
        if bonusBlocks.getPrize then
          Audio.playSFX(Misc.resolveFile("hoopla/foodcourt-tada.ogg"))
        else
          Audio.playSFX(Misc.resolveFile("hoopla/foodcourt-lose.ogg"))
        end
      end
    end
end

function onLoadSection4()
  local rng = require("rng")
  bonusBlocks = {
    Contents = {1090,1248,1170},
    getBlocks = Block.get(224),
    getGround = Block.get(52,1007),
    iceShattered = false,
    getPrize = false,
    allDone = false
  }

  for index,myBonusBlock in ipairs(bonusBlocks.getBlocks) do
    myBonusBlock.contentID = bonusBlocks.Contents[index]
  end
end

function onLoopSection4()
  if not bonusBlocks.allDone then
    if bonusBlocks.iceShattered then
      -- Bonus game is done!
      --if bonusBlocks.getGround:collideswith(player) then
      --  bonusBlocks.allDone = true
      --end

      -- Get a cool prize!
      --if bonusBlocks.getBlocks:collideswith(player) then
      --  bonusBlocks.getPrize = true
      --end
      for index,myBonusBlock in ipairs(bonusBlocks.getBlocks) do
        if mybonusBlock:collideswith(player) == 3 then
          bonusBlocks.getPrize = true
        end
      end

      for index,myGroundBlock in ipairs(bonusBlocks.getGround) do
        if myGroundBlock:collideswith(player) == 1 then
          bonusBlocks.allDone = true
        end
      end
    end
  end
end
Edit: Here is an image of the debug I encountered:
Image
Sorry for the double post, but here is rare footage of the glitchy footage (click the pic in the spoiler to play!):
Image

Re: LunaLua Help

Posted: 19 Jul 2019, 05:47
by Hoeloe
None of that is really valid to do. First off, don't use onLoopSection, use onTick and check for the player's section.

Second, don't load libraries inside functions unless you have a REALLY good reason. Just load what you need at the top of the file.

Third and most importantly, you can't grab a list of blocks and use it later expecting it to stay up to date. Same is true of NPCs, BGOs, etc. You must grab a new list every time you want to use them, otherwise you're just asking for errors like this as you attempt to access invalid memory.

Re: LunaLua Help

Posted: 19 Jul 2019, 12:23
by Emral
Fourth: Capitalization matters.

Re: LunaLua Help

Posted: 19 Jul 2019, 14:40
by ItsFuntime
Hoeloe wrote: 4 years ago None of that is really valid to do. First off, don't use onLoopSection, use onTick and check for the player's section.

Second, don't load libraries inside functions unless you have a REALLY good reason. Just load what you need at the top of the file.

Third and most importantly, you can't grab a list of blocks and use it later expecting it to stay up to date. Same is true of NPCs, BGOs, etc. You must grab a new list every time you want to use them, otherwise you're just asking for errors like this as you attempt to access invalid memory.
Okay, I took your advice, Hueylou, and I changed the code around, and now, whenever a bonus block gets hit, it calls an event called "Bonus Block Hit", which sets "getPrize" to "true". Now, when the ice block dies, the floor gets covered with a layer of invisible triggers (REEEEEEE) that finish the bonus game once and for all. And right now, the think the bonus game is all set for now! Thanks~! :D

Only one problemo...each block has the same contents in order, and the content identities are in the same order. I just want the table of contents to have its pages become randomized when Mario enters the room, so that the bonus room will be ready for Klonoa to try out. How would you randomize a table in LunaLua?
Enjl wrote:Fourth: Capitalization matters.
Well, you're not wrong. I mean...

Re: LunaLua Help

Posted: 21 Jul 2019, 21:59
by Hoeloe
ItsFuntime wrote: 4 years ago
Enjl wrote:Fourth: Capitalization matters.
Well, you're not wrong. I mean...
In programming, there is an actual difference between "function" and "Function". As far as the program is concerned, these are as different as "local" and "kjsadkjfkjafsjksakjfjlkjalsk" - totally different.

As for randomising the blocks, you can use either onStart (to randomise at the start of the level) or onLoadSection# (substituting # for the section number, to randomise when the section is entered).

Then, you can create a list of items you want, loop over the blocks using Block.get(id), and then use RNG.irandomEntry on the list of items to select random items to place in them, adjusting the block contents as you do.

Re: LunaLua Help

Posted: 05 Aug 2019, 14:36
by ItsFuntime
Well then! I have randomized the list and now Klonoa can have his little fun and acquire a cool prize whenever he enters the room! Thanks!



Now, about the Toad NPCs...I wonder if you could make a custom NPC that acts like the Toads, such as rewarding a player with a mushroom, or dying on contact from the bad guys...

Edit: Never mind that. Nerf my question!