/**************************************************************************/ /* */ /* */ /* Raven 3D Engine */ /* Copyright (C) 1996 by Softdisk Publishing */ /* */ /* Original Design: */ /* John Carmack of id Software */ /* */ /* Enhancements by: */ /* Robert Morgan of Channel 7............................Main Engine Code */ /* Todd Lewis of Softdisk Publishing......Tools,Utilities,Special Effects */ /* John Bianca of Softdisk Publishing..............Low-level Optimization */ /* Carlos Hasan..........................................Music/Sound Code */ /* */ /* */ /***************************************************************************/ #include #include #include #include #include #include "d_disk.h" #include "d_global.h" #include "r_refdef.h" #include "d_ints.h" #include "protos.h" #include "d_misc.h" /**** VARIABLES ****/ scaleobj_t *msprite, probe; boolean spritehit, playerhit; fixed_t hitx, hity, targx, targy, targz; int spriteloc; // where did it hit on a sprite /**** FUNCTIONS ****/ boolean SP_TryDoor (fixed_t xcenter, fixed_t ycenter) { int xl, yl, xh, yh, x, y; doorobj_t *door_p, *last_p; if (msprite==&probe) return true; // These values will probably have to be tweaked for doors that are along // the vertical opposite axis (northwall) xl = (int)((xcenter-msprite->movesize) >> FRACTILESHIFT); yl = (int)((ycenter-msprite->movesize/* - (TILEUNIT >> 1)*/) >> FRACTILESHIFT); xh = (int)((xcenter+msprite->movesize) >> FRACTILESHIFT); yh = (int)((ycenter+msprite->movesize/* - (TILEUNIT >> 1)*/) >> FRACTILESHIFT); // check for doors on the north wall for (y=yl+1;y<=yh;y++) for (x=xl;x<=xh;x++) { if (mapflags[y*MAPSIZE+x] & FL_DOOR) // if tile has a door { last_p=&doorlist[numdoors]; for (door_p=doorlist;door_p!=last_p;door_p++) if (door_p->tilex==x && door_p->tiley==y && (door_p->orientation==dr_horizontal || door_p->orientation==dr_horizontal2)) { if (door_p->doorOpen && !door_p->doorClosing) return true; // can move, door is open else if (!door_p->doorOpen && door_p->doorBumpable && !door_p->doorOpening) { door_p->doorOpening=true; door_p->doorClosing=false; SoundEffect(SN_DOOR,15,door_p->tilex<tiley<doorTimer+=20; if (door_p->orientation==dr_horizontal) SP_TryDoor(xcenter+64*FRACUNIT,ycenter); else SP_TryDoor(xcenter-64*FRACUNIT,ycenter); return false; } else if (!door_p->doorOpen && door_p->doorBumpable && door_p->doorClosing) { door_p->doorClosing=false; door_p->doorOpening=true; SoundEffect(SN_DOOR,15,door_p->tilex<tiley<doorTimer+=20; if (door_p->orientation==dr_horizontal) SP_TryDoor(xcenter+64*FRACUNIT,ycenter); else SP_TryDoor(xcenter-64*FRACUNIT,ycenter); return false; } else return false; } } } // check for doors on the west wall xl = (int)((xcenter-msprite->movesize/* - (TILEUNIT >> 1)*/) >> FRACTILESHIFT); yl = (int)((ycenter-msprite->movesize) >> FRACTILESHIFT); xh = (int)((xcenter+msprite->movesize/* - (TILEUNIT >> 1)*/) >> FRACTILESHIFT); yh = (int)((ycenter+msprite->movesize) >> FRACTILESHIFT); for (y=yl;y<=yh;y++) for (x=xl+1;x<=xh;x++) { if (mapflags[y*MAPSIZE+x] & FL_DOOR) // if tile has a door { last_p=&doorlist[numdoors]; for (door_p=doorlist; door_p != last_p; door_p++) if (door_p->tilex==x && door_p->tiley==y && (door_p->orientation==dr_vertical || door_p->orientation==dr_vertical2)) { if (door_p->doorOpen && !door_p->doorClosing) return true; // can move, door is open else if (!door_p->doorOpen && door_p->doorBumpable && !door_p->doorOpening) { door_p->doorOpening=true; door_p->doorClosing=false; SoundEffect(SN_DOOR,15,door_p->tilex<tiley<doorTimer+=20; if (door_p->orientation==dr_vertical) SP_TryDoor(xcenter,ycenter+64*FRACUNIT); else SP_TryDoor(xcenter,ycenter-64*FRACUNIT); return false; } else if (!door_p->doorOpen && door_p->doorBumpable && door_p->doorClosing) { door_p->doorClosing=false; door_p->doorOpening=true; SoundEffect(SN_DOOR,15,door_p->tilex<tiley<doorTimer+=20; if (door_p->orientation==dr_vertical) SP_TryDoor(xcenter,ycenter+64*FRACUNIT); else SP_TryDoor(xcenter,ycenter-64*FRACUNIT); return false; } else return false; } } } return true; } int SP_TryMove(fixed_t xcenter, fixed_t ycenter) { int xl, yl, xh, yh, x, y, mapspot; xl = (int)((xcenter-msprite->movesize) >> FRACTILESHIFT); yl = (int)((ycenter-msprite->movesize) >> FRACTILESHIFT); xh = (int)((xcenter+msprite->movesize) >> FRACTILESHIFT); yh = (int)((ycenter+msprite->movesize) >> FRACTILESHIFT); for (y=yl;y<=yh;y++) for (x=xl;x<=xh;x++) { mapspot=MAPCOLS*y+x; if ((y>yl && northwall[mapspot] && !(northflags[mapspot] & F_NOCLIP) && !(northflags[mapspot] & F_NOBULLETCLIP)) || (x>xl && westwall[mapspot] && !(westflags[mapspot] & F_NOCLIP) && !(westflags[mapspot] & F_NOBULLETCLIP))) return 2; // wall hit if (msprite!=&probe) { if (msprite->zz>RF_GetCeilingZ((x<0 && mapsprites[mapspot]<128 && mapspot!=msprite->startspot) { spritehit=true; spriteloc=mapspot; return 1; } if (mapspot==player.mapspot && mapspot!=msprite->startspot && msprite->spawnid!=playernum) // can't shot yourself { playerhit=true; return 1; } } return 0; } byte SP_ClipMove(fixed_t xmove,fixed_t ymove,fixed_t zmove) { int result; fixed_t dx, dy; dx=msprite->x+xmove; dy=msprite->y+ymove; spritehit=false; result=SP_TryMove(dx,dy); if (result) { hitx=dx; hity=dy; } if (result!=2 && !SP_TryDoor(dx,dy)) result=2; // door hit or wall hit if (result!=2) { msprite->x+=xmove; msprite->y+=ymove; msprite->z+=zmove; } return result; } byte SP_Thrust() { msprite->angle&=ANGLES; msprite->angle2&=ANGLES; return SP_ClipMove(costable[msprite->angle],-sintable[msprite->angle],sintable[msprite->angle2]); } boolean SP_TryMove2(int angle,fixed_t xcenter, fixed_t ycenter,int smapspot) { int xl, yl, xh, yh, x, y, mapspot; fixed_t sz, sz2, floorz, ceilingz; if (angleSOUTH) { xl=xcenter>>FRACTILESHIFT; xh=(xcenter+msprite->movesize) >> FRACTILESHIFT; } else if (angle>NORTH && angle>FRACTILESHIFT; xl=(xcenter-msprite->movesize) >> FRACTILESHIFT; } else { xl=(xcenter-msprite->movesize) >> FRACTILESHIFT; xh=(xcenter+msprite->movesize) >> FRACTILESHIFT; } if (angle>WEST) { yl=ycenter>>FRACTILESHIFT; yh=(ycenter+msprite->movesize) >> FRACTILESHIFT; } else if (anglemovesize) >> FRACTILESHIFT; yh=ycenter>>FRACTILESHIFT; } else { yl=(ycenter-msprite->movesize) >> FRACTILESHIFT; yh=(ycenter+msprite->movesize) >> FRACTILESHIFT; } sz = msprite->z - msprite->zadj + (20<z - msprite->zadj; for (y=yl;y<=yh;y++) for (x=xl;x<=xh;x++) { mapspot=MAPCOLS*y+x; if (mapspot==player.mapspot || (y>yl && northwall[mapspot] && !(northflags[mapspot] & F_NOCLIP)) || (x>xl && westwall[mapspot] && !(westflags[mapspot] & F_NOCLIP))) return false; // wall hit floorz=RF_GetFloorZ((x<sz) return false; if (msprite->nofalling && floorz+(5<z+msprite->height) return false; if (ceilingz-floorzheight) return false; if (mapspot!=smapspot && mapsprites[mapspot]) return false; } return true; } byte SP_ClipMove2(fixed_t xmove, fixed_t ymove) { fixed_t dx, dy; int smapspot, angle2, ms; if (msprite->type==S_CLONE) ms=SM_CLONE; else ms=1; dx=msprite->x+xmove; dy=msprite->y+ymove; smapspot=(msprite->y>>FRACTILESHIFT)*MAPCOLS+(msprite->x>>FRACTILESHIFT); if (SP_TryMove2(msprite->angle,dx,dy,smapspot) && SP_TryDoor(dx,dy)) { if (floorpic[(dy>>FRACTILESHIFT)*MAPCOLS+(dx>>FRACTILESHIFT)]==0) return 0; mapsprites[smapspot]=0; msprite->x+=xmove; msprite->y+=ymove; mapsprites[(msprite->y>>FRACTILESHIFT)*MAPCOLS+(msprite->x>>FRACTILESHIFT)]=ms; return 1; } // the move goes into a wall, so try and move along one axis if (xmove>0) { angle2=EAST; dx=msprite->x+msprite->moveSpeed; } else { angle2=WEST; dx=msprite->x-msprite->moveSpeed; } if (SP_TryMove2(angle2,dx,msprite->y,smapspot) && SP_TryDoor(dx,msprite->y)) { if (floorpic[(msprite->y>>FRACTILESHIFT)*MAPCOLS+(dx>>FRACTILESHIFT)]==0) return 0; mapsprites[smapspot]=0; msprite->x+=xmove; mapsprites[(msprite->y>>FRACTILESHIFT)*MAPCOLS+(msprite->x>>FRACTILESHIFT)]=ms; return 2; } if (ymove>0) { angle2=SOUTH; dy=msprite->y+msprite->moveSpeed; } else { angle2=NORTH; dy=msprite->y-msprite->moveSpeed; } if (SP_TryMove2(angle2,msprite->x,dy,smapspot) && SP_TryDoor(msprite->x,dy)) { if (floorpic[(dy>>FRACTILESHIFT)*MAPCOLS+(msprite->x>>FRACTILESHIFT)]==0) return 0; mapsprites[smapspot]=0; msprite->y+=ymove; mapsprites[(msprite->y>>FRACTILESHIFT)*MAPCOLS+(msprite->x>>FRACTILESHIFT)]=ms; return 3; } return 0; } byte SP_Thrust2() { fixed_t xmove, ymove; msprite->angle&=ANGLES; xmove=FIXEDMUL(msprite->moveSpeed,costable[msprite->angle]); ymove=-FIXEDMUL(msprite->moveSpeed,sintable[msprite->angle]); return SP_ClipMove2(xmove,ymove); } void ActivationSound(scaleobj_t *sp) { switch (sp->type) { case S_MONSTER1: SoundEffect(SN_MON1_WAKE,7,sp->x,sp->y); break; case S_MONSTER2: SoundEffect(SN_MON2_WAKE,7,sp->x,sp->y); break; case S_MONSTER3: SoundEffect(SN_MON3_WAKE,7,sp->x,sp->y); break; case S_MONSTER4: SoundEffect(SN_MON4_WAKE,7,sp->x,sp->y); break; case S_MONSTER5: SoundEffect(SN_MON5_WAKE,7,sp->x,sp->y); break; case S_MONSTER6: SoundEffect(SN_MON6_WAKE,7,sp->x,sp->y); break; case S_MONSTER7: SoundEffect(SN_MON7_WAKE,7,sp->x,sp->y); break; case S_MONSTER8: SoundEffect(SN_MON8_WAKE,7,sp->x,sp->y); break; case S_MONSTER9: SoundEffect(SN_MON9_WAKE,7,sp->x,sp->y); break; case S_MONSTER10: SoundEffect(SN_MON10_WAKE,7,sp->x,sp->y); break; case S_MONSTER11: SoundEffect(SN_MON11_WAKE,7,sp->x,sp->y); break; case S_MONSTER12: SoundEffect(SN_MON12_WAKE,7,sp->x,sp->y); break; case S_MONSTER13: SoundEffect(SN_MON13_WAKE,7,sp->x,sp->y); break; case S_MONSTER14: SoundEffect(SN_MON14_WAKE,7,sp->x,sp->y); break; case S_MONSTER15: SoundEffect(SN_MON15_WAKE,7,sp->x,sp->y); break; } } void ActivateSprites(int sx,int sy) /* proximity activation (recursive chain reaction) */ { scaleobj_t *sp; int x, y; for(sp=firstscaleobj.next;sp!=&lastscaleobj;sp=sp->next) if (sp->active==false && sp->moveSpeed) { x=sp->x>>FRACTILESHIFT; y=sp->y>>FRACTILESHIFT; if (abs(x-sx)<5 && abs(y-sy)<5) { sp->active=true; sp->actiontime=timecount+40; ActivationSound(sp); ActivationSound(sp); ActivateSprites(x,y); } } } void ShowWallPuff() { int i; switch (msprite->type) { case S_BULLET3: case S_BULLET12: case S_BULLET17: case S_MONSTERBULLET2: case S_MONSTERBULLET4: case S_MONSTERBULLET6: case S_MONSTERBULLET8: case S_GRENADEBULLET: i=S_SMALLEXPLODE; break; case S_BULLET4: case S_MONSTERBULLET5: case S_MONSTERBULLET11: i=S_PLASMAWALLPUFF; break; case S_HANDBULLET: case S_BLOODSPLAT: case S_BULLET7: case S_MONSTERBULLET7: case S_MONSTERBULLET10: case S_MONSTERBULLET12: case S_MONSTERBULLET15: case S_SOULBULLET: return; case S_BULLET9: i=S_ARROWPUFF; break; case S_BULLET10: case S_BULLET18: i=S_GREENPUFF; break; case S_MINEBULLET: i=S_MINEPUFF; break; default: i=S_WALLPUFF; } SpawnSprite(i,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); ActivateSprites(msprite->x>>FRACTILESHIFT,msprite->y>>FRACTILESHIFT); } void HitSprite(scaleobj_t *sp) { switch (sp->type) { case S_CLONE: if (!sp->active) { ActivateSprites((int)(sp->x>>FRACTILESHIFT),(int)(sp->y>>FRACTILESHIFT)); sp->active=true; } sp->modetime=timecount+8; sp->basepic=sp->startpic+32; SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); if (msprite->type!=S_BULLET17) { SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); } break; case S_MONSTER1: case S_MONSTER2: case S_MONSTER7: case S_MONSTER9: case S_MONSTER10: case S_MONSTER12: case S_MONSTER13: case S_MONSTER14: case S_MONSTER15: if (!sp->active) { ActivateSprites((int)(sp->x>>FRACTILESHIFT),(int)(sp->y>>FRACTILESHIFT)); sp->active=true; } sp->modetime=timecount+8; sp->basepic=sp->startpic+40; SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); if (msprite->type!=S_BULLET17) { SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); } break; case S_MONSTER3: case S_MONSTER4: case S_MONSTER5: case S_MONSTER6: case S_MONSTER8: case S_MONSTER11: ShowWallPuff(); break; } } boolean Int0(void) /* control of bullets, explosions, and other objects (not monsters!!) */ { scaleobj_t *hsprite, *sp; int counter, mapspot, result, angle, angleinc, i, oldfall; int oldangle, oldmovespeed; boolean killed, blood; counter=0; killed=false; if (msprite->type==S_GRENADE) msprite->angle2-=4; else if ((msprite->type==S_BLOODSPLAT || msprite->type==S_METALPARTS) && (msprite->angle2angle2>SOUTH)) msprite->angle2-=32; if (msprite->maxmove) { --msprite->maxmove; if (msprite->maxmove<=0) { ShowWallPuff(); return true; } } if (msprite->type==S_MONSTERBULLET4 || msprite->type==S_MONSTERBULLET6 || msprite->type==S_BULLET17) SpawnSprite(S_WALLPUFF,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); blood=false; while (counter++moveSpeed) { result=SP_Thrust(); if (msprite->type==S_BULLET3) msprite->z=RF_GetFloorZ(msprite->x,msprite->y)+(20<type==S_BLOODSPLAT) { if (result==2) return true; spritehit=false; playerhit=false; } else if (msprite->type==S_METALPARTS && result==2) { playerhit=false; return true; } if (spritehit) { if (mapsprites[spriteloc]==SM_NETPLAYER) { for(hsprite=firstscaleobj.next;hsprite!=&lastscaleobj;hsprite=hsprite->next) if (hsprite!=msprite) { mapspot=(hsprite->y>>FRACTILESHIFT)*MAPCOLS+(hsprite->x>>FRACTILESHIFT); if (mapspot==spriteloc) { if (msprite->zz || msprite->z>hsprite->z+hsprite->height || hsprite->type!=S_NETPLAYER) break; { SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); // if (msprite->type!=S_BULLET17) // { SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); SpawnSprite(S_BLOODSPLAT,msprite->x,msprite->y,msprite->z,msprite->zadj,0,0,false,0); blood=true; killed=true; // } } } } } else for(hsprite=firstscaleobj.next;hsprite!=&lastscaleobj;hsprite=hsprite->next) if (hsprite!=msprite) { mapspot=(hsprite->y>>FRACTILESHIFT)*MAPCOLS+(hsprite->x>>FRACTILESHIFT); if (mapspot==spriteloc) { if (msprite->zz || msprite->z>hsprite->z+hsprite->height) continue; if (hsprite->hitpoints) { if (hsprite->type!=S_MONSTER5) hsprite->actiontime+=15; else hsprite->actiontime+=5; hsprite->hitpoints-=msprite->damage; if (msprite->spawnid==255) hsprite->enraged++; if (msprite->type==S_SOULBULLET && msprite->spawnid==playernum) { heal(msprite->damage/2); medpaks(msprite->damage/2); } killed=true; if (hsprite->hitpoints<=0) { if (msprite->spawnid==playernum || msprite->spawnid-200==playernum) { ++player.bodycount; addscore(hsprite->score); } mapsprites[spriteloc]=0; blood=true; HitSprite(hsprite); KillSprite(hsprite,msprite->type); } else if (msprite->damage) { oldangle=hsprite->angle; oldmovespeed=hsprite->moveSpeed; hsprite->angle=msprite->angle; hsprite->moveSpeed=(msprite->damage>>2)<nofalling; msprite->nofalling=0; SP_Thrust2(); msprite->nofalling=oldfall; msprite=sp; hsprite->angle=oldangle; hsprite->moveSpeed=oldmovespeed; blood=true; HitSprite(hsprite); } break; } } } } else if (playerhit && msprite->z>player.z-player.height && msprite->zdamage); if (player.angst==0 && netmode) NetDeath(msprite->spawnid); } Thrust(msprite->angle,msprite->damage<<(FRACBITS-3)); playerhit=false; killed=true; if (msprite->damage>50) { player.angle+=-15+(MS_RndT()&31); player.angle&=ANGLES; } } if (result==2) killed=true; if (killed) { if (!blood) ShowWallPuff(); break; } } } if (killed && msprite->type==S_GRENADE) { angleinc=ANGLES/12; angle=0; for(i=0,angle=0;i<12;i++,angle+=angleinc) { sp=SpawnSprite(S_GRENADEBULLET,msprite->x,msprite->y,msprite->z,20<spawnid); sp->maxmove=3; sp->startspot=-1; } angleinc=ANGLES/8; angle=0; for(i=0,angle=0;i<8;i++,angle+=angleinc) { sp=SpawnSprite(S_GRENADEBULLET,msprite->x,msprite->y,msprite->z,20<spawnid); sp->maxmove=2; sp->startspot=-1; } angleinc=ANGLES/8; angle=0; for(i=0,angle=0;i<8;i++,angle+=angleinc) { sp=SpawnSprite(S_GRENADEBULLET,msprite->x,msprite->y,msprite->z,20<spawnid); sp->maxmove=2; sp->startspot=-1; } sp=SpawnSprite(S_EXPLODE,msprite->x,msprite->y,msprite->z,0,0,0,true,255); SoundEffect(SN_EXPLODE1+(MS_RndT()&1),15,msprite->x,msprite->y); } else if (killed && msprite->type==S_BULLET17) { angleinc=ANGLES/8; angle=0; for(i=0,angle=0;i<8;i++,angle+=angleinc) { sp=SpawnSprite(S_GRENADEBULLET,msprite->x,msprite->y,msprite->z,20<spawnid); sp->maxmove=3; sp->startspot=-1; } angleinc=ANGLES/6; angle=0; for(i=0,angle=0;i<6;i++,angle+=angleinc) { sp=SpawnSprite(S_GRENADEBULLET,msprite->x,msprite->y,msprite->z,20<spawnid); sp->maxmove=2; sp->startspot=-1; } angleinc=ANGLES/6; angle=0; for(i=0,angle=0;i<6;i++,angle+=angleinc) { sp=SpawnSprite(S_GRENADEBULLET,msprite->x,msprite->y,msprite->z,20<spawnid); sp->maxmove=2; sp->startspot=-1; } sp=SpawnSprite(S_EXPLODE,msprite->x,msprite->y,msprite->z,0,0,0,true,255); SoundEffect(SN_EXPLODE1+(MS_RndT()&1),15,msprite->x,msprite->y); } return killed; } /***************************************************************************/ int ScanX(int limit1, int x1, int y1, int x2, int y2,int *tx,int *ty) /* check for the player along the x axis */ { int mapspot, wall, x, limit, flags; mapspot=y1*MAPCOLS+x1+1; x=x1; limit=limit1; while (1) { if (mapsprites[mapspot]==SM_NETPLAYER || mapsprites[mapspot]==SM_CLONE || (x==x2 && y1==y2)) { *tx=x+1; return 2; } if (msprite->enraged>=6-player.difficulty && mapsprites[mapspot]==1) { *tx=x+1; *ty=y1; return 2; } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; wall=westwall[mapspot]; flags=westflags[mapspot]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; ++mapspot; ++x; --limit; if (!limit) break; } limit=limit1; mapspot=y1*MAPCOLS+x1-1; x=x1; while (1) { if (mapsprites[mapspot]==SM_NETPLAYER || mapsprites[mapspot]==SM_CLONE || (x==x2 && y1==y2)) { *tx=x-1; return 2; } if (msprite->enraged>=6-player.difficulty && mapsprites[mapspot]==1) { *tx=x-1; *ty=y1; return 2; } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) return 1; wall=westwall[mapspot+1]; flags=westflags[mapspot+1]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) return 0; --mapspot; --x; --limit; if (!limit) break; } return 0; } int ScanY(int limit1, int x1, int y1, int x2, int y2,int *tx,int *ty) /* check for the player along the y axis */ { int mapspot, wall, y, limit, flags; limit=limit1; mapspot=y1*MAPCOLS+x1+MAPCOLS; y=y1; while (1) { if (mapsprites[mapspot]==SM_NETPLAYER || mapsprites[mapspot]==SM_CLONE || (y==y2 && x1==x2)) { *ty=y+1; return 2; } if (msprite->enraged>=6-player.difficulty && mapsprites[mapspot]==1) { *tx=x1; *ty=y+1; return 2; } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; wall=northwall[mapspot]; flags=northflags[mapspot]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; mapspot+=MAPCOLS; ++y; --limit; if (!limit) break; } limit=limit1; mapspot=y1*MAPCOLS+x1-MAPCOLS; y=y1; while (1) { if (mapsprites[mapspot]==SM_NETPLAYER || mapsprites[mapspot]==SM_CLONE || (y==y2 && x1==x2)) { *ty=y-1; return 2; } if (msprite->enraged>=6-player.difficulty && mapsprites[mapspot]==1) { *tx=x1; *ty=y-1; return 2; } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; wall=northwall[mapspot+MAPCOLS]; flags=northflags[mapspot+MAPCOLS]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; mapspot-=MAPCOLS; --y; --limit; if (!limit) break; } return 0; } int ScanAngle(int limit1, int x1, int y1, int x2, int y2,int *tx,int *ty) /* scan for the player along a 45 degree angle this is not very accurate!! approximate only */ { int mapspot, wall, x, y, limit, flags; limit=limit1; mapspot=y1*MAPCOLS+x1+MAPCOLS+1; y=y1; x=x1; while (1) { wall=northwall[mapspot-1]; flags=northflags[mapspot-1]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; wall=westwall[mapspot-MAPCOLS]; flags=westflags[mapspot-MAPCOLS]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) return 0; if (mapsprites[mapspot]==SM_NETPLAYER || mapsprites[mapspot]==SM_CLONE || (y==y2 && x==x2)) { *tx=x+1; *ty=y+1; return 2; } if (msprite->enraged>=6-player.difficulty && mapsprites[mapspot]==1) { *tx=x+1; *ty=y+1; return 2; } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; mapspot+=MAPCOLS+1; ++y; ++x; --limit; if (!limit) break; } limit=limit1; mapspot=y1*MAPCOLS+x1+MAPCOLS-1; y=y1; x=x1; while (1) { wall=northwall[mapspot+1]; flags=northflags[mapspot+1]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; wall=westwall[mapspot-MAPCOLS]; flags=westflags[mapspot-MAPCOLS]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) return 0; if (mapsprites[mapspot]==SM_NETPLAYER || mapsprites[mapspot]==SM_CLONE || (y==y2 && x==x2)) { *tx=x-1; *ty=y+1; return 2; } if (msprite->enraged>=6-player.difficulty && mapsprites[mapspot]==1) { *tx=x-1; *ty=y+1; return 2; } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; mapspot+=MAPCOLS-1; ++y; --x; --limit; if (!limit) break; } limit=limit1; mapspot=y1*MAPCOLS+x1-MAPCOLS+1; y=y1; x=x1; while (1) { wall=northwall[mapspot-1+MAPCOLS]; flags=northflags[mapspot-1+MAPCOLS]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; wall=westwall[mapspot-MAPCOLS]; flags=westflags[mapspot-MAPCOLS]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) return 0; if (mapsprites[mapspot]==SM_NETPLAYER || mapsprites[mapspot]==SM_CLONE || (y==y2 && x==x2)) { *tx=x+1; *ty=y-1; return 2; } if (msprite->enraged>=6-player.difficulty && mapsprites[mapspot]==1) { *tx=x+1; *ty=y-1; return 2; } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; mapspot-=MAPCOLS+1; --y; ++x; --limit; if (!limit) break; } limit=limit1; mapspot=y1*MAPCOLS+x1-MAPCOLS-1; y=y1; x=x1; while (1) { wall=northwall[mapspot+1+MAPCOLS]; flags=northflags[mapspot+1+MAPCOLS]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; wall=westwall[mapspot-MAPCOLS]; flags=westflags[mapspot-MAPCOLS]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) return 0; if (mapsprites[mapspot]==SM_NETPLAYER || mapsprites[mapspot]==SM_CLONE || (y==y2 && x==x2)) { *tx=x-1; *ty=y-1; return 2; } if (msprite->enraged>=6-player.difficulty && mapsprites[mapspot]==1) { *tx=x-1; *ty=y-1; return 2; } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; mapspot-=MAPCOLS-1; --y; --x; --limit; if (!limit) break; } return 0; } /***************************************************************************/ int GetFireAngle(fixed_t sz,int x1,int y1,fixed_t px,fixed_t py,fixed_t pz) { scaleobj_t *hsprite; int x, y, z, d, spriteloc, mapspot; boolean found; sz+=msprite->z; if (x1!=px>>FRACTILESHIFT || y1!=py>>FRACTILESHIFT) { spriteloc=y1*MAPCOLS+x1; found=false; for(hsprite=firstscaleobj.next;hsprite!=&lastscaleobj;hsprite=hsprite->next) if (hsprite->hitpoints) { mapspot=(hsprite->y>>FRACTILESHIFT)*MAPCOLS+(hsprite->x>>FRACTILESHIFT); if (mapspot==spriteloc) { found=true; break; } } if (found) { px=hsprite->x; py=hsprite->y; pz=hsprite->z+(32<pz) { z=(sz-pz)>>(FRACBITS+2); if (z>=MAXAUTO) return 0; x=(msprite->x-px)>>(FRACBITS+2); y=(msprite->y-py)>>(FRACBITS+2); d=sqrt(x*x + y*y); if (d>=MAXAUTO || autoangle2[d][z]==-1) return 0; return -autoangle2[d][z]; } else if (sz>(FRACBITS+2); if (z>=MAXAUTO) return 0; x=(msprite->x-px)>>(FRACBITS+2); y=(msprite->y-py)>>(FRACBITS+2); d=sqrt(x*x + y*y); if (d>=MAXAUTO || autoangle2[d][z]==-1) return 0; return autoangle2[d][z]; } else return 0; } /***************************************************************************/ void Int5(void) // priests / viscount lords { int angle, sx, sy, px, py, tx, ty, pangle; fixed_t floorz, oldspeed, fheight; sx=msprite->x>>FRACTILESHIFT; sy=msprite->y>>FRACTILESHIFT; if (netmode) NetGetClosestPlayer(sx,sy); else { if (specialeffect==SE_INVISIBILITY) { targx=0; targy=0; targz=0; } else { targx=player.x; targy=player.y; targz=player.z; } } px=targx>>FRACTILESHIFT; py=targy>>FRACTILESHIFT; oldspeed=msprite->moveSpeed; if (abs(px-sx)<6 && abs(py-sy)<6) msprite->moveSpeed=msprite->moveSpeed*2; if (timecount>msprite->movetime) { if (px>sx) angle=EAST; else if (pxsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } angle=angle - DEGREE45 + MS_RndT(); msprite->angle=angle&ANGLES; msprite->movetime=timecount+140; // 350 } if (timecount>msprite->firetime && timecount>msprite->scantime) { tx=px; ty=py; if (ScanX(10,sx,sy,px,py,&tx,&ty)>1 || ScanY(10,sx,sy,px,py,&tx,&ty)>1 || ScanAngle(10,sx,sy,px,py,&tx,&ty)>1) { if (tx>sx) angle=EAST; else if (txsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } msprite->angle=angle&ANGLES; msprite->basepic=msprite->startpic+24; msprite->movemode=4; msprite->firetime=timecount+(40+5*player.difficulty); msprite->actiontime=timecount+30; msprite->modetime=timecount+15; } msprite->scantime=timecount+30; } if (timecount>msprite->modetime) { msprite->modetime=timecount+10; switch (msprite->movemode) { case 0: // left case 1: // mid if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { ++msprite->movemode; msprite->basepic=msprite->startpic+msprite->movemode*8; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 2: // right if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->basepic=msprite->startpic + 8; // midstep ++msprite->movemode; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 3: // mid #2 if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->movemode=0; msprite->basepic=msprite->startpic; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 4: // fire #1 tx=px; ty=py; if (ScanX(10,sx,sy,px,py,&tx,&ty)>1 || ScanY(10,sx,sy,px,py,&tx,&ty)>1 || ScanAngle(10,sx,sy,px,py,&tx,&ty)>1) { if (tx>sx) angle=EAST; else if (txsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } msprite->angle=angle&ANGLES; msprite->movemode=5; msprite->basepic=msprite->startpic+32; if (msprite->type==S_MONSTER7) fheight=15<bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31),pangle,true,255); msprite->modetime+=8; } else { msprite->movemode=0; msprite->basepic=msprite->startpic; } break; case 5: // fire #2 msprite->movemode=0; msprite->basepic=msprite->startpic; break; } } if (timecount>msprite->actiontime && SP_Thrust2()!=1) { angle=msprite->angle+DEGREE45; msprite->angle=angle&ANGLES; } floorz=RF_GetFloorZ(msprite->x,msprite->y); if (floorz+msprite->zadjz) msprite->z-=FRACUNIT<<4; if (floorz+msprite->zadj>msprite->z) msprite->z=floorz+msprite->zadj; msprite->moveSpeed=oldspeed; if (MS_RndT()>=255) ActivationSound(msprite); } /***************************************************************************/ boolean Int6() // intelligence for mines { scaleobj_t *sp; int i, j, angle,angleinc, x, y, sx, sy; boolean activate; if (timecount>msprite->actiontime) // now active { if (msprite->type==S_TIMEMINE) { angleinc=ANGLES/20; angle=0; for(i=0,angle=0;i<20;i++,angle+=angleinc) sp=SpawnSprite(S_MINEBULLET,msprite->x,msprite->y,msprite->z,20<spawnid); sp=SpawnSprite(S_EXPLODE,msprite->x,msprite->y,msprite->z,0,0,0,true,255); SoundEffect(SN_EXPLODE1+(MS_RndT()&1),15,msprite->x,msprite->y); return true; } else if (msprite->type==S_PROXMINE) { if (MS_RndT()&1) msprite->angle+=8; else msprite->angle-=8; msprite->angle&=ANGLES; x=msprite->x>>FRACTILESHIFT; y=msprite->y>>FRACTILESHIFT; activate=false; if (abs(x-(player.x>>FRACTILESHIFT))<2 && abs(y-(player.y>>FRACTILESHIFT))<2) activate=true; if (!activate) for (sp=firstscaleobj.next;sp!=&lastscaleobj;sp=sp->next) if (sp->hitpoints) { sx=sp->x>>FRACTILESHIFT; sy=sp->y>>FRACTILESHIFT; if (abs(x-sx)<2 && abs(y-sy)<2) { activate=true; break; } } for(i=-1;i<2;i++) for(j=-1;j<2;j++) if (mapsprites[(i+y)*MAPCOLS+j+x]==SM_NETPLAYER) activate=true; if (activate) { angleinc=ANGLES/16; angle=0; for(i=0,angle=0;i<16;i++,angle+=angleinc) sp=SpawnSprite(S_MINEBULLET,msprite->x,msprite->y,msprite->z,20<spawnid); sp=SpawnSprite(S_EXPLODE,msprite->x,msprite->y,msprite->z,0,0,0,true,255); SoundEffect(SN_EXPLODE1+(MS_RndT()&1),15,msprite->x,msprite->y); return true; } } else if (msprite->type==S_INSTAWALL) { mapsprites[(msprite->y>>FRACTILESHIFT)*MAPCOLS+(msprite->x>>FRACTILESHIFT)]=0; return true; } } return false; } /***************************************************************************/ int CloneScanX(int x,int y,int *x2) /* check for the target along the x axis */ { int mapspot, wall, x1, limit, flags; mapspot=y*MAPCOLS+x+1; x1=x; limit=10; while (1) { if (mapsprites[mapspot]==SM_CLONE || mapsprites[mapspot]==1) { *x2=x1+1; return 1+(MS_RndT()&1); } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; wall=westwall[mapspot]; flags=westflags[mapspot]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; ++mapspot; ++x1; --limit; if (!limit) break; } limit=10; mapspot=y*MAPCOLS+x-1; x1=x; while (1) { if (mapsprites[mapspot]==SM_CLONE || mapsprites[mapspot]==1) { *x2=x1-1; return 1+(MS_RndT()&1); } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) return 1; wall=westwall[mapspot+1]; flags=westflags[mapspot+1]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) return 0; --mapspot; --x1; --limit; if (!limit) break; } return 0; } int CloneScanY(int x,int y,int *y2) /* check for the player along the y axis */ { int mapspot, wall, y1, limit, flags; limit=10; mapspot=y*MAPCOLS+x+MAPCOLS; y1=y; while (1) { if (mapsprites[mapspot]==SM_CLONE || mapsprites[mapspot]==1) { *y2=y1+1; return 1+(MS_RndT()&1); } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; wall=northwall[mapspot]; flags=northflags[mapspot]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; mapspot+=MAPCOLS; ++y1; --limit; if (!limit) break; } limit=10; mapspot=y*MAPCOLS+x-MAPCOLS; y1=y; while (1) { if (mapsprites[mapspot]==SM_CLONE || mapsprites[mapspot]==1) { *y2=y1-1; return 1+(MS_RndT()&1); } if (mapsprites[mapspot]>0 && mapsprites[mapspot]<128) break; wall=northwall[mapspot+MAPCOLS]; flags=northflags[mapspot+MAPCOLS]; if (wall && !(flags & F_NOCLIP) && !(flags & F_NOBULLETCLIP)) break; mapspot-=MAPCOLS; --y1; --limit; if (!limit) break; } return 0; } void Int7(void) // clone ai { int angle, sx, sy, px, py, pangle, r; fixed_t floorz, fheight; sx=msprite->x>>FRACTILESHIFT; sy=msprite->y>>FRACTILESHIFT; if (timecount>msprite->movetime) { angle=msprite->angle - DEGREE45; r=MS_RndT()%3; if (r==1) angle+=DEGREE45; else if (r==2) angle+=NORTH; msprite->angle=angle&ANGLES; msprite->movetime=timecount+250; } if (timecount>msprite->firetime && timecount>msprite->scantime) { px=sx; py=sy; if (CloneScanX(sx,sy,&px)>1) { if (px>sx) angle=EAST; else if (pxangle=angle&ANGLES; msprite->movemode=4; msprite->basepic=msprite->startpic+24; fheight=40<bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle,pangle,true,255); msprite->modetime=timecount+8; msprite->actiontime=timecount+30; msprite->firetime=timecount+30; } else if (CloneScanY(sx,sy,&py)>1) { if (py>sy) angle=SOUTH; else if (pyangle=angle&ANGLES; msprite->movemode=4; msprite->basepic=msprite->startpic+24; fheight=40<bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle,pangle,true,255); msprite->modetime=timecount+8; msprite->actiontime=timecount+30; msprite->firetime=timecount+30; } msprite->scantime=timecount+20; } if (timecount>msprite->modetime) { msprite->modetime=timecount+10; switch (msprite->movemode) { case 0: // left case 1: // mid if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { ++msprite->movemode; msprite->basepic=msprite->startpic+msprite->movemode*8; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 2: // right if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->basepic=msprite->startpic + 8; ++msprite->movemode; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 3: // mid #2 if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->movemode=0; msprite->basepic=msprite->startpic; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 4: // fire msprite->movemode=0; msprite->basepic=msprite->startpic; break; } } if (timecount>msprite->actiontime && SP_Thrust2()!=1) { angle=msprite->angle+DEGREE45; msprite->angle=angle&ANGLES; } floorz=RF_GetFloorZ(msprite->x,msprite->y); if (floorz+msprite->zadjz) msprite->z-=FRACUNIT<<4; if (floorz+msprite->zadj>msprite->z) msprite->z=floorz+msprite->zadj; } /***************************************************************************/ void Int8(void) // prisoners { int angle, sx, sy, px, py, tx, ty, pangle; fixed_t floorz, oldspeed, fheight; sx=msprite->x>>FRACTILESHIFT; sy=msprite->y>>FRACTILESHIFT; if (netmode) NetGetClosestPlayer(sx,sy); else { if (specialeffect==SE_INVISIBILITY) { targx=0; targy=0; targz=0; } else { targx=player.x; targy=player.y; targz=player.z; } } px=targx>>FRACTILESHIFT; py=targy>>FRACTILESHIFT; oldspeed=msprite->moveSpeed; if (abs(px-sx)<6 && abs(py-sy)<6) msprite->moveSpeed=msprite->moveSpeed*2; if (timecount>msprite->movetime) { if (px>sx) angle=EAST; else if (pxsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } angle=angle - DEGREE45 + MS_RndT(); msprite->angle=angle&ANGLES; msprite->movetime=timecount+350; } if (timecount>msprite->firetime && timecount>msprite->scantime) { tx=px; ty=py; if (ScanX(7,sx,sy,px,py,&tx,&ty)>1 || ScanY(7,sx,sy,px,py,&tx,&ty)>1 || ScanAngle(7,sx,sy,px,py,&tx,&ty)>1) { if (tx>sx) angle=EAST; else if (txsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } msprite->angle=angle&ANGLES; if (abs(tx-sx)>2 || abs(ty-sy)>2) { msprite->scantime=timecount+45; goto endscan; } msprite->basepic=msprite->startpic+24; msprite->movemode=4; msprite->firetime=timecount+(80+5*player.difficulty); msprite->actiontime=timecount+30; msprite->modetime=timecount+15; } msprite->scantime=timecount+45; } endscan: if (timecount>msprite->modetime) { msprite->modetime=timecount+10; switch (msprite->movemode) { case 0: // left case 1: // mid if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { ++msprite->movemode; msprite->basepic=msprite->startpic+msprite->movemode*8; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 2: // right if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->basepic=msprite->startpic + 8; // midstep ++msprite->movemode; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 3: // mid #2 if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->movemode=0; msprite->basepic=msprite->startpic; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 4: // fire #1 tx=px; ty=py; if (ScanX(7,sx,sy,px,py,&tx,&ty)>1 || ScanY(7,sx,sy,px,py,&tx,&ty)>1 || ScanAngle(7,sx,sy,px,py,&tx,&ty)>1) { if (tx>sx) angle=EAST; else if (txsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } msprite->angle=angle&ANGLES; if (abs(tx-sx)>2 || abs(ty-sy)>2) { msprite->movemode=0; msprite->basepic=msprite->startpic; break; } msprite->movemode=5; msprite->basepic=msprite->startpic+32; fheight=40<bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle,pangle,true,255); msprite->modetime+=8; } else { msprite->movemode=0; msprite->basepic=msprite->startpic; } break; case 5: // fire #2 msprite->movemode=0; msprite->basepic=msprite->startpic; break; } } if (timecount>msprite->actiontime && SP_Thrust2()!=1) { angle=msprite->angle+DEGREE45; msprite->angle=angle&ANGLES; } floorz=RF_GetFloorZ(msprite->x,msprite->y); if (floorz+msprite->zadjz) msprite->z-=FRACUNIT<<4; if (floorz+msprite->zadj>msprite->z) msprite->z=floorz+msprite->zadj; msprite->moveSpeed=oldspeed; if (MS_RndT()>=255) ActivationSound(msprite); } /***************************************************************************/ void Int9(void) // big guards only { int i, angleinc, angle, sx, sy, px, py, tx, ty, pangle; fixed_t floorz, oldspeed, fheight; if (msprite->hitpoints<1000) msprite->hitpoints+=10; msprite->enraged=0; sx=msprite->x>>FRACTILESHIFT; sy=msprite->y>>FRACTILESHIFT; if (netmode) NetGetClosestPlayer(sx,sy); else { if (specialeffect==SE_INVISIBILITY) { targx=0; targy=0; targz=0; } else { targx=player.x; targy=player.y; targz=player.z; } } px=targx>>FRACTILESHIFT; py=targy>>FRACTILESHIFT; oldspeed=msprite->moveSpeed; if (abs(px-sx)<6 && abs(py-sy)<6) msprite->moveSpeed=msprite->moveSpeed*2; if (timecount>msprite->movetime) { if (px>sx) angle=EAST; else if (pxsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } angle=angle - DEGREE45 + MS_RndT(); msprite->angle=angle&ANGLES; msprite->movetime=timecount+200; } if (timecount>msprite->firetime && timecount>msprite->scantime) { SoundEffect(SN_MON11_WAKE,7,msprite->x,msprite->y); tx=px; ty=py; if (ScanX(8,sx,sy,px,py,&tx,&ty)>1 || ScanY(8,sx,sy,px,py,&tx,&ty)>1 || ScanAngle(8,sx,sy,px,py,&tx,&ty)>1) { if (tx>sx) angle=EAST; else if (txsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } msprite->angle=angle&ANGLES; msprite->basepic=msprite->startpic+24; msprite->movemode=4; msprite->firetime=timecount+(120+5*player.difficulty); msprite->actiontime=timecount+30; msprite->modetime=timecount+20; } msprite->scantime=timecount+45; } if (timecount>msprite->modetime) { msprite->modetime=timecount+20; switch (msprite->movemode) { case 0: // left case 1: // mid if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { ++msprite->movemode; msprite->basepic=msprite->startpic+msprite->movemode*8; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } if (MS_RndT()<32) { angle=0; angleinc=ANGLES/16; for (i=0;i<16;i++,angle+=angleinc) SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,32<x,msprite->y); } break; case 2: // right if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->basepic=msprite->startpic + 8; // midstep ++msprite->movemode; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } if (MS_RndT()<32) { angle=0; angleinc=ANGLES/16; for (i=0;i<16;i++,angle+=angleinc) SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,32<x,msprite->y); } break; case 3: // mid #2 if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->movemode=0; msprite->basepic=msprite->startpic; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } if (MS_RndT()<32) { angle=0; angleinc=ANGLES/16; for (i=0;i<16;i++,angle+=angleinc) SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,32<x,msprite->y); } break; case 4: // firing bullets case 5: case 6: case 7: tx=px; ty=py; if (ScanX(8,sx,sy,px,py,&tx,&ty)>1 || ScanY(8,sx,sy,px,py,&tx,&ty)>1 || ScanAngle(8,sx,sy,px,py,&tx,&ty)>1) { if (tx>sx) angle=EAST; else if (txsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } msprite->angle=angle&ANGLES; ++msprite->movemode; msprite->basepic=msprite->startpic+32; fheight=70<movemode==5 && MS_RndT()<32) { SpawnSprite(S_GRENADE,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31),0,true,255); SpawnSprite(S_GRENADE,msprite->x,msprite->y,msprite->z,fheight,msprite->angle+15+(MS_RndT()&31),0,true,255); SoundEffect(SN_GRENADE,0,msprite->x,msprite->y); msprite->movemode=0; msprite->basepic=msprite->startpic; msprite->firetime=timecount+(120+5*player.difficulty); msprite->actiontime=timecount+30; } else { pangle=GetFireAngle(fheight,tx,ty,targx,targy,targz)-15+(MS_RndT()&31); SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31),pangle,true,255); SoundEffect(SN_MON11_FIRE,7,msprite->x,msprite->y); msprite->modetime=timecount+15; } } else { msprite->movemode=0; msprite->basepic=msprite->startpic; msprite->firetime=timecount+(120+5*player.difficulty); msprite->actiontime=timecount+30; } break; case 8: // fire #2 msprite->movemode=0; msprite->basepic=msprite->startpic; msprite->firetime=timecount+(120+5*player.difficulty); msprite->actiontime=timecount+30; break; } } if (timecount>msprite->actiontime && SP_Thrust2()!=1) { angle=msprite->angle+DEGREE45; msprite->angle=angle&ANGLES; } floorz=RF_GetFloorZ(msprite->x,msprite->y); if (floorz+msprite->zadjz) msprite->z-=FRACUNIT<<4; if (floorz+msprite->zadj>msprite->z) msprite->z=floorz+msprite->zadj; msprite->moveSpeed=oldspeed; if (MS_RndT()>=255) ActivationSound(msprite); } /***************************************************************************/ void Int10(void) { int angle, sx, sy, px, py, tx, ty, pangle; fixed_t floorz, oldspeed, fheight; if (msprite->type==S_MONSTER5 && msprite->hitpoints<5000) msprite->hitpoints+=4; else if (msprite->type==S_MONSTER13 && msprite->hitpoints<300) { msprite->hitpoints+=25; msprite->enraged=0; } else if (msprite->type==S_MONSTER15 && msprite->hitpoints<2000) { msprite->hitpoints+=6; msprite->enraged=0; } else if (msprite->type==S_MONSTER14 && msprite->hitpoints<350) msprite->hitpoints+=1; sx=msprite->x>>FRACTILESHIFT; sy=msprite->y>>FRACTILESHIFT; if (netmode) NetGetClosestPlayer(sx,sy); else { if (specialeffect==SE_INVISIBILITY) { targx=0; targy=0; targz=0; } else { targx=player.x; targy=player.y; targz=player.z; } } px=targx>>FRACTILESHIFT; py=targy>>FRACTILESHIFT; oldspeed=msprite->moveSpeed; if (abs(px-sx)<6 && abs(py-sy)<6) msprite->moveSpeed=msprite->moveSpeed*2; if (timecount>msprite->movetime) { if (px>sx) angle=EAST; else if (pxsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } angle=angle - DEGREE45 + MS_RndT(); msprite->angle=angle&ANGLES; msprite->movetime=timecount+350; } if (timecount>msprite->firetime && timecount>msprite->scantime) { tx=px; ty=py; if (ScanX(10,sx,sy,px,py,&tx,&ty)>1 || ScanY(10,sx,sy,px,py,&tx,&ty)>1 || ScanAngle(10,sx,sy,px,py,&tx,&ty)>1) { if (tx>sx) angle=EAST; else if (txsy) { if (angle==EAST) angle-=DEGREE45; else if (angle==WEST) angle+=DEGREE45; else angle=SOUTH; } msprite->angle=angle&ANGLES; if (msprite->type==S_MONSTER7 && (abs(tx-sx)>2 || abs(ty-sy)>2)) { msprite->scantime=timecount+30; goto endscan; } if (msprite->type==S_MONSTER15 && (abs(tx-sx)>4 || abs(ty-sy)>4)) { msprite->scantime=timecount+30; goto endscan; } msprite->basepic=msprite->startpic+32; msprite->movemode=6; if (msprite->type==S_MONSTER5) msprite->firetime=timecount+(10+3*player.difficulty); else msprite->firetime=timecount+(40+5*player.difficulty); msprite->actiontime=timecount+30; msprite->modetime=timecount+15; if (msprite->type==S_MONSTER3) fheight=3<type==S_MONSTER6) fheight=100<type==S_MONSTER13 || msprite->type==S_MONSTER6 || msprite->type==S_MONSTER15 || msprite->type==S_MONSTER5) { SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31)+16,pangle,true,255); SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31)-16,pangle,true,255); SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31),pangle,true,255); } else if (msprite->type==S_MONSTER4) { SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31)+8,pangle,true,255); SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31)-8,pangle,true,255); } else SpawnSprite(msprite->bullet,msprite->x,msprite->y,msprite->z,fheight,msprite->angle-15+(MS_RndT()&31),pangle,true,255); } msprite->scantime=timecount+30; } endscan: if (timecount>msprite->modetime) { msprite->modetime=timecount+8; switch (msprite->movemode) { case 0: // 1 case 1: // 2 case 2: // 3 if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { ++msprite->movemode; msprite->basepic=msprite->startpic+msprite->movemode*8; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 3: // 2 case 4: // 1 if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->movemode++; msprite->basepic=msprite->startpic+(6-msprite->movemode)*8; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 5: if (msprite->lastx!=msprite->x || msprite->lasty!=msprite->y) { msprite->movemode=0; msprite->basepic=msprite->startpic; msprite->lasty=msprite->y; msprite->lastx=msprite->x; } break; case 6: // fire msprite->movemode=0; msprite->basepic=msprite->startpic; break; } } if (timecount>msprite->actiontime && SP_Thrust2()!=1) { angle=msprite->angle+DEGREE45; msprite->angle=angle&ANGLES; } floorz=RF_GetFloorZ(msprite->x,msprite->y) + msprite->zadj; if (floorzz) msprite->z-=FRACUNIT<<4; if (floorz>msprite->z) msprite->z=floorz; msprite->moveSpeed=oldspeed; if (MS_RndT()>=255) ActivationSound(msprite); } /***************************************************************************/ void MoveSprites(void) { int mapspot, i, j, c, px, py, sx, sy; boolean killed; fixed_t floor; if (!netmode) { targx=player.x; targy=player.y; px=targx>>FRACTILESHIFT; py=targy>>FRACTILESHIFT; } for (msprite=firstscaleobj.next;msprite!=&lastscaleobj;msprite=msprite->next) { if (msprite->active) { if (msprite->moveSpeed) switch (msprite->intelligence) { case 0: killed=Int0(); if (killed) { if (msprite->type==S_BLOODSPLAT) { msprite->intelligence=128; break; } else if (msprite->type==S_METALPARTS && !spritehit) { killed=false; continue; } msprite=msprite->prev; RF_RemoveSprite(msprite->next); killed=false; continue; } break; case 5: Int5(); break; case 6: killed=Int6(); if (killed) { msprite=msprite->prev; RF_RemoveSprite(msprite->next); killed=false; continue; } break; case 7: Int7(); break; case 8: Int8(); break; case 9: Int9(); break; case 10: Int10(); break; case 128: floor=RF_GetFloorZ(msprite->x,msprite->y); if (msprite->z>floor+FRACUNIT) msprite->z-=FRACUNIT*2; if (msprite->zz=floor; break; } if (!killed && msprite->heat) { mapspot=(msprite->y>>FRACTILESHIFT)*MAPCOLS+(msprite->x>>FRACTILESHIFT); if (msprite->heat>256) { c=msprite->heat>>1; for(i=-1;i<2;i++) for(j=-1;j<2;j++) reallight[mapspot+(i*MAPCOLS)+j]-=c; reallight[mapspot]-=msprite->heat>>2; } else reallight[mapspot]-=msprite->heat; } killed=false; } else if (msprite->intelligence!=255) { if (msprite->moveSpeed) { sx=msprite->x>>FRACTILESHIFT; sy=msprite->y>>FRACTILESHIFT; if (netmode) { NetGetClosestPlayer(sx,sy); px=targx>>FRACTILESHIFT; py=targy>>FRACTILESHIFT; } if ((abs(px-sx)<6 && abs(py-sy)<6)) { msprite->active=true; ActivateSprites(sx,sy); } } floor=RF_GetFloorZ(msprite->x,msprite->y)+msprite->zadj; if (msprite->z>floor) msprite->z-=FRACUNIT<<4; if (msprite->zz=floor; if (msprite->heat) { mapspot=(msprite->y>>FRACTILESHIFT)*MAPCOLS+(msprite->x>>FRACTILESHIFT); if (msprite->heat>256) { c=msprite->heat>>1; for(i=-1;i<2;i++) for(j=-1;j<2;j++) reallight[mapspot+(i*MAPCOLS)+j]-=c; reallight[mapspot]-=msprite->heat>>2; msprite->heat-=64; } else reallight[mapspot]-=msprite->heat; } } } }