Solved How to setup traps properly (?)

Question that is answered or resolved.

Crimsondeath

Active member
Hi everyone, I've more or less got this part working, the issue I'm having is that the mines (or the traps in general) I've created don't activate immediately. I have to walk through them several times before they attack. Here's how the mine is coded, for example:

Code:
name    Mine
type    trap
shadow  0
noatflash 1
nolife 1
aggresion 9999
min_noatk_chance 0
max_noatk_chance 0
stealth         6 10

hostile player enemy npc
candamage enemy player npc obstacle

palette data/chars/traps/mine/idle.gif

animationscript  data/scripts/entities/traps/mine.c

anim    idle
    loop    1
    delay    8
    offset    3 3
    @cmd    attackZ -20 20 0 20 -20 20 "ANI_ATTACK1"
    frame    data/chars/traps/mine/idle.gif
    frame    data/chars/traps/mine/idle.gif
    @cmd    clearL
    frame    data/chars/traps/mine/idle.gif

anim    attack1
    loop    0
    delay    10
    offset    4 3
    @cmd    spawnAni "QuakeCall" 0 0 0 "ANI_FOLLOW8" NULL() NULL() NULL()
    frame    data/chars/traps/mine/idle1.gif
    delay    6
    offset    2 2
    @cmd    spawnAni "Explosion1" 0 0 0 "ANI_FOLLOW2" NULL() NULL() NULL()
    frame    data/chars/misc/empty.gif
    @cmd    killentity getlocalvar("self")
    frame    data/chars/misc/empty.gif

I think that "attackZ" makes the trap target a particular entity and not the one that passes over it (sometimes there are like 4 or 5 entities on screen), for example attackZ targets an enemy but when the player walks over the mine, the mine does not explode, until that enemy that it targeted passes over the mine (that's why I added the "clearL" to see if it would help but it didn't xd).

Here's the code for "attackZ":
C++:
void attackZ(int RxMin, int RxMax, int RyMin, int RyMax, int RzMin, int RzMax, void Ani)
{// Attack interruption with range check
    void self = getlocalvar("self");
    void target = findtarget(self); // <----- Get nearest entity (?)
    float x = getentityproperty(self, "x");
    float y = getentityproperty(self, "a");
    float z = getentityproperty(self, "z");
    int dir = getentityproperty(self, "direction");

    if(target!=NULL()){
      float Tx = getentityproperty(target, "x");
      float Ty = getentityproperty(target, "a");
      float Tz = getentityproperty(target, "z");
      float Disx = Tx - x;
      float Disy = Ty - y;
      float Disz = Tz - z;

      if( Disx >= RxMin && Disx <= RxMax && Disy >= RyMin && Disy <= RyMax && Disz >= RzMin && Disz <= RzMax &&dir == 1) // Target within range on right facing?
      {
        performattack(self, openborconstant(Ani)); //Change the animation
      } else if( Disx >= -RxMax && Disx <= -RxMin && Disy >= RyMin && Disy <= RyMax && Disz >= -RzMax && Disz <= -RzMin && dir == 0) // Target within range on left facing?
      {
        performattack(self, openborconstant(Ani)); //Change the animation
      }
    }
}
 
Solution
As Ilu posted above, attackbox is sufficient for landmines.

Though for your scripted method, the detection function is slightly different than mine. The biggest difference is in IDLE. In your IDLE, the function is delcared once so the detection is once every 3x8 centiseconds.
In my IDLE, the function is run in all IDLE frames but the first one.
Code:
anim    idle
@script
  if(frame>=1){
    attack4(-30, 30, -10, 10, 10, "ANI_FOLLOW1");
  }
@end_script
    loop    1
    delay    7
    offset    11 14
    frame    data/chars/misc/traps/mine.png
    frame    data/chars/misc/traps/mine.png
    frame    data/chars/misc/traps/mine.png
    frame    data/chars/misc/traps/mine.png
    frame    data/chars/misc/traps/mine.png #
    frame...
I don't use any script to attack the players on my traps, I just rely on attackboxes.
This is my "stepmine" code:

Header
name stepmine
type trap
shadow 0
facing 1
nolife 1

candamage player npc enemy

palette none

animationscript data/scripts/grabscript.c

Idle and follow (for the explosion and calling particles

anim follow2
loop 0
delay 2
offset 13 38
sound data/sounds/boom.wav
@cmd spawnRandEnt "debris1" "debris2" "debris3" "debris4" 0 0 0
@cmd spawn01 "fboom" 0 0 1
@cmd killentity getlocalvar("self")
frame data/sprites/0empty.gif

anim idle
loop 1
delay 10
offset 9 3
hitflash hitnone
followcond 1
followanim 2
burn -5 0 27 8 15 10 1 0 0 15
dropv 4 4
frame data/chars/misc/stepmine/1.gif
attack 0
frame data/chars/misc/stepmine/1.gif
The trick I use for those traps is: the idle animation has an attackbox on one frame and I disable it on the next one.
Doing this, it will hurt the player again without needing the enemy to be knocked down by other attack.

That mine will explode uppon contact and destroys itself.

For a trap that can hit the player again, I do the same route, but I make the follow animation looped
anim follow2
loop 0
delay 2
offset 13 38
sound data/sounds/boom.wav
@cmd spawnRandEnt "debris1" "debris2" "debris3" "debris4" 0 0 0
@cmd spawn01 "fboom" 0 0 1
@cmd killentity getlocalvar("self")
frame data/sprites/0empty.gif

anim idle
loop 1
delay 10
offset 9 3
hitflash hitnone
followcond 1
followanim 2
burn -5 0 27 8 15 10 1 0 0 15
dropv 4 4
frame data/chars/misc/stepmine/1.gif
attack 0
frame data/chars/misc/stepmine/1.gif
 
As Ilu posted above, attackbox is sufficient for landmines.

Though for your scripted method, the detection function is slightly different than mine. The biggest difference is in IDLE. In your IDLE, the function is delcared once so the detection is once every 3x8 centiseconds.
In my IDLE, the function is run in all IDLE frames but the first one.
Code:
anim    idle
@script
  if(frame>=1){
    attack4(-30, 30, -10, 10, 10, "ANI_FOLLOW1");
  }
@end_script
    loop    1
    delay    7
    offset    11 14
    frame    data/chars/misc/traps/mine.png
    frame    data/chars/misc/traps/mine.png
    frame    data/chars/misc/traps/mine.png
    frame    data/chars/misc/traps/mine.png
    frame    data/chars/misc/traps/mine.png #
    frame    data/chars/misc/traps/mine.png

The detection is once every 7 centiseconds.
You should declare it in all frames to make the mine more reactive.
 
Solution
Both solutions are great, I used the followanim with the invisible hitbox on the old version for everything, even for the chandeliers falling traps xd. But I take de bloodbane solution (I completely forgot that you could do that with frames 😓) , the mine is more reactive now, thanks :) .
 
Back
Top Bottom