#include "ns.h" #include "wh.h" BEGIN_WH_NS static void checkexpl(PLAYER& plr, short i); static void chase(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag < 0) spr.lotag = 250; short osectnum = spr.sectnum; if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7), spr.sectnum) && plr.invisibletime < 0) { if (checkdist(plr, i)) { if (plr.shadowtime > 0) { spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); newstatus(i, FLEE); } else newstatus(i, ATTACK); } else if (krand() % 63 > 60) { spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047); newstatus(i, FLEE); } else { int movestat = aimove(i); if ((movestat & kHitTypeMask) == kHitSprite) { if ((movestat & kHitIndexMask) != plr.spritenum) { short daang = (short)((spr.ang - 256) & 2047); spr.ang = daang; if (plr.shadowtime > 0) { spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); newstatus(i, FLEE); } else newstatus(i, SKIRMISH); } else { spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); newstatus(i, SKIRMISH); } } } } else { spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); newstatus(i, FLEE); } getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0); if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10)) warpsprite(i); if (checksector6(i)) return; processfluid(i, zr_florhit, false); if (sector[osectnum].lotag == KILLSECTOR) { spr.hitag--; if (spr.hitag < 0) newstatus(i, DIE); } setsprite(i, spr.x, spr.y, spr.z); if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA || sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) { spr.hitag--; if (spr.hitag < 0) newstatus(i, DIE); } checkexpl(plr, i); } static void skirmish(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag < 0) newstatus(i, FACE); short osectnum = spr.sectnum; if (aimove(i) != 0) { spr.ang = getangle(plr.x - spr.x, plr.y - spr.y); newstatus(i, FACE); } if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10)) warpsprite(i); processfluid(i, zr_florhit, false); setsprite(i, spr.x, spr.y, spr.z); if (checksector6(i)) return; checkexpl(plr, i); } static void die(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag <= 0) { spr.picnum++; spr.lotag = 20; if (spr.picnum == FREDDEAD) { if (difficulty == 4) newstatus(i, RESURECT); else { kills++; newstatus(i, DEAD); } } } } static void search(PLAYER& plr, short i) { aisearch(plr, i, false); if (!checksector6(i)) checkexpl(plr, i); } static void frozen(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag < 0) { spr.pal = 0; spr.picnum = FRED; newstatus(i, FACE); } } static void face(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7), spr.sectnum); if (cansee && plr.invisibletime < 0) { spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047); if (plr.shadowtime > 0) { spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); newstatus(i, FLEE); } else { spr.owner = plr.spritenum; newstatus(i, CHASE); } } else { // get off the wall if (spr.owner == plr.spritenum) { spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047); newstatus(i, FINDME); } else if (cansee) newstatus(i, FLEE); } if (checkdist(plr, i)) newstatus(i, ATTACK); checkexpl(plr, i); } static void attack(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0); spr.z = zr_florz; switch (checkfluid(i, zr_florhit)) { case TYPELAVA: sprite[i].hitag--; if (sprite[i].hitag < 0) newstatus(i, DIE); case TYPEWATER: spr.z += tilesizy[spr.picnum] << 5; break; } setsprite(i, spr.x, spr.y, spr.z); if (spr.lotag >= 64) { if (checksight(plr, i)) if (checkdist(plr, i)) { spr.ang = (short)checksight_ang; attack(plr, i); } } else if (spr.lotag < 0) { if (plr.shadowtime > 0) { spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW newstatus(i, FLEE); } else newstatus(i, CHASE); } spr.lotag -= TICSPERFRAME; checksector6(i); } static void flee(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; short osectnum = spr.sectnum; int movestat = aimove(i); if (movestat != 0) { if ((movestat & kHitTypeMask) == kHitWall) { int nWall = movestat & kHitIndexMask; int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4; int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4; spr.ang = getangle(nx, ny); } else { spr.ang = getangle(plr.x - spr.x, plr.y - spr.y); newstatus(i, FACE); } } if (spr.lotag < 0) newstatus(i, FACE); if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10)) warpsprite(i); if (checksector6(i)) return; processfluid(i, zr_florhit, false); setsprite(i, spr.x, spr.y, spr.z); checkexpl(plr, i); } static void pain(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag < 0) { spr.picnum = FRED; spr.ang = (short)plr.ang; newstatus(i, FLEE); } aimove(i); processfluid(i, zr_florhit, false); setsprite(i, spr.x, spr.y, spr.z); checkexpl(plr, i); } static void resurect(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag < 0) { newstatus(i, FACE); spr.picnum = FRED; spr.hitag = (short)adjusthp(40); spr.lotag = 100; spr.cstat |= 1; } } static void checkexpl(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; short j = headspritesect[spr.sectnum]; while (j != -1) { short nextj = nextspritesect[j]; long dx = klabs(spr.x - sprite[j].x); // x distance to sprite long dy = klabs(spr.y - sprite[j].y); // y distance to sprite long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) { if (sprite[j].picnum == EXPLO2 || sprite[j].picnum == SMOKEFX || sprite[j].picnum == MONSTERBALL) { spr.hitag -= TICSPERFRAME << 2; if (spr.hitag < 0) { newstatus(i, DIE); } } } j = nextj; } } void createFredAI() { auto &e = enemy[FREDTYPE]; e.info.Init(48, 48, 1024 + 256, 120, 0, 64, false, 40, 0); e.chase = chase; e.skirmish = skirmish; e.die = die; e.search = search; e.frozen = frozen; e.face = face; e.attack = attack; e.flee = flee; e.pain = pain; e.resurect = resurect; } void premapFred(short i) { SPRITE& spr = sprite[i]; if (spr.picnum == FRED && spr.pal == 1) { deletesprite(i); return; } spr.detail = FREDTYPE; changespritestat(i, FACE); enemy[FREDTYPE].info.set(spr); if (krand() % 100 > 50) spr.extra = 1; } END_WH_NS