#include "ns.h" #include "wh.h" BEGIN_WH_NS static void newguyarrow(short s, PLAYER& plr); static void stand(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; if (sintable[(spr.ang + 512) & 2047] * (plr.x - spr.x) + sintable[spr.ang & 2047] * (plr.y - spr.y) >= 0) if (cansee(spr.x, spr.y, spr.z - (tileHeight(spr.picnum) << 7), spr.sectnum, plr.x, plr.y, plr.z, plr.sector) && plr.invisibletime < 0) { if (plr.shadowtime > 0) { spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); newstatus(i, FLEE); } else newstatus(i, CHASE); } } 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 - (tileHeight(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) == kHitFloor) { spr.ang = (short)((spr.ang + 1024) & 2047); newstatus(i, FLEE); return; } 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); spr.z = zr_florz; 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); } } static void resurect(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag < 0) { newstatus(i, FACE); int j = krand() % 3; switch (j) { case 0: spr.extra = 30; spr.hitag = (short)adjusthp(85); break; case 1: spr.extra = 20; spr.hitag = (short)adjusthp(85); break; case 2: spr.extra = 10; spr.hitag = (short)adjusthp(45); break; case 3: spr.extra = 0; spr.hitag = (short)adjusthp(15); break; } spr.xrepeat = 35; spr.yrepeat = 35; spr.picnum = NEWGUY; } } 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; int movestat = aimove(i); if ((movestat & kHitTypeMask) != kHitFloor && movestat != 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); checksector6(i); } static void search(PLAYER& plr, short i) { aisearch(plr, i, false); checksector6(i); } static void nuked(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang); trailingsmoke(i, false); newstatus((short)i, DIE); } static void pain(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag < 0) { spr.picnum = NEWGUY; spr.ang = (short)plr.ang; newstatus(i, FLEE); } aimove(i); processfluid(i, zr_florhit, false); setsprite(i, spr.x, spr.y, spr.z); } 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 - (tileHeight(spr.picnum) << 7), spr.sectnum); if (cansee && plr.invisibletime < 0) { spr.ang = getangle(plr.x - spr.x, plr.y - spr.y); 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); } static void flee(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; short osectnum = spr.sectnum; int movestat = aimove(i); if ((movestat & kHitTypeMask) != kHitFloor && 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 { if (plr.invisibletime < 0) 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); } 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: case TYPEWATER: spr.z += tileHeight(spr.picnum) << 5; break; } setsprite(i, spr.x, spr.y, spr.z); switch (spr.picnum) { case NEWGUYCAST: case NEWGUYBOW: sprite[i].lotag -= TICSPERFRAME; if (sprite[i].lotag < 0) { if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y, sprite[i].z - (tileHeight(sprite[i].picnum) << 7), sprite[i].sectnum)) newstatus(i, CAST); else newstatus(i, CHASE); } else sprite[i].ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y); break; case NEWGUYMACE: case NEWGUYPUNCH: if (spr.lotag == 31) { 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); break; } } 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 == NEWGUYDEAD) { if (difficulty == 4) newstatus(i, RESURECT); else { kills++; newstatus(i, DEAD); } } } } static void cast(PLAYER& plr, short i) { SPRITE& spr = sprite[i]; spr.lotag -= TICSPERFRAME; if (spr.lotag < 0) { spr.picnum++; spr.lotag = 12; } if (spr.picnum == NEWGUYCAST + 2) { spr.extra--; spr.picnum = NEWGUY; playsound_loc(S_WISP, sprite[i].x, sprite[i].y); skullycastspell(plr, i); newstatus(i, CHASE); } if (spr.picnum == NEWGUYBOW + 2) { spr.extra--; spr.picnum = NEWGUY; playsound_loc(S_PLRWEAPON3, sprite[i].x, sprite[i].y); newguyarrow(i, plr); newstatus(i, CHASE); } checksector6(i); } static void newguyarrow(short s, PLAYER& plr) { int j = insertsprite(sprite[s].sectnum, JAVLIN); if (j == -1) return; SPRITE& spr = sprite[j]; spr.x = sprite[s].x; spr.y = sprite[s].y; spr.z = sprite[s].z - (40 << 8); spr.cstat = 21; spr.picnum = WALLARROW; spr.ang = (short)(((sprite[s].ang + 2048 + 96) - 512) & 2047); spr.xrepeat = 24; spr.yrepeat = 24; spr.clipdist = 32; spr.extra = sprite[s].ang; spr.shade = -15; spr.xvel = (short)((krand() & 256) - 128); spr.yvel = (short)((krand() & 256) - 128); spr.zvel = (short)(((plr.z + (8 << 8) - sprite[s].z) << 7) / ksqrt((plr.x - sprite[s].x) * (plr.x - sprite[s].x) + (plr.y - sprite[s].y) * (plr.y - sprite[s].y))); spr.zvel += ((krand() % 256) - 128); spr.owner = s; spr.lotag = 1024; spr.hitag = 0; spr.pal = 0; } void createNewGuyAI() { //picanm[NEWGUYDIE] = 0; //picanm[NEWGUYDIE + 3] = 0; auto& e = enemy[NEWGUYTYPE]; e.info.Init(35, 35, 1024 + 256, 120, 0, 48, false, 90, 0); e.info.getAttackDist = [](EnemyInfo& e, SPRITE& spr) { int out = e.attackdist; switch (spr.picnum) { case NEWGUY: case NEWGUYMACE: case NEWGUYCAST: case NEWGUYBOW: if (spr.extra > 10) out = 2048 << 1; else out = 1024 + 256; break; case NEWGUYPUNCH: out = 1024 + 256; break; default: out = 512; break; } return out; }; e.info.getHealth = [](EnemyInfo& e, SPRITE& spr) { switch (spr.picnum) { case NEWGUYSTAND: case NEWGUYKNEE: return adjusthp(50); case NEWGUYCAST: return adjusthp(85); case NEWGUYBOW: return adjusthp(85); case NEWGUYMACE: return adjusthp(45); case NEWGUYPUNCH: return adjusthp(15); } return adjusthp(e.health); }; e.stand = stand; e.chase = chase; e.resurect = resurect; e.skirmish = skirmish; e.search = search; e.nuked = nuked; e.pain = pain; e.face = face; e.flee = flee; e.attack = attack; e.die = die; e.cast = cast; } void premapNewGuy(short i) { SPRITE& spr = sprite[i]; spr.detail = NEWGUYTYPE; enemy[NEWGUYTYPE].info.set(spr); switch (spr.picnum) { case NEWGUYSTAND: case NEWGUYKNEE: changespritestat(i, STAND); if (spr.picnum == NEWGUYSTAND) spr.extra = 20; else spr.extra = 30; break; case NEWGUYCAST: case NEWGUYBOW: case NEWGUYMACE: case NEWGUYPUNCH: case NEWGUY: switch (spr.picnum) { case NEWGUYCAST: spr.extra = 30; break; case NEWGUYBOW: spr.extra = 20; break; case NEWGUYMACE: spr.extra = 10; break; case NEWGUYPUNCH: spr.extra = 0; break; } changespritestat(i, FACE); spr.picnum = NEWGUY; } } END_WH_NS