Decided to script a typical baddy.

Features :

- Highlight customizable settings
- Sword and Bow attacks
- Solid wall detection
- Goes ‘agro’ on anyone near him swinging his sword if he happens to be hit(AKA cheap ‘chase player that hit me detection’)
- Cuts down bushes in his path to try to reach you

Also taking any suggestions to improve him!

[php]

i// NPC made by Shiny

if (created) {

showcharacter;

setcharprop #n,Bad Guy; // Name

setcharprop #1,sword1.png; // Sword image

setcharprop #2,shield1.png; // Shield image

setcharprop #3,head1212.png; // Head image

setcharprop #8,body.png; // Body image

setcharprop #C0,black; // Skin color

setcharprop #C1,black; // Coat color

setcharprop #C2,black; // Sleeve color

setcharprop #C3,black; // Shoe color

setcharprop #C4,black; // Belt color

swordpower = 1; // Sword power

dir = 2; // Starting direction

hearts = 3; // Heart count

darts = 5; // Dart count

this.speed = .45; // Chase speed

this.sight = 15; // How far it can see

this.bowcooldown = 2; // How long between shooting

this.bowfreezetime = .5; // Freeze time from shooting

this.swordfreezetime = .35; // Freeze time from swinging sword

this.hurtrecoil = .35; // How long they recoil from a hit

this.hurtpause = .75; // How long they freeze from a hit

this.patience = 5; // How long they will wait until giving up when they can’t get to player

setstring this.animations,idle,walk,walk,sword2,shoot,hurt,dead;

this.orghearts = hearts;

this.orgdarts = darts;

this.mode = 0;

this.freezetimer = 0;

hurtdx = 0;

hurtdy = 0;

this.bushtiles = {

0x2, 0x3,

0x12, 0x13,

0x35E,0x35F,

0x36E,0x36F,

0xA02,0xA03,

0xA12,0xA13,

};

this.bushreplace = {

0x2A5,0x2A6,

0x2B5,0x2B6,

0x388,0x389,

0x389,0x388,

0xC90,0xC91,

0xCA0,0xCA1,

};

timeout = 0.05;

}

if (playerenters) {

if (hearts <= 0) {

hearts = this.orghearts;

hurtdx = 0;

hurtdy = 0;

this.target = -1;

darts = this.orgdarts;

this.freezetimer = 0;

this.mode = 0;

}

timeout = 0.05;

}

if (timeout) {

if (this.mode != 6) {

if (this.freezetimer =< 0){

if (this.mode == 0) {

this.target = -1;

FindPlayer();

} else if (this.mode == 2) {

if (this.target == -1 || players[this.target].hearts <= 0) this.mode = 0;

dx = (players[this.target].x+1.5) - (x+1.5);

dy = (players[this.target].y+2) - (y+2);

dist = (dx^2 + dy^2)^.5;

dir = getdir(dx,dy);

```
if (dist =< 4 || (dist < 5 && strequals(#m(this.target),sword2))) {
CheckBushes();
this.mode = 3;
this.freezetimer = this.swordfreezetime;
}
this.cansee = 1;
for (i=1;i<((dist < this.sight) ? int(dist) : this.sight);i++) {
if (onwall(x+1.5+(dx/dist)*i+.5,y+2+(dy/dist)*i+.5)) this.cansee = 0;
}
if (this.cansee == 0) this.findtolerance += 0.05;
else this.findtolerance = 0;
if (this.findtolerance > this.patience) this.mode = 0;
if (dist > 3) {
if (dist > this.sight) {
if (this.shootcooldown <= 0 && darts>0 && ((dir in {0,2} && abs(dx) < 2) || (dir in {1,3} && abs(dy) < 2))) {
shootarrow dir;
darts--;
this.mode = 4;
this.freezetimer = this.bowfreezetime;
this.shootcooldown = this.bowcooldown;
}
this.farchase += 0.05;
} else {
this.shootcooldown = 0;
this.farchase = 0;
}
if (this.farchase > this.patience) this.mode = 0;
if (!onwall2(x+.5+(1/16)+vecx(dx>0?3:1)*this.speed,y+1+(1/16),2-2/16,2-2/16)) x += (dx/dist)*this.speed;
else x = int(x)+.5;
if (!onwall2(x+.5+(1/16)+,y+1+(1/16)+vecy(dy>0?2:0)*this.speed,2-2/16,2-2/16)) y += (dy/dist)*this.speed;
else y = int(y+.5);
CheckBushes();
}
} else if (this.mode in {3,4,5}) {
if (this.freezetimer == 0) this.mode = 2;
}
if(!strequals(#m(-1),#I(this.animations,this.mode))) setcharani #I(this.animations,this.mode),;
} else if (this.mode == 5) {
if (!onwall2(x+.5+vecx(hurtdx>0?3:1),y+1,2,2)) x += hurtdx;
else x = int(x)+.5;
if (!onwall2(x+.5,y+1+vecy(hurtdy>0?2:0),2,2)) y += hurtdy;
else y = int(y+.5);
}
if (this.shootcooldown > 0) this.shootcooldown -= 0.05;
if (this.freezetimer > 0) this.freezetimer -= 0.05;
if (this.hurtcounter > 0) this.hurtcounter -= 0.05;
else if (this.mode == 5) this.mode = 2;
```

}

timeout = 0.05;

}

if (washit && this.mode!=5 && hearts > 0) {

hearts -= playerswordpower/2;

if (hearts <= 0) {

this.mode = 6;

setcharani dead,;

dontblock;

} else {

dx = (x+1.5)-(playerx+1.5);

dy = (y+2)-(playery+2);

dist = (dx^2 + dy^2)^.5;

hurtdx = dx/dist;

hurtdy = dy/dist;

this.mode = 5;

this.freezetimer = this.hurtpause;

this.hurtcounter = this.hurtrecoil;

setcharani hurt,;

if (this.target == -1) FindPlayer();

}

}

function FindPlayer() {

for (i=0;i<playerscount;i++) {

if (players[i].hearts>0 && players[i].id>=0) {

dx = (players[i].x+1.5) - (x+1.5);

dy = (players[i].y+2) - (y+2);

dist = (dx^2 + dy^2)^.5;

checkdir = getdir(dx,dy);

this.agro = this.mode == 5 && this.target == -1;

if (this.agro == 1) {

if (strequals(#m(i),sword2)) {

if (dist < this.sight) this.target = i;

}

} else {

if (dist < this.sight && checkdir == dir) {

this.cansee = 1;

for (j=1;j<((dist < this.sight) ? int(dist) : this.sight);j++) {

if (onwall(x+1.5+(dx/dist)*j+.5,y+2+(dy/dist)*j+.5)) this.cansee = 0;

}

if (this.cansee == 1) {

this.target = i;

this.mode = 2;

break;

}

}

}

}

}

}

function CheckBushes() {

bushtype = -1;

px = int(x+(dir==1? -0.5: (dir==3? 3.5: 1.5)));

py = int(y+(dir==0? 0: (dir==2? 4: 2)));

for (i=0; i<(arraylen(this.bushtiles)-1)/4; i++) {

for (j=0;j<4;j++) {

if (tiles[px,py] == this.bushtiles[(i*4)+j]) {
bushtype = i;
break;
}
}
}
if (bushtype >= 0) {
this.mode = 3;
this.freezetimer = this.swordfreezetime;
for (i=0;i<4;i++) {
if (tiles[px-1+(i%2),py-1+int(i/2)] == this.bushtiles[bushtype*4]) {

px = px-1+(i%2);

py = py-1+int(i/2);

break;

}

}

replacebush = true;

for (i=0;i<4;i++) {

if (tiles[px+i%2,py+int(i/2)] != this.bushtiles[(bushtype

*4)+i]) {*

replacebush = false;

break;

}

}

if (replacebush == true) {

for (i=0;i<4;i++) {

tiles[px+i%2,py+int(i/2)] = this.bushreplace[(bushtype4)+i];

replacebush = false;

break;

}

}

if (replacebush == true) {

for (i=0;i<4;i++) {

tiles[px+i%2,py+int(i/2)] = this.bushreplace[(bushtype

}

putleaps 0,px,py;

updateboard px,py,2,2;

}

}

}

[/php]

I may also be posting more enemies here that function differently from your typical character baddy.

Interesting tidbit: Did you know the custom NPC baddies(placed with the editor) have some sort of makeshift, minimal pathfinding detection? I’ve been playing with them in my test level and they can do a decent job of navigating around obstacles, regardless of where I am. They almost ‘follow’ my path around things. It’s interesting, and I never really noticed it.