From 49832b114b15082a9cf86f441831288b0b350fd3 Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 27 Oct 2015 07:24:17 +0000 Subject: [PATCH] Updates to Mission Target logic. Tidying up of entity.c --- data/missions/test/test.json | 17 ++++- src/battle/ai.c | 2 +- src/battle/entities.c | 77 +++++++++++++++-------- src/battle/entities.h | 3 +- src/battle/fighters.c | 116 +++++++++++++---------------------- src/battle/fighters.h | 1 + src/battle/player.c | 53 ++++++++++++++-- src/battle/waypoints.c | 42 ++++++++++--- src/battle/waypoints.h | 5 ++ src/defs.h | 1 + src/galaxy/mission.c | 54 ++++++++++++++++ src/structs.h | 3 +- 12 files changed, 256 insertions(+), 118 deletions(-) diff --git a/data/missions/test/test.json b/data/missions/test/test.json index 1767e0c..7731afd 100644 --- a/data/missions/test/test.json +++ b/data/missions/test/test.json @@ -8,12 +8,23 @@ "type" : "Nymph", "side" : "SIDE_CSN" }, - "entities" : [ + "fighters" : [ + { + "name" : "Dart", + "type" : "Dart", + "side" : "SIDE_CSN", + "x" : 1800, + "y" : 200 + } + ], + "entitiesGroups" : [ { "name" : "Waypoint", "type" : "ET_WAYPOINT", - "x" : 100, - "y" : 100 + "number" : 10, + "x" : 640, + "y" : -10000, + "scatter" : 10000 } ] } diff --git a/src/battle/ai.c b/src/battle/ai.c index 51d22fe..297596b 100644 --- a/src/battle/ai.c +++ b/src/battle/ai.c @@ -150,7 +150,7 @@ static void findTarget(void) for (f = battle.entityHead.next ; f != NULL ; f = f->next) { - if (f->side != self->side && f->health > 0 && canAttack(f)) + if (f->type == ET_FIGHTER && f->side != self->side && f->health > 0 && canAttack(f)) { dist = getDistance(self->x, self->y, f->x, f->y); if (dist < closest) diff --git a/src/battle/entities.c b/src/battle/entities.c index 80b9d2f..1b949de 100644 --- a/src/battle/entities.c +++ b/src/battle/entities.c @@ -21,7 +21,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "entities.h" static void drawEntity(Entity *e); -static void doEntity(Entity *e, Entity *prev); +static void doEntity(Entity *prev); + +Entity *spawnEntity(void) +{ + Entity *e = malloc(sizeof(Entity)); + memset(e, 0, sizeof(Entity)); + e->id = battle.entId++; + + battle.entityTail->next = e; + battle.entityTail = e; + + return e; +} void doEntities(void) { @@ -35,48 +47,63 @@ void doEntities(void) { self = e; + if (self->target != NULL && self->target->health <= 0) + { + self->action = self->defaultAction; + self->target = NULL; + } + + self->x += self->dx; + self->y += self->dy; + + if (self != player) + { + self->x -= battle.ssx; + self->y -= battle.ssy; + } + + if (self->action != NULL) + { + if (--self->thinkTime <= 0) + { + self->thinkTime = 0; + self->action(); + } + } + switch (e->type) { case ET_FIGHTER: - doFighter(e, prev); + doFighter(prev); break; default: - doEntity(e, prev); + doEntity(prev); break; } + + prev = self; } } -static void doEntity(Entity *e, Entity *prev) +static void doEntity(Entity *prev) { - e->x += e->dx; - e->y += e->dy; - - e->x -= battle.ssx; - e->y -= battle.ssy; - - if (e->action != NULL) + if (self->health <= 0) { - if (--e->thinkTime <= 0) - { - e->action(); - } - } - - if (e->health <= 0) - { - if (e == battle.entityTail) + if (self == battle.entityTail) { battle.entityTail = prev; } - prev->next = e->next; - free(e); - e = prev; + if (self == battle.missionTarget) + { + battle.missionTarget = NULL; + } + + prev->next = self->next; + free(self); + self = prev; } - - prev = e; } void drawEntities(void) diff --git a/src/battle/entities.h b/src/battle/entities.h index 476a5ac..5cae36b 100644 --- a/src/battle/entities.h +++ b/src/battle/entities.h @@ -25,7 +25,8 @@ 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 drawFighter(Entity *e); -extern void doFighter(Entity *e, Entity *prev); +extern void doFighter(Entity *prev); extern Battle battle; extern Entity *self; +extern Entity *player; diff --git a/src/battle/fighters.c b/src/battle/fighters.c index 34a23fe..30bbcab 100644 --- a/src/battle/fighters.c +++ b/src/battle/fighters.c @@ -32,18 +32,15 @@ Entity *spawnFighter(char *name, int x, int y, int side) { Entity *f, *def; - f = malloc(sizeof(Entity)); - memset(f, 0, sizeof(Entity)); + f = spawnEntity(); def = getFighterDef(name); memcpy(f, def, sizeof(Entity)); + f->id = battle.entId; f->next = NULL; - battle.entityTail->next = f; - battle.entityTail = f; - f->x = x; f->y = y; f->side = side; @@ -153,16 +150,11 @@ static void randomizeDartGuns(Entity *dart) } } -void doFighter(Entity *f, Entity *prev) +void doFighter(Entity *prev) { if (player != NULL) { - if (f != player && f->health > 0) - { - separate(); - } - - if (f->side == player->side) + if (self->side == player->side) { battle.numAllies++; } @@ -172,92 +164,68 @@ void doFighter(Entity *f, Entity *prev) } } - if (self->target != NULL && self->target->health <= 0) + if (self != player && self->health > 0) { - self->action = self->defaultAction; - self->target = NULL; + separate(); } - if (!battle.missionTarget && f->flags & EF_MISSION_TARGET && f->health > 0) + if (self->health > 0) { - battle.missionTarget = f; - } - - f->x += f->dx; - f->y += f->dy; - - if (f != player) - { - f->x -= battle.ssx; - f->y -= battle.ssy; - } - - if (f->health > 0) - { - f->reload = MAX(f->reload - 1, 0); - f->shieldRecharge = MAX(f->shieldRecharge - 1, 0); - f->armourHit = MAX(f->armourHit - 25, 0); - f->shieldHit = MAX(f->shieldHit - 5, 0); - f->systemHit = MAX(f->systemHit - 25, 0); + self->reload = MAX(self->reload - 1, 0); + self->shieldRecharge = MAX(self->shieldRecharge - 1, 0); + self->armourHit = MAX(self->armourHit - 25, 0); + self->shieldHit = MAX(self->shieldHit - 5, 0); + self->systemHit = MAX(self->systemHit - 25, 0); if (self->thrust > 0.25) { addEngineEffect(); } - if (!f->shieldRecharge) + if (!self->shieldRecharge) { - f->shield = MIN(f->shield + 1, f->maxShield); - f->shieldRecharge = f->shieldRechargeRate; + self->shield = MIN(self->shield + 1, self->maxShield); + self->shieldRecharge = self->shieldRechargeRate; } - if (f->action == NULL && f->defaultAction != NULL) + if (self->action == NULL && self->defaultAction != NULL) { - f->action = f->defaultAction; + self->action = self->defaultAction; } } - if (f->action != NULL) + if (self->alive == ALIVE_ALIVE) { - if (--f->thinkTime <= 0) + if (self->health <= 0) { - f->thinkTime = 0; - f->action(); - } - } - - if (f->alive == ALIVE_ALIVE) - { - if (f->health <= 0) - { - f->health = 0; - f->alive = ALIVE_DYING; - f->die(); + self->health = 0; + self->alive = ALIVE_DYING; + self->die(); - if (f == battle.missionTarget) + if (self == battle.missionTarget) { battle.missionTarget = NULL; } } - else if (f->systemPower <= 0) + else if (self->systemPower <= 0) { - f->dx *= 0.99; - f->dy *= 0.99; - f->thrust = 0; - f->shield = f->maxShield = 0; - f->action = NULL; + self->dx *= 0.99; + self->dy *= 0.99; + self->thrust = 0; + self->shield = self->maxShield = 0; + self->action = NULL; - if (f->alive == ALIVE_ALIVE) + if (self->alive == ALIVE_ALIVE) { - updateObjective(f->name, TT_DISABLE); + updateObjective(self->name, TT_DISABLE); battle.stats[STAT_DISABLED]++; } } } - if (f->alive == ALIVE_DEAD) + if (self->alive == ALIVE_DEAD) { - if (f == player) + if (self == player) { battle.stats[STAT_PLAYER_KILLED]++; } @@ -265,7 +233,7 @@ void doFighter(Entity *f, Entity *prev) { if (player->alive == ALIVE_ALIVE) { - if (f->side != player->side) + if (self->side != player->side) { battle.stats[STAT_ENEMIES_KILLED]++; } @@ -277,26 +245,26 @@ void doFighter(Entity *f, Entity *prev) } } - updateObjective(f->name, TT_DESTROY); + updateObjective(self->name, TT_DESTROY); - updateCondition(f->name, TT_DESTROY); + updateCondition(self->name, TT_DESTROY); - checkTrigger(f->name, TRIGGER_KILLS); + checkTrigger(self->name, TRIGGER_KILLS); } - if (f == battle.entityTail) + if (self == battle.entityTail) { battle.entityTail = prev; } - if (f == player) + if (self == player) { player = NULL; } - prev->next = f->next; - free(f); - f = prev; + prev->next = self->next; + free(self); + self = prev; } } diff --git a/src/battle/fighters.h b/src/battle/fighters.h index 70dc095..c304d91 100644 --- a/src/battle/fighters.h +++ b/src/battle/fighters.h @@ -38,6 +38,7 @@ extern void updateCondition(char *name, int type); extern Entity *getFighterDef(char *name); extern void addHudMessage(SDL_Color c, char *format, ...); extern void checkTrigger(char *name, int type); +extern Entity *spawnEntity(void); extern App app; extern Battle battle; diff --git a/src/battle/player.c b/src/battle/player.c index 65ef66a..f5181a2 100644 --- a/src/battle/player.c +++ b/src/battle/player.c @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void selectTarget(void); static void switchGuns(void); +static void selectMissionTarget(void); static int availableGuns[BT_MAX]; @@ -100,6 +101,11 @@ void doPlayer(void) { selectTarget(); } + + if (!battle.missionTarget) + { + selectMissionTarget(); + } } player->angle = ((int)player->angle) % 360; @@ -136,20 +142,57 @@ static void selectTarget(void) { unsigned int closest = 65535; unsigned int dist = 65535; - Entity *f; + Entity *e; player->target = NULL; - for (f = battle.entityHead.next ; f != NULL ; f = f->next) + for (e = battle.entityHead.next ; e != NULL ; e = e->next) { - if (f != player && f->side != SIDE_NONE && f->side != player->side && f->alive == ALIVE_ALIVE) + if (e != player && e->type == ET_FIGHTER && e->side != player->side && e->alive == ALIVE_ALIVE) { - dist = getDistance(self->x, self->y, f->x, f->y); + dist = getDistance(self->x, self->y, e->x, e->y); if (dist < closest) { - player->target = f; + player->target = e; closest = dist; } } } } + +static void selectMissionTarget(void) +{ + unsigned int closest = 65535; + unsigned int dist = 65535; + Entity *e; + + battle.missionTarget = NULL; + + for (e = battle.entityHead.next ; e != NULL ; e = e->next) + { + if (e->flags & EF_MISSION_TARGET && e->alive == ALIVE_ALIVE) + { + if (battle.missionTarget == NULL) + { + battle.missionTarget = e; + } + else if (battle.missionTarget->type == ET_WAYPOINT && e->type != ET_WAYPOINT) + { + battle.missionTarget = e; + } + else if (battle.missionTarget->type != ET_WAYPOINT) + { + dist = getDistance(self->x, self->y, e->x, e->y); + if (dist < closest) + { + battle.missionTarget = e; + closest = dist; + } + } + else if (battle.missionTarget->type == ET_WAYPOINT && e->type == ET_WAYPOINT && e->id < battle.missionTarget->id) + { + battle.missionTarget = e; + } + } + } +} diff --git a/src/battle/waypoints.c b/src/battle/waypoints.c index f7e61c9..0c77c6a 100644 --- a/src/battle/waypoints.c +++ b/src/battle/waypoints.c @@ -20,28 +20,54 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "waypoints.h" -static void rotate(void); +static void think(void); +static int teamMatesClose(void); Entity *spawnWaypoint(void) { - Entity *waypoint = malloc(sizeof(Entity)); - memset(waypoint, 0, sizeof(Entity)); - battle.entityTail->next = waypoint; - battle.entityTail = waypoint; + Entity *waypoint = spawnEntity(); waypoint->type = ET_WAYPOINT; waypoint->health = waypoint->maxHealth = FPS; waypoint->texture = getTexture("gfx/entities/waypoint.png"); - waypoint->action = rotate; + waypoint->flags = EF_MISSION_TARGET; + waypoint->action = think; return waypoint; } -static void rotate(void) +static void think(void) { - self->angle += 0.1; + self->thinkTime = 4; + + self->angle++; if (self->angle >= 360) { self -= 360; } + + if (getDistance(player->x, player->y, self->x, self->y) <= 32 && teamMatesClose()) + { + self->health = 0; + } +} + +static int teamMatesClose(void) +{ + Entity *e; + + for (e = battle.entityHead.next ; e != NULL ; e = e->next) + { + if (e->type == ET_FIGHTER && e->side == player->side) + { + if (getDistance(player->x, player->y, e->x, e->y) > 350) + { + addHudMessage(colors.cyan, "Cannot activate waypoint - team mates too far away"); + self->thinkTime = FPS; + return 0; + } + } + } + + return 1; } diff --git a/src/battle/waypoints.h b/src/battle/waypoints.h index f7b2553..2f7d614 100644 --- a/src/battle/waypoints.h +++ b/src/battle/waypoints.h @@ -24,6 +24,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../structs.h" extern SDL_Texture *getTexture(char *filename); +extern int getDistance(int x1, int y1, int x2, int y2); +extern void addHudMessage(SDL_Color c, char *format, ...); +extern Entity *spawnEntity(void); extern Battle battle; +extern Colors colors; extern Entity *self; +extern Entity *player; diff --git a/src/defs.h b/src/defs.h index 39e705b..cf7deb5 100644 --- a/src/defs.h +++ b/src/defs.h @@ -56,6 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define EF_DISABLE (2 << 1) #define EF_IMMORTAL (2 << 2) #define EF_MISSION_TARGET (2 << 3) +#define EF_INVISIBLE (2 << 4) enum { diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index 9f2c687..0050d70 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -26,6 +26,7 @@ static void loadPlayer(cJSON *node); static void loadFighters(cJSON *node); static void loadFighterGroups(cJSON *node); static void loadEntities(cJSON *node); +static void loadEntityGroups(cJSON *node); static unsigned long hashcode(const char *str); static char **toFighterTypeArray(char *types, int *numTypes); @@ -61,6 +62,8 @@ void loadMission(char *filename) loadEntities(cJSON_GetObjectItem(root, "entities")); + loadEntityGroups(cJSON_GetObjectItem(root, "entityGroups")); + STRNCPY(music, cJSON_GetObjectItem(root, "music")->valuestring, MAX_NAME_LENGTH); cJSON_Delete(root); @@ -283,6 +286,57 @@ static void loadEntities(cJSON *node) } } +static void loadEntityGroups(cJSON *node) +{ + Entity *e; + char *name; + int i, type, x, y, scatter, number; + long flags; + + scatter = 1; + flags = 0; + + if (node) + { + node = node->child; + + while (node) + { + type = lookup(cJSON_GetObjectItem(node, "type")->valuestring); + name = cJSON_GetObjectItem(node, "name")->valuestring; + number = cJSON_GetObjectItem(node, "number")->valueint; + x = cJSON_GetObjectItem(node, "x")->valueint; + y = cJSON_GetObjectItem(node, "y")->valueint; + + if (cJSON_GetObjectItem(node, "flags")) + { + flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring); + } + + for (i = 0 ; i < number ; i++) + { + switch (type) + { + case ET_WAYPOINT: + e = spawnWaypoint(); + break; + } + + STRNCPY(e->name, name, MAX_NAME_LENGTH); + e->id = battle.entId++; + e->x = x; + e->y = y; + e->flags = flags; + + e->x += (rand() % scatter) - (rand() % scatter); + e->y += (rand() % scatter) - (rand() % scatter); + } + + node = node->next; + } + } +} + static char **toFighterTypeArray(char *types, int *numTypes) { int i; diff --git a/src/structs.h b/src/structs.h index 8654abf..20936aa 100644 --- a/src/structs.h +++ b/src/structs.h @@ -71,7 +71,7 @@ struct Weapon { struct Entity { int type; char name[MAX_NAME_LENGTH]; - int active; + int id; int side; float x; float y; @@ -213,6 +213,7 @@ struct StarSystem { }; typedef struct { + int entId; float ssx; float ssy; int numAllies;