Merge from develop.

This commit is contained in:
Steve 2016-03-12 18:22:48 +00:00
parent da97818259
commit 0a69dd0e5e
39 changed files with 615 additions and 110 deletions

60
data/challenges/10.json Normal file
View File

@ -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"
]
}
]
}

View File

@ -7,6 +7,11 @@
"shieldRechargeRate" : 45, "shieldRechargeRate" : 45,
"texture" : "gfx/fighters/rook.png", "texture" : "gfx/fighters/rook.png",
"guns" : [ "guns" : [
{
"type" : "BT_PLASMA",
"x" : 0,
"y" : 0
},
{ {
"type" : "BT_PLASMA", "type" : "BT_PLASMA",
"x" : -9, "x" : -9,

View File

@ -8,7 +8,7 @@
"manualComplete" : 1, "manualComplete" : 1,
"objectives" : [ "objectives" : [
{ {
"description" : "Check all wayponts", "description" : "Check all waypoints",
"targetName" : "Waypoint", "targetName" : "Waypoint",
"targetValue" : 5, "targetValue" : 5,
"targetType" : "TT_WAYPOINT" "targetType" : "TT_WAYPOINT"
@ -42,6 +42,12 @@
} }
], ],
"script" : [ "script" : [
{
"function" : "TIME 0",
"lines" : [
"ACTIVATE_NEXT_WAYPOINT"
]
},
{ {
"function" : "Waypoint #2", "function" : "Waypoint #2",
"lines" : [ "lines" : [

View File

@ -59,6 +59,12 @@
} }
], ],
"script" : [ "script" : [
{
"function" : "TIME 0",
"lines" : [
"ACTIVATE_NEXT_WAYPOINT"
]
},
{ {
"function" : "Waypoint #3", "function" : "Waypoint #3",
"lines" : [ "lines" : [

View File

@ -45,6 +45,12 @@
} }
], ],
"script" : [ "script" : [
{
"function" : "TIME 0",
"lines" : [
"ACTIVATE_NEXT_WAYPOINT"
]
},
{ {
"function" : "TIME 3", "function" : "TIME 3",
"lines" : [ "lines" : [

View File

@ -74,7 +74,7 @@
"type" : "ET_JUMPGATE", "type" : "ET_JUMPGATE",
"x" : 25, "x" : 25,
"y" : 25, "y" : 25,
"systemPower" : 0 "flags" : "+EF_DISABLED"
} }
], ],
"script" : [ "script" : [
@ -99,7 +99,7 @@
"MSG_BOX Dodds;Estelle, we've got this. We can take them.", "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.", "MSG_BOX de Winter;We're taking too many losses, Dodds. Fall back now, that's an order.",
"WAIT_MSG_BOX", "WAIT_MSG_BOX",
"ACTIVATE_JUMPGATE", "ACTIVATE_JUMPGATE 1",
"RETREAT_ALLIES" "RETREAT_ALLIES"
] ]
} }

View File

@ -110,7 +110,7 @@
"type" : "ET_JUMPGATE", "type" : "ET_JUMPGATE",
"x" : 10, "x" : 10,
"y" : 8, "y" : 8,
"systemPower" : 0 "flags" : "+EF_DISABLED"
} }
], ],
"items" : [ "items" : [
@ -126,6 +126,12 @@
} }
], ],
"script" : [ "script" : [
{
"function" : "TIME 0",
"lines" : [
"ACTIVATE_NEXT_WAYPOINT"
]
},
{ {
"function" : "Waypoint #2", "function" : "Waypoint #2",
"lines" : [ "lines" : [
@ -153,7 +159,7 @@
"WAIT 2", "WAIT 2",
"MSG_BOX Tug;Tow cable attached. Ready to head home.", "MSG_BOX Tug;Tow cable attached. Ready to head home.",
"MSG_BOX Carr;We're done here. Let's bring our mystery guest in.", "MSG_BOX Carr;We're done here. Let's bring our mystery guest in.",
"ACTIVATE_JUMPGATE", "ACTIVATE_JUMPGATE 1",
"WAIT 20", "WAIT 20",
"ACTIVATE_ENTITIES Dart", "ACTIVATE_ENTITIES Dart",
"ACTIVATE_OBJECTIVES Destroy intercepting Darts", "ACTIVATE_OBJECTIVES Destroy intercepting Darts",

View File

@ -126,6 +126,12 @@
} }
], ],
"script" : [ "script" : [
{
"function" : "TIME 0",
"lines" : [
"ACTIVATE_NEXT_WAYPOINT"
]
},
{ {
"function" : "Waypoint #1", "function" : "Waypoint #1",
"lines" : [ "lines" : [

View File

@ -75,8 +75,7 @@
"y" : 25, "y" : 25,
"number" : 12, "number" : 12,
"scatter" : 5000, "scatter" : 5000,
"systemPower" : 0, "flags" : "+EF_DISABLED+EF_NO_KILL+EF_MISSION_TARGET"
"flags" : "+EF_NO_KILL+EF_MISSION_TARGET"
}, },
{ {
"name" : "CSN Tug", "name" : "CSN Tug",

View File

@ -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"
]
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TBFTSS: The Pandoran War\n" "Project-Id-Version: TBFTSS: The Pandoran War\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-03-10 15:44:08+0000\n" "POT-Creation-Date: 2016-03-12 15:00:11+0000\n"
"PO-Revision-Date: ???\n" "PO-Revision-Date: ???\n"
"Last-Translator: ???\n" "Last-Translator: ???\n"
"Language-Team: ???\n" "Language-Team: ???\n"
@ -190,6 +190,9 @@ msgstr ""
msgid "Collect %d packages" msgid "Collect %d packages"
msgstr "" msgstr ""
msgid "Rescue %d civilians"
msgstr ""
msgid "%s has fallen to the Pandorans" msgid "%s has fallen to the Pandorans"
msgstr "" msgstr ""
@ -934,7 +937,7 @@ msgstr ""
msgid "Can you disable the gate remotely?" msgid "Can you disable the gate remotely?"
msgstr "" msgstr ""
msgid "Negative, the Pandorans have control. We're working take back command function. Stand by." msgid "Negative, the Pandorans have control. We're working take back command functions. Stand by."
msgstr "" msgstr ""
msgid "Griffin, all enemy tugs have been dispatched." msgid "Griffin, all enemy tugs have been dispatched."
@ -955,6 +958,51 @@ msgstr ""
msgid "I knew I could count on you, de Winter. Head back to Griffin." msgid "I knew I could count on you, de Winter. Head back to Griffin."
msgstr "" msgstr ""
msgid "Control, we're in position. Awaiting the Irregular Nomads."
msgstr ""
msgid "Irregular Nomads have just exited the jumpgate. They'll be with you shortly."
msgstr ""
msgid "Commander Spencer, we're on our way. We'll join you at the waypoint."
msgstr ""
msgid "Acknowledged, Lieutenant, we'll see you in a bit."
msgstr ""
msgid "Control, we're ready to--"
msgstr ""
msgid "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."
msgstr ""
msgid "Pandorans?"
msgstr ""
msgid "Their signatures don't suggest so."
msgstr ""
msgid "Commander, incoming fighters are hostile. Suggest you prepare to engage or fallback to the jumpgate."
msgstr ""
msgid "Acknowledged, moving to engage."
msgstr ""
msgid "Control, enemy targets have been eliminated."
msgstr ""
msgid "Any survivors?"
msgstr ""
msgid "Negative, I didn't see anyone eject from those fighters."
msgstr ""
msgid "Commander, your current missions has been aborted. Return to the jumpgate. We need a full report as to what just happened out there."
msgstr ""
msgid "Got it, coming home."
msgstr ""
msgid "A simple test flight. Get used to piloting your fighter, without threat of attack or any other dangers to face. There are no objectives to complete in this mission, so you may quit it at any time and move on to the next one." msgid "A simple test flight. Get used to piloting your fighter, without threat of attack or any other dangers to face. There are no objectives to complete in this mission, so you may quit it at any time and move on to the next one."
msgstr "" msgstr ""

View File

@ -607,9 +607,11 @@ static void moveToPlayer(void)
{ {
if (fabs(player->dx) >= 1 && fabs(player->dy) >= 1) if (fabs(player->dx) >= 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); turnToFace(wantedAngle);
applyFighterThrust();
} }
if (dist <= 250) 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)); wantedAngle = getAngle(self->leader->x, self->leader->y, self->leader->x + (self->leader->dx * 10), self->leader->y + (self->leader->dy * 10));
turnToFace(wantedAngle); turnToFace(wantedAngle);
applyFighterThrust();
} }
if (dist <= 250) if (dist <= 250)

View File

@ -60,8 +60,6 @@ void initBattle(void)
initStars(); initStars();
initBullets();
initBackground(); initBackground();
initEffects(); initEffects();
@ -160,12 +158,10 @@ static void doBattle(void)
if (battle.status == MS_IN_PROGRESS) if (battle.status == MS_IN_PROGRESS)
{ {
doScript(); 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();
} }
} }
} }

View File

@ -84,6 +84,7 @@ extern void destroyEffects(void);
extern void initChallengeHome(void); extern void initChallengeHome(void);
extern void updateAccuracyStats(unsigned int *stats); extern void updateAccuracyStats(unsigned int *stats);
extern void clearInput(void); extern void clearInput(void);
extern void runScriptTimeFunctions(void);
extern App app; extern App app;
extern Battle battle; extern Battle battle;

View File

@ -379,6 +379,10 @@ static void loadCapitalShipDef(char *filename)
cJSON_Delete(root); cJSON_Delete(root);
} }
else
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to load '%s'", filename);
}
free(text); free(text);
} }

View File

@ -99,6 +99,42 @@ Entity *spawnFighter(char *name, int x, int y, int side)
return e; 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) static void randomizeDart(Entity *dart)
{ {
char texture[MAX_DESCRIPTION_LENGTH]; char texture[MAX_DESCRIPTION_LENGTH];
@ -728,6 +764,10 @@ static void loadFighterDef(char *filename)
cJSON_Delete(root); cJSON_Delete(root);
} }
else
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to load '%s'", filename);
}
free(text); free(text);
} }

View File

@ -47,6 +47,7 @@ extern void addDebris(int x, int y, int amount);
extern char **getFileList(char *dir, int *count); extern char **getFileList(char *dir, int *count);
extern char *getTranslatedString(char *string); extern char *getTranslatedString(char *string);
extern int getJSONValue(cJSON *node, char *name, int defValue); extern int getJSONValue(cJSON *node, char *name, int defValue);
extern char **toTypeArray(char *types, int *numTypes);
extern App app; extern App app;
extern Battle battle; extern Battle battle;

View File

@ -330,7 +330,7 @@ static void drawPlayerTargeter(void)
float angle; float angle;
int x, y; int x, y;
if (player->target || battle.missionTarget || battle.jumpgate) if (player->target || battle.missionTarget || jumpgateEnabled())
{ {
if (player->target) if (player->target)
{ {
@ -376,7 +376,7 @@ static void drawPlayerTargeter(void)
blitRotated(targetPointer, x - battle.camera.x, y - battle.camera.y, angle); 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); angle = getAngle(player->x, player->y, battle.jumpgate->x, battle.jumpgate->y);
x = player->x; 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); 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 else
{ {
@ -452,7 +456,7 @@ static void drawDistancesInfo(void)
y = 11; y = 11;
if (player->target != NULL) if (player->target)
{ {
drawText(SCREEN_WIDTH - 15, y, 18, TA_RIGHT, colors.red, player->target->name); drawText(SCREEN_WIDTH - 15, y, 18, TA_RIGHT, colors.red, player->target->name);
@ -465,7 +469,7 @@ static void drawDistancesInfo(void)
y += 25; y += 25;
} }
if (battle.missionTarget != NULL) if (battle.missionTarget)
{ {
distance = distanceToKM(player->x, player->y, battle.missionTarget->x, battle.missionTarget->y); distance = distanceToKM(player->x, player->y, battle.missionTarget->x, battle.missionTarget->y);
@ -474,7 +478,7 @@ static void drawDistancesInfo(void)
y += 25; y += 25;
} }
if (battle.jumpgate != NULL) if (jumpgateEnabled())
{ {
distance = distanceToKM(player->x, player->y, battle.jumpgate->x, battle.jumpgate->y); distance = distanceToKM(player->x, player->y, battle.jumpgate->x, battle.jumpgate->y);

View File

@ -34,6 +34,7 @@ extern int getPercent(float current, float total);
extern int playerHasGun(int type); extern int playerHasGun(int type);
extern char *getTranslatedString(char *string); extern char *getTranslatedString(char *string);
extern char *timeToString(long millis, int showHours); extern char *timeToString(long millis, int showHours);
extern int jumpgateEnabled(void);
extern App app; extern App app;
extern Battle battle; extern Battle battle;

View File

@ -54,6 +54,7 @@ void loadItemDefs(void)
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h);
defTail->next = e; defTail->next = e;
defTail = e;
} }
cJSON_Delete(root); cJSON_Delete(root);

View File

@ -45,6 +45,26 @@ Entity *spawnJumpgate(void)
return jumpgate; 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) static void think(void)
{ {
self->thinkTime = 4; self->thinkTime = 4;
@ -55,7 +75,7 @@ static void think(void)
self->angle -= 360; self->angle -= 360;
} }
if (self->systemPower) if (jumpgateEnabled())
{ {
handleFleeingEntities(); handleFleeingEntities();
} }
@ -128,7 +148,7 @@ static void addEscapeEffect(Entity *ent)
static void draw(void) static void draw(void)
{ {
if (self->systemPower) if (jumpgateEnabled())
{ {
blitRotated(portal, self->x - battle.camera.x, self->y - battle.camera.y, portalAngle); blitRotated(portal, self->x - battle.camera.x, self->y - battle.camera.y, portalAngle);
} }

View File

@ -24,8 +24,6 @@ static Entity **candidates;
static int cIndex; static int cIndex;
static int cCapacity; static int cCapacity;
static int memory;
static int getIndex(Quadtree *root, int x, int y, int w, int h); static int getIndex(Quadtree *root, int x, int y, int w, int h);
static void removeEntity(Entity *e, Quadtree *root); static void removeEntity(Entity *e, Quadtree *root);
static int candidatesComparator(const void *a, const void *b); static int candidatesComparator(const void *a, const void *b);
@ -48,11 +46,12 @@ void initQuadtree(Quadtree *root)
root->ents = malloc(sizeof(Entity*) * root->capacity); root->ents = malloc(sizeof(Entity*) * root->capacity);
memset(root->ents, 0, 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; w = root->w / 2;
h = root->h / 2; h = root->h / 2;
@ -101,11 +100,6 @@ void initQuadtree(Quadtree *root)
initQuadtree(node); 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) void addToQuadtree(Entity *e, Quadtree *root)
@ -277,23 +271,28 @@ void destroyQuadtree(void)
{ {
destroyQuadtreeNode(&battle.quadtree); destroyQuadtreeNode(&battle.quadtree);
free(candidates); if (candidates)
{
candidates = NULL; free(candidates);
candidates = NULL;
}
} }
static void destroyQuadtreeNode(Quadtree *root) static void destroyQuadtreeNode(Quadtree *root)
{ {
int i; int i;
free(root->ents);
root->ents = NULL;
if (root->node[0]) if (root->node[0])
{ {
for (i = 0 ; i < 4 ; i++) for (i = 0 ; i < 4 ; i++)
{ {
destroyQuadtreeNode(root->node[i]); destroyQuadtreeNode(root->node[i]);
free(root->node[i]->ents);
free(root->node[i]); free(root->node[i]);
root->node[i] = NULL; root->node[i] = NULL;

View File

@ -28,10 +28,24 @@ static ScriptRunner *tail;
void initScript(cJSON *scriptNode) void initScript(cJSON *scriptNode)
{ {
cJSON *function;
memset(&head, 0, sizeof(ScriptRunner)); memset(&head, 0, sizeof(ScriptRunner));
tail = &head; tail = &head;
scriptJSON = scriptNode; 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) 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) static void executeNextLine(ScriptRunner *runner)
{ {
char *line; char *line;
char command[24]; char command[24];
char strParam[2][256]; char strParam[3][256];
int intParam[2]; int intParam[2];
line = runner->line->valuestring; line = runner->line->valuestring;
@ -143,7 +211,12 @@ static void executeNextLine(ScriptRunner *runner)
} }
else if (strcmp(command, "ACTIVATE_JUMPGATE") == 0) 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) else if (strcmp(command, "MSG_BOX") == 0)
{ {
@ -183,6 +256,11 @@ static void executeNextLine(ScriptRunner *runner)
battle.isEpic = 0; battle.isEpic = 0;
retreatEnemies(); 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 else
{ {
printf("ERROR: Unrecognised script command '%s'\n", command); printf("ERROR: Unrecognised script command '%s'\n", command);
@ -196,6 +274,13 @@ static void executeNextLine(ScriptRunner *runner)
void destroyScript(void) void destroyScript(void)
{ {
ScriptRunner *scriptRunner; ScriptRunner *scriptRunner;
if (scriptJSON)
{
cJSON_Delete(scriptJSON);
scriptJSON = NULL;
}
while (head.next) while (head.next)
{ {

View File

@ -34,6 +34,9 @@ extern void activateLocations(char *locations);
void activateObjectives(char *objectives); void activateObjectives(char *objectives);
extern int showingMessageBoxes(void); extern int showingMessageBoxes(void);
extern char *getTranslatedString(char *string); 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 Battle battle;
extern Colors colors; extern Colors colors;

View File

@ -50,25 +50,29 @@ Entity *spawnWaypoint(void)
static void think(void) static void think(void)
{ {
self->thinkTime = 4; self->angle += 0.25;
self->angle++;
if (self->angle >= 360) if (self->angle >= 360)
{ {
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); if (self->health && player != NULL && getDistance(player->x, player->y, self->x, self->y) <= 128 && isCurrentObjective() && teamMatesClose())
{
runScriptFunction(self->name); self->health = 0;
activateNextWaypoint(self->id); updateObjective("Waypoint", TT_WAYPOINT);
battle.stats[STAT_WAYPOINTS_VISITED]++; runScriptFunction(self->name);
activateNextWaypoint(self->id);
battle.stats[STAT_WAYPOINTS_VISITED]++;
}
} }
} }
@ -79,7 +83,7 @@ static int isCurrentObjective(void)
if (numActiveObjectives > 1) if (numActiveObjectives > 1)
{ {
addHudMessage(colors.cyan, _("Cannot activate waypoint - outstanding objectives not yet complete")); addHudMessage(colors.cyan, _("Cannot activate waypoint - outstanding objectives not yet complete"));
self->thinkTime = FPS; self->aiActionTime = FPS;
return 0; return 0;
} }
@ -97,7 +101,7 @@ static int teamMatesClose(void)
if (getDistance(player->x, player->y, e->x, e->y) > 350) if (getDistance(player->x, player->y, e->x, e->y) > 350)
{ {
addHudMessage(colors.cyan, _("Cannot activate waypoint - team mates too far away")); addHudMessage(colors.cyan, _("Cannot activate waypoint - team mates too far away"));
self->thinkTime = FPS; self->aiActionTime = FPS;
return 0; return 0;
} }
} }

View File

@ -57,6 +57,7 @@ void initChallenges(void)
challengeDescription[CHALLENGE_PLAYER_KILLS] = _("Take down %d enemy targets"); challengeDescription[CHALLENGE_PLAYER_KILLS] = _("Take down %d enemy targets");
challengeDescription[CHALLENGE_DISABLE] = _("Disable %d or more enemy fighters"); challengeDescription[CHALLENGE_DISABLE] = _("Disable %d or more enemy fighters");
challengeDescription[CHALLENGE_ITEMS] = _("Collect %d packages"); challengeDescription[CHALLENGE_ITEMS] = _("Collect %d packages");
challengeDescription[CHALLENGE_RESCUE] = _("Rescue %d civilians");
tail = &game.challengeMissionHead; tail = &game.challengeMissionHead;
@ -128,6 +129,11 @@ static int challengeFinished(void)
return 1; 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) if (game.currentMission->challengeData.scriptedEnd)
{ {
return 1; return 1;

View File

@ -293,6 +293,7 @@ enum
CHALLENGE_PLAYER_KILLS, CHALLENGE_PLAYER_KILLS,
CHALLENGE_DISABLE, CHALLENGE_DISABLE,
CHALLENGE_ITEMS, CHALLENGE_ITEMS,
CHALLENGE_RESCUE,
CHALLENGE_MAX CHALLENGE_MAX
}; };

View File

@ -28,7 +28,6 @@ static void loadEntities(cJSON *node);
static void loadItems(cJSON *node); static void loadItems(cJSON *node);
static void loadLocations(cJSON *node); static void loadLocations(cJSON *node);
static unsigned long hashcode(const char *str); static unsigned long hashcode(const char *str);
static char **toTypeArray(char *types, int *numTypes);
static void loadEpicData(cJSON *node); static void loadEpicData(cJSON *node);
static char *getAutoBackground(char *filename); static char *getAutoBackground(char *filename);
static char *getAutoPlanet(char *filename); static char *getAutoPlanet(char *filename);
@ -87,6 +86,7 @@ Mission *loadMissionMeta(char *filename)
mission->challengeData.escapeLimit = getJSONValue(node, "escapeLimit", 0); mission->challengeData.escapeLimit = getJSONValue(node, "escapeLimit", 0);
mission->challengeData.waypointLimit = getJSONValue(node, "waypointLimit", 0); mission->challengeData.waypointLimit = getJSONValue(node, "waypointLimit", 0);
mission->challengeData.itemLimit = getJSONValue(node, "itemLimit", 0); mission->challengeData.itemLimit = getJSONValue(node, "itemLimit", 0);
mission->challengeData.rescueLimit = getJSONValue(node, "rescueLimit", 0);
/* restrictions */ /* restrictions */
mission->challengeData.noMissiles = getJSONValue(node, "noMissiles", 0); mission->challengeData.noMissiles = getJSONValue(node, "noMissiles", 0);
@ -121,6 +121,10 @@ Mission *loadMissionMeta(char *filename)
cJSON_Delete(root); cJSON_Delete(root);
} }
else
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to load '%s'", filename);
}
free(text); free(text);
@ -216,8 +220,6 @@ void loadMission(char *filename)
battle.status = MS_IN_PROGRESS; battle.status = MS_IN_PROGRESS;
} }
activateNextWaypoint();
countNumEnemies(); countNumEnemies();
initPlayer(); initPlayer();
@ -376,7 +378,7 @@ static void loadFighters(cJSON *node)
Entity *e; Entity *e;
char **types, *name, *groupName, *type; char **types, *name, *groupName, *type;
int side, scatter, number, active; int side, scatter, number, active;
int i, numTypes, addFlags, addAIFlags, systemPower; int i, numTypes, addFlags, addAIFlags;
long flags, aiFlags; long flags, aiFlags;
float x, y; float x, y;
@ -400,7 +402,6 @@ static void loadFighters(cJSON *node)
number = getJSONValue(node, "number", 1); number = getJSONValue(node, "number", 1);
scatter = getJSONValue(node, "scatter", 1); scatter = getJSONValue(node, "scatter", 1);
active = getJSONValue(node, "active", 1); active = getJSONValue(node, "active", 1);
systemPower = getJSONValue(node, "systemPower", MAX_SYSTEM_POWER);
if (cJSON_GetObjectItem(node, "flags")) if (cJSON_GetObjectItem(node, "flags"))
{ {
@ -463,12 +464,6 @@ static void loadFighters(cJSON *node)
{ {
STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH);
} }
e->systemPower = systemPower;
if (!e->systemPower)
{
e->flags |= EF_DISABLED;
}
} }
node = node->next; node = node->next;
@ -574,8 +569,9 @@ static void loadEntities(cJSON *node)
{ {
Entity *e; Entity *e;
char *name, *groupName; char *name, *groupName;
int i, type, scatter, number, active, systemPower; int i, type, scatter, number, active, addFlags;
float x, y; float x, y;
long flags;
if (node) if (node)
{ {
@ -595,7 +591,11 @@ static void loadEntities(cJSON *node)
number = getJSONValue(node, "number", 1); number = getJSONValue(node, "number", 1);
active = getJSONValue(node, "active", 1); active = getJSONValue(node, "active", 1);
scatter = getJSONValue(node, "scatter", 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++) for (i = 0 ; i < number ; i++)
{ {
@ -624,6 +624,20 @@ static void loadEntities(cJSON *node)
{ {
STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); 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->x = x;
e->y = y; e->y = y;
@ -636,8 +650,6 @@ static void loadEntities(cJSON *node)
e->active = active; e->active = active;
e->systemPower = systemPower;
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); 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) static void loadEpicData(cJSON *node)
{ {
Entity *e; Entity *e;

View File

@ -35,7 +35,6 @@ extern void stopMusic(void);
extern void initPlayer(void); extern void initPlayer(void);
extern long flagsToLong(char *flags, int *add); extern long flagsToLong(char *flags, int *add);
extern Entity *spawnWaypoint(void); extern Entity *spawnWaypoint(void);
extern void activateNextWaypoint(void);
extern void selectWidget(const char *name, const char *group); extern void selectWidget(const char *name, const char *group);
extern Entity *spawnJumpgate(void); extern Entity *spawnJumpgate(void);
extern Entity *spawnItem(char *type); extern Entity *spawnItem(char *type);
@ -55,6 +54,7 @@ extern char *getMusicFilename(int n);
extern int getJSONValue(cJSON *node, char *name, int defValue); extern int getJSONValue(cJSON *node, char *name, int defValue);
extern char *getJSONValueStr(cJSON *node, char *name, char *defValue); extern char *getJSONValueStr(cJSON *node, char *name, char *defValue);
extern void addAllEntsToQuadtree(void); extern void addAllEntsToQuadtree(void);
extern char **toTypeArray(char *types, int *numTypes);
extern Battle battle; extern Battle battle;
extern Entity *player; extern Entity *player;

View File

@ -27,9 +27,10 @@ int main(int argc, char *argv[])
float td; float td;
long then, lastFrameTime, frames; long then, lastFrameTime, frames;
long expireTextTimer; long expireTextTimer;
SDL_Event event; SDL_Event event;
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN);
memset(&app, 0, sizeof(App)); memset(&app, 0, sizeof(App));
memset(&dev, 0, sizeof(Dev)); memset(&dev, 0, sizeof(Dev));
@ -169,6 +170,8 @@ static void handleArguments(int argc, char *argv[])
dev.debug = 1; dev.debug = 1;
createScreenshotFolder(); createScreenshotFolder();
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
} }
} }
} }

View File

@ -251,6 +251,7 @@ typedef struct {
int itemLimit; int itemLimit;
int escapeLimit; int escapeLimit;
int waypointLimit; int waypointLimit;
int rescueLimit;
int noMissiles; int noMissiles;
int noBoost; int noBoost;
int noECM; int noECM;

View File

@ -79,7 +79,7 @@ void setLanguage(char *applicationName, char *languageCode)
STRNCPY(language, lang, MAX_LINE_LENGTH); 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); sprintf(c, "%s/%s/LC_MESSAGES/%s.mo", LOCALE_DIR, language, applicationName);

View File

@ -131,9 +131,9 @@ void initGameSystem(void)
initStarSystems, initStarSystems,
initChallenges, initChallenges,
initStats, initStats,
initBattle,
initModalDialog, initModalDialog,
initBackground, initBackground,
initStars,
initControls initControls
}; };
@ -338,10 +338,10 @@ void cleanup(void)
destroyWidgets(); destroyWidgets();
destroyResources(); destroyResources();
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Done");
TTF_Quit(); TTF_Quit();
SDL_Quit(); SDL_Quit();
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Done");
} }

View File

@ -70,6 +70,7 @@ extern void createSaveFolder(void);
extern void setLanguage(char *applicationName, char *languageCode); extern void setLanguage(char *applicationName, char *languageCode);
extern char *getLookupName(char *prefix, long num); extern char *getLookupName(char *prefix, long num);
extern long lookup(char *name); extern long lookup(char *name);
extern void initStars(void);
extern App app; extern App app;
extern Colors colors; extern Colors colors;

View File

@ -132,6 +132,7 @@ void initLookups(void)
addLookup("CHALLENGE_PLAYER_KILLS", CHALLENGE_PLAYER_KILLS); addLookup("CHALLENGE_PLAYER_KILLS", CHALLENGE_PLAYER_KILLS);
addLookup("CHALLENGE_DISABLE", CHALLENGE_DISABLE); addLookup("CHALLENGE_DISABLE", CHALLENGE_DISABLE);
addLookup("CHALLENGE_ITEMS", CHALLENGE_ITEMS); addLookup("CHALLENGE_ITEMS", CHALLENGE_ITEMS);
addLookup("CHALLENGE_RESCUE", CHALLENGE_RESCUE);
addLookup("STAT_PERCENT_COMPLETE", STAT_PERCENT_COMPLETE); addLookup("STAT_PERCENT_COMPLETE", STAT_PERCENT_COMPLETE);
addLookup("STAT_MISSIONS_STARTED", STAT_MISSIONS_STARTED); addLookup("STAT_MISSIONS_STARTED", STAT_MISSIONS_STARTED);

View File

@ -98,7 +98,20 @@ char *getMusicFilename(int i)
void destroyResources(void) void destroyResources(void)
{ {
free(backgrounds); int i;
free(planets);
free(musicFiles); 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]);
}
} }

View File

@ -73,6 +73,38 @@ void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy)
*dy /= steps; *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) char *timeToString(long millis, int showHours)
{ {
static char TIME[MAX_NAME_LENGTH]; static char TIME[MAX_NAME_LENGTH];

View File

@ -427,6 +427,10 @@ static void loadWidgetSet(char *filename)
cJSON_Delete(root); cJSON_Delete(root);
} }
else
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to load '%s'", filename);
}
free(text); free(text);
} }
@ -507,6 +511,8 @@ void destroyWidgets(void)
{ {
free(w->options[i]); free(w->options[i]);
} }
free(w->options);
next = w->next; next = w->next;
free(w); free(w);