#include "../sdl/sound/CSound.h" #include "../keen.h" #include "../include/game.h" #include "../include/enemyai.h" // Tank Robot (Ep2) #define TANK_LOOK 0 #define TANK_WALK 1 #define TANK2_SAME_LEVEL_TIME 150 #define TANK_REPEAT_FIRE_TIME 800 // when this probability is satisfied, there is 50% probability // of a look, 50% probability of a fire. #define TANK_LOOKFIRE_PROB 500 #define TANK_MINTRAVELDIST 200 #define TANK_WALK_SPEED 4 #define TANK_WALK_ANIM_TIME 60 #define TANK_LOOK_ANIM_TIME 110 #define TANK_LOOK_TOTALTIME 250 #define TANK2_PREPAREFIRE_TIME 80 // frames #define TANK2_WALK_LEFT_FRAME 116 #define TANK2_WALK_RIGHT_FRAME 112 #define TANK2_LOOK_FRAME 120 #define TANKPUSHAMOUNT 16 #define TANK2_SHOTS_PER_VOLLEY 4 #define TANK2_MIN_TIME_TILL_CAN_FIRE 600 #define TANK2_MAX_TIME_TILL_CAN_FIRE 1000 #define TANK2_PAUSE_BEFORE_FIRST_SHOT 150 #define TANK2_TIME_BETWEEN_SHOTS 50 #define TANK2_TIME_BEFORE_FIRE_WHEN_SEE 100 #define TANK2_TIME_BETWEEN_FIRE_CAUSE_LEVEL 400 void tankep2_ai(int o, stCloneKeenPlus *pCKP) { int newobject; //int not_about_to_fall; unsigned int i; if (objects[o].needinit) { // first time initilization objects[o].ai.tank.state = TANK_WALK; objects[o].ai.tank.movedir = RIGHT; objects[o].ai.tank.fireafterlook = 0; objects[o].ai.tank.animtimer = 0; objects[o].ai.tank.timer = 0; objects[o].ai.tank.dist_traveled = 0; objects[o].ai.tank.timetillcanfire = TANK2_MAX_TIME_TILL_CAN_FIRE; objects[o].ai.tank.firetimes = 0; objects[o].ai.tank.detectedPlayer = 0; objects[o].ai.tank.detectedPlayerIndex = primaryplayer; objects[o].canbezapped = 1; // will stop bullets but is not harmed objects[o].inhibitfall = 1; objects[o].needinit = 0; } // touched player? if (objects[o].touchPlayer && !player[objects[o].touchedBy].pdie) { killplayer(objects[o].touchedBy, pCKP); } switch(objects[o].ai.tank.state) { case TANK_LOOK: objects[o].sprite = TANK2_LOOK_FRAME + objects[o].ai.tank.frame; // animation if (objects[o].ai.tank.animtimer > TANK_LOOK_ANIM_TIME) { objects[o].ai.tank.frame ^= 1; objects[o].ai.tank.animtimer = 0; } else objects[o].ai.tank.animtimer++; // when time is up go back to moving if (objects[o].ai.tank.timer > TANK_LOOK_TOTALTIME) { // decide what direction to go if (objects[o].blockedr) { objects[o].ai.tank.movedir = LEFT; } else if (objects[o].blockedl) { objects[o].ai.tank.movedir = RIGHT; } else if (objects[o].x > player[0].x) { objects[o].ai.tank.movedir = LEFT; } else { objects[o].ai.tank.movedir = RIGHT; } objects[o].ai.tank.alreadyfiredcauseonsamelevel = 0; objects[o].ai.tank.timetillcanfire = (rand()%(TANK2_MAX_TIME_TILL_CAN_FIRE-TANK2_MIN_TIME_TILL_CAN_FIRE))+TANK2_MIN_TIME_TILL_CAN_FIRE; objects[o].ai.tank.timetillcanfirecauseonsamelevel = TANK2_TIME_BEFORE_FIRE_WHEN_SEE; objects[o].ai.tank.firetimes = 0; objects[o].ai.tank.state = TANK_WALK; objects[o].ai.tank.frame = 0; objects[o].ai.tank.animtimer = 0; objects[o].ai.tank.timer = 0; objects[o].ai.tank.dist_traveled = 0; } else objects[o].ai.tank.timer++; break; case TANK_WALK: // is keen on same level? objects[o].ai.tank.detectedPlayer = 0; for(i=0;i= objects[o].y-(12<>CSF)+sprites[0].ysize <= (objects[o].y>>CSF)+sprites[objects[o].sprite].ysize+12) { objects[o].ai.tank.detectedPlayer = 1; objects[o].ai.tank.detectedPlayerIndex = i; break; } } } if (objects[o].ai.tank.detectedPlayer) { // facing keen? objects[o].ai.tank.alreadyfiredcauseonsamelevel = 1; // are we facing him? if (((player[objects[o].ai.tank.detectedPlayerIndex].x < objects[o].x) && objects[o].ai.tank.movedir==LEFT) || \ ((player[objects[o].ai.tank.detectedPlayerIndex].x > objects[o].x) && objects[o].ai.tank.movedir==RIGHT)) { // yes, we're facing him! FIRE!!! if (!objects[o].ai.tank.firetimes) { if (!objects[o].ai.tank.timetillcanfirecauseonsamelevel) { objects[o].ai.tank.firetimes = TANK2_SHOTS_PER_VOLLEY; objects[o].ai.tank.timetillnextshot = TANK2_PAUSE_BEFORE_FIRST_SHOT; objects[o].ai.tank.timetillcanfire = (rand()%(TANK2_MAX_TIME_TILL_CAN_FIRE-TANK2_MIN_TIME_TILL_CAN_FIRE))+TANK2_MIN_TIME_TILL_CAN_FIRE; objects[o].ai.tank.timetillcanfirecauseonsamelevel = TANK2_TIME_BETWEEN_FIRE_CAUSE_LEVEL; } else objects[o].ai.tank.timetillcanfirecauseonsamelevel--; } } else { // no we're not facing him, on hard difficulty turn around if (pCKP->Control.levelcontrol.hardmode) { objects[o].ai.tank.frame = 0; objects[o].ai.tank.timer = 0; objects[o].ai.tank.animtimer = 0; objects[o].ai.tank.state = TANK_LOOK; } } } else { // no, not on same level objects[o].ai.tank.alreadyfiredcauseonsamelevel = 0; } // are we firing a volley? if (objects[o].ai.tank.firetimes) { // is it time to fire the next shot in the volley? if (!objects[o].ai.tank.timetillnextshot) { if (objects[o].onscreen) g_pSound->playStereofromCoord(SOUND_TANK_FIRE, PLAY_NOW, objects[o].scrx); if (objects[o].ai.tank.movedir==RIGHT) { newobject = spawn_object(objects[o].x+(sprites[TANK2_WALK_RIGHT_FRAME].xsize< TANK_WALK_ANIM_TIME) { if (objects[o].ai.tank.frame>=3) objects[o].ai.tank.frame=0; else objects[o].ai.tank.frame++; objects[o].ai.tank.animtimer = 0; } else objects[o].ai.tank.animtimer++; break; } }