// C Header File // Created 5/18/2003; 5:21:56 PM static inline void AnimateStaticSprites(void); static short giveAmmo(short i); static inline void RunCustomSpriteTasks(short idx, short alive_idx); static inline short SpriteHasCollisionCode(char type); static inline void CheckForSpriteCollisions(void); static inline void SpritesExecute(void); #ifndef __SPRITES_EXEC_H__ #define __SPRITES_EXEC_H__ #include "enemies.h" #include "sprites_init.h" static inline void AnimateStaticSprites(void) { register GameGlobals *ggg asm("a4") = gg; short a; register SpriteStruct *extra = ggg->sprites_extra; for(a=0;asprite_count;a++,extra++) { if(extra->animated == FALSE) continue; FATSPRITE *sprite = ggg->sprites + a; if(extra->cycles==extra->delaycycles) { extra->cycles = 0; if(extra->type==deathAnim/* || extra->type==instantHitShow*/) SpriteLife(a,-1); if(extra->pos < extra->lastframe) { extra->pos++; if(extra->pattern) sprite->textures = extra->src + extra->first_idx + extra->pattern[extra->pos]; else sprite->textures++; } else { sprite->textures = extra->src + extra->first_idx; extra->pos = 0; } } else if(extra->delaycycles) extra->cycles++; } } static short giveAmmo(short i) { if(WeaponsValid[i]) { if(weapons[i].ammo < weapons[i].cur->maxammo) { weapons[i].ammo += weapons[i].cur->clip_ammo; if(weapons[i].ammo > weapons[i].cur->maxammo) weapons[i].ammo = weapons[i].cur->maxammo; return 1; //Successful } } return 0; //Unsuccessful } static inline void RunCustomSpriteTasks(short idx, short alive_idx) { register GameGlobals *ggg asm("a4") = gg; short type = (ggg->sprites_extra + idx)->type; short success = 0; if(alive_idx==-1) //Sprites affecting the player { switch(type) { case healthSmall: if(ggg->player.lifeplayer.life += 10; success++; if(ggg->player.life>MAX_HEALTH) ggg->player.life = MAX_HEALTH; textEnqueue(stringIdx(gamestrings,e10Health)); } break; case healthLarge: if(ggg->player.lifeplayer.life += 25; success++; if(ggg->player.life>MAX_HEALTH) ggg->player.life = MAX_HEALTH; textEnqueue(stringIdx(gamestrings,e25Health)); } break; case healthPlant: if(ggg->player.lifeplayer.life += 15; success++; if(ggg->player.life>MAX_HEALTH) ggg->player.life = MAX_HEALTH; textEnqueue(stringIdx(gamestrings,e15Health)); } break; case armorLight: if(ggg->player.armorplayer.armor += 50; success++; if(ggg->player.armor>MAX_ARMOR) ggg->player.armor = MAX_ARMOR; textEnqueue(stringIdx(gamestrings,e50Armor)); } break; case armorHeavy: if(ggg->player.armorplayer.armor += 100; success++; if(ggg->player.armor>MAX_ARMOR) ggg->player.armor = MAX_ARMOR; textEnqueue(stringIdx(gamestrings,e100Armor)); } break; case keycard: ggg->playerHasKeycard = TRUE; success++; textEnqueue(stringIdx(gamestrings,eKeycard)); break; case keycardTrigger: ggg->playerHasKeycard = TRUE; success++; textEnqueue(stringIdx(gamestrings,eKeycard)); handleLightSkullsTriggerEnemies(); break; case pistolAmmo: if((success+=giveAmmo(PISTOL))) textEnqueue(stringIdx(gamestrings,ePistolAmmo)); break; case machinegunAmmo: if((success+=giveAmmo(MACHINEGUN))) textEnqueue(stringIdx(gamestrings,eMachGunAmmo)); break; case rocketlauncherAmmo: if((success+=giveAmmo(ROCKETLAUNCHER))) textEnqueue(stringIdx(gamestrings,eRocketAmmo)); break; case plasmagunAmmo: if((success+=giveAmmo(PLASMAGUN))) textEnqueue(stringIdx(gamestrings,ePlasmaAmmo)); break; case railgunAmmo: if((success+=giveAmmo(RAILGUN))) textEnqueue(stringIdx(gamestrings,eRailGunAmmo)); break; case deathBox: KillSprite(idx); success++; break; case pistol: GiveWeapon(PISTOL); success++; textEnqueue(stringIdx(gamestrings,ePistol)); break; case machinegun: GiveWeapon(MACHINEGUN); success++; textEnqueue(stringIdx(gamestrings,eMachinegun)); break; case rocketlauncher: GiveWeapon(ROCKETLAUNCHER); success++; textEnqueue(stringIdx(gamestrings,eRocketLauncher)); break; case plasmagun: GiveWeapon(PLASMAGUN); success++; textEnqueue(stringIdx(gamestrings,ePlasmaGun)); break; case railgun: GiveWeapon(RAILGUN); success++; textEnqueue(stringIdx(gamestrings,eRailGun)); break; } if((ggg->sprites_extra + idx)->pickup && success) KillSprite(idx); if(ggg->player.life<=0) ggg->quitting = PLAYER_DIED; } else //Sprites affecting other sprites (i.e. the enemies... fewer) { switch(type) { case deathBox: KillSprite(idx); success++; break; } if((ggg->sprites_extra + idx)->pickup && success) KillSprite(idx); } } static inline short SpriteHasCollisionCode(char type) { switch(type) { case deathBox: return 1; default: return 0; } } static inline void CheckForSpriteCollisions(void) { register GameGlobals *ggg asm("a4") = gg; short a,i; register FATSPRITE *alive = ggg->sprites; SpriteStruct *alive_extra = ggg->sprites_extra; for(a=0;asprite_count;a++,alive++,alive_extra++) { if(alive_extra->type==deathBox) { if(iRoundEqual(fc->cam_xpos,alive->xpos,8) && iRoundEqual(fc->cam_ypos,alive->ypos,8)) { if(!RayBlocked(fc->cam_xpos,fc->cam_ypos,alive->xpos,alive->ypos)) RunCustomSpriteTasks(a,-1); } } else if(iRoundEqual(fc->cam_xpos,alive->xpos,6) && iRoundEqual(fc->cam_ypos,alive->ypos,6)) //Collision { //textEnqueueF("Collision with #%i (%i).",a,(ggg->sprites_extra+a)->type); RunCustomSpriteTasks(a,-1); } if(alive_extra->desire!=ENEMY_NONE || alive_extra->type==deathBox) { FATSPRITE *spr = ggg->sprites; SpriteStruct *e = ggg->sprites_extra; for(i=0;isprite_count;i++,spr++,e++) { if(i!=a && SpriteHasCollisionCode(e->type)) { if(alive_extra->type==deathBox) { if(iRoundEqual(alive->xpos,spr->xpos,8) && iRoundEqual(alive->ypos,spr->ypos,8)) //Collision { if(!RayBlocked(alive->xpos,alive->ypos,spr->xpos,spr->ypos)) RunCustomSpriteTasks(i,a); } } if(iRoundEqual(alive->xpos,spr->xpos,7) && iRoundEqual(alive->ypos,spr->ypos,7)) //Collision { RunCustomSpriteTasks(i,a); } } } } } }/* static inline void CheckForSpriteCollisions(void) { register GameGlobals *ggg asm("a4") = gg; short a,i; FATSPRITE *alive = sprites; SpriteStruct *alive_extra = ggg->sprites_extra; FATSPRITE *spr = sprites; for(a=0;acam_xpos,spr->xpos,6) && iRoundEqual(fc->cam_ypos,spr->ypos,6)) //Collision { //textEnqueueF("Collision with #%i (%i).",a,(ggg->sprites_extra+a)->type); RunCustomSpriteTasks(a,-1); } ++spr; } for(i=0;idesire!=ENEMY_NONE) { spr = sprites; SpriteStruct *e = ggg->sprites_extra; for(a=0;atype)) { if(iRoundEqual(alive->xpos,spr->xpos,6) && iRoundEqual(alive->ypos,spr->ypos,6)) //Collision { RunCustomSpriteTasks(a,i); } } ++spr; ++e; } } ++alive; ++alive_extra; } }*/ static inline void SpritesExecute(void) { register GameGlobals *ggg asm("a4") = gg; short a; FATSPRITE *spr = ggg->sprites; register SpriteStruct *extra = ggg->sprites_extra; for(a=0;asprite_count;a++,spr++,extra++) { short desire = extra->desire; if(desire) { short px = fc->cam_xpos; short py = fc->cam_ypos; short ex = spr->xpos; short ey = spr->ypos; short dx = px - ex; //Must be this order short dy = py - ey; //Must be this order long distance_squared = (long)dx*dx + (long)dy*dy; unsigned long distance = FAT_FastSqrt(distance_squared); if(!extra->active) { if(spr->height == -1) continue; if(distance > (unsigned long)MAX_ACTING_DISTANCE) { if(extra->life == life(extra->type))//current health == starting health //(lets the enemy do stuff it it has been hit) { spr->orientation = FAT_ClampAngle(FAT_GetArcTanYX (dy, dx)-ANGLE_180); if(extra->nr_textures==2) { if(extra->pattern) spr->textures = extra->src + extra->first_idx + extra->pattern[extra->lastframe+1]; else spr->textures = extra->src + extra->first_idx + extra->lastframe + 1; } continue; } } if(RayBlocked(px,py,ex,ey)) //Wall in between player/enemy { if(extra->nr_textures==2) { if(extra->pattern) spr->textures = extra->src + extra->first_idx + extra->pattern[extra->lastframe+1]; else spr->textures = extra->src + extra->first_idx + extra->lastframe + 1; } continue; } extra->active = TRUE; } short angle = FAT_GetArcTanYX (dy, dx); if(desire & ENEMY_SHOOTER) { spr->orientation = angle; EnemyShoot(a); } if(desire & ENEMY_CHASER) { spr->orientation = angle; EnemyChase(a,distance); } if(desire & ENEMY_BOSS) { spr->orientation = angle; EnemyBoss(a,distance); } } } } static inline void SpawnExplosion(short x, short y) { register GameGlobals *ggg asm("a4") = gg; #define MAX_EXPLOSION_DAMAGE 250 #define MAX_EXPLOSION_DISTANCE_TILES (3L) #define MAX_EXPLOSION_DISTANCE ((MAX_EXPLOSION_DISTANCE_TILES<<6)*(MAX_EXPLOSION_DISTANCE_TILES<<6)) short a; short dx,dy,damage; long distance_squared; FATSPRITE *s = ggg->sprites; SpriteStruct *e = ggg->sprites_extra; for(a=0;asprite_count;a++,s++,e++) { if(e->pickup) continue; if(RayBlocked(s->xpos,s->ypos,x,y)) continue; dx = abs(s->xpos - x); dy = abs(s->ypos - y); if(dx>>6>MAX_EXPLOSION_DISTANCE_TILES+2 || dy>>6>MAX_EXPLOSION_DISTANCE_TILES+2) continue; distance_squared = ((long)dx*dx + (long)dy*dy); if(distance_squared>=MAX_EXPLOSION_DISTANCE) continue; distance_squared = MAX_EXPLOSION_DISTANCE - distance_squared; damage = (distance_squared*MAX_EXPLOSION_DAMAGE)/MAX_EXPLOSION_DISTANCE; SpriteLife(a,-damage); } if(RayBlocked(fc->cam_xpos,fc->cam_ypos,x,y)) return; dx = abs(fc->cam_xpos - x); dy = abs(fc->cam_ypos - y); if(dx>>6>5 || dy>>6>5) return; distance_squared = ((long)dx*dx + (long)dy*dy); if(distance_squared>=MAX_EXPLOSION_DISTANCE) return; distance_squared = MAX_EXPLOSION_DISTANCE - distance_squared; damage = (distance_squared*MAX_EXPLOSION_DAMAGE)/MAX_EXPLOSION_DISTANCE; PlayerLife(-damage); } #endif