From 0a69dd0e5e1ccaa2e7e5503f909b212bcc314708 Mon Sep 17 00:00:00 2001 From: Steve Date: Sat, 12 Mar 2016 18:22:48 +0000 Subject: [PATCH] Merge from develop. --- data/challenges/10.json | 60 +++++++ data/fighters/rook.json | 5 + data/missions/alba/01 - patrol #1.json | 8 +- data/missions/alba/02 - patrol #2.json | 6 + data/missions/alba/03 - patrol #3.json | 6 + .../coyote/03 - coyote assault #3.json | 4 +- .../granada/02 - suspect packages #2.json | 10 +- .../granada/03 - suspect packages #3.json | 6 + .../rothan/01 - rothan defence #1.json | 3 +- .../rothan/02 - rothan defence #2.json | 156 ++++++++++++++++++ gfx/entities/waypoint.png | Bin 15204 -> 17675 bytes locale/tbftss.pot | 52 +++++- src/battle/ai.c | 6 +- src/battle/battle.c | 10 +- src/battle/battle.h | 1 + src/battle/capitalShips.c | 4 + src/battle/fighters.c | 40 +++++ src/battle/fighters.h | 1 + src/battle/hud.c | 14 +- src/battle/hud.h | 1 + src/battle/items.c | 1 + src/battle/jumpgate.c | 24 ++- src/battle/quadtree.c | 29 ++-- src/battle/script.c | 89 +++++++++- src/battle/script.h | 3 + src/battle/waypoints.c | 30 ++-- src/challenges/challenges.c | 6 + src/defs.h | 1 + src/galaxy/mission.c | 74 +++------ src/galaxy/mission.h | 2 +- src/main.c | 5 +- src/structs.h | 1 + src/system/i18n.c | 2 +- src/system/init.c | 6 +- src/system/init.h | 1 + src/system/lookup.c | 1 + src/system/resources.c | 19 ++- src/system/util.c | 32 ++++ src/system/widgets.c | 6 + 39 files changed, 615 insertions(+), 110 deletions(-) create mode 100644 data/challenges/10.json create mode 100644 data/missions/rothan/02 - rothan defence #2.json diff --git a/data/challenges/10.json b/data/challenges/10.json new file mode 100644 index 0000000..53e2535 --- /dev/null +++ b/data/challenges/10.json @@ -0,0 +1,60 @@ +{ + "name" : "Rescue Civilians", + "description" : "Rescue Civilians", + "background" : "AUTO", + "planet" : "AUTO", + "music" : "AUTO", + "player" : { + "type" : "Tug", + "side" : "SIDE_ALLIES", + "pilot" : "-", + "squadron" : "-", + "x" : 25, + "y" : 25 + }, + "challenge" : { + "rescueLimit" : 8, + "timeLimit" : 300, + "challenges" : [ + { + "type" : "CHALLENGE_RESCUE", + "value" : 4 + }, + { + "type" : "CHALLENGE_RESCUE", + "value" : 5 + }, + { + "type" : "CHALLENGE_RESCUE", + "value" : 8 + } + ] + }, + "fighters" : [ + { + "types" : "Civilian", + "x" : 25, + "y" : 25, + "side" : "SIDE_ALLIES", + "flags" : "+EF_DISABLED", + "number" : 8, + "scatter" : 5000 + } + ], + "entities" : [ + { + "name" : "Jumpgate", + "type" : "ET_JUMPGATE", + "x" : 25, + "y" : 25 + } + ], + "script" : [ + { + "function" : "INTERVAL 30", + "lines" : [ + "SPAWN_FIGHTERS Dart SIDE_PIRATE 1 OFFSCREEN" + ] + } + ] +} diff --git a/data/fighters/rook.json b/data/fighters/rook.json index 40d9295..f1974e4 100644 --- a/data/fighters/rook.json +++ b/data/fighters/rook.json @@ -7,6 +7,11 @@ "shieldRechargeRate" : 45, "texture" : "gfx/fighters/rook.png", "guns" : [ + { + "type" : "BT_PLASMA", + "x" : 0, + "y" : 0 + }, { "type" : "BT_PLASMA", "x" : -9, diff --git a/data/missions/alba/01 - patrol #1.json b/data/missions/alba/01 - patrol #1.json index 8fcb918..34495c5 100644 --- a/data/missions/alba/01 - patrol #1.json +++ b/data/missions/alba/01 - patrol #1.json @@ -8,7 +8,7 @@ "manualComplete" : 1, "objectives" : [ { - "description" : "Check all wayponts", + "description" : "Check all waypoints", "targetName" : "Waypoint", "targetValue" : 5, "targetType" : "TT_WAYPOINT" @@ -42,6 +42,12 @@ } ], "script" : [ + { + "function" : "TIME 0", + "lines" : [ + "ACTIVATE_NEXT_WAYPOINT" + ] + }, { "function" : "Waypoint #2", "lines" : [ diff --git a/data/missions/alba/02 - patrol #2.json b/data/missions/alba/02 - patrol #2.json index f586241..74a8b56 100644 --- a/data/missions/alba/02 - patrol #2.json +++ b/data/missions/alba/02 - patrol #2.json @@ -59,6 +59,12 @@ } ], "script" : [ + { + "function" : "TIME 0", + "lines" : [ + "ACTIVATE_NEXT_WAYPOINT" + ] + }, { "function" : "Waypoint #3", "lines" : [ diff --git a/data/missions/alba/03 - patrol #3.json b/data/missions/alba/03 - patrol #3.json index fe1ccb2..32e6290 100644 --- a/data/missions/alba/03 - patrol #3.json +++ b/data/missions/alba/03 - patrol #3.json @@ -45,6 +45,12 @@ } ], "script" : [ + { + "function" : "TIME 0", + "lines" : [ + "ACTIVATE_NEXT_WAYPOINT" + ] + }, { "function" : "TIME 3", "lines" : [ diff --git a/data/missions/coyote/03 - coyote assault #3.json b/data/missions/coyote/03 - coyote assault #3.json index 1d71700..74e6198 100644 --- a/data/missions/coyote/03 - coyote assault #3.json +++ b/data/missions/coyote/03 - coyote assault #3.json @@ -74,7 +74,7 @@ "type" : "ET_JUMPGATE", "x" : 25, "y" : 25, - "systemPower" : 0 + "flags" : "+EF_DISABLED" } ], "script" : [ @@ -99,7 +99,7 @@ "MSG_BOX Dodds;Estelle, we've got this. We can take them.", "MSG_BOX de Winter;We're taking too many losses, Dodds. Fall back now, that's an order.", "WAIT_MSG_BOX", - "ACTIVATE_JUMPGATE", + "ACTIVATE_JUMPGATE 1", "RETREAT_ALLIES" ] } diff --git a/data/missions/granada/02 - suspect packages #2.json b/data/missions/granada/02 - suspect packages #2.json index 5e6a208..2f76c94 100644 --- a/data/missions/granada/02 - suspect packages #2.json +++ b/data/missions/granada/02 - suspect packages #2.json @@ -110,7 +110,7 @@ "type" : "ET_JUMPGATE", "x" : 10, "y" : 8, - "systemPower" : 0 + "flags" : "+EF_DISABLED" } ], "items" : [ @@ -126,6 +126,12 @@ } ], "script" : [ + { + "function" : "TIME 0", + "lines" : [ + "ACTIVATE_NEXT_WAYPOINT" + ] + }, { "function" : "Waypoint #2", "lines" : [ @@ -153,7 +159,7 @@ "WAIT 2", "MSG_BOX Tug;Tow cable attached. Ready to head home.", "MSG_BOX Carr;We're done here. Let's bring our mystery guest in.", - "ACTIVATE_JUMPGATE", + "ACTIVATE_JUMPGATE 1", "WAIT 20", "ACTIVATE_ENTITIES Dart", "ACTIVATE_OBJECTIVES Destroy intercepting Darts", diff --git a/data/missions/granada/03 - suspect packages #3.json b/data/missions/granada/03 - suspect packages #3.json index 87663cf..ef8e8e5 100644 --- a/data/missions/granada/03 - suspect packages #3.json +++ b/data/missions/granada/03 - suspect packages #3.json @@ -126,6 +126,12 @@ } ], "script" : [ + { + "function" : "TIME 0", + "lines" : [ + "ACTIVATE_NEXT_WAYPOINT" + ] + }, { "function" : "Waypoint #1", "lines" : [ diff --git a/data/missions/rothan/01 - rothan defence #1.json b/data/missions/rothan/01 - rothan defence #1.json index d762c03..ea40cb3 100644 --- a/data/missions/rothan/01 - rothan defence #1.json +++ b/data/missions/rothan/01 - rothan defence #1.json @@ -75,8 +75,7 @@ "y" : 25, "number" : 12, "scatter" : 5000, - "systemPower" : 0, - "flags" : "+EF_NO_KILL+EF_MISSION_TARGET" + "flags" : "+EF_DISABLED+EF_NO_KILL+EF_MISSION_TARGET" }, { "name" : "CSN Tug", diff --git a/data/missions/rothan/02 - rothan defence #2.json b/data/missions/rothan/02 - rothan defence #2.json new file mode 100644 index 0000000..42b580d --- /dev/null +++ b/data/missions/rothan/02 - rothan defence #2.json @@ -0,0 +1,156 @@ +{ + "name" : "Rothan Defence #2", + "description" : "", + "requires" : 29, + "background" : "gfx/backgrounds/background05.jpg", + "planet" : "gfx/planets/bluePlanet.png", + "music" : "music/battle/determination.mp3", + "objectives" : [ + { + "description" : "Rendezvous with Irregular Nomads", + "targetName" : "Waypoint", + "targetValue" : 1, + "targetType" : "TT_WAYPOINT" + }, + { + "description" : "Eliminate UNF fighters", + "targetName" : "Enemy", + "targetValue" : 1, + "targetType" : "TT_DESTROY", + "isEliminateAll" : 1, + "active" : 0 + }, + { + "description" : "Retreat to jumpgate", + "targetName" : "Player", + "targetValue" : 1, + "targetType" : "TT_ESCAPED", + "active" : 0 + } + ], + "player" : { + "type" : "Rook", + "side" : "SIDE_ALLIES", + "pilot" : "Julian Spencer", + "squadron" : "Blue Jesters", + "x" : 10, + "y" : 5 + }, + "fighters" : [ + { + "name" : "CSN Pilot", + "types" : "TAF;Ray;Kingfisher;Hammerhead;Rook", + "side" : "SIDE_ALLIES", + "x" : 10, + "y" : 5, + "number" : 3, + "scatter" : 500 + }, + { + "name" : "CSN Pilot", + "groupName" : "Irregular Nomads", + "types" : "TAF;Ray;Kingfisher;Hammerhead;Rook", + "side" : "SIDE_ALLIES", + "x" : 30, + "y" : 1, + "number" : 4, + "active" : 0 + }, + { + "name" : "Rebel", + "groupName" : "Rebels", + "types" : "Nymph;Firefly", + "side" : "SIDE_REBEL", + "x" : -1, + "y" : -1, + "number" : 5, + "aiFlags" : "+AIF_UNLIMITED_RANGE", + "active" : 0 + }, + { + "name" : "Rebel", + "groupName" : "Rebels", + "types" : "Nymph;Firefly", + "side" : "SIDE_REBEL", + "x" : 15, + "y" : -1, + "number" : 5, + "aiFlags" : "+AIF_UNLIMITED_RANGE", + "active" : 0 + }, + { + "name" : "Rebel", + "groupName" : "Rebels", + "types" : "Nymph;Firefly", + "side" : "SIDE_REBEL", + "x" : -1, + "y" : 15, + "number" : 5, + "aiFlags" : "+AIF_UNLIMITED_RANGE", + "active" : 0 + } + ], + "entities" : [ + { + "type" : "ET_WAYPOINT", + "x" : 15, + "y" : 15, + "active" : 0 + }, + { + "type" : "ET_JUMPGATE", + "x" : 30, + "y" : 1, + "flags" : "+EF_DISABLED" + } + ], + "script" : [ + { + "function" : "TIME 1", + "lines" : [ + "MSG_BOX Spencer;Control, we're in position. Awaiting the Irregular Nomads.", + "MSG_BOX Control;Irregular Nomads have just exited the jumpgate. They'll be with you shortly.", + "ACTIVATE_ENTITY_GROUPS Irregular Nomads" + ] + }, + { + "function" : "TIME 15", + "lines" : [ + "MSG_BOX Fox;Commander Spencer, we're on our way. We'll join you at the waypoint.", + "WAIT_MSG_BOX", + "ACTIVATE_NEXT_WAYPOINT", + "MSG_BOX Fox;Acknowledged, Lieutenant, we'll see you in a bit." + ] + }, + { + "function" : "Waypoint #1", + "lines" : [ + "MSG_BOX Spencer;Control, we're ready to--", + "MSG_BOX Control;Commander, be advised that we are detecting UNF fighters advancing on your position, several Nymphs and Fireflies. They are not responding to requests to identify presence or purpose.", + "MSG_BOX Spencer;Pandorans?", + "MSG_BOX Control;Their signatures don't suggest so.", + "WAIT_MSG_BOX", + "WAIT 4,", + "ACTIVATE_ENTITY_GROUPS Rebels", + "ACTIVATE_OBJECTIVES Eliminate UNF fighters", + "MSG_BOX Control;Commander, incoming fighters are hostile. Suggest you prepare to engage or fallback to the jumpgate.", + "MSG_BOX Spencer;Acknowledged, moving to engage." + ] + }, + { + "function" : "OBJECTIVES_COMPLETE 2", + "lines" : [ + "MSG_BOX Spencer;Control, enemy targets have been eliminated.", + "MSG_BOX Control;Any survivors?", + "MSG_BOX Spencer;Negative, I didn't see anyone eject from those fighters.", + "MSG_BOX Control;Commander, your current missions has been aborted. Return to the jumpgate. We need a full report as to what just happened out there.", + "MSG_BOX Spencer;Got it, coming home.", + "WAIT_MSG_BOX", + "ACTIVATE_JUMPGATE 1", + "ACTIVATE_OBJECTIVES Retreat to jumpgate", + "RETREAT_ALLIES" + ] + } + ] +} + diff --git a/gfx/entities/waypoint.png b/gfx/entities/waypoint.png index e84fa0ecd3d7e30df776e1e485794ba6302c3fc9..7a8fee7904d7ba37f188fd5d8e53fd04d69f20fc 100644 GIT binary patch literal 17675 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 >= 1 && fabs(player->dy) >= 1) { - wantedAngle = getAngle(player->x, player->y, player->x + (player->dx * 10), player->y + (player->dy * 10)); + wantedAngle = getAngle(player->x, player->y, player->x + (player->dx * 100), player->y + (player->dy * 100)); turnToFace(wantedAngle); + + applyFighterThrust(); } if (dist <= 250) @@ -806,6 +808,8 @@ static void moveToLeader(void) wantedAngle = getAngle(self->leader->x, self->leader->y, self->leader->x + (self->leader->dx * 10), self->leader->y + (self->leader->dy * 10)); turnToFace(wantedAngle); + + applyFighterThrust(); } if (dist <= 250) diff --git a/src/battle/battle.c b/src/battle/battle.c index 0769312..bc393e2 100644 --- a/src/battle/battle.c +++ b/src/battle/battle.c @@ -60,8 +60,6 @@ void initBattle(void) initStars(); - initBullets(); - initBackground(); initEffects(); @@ -160,12 +158,10 @@ static void doBattle(void) if (battle.status == MS_IN_PROGRESS) { doScript(); - - battle.stats[STAT_TIME]++; - - if (battle.stats[STAT_TIME] % FPS == 0) + + if (battle.stats[STAT_TIME]++ % FPS == 0) { - runScriptFunction("TIME %d", battle.stats[STAT_TIME] / 60); + runScriptTimeFunctions(); } } } diff --git a/src/battle/battle.h b/src/battle/battle.h index c507df1..0662b49 100644 --- a/src/battle/battle.h +++ b/src/battle/battle.h @@ -84,6 +84,7 @@ extern void destroyEffects(void); extern void initChallengeHome(void); extern void updateAccuracyStats(unsigned int *stats); extern void clearInput(void); +extern void runScriptTimeFunctions(void); extern App app; extern Battle battle; diff --git a/src/battle/capitalShips.c b/src/battle/capitalShips.c index b5910cd..12f0aed 100644 --- a/src/battle/capitalShips.c +++ b/src/battle/capitalShips.c @@ -379,6 +379,10 @@ static void loadCapitalShipDef(char *filename) cJSON_Delete(root); } + else + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to load '%s'", filename); + } free(text); } diff --git a/src/battle/fighters.c b/src/battle/fighters.c index 4cf275a..7c8ec45 100644 --- a/src/battle/fighters.c +++ b/src/battle/fighters.c @@ -99,6 +99,42 @@ Entity *spawnFighter(char *name, int x, int y, int side) return e; } +void spawnScriptFighter(char *fighterTypes, char *sideStr, int num, char *location) +{ + Entity *e; + int i, numTypes, side, offscreen; + char **types, *type; + + types = toTypeArray(fighterTypes, &numTypes); + side = lookup(sideStr); + offscreen = strcmp(location, "OFFSCREEN") == 0; + + for (i = 0 ; i < num ; i++) + { + type = types[rand() % numTypes]; + + e = spawnFighter(type, 0, 0, side); + + if (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; + } + + free(types); +} + static void randomizeDart(Entity *dart) { char texture[MAX_DESCRIPTION_LENGTH]; @@ -728,6 +764,10 @@ static void loadFighterDef(char *filename) cJSON_Delete(root); } + else + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to load '%s'", filename); + } free(text); } diff --git a/src/battle/fighters.h b/src/battle/fighters.h index 11c3600..c6394d5 100644 --- a/src/battle/fighters.h +++ b/src/battle/fighters.h @@ -47,6 +47,7 @@ extern void addDebris(int x, int y, int amount); extern char **getFileList(char *dir, int *count); extern char *getTranslatedString(char *string); extern int getJSONValue(cJSON *node, char *name, int defValue); +extern char **toTypeArray(char *types, int *numTypes); extern App app; extern Battle battle; diff --git a/src/battle/hud.c b/src/battle/hud.c index 9fbdc0b..eca800b 100644 --- a/src/battle/hud.c +++ b/src/battle/hud.c @@ -330,7 +330,7 @@ static void drawPlayerTargeter(void) float angle; int x, y; - if (player->target || battle.missionTarget || battle.jumpgate) + if (player->target || battle.missionTarget || jumpgateEnabled()) { if (player->target) { @@ -376,7 +376,7 @@ static void drawPlayerTargeter(void) blitRotated(targetPointer, x - battle.camera.x, y - battle.camera.y, angle); } - if (battle.jumpgate) + if (jumpgateEnabled()) { angle = getAngle(player->x, player->y, battle.jumpgate->x, battle.jumpgate->y); x = player->x; @@ -422,6 +422,10 @@ static void drawObjectives(void) { drawText(SCREEN_WIDTH / 2, 35, 14, TA_CENTER, colors.white, "%d / %d", battle.stats[STAT_ITEMS_COLLECTED] + battle.stats[STAT_ITEMS_COLLECTED_PLAYER], game.currentMission->challengeData.itemLimit); } + else if (game.currentMission->challengeData.rescueLimit) + { + drawText(SCREEN_WIDTH / 2, 35, 14, TA_CENTER, colors.white, "%d / %d", battle.stats[STAT_CIVILIANS_RESCUED], game.currentMission->challengeData.rescueLimit); + } } else { @@ -452,7 +456,7 @@ static void drawDistancesInfo(void) y = 11; - if (player->target != NULL) + if (player->target) { drawText(SCREEN_WIDTH - 15, y, 18, TA_RIGHT, colors.red, player->target->name); @@ -465,7 +469,7 @@ static void drawDistancesInfo(void) y += 25; } - if (battle.missionTarget != NULL) + if (battle.missionTarget) { distance = distanceToKM(player->x, player->y, battle.missionTarget->x, battle.missionTarget->y); @@ -474,7 +478,7 @@ static void drawDistancesInfo(void) y += 25; } - if (battle.jumpgate != NULL) + if (jumpgateEnabled()) { distance = distanceToKM(player->x, player->y, battle.jumpgate->x, battle.jumpgate->y); diff --git a/src/battle/hud.h b/src/battle/hud.h index 832fc6e..b67c9b8 100644 --- a/src/battle/hud.h +++ b/src/battle/hud.h @@ -34,6 +34,7 @@ extern int getPercent(float current, float total); extern int playerHasGun(int type); extern char *getTranslatedString(char *string); extern char *timeToString(long millis, int showHours); +extern int jumpgateEnabled(void); extern App app; extern Battle battle; diff --git a/src/battle/items.c b/src/battle/items.c index a2acb0b..1d9931e 100644 --- a/src/battle/items.c +++ b/src/battle/items.c @@ -54,6 +54,7 @@ void loadItemDefs(void) SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); defTail->next = e; + defTail = e; } cJSON_Delete(root); diff --git a/src/battle/jumpgate.c b/src/battle/jumpgate.c index 5dec983..64c6365 100644 --- a/src/battle/jumpgate.c +++ b/src/battle/jumpgate.c @@ -45,6 +45,26 @@ Entity *spawnJumpgate(void) return jumpgate; } +int jumpgateEnabled(void) +{ + return (battle.jumpgate && (!(battle.jumpgate->flags & EF_DISABLED))); +} + +void activateJumpgate(int activate) +{ + if (battle.jumpgate) + { + if (activate) + { + battle.jumpgate->flags &= ~EF_DISABLED; + } + else + { + battle.jumpgate->flags |= EF_DISABLED; + } + } +} + static void think(void) { self->thinkTime = 4; @@ -55,7 +75,7 @@ static void think(void) self->angle -= 360; } - if (self->systemPower) + if (jumpgateEnabled()) { handleFleeingEntities(); } @@ -128,7 +148,7 @@ static void addEscapeEffect(Entity *ent) static void draw(void) { - if (self->systemPower) + if (jumpgateEnabled()) { blitRotated(portal, self->x - battle.camera.x, self->y - battle.camera.y, portalAngle); } diff --git a/src/battle/quadtree.c b/src/battle/quadtree.c index 303c96a..c6eecf6 100644 --- a/src/battle/quadtree.c +++ b/src/battle/quadtree.c @@ -24,8 +24,6 @@ static Entity **candidates; static int cIndex; static int cCapacity; -static int memory; - static int getIndex(Quadtree *root, int x, int y, int w, int h); static void removeEntity(Entity *e, Quadtree *root); static int candidatesComparator(const void *a, const void *b); @@ -48,11 +46,12 @@ void initQuadtree(Quadtree *root) root->ents = malloc(sizeof(Entity*) * root->capacity); memset(root->ents, 0, sizeof(Entity*) * root->capacity); - memory = 0; + cIndex = 0; + cCapacity = QT_INITIAL_CAPACITY; + candidates = malloc(sizeof(Entity*) * cCapacity); + memset(candidates, 0, sizeof(Entity*) * cCapacity); } - memory += sizeof(Quadtree); - w = root->w / 2; h = root->h / 2; @@ -101,11 +100,6 @@ void initQuadtree(Quadtree *root) initQuadtree(node); } } - - cIndex = 0; - cCapacity = QT_INITIAL_CAPACITY; - candidates = malloc(sizeof(Entity*) * cCapacity); - memset(candidates, 0, sizeof(Entity*) * cCapacity); } void addToQuadtree(Entity *e, Quadtree *root) @@ -277,23 +271,28 @@ void destroyQuadtree(void) { destroyQuadtreeNode(&battle.quadtree); - free(candidates); - - candidates = NULL; + if (candidates) + { + free(candidates); + + candidates = NULL; + } } static void destroyQuadtreeNode(Quadtree *root) { int i; + free(root->ents); + + root->ents = NULL; + if (root->node[0]) { for (i = 0 ; i < 4 ; i++) { destroyQuadtreeNode(root->node[i]); - free(root->node[i]->ents); - free(root->node[i]); root->node[i] = NULL; diff --git a/src/battle/script.c b/src/battle/script.c index 6aafdb4..929422b 100644 --- a/src/battle/script.c +++ b/src/battle/script.c @@ -28,10 +28,24 @@ static ScriptRunner *tail; void initScript(cJSON *scriptNode) { + cJSON *function; + memset(&head, 0, sizeof(ScriptRunner)); tail = &head; scriptJSON = scriptNode; + + if (scriptJSON) + { + function = scriptJSON->child; + + while (function) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Found script function: '%s'", cJSON_GetObjectItem(function, "function")->valuestring); + + function = function->next; + } + } } void doScript(void) @@ -110,11 +124,65 @@ void runScriptFunction(const char *format, ...) } } +void runScriptTimeFunctions(void) +{ + ScriptRunner *scriptRunner; + cJSON *function; + char *functionName; + char funcNameBuffer[MAX_NAME_LENGTH]; + int intParam; + + if (scriptJSON) + { + function = scriptJSON->child; + + sprintf(funcNameBuffer, "TIME %d", battle.stats[STAT_TIME] / 60); + + while (function) + { + functionName = cJSON_GetObjectItem(function, "function")->valuestring; + + if (strcmp(functionName, funcNameBuffer) == 0) + { + scriptRunner = malloc(sizeof(ScriptRunner)); + memset(scriptRunner, 0, sizeof(ScriptRunner)); + + scriptRunner->line = cJSON_GetObjectItem(function, "lines")->child; + + tail->next = scriptRunner; + tail = scriptRunner; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Running script '%s'", funcNameBuffer); + } + + if (strstr(functionName, "INTERVAL")) + { + sscanf(functionName, "%*s %d", &intParam); + + if ((battle.stats[STAT_TIME] / 60) % intParam == 0) + { + scriptRunner = malloc(sizeof(ScriptRunner)); + memset(scriptRunner, 0, sizeof(ScriptRunner)); + + scriptRunner->line = cJSON_GetObjectItem(function, "lines")->child; + + tail->next = scriptRunner; + tail = scriptRunner; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Running script '%s'", funcNameBuffer); + } + } + + function = function->next; + } + } +} + static void executeNextLine(ScriptRunner *runner) { char *line; char command[24]; - char strParam[2][256]; + char strParam[3][256]; int intParam[2]; line = runner->line->valuestring; @@ -143,7 +211,12 @@ static void executeNextLine(ScriptRunner *runner) } else if (strcmp(command, "ACTIVATE_JUMPGATE") == 0) { - battle.jumpgate->systemPower = MAX_SYSTEM_POWER; + sscanf(line, "%*s %d", &intParam[0]); + activateJumpgate(intParam[0]); + } + else if (strcmp(command, "ACTIVATE_NEXT_WAYPOINT") == 0) + { + activateNextWaypoint(0); } else if (strcmp(command, "MSG_BOX") == 0) { @@ -183,6 +256,11 @@ static void executeNextLine(ScriptRunner *runner) battle.isEpic = 0; retreatEnemies(); } + else if (strcmp(command, "SPAWN_FIGHTERS") == 0) + { + sscanf(line, "%*s %s %s %d %s", strParam[0], strParam[1], &intParam[0], strParam[2]); + spawnScriptFighter(strParam[0], strParam[1], intParam[0], strParam[2]); + } else { printf("ERROR: Unrecognised script command '%s'\n", command); @@ -196,6 +274,13 @@ static void executeNextLine(ScriptRunner *runner) void destroyScript(void) { ScriptRunner *scriptRunner; + + if (scriptJSON) + { + cJSON_Delete(scriptJSON); + + scriptJSON = NULL; + } while (head.next) { diff --git a/src/battle/script.h b/src/battle/script.h index aadcba0..b2c98c1 100644 --- a/src/battle/script.h +++ b/src/battle/script.h @@ -34,6 +34,9 @@ extern void activateLocations(char *locations); void activateObjectives(char *objectives); extern int showingMessageBoxes(void); extern char *getTranslatedString(char *string); +extern void spawnScriptFighter(char *fighters, char *side, int num, char *location); +extern void activateNextWaypoint(int id); +extern void activateJumpgate(int activate); extern Battle battle; extern Colors colors; diff --git a/src/battle/waypoints.c b/src/battle/waypoints.c index cd87001..70226d4 100644 --- a/src/battle/waypoints.c +++ b/src/battle/waypoints.c @@ -50,25 +50,29 @@ Entity *spawnWaypoint(void) static void think(void) { - self->thinkTime = 4; + self->angle += 0.25; - self->angle++; if (self->angle >= 360) { self->angle -= 360; } - if (player != NULL && getDistance(player->x, player->y, self->x, self->y) <= 64 && isCurrentObjective() && teamMatesClose()) + if (--self->aiActionTime <= 0) { - self->health = 0; + self->aiActionTime = 0; - updateObjective("Waypoint", TT_WAYPOINT); - - runScriptFunction(self->name); - - activateNextWaypoint(self->id); - - battle.stats[STAT_WAYPOINTS_VISITED]++; + if (self->health && player != NULL && getDistance(player->x, player->y, self->x, self->y) <= 128 && isCurrentObjective() && teamMatesClose()) + { + self->health = 0; + + updateObjective("Waypoint", TT_WAYPOINT); + + runScriptFunction(self->name); + + activateNextWaypoint(self->id); + + battle.stats[STAT_WAYPOINTS_VISITED]++; + } } } @@ -79,7 +83,7 @@ static int isCurrentObjective(void) if (numActiveObjectives > 1) { addHudMessage(colors.cyan, _("Cannot activate waypoint - outstanding objectives not yet complete")); - self->thinkTime = FPS; + self->aiActionTime = FPS; return 0; } @@ -97,7 +101,7 @@ static int teamMatesClose(void) 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; + self->aiActionTime = FPS; return 0; } } diff --git a/src/challenges/challenges.c b/src/challenges/challenges.c index 61180ee..27082ad 100644 --- a/src/challenges/challenges.c +++ b/src/challenges/challenges.c @@ -57,6 +57,7 @@ void initChallenges(void) challengeDescription[CHALLENGE_PLAYER_KILLS] = _("Take down %d enemy targets"); challengeDescription[CHALLENGE_DISABLE] = _("Disable %d or more enemy fighters"); challengeDescription[CHALLENGE_ITEMS] = _("Collect %d packages"); + challengeDescription[CHALLENGE_RESCUE] = _("Rescue %d civilians"); tail = &game.challengeMissionHead; @@ -128,6 +129,11 @@ static int challengeFinished(void) return 1; } + if (game.currentMission->challengeData.rescueLimit > 0 && (battle.stats[STAT_CIVILIANS_RESCUED] + battle.stats[STAT_CIVILIANS_KILLED]) >= game.currentMission->challengeData.rescueLimit) + { + return 1; + } + if (game.currentMission->challengeData.scriptedEnd) { return 1; diff --git a/src/defs.h b/src/defs.h index a004116..2feb4bd 100644 --- a/src/defs.h +++ b/src/defs.h @@ -293,6 +293,7 @@ enum CHALLENGE_PLAYER_KILLS, CHALLENGE_DISABLE, CHALLENGE_ITEMS, + CHALLENGE_RESCUE, CHALLENGE_MAX }; diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index 9ada9e3..69700eb 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -28,7 +28,6 @@ static void loadEntities(cJSON *node); static void loadItems(cJSON *node); static void loadLocations(cJSON *node); static unsigned long hashcode(const char *str); -static char **toTypeArray(char *types, int *numTypes); static void loadEpicData(cJSON *node); static char *getAutoBackground(char *filename); static char *getAutoPlanet(char *filename); @@ -87,6 +86,7 @@ Mission *loadMissionMeta(char *filename) mission->challengeData.escapeLimit = getJSONValue(node, "escapeLimit", 0); mission->challengeData.waypointLimit = getJSONValue(node, "waypointLimit", 0); mission->challengeData.itemLimit = getJSONValue(node, "itemLimit", 0); + mission->challengeData.rescueLimit = getJSONValue(node, "rescueLimit", 0); /* restrictions */ mission->challengeData.noMissiles = getJSONValue(node, "noMissiles", 0); @@ -121,6 +121,10 @@ Mission *loadMissionMeta(char *filename) cJSON_Delete(root); } + else + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to load '%s'", filename); + } free(text); @@ -216,8 +220,6 @@ void loadMission(char *filename) battle.status = MS_IN_PROGRESS; } - activateNextWaypoint(); - countNumEnemies(); initPlayer(); @@ -376,7 +378,7 @@ static void loadFighters(cJSON *node) Entity *e; char **types, *name, *groupName, *type; int side, scatter, number, active; - int i, numTypes, addFlags, addAIFlags, systemPower; + int i, numTypes, addFlags, addAIFlags; long flags, aiFlags; float x, y; @@ -400,7 +402,6 @@ static void loadFighters(cJSON *node) number = getJSONValue(node, "number", 1); scatter = getJSONValue(node, "scatter", 1); active = getJSONValue(node, "active", 1); - systemPower = getJSONValue(node, "systemPower", MAX_SYSTEM_POWER); if (cJSON_GetObjectItem(node, "flags")) { @@ -463,12 +464,6 @@ static void loadFighters(cJSON *node) { STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); } - - e->systemPower = systemPower; - if (!e->systemPower) - { - e->flags |= EF_DISABLED; - } } node = node->next; @@ -574,8 +569,9 @@ static void loadEntities(cJSON *node) { Entity *e; char *name, *groupName; - int i, type, scatter, number, active, systemPower; + int i, type, scatter, number, active, addFlags; float x, y; + long flags; if (node) { @@ -595,7 +591,11 @@ static void loadEntities(cJSON *node) number = getJSONValue(node, "number", 1); active = getJSONValue(node, "active", 1); scatter = getJSONValue(node, "scatter", 1); - systemPower = getJSONValue(node, "systemPower", MAX_SYSTEM_POWER); + + if (cJSON_GetObjectItem(node, "flags")) + { + flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags); + } for (i = 0 ; i < number ; i++) { @@ -624,6 +624,20 @@ static void loadEntities(cJSON *node) { STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); } + + if (flags != -1) + { + if (addFlags) + { + e->flags |= flags; + } + else + { + e->flags = flags; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Flags for '%s' (%s) replaced", e->name, e->defName); + } + } e->x = x; e->y = y; @@ -636,8 +650,6 @@ static void loadEntities(cJSON *node) e->active = active; - e->systemPower = systemPower; - SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); } @@ -759,38 +771,6 @@ static void loadLocations(cJSON *node) } } -static char **toTypeArray(char *types, int *numTypes) -{ - int i; - char **typeArray, *type; - - *numTypes = 1; - - for (i = 0 ; i < strlen(types) ; i++) - { - if (types[i] == ';') - { - *numTypes = *numTypes + 1; - } - } - - typeArray = malloc(*numTypes * sizeof(char*)); - - i = 0; - type = strtok(types, ";"); - while (type) - { - typeArray[i] = malloc(strlen(type) + 1); - strcpy(typeArray[i], type); - - type = strtok(NULL, ";"); - - i++; - } - - return typeArray; -} - static void loadEpicData(cJSON *node) { Entity *e; diff --git a/src/galaxy/mission.h b/src/galaxy/mission.h index af2a4d9..c6a8647 100644 --- a/src/galaxy/mission.h +++ b/src/galaxy/mission.h @@ -35,7 +35,6 @@ extern void stopMusic(void); extern void initPlayer(void); extern long flagsToLong(char *flags, int *add); extern Entity *spawnWaypoint(void); -extern void activateNextWaypoint(void); extern void selectWidget(const char *name, const char *group); extern Entity *spawnJumpgate(void); extern Entity *spawnItem(char *type); @@ -55,6 +54,7 @@ extern char *getMusicFilename(int n); extern int getJSONValue(cJSON *node, char *name, int defValue); extern char *getJSONValueStr(cJSON *node, char *name, char *defValue); extern void addAllEntsToQuadtree(void); +extern char **toTypeArray(char *types, int *numTypes); extern Battle battle; extern Entity *player; diff --git a/src/main.c b/src/main.c index c1d08d7..6617833 100644 --- a/src/main.c +++ b/src/main.c @@ -27,9 +27,10 @@ int main(int argc, char *argv[]) float td; long then, lastFrameTime, frames; long expireTextTimer; - SDL_Event event; + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN); + memset(&app, 0, sizeof(App)); memset(&dev, 0, sizeof(Dev)); @@ -169,6 +170,8 @@ static void handleArguments(int argc, char *argv[]) dev.debug = 1; createScreenshotFolder(); + + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG); } } } diff --git a/src/structs.h b/src/structs.h index 245c007..34c0587 100644 --- a/src/structs.h +++ b/src/structs.h @@ -251,6 +251,7 @@ typedef struct { int itemLimit; int escapeLimit; int waypointLimit; + int rescueLimit; int noMissiles; int noBoost; int noECM; diff --git a/src/system/i18n.c b/src/system/i18n.c index 6f17493..7283929 100644 --- a/src/system/i18n.c +++ b/src/system/i18n.c @@ -79,7 +79,7 @@ void setLanguage(char *applicationName, char *languageCode) STRNCPY(language, lang, MAX_LINE_LENGTH); } - printf("Locale is %s\n", language); + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Locale is %s", language); sprintf(c, "%s/%s/LC_MESSAGES/%s.mo", LOCALE_DIR, language, applicationName); diff --git a/src/system/init.c b/src/system/init.c index 507c0b8..2d04920 100644 --- a/src/system/init.c +++ b/src/system/init.c @@ -131,9 +131,9 @@ void initGameSystem(void) initStarSystems, initChallenges, initStats, - initBattle, initModalDialog, initBackground, + initStars, initControls }; @@ -338,10 +338,10 @@ void cleanup(void) destroyWidgets(); destroyResources(); + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Done"); TTF_Quit(); SDL_Quit(); - - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Done"); } diff --git a/src/system/init.h b/src/system/init.h index 78133cb..6d6dd05 100644 --- a/src/system/init.h +++ b/src/system/init.h @@ -70,6 +70,7 @@ extern void createSaveFolder(void); extern void setLanguage(char *applicationName, char *languageCode); extern char *getLookupName(char *prefix, long num); extern long lookup(char *name); +extern void initStars(void); extern App app; extern Colors colors; diff --git a/src/system/lookup.c b/src/system/lookup.c index 2d66ca5..f205f21 100644 --- a/src/system/lookup.c +++ b/src/system/lookup.c @@ -132,6 +132,7 @@ void initLookups(void) addLookup("CHALLENGE_PLAYER_KILLS", CHALLENGE_PLAYER_KILLS); addLookup("CHALLENGE_DISABLE", CHALLENGE_DISABLE); addLookup("CHALLENGE_ITEMS", CHALLENGE_ITEMS); + addLookup("CHALLENGE_RESCUE", CHALLENGE_RESCUE); addLookup("STAT_PERCENT_COMPLETE", STAT_PERCENT_COMPLETE); addLookup("STAT_MISSIONS_STARTED", STAT_MISSIONS_STARTED); diff --git a/src/system/resources.c b/src/system/resources.c index d4b5ef1..ba88d56 100644 --- a/src/system/resources.c +++ b/src/system/resources.c @@ -98,7 +98,20 @@ char *getMusicFilename(int i) void destroyResources(void) { - free(backgrounds); - free(planets); - free(musicFiles); + int i; + + for (i = 0 ; i < numBackgrounds ; i++) + { + free(backgrounds[i]); + } + + for (i = 0 ; i < numPlanets ; i++) + { + free(planets[i]); + } + + for (i = 0 ; i < numMusicFiles ; i++) + { + free(musicFiles[i]); + } } diff --git a/src/system/util.c b/src/system/util.c index 982b45f..2d9f409 100644 --- a/src/system/util.c +++ b/src/system/util.c @@ -73,6 +73,38 @@ void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy) *dy /= steps; } +char **toTypeArray(char *types, int *numTypes) +{ + int i; + char **typeArray, *type; + + *numTypes = 1; + + for (i = 0 ; i < strlen(types) ; i++) + { + if (types[i] == ';') + { + *numTypes = *numTypes + 1; + } + } + + typeArray = malloc(*numTypes * sizeof(char*)); + + i = 0; + type = strtok(types, ";"); + while (type) + { + typeArray[i] = malloc(strlen(type) + 1); + strcpy(typeArray[i], type); + + type = strtok(NULL, ";"); + + i++; + } + + return typeArray; +} + char *timeToString(long millis, int showHours) { static char TIME[MAX_NAME_LENGTH]; diff --git a/src/system/widgets.c b/src/system/widgets.c index c5fa49a..d8fa666 100644 --- a/src/system/widgets.c +++ b/src/system/widgets.c @@ -427,6 +427,10 @@ static void loadWidgetSet(char *filename) cJSON_Delete(root); } + else + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to load '%s'", filename); + } free(text); } @@ -507,6 +511,8 @@ void destroyWidgets(void) { free(w->options[i]); } + + free(w->options); next = w->next; free(w);