diff --git a/data/capitalShips/corvette.json b/data/capitalShips/corvette.json index 3d67888..0c9e1b6 100644 --- a/data/capitalShips/corvette.json +++ b/data/capitalShips/corvette.json @@ -71,28 +71,28 @@ ], "engines" : [ { - "health" : 100, + "health" : 1000, "texture" : "gfx/capitalShips/corvette/engine1.png", "x" : -112, "y" : 281, "flags" : "EF_TAKES_DAMAGE+EF_STATIC" }, { - "health" : 100, + "health" : 1000, "texture" : "gfx/capitalShips/corvette/engine1.png", "x" : 112, "y" : 281, "flags" : "EF_TAKES_DAMAGE+EF_STATIC" }, { - "health" : 100, + "health" : 1000, "texture" : "gfx/capitalShips/corvette/engine2.png", "x" : -34, "y" : 268, "flags" : "EF_TAKES_DAMAGE+EF_STATIC" }, { - "health" : 100, + "health" : 1000, "texture" : "gfx/capitalShips/corvette/engine2.png", "x" : 34, "y" : 268, @@ -108,7 +108,8 @@ "reloadTime" : 40, "type" : "BT_ROCKET", "flags" : "EF_TAKES_DAMAGE+EF_STATIC+EF_SECONDARY_TARGET", - "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE" + "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE", + "missiles" : 9999 }, { "health" : 250, @@ -118,7 +119,8 @@ "reloadTime" : 40, "type" : "BT_ROCKET", "flags" : "EF_TAKES_DAMAGE+EF_STATIC+EF_SECONDARY_TARGET", - "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE" + "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE", + "missiles" : 9999 }, { "health" : 250, @@ -128,7 +130,8 @@ "reloadTime" : 10, "type" : "BT_PLASMA", "flags" : "EF_TAKES_DAMAGE+EF_SECONDARY_TARGET", - "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE" + "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE", + "missiles" : 9999 }, { "health" : 250, @@ -138,7 +141,8 @@ "reloadTime" : 10, "type" : "BT_PLASMA", "flags" : "EF_TAKES_DAMAGE+EF_SECONDARY_TARGET", - "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE" + "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE", + "missiles" : 9999 }, { "health" : 250, @@ -148,7 +152,8 @@ "reloadTime" : 10, "type" : "BT_PLASMA", "flags" : "EF_TAKES_DAMAGE+EF_SECONDARY_TARGET", - "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE" + "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE", + "missiles" : 9999 }, { "health" : 250, @@ -158,7 +163,8 @@ "reloadTime" : 10, "type" : "BT_PLASMA", "flags" : "EF_TAKES_DAMAGE+EF_SECONDARY_TARGET", - "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE" + "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE", + "missiles" : 9999 }, { "health" : 250, @@ -168,7 +174,8 @@ "reloadTime" : 10, "type" : "BT_PLASMA", "flags" : "EF_TAKES_DAMAGE+EF_SECONDARY_TARGET", - "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE" + "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE", + "missiles" : 9999 }, { "health" : 250, @@ -178,7 +185,8 @@ "reloadTime" : 10, "type" : "BT_PLASMA", "flags" : "EF_TAKES_DAMAGE+EF_SECONDARY_TARGET", - "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE" + "aiFlags" : "AIF_AGGRESSIVE+AIF_LONG_RANGE_FIRE", + "missiles" : 9999 } ] } diff --git a/src/battle/capitalShips.c b/src/battle/capitalShips.c index 4d5926f..20ab112 100644 --- a/src/battle/capitalShips.c +++ b/src/battle/capitalShips.c @@ -20,12 +20,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "capitalShips.h" +static void separate(void); static void think(void); static void gunThink(void); static void gunDie(void); static void componentDie(void); static void engineThink(void); static void engineDie(void); +static void findAITarget(void); static void loadCapitalShipDef(char *filename); static void loadComponents(Entity *parent, cJSON *components); static void loadGuns(Entity *parent, cJSON *guns); @@ -66,6 +68,26 @@ Entity *spawnCapitalShip(char *name, int x, int y, int side) return capitalShip; } +void doCapitalShip(void) +{ + if (self->alive == ALIVE_ALIVE) + { + separate(); + + if (self->health <= 0) + { + self->health = 0; + self->alive = ALIVE_DYING; + self->die(); + + if (self == battle.missionTarget) + { + battle.missionTarget = NULL; + } + } + } +} + static void think(void) { float dir; @@ -73,13 +95,7 @@ static void think(void) if (--self->aiActionTime <= 0) { - self->targetLocation.x = rand() % GRID_SIZE; - self->targetLocation.x *= GRID_CELL_WIDTH; - - self->targetLocation.y = rand() % GRID_SIZE; - self->targetLocation.y *= GRID_CELL_HEIGHT; - - self->aiActionTime = FPS * (30 + (rand() % 120)); + findAITarget(); } wantedAngle = getAngle(self->x, self->y, self->targetLocation.x, self->targetLocation.y); @@ -100,6 +116,94 @@ static void think(void) applyFighterThrust(); } +static void findAITarget(void) +{ + Entity *e; + unsigned int dist, closest; + + self->target = NULL; + dist = closest = MAX_TARGET_RANGE; + + for (e = battle.entityHead.next ; e != NULL ; e = e->next) + { + if (e->active && e->side != self->side && e->flags & EF_AI_TARGET) + { + dist = getDistance(self->x, self->y, e->x, e->y); + + if (!self->target || dist < closest) + { + self->target = e; + closest = dist; + } + } + } + + if (self->target) + { + self->targetLocation.x = self->target->x + (rand() % 1000 - rand() % 1000); + self->targetLocation.y = self->target->y + (rand() % 1000 - rand() % 1000); + + self->aiActionTime = FPS * 15; + } + else + { + self->targetLocation.x = 5 + (rand() % (GRID_SIZE - 10)); + self->targetLocation.x *= GRID_CELL_WIDTH; + + self->targetLocation.y = 5 + (rand() % (GRID_SIZE - 10)); + self->targetLocation.y *= GRID_CELL_HEIGHT; + + self->aiActionTime = FPS * (30 + (rand() % 120)); + } +} + +static void separate(void) +{ + int angle; + int distance; + float dx, dy, force; + int count; + Entity *e, **candidates; + int i; + + dx = dy = 0; + count = 0; + force = 0; + + candidates = getAllEntsWithin(self->x - (self->w / 2), self->y - (self->h / 2), self->w, self->h, self); + + for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) + { + if (e->type == ET_CAPITAL_SHIP) + { + distance = getDistance(e->x, e->y, self->x, self->y); + + if (distance > 0 && distance < self->separationRadius) + { + angle = getAngle(self->x, self->y, e->x, e->y); + + dx += sin(TO_RAIDANS(angle)); + dy += -cos(TO_RAIDANS(angle)); + force += (self->separationRadius - distance) * 0.005; + + count++; + } + } + } + + if (count > 0) + { + dx /= count; + dy /= count; + + dx *= force; + dy *= force; + + self->dx -= dx; + self->dy -= dy; + } +} + static void gunThink(void) { doAI(); @@ -214,6 +318,9 @@ static void loadCapitalShipDef(char *filename) e->action = think; e->die = die; + SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); + e->separationRadius = MAX(e->w, e->h) * 3; + SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); loadComponents(e, cJSON_GetObjectItem(root, "components")); @@ -307,6 +414,11 @@ static void loadGuns(Entity *parent, cJSON *guns) e->texture = getTexture(cJSON_GetObjectItem(gun, "texture")->valuestring); e->guns[0].type = lookup(cJSON_GetObjectItem(gun, "type")->valuestring); + if (cJSON_GetObjectItem(gun, "missiles")) + { + e->missiles = cJSON_GetObjectItem(gun, "missiles")->valueint; + } + if (cJSON_GetObjectItem(gun, "aiFlags")) { e->aiFlags = flagsToLong(cJSON_GetObjectItem(gun, "aiFlags")->valuestring); diff --git a/src/battle/capitalShips.h b/src/battle/capitalShips.h index 380dfe8..edab4c5 100644 --- a/src/battle/capitalShips.h +++ b/src/battle/capitalShips.h @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern Entity *spawnEntity(void); extern void addSmallExplosion(void); extern void playBattleSound(int id, int x, int y); +extern float getAngle(int x1, int y1, int x2, int y2); extern SDL_Texture *getTexture(char *filename); extern char *readFile(char *filename); extern char *getFileLocation(char *filename); @@ -38,6 +39,8 @@ extern float getAngle(int x1, int y1, int x2, int y2); extern float mod(float n, float x); extern void applyFighterThrust(void); extern void addLargeEngineEffect(void); +extern int getDistance(int x1, int y1, int x2, int y2); +extern Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore); extern Battle battle; extern Entity *self; diff --git a/src/battle/entities.c b/src/battle/entities.c index 4f781e3..06eb561 100644 --- a/src/battle/entities.c +++ b/src/battle/entities.c @@ -90,6 +90,10 @@ void doEntities(void) doFighter(); break; + case ET_CAPITAL_SHIP: + doCapitalShip(); + break; + default: doEntity(); break; @@ -236,7 +240,7 @@ static void doEntity(void) { if (self->die) { - if (self->health <= 0 && self->die && self->alive == ALIVE_ALIVE) + if (self->health <= 0 && self->alive == ALIVE_ALIVE) { self->health = 0; self->alive = ALIVE_DYING; diff --git a/src/battle/entities.h b/src/battle/entities.h index 721369b..5976769 100644 --- a/src/battle/entities.h +++ b/src/battle/entities.h @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern void blitRotated(SDL_Texture *t, int x, int y, int angle); extern void doFighter(void); +extern void doCapitalShip(void); extern void addToGrid(Entity *e); extern void removeFromGrid(Entity *e); extern Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore); diff --git a/src/defs.h b/src/defs.h index 9c846df..631a0a7 100644 --- a/src/defs.h +++ b/src/defs.h @@ -82,6 +82,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define EF_STATIC (2 << 10) #define EF_TAKES_DAMAGE (2 << 11) #define EF_SECONDARY_TARGET (2 << 12) +#define EF_AI_TARGET (2 << 13) +#define EF_AI_LEADER (2 << 14) #define AIF_NONE 0 #define AIF_FOLLOWS_PLAYER (2 << 0) diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index 1a68ba2..cfeaa45 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -307,6 +307,7 @@ static void loadCapitalShips(cJSON *node) char **types, *name, *groupName, *type; int side, scatter, number, active; int i, numTypes; + long flags; float x, y; if (node) @@ -320,6 +321,7 @@ static void loadCapitalShips(cJSON *node) scatter = 1; active = 1; number = 1; + flags = -1; types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes); side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); @@ -351,6 +353,11 @@ static void loadCapitalShips(cJSON *node) active = cJSON_GetObjectItem(node, "active")->valueint; } + if (cJSON_GetObjectItem(node, "flags")) + { + flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring); + } + for (i = 0 ; i < number ; i++) { type = types[rand() % numTypes]; @@ -374,6 +381,11 @@ static void loadCapitalShips(cJSON *node) { STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); } + + if (flags != -1) + { + e->flags = flags; + } } node = node->next; diff --git a/src/system/lookup.c b/src/system/lookup.c index 425e49a..e304415 100644 --- a/src/system/lookup.c +++ b/src/system/lookup.c @@ -46,6 +46,7 @@ void initLookups(void) addLookup("EF_STATIC", EF_STATIC); addLookup("EF_TAKES_DAMAGE", EF_TAKES_DAMAGE); addLookup("EF_SECONDARY_TARGET", EF_SECONDARY_TARGET); + addLookup("EF_AI_TARGET", EF_AI_TARGET); addLookup("AIF_NONE", AIF_NONE); addLookup("AIF_MOVES_TO_PLAYER", AIF_MOVES_TO_PLAYER);