Looking for an Attack
I am going to show a few functions here, these will have to work together to produce one common effect: the sword attack.  I'm illustrating the sword attack because it is the easiest to script when dealing with showcharacter NPCs.
 
function AttackCheck(){ 
  GetDist()
  if (this.dist<= this.attackdist){ 
    this.mode=1; 
    sprite=9; 
  } 
}
Lets start off with the function AttackCheck().  That one opens up by getting the distance from the NPC to its target by calling GetDist().  Then it compares that distance ( this.dist) to the distance you want it to attack at (defined in the Initialize() function, set to this.attackdist); and if the current distance to the target is less than or equal to the distance it needs to attack at, then it sets the mode of the NPC (this.mode) to 1.  Later, in the Control Loop, you will see how to manipulate " modes" of your baddy to keep the script short and simple.  Since I have designated this to be a sword attack, then a mode of 1 is going to be my sword attack, so I have to set the sprite of the baddy to 9.
This function is called somewhere within the Control Loop so that everytime the NPC does an action (during a timeout) it will check to see if it is close enough to its target to attack it.

Maybe I'm a complete moron, but everytime I try to use setani or setcharani it does NOT change the sprites or animation of my NPCs.  Because of this, I stick to the old sprite numbering system.  It will make me need to use another function just for changing the sprites during the sword attack, however.

 
Using a Sword
This next function is what controls the changing of the sprites of the baddy.
 
function SwordAttack(){ 
  if (sprite<13) sprite++; 
  else { 
    sprite=0; 
    this.mode=0; 
  } 
}
The sword attacking sprites are from 9 to 13.  If this function is called, the baddy's mode is already set to 1 (the attacking mode ) and its sprite was also set to 9.  Because of this, we want to see if the current sprite is less than 13, and if it is,we'll add one to that to go to the next frame of animation.  But if the 13th sprite has already been reached, then the sword attack is over, so we reset this.mode to 0, and also set the sprite back to 0 so it can begin walking again. 
This function will also need to be called within the Control Loop, and since the control loop is a timeout loop, this function works because one is being added to the current sprite every timeout; thus creating animation.

The next function is totally optional, but I think it rounds off the baddy.  Hell, if you want a baddy that doesn't use a sword, but attacks just by touching its target, forget the previous two functions I spoke about, and just use the following one.
 

Attacking Without a Weapon
In the old days, we used the playertouchsme flag to check to see if a player is touching the baddy so that the baddy can hurt the player.  Well that method sucks if you want to hurt something besides the player.  Then there was this whole use of testnpc/testcompu/testplayer.  Those work great, but then "hitobjects" was created.  So what I did was I took the old circle drawing script and turned it into a "if anything touches me" type of thing.  Here, just look at the following function:
 
function RadialHitDetection(){ 
 for (this.angle=0; this.count<20;this.angle+=.314){ 
    this.testx=x+1+cos( this.angle)*this.radius
    this.testy=y+1.3+sin( this.angle)*this.radius
    this.count++; 
    hitobjects swordpower, this.testx,this.testy
  } 
  this.count=0; 
}
This function starts by defining a for loop that has a variable this.angle initialized as 0, and will increase it by .314 each loop, and will keep executing until this.count has reached 20.  For those of you who haven't had trig, a circle is equal to 2*pi.  And pi is equal to 3.14.  So if this.angle is increasing by .314, 20 times, then it will be equal to 2*3.14 when this loop has finished executing, thus drawing a perfect circle around the NPC.  What I do from there is I set this.testx equal to the center of the NPC plus the cos of this.angle times this.radius.  If you are to use this function you should define this.radius in your Initialize() function, and should be equal to half the width of your NPC (that is also where you set the value for swordpower).  Since showcharacter NPCs are 3 tiles wide, I initialize this.radius as 1.5.  Then this.testy is set to the same thing except using sin instead of cos (this is all basic trig stuff).  After that I add one to this.count (so that it can eventually reach 20).  Lastly for this loop, I hit any object that is on this.testx,this.testy .  Notice that even though I use the same vars as the other functions (this.testx and this.testy ) I can use this function in conjunction with the others without causing glitches because this.testx and this.testy and defined every single time before they are used.  And the very last step of the RadialHitDetection() function is to reset this.count to 0 so I can use this loop again next timeout.
This function would need to be called in the Control Loop but while the NPC is not attacking.  So basically at the same time the movement function is being called.
If you want to visually see what this hit detection looks like, just below the "hitobjects" command, add in the following command:
 
showimg this.count, image.png,this.testx, this.testy;
 
Replace image.png with a small graphic that you have on your computer.  This will place an image at every point that the NPC checks to hit.
 
Previous Topic         Home           Next Topic