Destroying an NPC via mouseclick PLOTSCRIPTING

Make games! Discuss those games here.

Moderators: Bob the Hamster, marionline, SDHawk

Post Reply
User avatar
Fenrir-Lunaris
Metal Slime
Posts: 741
Joined: Mon Oct 15, 2007 10:45 pm
Location: OHR Depot

Destroying an NPC via mouseclick PLOTSCRIPTING

Post by Fenrir-Lunaris »

I'm developing a minigame where you can use the {MOUSE} to fire at enemies and destroy them with a simple click, similar to that minigame in Mario paint where you swatted flies. Since this is my first experience with manipulating the mouse, here's a short run of what I've got, and where things break down.

Image
A brief technical demonstration of what's going on. Enemies rush at you with deadly weapons, who'll kill you in one hit and send you back to the start of the level/nearest safe point. You use the mouse to shoot and kill them before they can touch you. Simple and easy, right?

Code: Select all

script, mouse script, begin
  # Must be called before any other mouse command
  init mouse
  variable (avoid warning) # Kludge to suppress the "infinite loop" compiler warning
  avoid warning := true
  # Infinite loop, yes, there's a reason
  while (avoid warning) do, begin
    # You can put an appropriate condition here, or "true" (or "avoid warning" to avoid the warning)
    if (tag:Mouse active) then, begin
      # In the next line, change the "0" to the ID of the mouse NPC
      put NPC (0, mouse pixel x + camera pixel x, mouse pixel y + camera pixel y)
      if (mouse button(left button)) then, begin
        variable (NPC, Num NPC, i)
        num NPC := NPC at pixel (mouse pixel x + camera pixel x, mouse pixel y + camera pixel y, 1)
        for (i,0,Num NPC -- 1,1) do, begin
          NPC := npc at pixel(mouse pixel x + camera pixel x, mouse pixel y + camera pixel y, i)
          if(get NPC ID(NPC) == 8) then, begin
            FOE8
          end
	  if(get NPC ID(NPC) == 9) then, begin
            FOE9
          end
	  if(get NPC ID(NPC) == 10) then, begin
            FOE10
          end
        end
        # Check what's been clicked
      end
    end
    # Let game.exe breathe
    wait
  end
end
NPC 0 has a little crosshairs to lock onto any foe on screen, and if the script is working, it'll recognize which NPC is being targeted, then run a smaller script to determine what to do with it...

Code: Select all

script,FOE8,begin
 suspend NPCs  #I don't really want anything moving around for a second
 tweak palette (40,-10,-10)
 update palette
 play sound (sfx:Slash8Bit,false,true)
 wait (1)
 reset palette
 update palette #All this is to basically make the screen flash
 Alter NPC (8,NPCstat:picture,14)
 wait (1)#the NPC VERY briefly changes its sprite to explode
 set tag (tag:FOE8,on)#And this tag kills the NPC
 resume NPCs
end
The script is doing one of two things, which I'm not positive I understand what's going on. Either the NPC crosshairs is not lining up at all with the desired NPCs to trigger the proper script.... ...OR, there's an error in each NPC script that somehow is preventing them from running. I'd much rather not even bother with the ACCURACY of whether the mouse's crosshairs are exactly lined up with the NPC "enemy", so long as it's on the same tile It also has to be specific as to what NPC is being targeted, since there are "friendlies" also on each map who you don't want exploding for no apparent reason.
To friends long gone, and those I've yet to meet - thank you.
User avatar
Mogri
Super Slime
Posts: 4598
Joined: Mon Oct 15, 2007 6:38 pm
Location: Austin, TX
Contact:

Post by Mogri »

Try something like this:

Code: Select all

for (i, 8, 10) do, begin #NPC ids 8-10
  for (j, 0, npc copy count(i)) do, begin
    ref := npc reference(i, j) # Get the Jth copy of npc I
    if &#40;npc pixel x&#40;ref&#41; -- npc pixel x&#40;0&#41; << 10 &&
	npc pixel x&#40;0&#41; -- npc pixel x&#40;ref&#41; << 10 &&
	npc pixel y&#40;ref&#41; -- npc pixel y&#40;0&#41; << 10 &&
	npc pixel y&#40;0&#41; -- npc pixel y&#40;ref&#41; << 10&#41; then, begin
      kill npc &#40;ref&#41; # kill off the one we found
    end
  end
end
And replace kill npc(ref) with whatever it is you want to do with them. The problem, I think, is that npc at pixel does not really work like you want it to. The code above will detect any NPCs that are within the hitbox of the crosshairs. You can increase or decrease the 10s to adjust the precision needed.

Let me know if this needs more explaining.
User avatar
Bob the Hamster
Liquid Metal King Slime
Posts: 7460
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

By the way, that "avoid warning" hack is not needed unless you are using a rather old version of hspeak.

Code: Select all

--3Ec 2006-11-30 while&#40;true&#41; no longer produces a warning
User avatar
Fenrir-Lunaris
Metal Slime
Posts: 741
Joined: Mon Oct 15, 2007 10:45 pm
Location: OHR Depot

Post by Fenrir-Lunaris »

Mogri wrote:Try something like this:

Code: Select all

for &#40;i, 8, 10&#41; do, begin #NPC ids 8-10
  for &#40;j, 0, npc copy count&#40;i&#41;&#41; do, begin
    ref &#58;= npc reference&#40;i, j&#41; # Get the Jth copy of npc I
    if &#40;npc pixel x&#40;ref&#41; -- npc pixel x&#40;0&#41; << 10 &&
	npc pixel x&#40;0&#41; -- npc pixel x&#40;ref&#41; << 10 &&
	npc pixel y&#40;ref&#41; -- npc pixel y&#40;0&#41; << 10 &&
	npc pixel y&#40;0&#41; -- npc pixel y&#40;ref&#41; << 10&#41; then, begin
      kill npc &#40;ref&#41; # kill off the one we found
    end
  end
end
And replace kill npc(ref) with whatever it is you want to do with them. The problem, I think, is that npc at pixel does not really work like you want it to. The code above will detect any NPCs that are within the hitbox of the crosshairs. You can increase or decrease the 10s to adjust the precision needed.

Let me know if this needs more explaining.
Image
This was the first thing that went through my head reading this. To be frank, there's a reason my games focus almost entirely on graphics, rather than scripting. Last month's Hamsterspeak "comic" using the endless loop of two backdrops is literally the most complex scripting I've ever done.

The script I posted was essentially a cut-and-run copy from the official site. Somehow I'll have to figure out how to make it so it also recognize individual NPC "foes" so I can make some take more than one hit to kill. This was partly the reason I have it check each individual NPC, rather than use NPC references. Normal foes simply turn on a specific tag for each individual foe, whereas stronger enemies would add a temporary item to the inventory, then die after so many of those temporary items are aquired. I figure this is the easiest way to fake enemy health. If I could somehow or other dumb it down even further to only check by TILES instead of pixels, that would be tremendously more helpful. Anything to avoid using the default battle engine.
To friends long gone, and those I've yet to meet - thank you.
User avatar
Mogri
Super Slime
Posts: 4598
Joined: Mon Oct 15, 2007 6:38 pm
Location: Austin, TX
Contact:

Re: Destroying an NPC via mouseclick PLOTSCRIPTING

Post by Mogri »

Right. Well, in other words, your script should look like this:

Code: Select all

script, mouse script, begin
  # Must be called before any other mouse command
  init mouse
  variable &#40;avoid warning&#41; # Kludge to suppress the "infinite loop" compiler warning
  avoid warning &#58;= true
  # Infinite loop, yes, there's a reason
  while &#40;avoid warning&#41; do, begin
    # You can put an appropriate condition here, or "true" &#40;or "avoid warning" to avoid the warning&#41;
    if &#40;tag&#58;Mouse active&#41; then, begin
      # In the next line, change the "0" to the ID of the mouse NPC
      put NPC &#40;0, mouse pixel x + camera pixel x, mouse pixel y + camera pixel y&#41;
      if &#40;mouse button&#40;left button&#41;&#41; then, begin
        # Check what's been clicked
        for &#40;i, 8, 10&#41; do, begin #NPC ids 8-10
          for &#40;j, 0, npc copy count&#40;i&#41;&#41; do, begin
            ref &#58;= npc reference&#40;i, j&#41; # Get the Jth copy of npc I
            if &#40;npc pixel x&#40;ref&#41; -- npc pixel x&#40;0&#41; << 10 &&
                npc pixel x&#40;0&#41; -- npc pixel x&#40;ref&#41; << 10 &&
                npc pixel y&#40;ref&#41; -- npc pixel y&#40;0&#41; << 10 &&
                npc pixel y&#40;0&#41; -- npc pixel y&#40;ref&#41; << 10&#41; then, begin
              kill npc &#40;ref&#41; # kill off the one we found
            end
         end
       end
      end
    end
    # Let game.exe breathe
    wait
  end
end
You might replace kill npc(ref) with FOE8, FOE9, and FOE10, based on your script.

Needs more splaining?
User avatar
Fenrir-Lunaris
Metal Slime
Posts: 741
Joined: Mon Oct 15, 2007 10:45 pm
Location: OHR Depot

Post by Fenrir-Lunaris »

Great!

Except I need to define the following now:
i
j
ref

And the figure how to make it differentiate and run an entirely different script depending on what NPC reference is called.
To friends long gone, and those I've yet to meet - thank you.
User avatar
Mogri
Super Slime
Posts: 4598
Joined: Mon Oct 15, 2007 6:38 pm
Location: Austin, TX
Contact:

Post by Mogri »

Do your FOE* scripts do anything different? If not, you can just replace the 8 in FOE8 with the "ref" parameter.

Code: Select all

script,  KILLFOE, who, begin
 suspend NPCs  #I don't really want anything moving around for a second
 tweak palette &#40;40,-10,-10&#41;
 update palette
 play sound &#40;sfx&#58;Slash8Bit,false,true&#41;
 wait &#40;1&#41;
 reset palette
 update palette #All this is to basically make the screen flash
 Alter NPC &#40;WHO, NPCstat&#58;picture,14&#41;
 wait &#40;1&#41;#the NPC VERY briefly changes its sprite to explode
 set tag &#40;WHO, on&#41;#And this tag kills the NPC
 resume NPCs
end
...making sure tag 8 corresponds to NPC 8, etc.
User avatar
Fenrir-Lunaris
Metal Slime
Posts: 741
Joined: Mon Oct 15, 2007 10:45 pm
Location: OHR Depot

Post by Fenrir-Lunaris »

For the sake of argument, every NPC does something radically and totally different. Otherwise, even bosses would die in a single hit, locked doors wouldn't function properly, etc.

http://hamsterrepublic.com/ohrrpgce/ind ... game_.html
To friends long gone, and those I've yet to meet - thank you.
User avatar
Fenrir-Lunaris
Metal Slime
Posts: 741
Joined: Mon Oct 15, 2007 10:45 pm
Location: OHR Depot

Post by Fenrir-Lunaris »

WORKAROUND. Make the Target check TILE locations! Granted, it's now about as accurate as a Nintendo Zapper (tm), but checking NPC locations SHOULD theoretically be MUCH easier.

Code: Select all

script, mouse script, begin
  # Must be called before any other mouse command
  init mouse
  variable &#40;avoid warning&#41; # Kludge to suppress the "infinite loop" compiler warning
  avoid warning &#58;= true
  # Infinite loop, yes, there's a reason
  while &#40;avoid warning&#41; do, begin
    # You can put an appropriate condition here, or "true" &#40;or "avoid warning" to avoid the warning&#41;
    if &#40;tag&#58;Mouse active&#41; then, begin
      # In the next line, change the "0" to the ID of the mouse NPC
      set NPC Position &#40;0, &#40;&#40;mouse pixel x + camera pixel x&#41; /20&#41; , &#40;&#40;mouse pixel y + camera pixel y&#41; /20&#41;&#41;
      if &#40;mouse button&#40;left button&#41;&#41; then, begin
        variable &#40;NPC, Num NPC, i&#41;
        num NPC &#58;= NPC at spot &#40; &#40;&#40;mouse pixel x + camera pixel x&#41; /20&#41; , &#40;&#40;mouse pixel y + camera pixel y&#41; /20&#41;, 1&#41;
        for &#40;i,0,Num NPC -- 1,1&#41; do, begin
          NPC &#58;= npc at spot&#40;&#40;&#40;mouse pixel x + camera pixel x&#41; /20&#41;,  &#40;&#40;mouse pixel y + camera pixel y&#41; /20&#41;, i&#41;

          if&#40;get NPC ID&#40;NPC&#41; == 8&#41; then, begin
            FOE8
          end
     	  if&#40;get NPC ID&#40;NPC&#41; == 9&#41; then, begin
            FOE9
          end
     	  if&#40;get NPC ID&#40;NPC&#41; == 10&#41; then, begin
            FOE10
          end
        end
        # Check what's been clicked
      end
    end
    # Let game.exe breathe
    wait
  end
end
To friends long gone, and those I've yet to meet - thank you.
User avatar
Fenrir-Lunaris
Metal Slime
Posts: 741
Joined: Mon Oct 15, 2007 10:45 pm
Location: OHR Depot

Post by Fenrir-Lunaris »

And there it is. Working.

Code: Select all

script, mouse script, begin
  # Must be called before any other mouse command
  init mouse
  variable &#40;avoid warning&#41; # Kludge to suppress the "infinite loop" compiler warning
  avoid warning &#58;= true
  # Infinite loop, yes, there's a reason
  while &#40;avoid warning&#41; do, begin
    # You can put an appropriate condition here, or "true" &#40;or "avoid warning" to avoid the warning&#41;
    if &#40;tag&#58;Mouse active&#41; then, begin
      # In the next line, change the "0" to the ID of the mouse NPC
      set NPC Position &#40;0, &#40;&#40;mouse pixel x + camera pixel x&#41; /20&#41; , &#40;&#40;mouse pixel y + camera pixel y&#41; /20&#41;&#41;
      if &#40;mouse button&#40;left button&#41;&#41; then, begin
	  
          if &#40; &#40; &#40;NPC X &#40;0&#41;&#41; == &#40;NPC X &#40;8&#41;&#41; &#41; and &#40; &#40;NPC Y &#40;0&#41;&#41; == &#40;NPC Y &#40;8&#41;&#41; &#41; &#41; then, begin
            FOE8
          end
     	  if &#40; &#40; &#40;NPC X &#40;0&#41;&#41; == &#40;NPC X &#40;9&#41;&#41; &#41; and &#40; &#40;NPC Y &#40;0&#41;&#41; == &#40;NPC Y &#40;9&#41;&#41; &#41; &#41; then, begin
            FOE9
          end
     	  if &#40; &#40; &#40;NPC X &#40;0&#41;&#41; == &#40;NPC X &#40;10&#41;&#41; &#41; and &#40; &#40;NPC Y &#40;0&#41;&#41; == &#40;NPC Y &#40;10&#41;&#41; &#41; &#41; then, begin
            FOE10
          end
        # Check what's been clicked
      end
    end
    # Let game.exe breathe
    wait
  end
end
And there it is. TILE-based mouse movement, with a simple-to-understand series of steps to check for individual NPC placement, and run individualized scripts. Even a newbie should be able to reasonably tweak it, or use it in their own games, or even edit levels. Nice.
To friends long gone, and those I've yet to meet - thank you.
Post Reply