diff --git a/common.mk b/common.mk index a2c3139..9be17b4 100644 --- a/common.mk +++ b/common.mk @@ -10,7 +10,7 @@ DEPS += defs.h structs.h OBJS += ai.o OBJS += battle.o bullets.o -OBJS += challenges.o cJSON.o +OBJS += capitalShips.o challenges.o cJSON.o OBJS += draw.o OBJS += effects.o entities.o extractionPoint.o OBJS += fighters.o diff --git a/data/capitalShips/list.json b/data/capitalShips/list.json new file mode 100644 index 0000000..e4ef1a1 --- /dev/null +++ b/data/capitalShips/list.json @@ -0,0 +1,3 @@ +[ + "data/capitalShips/test.json" +] diff --git a/data/capitalShips/test.json b/data/capitalShips/test.json new file mode 100644 index 0000000..c3a5403 --- /dev/null +++ b/data/capitalShips/test.json @@ -0,0 +1,46 @@ +{ + "name" : "Test Frigate", + "health" : 1, + "shield" : 500, + "shieldRechargeRate" : 60, + "texture" : "gfx/capitalShips/test/body.png", + "components" : [ + { + "health" : 100, + "texture" : "gfx/capitalShips/test/core.png", + "x" : 0, + "y" : -100, + "flags" : "EF_TAKES_DAMAGE" + }, + { + "health" : 100, + "texture" : "gfx/capitalShips/test/engine1.png", + "x" : -112, + "y" : 281, + "flags" : "EF_TAKES_DAMAGE" + }, + { + "health" : 100, + "texture" : "gfx/capitalShips/test/engine1.png", + "x" : 112, + "y" : 281, + "flags" : "EF_TAKES_DAMAGE" + }, + { + "health" : 100, + "texture" : "gfx/capitalShips/test/engine2.png", + "x" : -34, + "y" : 268, + "flags" : "EF_TAKES_DAMAGE" + }, + { + "health" : 100, + "texture" : "gfx/capitalShips/test/engine2.png", + "x" : 34, + "y" : 268, + "flags" : "EF_TAKES_DAMAGE" + } + ], + "guns" : [ + ] +} diff --git a/gfx/capitalShips/test/body.png b/gfx/capitalShips/test/body.png new file mode 100644 index 0000000..e3e387d Binary files /dev/null and b/gfx/capitalShips/test/body.png differ diff --git a/gfx/capitalShips/test/core.png b/gfx/capitalShips/test/core.png new file mode 100644 index 0000000..f0d36ad Binary files /dev/null and b/gfx/capitalShips/test/core.png differ diff --git a/gfx/capitalShips/test/engine1.png b/gfx/capitalShips/test/engine1.png new file mode 100644 index 0000000..2767de7 Binary files /dev/null and b/gfx/capitalShips/test/engine1.png differ diff --git a/gfx/capitalShips/test/engine2.png b/gfx/capitalShips/test/engine2.png new file mode 100644 index 0000000..0bde9e5 Binary files /dev/null and b/gfx/capitalShips/test/engine2.png differ diff --git a/src/battle/capitalShips.c b/src/battle/capitalShips.c new file mode 100644 index 0000000..13a544d --- /dev/null +++ b/src/battle/capitalShips.c @@ -0,0 +1,187 @@ +/* +Copyright (C) 2015 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "capitalShips.h" + +static void componentDie(void); +static void loadCapitalShipDef(char *filename); +static void loadComponents(Entity *parent, cJSON *components); +static void loadGuns(Entity *parent, cJSON *guns); + +static Entity defHead, *defTail; + +Entity *spawnCapitalShip(char *name, int x, int y, int side) +{ + Entity *def, *e, *capitalShip; + + for (def = defHead.next ; def != NULL ; def = def->next) + { + if (strcmp(def->name, name) == 0) + { + e = spawnEntity(); + + memcpy(e, def, sizeof(Entity)); + + e->id = battle.entId; + e->next = NULL; + + e->x = x; + e->y = y; + e->side = side; + + if (e->type == ET_CAPITAL_SHIP) + { + capitalShip = e; + } + else + { + e->owner = capitalShip; + } + } + } + + return capitalShip; +} + +static void componentDie(void) +{ + self->alive = ALIVE_DEAD; + addSmallExplosion(); + playBattleSound(SND_EXPLOSION_1 + rand() % 4, self->x, self->y); +} + +static void die(void) +{ +} + +void loadCapitalShipDefs(void) +{ + cJSON *root, *node; + char *text; + + text = readFile(getFileLocation("data/capitalShips/list.json")); + root = cJSON_Parse(text); + + memset(&defHead, 0, sizeof(Entity)); + defTail = &defHead; + + for (node = root->child ; node != NULL ; node = node->next) + { + loadCapitalShipDef(node->valuestring); + } + + cJSON_Delete(root); + free(text); +} + +static void loadCapitalShipDef(char *filename) +{ + cJSON *root; + char *text; + Entity *e; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", filename); + + text = readFile(getFileLocation(filename)); + + e = malloc(sizeof(Entity)); + memset(e, 0, sizeof(Entity)); + defTail->next = e; + defTail = e; + + e->type = ET_CAPITAL_SHIP; + e->active = 1; + + root = cJSON_Parse(text); + + STRNCPY(e->name, cJSON_GetObjectItem(root, "name")->valuestring, MAX_NAME_LENGTH); + STRNCPY(e->defName, e->name, MAX_NAME_LENGTH); + e->health = e->maxHealth = cJSON_GetObjectItem(root, "health")->valueint; + e->shield = e->maxShield = cJSON_GetObjectItem(root, "shield")->valueint; + e->shieldRechargeRate = cJSON_GetObjectItem(root, "shieldRechargeRate")->valueint; + e->texture = getTexture(cJSON_GetObjectItem(root, "texture")->valuestring); + + e->die = die; + + SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); + + loadComponents(e, cJSON_GetObjectItem(root, "components")); + + loadGuns(e, cJSON_GetObjectItem(root, "guns")); + + cJSON_Delete(root); + free(text); +} + +static void loadComponents(Entity *parent, cJSON *components) +{ + Entity *e; + cJSON *component; + + if (components) + { + component = components->child; + + while (component) + { + e = malloc(sizeof(Entity)); + memset(e, 0, sizeof(Entity)); + defTail->next = e; + defTail = e; + + e->active = 1; + + e->type = ET_CAPITAL_SHIP_COMPONENT; + STRNCPY(e->name, parent->name, MAX_NAME_LENGTH); + STRNCPY(e->defName, parent->defName, MAX_NAME_LENGTH); + e->health = e->maxHealth = cJSON_GetObjectItem(component, "health")->valueint; + e->offsetX = cJSON_GetObjectItem(component, "x")->valueint; + e->offsetY = cJSON_GetObjectItem(component, "y")->valueint; + e->texture = getTexture(cJSON_GetObjectItem(component, "texture")->valuestring); + + SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); + + if (cJSON_GetObjectItem(component, "flags")) + { + e->flags = flagsToLong(cJSON_GetObjectItem(component, "flags")->valuestring); + } + + e->die = componentDie; + + component = component->next; + } + } +} + +static void loadGuns(Entity *parent, cJSON *guns) +{ +} + +void destroyCapitalShipDefs(void) +{ + Entity *e; + + while (defHead.next) + { + e = defHead.next; + defHead.next = e->next; + free(e); + } +} diff --git a/src/battle/capitalShips.h b/src/battle/capitalShips.h new file mode 100644 index 0000000..5b0c4b5 --- /dev/null +++ b/src/battle/capitalShips.h @@ -0,0 +1,34 @@ +/* +Copyright (C) 2015 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +#include "../json/cJSON.h" + +extern Entity *spawnEntity(void); +extern void addSmallExplosion(void); +extern void playBattleSound(int id, int x, int y); +extern SDL_Texture *getTexture(char *filename); +extern char *readFile(char *filename); +extern char *getFileLocation(char *filename); +extern long flagsToLong(char *flags); + +extern Battle battle; +extern Entity *self; diff --git a/src/defs.h b/src/defs.h index 03d7089..fb270a9 100644 --- a/src/defs.h +++ b/src/defs.h @@ -80,6 +80,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define EF_RETREATING (2 << 8) #define EF_NO_EPIC (2 << 9) #define EF_STATIC (2 << 10) +#define EF_TAKES_DAMAGE (2 << 11) #define AIF_NONE 0 #define AIF_FOLLOWS_PLAYER (2 << 0) @@ -105,7 +106,10 @@ enum ET_FIGHTER, ET_ITEM, ET_WAYPOINT, - ET_EXTRACTION_POINT + ET_EXTRACTION_POINT, + ET_CAPITAL_SHIP_COMPONENT, + ET_CAPITAL_SHIP_GUN, + ET_CAPITAL_SHIP }; enum diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index ec2fd69..1a68ba2 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -23,10 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void loadObjectives(cJSON *node); static void loadPlayer(cJSON *node); static void loadFighters(cJSON *node); +static void loadCapitalShips(cJSON *node); static void loadEntities(cJSON *node); static void loadItems(cJSON *node); static unsigned long hashcode(const char *str); -static char **toFighterTypeArray(char *types, int *numTypes); +static char **toTypeArray(char *types, int *numTypes); static void loadEpicData(cJSON *node); void loadMission(char *filename) @@ -55,6 +56,8 @@ void loadMission(char *filename) loadFighters(cJSON_GetObjectItem(root, "fighters")); + loadCapitalShips(cJSON_GetObjectItem(root, "capitalShips")); + loadEntities(cJSON_GetObjectItem(root, "entities")); loadItems(cJSON_GetObjectItem(root, "items")); @@ -216,7 +219,7 @@ static void loadFighters(cJSON *node) active = 1; number = 1; - types = toFighterTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes); + types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes); side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); x = cJSON_GetObjectItem(node, "x")->valuedouble * GRID_CELL_WIDTH; y = cJSON_GetObjectItem(node, "y")->valuedouble * GRID_CELL_HEIGHT; @@ -262,8 +265,11 @@ static void loadFighters(cJSON *node) f = spawnFighter(type, x, y, side); - f->x += (rand() % scatter) - (rand() % scatter); - f->y += (rand() % scatter) - (rand() % scatter); + if (scatter > 1) + { + f->x += (rand() % scatter) - (rand() % scatter); + f->y += (rand() % scatter) - (rand() % scatter); + } f->active = active; @@ -295,6 +301,88 @@ static void loadFighters(cJSON *node) } } +static void loadCapitalShips(cJSON *node) +{ + Entity *e; + char **types, *name, *groupName, *type; + int side, scatter, number, active; + int i, numTypes; + float x, y; + + if (node) + { + node = node->child; + + while (node) + { + name = NULL; + groupName = NULL; + scatter = 1; + active = 1; + number = 1; + + types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes); + side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); + x = cJSON_GetObjectItem(node, "x")->valuedouble * GRID_CELL_WIDTH; + y = cJSON_GetObjectItem(node, "y")->valuedouble * GRID_CELL_HEIGHT; + + if (cJSON_GetObjectItem(node, "name")) + { + name = cJSON_GetObjectItem(node, "name")->valuestring; + } + + if (cJSON_GetObjectItem(node, "groupName")) + { + groupName = cJSON_GetObjectItem(node, "groupName")->valuestring; + } + + if (cJSON_GetObjectItem(node, "number")) + { + number = cJSON_GetObjectItem(node, "number")->valueint; + } + + if (cJSON_GetObjectItem(node, "scatter")) + { + scatter = cJSON_GetObjectItem(node, "scatter")->valueint; + } + + if (cJSON_GetObjectItem(node, "active")) + { + active = cJSON_GetObjectItem(node, "active")->valueint; + } + + for (i = 0 ; i < number ; i++) + { + type = types[rand() % numTypes]; + + e = spawnCapitalShip(type, x, y, side); + + if (scatter > 1) + { + e->x += (rand() % scatter) - (rand() % scatter); + e->y += (rand() % scatter) - (rand() % scatter); + } + + e->active = active; + + if (name) + { + STRNCPY(e->name, name, MAX_NAME_LENGTH); + } + + if (groupName) + { + STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); + } + } + + node = node->next; + + free(types); + } + } +} + static void loadEntities(cJSON *node) { Entity *e; @@ -374,8 +462,11 @@ static void loadEntities(cJSON *node) e->x = x; e->y = y; - e->x += (rand() % scatter) - (rand() % scatter); - e->y += (rand() % scatter) - (rand() % scatter); + if (scatter > 1) + { + e->x += (rand() % scatter) - (rand() % scatter); + e->y += (rand() % scatter) - (rand() % scatter); + } e->active = active; @@ -465,8 +556,11 @@ static void loadItems(cJSON *node) e->y = y; e->active = active; - e->x += (rand() % scatter) - (rand() % scatter); - e->y += (rand() % scatter) - (rand() % scatter); + if (scatter > 1) + { + e->x += (rand() % scatter) - (rand() % scatter); + e->y += (rand() % scatter) - (rand() % scatter); + } SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); } @@ -476,7 +570,7 @@ static void loadItems(cJSON *node) } } -static char **toFighterTypeArray(char *types, int *numTypes) +static char **toTypeArray(char *types, int *numTypes) { int i; char **typeArray, *type; diff --git a/src/galaxy/mission.h b/src/galaxy/mission.h index 0142960..2667899 100644 --- a/src/galaxy/mission.h +++ b/src/galaxy/mission.h @@ -28,6 +28,7 @@ extern long lookup(char *name); extern char *readFile(char *filename); extern SDL_Texture *getTexture(char *filename); extern Entity *spawnFighter(char *name, int x, int y, int side); +extern Entity *spawnCapitalShip(char *name, int x, int y, int side); extern void startSectionTransition(void); extern void endSectionTransition(void); extern void playMusic(char *filename); diff --git a/src/structs.h b/src/structs.h index 499ecd9..a757746 100644 --- a/src/structs.h +++ b/src/structs.h @@ -79,6 +79,8 @@ struct Entity { int side; float x; float y; + int offsetX; + int offsetY; int w; int h; float dx; diff --git a/src/system/init.c b/src/system/init.c index 39b04e8..e78def6 100644 --- a/src/system/init.c +++ b/src/system/init.c @@ -120,6 +120,8 @@ void initGameSystem(void) loadFighterDefs(); + loadCapitalShipDefs(); + loadItemDefs(); initBulletDefs(); @@ -219,6 +221,8 @@ void cleanup(void) destroyFighterDefs(); + destroyCapitalShipDefs(); + destroyBulletDefs(); destroyItemDefs(); diff --git a/src/system/init.h b/src/system/init.h index 4ab9fff..672801b 100644 --- a/src/system/init.h +++ b/src/system/init.h @@ -32,6 +32,7 @@ extern int writeFile(char *filename, char *data); extern char *getSaveFilePath(char *filename); extern void initSounds(void); extern void loadFighterDefs(void); +extern void loadCapitalShipDefs(void); extern void loadItemDefs(void); extern void initFonts(void); extern void initBulletDefs(void); @@ -45,6 +46,7 @@ extern void destroyFonts(void); extern void destroySounds(void); extern void destroyGame(void); extern void destroyFighterDefs(void); +extern void destroyCapitalShipDefs(void); extern void destroyBulletDefs(void); extern void destroyItemDefs(void); extern void destroyStarSystems(void); diff --git a/src/system/lookup.c b/src/system/lookup.c index c4620ab..20e5435 100644 --- a/src/system/lookup.c +++ b/src/system/lookup.c @@ -32,6 +32,7 @@ void initLookups(void) addLookup("ET_WAYPOINT", ET_WAYPOINT); addLookup("ET_EXTRACTION_POINT", ET_EXTRACTION_POINT); + addLookup("ET_CAPITAL_SHIP", ET_CAPITAL_SHIP); addLookup("EF_NO_KILL", EF_NO_KILL); addLookup("EF_DISABLED", EF_DISABLED); @@ -43,6 +44,7 @@ void initLookups(void) addLookup("EF_COLLECTS_ITEMS", EF_COLLECTS_ITEMS); addLookup("EF_NO_EPIC", EF_NO_EPIC); addLookup("EF_STATIC", EF_STATIC); + addLookup("EF_TAKES_DAMAGE", EF_TAKES_DAMAGE); addLookup("AIF_NONE", AIF_NONE); addLookup("AIF_MOVES_TO_PLAYER", AIF_MOVES_TO_PLAYER);