7. Scripting a Swordsman
Instead of the old if (playertouchsme){hurt} stuff, lets make the NPC
baddy use a sword to attack players. Back where we first set up the
NPC, we'll have to make some changes.
//New Beginning Part
if (created){
showcharacter;
this.speed=.5;
swordpower=1; //removed this.pow since
I'm not gonna use it, and added swordpower. this is the amount of
half hearts to be taken off of a player that is hit by the sword.
setcharprop #1,flaminsword.gif; //this
is the image that will be used for the baddy's sword.
this.attackdist=3;
//this distance that baddy has to be before attacking. (The smaller
the number, the closer the baddy will need to be before using his sword.)
hearts=3;
hurtdx=0;
hurtdy=0;
timeout=.05;
}
//End of Script
Now that we have that stuff set, we need to make it attack.
So we're gonna go within the timeout loop we set up earlier, and add
a bit. Also, to make it easier, we're going to combine all the hearts>0
stuff in the timeout part. You'll see why.
//New Timeout sections
if (timeout&&hearts>0&&this.swing!=1){ //this
shows all the stuff to be done in the timeout while the npc has hearts,
and is not using his sword.
sprite=(sprite%8)+1;
this.distx=abs(playerx-x);
this.disty=abs(playery-y);
if (this.distx<=this.disty){
if (playery<y)dir=0;
if (playery>y)dir=2;
}else{
if (playerx<x)dir=1;
if (playerx>x)dir=3;
}
if (this.distx==0){
this.addy=this.speed;
}else if (this.disty==0){
this.addx=this.speed;
}else if (this.distx>this.disty){
this.ratio=this.disty/this.distx;
this.addx=this.speed;
this.addy=this.speed*this.ratio;
}else if (this.disty>this.distx){
this.ratio=this.distx/this.disty;
this.addy=this.speed;
this.addx=this.speed*this.ratio;
}
if (y<playery&&!onwall(x+1.5,y+3+this.addy)) y+=this.addy;
if (y>playery&&!onwall(x+1.5,y-this.addy)) y-=this.addy;
if (x<playerx&&!onwall(x+3+this.addx,y+1.5)) x+=this.addx;
if (x>playerx&&!onwall(x-this.addx,y+1.5)) x-=this.addx;
this.distance=((this.distx*this.distx)+(this.disty*this.disty))^.5;
//this
will find the total distance between the baddy and the player
if (this.distance<=this.attackdist){ //tells
what to do if the distance is less than or equal to what we specified as
the closest the baddy will be when he swings his sword.
this.swing=1; //tells
the baddy to start swinging his sword
sprite=9; //the first
sprite for a sword swing.
}
timeout=.05;
}
if (timeout&&this.swing==1&&hearts>0){ //this
is the timeout for when the npc IS swinging his sword
if (sprite<13){ //13 is the last
sword swinging sprite, so if the baddy is less than sprite 13, it still
has sprites to do.
sprite++; //same concept
as the walking script
}else{
sprite=1; //if the baddy
is done swinging his sword, he needs to be walking again
this.distance=this.attackdist+5; //dont
want him to continue to swing his sword, so you reset the distance
this.swing=0; //so he
wont continue to swing his sword
}
timeout=.05; //to continue the other
timeout loop.
}
//End of Script
Quite a bit had to be changed. But it shouldn't be to hard to
understand. I'd personally remove the previous hurt stuff that was
added if you go for this method of attack.
Keep in mind, you can make the baddy more or less challenging based
on what you set your variables too. For example, the defualt character
NPCs that stefan made, attacks when 3 spaces away from the player.
I made a NPC that attacks when 4 spaces away. The difference is,
at 4 spaces away the player can NOT hit the baddy with his sword.
At 3, the player can hit it from certain angles. 2 or below, can
easily be hit with a well timed swing. Above 4, the baddy swings
way to early, and is vulnerable (also dumb looking).
This script can create a minor glitch, if the baddy is hit when using
its sword, after recovering from the hit, the baddy finishes his sword
(can look glitchy, and cause problems). So we're going to fix that.
Just go to the hit part of the script and add in this.swing=0, like so:
//Fixing the sword swing glitch after a hit
if ((washit||wasshot||exploded||waspelt)&&hearts>0){
if (washit){
hurtdx=x;
hurtdy=y;
hearts-=playerswordpower;
}
if (wasshot){
hearts--;
}
if (exploded){
hearts--;
}
if (waspelt){
if (peltwithbush) hearts-=.5;
if (peltwithsign || peltwithvase
|| peltwithstone) hearts-=1;
if (peltwithblackstone) hearts
-=1.5;
}
sprite=39;
this.hit=1;
while(this.hit==1){
i+=.5;
if (x>playerx&&!onwall(x+2.5,y+1.5)) x+=.5;
if (x<playerx&&!onwall(x-.5,y+1.5)) x-=.5;
if (y>playery&&!onwall(x+1.5,y+2.5)) y+=.5;
if (y<playery&&!onwall(x-1.5,y-.5)) y-=.5;
if (i>=3.5){
this.hit=0;
i=0;
}
sleep .05;
}
this.swing=0; //Necessary to stop
any glitches accomodating the sword swing.
timeout=.05;
}
//End of Script
And thats it for adjustments.
So lets compile the basic Swordsman baddy.
//Basic Swordman Baddy
if (created){
showcharacter;
setcharprop #1,sword1.gif;
setcharprop #n,Basic Swordsman;
hearts=3;
hurtdx=0;
hurtdy=0;
}
if (playerenters||wasthrown){
this.attackdist=3;
this.speed=.5;
swordpower=1;
timeout=.05;
}
if (timeout&&isleader&&hearts>0&&this.swing!=1){
if (hearts>0){
sprite=(sprite%8)+1;
this.distx=abs(playerx-x);
this.disty=abs(playery-y);
if (this.distx<=this.disty){
if (playery<y)dir=0;
if (playery>y)dir=2;
}else{
if (playerx<x)dir=1;
if (playerx>x)dir=3;
}
if (this.distx==0){
this.addy=this.speed;
}else if (this.disty==0){
this.addx=this.speed;
}else if (this.distx>this.disty){
this.ratio=this.disty/this.distx;
this.addx=this.speed;
this.addy=this.speed*this.ratio;
}else if (this.disty>this.distx){
this.ratio=this.distx/this.disty;
this.addy=this.speed;
this.addx=this.speed*this.ratio;
}
if (y<playery&&!onwall(x+1.5,y+3+this.addy))
y+=this.addy;
if (y>playery&&!onwall(x+1.5,y-this.addy))
y-=this.addy;
if (x<playerx&&!onwall(x+3+this.addx,y+1.5))
x+=this.addx;
if (x>playerx&&!onwall(x-this.addx,y+1.5))
x-=this.addx;
this.distance=((this.distx*this.distx)+(this.disty*this.disty))^.5;
if (this.distance<=this.attackdist){
this.swing=1;
sprite=9;
}
timeout=.05;
}
}
if (timeout&&isleader&&this.swing==1&&hearts>0){
if (sprite<13){
sprite++;
}else{
sprite=1;
this.distance=this.attackdist+5;
this.swing=0;
}
timeout=.05;
}
if ((washit||wasshot||exploded||waspelt)&&hearts>0){
if (washit){
hurtdx=x;
hurtdy=y;
hearts-=playerswordpower;
}
if (wasshot){
hearts--;
}
if (exploded){
hearts--;
}
if (waspelt){
if (peltwithbush) hearts-=.5;
if (peltwithsign || peltwithvase || peltwithstone)
hearts-=1;
if (peltwithblackstone) hearts -=1.5;
}
sprite=39;
this.swing=0;
this.hit=1;
while(this.hit==1){
i+=.5;
if (x>playerx&&!onwall(x+2.5,y+1.5)) x+=.5;
if (x<playerx&&!onwall(x-.5,y+1.5)) x-=.5;
if (y>playery&&!onwall(x+1.5,y+2.5)) y+=.5;
if (y<playery&&!onwall(x-1.5,y-.5)) y-=.5;
if (i>=3.5){
this.hit=0;
i=0;
}
sleep .05;
}
timeout=.05;
}
if (hurtdx!=0||hurtdy!=0){
sprite=39;
hurtdx=0;
hurtdy=0;
}
if (timeout&&hearts<=0&&isleader){
while(d<=8){
dir=(dir+3)%4;
d++;
sleep .1;
}
i = random(0,100);
if (i<10) lay greenrupee;
else if (i<15) lay bluerupee;
else if (i<30) lay heart;
sprite=40;
}
//End of Script
The NPC with the name "Basic Swordman" in the level basicswordmen.graal,
will have that script.