12. Making a baddy that can catch/throw objects
The following baddy takes advantage of the new commands found in version
1.3.7 of Graal (so of course you need that version or later to make this
kind of baddy). We're going to take the basic baddy, and edit it's
script a little bit.
First off, we want to script it so it can catch something when thrown
at it. So we do the following:
//Catching Script
if (waspelt&&this.carry!=1){ //This
is what to do if the baddy was pelt, and it's not currently carrying something.
this.carry=1; //I'll be using "this.carry"
to tell if the baddy is carrying something or not. When this is equal
to 1, it is carrying.
sprite=24; //The first carrying
sprite.
if (peltwithbush) carryobject bush; //This
and the lines after it tell what to carry based on what it was hit with.
if (peltwithsign) carryobject sign;
if (peltwithvase) carryobject vase;
if (peltwithstone) carryobject stone;
if (peltwithblackstone) carryobject blackstone;
timeout=.05; //resets the timeout
so the NPC can walk again.
}
//End of Script
And that will make the baddy catch something thrown at it.
But we need to tweak the hit detection script to allow for the new
catching ability.
//New Hit Detection Script
if ((washit||wasshot||exploded||(waspelt&&this.carry!=0))&&hearts>0){
//included
the (waspelt&&this.carry!=0) which means the baddy can be hurt
when it is pelt with an object and is currently not carrying anything.
if (this.carry==1){ //this is what
to do if the baddy happens to be carrying something
throwcarry; //throws
whatever it was carrying
this.carry=0; //says
it is no longer carrying an object
}
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;
}
timeout=.05;
}
//End of Script
Now it can be hurt and can catch things.
But we still need to make it walk and carry the objects at the same
time, so we're going to edit the walking script. Also, the attacking
stuff is included in the same timeout, so we'll do both right now:
//New walking script
if (timeout){
if (hearts>0){
if (this.carry!=1){
//If it's not carrying something it needs to use the usual walking sprites
sprite=(sprite%8)+1;
}else if (this.carry==1){ //But
if it is carrying an object it needs to use the carrying sprites
if (sprite<32){
//the last carrying sprite
sprite++;
}else{
sprite=25; //the
first carrying sprite
}
}
this.distx=abs(playerx-x);
this.disty=abs(playery-y);
this.distance=((this.distx*this.distx)+(this.disty*this.disty))^.5;
//checks
for the overall distance between the player and the baddy
if (this.distance<=this.attackdist&&this.carry!=0){
//this
is what to do if the baddy is close enough to the player to throw what
it is carrying
throwcarry; //throws
what the baddy is carrying
this.carry=0; //resets
this.carry since the baddy is no longer carrying something
}
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;
timeout=.05;
}
}
//End of Script
Well, it can carry the object, as well as throw it.
But I used the variable "this.attackdist" so we need to define it.
Keep in mind that the NPC will throw the object when the distance between
it and the player is less than or equal to the amount specified in this.attackdist.
//New Beginning Part
if (created){
showcharacter;
this.speed=.1;
this.pow=2;
this.attackdist=5; //this is how
close the baddy must be before throwing his object
hearts=3;
hurtdx=0;
hurtdy=0;
}
//End of Script
There, we're all done.
Lets compile the entire catcher/thrower script:
//Completed Catcher/Thrower Script
if (created){
showcharacter;
setcharprop #n,Catcher;
hearts=3;
hurtdx=0;
hurtdy=0;
}
if (playerenters||wasthrown){
this.speed=.3;
this.pow=2;
this.attackdist=5;
timeout=.05;
}
if (timeout&&isleader){
if (hearts>0){
if (this.carry!=1){
sprite=(sprite%8)+1;
}else if (this.carry==1){
if (sprite<32){
sprite++;
}else{
sprite=25;
}
}
this.distx=abs(playerx-x);
this.disty=abs(playery-y);
this.distance=((this.distx*this.distx)+(this.disty*this.disty))^.5;
if (this.distance<=this.attackdist&&this.carry!=0){
throwcarry;
this.carry=0;
}
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;
timeout=.05;
}
}
if (hearts>0&&(playertouchsme||(abs((x+1.5)-(playerx+1.5))<=3
&&abs((playery+1.5)-(y+1.5))<=3))) {
hurt this.pow;
}
if ((washit||wasshot||exploded||(waspelt&&this.carry!=0))&&hearts>0){
if (this.carry==1){
throwcarry;
this.carry=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;
}
timeout=.05;
}
if (waspelt&&this.carry!=1){
this.carry=1;
sprite=24;
if (peltwithbush) carryobject bush;
if (peltwithsign) carryobject sign;
if (peltwithvase) carryobject vase;
if (peltwithstone) carryobject stone;
if (peltwithblackstone) carryobject blackstone;
timeout=.05;
}
if (hurtdx!=0||hurtdy!=0){
sprite=0;
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
There you have it. This baddy has the name "Catcher" in basicbaddies.graal