diff --git a/src/battle/ai.c b/src/battle/ai.c index 1443dc5..72657a3 100644 --- a/src/battle/ai.c +++ b/src/battle/ai.c @@ -20,15 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "ai.h" -static int aggression[][5] = -{ - {60, 65, 70, 75, 80}, - {50, 55, 60, 65, 70}, - {40, 45, 50, 55, 60}, - {30, 35, 40, 45, 50}, - {15, 20, 25, 30, 35} -}; - static void faceTarget(Entity *f); static int isInFOV(Entity *f, int fov); static void preAttack(void); @@ -44,21 +35,36 @@ static void slow(void); static void moveToPlayer(void); static int canAttack(Entity *f); static int selectWeapon(int type); -static void flee(void); static int nearExtractionPoint(void); static int nearEnemies(void); static void lookForPlayer(void); static void fleeEnemies(void); static void moveToExtractionPoint(void); +static int getActionChance(int type); +static void flee(void); +static void doFighterAI(void); +static void doCivilianAI(void); void doAI(void) +{ + if (self->flags & EF_CIVILIAN) + { + doCivilianAI(); + } + else + { + doFighterAI(); + } +} + +static void doFighterAI(void) { int r; /* don't hold a grudge against current target */ if ((self->target != NULL && self->target->health <= 0) || rand() % 2 == 0) { - self->action = self->defaultAction; + self->action = doAI; self->target = NULL; } @@ -83,27 +89,27 @@ void doAI(void) r = rand() % 100; - if (r <= aggression[self->aggression][0]) + if (r <= getActionChance(AI_DODGE)) { self->action = dodge; self->aiActionTime = FPS; } - else if (r <= aggression[self->aggression][1]) + else if (r <= getActionChance(AI_BOOST)) { self->action = boost; self->aiActionTime = FPS / 2; } - else if (r <= aggression[self->aggression][2]) + else if (r <= getActionChance(AI_SLOW)) { self->action = slow; self->aiActionTime = FPS / 2; } - else if (r <= aggression[self->aggression][3]) + else if (r <= getActionChance(AI_STRAIGHT)) { self->action = flyStraight; self->aiActionTime = FPS; } - else if (r <= aggression[self->aggression][4]) + else if (r <= getActionChance(AI_HUNT)) { self->action = huntTarget; self->aiActionTime = FPS * 2; @@ -114,7 +120,7 @@ void doAI(void) self->aiActionTime = FPS; } - if (player != NULL && battle.numEnemies <= 2 && self->flags & EF_FLEES) + if ((player != NULL && battle.numEnemies <= 2 && self->flags & EF_FLEES) || (self->flags & EF_ALWAYS_FLEES)) { self->action = flee; self->aiActionTime = FPS * 3; @@ -126,6 +132,29 @@ void doAI(void) } } +static int getActionChance(int type) +{ + switch (type) + { + case AI_DODGE: + return 40 - (self->aggression * 5); + + case AI_BOOST: + return 50 - (self->aggression * 5); + + case AI_SLOW: + return 60 - (self->aggression * 5); + + case AI_STRAIGHT: + return 70 - (self->aggression * 5); + + case AI_HUNT: + return 80 - (self->aggression * 5); + } + + return 100; +} + static void huntTarget(void) { faceTarget(self->target); @@ -341,10 +370,61 @@ static void dodge(void) nextAction(); } +static void nextAction(void) +{ + if (--self->aiActionTime <= 0) + { + self->action = doAI; + } +} + static void flee(void) +{ + if (!nearEnemies() && battle.extractionPoint) + { + self->target = battle.extractionPoint; + moveToExtractionPoint(); + } +} + +static int nearEnemies(void) +{ + int i, numEnemies; + Entity *e, **candidates; + + candidates = getAllEntsWithin(self->x - (self->w / 2) - 1000, self->y - (self->h / 2) - 1000, 2000, 2000, self); + + self->target = NULL; + self->targetLocation.x = self->targetLocation.y = 0; + + numEnemies = 0; + + for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) + { + if (e->type == ET_FIGHTER && e->side != self->side) + { + self->targetLocation.x += e->x; + self->targetLocation.y += e->y; + numEnemies++; + } + } + + if (numEnemies) + { + self->targetLocation.x /= numEnemies; + self->targetLocation.y /= numEnemies; + self->action = fleeEnemies; + self->aiActionTime = FPS / 2; + return 1; + } + + return 0; +} + +static void fleeEnemies(void) { int dir; - int wantedAngle = 180 + getAngle(self->x, self->y, player->x, player->y); + int wantedAngle = 180 + getAngle(self->x, self->y, self->targetLocation.x, self->targetLocation.y); wantedAngle %= 360; @@ -359,17 +439,14 @@ static void flee(void) applyFighterThrust(); - nextAction(); -} - -static void nextAction(void) -{ if (--self->aiActionTime <= 0) { self->action = doAI; } } +/* ====== Ally AI ======= */ + static void moveToPlayer(void) { int dist = getDistance(self->x, self->y, player->x, player->y); @@ -430,64 +507,6 @@ static void moveToExtractionPoint(void) applyFighterThrust(); } -static int nearEnemies(void) -{ - int i, numEnemies; - Entity *e, **candidates; - - candidates = getAllEntsWithin(self->x - (self->w / 2) - 1000, self->y - (self->h / 2) - 1000, 2000, 2000, self); - - self->target = NULL; - self->targetLocation.x = self->targetLocation.y = 0; - - numEnemies = 0; - - for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) - { - if (e->type == ET_FIGHTER && e->side != SIDE_ALLIES) - { - self->targetLocation.x += e->x; - self->targetLocation.y += e->y; - numEnemies++; - } - } - - if (numEnemies) - { - self->targetLocation.x /= numEnemies; - self->targetLocation.y /= numEnemies; - self->action = fleeEnemies; - self->aiActionTime = FPS / 2; - return 1; - } - - return 0; -} - -static void fleeEnemies(void) -{ - int dir; - int wantedAngle = 180 + getAngle(self->x, self->y, self->targetLocation.x, self->targetLocation.y); - - wantedAngle %= 360; - - if (fabs(wantedAngle - self->angle) > TURN_THRESHOLD) - { - dir = ((int)(wantedAngle - self->angle + 360)) % 360 > 180 ? -1 : 1; - - self->angle += dir * TURN_SPEED; - - self->angle = mod(self->angle, 360); - } - - applyFighterThrust(); - - if (--self->aiActionTime <= 0) - { - self->action = doCivilianAI; - } -} - static void lookForPlayer(void) { if (player != NULL && getDistance(self->x, self->y, player->x, player->y) < 1000) diff --git a/src/battle/ai.h b/src/battle/ai.h index fdbeb50..8182f42 100644 --- a/src/battle/ai.h +++ b/src/battle/ai.h @@ -23,6 +23,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../defs.h" #include "../structs.h" +#define AI_DODGE 0 +#define AI_BOOST 1 +#define AI_SLOW 2 +#define AI_STRAIGHT 3 +#define AI_HUNT 4 + #define TURN_SPEED 4 #define TURN_THRESHOLD 2 diff --git a/src/battle/fighters.c b/src/battle/fighters.c index aac58f8..a331a8e 100644 --- a/src/battle/fighters.c +++ b/src/battle/fighters.c @@ -75,15 +75,7 @@ Entity *spawnFighter(char *name, int x, int y, int side) f->texture = getTexture("gfx/craft/civilian02.png"); } - if (f->flags & EF_CIVILIAN) - { - f->defaultAction = doCivilianAI; - } - else - { - f->defaultAction = doAI; - } - + f->action = doAI; f->die = die; return f; @@ -193,11 +185,6 @@ void doFighter(void) self->shieldRecharge = self->shieldRechargeRate; } - if (self->action == NULL && self->defaultAction != NULL) - { - self->action = self->defaultAction; - } - if (self->health <= 0) { self->health = 0; @@ -395,7 +382,7 @@ void damageFighter(Entity *f, int amount, long flags) if (f->systemPower == 0) { f->shield = f->maxShield = 0; - f->action = f->defaultAction = NULL; + f->action = NULL; } } else @@ -491,3 +478,16 @@ static void straightDie(void) playBattleSound(SND_EXPLOSION_1 + rand() % 4, self->x, self->y); } } + +void fleeAllEnemies(void) +{ + Entity *e; + + for (e = battle.entityHead.next ; e != NULL ; e = e->next) + { + if (e->type == ET_FIGHTER && e->side != SIDE_ALLIES) + { + e->flags |= EF_ALWAYS_FLEES; + } + } +} diff --git a/src/battle/player.c b/src/battle/player.c index 84406fd..a736c8c 100644 --- a/src/battle/player.c +++ b/src/battle/player.c @@ -56,7 +56,6 @@ void initPlayer(void) STRNCPY(player->name, "Player", MAX_NAME_LENGTH); player->action = NULL; - player->defaultAction = NULL; } void doPlayer(void) diff --git a/src/structs.h b/src/structs.h index a7db757..f73cff2 100644 --- a/src/structs.h +++ b/src/structs.h @@ -113,7 +113,6 @@ struct Entity { Entity *target; Entity *owner; void (*action)(void); - void (*defaultAction)(void); void (*die)(void); SDL_Texture *texture; Entity *next;