diff --git a/common.mk b/common.mk index ebd2cba..84a8ad0 100644 --- a/common.mk +++ b/common.mk @@ -24,7 +24,7 @@ OBJS += objectives.o options.o OBJS += player.o OBJS += quadtree.o OBJS += radar.o resources.o rope.o -OBJS += save.o script.o sound.o starfield.o starSystems.o stats.o +OBJS += save.o script.o sound.o spawners.o starfield.o starSystems.o stats.o OBJS += testMission.o textures.o text.o title.o transition.o trophies.o OBJS += util.o OBJS += waypoints.o widgets.o diff --git a/src/battle/battle.c b/src/battle/battle.c index 62149b9..2607f15 100644 --- a/src/battle/battle.c +++ b/src/battle/battle.c @@ -47,6 +47,7 @@ void initBattle(void) battle.effectTail = &battle.effectHead; battle.objectiveTail = &battle.objectiveHead; battle.locationTail = &battle.locationHead; + battle.spawnerTail = &battle.spawnerHead; app.delegate.logic = &logic; app.delegate.draw = &draw; @@ -140,6 +141,8 @@ static void doBattle(void) doStars(ssx, ssy); doBullets(); + + doSpawners(); doEntities(); @@ -383,6 +386,7 @@ void destroyBattle(void) Effect *e; Objective *o; Location *l; + Spawner *s; while (battle.entityHead.next) { @@ -431,6 +435,14 @@ void destroyBattle(void) free(l); } battle.locationTail = &battle.locationHead; + + while (battle.spawnerHead.next) + { + s = battle.spawnerHead.next; + battle.spawnerHead.next = s->next; + free(s); + } + battle.spawnerTail = &battle.spawnerHead; cJSON_Delete(battle.missionJSON); diff --git a/src/battle/battle.h b/src/battle/battle.h index 975a5bb..3464db7 100644 --- a/src/battle/battle.h +++ b/src/battle/battle.h @@ -84,6 +84,7 @@ extern void initChallengeHome(void); extern void updateAccuracyStats(unsigned int *stats); extern void clearInput(void); extern void runScriptTimeFunctions(void); +extern void doSpawners(void); extern App app; extern Battle battle; diff --git a/src/battle/spawners.c b/src/battle/spawners.c new file mode 100644 index 0000000..326f161 --- /dev/null +++ b/src/battle/spawners.c @@ -0,0 +1,69 @@ +/* +Copyright (C) 2015-2016 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 "spawners.h" + +void doSpawners(void) +{ + Entity *e; + Spawner *s; + char *type; + int i, num; + + for (s = battle.spawnerHead.next ; s != NULL ; s = s->next) + { + if (s->active && --s->time <= 0) + { + num = s->step; + + if (s->limit) + { + num = MIN(s->step, s->total); + + s->total -= num; + } + + for (i = 0 ; i < num ; i++) + { + type = s->types[rand() % s->numTypes]; + + e = spawnFighter(type, 0, 0, s->side); + + if (s->offscreen) + { + e->x = player->x; + e->y = player->y; + } + else + { + e->x = rand() % 2 ? 0 : BATTLE_AREA_WIDTH; + e->y = rand() % 2 ? 0 : BATTLE_AREA_HEIGHT; + } + + e->x += (rand() % 2) ? -SCREEN_WIDTH : SCREEN_WIDTH; + e->y += (rand() % 2) ? -SCREEN_HEIGHT : SCREEN_HEIGHT; + + e->aiFlags |= AIF_UNLIMITED_RANGE; + } + + s->time = s->interval; + } + } +} diff --git a/src/battle/spawners.h b/src/battle/spawners.h new file mode 100644 index 0000000..f6f44b9 --- /dev/null +++ b/src/battle/spawners.h @@ -0,0 +1,26 @@ +/* +Copyright (C) 2015-2016 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" + +extern Entity *spawnFighter(char *name, int x, int y, int side); + +extern Battle battle; +extern Entity *player; diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index 69700eb..9f761ea 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -27,6 +27,7 @@ static void loadCapitalShips(cJSON *node); static void loadEntities(cJSON *node); static void loadItems(cJSON *node); static void loadLocations(cJSON *node); +static void loadSpawners(cJSON *node); static unsigned long hashcode(const char *str); static void loadEpicData(cJSON *node); static char *getAutoBackground(char *filename); @@ -160,6 +161,8 @@ void loadMission(char *filename) loadItems(cJSON_GetObjectItem(root, "items")); loadLocations(cJSON_GetObjectItem(root, "locations")); + + loadSpawners(cJSON_GetObjectItem(root, "spawners")); if (cJSON_GetObjectItem(root, "epic")) { @@ -757,14 +760,43 @@ static void loadLocations(cJSON *node) STRNCPY(l->name, cJSON_GetObjectItem(node, "name")->valuestring, MAX_NAME_LENGTH); l->x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; l->y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; - l->size = cJSON_GetObjectItem(node, "size")->valueint; - - active = getJSONValue(node, "active", 1); + l->active = active = getJSONValue(node, "active", 1); l->x += (SCREEN_WIDTH / 2); l->y += (SCREEN_HEIGHT / 2); - l->active = active; + + + node = node->next; + } + } +} + +static void loadSpawners(cJSON *node) +{ + int active; + Spawner *s; + + if (node) + { + node = node->child; + + while (node) + { + s = malloc(sizeof(Spawner)); + memset(s, 0, sizeof(Spawner)); + battle.spawnerTail->next = s; + battle.spawnerTail = s; + + STRNCPY(s->name, cJSON_GetObjectItem(node, "name")->valuestring, MAX_NAME_LENGTH); + s->types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &s->numTypes); + s->side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); + s->interval = cJSON_GetObjectItem(node, "interval")->valueint * FPS; + s->limit = cJSON_GetObjectItem(node, "limit")->valueint; + s->total = cJSON_GetObjectItem(node, "total")->valueint; + s->step = cJSON_GetObjectItem(node, "step")->valueint; + s->offscreen = getJSONValue(node, "offscreen", 0); + s->active = active = getJSONValue(node, "active", 1); node = node->next; } diff --git a/src/structs.h b/src/structs.h index 334d792..9bbc0f8 100644 --- a/src/structs.h +++ b/src/structs.h @@ -26,6 +26,7 @@ typedef struct Entity Entity; typedef struct Bullet Bullet; typedef struct Debris Debris; typedef struct Effect Effect; +typedef struct Spawner Spawner; typedef struct Objective Objective; typedef struct StarSystem StarSystem; typedef struct Challenge Challenge; @@ -303,6 +304,21 @@ struct Quadtree { Quadtree *node[4]; }; +struct Spawner { + char name[MAX_NAME_LENGTH]; + char **types; + int numTypes; + int side; + int time; + int interval; + int limit; + int total; + int step; + int offscreen; + int active; + Spawner *next; +}; + typedef struct { int entId; SDL_Point camera; @@ -332,6 +348,7 @@ typedef struct { Effect effectHead, *effectTail; Objective objectiveHead, *objectiveTail; Location locationHead, *locationTail; + Spawner spawnerHead, *spawnerTail; struct cJSON *missionJSON; unsigned int stats[STAT_MAX]; Quadtree quadtree;