Added getJSONValue to aid with optional JSON data.

This commit is contained in:
Steve 2016-03-04 14:14:04 +00:00
parent b6012a2e21
commit 95cb35d5a1
9 changed files with 501 additions and 572 deletions

View File

@ -38,24 +38,24 @@ static Entity defHead, *defTail;
Entity *spawnCapitalShip(char *name, int x, int y, int side) Entity *spawnCapitalShip(char *name, int x, int y, int side)
{ {
Entity *def, *e, *capitalShip; Entity *def, *e, *capitalShip;
capitalShip = NULL; capitalShip = NULL;
for (def = defHead.next ; def != NULL ; def = def->next) for (def = defHead.next ; def != NULL ; def = def->next)
{ {
if ((strcmp(def->name, name) == 0) || (def->owner != NULL && strcmp(def->owner->name, name) == 0)) if ((strcmp(def->name, name) == 0) || (def->owner != NULL && strcmp(def->owner->name, name) == 0))
{ {
e = spawnEntity(); e = spawnEntity();
memcpy(e, def, sizeof(Entity)); memcpy(e, def, sizeof(Entity));
e->id = battle.entId; e->id = battle.entId;
e->next = NULL; e->next = NULL;
e->x = x; e->x = x;
e->y = y; e->y = y;
e->side = side; e->side = side;
if (e->type == ET_CAPITAL_SHIP) if (e->type == ET_CAPITAL_SHIP)
{ {
capitalShip = e; capitalShip = e;
@ -66,13 +66,13 @@ Entity *spawnCapitalShip(char *name, int x, int y, int side)
} }
} }
} }
if (!capitalShip) if (!capitalShip)
{ {
printf("Error: no such capital ship '%s'\n", name); printf("Error: no such capital ship '%s'\n", name);
exit(1); exit(1);
} }
return capitalShip; return capitalShip;
} }
@ -85,12 +85,12 @@ void doCapitalShip(void)
self->health = 0; self->health = 0;
self->alive = ALIVE_DYING; self->alive = ALIVE_DYING;
self->die(); self->die();
if (self == battle.missionTarget) if (self == battle.missionTarget)
{ {
battle.missionTarget = NULL; battle.missionTarget = NULL;
} }
if (self->side == SIDE_ALLIES) if (self->side == SIDE_ALLIES)
{ {
battle.stats[STAT_CAPITAL_SHIPS_LOST]++; battle.stats[STAT_CAPITAL_SHIPS_LOST]++;
@ -107,25 +107,25 @@ static void think(void)
{ {
float dir; float dir;
int wantedAngle; int wantedAngle;
if (--self->aiActionTime <= 0) if (--self->aiActionTime <= 0)
{ {
findAITarget(); findAITarget();
} }
wantedAngle = steer(); wantedAngle = steer();
if (fabs(wantedAngle - self->angle) > TURN_THRESHOLD) if (fabs(wantedAngle - self->angle) > TURN_THRESHOLD)
{ {
dir = ((int)(wantedAngle - self->angle + 360)) % 360 > 180 ? -1 : 1; dir = ((int)(wantedAngle - self->angle + 360)) % 360 > 180 ? -1 : 1;
dir *= TURN_SPEED; dir *= TURN_SPEED;
self->angle += dir; self->angle += dir;
self->angle = fmod(self->angle, 360); self->angle = fmod(self->angle, 360);
} }
applyFighterThrust(); applyFighterThrust();
} }
@ -133,16 +133,16 @@ static void findAITarget(void)
{ {
Entity *e; Entity *e;
unsigned int dist, closest; unsigned int dist, closest;
self->target = NULL; self->target = NULL;
dist = closest = MAX_TARGET_RANGE; dist = closest = MAX_TARGET_RANGE;
for (e = battle.entityHead.next ; e != NULL ; e = e->next) for (e = battle.entityHead.next ; e != NULL ; e = e->next)
{ {
if (e->active && e->side != self->side && e->flags & EF_AI_TARGET) if (e->active && e->side != self->side && e->flags & EF_AI_TARGET)
{ {
dist = getDistance(self->x, self->y, e->x, e->y); dist = getDistance(self->x, self->y, e->x, e->y);
if (!self->target || dist < closest) if (!self->target || dist < closest)
{ {
self->target = e; self->target = e;
@ -150,19 +150,19 @@ static void findAITarget(void)
} }
} }
} }
if (self->target) if (self->target)
{ {
self->targetLocation.x = self->target->x + (rand() % 1000 - rand() % 1000); self->targetLocation.x = self->target->x + (rand() % 1000 - rand() % 1000);
self->targetLocation.y = self->target->y + (rand() % 1000 - rand() % 1000); self->targetLocation.y = self->target->y + (rand() % 1000 - rand() % 1000);
self->aiActionTime = FPS * 15; self->aiActionTime = FPS * 15;
} }
else else
{ {
self->targetLocation.x = 500 + (rand() % (BATTLE_AREA_WIDTH - 1000)); self->targetLocation.x = 500 + (rand() % (BATTLE_AREA_WIDTH - 1000));
self->targetLocation.y = 500 + (rand() % (BATTLE_AREA_HEIGHT - 1000)); self->targetLocation.y = 500 + (rand() % (BATTLE_AREA_HEIGHT - 1000));
self->aiActionTime = FPS * (30 + (rand() % 120)); self->aiActionTime = FPS * (30 + (rand() % 120));
} }
} }
@ -176,53 +176,53 @@ static int steer(void)
int count; int count;
Entity *e, **candidates; Entity *e, **candidates;
int i; int i;
dx = dy = 0; dx = dy = 0;
count = 0; count = 0;
force = 0; force = 0;
candidates = getAllEntsWithin(self->x - 1000, self->y - 1000, 2000, 2000, self); candidates = getAllEntsWithin(self->x - 1000, self->y - 1000, 2000, 2000, self);
for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i])
{ {
if (e->type == ET_CAPITAL_SHIP) if (e->type == ET_CAPITAL_SHIP)
{ {
distance = getDistance(e->x, e->y, self->x, self->y); distance = getDistance(e->x, e->y, self->x, self->y);
if (distance > 0 && distance < self->separationRadius) if (distance > 0 && distance < self->separationRadius)
{ {
angle = getAngle(self->x, self->y, e->x, e->y); angle = getAngle(self->x, self->y, e->x, e->y);
dx += sin(TO_RAIDANS(angle)); dx += sin(TO_RAIDANS(angle));
dy += -cos(TO_RAIDANS(angle)); dy += -cos(TO_RAIDANS(angle));
force += (self->separationRadius - distance); force += (self->separationRadius - distance);
count++; count++;
} }
} }
} }
if (count > 0) if (count > 0)
{ {
dx /= count; dx /= count;
dy /= count; dy /= count;
dx *= force; dx *= force;
dy *= force; dy *= force;
self->dx -= (dx * 0.001); self->dx -= (dx * 0.001);
self->dy -= (dy * 0.001); self->dy -= (dy * 0.001);
self->targetLocation.x -= dx; self->targetLocation.x -= dx;
self->targetLocation.y -= dy; self->targetLocation.y -= dy;
self->aiActionTime = FPS * 10; self->aiActionTime = FPS * 10;
} }
wantedAngle = getAngle(self->x, self->y, self->targetLocation.x, self->targetLocation.y); wantedAngle = getAngle(self->x, self->y, self->targetLocation.x, self->targetLocation.y);
wantedAngle %= 360; wantedAngle %= 360;
return wantedAngle; return wantedAngle;
} }
@ -237,9 +237,9 @@ static void componentDie(void)
addSmallExplosion(); addSmallExplosion();
playBattleSound(SND_EXPLOSION_1 + rand() % 4, self->x, self->y); playBattleSound(SND_EXPLOSION_1 + rand() % 4, self->x, self->y);
addDebris(self->x, self->y, 3 + rand() % 4); addDebris(self->x, self->y, 3 + rand() % 4);
self->owner->health--; self->owner->health--;
if (self->owner->health > 0) if (self->owner->health > 0)
{ {
runScriptFunction("CAP_HEALTH %s %d", self->owner->name, self->owner->health); runScriptFunction("CAP_HEALTH %s %d", self->owner->name, self->owner->health);
@ -262,12 +262,12 @@ static void engineThink(void)
static void engineDie(void) static void engineDie(void)
{ {
Entity *e; Entity *e;
self->alive = ALIVE_DEAD; self->alive = ALIVE_DEAD;
addSmallExplosion(); addSmallExplosion();
playBattleSound(SND_EXPLOSION_1 + rand() % 4, self->x, self->y); playBattleSound(SND_EXPLOSION_1 + rand() % 4, self->x, self->y);
addDebris(self->x, self->y, 4 + rand() % 9); addDebris(self->x, self->y, 4 + rand() % 9);
for (e = battle.entityHead.next ; e != NULL ; e = e->next) for (e = battle.entityHead.next ; e != NULL ; e = e->next)
{ {
if (e != self && e->owner == self->owner && e->type == ET_CAPITAL_SHIP_ENGINE) if (e != self && e->owner == self->owner && e->type == ET_CAPITAL_SHIP_ENGINE)
@ -275,14 +275,14 @@ static void engineDie(void)
return; return;
} }
} }
/* no more engines - stop moving */ /* no more engines - stop moving */
if (self->owner->health > 0) if (self->owner->health > 0)
{ {
self->owner->speed = 0; self->owner->speed = 0;
self->owner->action = NULL; self->owner->action = NULL;
self->owner->dx = self->owner->dy = 0; self->owner->dx = self->owner->dy = 0;
runScriptFunction("CAP_ENGINES_DESTROYED %s", self->owner->name); runScriptFunction("CAP_ENGINES_DESTROYED %s", self->owner->name);
} }
} }
@ -290,11 +290,11 @@ static void engineDie(void)
static void die(void) static void die(void)
{ {
Entity *e; Entity *e;
self->alive = ALIVE_DEAD; self->alive = ALIVE_DEAD;
addDebris(self->x, self->y, 50); addDebris(self->x, self->y, 50);
for (e = battle.entityHead.next ; e != NULL ; e = e->next) for (e = battle.entityHead.next ; e != NULL ; e = e->next)
{ {
if (e->owner == self) if (e->owner == self)
@ -302,9 +302,9 @@ static void die(void)
e->health = 0; e->health = 0;
} }
} }
updateObjective(self->name, TT_DESTROY); updateObjective(self->name, TT_DESTROY);
updateObjective(self->groupName, TT_DESTROY); updateObjective(self->groupName, TT_DESTROY);
} }
@ -313,21 +313,21 @@ void loadCapitalShipDefs(void)
char **filenames; char **filenames;
char path[MAX_FILENAME_LENGTH]; char path[MAX_FILENAME_LENGTH];
int count, i; int count, i;
memset(&defHead, 0, sizeof(Entity)); memset(&defHead, 0, sizeof(Entity));
defTail = &defHead; defTail = &defHead;
filenames = getFileList(getFileLocation("data/capitalShips"), &count); filenames = getFileList(getFileLocation("data/capitalShips"), &count);
for (i = 0 ; i < count ; i++) for (i = 0 ; i < count ; i++)
{ {
sprintf(path, "data/capitalShips/%s", filenames[i]); sprintf(path, "data/capitalShips/%s", filenames[i]);
loadCapitalShipDef(path); loadCapitalShipDef(path);
free(filenames[i]); free(filenames[i]);
} }
free(filenames); free(filenames);
} }
@ -336,41 +336,41 @@ static void loadCapitalShipDef(char *filename)
cJSON *root; cJSON *root;
char *text; char *text;
Entity *e; Entity *e;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", filename); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", filename);
text = readFile(getFileLocation(filename)); text = readFile(getFileLocation(filename));
e = malloc(sizeof(Entity)); e = malloc(sizeof(Entity));
memset(e, 0, sizeof(Entity)); memset(e, 0, sizeof(Entity));
defTail->next = e; defTail->next = e;
defTail = e; defTail = e;
e->type = ET_CAPITAL_SHIP; e->type = ET_CAPITAL_SHIP;
e->active = 1; e->active = 1;
root = cJSON_Parse(text); root = cJSON_Parse(text);
STRNCPY(e->name, cJSON_GetObjectItem(root, "name")->valuestring, MAX_NAME_LENGTH); STRNCPY(e->name, cJSON_GetObjectItem(root, "name")->valuestring, MAX_NAME_LENGTH);
STRNCPY(e->defName, e->name, MAX_NAME_LENGTH); STRNCPY(e->defName, e->name, MAX_NAME_LENGTH);
e->shield = e->maxShield = cJSON_GetObjectItem(root, "shield")->valueint; e->shield = e->maxShield = cJSON_GetObjectItem(root, "shield")->valueint;
e->shieldRechargeRate = cJSON_GetObjectItem(root, "shieldRechargeRate")->valueint; e->shieldRechargeRate = cJSON_GetObjectItem(root, "shieldRechargeRate")->valueint;
e->texture = getTexture(cJSON_GetObjectItem(root, "texture")->valuestring); e->texture = getTexture(cJSON_GetObjectItem(root, "texture")->valuestring);
e->speed = 1; e->speed = 1;
e->action = think; e->action = think;
e->die = die; e->die = die;
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h);
e->separationRadius = MAX(e->w, e->h); e->separationRadius = MAX(e->w, e->h);
loadComponents(e, cJSON_GetObjectItem(root, "components")); loadComponents(e, cJSON_GetObjectItem(root, "components"));
loadGuns(e, cJSON_GetObjectItem(root, "guns")); loadGuns(e, cJSON_GetObjectItem(root, "guns"));
loadEngines(e, cJSON_GetObjectItem(root, "engines")); loadEngines(e, cJSON_GetObjectItem(root, "engines"));
cJSON_Delete(root); cJSON_Delete(root);
free(text); free(text);
} }
@ -379,52 +379,52 @@ static void loadComponents(Entity *parent, cJSON *components)
{ {
Entity *e; Entity *e;
cJSON *component; cJSON *component;
parent->health = 0; parent->health = 0;
if (components) if (components)
{ {
component = components->child; component = components->child;
while (component) while (component)
{ {
e = malloc(sizeof(Entity)); e = malloc(sizeof(Entity));
memset(e, 0, sizeof(Entity)); memset(e, 0, sizeof(Entity));
defTail->next = e; defTail->next = e;
defTail = e; defTail = e;
e->active = 1; e->active = 1;
e->type = ET_CAPITAL_SHIP_COMPONENT; e->type = ET_CAPITAL_SHIP_COMPONENT;
e->health = e->maxHealth = cJSON_GetObjectItem(component, "health")->valueint; e->health = e->maxHealth = cJSON_GetObjectItem(component, "health")->valueint;
e->offsetX = cJSON_GetObjectItem(component, "x")->valueint; e->offsetX = cJSON_GetObjectItem(component, "x")->valueint;
e->offsetY = cJSON_GetObjectItem(component, "y")->valueint; e->offsetY = cJSON_GetObjectItem(component, "y")->valueint;
e->texture = getTexture(cJSON_GetObjectItem(component, "texture")->valuestring); e->texture = getTexture(cJSON_GetObjectItem(component, "texture")->valuestring);
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h);
if (cJSON_GetObjectItem(component, "flags")) if (cJSON_GetObjectItem(component, "flags"))
{ {
e->flags = flagsToLong(cJSON_GetObjectItem(component, "flags")->valuestring, NULL); e->flags = flagsToLong(cJSON_GetObjectItem(component, "flags")->valuestring, NULL);
} }
if (cJSON_GetObjectItem(component, "aiFlags")) if (cJSON_GetObjectItem(component, "aiFlags"))
{ {
e->aiFlags = flagsToLong(cJSON_GetObjectItem(component, "aiFlags")->valuestring, NULL); e->aiFlags = flagsToLong(cJSON_GetObjectItem(component, "aiFlags")->valuestring, NULL);
} }
e->systemPower = 100; e->systemPower = 100;
e->die = componentDie; e->die = componentDie;
e->owner = parent; e->owner = parent;
component = component->next; component = component->next;
parent->health++; parent->health++;
} }
} }
parent->maxHealth = parent->health; parent->maxHealth = parent->health;
} }
@ -432,20 +432,20 @@ static void loadGuns(Entity *parent, cJSON *guns)
{ {
Entity *e; Entity *e;
cJSON *gun; cJSON *gun;
if (guns) if (guns)
{ {
gun = guns->child; gun = guns->child;
while (gun) while (gun)
{ {
e = malloc(sizeof(Entity)); e = malloc(sizeof(Entity));
memset(e, 0, sizeof(Entity)); memset(e, 0, sizeof(Entity));
defTail->next = e; defTail->next = e;
defTail = e; defTail = e;
e->active = 1; e->active = 1;
e->type = ET_CAPITAL_SHIP_GUN; e->type = ET_CAPITAL_SHIP_GUN;
e->health = e->maxHealth = cJSON_GetObjectItem(gun, "health")->valueint; e->health = e->maxHealth = cJSON_GetObjectItem(gun, "health")->valueint;
e->reloadTime = cJSON_GetObjectItem(gun, "reloadTime")->valueint; e->reloadTime = cJSON_GetObjectItem(gun, "reloadTime")->valueint;
@ -453,31 +453,27 @@ static void loadGuns(Entity *parent, cJSON *guns)
e->offsetY = cJSON_GetObjectItem(gun, "y")->valueint; e->offsetY = cJSON_GetObjectItem(gun, "y")->valueint;
e->texture = getTexture(cJSON_GetObjectItem(gun, "texture")->valuestring); e->texture = getTexture(cJSON_GetObjectItem(gun, "texture")->valuestring);
e->guns[0].type = lookup(cJSON_GetObjectItem(gun, "type")->valuestring); e->guns[0].type = lookup(cJSON_GetObjectItem(gun, "type")->valuestring);
e->missiles = getJSONValue(gun, "missiles", 0);
if (cJSON_GetObjectItem(gun, "missiles"))
{
e->missiles = cJSON_GetObjectItem(gun, "missiles")->valueint;
}
if (cJSON_GetObjectItem(gun, "flags")) if (cJSON_GetObjectItem(gun, "flags"))
{ {
e->flags = flagsToLong(cJSON_GetObjectItem(gun, "flags")->valuestring, NULL); e->flags = flagsToLong(cJSON_GetObjectItem(gun, "flags")->valuestring, NULL);
} }
if (cJSON_GetObjectItem(gun, "aiFlags")) if (cJSON_GetObjectItem(gun, "aiFlags"))
{ {
e->aiFlags = flagsToLong(cJSON_GetObjectItem(gun, "aiFlags")->valuestring, NULL); e->aiFlags = flagsToLong(cJSON_GetObjectItem(gun, "aiFlags")->valuestring, NULL);
} }
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h);
e->systemPower = 100; e->systemPower = 100;
e->action = gunThink; e->action = gunThink;
e->die = gunDie; e->die = gunDie;
e->owner = parent; e->owner = parent;
gun = gun->next; gun = gun->next;
} }
} }
@ -487,40 +483,40 @@ static void loadEngines(Entity *parent, cJSON *engines)
{ {
Entity *e; Entity *e;
cJSON *engine; cJSON *engine;
if (engines) if (engines)
{ {
engine = engines->child; engine = engines->child;
while (engine) while (engine)
{ {
e = malloc(sizeof(Entity)); e = malloc(sizeof(Entity));
memset(e, 0, sizeof(Entity)); memset(e, 0, sizeof(Entity));
defTail->next = e; defTail->next = e;
defTail = e; defTail = e;
e->active = 1; e->active = 1;
e->type = ET_CAPITAL_SHIP_ENGINE; e->type = ET_CAPITAL_SHIP_ENGINE;
e->health = e->maxHealth = cJSON_GetObjectItem(engine, "health")->valueint; e->health = e->maxHealth = cJSON_GetObjectItem(engine, "health")->valueint;
e->offsetX = cJSON_GetObjectItem(engine, "x")->valueint; e->offsetX = cJSON_GetObjectItem(engine, "x")->valueint;
e->offsetY = cJSON_GetObjectItem(engine, "y")->valueint; e->offsetY = cJSON_GetObjectItem(engine, "y")->valueint;
e->texture = getTexture(cJSON_GetObjectItem(engine, "texture")->valuestring); e->texture = getTexture(cJSON_GetObjectItem(engine, "texture")->valuestring);
if (cJSON_GetObjectItem(engine, "flags")) if (cJSON_GetObjectItem(engine, "flags"))
{ {
e->flags = flagsToLong(cJSON_GetObjectItem(engine, "flags")->valuestring, NULL); e->flags = flagsToLong(cJSON_GetObjectItem(engine, "flags")->valuestring, NULL);
} }
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h);
e->systemPower = 100; e->systemPower = 100;
e->action = engineThink; e->action = engineThink;
e->die = engineDie; e->die = engineDie;
e->owner = parent; e->owner = parent;
engine = engine->next; engine = engine->next;
} }
} }
@ -529,7 +525,7 @@ static void loadEngines(Entity *parent, cJSON *engines)
void updateCapitalShipComponentProperties(Entity *parent) void updateCapitalShipComponentProperties(Entity *parent)
{ {
Entity *e; Entity *e;
for (e = battle.entityHead.next ; e != NULL ; e = e->next) for (e = battle.entityHead.next ; e != NULL ; e = e->next)
{ {
if (e->owner == parent) if (e->owner == parent)
@ -539,16 +535,16 @@ void updateCapitalShipComponentProperties(Entity *parent)
case ET_CAPITAL_SHIP_ENGINE: case ET_CAPITAL_SHIP_ENGINE:
sprintf(e->name, "%s (Engine)", parent->name); sprintf(e->name, "%s (Engine)", parent->name);
break; break;
case ET_CAPITAL_SHIP_COMPONENT: case ET_CAPITAL_SHIP_COMPONENT:
sprintf(e->name, "%s (Component)", parent->name); sprintf(e->name, "%s (Component)", parent->name);
break; break;
case ET_CAPITAL_SHIP_GUN: case ET_CAPITAL_SHIP_GUN:
sprintf(e->name, "%s (Gun)", parent->name); sprintf(e->name, "%s (Gun)", parent->name);
break; break;
} }
e->active = parent->active; e->active = parent->active;
} }
} }
@ -557,7 +553,7 @@ void updateCapitalShipComponentProperties(Entity *parent)
void destroyCapitalShipDefs(void) void destroyCapitalShipDefs(void)
{ {
Entity *e; Entity *e;
while (defHead.next) while (defHead.next)
{ {
e = defHead.next; e = defHead.next;

View File

@ -47,6 +47,7 @@ extern void addDebris(int x, int y, int amount);
extern void runScriptFunction(char *format, ...); extern void runScriptFunction(char *format, ...);
extern void updateObjective(char *name, int type); extern void updateObjective(char *name, int type);
extern char **getFileList(char *dir, int *count); extern char **getFileList(char *dir, int *count);
extern int getJSONValue(cJSON *node, char *name, int defValue);
extern Battle battle; extern Battle battle;
extern Entity *self; extern Entity *self;

View File

@ -36,20 +36,20 @@ static Entity defHead, *defTail;
Entity *spawnFighter(char *name, int x, int y, int side) Entity *spawnFighter(char *name, int x, int y, int side)
{ {
Entity *e, *def; Entity *e, *def;
e = spawnEntity(); e = spawnEntity();
def = getFighterDef(name); def = getFighterDef(name);
memcpy(e, def, sizeof(Entity)); memcpy(e, def, sizeof(Entity));
e->id = battle.entId; e->id = battle.entId;
e->next = NULL; e->next = NULL;
e->x = x; e->x = x;
e->y = y; e->y = y;
e->side = side; e->side = side;
switch (side) switch (side)
{ {
case SIDE_ALLIES: case SIDE_ALLIES:
@ -59,91 +59,91 @@ Entity *spawnFighter(char *name, int x, int y, int side)
e->aiFlags |= AIF_MOVES_TO_PLAYER; e->aiFlags |= AIF_MOVES_TO_PLAYER;
} }
break; break;
case SIDE_PIRATE: case SIDE_PIRATE:
e->aiAggression = rand() % 3; e->aiAggression = rand() % 3;
break; break;
case SIDE_PANDORAN: case SIDE_PANDORAN:
e->aiAggression = 3 + rand() % 2; e->aiAggression = 3 + rand() % 2;
break; break;
case SIDE_REBEL: case SIDE_REBEL:
e->aiAggression = 1 + rand() % 3; e->aiAggression = 1 + rand() % 3;
break; break;
} }
if (strcmp(name, "ATAF") == 0) if (strcmp(name, "ATAF") == 0)
{ {
e->aiAggression = 4; e->aiAggression = 4;
} }
if (strcmp(name, "Dart") == 0) if (strcmp(name, "Dart") == 0)
{ {
randomizeDart(e); randomizeDart(e);
} }
if (strcmp(name, "Civilian") == 0 && rand() % 2 == 0) if (strcmp(name, "Civilian") == 0 && rand() % 2 == 0)
{ {
e->texture = getTexture("gfx/craft/civilian02.png"); e->texture = getTexture("gfx/craft/civilian02.png");
} }
if (e->aiFlags & AIF_AGGRESSIVE) if (e->aiFlags & AIF_AGGRESSIVE)
{ {
e->aiAggression = 4; e->aiAggression = 4;
} }
e->action = doAI; e->action = doAI;
e->die = die; e->die = die;
return e; return e;
} }
static void randomizeDart(Entity *dart) static void randomizeDart(Entity *dart)
{ {
char texture[MAX_DESCRIPTION_LENGTH]; char texture[MAX_DESCRIPTION_LENGTH];
if (rand() % 5 == 0) if (rand() % 5 == 0)
{ {
dart->health = dart->maxHealth = 5 + (rand() % 21); dart->health = dart->maxHealth = 5 + (rand() % 21);
} }
if (rand() % 5 == 0) if (rand() % 5 == 0)
{ {
dart->shield = dart->maxShield = 1 + (rand() % 16); dart->shield = dart->maxShield = 1 + (rand() % 16);
dart->shieldRechargeRate = 30 + (rand() % 90); dart->shieldRechargeRate = 30 + (rand() % 90);
} }
if (rand() % 5 == 0) if (rand() % 5 == 0)
{ {
dart->speed = 2 + (rand() % 3); dart->speed = 2 + (rand() % 3);
} }
if (rand() % 5 == 0) if (rand() % 5 == 0)
{ {
dart->reloadTime = 24 + (rand() % 11); dart->reloadTime = 24 + (rand() % 11);
} }
randomizeDartGuns(dart); randomizeDartGuns(dart);
dart->missiles = rand() % 3; dart->missiles = rand() % 3;
sprintf(texture, "gfx/fighters/dart0%d.png", 1 + rand() % 7); sprintf(texture, "gfx/fighters/dart0%d.png", 1 + rand() % 7);
dart->texture = getTexture(texture); dart->texture = getTexture(texture);
} }
static void randomizeDartGuns(Entity *dart) static void randomizeDartGuns(Entity *dart)
{ {
int i; int i;
switch (rand() % 4) switch (rand() % 4)
{ {
/* Single plasma gun */ /* Single plasma gun */
case 0: case 0:
dart->guns[0].type = BT_PLASMA; dart->guns[0].type = BT_PLASMA;
dart->guns[0].x = dart->guns[0].y = 0; dart->guns[0].x = dart->guns[0].y = 0;
for (i = 1 ; i < MAX_FIGHTER_GUNS ; i++) for (i = 1 ; i < MAX_FIGHTER_GUNS ; i++)
{ {
if (dart->guns[i].type) if (dart->guns[i].type)
@ -152,25 +152,25 @@ static void randomizeDartGuns(Entity *dart)
} }
} }
break; break;
/* Dual plasma guns */ /* Dual plasma guns */
case 1: case 1:
dart->guns[0].type = BT_PLASMA; dart->guns[0].type = BT_PLASMA;
dart->guns[1].type = BT_PLASMA; dart->guns[1].type = BT_PLASMA;
break; break;
/* Triple particle guns */ /* Triple particle guns */
case 2: case 2:
dart->guns[2].type = BT_PARTICLE; dart->guns[2].type = BT_PARTICLE;
dart->guns[2].y = -10; dart->guns[2].y = -10;
break; break;
/* Plasma / Laser cannons */ /* Plasma / Laser cannons */
case 3: case 3:
dart->guns[0].type = BT_PLASMA; dart->guns[0].type = BT_PLASMA;
dart->guns[0].x = dart->guns[0].y = 0; dart->guns[0].x = dart->guns[0].y = 0;
dart->guns[1].type = BT_LASER; dart->guns[1].type = BT_LASER;
dart->guns[1].x = dart->guns[1].y = 0; dart->guns[1].x = dart->guns[1].y = 0;
break; break;
@ -191,20 +191,20 @@ void doFighter(void)
{ {
separate(); separate();
} }
attachRope(); attachRope();
if (self->thrust > 0.25) if (self->thrust > 0.25)
{ {
addEngineEffect(); addEngineEffect();
} }
if (self->health <= 0) if (self->health <= 0)
{ {
self->health = 0; self->health = 0;
self->alive = ALIVE_DYING; self->alive = ALIVE_DYING;
self->die(); self->die();
if (self == battle.missionTarget) if (self == battle.missionTarget)
{ {
battle.missionTarget = NULL; battle.missionTarget = NULL;
@ -217,38 +217,38 @@ void doFighter(void)
self->thrust = 0; self->thrust = 0;
self->shield = self->maxShield = 0; self->shield = self->maxShield = 0;
self->action = NULL; self->action = NULL;
if ((self->flags & EF_DISABLED) == 0) if ((self->flags & EF_DISABLED) == 0)
{ {
playBattleSound(SND_POWER_DOWN, self->x, self->y); playBattleSound(SND_POWER_DOWN, self->x, self->y);
self->flags |= EF_DISABLED; self->flags |= EF_DISABLED;
self->flags |= EF_SECONDARY_TARGET; self->flags |= EF_SECONDARY_TARGET;
battle.stats[STAT_ENEMIES_DISABLED]++; battle.stats[STAT_ENEMIES_DISABLED]++;
updateObjective(self->name, TT_DISABLE); updateObjective(self->name, TT_DISABLE);
} }
} }
if (self->target != NULL && self->target->alive != ALIVE_ALIVE) if (self->target != NULL && self->target->alive != ALIVE_ALIVE)
{ {
self->target = NULL; self->target = NULL;
if (self != player) if (self != player)
{ {
self->action = doAI; self->action = doAI;
} }
} }
} }
if (self->alive == ALIVE_ESCAPED) if (self->alive == ALIVE_ESCAPED)
{ {
if (self == player) if (self == player)
{ {
completeMission(); completeMission();
} }
if (self->side != SIDE_ALLIES && (!(self->flags & EF_DISABLED))) if (self->side != SIDE_ALLIES && (!(self->flags & EF_DISABLED)))
{ {
addHudMessage(colors.red, _("Mission target has escaped.")); addHudMessage(colors.red, _("Mission target has escaped."));
@ -258,12 +258,12 @@ void doFighter(void)
{ {
battle.stats[STAT_CIVILIANS_RESCUED]++; battle.stats[STAT_CIVILIANS_RESCUED]++;
} }
updateObjective(self->name, TT_ESCAPED); updateObjective(self->name, TT_ESCAPED);
updateCondition(self->name, TT_ESCAPED); updateCondition(self->name, TT_ESCAPED);
} }
if (self->alive == ALIVE_DEAD) if (self->alive == ALIVE_DEAD)
{ {
if (self == player) if (self == player)
@ -277,7 +277,7 @@ void doFighter(void)
if (self->side != SIDE_ALLIES) if (self->side != SIDE_ALLIES)
{ {
battle.stats[STAT_ENEMIES_KILLED]++; battle.stats[STAT_ENEMIES_KILLED]++;
runScriptFunction("ENEMIES_KILLED %d", battle.stats[STAT_ENEMIES_KILLED]); runScriptFunction("ENEMIES_KILLED %d", battle.stats[STAT_ENEMIES_KILLED]);
} }
else else
@ -297,17 +297,17 @@ void doFighter(void)
{ {
addHudMessage(colors.red, _("Ally has been killed")); addHudMessage(colors.red, _("Ally has been killed"));
} }
runScriptFunction("ALLIES_KILLED %d", battle.stats[STAT_ALLIES_KILLED]); runScriptFunction("ALLIES_KILLED %d", battle.stats[STAT_ALLIES_KILLED]);
} }
} }
} }
updateObjective(self->name, TT_DESTROY); updateObjective(self->name, TT_DESTROY);
updateObjective(self->groupName, TT_DESTROY); updateObjective(self->groupName, TT_DESTROY);
adjustObjectiveTargetValue(self->name, TT_ESCAPED, -1); adjustObjectiveTargetValue(self->name, TT_ESCAPED, -1);
updateCondition(self->name, TT_DESTROY); updateCondition(self->name, TT_DESTROY);
} }
} }
@ -321,40 +321,40 @@ static void separate(void)
int count; int count;
Entity *e, **candidates; Entity *e, **candidates;
int i; int i;
dx = dy = 0; dx = dy = 0;
count = 0; count = 0;
force = 0; force = 0;
candidates = getAllEntsWithin(self->x - (self->w / 2), self->y - (self->h / 2), self->w, self->h, self); candidates = getAllEntsWithin(self->x - (self->w / 2), self->y - (self->h / 2), self->w, self->h, self);
for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i])
{ {
if (e->flags & EF_TAKES_DAMAGE) if (e->flags & EF_TAKES_DAMAGE)
{ {
distance = getDistance(e->x, e->y, self->x, self->y); distance = getDistance(e->x, e->y, self->x, self->y);
if (distance > 0 && distance < self->separationRadius) if (distance > 0 && distance < self->separationRadius)
{ {
angle = getAngle(self->x, self->y, e->x, e->y); angle = getAngle(self->x, self->y, e->x, e->y);
dx += sin(TO_RAIDANS(angle)); dx += sin(TO_RAIDANS(angle));
dy += -cos(TO_RAIDANS(angle)); dy += -cos(TO_RAIDANS(angle));
force += (self->separationRadius - distance) * 0.005; force += (self->separationRadius - distance) * 0.005;
count++; count++;
} }
} }
} }
if (count > 0) if (count > 0)
{ {
dx /= count; dx /= count;
dy /= count; dy /= count;
dx *= force; dx *= force;
dy *= force; dy *= force;
self->dx -= dx; self->dx -= dx;
self->dy -= dy; self->dy -= dy;
} }
@ -363,11 +363,11 @@ static void separate(void)
void applyFighterThrust(void) void applyFighterThrust(void)
{ {
float v; float v;
self->dx += sin(TO_RAIDANS(self->angle)) * 0.1; self->dx += sin(TO_RAIDANS(self->angle)) * 0.1;
self->dy += -cos(TO_RAIDANS(self->angle)) * 0.1; self->dy += -cos(TO_RAIDANS(self->angle)) * 0.1;
self->thrust = sqrt((self->dx * self->dx) + (self->dy * self->dy)); self->thrust = sqrt((self->dx * self->dx) + (self->dy * self->dy));
if (self->thrust > self->speed * self->speed) if (self->thrust > self->speed * self->speed)
{ {
v = (self->speed / sqrt(self->thrust)); v = (self->speed / sqrt(self->thrust));
@ -381,25 +381,25 @@ void applyFighterBrakes(void)
{ {
self->dx *= 0.95; self->dx *= 0.95;
self->dy *= 0.95; self->dy *= 0.95;
self->thrust = sqrt((self->dx * self->dx) + (self->dy * self->dy)); self->thrust = sqrt((self->dx * self->dx) + (self->dy * self->dy));
} }
void damageFighter(Entity *e, int amount, long flags) void damageFighter(Entity *e, int amount, long flags)
{ {
int prevShield = e->shield; int prevShield = e->shield;
e->aiDamageTimer = FPS; e->aiDamageTimer = FPS;
e->aiDamagePerSec += amount; e->aiDamagePerSec += amount;
if (flags & BF_SYSTEM_DAMAGE) if (flags & BF_SYSTEM_DAMAGE)
{ {
playBattleSound(SND_MAG_HIT, e->x, e->y); playBattleSound(SND_MAG_HIT, e->x, e->y);
e->systemPower = MAX(0, e->systemPower - amount); e->systemPower = MAX(0, e->systemPower - amount);
e->systemHit = 255; e->systemHit = 255;
if (e->systemPower == 0) if (e->systemPower == 0)
{ {
e->shield = e->maxShield = 0; e->shield = e->maxShield = 0;
@ -409,14 +409,14 @@ void damageFighter(Entity *e, int amount, long flags)
else if (flags & BF_SHIELD_DAMAGE) else if (flags & BF_SHIELD_DAMAGE)
{ {
e->shield -= amount; e->shield -= amount;
if (e->shield <= 0 && prevShield > 0) if (e->shield <= 0 && prevShield > 0)
{ {
playBattleSound(SND_SHIELD_BREAK, e->x, e->y); playBattleSound(SND_SHIELD_BREAK, e->x, e->y);
addShieldSplinterEffect(e); addShieldSplinterEffect(e);
e->shield = -(FPS * 10); e->shield = -(FPS * 10);
} }
e->shield = MAX(-(FPS * 10), e->shield); e->shield = MAX(-(FPS * 10), e->shield);
} }
else else
@ -424,7 +424,7 @@ void damageFighter(Entity *e, int amount, long flags)
if (e->shield > 0) if (e->shield > 0)
{ {
e->shield -= amount; e->shield -= amount;
if (e->shield < 0) if (e->shield < 0)
{ {
e->health += e->shield; e->health += e->shield;
@ -435,21 +435,21 @@ void damageFighter(Entity *e, int amount, long flags)
{ {
e->health -= amount; e->health -= amount;
e->armourHit = 255; e->armourHit = 255;
playBattleSound(SND_ARMOUR_HIT, e->x, e->y); playBattleSound(SND_ARMOUR_HIT, e->x, e->y);
} }
} }
if (e->shield > 0) if (e->shield > 0)
{ {
e->shieldHit = 255; e->shieldHit = 255;
/* don't allow the shield to recharge immediately after taking a hit */ /* don't allow the shield to recharge immediately after taking a hit */
e->shieldRecharge = e->shieldRechargeRate; e->shieldRecharge = e->shieldRechargeRate;
playBattleSound(SND_SHIELD_HIT, e->x, e->y); playBattleSound(SND_SHIELD_HIT, e->x, e->y);
} }
/* /*
* Sometimes run away if you take too much damage in a short space of time * Sometimes run away if you take too much damage in a short space of time
*/ */
@ -471,7 +471,7 @@ void damageFighter(Entity *e, int amount, long flags)
static void die(void) static void die(void)
{ {
int n = rand() % 3; int n = rand() % 3;
switch (self->deathType) switch (self->deathType)
{ {
case DT_ANY: case DT_ANY:
@ -484,22 +484,22 @@ static void die(void)
n = 2; n = 2;
break; break;
} }
if (self == player && battle.isEpic) if (self == player && battle.isEpic)
{ {
n = 1; n = 1;
} }
switch (n) switch (n)
{ {
case 0: case 0:
self->action = spinDie; self->action = spinDie;
break; break;
case 1: case 1:
self->action = straightDie; self->action = straightDie;
break; break;
case 2: case 2:
self->action = immediateDie; self->action = immediateDie;
break; break;
@ -521,14 +521,14 @@ static void spinDie(void)
self->armourHit = 0; self->armourHit = 0;
self->shieldHit = 0; self->shieldHit = 0;
self->systemHit = 0; self->systemHit = 0;
self->angle += 8; self->angle += 8;
if (rand() % 2 == 0) if (rand() % 2 == 0)
{ {
addSmallFighterExplosion(); addSmallFighterExplosion();
} }
if (self->health <= -(FPS * 1.5)) if (self->health <= -(FPS * 1.5))
{ {
self->alive = ALIVE_DEAD; self->alive = ALIVE_DEAD;
@ -545,12 +545,12 @@ static void straightDie(void)
self->armourHit = 0; self->armourHit = 0;
self->shieldHit = 0; self->shieldHit = 0;
self->systemHit = 0; self->systemHit = 0;
if (rand() % 2 == 0) if (rand() % 2 == 0)
{ {
addSmallFighterExplosion(); addSmallFighterExplosion();
} }
if (self->health <= -(FPS * 1.5)) if (self->health <= -(FPS * 1.5))
{ {
self->alive = ALIVE_DEAD; self->alive = ALIVE_DEAD;
@ -563,7 +563,7 @@ static void straightDie(void)
void retreatEnemies(void) void retreatEnemies(void)
{ {
Entity *e; Entity *e;
for (e = battle.entityHead.next ; e != NULL ; e = e->next) for (e = battle.entityHead.next ; e != NULL ; e = e->next)
{ {
if (e->type == ET_FIGHTER && e->side != SIDE_ALLIES) if (e->type == ET_FIGHTER && e->side != SIDE_ALLIES)
@ -576,13 +576,13 @@ void retreatEnemies(void)
void retreatAllies(void) void retreatAllies(void)
{ {
Entity *e; Entity *e;
for (e = battle.entityHead.next ; e != NULL ; e = e->next) for (e = battle.entityHead.next ; e != NULL ; e = e->next)
{ {
if (e->type == ET_FIGHTER && e->side == SIDE_ALLIES) if (e->type == ET_FIGHTER && e->side == SIDE_ALLIES)
{ {
e->flags |= EF_RETREATING; e->flags |= EF_RETREATING;
e->aiFlags |= AIF_AVOIDS_COMBAT; e->aiFlags |= AIF_AVOIDS_COMBAT;
e->aiFlags |= AIF_UNLIMITED_RANGE; e->aiFlags |= AIF_UNLIMITED_RANGE;
e->aiFlags |= AIF_GOAL_EXTRACTION; e->aiFlags |= AIF_GOAL_EXTRACTION;
@ -595,7 +595,7 @@ void retreatAllies(void)
static Entity *getFighterDef(char *name) static Entity *getFighterDef(char *name)
{ {
Entity *e; Entity *e;
for (e = defHead.next ; e != NULL ; e = e->next) for (e = defHead.next ; e != NULL ; e = e->next)
{ {
if (strcmp(e->name, name) == 0) if (strcmp(e->name, name) == 0)
@ -603,7 +603,7 @@ static Entity *getFighterDef(char *name)
return e; return e;
} }
} }
printf("Error: no such fighter '%s'\n", name); printf("Error: no such fighter '%s'\n", name);
exit(1); exit(1);
} }
@ -612,7 +612,7 @@ void loadFighterDefs(void)
{ {
memset(&defHead, 0, sizeof(Entity)); memset(&defHead, 0, sizeof(Entity));
defTail = &defHead; defTail = &defHead;
loadFighterDefList("data/fighters"); loadFighterDefList("data/fighters");
loadFighterDefList("data/craft"); loadFighterDefList("data/craft");
loadFighterDefList("data/turrets"); loadFighterDefList("data/turrets");
@ -623,18 +623,18 @@ static void loadFighterDefList(char *dir)
char **filenames; char **filenames;
char path[MAX_FILENAME_LENGTH]; char path[MAX_FILENAME_LENGTH];
int count, i; int count, i;
filenames = getFileList(getFileLocation(dir), &count); filenames = getFileList(getFileLocation(dir), &count);
for (i = 0 ; i < count ; i++) for (i = 0 ; i < count ; i++)
{ {
sprintf(path, "%s/%s", dir, filenames[i]); sprintf(path, "%s/%s", dir, filenames[i]);
loadFighterDef(path); loadFighterDef(path);
free(filenames[i]); free(filenames[i]);
} }
free(filenames); free(filenames);
} }
@ -644,21 +644,21 @@ static void loadFighterDef(char *filename)
char *text; char *text;
Entity *e; Entity *e;
int i; int i;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", filename); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", filename);
text = readFile(getFileLocation(filename)); text = readFile(getFileLocation(filename));
e = malloc(sizeof(Entity)); e = malloc(sizeof(Entity));
memset(e, 0, sizeof(Entity)); memset(e, 0, sizeof(Entity));
defTail->next = e; defTail->next = e;
defTail = e; defTail = e;
e->type = ET_FIGHTER; e->type = ET_FIGHTER;
e->active = 1; e->active = 1;
root = cJSON_Parse(text); root = cJSON_Parse(text);
STRNCPY(e->name, cJSON_GetObjectItem(root, "name")->valuestring, MAX_NAME_LENGTH); STRNCPY(e->name, cJSON_GetObjectItem(root, "name")->valuestring, MAX_NAME_LENGTH);
STRNCPY(e->defName, e->name, MAX_NAME_LENGTH); STRNCPY(e->defName, e->name, MAX_NAME_LENGTH);
e->health = e->maxHealth = cJSON_GetObjectItem(root, "health")->valueint; e->health = e->maxHealth = cJSON_GetObjectItem(root, "health")->valueint;
@ -667,61 +667,55 @@ static void loadFighterDef(char *filename)
e->reloadTime = cJSON_GetObjectItem(root, "reloadTime")->valueint; e->reloadTime = cJSON_GetObjectItem(root, "reloadTime")->valueint;
e->shieldRechargeRate = cJSON_GetObjectItem(root, "shieldRechargeRate")->valueint; e->shieldRechargeRate = cJSON_GetObjectItem(root, "shieldRechargeRate")->valueint;
e->texture = getTexture(cJSON_GetObjectItem(root, "texture")->valuestring); e->texture = getTexture(cJSON_GetObjectItem(root, "texture")->valuestring);
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h);
if (cJSON_GetObjectItem(root, "guns")) if (cJSON_GetObjectItem(root, "guns"))
{ {
i = 0; i = 0;
for (node = cJSON_GetObjectItem(root, "guns")->child ; node != NULL ; node = node->next) for (node = cJSON_GetObjectItem(root, "guns")->child ; node != NULL ; node = node->next)
{ {
e->guns[i].type = lookup(cJSON_GetObjectItem(node, "type")->valuestring); e->guns[i].type = lookup(cJSON_GetObjectItem(node, "type")->valuestring);
e->guns[i].x = cJSON_GetObjectItem(node, "x")->valueint; e->guns[i].x = cJSON_GetObjectItem(node, "x")->valueint;
e->guns[i].y = cJSON_GetObjectItem(node, "y")->valueint; e->guns[i].y = cJSON_GetObjectItem(node, "y")->valueint;
i++; i++;
if (i >= MAX_FIGHTER_GUNS) if (i >= MAX_FIGHTER_GUNS)
{ {
printf("ERROR: cannot assign more than %d guns to a fighter\n", MAX_FIGHTER_GUNS); printf("ERROR: cannot assign more than %d guns to a fighter\n", MAX_FIGHTER_GUNS);
exit(1); exit(1);
} }
} }
if (cJSON_GetObjectItem(root, "combinedGuns")) e->combinedGuns = getJSONValue(root, "combinedGuns", 0);
{
e->combinedGuns = cJSON_GetObjectItem(root, "combinedGuns")->valueint;
}
} }
e->selectedGunType = e->guns[0].type; e->selectedGunType = e->guns[0].type;
if (cJSON_GetObjectItem(root, "missiles")) e->missiles = getJSONValue(root, "missiles", 0);
{
e->missiles = cJSON_GetObjectItem(root, "missiles")->valueint;
}
if (cJSON_GetObjectItem(root, "flags")) if (cJSON_GetObjectItem(root, "flags"))
{ {
e->flags = flagsToLong(cJSON_GetObjectItem(root, "flags")->valuestring, NULL); e->flags = flagsToLong(cJSON_GetObjectItem(root, "flags")->valuestring, NULL);
} }
if (cJSON_GetObjectItem(root, "aiFlags")) if (cJSON_GetObjectItem(root, "aiFlags"))
{ {
e->aiFlags = flagsToLong(cJSON_GetObjectItem(root, "aiFlags")->valuestring, NULL); e->aiFlags = flagsToLong(cJSON_GetObjectItem(root, "aiFlags")->valuestring, NULL);
} }
if (cJSON_GetObjectItem(root, "deathType")) if (cJSON_GetObjectItem(root, "deathType"))
{ {
e->deathType = lookup(cJSON_GetObjectItem(root, "deathType")->valuestring); e->deathType = lookup(cJSON_GetObjectItem(root, "deathType")->valuestring);
} }
e->separationRadius = MAX(e->w, e->h) * 3; e->separationRadius = MAX(e->w, e->h) * 3;
/* all craft default to 100 system power */ /* all craft default to 100 system power */
e->systemPower = 100; e->systemPower = 100;
cJSON_Delete(root); cJSON_Delete(root);
free(text); free(text);
} }
@ -729,7 +723,7 @@ static void loadFighterDef(char *filename)
void destroyFighterDefs(void) void destroyFighterDefs(void)
{ {
Entity *e; Entity *e;
while (defHead.next) while (defHead.next)
{ {
e = defHead.next; e = defHead.next;

View File

@ -47,6 +47,7 @@ extern char *getFileLocation(char *filename);
extern void addDebris(int x, int y, int amount); 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 App app; extern App app;
extern Battle battle; extern Battle battle;

View File

@ -41,79 +41,78 @@ Mission *loadMissionMeta(char *filename)
Challenge *challenge; Challenge *challenge;
cJSON *root, *node; cJSON *root, *node;
char *text; char *text;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", filename); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", filename);
text = readFile(getFileLocation(filename)); text = readFile(getFileLocation(filename));
root = cJSON_Parse(text); root = cJSON_Parse(text);
mission = malloc(sizeof(Mission)); mission = malloc(sizeof(Mission));
memset(mission, 0, sizeof(Mission)); memset(mission, 0, sizeof(Mission));
STRNCPY(mission->name, cJSON_GetObjectItem(root, "name")->valuestring, MAX_NAME_LENGTH); STRNCPY(mission->name, cJSON_GetObjectItem(root, "name")->valuestring, MAX_NAME_LENGTH);
STRNCPY(mission->description, _(cJSON_GetObjectItem(root, "description")->valuestring), MAX_DESCRIPTION_LENGTH); STRNCPY(mission->description, _(cJSON_GetObjectItem(root, "description")->valuestring), MAX_DESCRIPTION_LENGTH);
STRNCPY(mission->filename, filename, MAX_DESCRIPTION_LENGTH); STRNCPY(mission->filename, filename, MAX_DESCRIPTION_LENGTH);
if (cJSON_GetObjectItem(root, "requires")) mission->requires = getJSONValue(root, "requires", 0);
{
mission->requires = cJSON_GetObjectItem(root, "requires")->valueint;
}
if (cJSON_GetObjectItem(root, "epic")) if (cJSON_GetObjectItem(root, "epic"))
{ {
mission->epic = 1; mission->epic = 1;
} }
node = cJSON_GetObjectItem(root, "player"); node = cJSON_GetObjectItem(root, "player");
if (node) if (node)
{ {
STRNCPY(mission->pilot, cJSON_GetObjectItem(node, "pilot")->valuestring, MAX_NAME_LENGTH); STRNCPY(mission->pilot, cJSON_GetObjectItem(node, "pilot")->valuestring, MAX_NAME_LENGTH);
STRNCPY(mission->squadron, cJSON_GetObjectItem(node, "squadron")->valuestring, MAX_NAME_LENGTH); STRNCPY(mission->squadron, cJSON_GetObjectItem(node, "squadron")->valuestring, MAX_NAME_LENGTH);
STRNCPY(mission->craft, cJSON_GetObjectItem(node, "type")->valuestring, MAX_NAME_LENGTH); STRNCPY(mission->craft, cJSON_GetObjectItem(node, "type")->valuestring, MAX_NAME_LENGTH);
} }
node = cJSON_GetObjectItem(root, "challenge"); node = cJSON_GetObjectItem(root, "challenge");
if (node) if (node)
{ {
mission->challengeData.isChallenge = 1; mission->challengeData.isChallenge = 1;
mission->challengeData.timeLimit = cJSON_GetObjectItem(node, "timeLimit")->valueint * FPS;
mission->challengeData.killLimit = cJSON_GetObjectItem(node, "killLimit")->valueint; mission->challengeData.timeLimit = getJSONValue(node, "timeLimit", 0);
mission->challengeData.noMissiles = cJSON_GetObjectItem(node, "noMissiles") ? 1 : 0; mission->challengeData.killLimit = getJSONValue(node, "killLimit", 0);
mission->challengeData.noECM = cJSON_GetObjectItem(node, "noECM") ? 1 : 0; mission->challengeData.waypointLimit = getJSONValue(node, "waypointLimit", 0);
mission->challengeData.noBoost = cJSON_GetObjectItem(node, "noBoost") ? 1 : 0; mission->challengeData.noMissiles = getJSONValue(node, "noMissiles", 0);
mission->challengeData.noGuns = cJSON_GetObjectItem(node, "noGuns") ? 1 : 0; mission->challengeData.noECM = getJSONValue(node, "noECM", 0);
mission->challengeData.noBoost = getJSONValue(node, "noBoost", 0);
mission->challengeData.noGuns = getJSONValue(node, "noGuns", 0);
node = cJSON_GetObjectItem(node, "challenges"); node = cJSON_GetObjectItem(node, "challenges");
if (node) if (node)
{ {
node = node->child; node = node->child;
i = 0; i = 0;
while (node && i < MAX_CHALLENGES) while (node && i < MAX_CHALLENGES)
{ {
challenge = malloc(sizeof(Challenge)); challenge = malloc(sizeof(Challenge));
memset(challenge, 0, sizeof(Challenge)); memset(challenge, 0, sizeof(Challenge));
challenge->type = lookup(cJSON_GetObjectItem(node, "type")->valuestring); challenge->type = lookup(cJSON_GetObjectItem(node, "type")->valuestring);
challenge->value = cJSON_GetObjectItem(node, "value")->valueint; challenge->value = cJSON_GetObjectItem(node, "value")->valueint;
mission->challengeData.challenges[i] = challenge; mission->challengeData.challenges[i] = challenge;
node = node->next; node = node->next;
i++; i++;
} }
} }
} }
cJSON_Delete(root); cJSON_Delete(root);
free(text); free(text);
return mission; return mission;
} }
@ -122,63 +121,56 @@ void loadMission(char *filename)
cJSON *root; cJSON *root;
char *text, music[MAX_DESCRIPTION_LENGTH], *background, *planet; char *text, music[MAX_DESCRIPTION_LENGTH], *background, *planet;
float planetScale; float planetScale;
startSectionTransition(); startSectionTransition();
stopMusic(); stopMusic();
text = readFile(getFileLocation(filename)); text = readFile(getFileLocation(filename));
root = cJSON_Parse(text); root = cJSON_Parse(text);
srand(hashcode(filename)); srand(hashcode(filename));
loadObjectives(cJSON_GetObjectItem(root, "objectives")); loadObjectives(cJSON_GetObjectItem(root, "objectives"));
loadPlayer(cJSON_GetObjectItem(root, "player")); loadPlayer(cJSON_GetObjectItem(root, "player"));
loadFighters(cJSON_GetObjectItem(root, "fighters")); loadFighters(cJSON_GetObjectItem(root, "fighters"));
loadCapitalShips(cJSON_GetObjectItem(root, "capitalShips")); loadCapitalShips(cJSON_GetObjectItem(root, "capitalShips"));
loadEntities(cJSON_GetObjectItem(root, "entities")); loadEntities(cJSON_GetObjectItem(root, "entities"));
loadItems(cJSON_GetObjectItem(root, "items")); loadItems(cJSON_GetObjectItem(root, "items"));
loadLocations(cJSON_GetObjectItem(root, "locations")); loadLocations(cJSON_GetObjectItem(root, "locations"));
if (cJSON_GetObjectItem(root, "epic")) if (cJSON_GetObjectItem(root, "epic"))
{ {
loadEpicData(cJSON_GetObjectItem(root, "epic")); loadEpicData(cJSON_GetObjectItem(root, "epic"));
} }
if (cJSON_GetObjectItem(root, "manualComplete")) battle.manualComplete = getJSONValue(root, "manualComplete", 0);
{ battle.unwinnable = getJSONValue(root, "unwinnable", 0);
battle.manualComplete = cJSON_GetObjectItem(root, "manualComplete")->valueint;
}
if (cJSON_GetObjectItem(root, "unwinnable"))
{
battle.unwinnable = cJSON_GetObjectItem(root, "unwinnable")->valueint;
}
initScript(cJSON_GetObjectItem(root, "script")); initScript(cJSON_GetObjectItem(root, "script"));
/* music, planet, and background loading must come last, so AUTO works properly */ /* music, planet, and background loading must come last, so AUTO works properly */
STRNCPY(music, cJSON_GetObjectItem(root, "music")->valuestring, MAX_DESCRIPTION_LENGTH); STRNCPY(music, cJSON_GetObjectItem(root, "music")->valuestring, MAX_DESCRIPTION_LENGTH);
if (strcmp(music, "AUTO") == 0) if (strcmp(music, "AUTO") == 0)
{ {
STRNCPY(music, getAutoMusic(filename), MAX_DESCRIPTION_LENGTH); STRNCPY(music, getAutoMusic(filename), MAX_DESCRIPTION_LENGTH);
} }
background = cJSON_GetObjectItem(root, "background")->valuestring; background = cJSON_GetObjectItem(root, "background")->valuestring;
if (strcmp(background, "AUTO") == 0) if (strcmp(background, "AUTO") == 0)
{ {
background = getAutoBackground(filename); background = getAutoBackground(filename);
} }
battle.background = getTexture(background); battle.background = getTexture(background);
planet = cJSON_GetObjectItem(root, "planet")->valuestring; planet = cJSON_GetObjectItem(root, "planet")->valuestring;
if (strcmp(planet, "AUTO") == 0) if (strcmp(planet, "AUTO") == 0)
{ {
@ -192,13 +184,13 @@ void loadMission(char *filename)
SDL_QueryTexture(battle.planetTexture, NULL, NULL, &battle.planetWidth, &battle.planetHeight); SDL_QueryTexture(battle.planetTexture, NULL, NULL, &battle.planetWidth, &battle.planetHeight);
battle.planetWidth *= planetScale; battle.planetWidth *= planetScale;
battle.planetHeight *= planetScale; battle.planetHeight *= planetScale;
srand(time(NULL)); srand(time(NULL));
free(text); free(text);
endSectionTransition(); endSectionTransition();
/* only increment num missions / challenges started if there are some (Free Flight excluded, for example) */ /* only increment num missions / challenges started if there are some (Free Flight excluded, for example) */
if (battle.objectiveHead.next) if (battle.objectiveHead.next)
{ {
@ -208,26 +200,26 @@ void loadMission(char *filename)
{ {
game.stats[STAT_CHALLENGES_STARTED]++; game.stats[STAT_CHALLENGES_STARTED]++;
} }
else else
{ {
battle.status = MS_IN_PROGRESS; battle.status = MS_IN_PROGRESS;
} }
activateNextWaypoint(); activateNextWaypoint();
countNumEnemies(); countNumEnemies();
initPlayer(); initPlayer();
initMissionInfo(); initMissionInfo();
playMusic(music); playMusic(music);
} }
static char *getAutoBackground(char *filename) static char *getAutoBackground(char *filename)
{ {
int hash; int hash;
if (!game.currentMission->challengeData.isChallenge) if (!game.currentMission->challengeData.isChallenge)
{ {
hash = hashcode(game.selectedStarSystem); hash = hashcode(game.selectedStarSystem);
@ -236,14 +228,14 @@ static char *getAutoBackground(char *filename)
{ {
hash = hashcode(filename); hash = hashcode(filename);
} }
return getBackgroundTextureName(hash); return getBackgroundTextureName(hash);
} }
static char *getAutoPlanet(char *filename) static char *getAutoPlanet(char *filename)
{ {
int hash; int hash;
if (!game.currentMission->challengeData.isChallenge) if (!game.currentMission->challengeData.isChallenge)
{ {
hash = hashcode(game.selectedStarSystem); hash = hashcode(game.selectedStarSystem);
@ -252,14 +244,14 @@ static char *getAutoPlanet(char *filename)
{ {
hash = hashcode(filename); hash = hashcode(filename);
} }
return getPlanetTextureName(hash); return getPlanetTextureName(hash);
} }
static char *getAutoMusic(char *filename) static char *getAutoMusic(char *filename)
{ {
int hash; int hash;
if (!game.currentMission->challengeData.isChallenge) if (!game.currentMission->challengeData.isChallenge)
{ {
hash = hashcode(game.selectedStarSystem); hash = hashcode(game.selectedStarSystem);
@ -268,7 +260,7 @@ static char *getAutoMusic(char *filename)
{ {
hash = hashcode(filename); hash = hashcode(filename);
} }
return getMusicFilename(hash); return getMusicFilename(hash);
} }
@ -279,13 +271,13 @@ void completeMission(void)
battle.status = MS_COMPLETE; battle.status = MS_COMPLETE;
battle.missionFinishedTimer = FPS; battle.missionFinishedTimer = FPS;
selectWidget("continue", "battleWon"); selectWidget("continue", "battleWon");
game.stats[STAT_MISSIONS_COMPLETED]++; game.stats[STAT_MISSIONS_COMPLETED]++;
completeConditions(); completeConditions();
retreatEnemies(); retreatEnemies();
player->flags |= EF_IMMORTAL; player->flags |= EF_IMMORTAL;
} }
} }
@ -297,9 +289,9 @@ void failMission(void)
battle.status = MS_FAILED; battle.status = MS_FAILED;
battle.missionFinishedTimer = FPS; battle.missionFinishedTimer = FPS;
selectWidget("retry", "battleLost"); selectWidget("retry", "battleLost");
failIncompleteObjectives(); failIncompleteObjectives();
player->flags |= EF_IMMORTAL; player->flags |= EF_IMMORTAL;
} }
} }
@ -307,40 +299,32 @@ void failMission(void)
static void loadObjectives(cJSON *node) static void loadObjectives(cJSON *node)
{ {
Objective *o; Objective *o;
if (node) if (node)
{ {
node = node->child; node = node->child;
while (node) while (node)
{ {
o = malloc(sizeof(Objective)); o = malloc(sizeof(Objective));
memset(o, 0, sizeof(Objective)); memset(o, 0, sizeof(Objective));
battle.objectiveTail->next = o; battle.objectiveTail->next = o;
battle.objectiveTail = o; battle.objectiveTail = o;
o->active = 1; o->active = 1;
STRNCPY(o->description, _(cJSON_GetObjectItem(node, "description")->valuestring), MAX_DESCRIPTION_LENGTH); STRNCPY(o->description, _(cJSON_GetObjectItem(node, "description")->valuestring), MAX_DESCRIPTION_LENGTH);
STRNCPY(o->targetName, cJSON_GetObjectItem(node, "targetName")->valuestring, MAX_NAME_LENGTH); STRNCPY(o->targetName, cJSON_GetObjectItem(node, "targetName")->valuestring, MAX_NAME_LENGTH);
o->targetValue = cJSON_GetObjectItem(node, "targetValue")->valueint; o->targetValue = cJSON_GetObjectItem(node, "targetValue")->valueint;
o->targetType = lookup(cJSON_GetObjectItem(node, "targetType")->valuestring); o->targetType = lookup(cJSON_GetObjectItem(node, "targetType")->valuestring);
o->active = getJSONValue(node, "active", 0);
if (cJSON_GetObjectItem(node, "active")) o->isCondition = getJSONValue(node, "isCondition", 0);
o->isEliminateAll = getJSONValue(node, "isEliminateAll", 0);
if (isEliminateAll)
{ {
o->active = cJSON_GetObjectItem(node, "active")->valueint;
}
if (cJSON_GetObjectItem(node, "isCondition"))
{
o->isCondition = cJSON_GetObjectItem(node, "isCondition")->valueint;
}
if (cJSON_GetObjectItem(node, "isEliminateAll"))
{
o->isEliminateAll = cJSON_GetObjectItem(node, "isEliminateAll")->valueint;
o->targetValue = 1; o->targetValue = 1;
} }
node = node->next; node = node->next;
} }
} }
@ -350,25 +334,25 @@ static void loadPlayer(cJSON *node)
{ {
char *type; char *type;
int side; int side;
type = cJSON_GetObjectItem(node, "type")->valuestring; type = cJSON_GetObjectItem(node, "type")->valuestring;
side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); side = lookup(cJSON_GetObjectItem(node, "side")->valuestring);
player = spawnFighter(type, 0, 0, side); player = spawnFighter(type, 0, 0, side);
player->x = BATTLE_AREA_WIDTH / 2; player->x = BATTLE_AREA_WIDTH / 2;
player->y = BATTLE_AREA_HEIGHT / 2; player->y = BATTLE_AREA_HEIGHT / 2;
if (cJSON_GetObjectItem(node, "x")) if (cJSON_GetObjectItem(node, "x"))
{ {
player->x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; player->x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH;
player->y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; player->y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT;
} }
if (strcmp(type, "Tug") == 0) if (strcmp(type, "Tug") == 0)
{ {
battle.stats[STAT_TUG]++; battle.stats[STAT_TUG]++;
} }
if (strcmp(type, "Shuttle") == 0) if (strcmp(type, "Shuttle") == 0)
{ {
battle.stats[STAT_SHUTTLE]++; battle.stats[STAT_SHUTTLE]++;
@ -383,11 +367,11 @@ static void loadFighters(cJSON *node)
int i, numTypes, addFlags, addAIFlags; int i, numTypes, addFlags, addAIFlags;
long flags, aiFlags; long flags, aiFlags;
float x, y; float x, y;
if (node) if (node)
{ {
node = node->child; node = node->child;
while (node) while (node)
{ {
name = NULL; name = NULL;
@ -397,61 +381,41 @@ static void loadFighters(cJSON *node)
scatter = 1; scatter = 1;
active = 1; active = 1;
number = 1; number = 1;
types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes); types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes);
side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); side = lookup(cJSON_GetObjectItem(node, "side")->valuestring);
x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH;
y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT;
name = getJSONValueStr(node, "name", NULL);
if (cJSON_GetObjectItem(node, "name")) groupName = getJSONValueStr(node, "groupName", NULL);
{ number = getJSONValue(node, "number", 0);
name = cJSON_GetObjectItem(node, "name")->valuestring; scatter = getJSONValue(node, "scatter", 0);
} active = getJSONValue(node, "active", 0);
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;
}
if (cJSON_GetObjectItem(node, "flags")) if (cJSON_GetObjectItem(node, "flags"))
{ {
flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags); flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags);
} }
if (cJSON_GetObjectItem(node, "aiFlags")) if (cJSON_GetObjectItem(node, "aiFlags"))
{ {
aiFlags = flagsToLong(cJSON_GetObjectItem(node, "aiFlags")->valuestring, &addAIFlags); aiFlags = flagsToLong(cJSON_GetObjectItem(node, "aiFlags")->valuestring, &addAIFlags);
} }
for (i = 0 ; i < number ; i++) for (i = 0 ; i < number ; i++)
{ {
type = types[rand() % numTypes]; type = types[rand() % numTypes];
e = spawnFighter(type, x, y, side); e = spawnFighter(type, x, y, side);
if (scatter > 1) if (scatter > 1)
{ {
e->x += (rand() % scatter) - (rand() % scatter); e->x += (rand() % scatter) - (rand() % scatter);
e->y += (rand() % scatter) - (rand() % scatter); e->y += (rand() % scatter) - (rand() % scatter);
} }
e->active = active; e->active = active;
if (flags != -1) if (flags != -1)
{ {
if (addFlags) if (addFlags)
@ -461,11 +425,11 @@ static void loadFighters(cJSON *node)
else else
{ {
e->flags = flags; e->flags = flags;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Flags for '%s' (%s) replaced", e->name, e->defName); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Flags for '%s' (%s) replaced", e->name, e->defName);
} }
} }
if (aiFlags != -1) if (aiFlags != -1)
{ {
if (addAIFlags) if (addAIFlags)
@ -475,29 +439,29 @@ static void loadFighters(cJSON *node)
else else
{ {
e->aiFlags = aiFlags; e->aiFlags = aiFlags;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "AI Flags for '%s' (%s) replaced", e->name, e->defName); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "AI Flags for '%s' (%s) replaced", e->name, e->defName);
} }
} }
if (name) if (name)
{ {
STRNCPY(e->name, name, MAX_NAME_LENGTH); STRNCPY(e->name, name, MAX_NAME_LENGTH);
} }
if (groupName) if (groupName)
{ {
STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH);
} }
} }
node = node->next; node = node->next;
for (i = 0 ; i < numTypes ; i++) for (i = 0 ; i < numTypes ; i++)
{ {
free(types[i]); free(types[i]);
} }
free(types); free(types);
} }
} }
@ -511,11 +475,11 @@ static void loadCapitalShips(cJSON *node)
int i, numTypes, addFlags; int i, numTypes, addFlags;
long flags; long flags;
float x, y; float x, y;
if (node) if (node)
{ {
node = node->child; node = node->child;
while (node) while (node)
{ {
name = NULL; name = NULL;
@ -524,66 +488,46 @@ static void loadCapitalShips(cJSON *node)
active = 1; active = 1;
number = 1; number = 1;
flags = -1; flags = -1;
types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes); types = toTypeArray(cJSON_GetObjectItem(node, "types")->valuestring, &numTypes);
side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); side = lookup(cJSON_GetObjectItem(node, "side")->valuestring);
x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH;
y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT;
name = cJSON_GetObjectItem(node, "name", NULL);
if (cJSON_GetObjectItem(node, "name")) groupName = getJSONValueStr(node, "groupName", NULL);
{ number = getJSONValueStr(node, "number", 0);
name = cJSON_GetObjectItem(node, "name")->valuestring; scatter = getJSONValueStr(node, "scatter", 0);
} active = getJSONValue(node, "active", 0);
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;
}
if (cJSON_GetObjectItem(node, "flags")) if (cJSON_GetObjectItem(node, "flags"))
{ {
flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags); flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags);
} }
for (i = 0 ; i < number ; i++) for (i = 0 ; i < number ; i++)
{ {
type = types[rand() % numTypes]; type = types[rand() % numTypes];
e = spawnCapitalShip(type, x, y, side); e = spawnCapitalShip(type, x, y, side);
if (scatter > 1) if (scatter > 1)
{ {
e->x += (rand() % scatter) - (rand() % scatter); e->x += (rand() % scatter) - (rand() % scatter);
e->y += (rand() % scatter) - (rand() % scatter); e->y += (rand() % scatter) - (rand() % scatter);
} }
e->active = active; e->active = active;
if (name) if (name)
{ {
STRNCPY(e->name, name, MAX_NAME_LENGTH); STRNCPY(e->name, name, MAX_NAME_LENGTH);
} }
if (groupName) if (groupName)
{ {
STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH);
} }
if (flags != -1) if (flags != -1)
{ {
if (addFlags) if (addFlags)
@ -593,21 +537,21 @@ static void loadCapitalShips(cJSON *node)
else else
{ {
e->flags = flags; e->flags = flags;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Flags for '%s' (%s) replaced", e->name, e->defName); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Flags for '%s' (%s) replaced", e->name, e->defName);
} }
} }
updateCapitalShipComponentProperties(e); updateCapitalShipComponentProperties(e);
} }
node = node->next; node = node->next;
for (i = 0 ; i < numTypes ; i++) for (i = 0 ; i < numTypes ; i++)
{ {
free(types[i]); free(types[i]);
} }
free(types); free(types);
} }
} }
@ -619,11 +563,11 @@ static void loadEntities(cJSON *node)
char *name, *groupName; char *name, *groupName;
int i, type, scatter, number, active; int i, type, scatter, number, active;
float x, y; float x, y;
if (node) if (node)
{ {
node = node->child; node = node->child;
while (node) while (node)
{ {
e = NULL; e = NULL;
@ -635,32 +579,17 @@ static void loadEntities(cJSON *node)
number = 1; number = 1;
active = 1; active = 1;
scatter = 1; scatter = 1;
if (cJSON_GetObjectItem(node, "name")) name = getJSONValueStr(node, "name", NULL);
{
name = cJSON_GetObjectItem(node, "name")->valuestring; groupName = getJSONValueStr(node, "groupName", NULL);
}
number = getJSONValue(node, "number", 0);
if (cJSON_GetObjectItem(node, "groupName"))
{ active = getJSONValue(node, "active", 0);
groupName = cJSON_GetObjectItem(node, "groupName")->valuestring;
} scatter = getJSONValue(node, "scatter", 0);
if (cJSON_GetObjectItem(node, "number"))
{
number = cJSON_GetObjectItem(node, "number")->valueint;
}
if (cJSON_GetObjectItem(node, "active"))
{
active = cJSON_GetObjectItem(node, "active")->valueint;
}
if (cJSON_GetObjectItem(node, "scatter"))
{
scatter = cJSON_GetObjectItem(node, "scatter")->valueint;
}
for (i = 0 ; i < number ; i++) for (i = 0 ; i < number ; i++)
{ {
switch (type) switch (type)
@ -668,41 +597,41 @@ static void loadEntities(cJSON *node)
case ET_WAYPOINT: case ET_WAYPOINT:
e = spawnWaypoint(); e = spawnWaypoint();
break; break;
case ET_EXTRACTION_POINT: case ET_EXTRACTION_POINT:
e = spawnExtractionPoint(); e = spawnExtractionPoint();
break; break;
default: default:
printf("Error: Unhandled entity type: %s\n", cJSON_GetObjectItem(node, "type")->valuestring); printf("Error: Unhandled entity type: %s\n", cJSON_GetObjectItem(node, "type")->valuestring);
exit(1); exit(1);
break; break;
} }
if (name) if (name)
{ {
STRNCPY(e->name, name, MAX_NAME_LENGTH); STRNCPY(e->name, name, MAX_NAME_LENGTH);
} }
if (groupName) if (groupName)
{ {
STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH);
} }
e->x = x; e->x = x;
e->y = y; e->y = y;
if (scatter > 1) if (scatter > 1)
{ {
e->x += (rand() % scatter) - (rand() % scatter); e->x += (rand() % scatter) - (rand() % scatter);
e->y += (rand() % scatter) - (rand() % scatter); e->y += (rand() % scatter) - (rand() % scatter);
} }
e->active = active; e->active = active;
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h);
} }
node = node->next; node = node->next;
} }
} }
@ -715,14 +644,14 @@ static void loadItems(cJSON *node)
int i, scatter, number, active, addFlags; int i, scatter, number, active, addFlags;
long flags; long flags;
float x, y; float x, y;
flags = -1; flags = -1;
scatter = 1; scatter = 1;
if (node) if (node)
{ {
node = node->child; node = node->child;
while (node) while (node)
{ {
type = cJSON_GetObjectItem(node, "type")->valuestring; type = cJSON_GetObjectItem(node, "type")->valuestring;
@ -732,51 +661,36 @@ static void loadItems(cJSON *node)
groupName = NULL; groupName = NULL;
number = 1; number = 1;
active = 1; active = 1;
if (cJSON_GetObjectItem(node, "name")) name = getJSONValueStr(node, "name", NULL);
{
name = cJSON_GetObjectItem(node, "name")->valuestring; groupName = getJSONValueStr(node, "groupName", NULL);
}
number = getJSONValue(node, "number", 0);
if (cJSON_GetObjectItem(node, "groupName"))
{ scatter = getJSONValue(node, "scatter", 0);
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, "flags")) if (cJSON_GetObjectItem(node, "flags"))
{ {
flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags); flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags);
} }
if (cJSON_GetObjectItem(node, "active")) active = getJSONValue(node, "active", 0);
{
active = cJSON_GetObjectItem(node, "active")->valueint;
}
for (i = 0 ; i < number ; i++) for (i = 0 ; i < number ; i++)
{ {
e = spawnItem(type); e = spawnItem(type);
if (name) if (name)
{ {
STRNCPY(e->name, name, MAX_NAME_LENGTH); STRNCPY(e->name, name, MAX_NAME_LENGTH);
} }
if (groupName) if (groupName)
{ {
STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH); STRNCPY(e->groupName, groupName, MAX_NAME_LENGTH);
} }
if (flags != -1) if (flags != -1)
{ {
if (addFlags) if (addFlags)
@ -786,24 +700,24 @@ static void loadItems(cJSON *node)
else else
{ {
e->flags = flags; e->flags = flags;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Flags for '%s' (%s) replaced", e->name, e->defName); 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;
e->active = active; e->active = active;
if (scatter > 1) if (scatter > 1)
{ {
e->x += (rand() % scatter) - (rand() % scatter); e->x += (rand() % scatter) - (rand() % scatter);
e->y += (rand() % scatter) - (rand() % scatter); e->y += (rand() % scatter) - (rand() % scatter);
} }
SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h);
} }
node = node->next; node = node->next;
} }
} }
@ -813,35 +727,32 @@ static void loadLocations(cJSON *node)
{ {
int active; int active;
Location *l; Location *l;
if (node) if (node)
{ {
node = node->child; node = node->child;
while (node) while (node)
{ {
active = 1; active = 1;
l = malloc(sizeof(Location)); l = malloc(sizeof(Location));
memset(l, 0, sizeof(Location)); memset(l, 0, sizeof(Location));
battle.locationTail->next = l; battle.locationTail->next = l;
battle.locationTail = l; battle.locationTail = l;
STRNCPY(l->name, cJSON_GetObjectItem(node, "name")->valuestring, MAX_NAME_LENGTH); 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->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->y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT;
l->size = cJSON_GetObjectItem(node, "size")->valueint; l->size = cJSON_GetObjectItem(node, "size")->valueint;
if (cJSON_GetObjectItem(node, "active")) active = getJSONValue(node, "active", 0);
{
active = cJSON_GetObjectItem(node, "active")->valueint;
}
l->x += (SCREEN_WIDTH / 2); l->x += (SCREEN_WIDTH / 2);
l->y += (SCREEN_HEIGHT / 2); l->y += (SCREEN_HEIGHT / 2);
l->active = active; l->active = active;
node = node->next; node = node->next;
} }
} }
@ -851,9 +762,9 @@ static char **toTypeArray(char *types, int *numTypes)
{ {
int i; int i;
char **typeArray, *type; char **typeArray, *type;
*numTypes = 1; *numTypes = 1;
for (i = 0 ; i < strlen(types) ; i++) for (i = 0 ; i < strlen(types) ; i++)
{ {
if (types[i] == ';') if (types[i] == ';')
@ -863,19 +774,19 @@ static char **toTypeArray(char *types, int *numTypes)
} }
typeArray = malloc(*numTypes * sizeof(char*)); typeArray = malloc(*numTypes * sizeof(char*));
i = 0; i = 0;
type = strtok(types, ";"); type = strtok(types, ";");
while (type) while (type)
{ {
typeArray[i] = malloc(strlen(type) + 1); typeArray[i] = malloc(strlen(type) + 1);
strcpy(typeArray[i], type); strcpy(typeArray[i], type);
type = strtok(NULL, ";"); type = strtok(NULL, ";");
i++; i++;
} }
return typeArray; return typeArray;
} }
@ -884,11 +795,11 @@ static void loadEpicData(cJSON *node)
Entity *e; Entity *e;
int numFighters[SIDE_MAX]; int numFighters[SIDE_MAX];
memset(numFighters, 0, sizeof(int) * SIDE_MAX); memset(numFighters, 0, sizeof(int) * SIDE_MAX);
battle.isEpic = 1; battle.isEpic = 1;
battle.epicFighterLimit = cJSON_GetObjectItem(node, "fighterLimit")->valueint; battle.epicFighterLimit = cJSON_GetObjectItem(node, "fighterLimit")->valueint;
for (e = battle.entityHead.next ; e != NULL ; e = e->next) for (e = battle.entityHead.next ; e != NULL ; e = e->next)
{ {
if (e->active && e->type == ET_FIGHTER && numFighters[e->side]++ >= battle.epicFighterLimit) if (e->active && e->type == ET_FIGHTER && numFighters[e->side]++ >= battle.epicFighterLimit)
@ -902,7 +813,7 @@ Mission *getMission(char *filename)
{ {
StarSystem *starSystem; StarSystem *starSystem;
Mission *mission; Mission *mission;
/* First, search the star systems */ /* First, search the star systems */
for (starSystem = game.starSystemHead.next ; starSystem != NULL ; starSystem = starSystem->next) for (starSystem = game.starSystemHead.next ; starSystem != NULL ; starSystem = starSystem->next)
{ {
@ -914,7 +825,7 @@ Mission *getMission(char *filename)
} }
} }
} }
/* now search the challenges */ /* now search the challenges */
for (mission = game.challengeMissionHead.next ; mission != NULL ; mission = mission->next) for (mission = game.challengeMissionHead.next ; mission != NULL ; mission = mission->next)
{ {
@ -923,16 +834,16 @@ Mission *getMission(char *filename)
return mission; return mission;
} }
} }
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "No such mission '%s'", filename); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "No such mission '%s'", filename);
return NULL; return NULL;
} }
void updateAllMissions(void) void updateAllMissions(void)
{ {
updateStarSystemMissions(); updateStarSystemMissions();
updateChallengeMissions(); updateChallengeMissions();
} }
@ -954,6 +865,6 @@ static unsigned long hashcode(const char *str)
c = *str++; c = *str++;
} }
return abs(hash); return abs(hash);
} }

View File

@ -53,6 +53,8 @@ extern void updateChallengeMissions(void);
extern char *getBackgroundTextureName(int n); extern char *getBackgroundTextureName(int n);
extern char *getPlanetTextureName(int n); extern char *getPlanetTextureName(int n);
extern char *getMusicFilename(int n); extern char *getMusicFilename(int n);
extern int getJSONValue(cJSON *node, char *name, int defValue);
extern char *getJSONValueStr(cJSON *node, char *name, char *defValue);
extern Battle battle; extern Battle battle;
extern Entity *player; extern Entity *player;

View File

@ -28,19 +28,19 @@ void initStarSystems(void)
cJSON *root, *node; cJSON *root, *node;
char *text; char *text;
StarSystem *starSystem, *tail; StarSystem *starSystem, *tail;
tail = &game.starSystemHead; tail = &game.starSystemHead;
text = readFile(getFileLocation("data/galaxy/starSystems.json")); text = readFile(getFileLocation("data/galaxy/starSystems.json"));
root = cJSON_Parse(text); root = cJSON_Parse(text);
for (node = cJSON_GetObjectItem(root, "starSystems")->child ; node != NULL ; node = node->next) for (node = cJSON_GetObjectItem(root, "starSystems")->child ; node != NULL ; node = node->next)
{ {
starSystem = loadStarSystem(node); starSystem = loadStarSystem(node);
tail->next = starSystem; tail->next = starSystem;
tail = starSystem; tail = starSystem;
} }
cJSON_Delete(root); cJSON_Delete(root);
free(text); free(text);
} }
@ -48,32 +48,28 @@ void initStarSystems(void)
static StarSystem *loadStarSystem(cJSON *starSystemJSON) static StarSystem *loadStarSystem(cJSON *starSystemJSON)
{ {
StarSystem *starSystem; StarSystem *starSystem;
starSystem = malloc(sizeof(StarSystem)); starSystem = malloc(sizeof(StarSystem));
memset(starSystem, 0, sizeof(StarSystem)); memset(starSystem, 0, sizeof(StarSystem));
STRNCPY(starSystem->name, cJSON_GetObjectItem(starSystemJSON, "name")->valuestring, MAX_NAME_LENGTH); STRNCPY(starSystem->name, cJSON_GetObjectItem(starSystemJSON, "name")->valuestring, MAX_NAME_LENGTH);
starSystem->side = lookup(cJSON_GetObjectItem(starSystemJSON, "side")->valuestring); starSystem->side = lookup(cJSON_GetObjectItem(starSystemJSON, "side")->valuestring);
starSystem->x = cJSON_GetObjectItem(starSystemJSON, "x")->valueint; starSystem->x = cJSON_GetObjectItem(starSystemJSON, "x")->valueint;
starSystem->y = cJSON_GetObjectItem(starSystemJSON, "y")->valueint; starSystem->y = cJSON_GetObjectItem(starSystemJSON, "y")->valueint;
starSystem->fallsToPandorans = getJSONValue(starSystemJSON, "fallsToPandorans", 0);
if (cJSON_GetObjectItem(starSystemJSON, "fallsToPandorans"))
{
starSystem->fallsToPandorans = cJSON_GetObjectItem(starSystemJSON, "fallsToPandorans")->valueint;
}
if (strcmp(starSystem->name, "Sol") == 0) if (strcmp(starSystem->name, "Sol") == 0)
{ {
starSystem->isSol = 1; starSystem->isSol = 1;
} }
starSystem->missionHead.completed = 1; starSystem->missionHead.completed = 1;
loadMissions(starSystem); loadMissions(starSystem);
starSystem->x *= 3; starSystem->x *= 3;
starSystem->y *= 3; starSystem->y *= 3;
return starSystem; return starSystem;
} }
@ -84,38 +80,38 @@ static void loadMissions(StarSystem *starSystem)
char path[MAX_FILENAME_LENGTH]; char path[MAX_FILENAME_LENGTH];
char **filenames; char **filenames;
Mission *mission, *tail; Mission *mission, *tail;
tail = &starSystem->missionHead; tail = &starSystem->missionHead;
STRNCPY(name, starSystem->name, MAX_NAME_LENGTH); STRNCPY(name, starSystem->name, MAX_NAME_LENGTH);
for (i = 0 ; name[i] ; i++) for (i = 0 ; name[i] ; i++)
{ {
name[i] = tolower(name[i]); name[i] = tolower(name[i]);
} }
sprintf(path, "data/missions/%s", name); sprintf(path, "data/missions/%s", name);
filenames = getFileList(getFileLocation(path), &count); filenames = getFileList(getFileLocation(path), &count);
for (i = 0 ; i < count ; i++) for (i = 0 ; i < count ; i++)
{ {
sprintf(path, "data/missions/%s/%s", name, filenames[i]); sprintf(path, "data/missions/%s/%s", name, filenames[i]);
mission = loadMissionMeta(path); mission = loadMissionMeta(path);
tail->next = mission; tail->next = mission;
tail = mission; tail = mission;
free(filenames[i]); free(filenames[i]);
} }
free(filenames); free(filenames);
} }
StarSystem *getStarSystem(char *name) StarSystem *getStarSystem(char *name)
{ {
StarSystem *starSystem; StarSystem *starSystem;
for (starSystem = game.starSystemHead.next ; starSystem != NULL ; starSystem = starSystem->next) for (starSystem = game.starSystemHead.next ; starSystem != NULL ; starSystem = starSystem->next)
{ {
if (strcmp(starSystem->name, name) == 0) if (strcmp(starSystem->name, name) == 0)
@ -123,7 +119,7 @@ StarSystem *getStarSystem(char *name)
return starSystem; return starSystem;
} }
} }
return NULL; return NULL;
} }
@ -131,51 +127,51 @@ void updateStarSystemMissions(void)
{ {
StarSystem *starSystem; StarSystem *starSystem;
Mission *mission, *prev; Mission *mission, *prev;
game.completedMissions = game.totalMissions = game.availableMissions = 0; game.completedMissions = game.totalMissions = game.availableMissions = 0;
for (starSystem = game.starSystemHead.next ; starSystem != NULL ; starSystem = starSystem->next) for (starSystem = game.starSystemHead.next ; starSystem != NULL ; starSystem = starSystem->next)
{ {
starSystem->completedMissions = starSystem->availableMissions = starSystem->totalMissions = 0; starSystem->completedMissions = starSystem->availableMissions = starSystem->totalMissions = 0;
for (mission = starSystem->missionHead.next ; mission != NULL ; mission = mission->next) for (mission = starSystem->missionHead.next ; mission != NULL ; mission = mission->next)
{ {
starSystem->totalMissions++; starSystem->totalMissions++;
if (mission->completed) if (mission->completed)
{ {
starSystem->completedMissions++; starSystem->completedMissions++;
} }
} }
if (strcmp(starSystem->name, "Sol") != 0) if (strcmp(starSystem->name, "Sol") != 0)
{ {
game.totalMissions += starSystem->totalMissions; game.totalMissions += starSystem->totalMissions;
game.completedMissions += starSystem->completedMissions; game.completedMissions += starSystem->completedMissions;
} }
} }
for (starSystem = game.starSystemHead.next ; starSystem != NULL ; starSystem = starSystem->next) for (starSystem = game.starSystemHead.next ; starSystem != NULL ; starSystem = starSystem->next)
{ {
prev = &starSystem->missionHead; prev = &starSystem->missionHead;
for (mission = starSystem->missionHead.next ; mission != NULL ; mission = mission->next) for (mission = starSystem->missionHead.next ; mission != NULL ; mission = mission->next)
{ {
mission->available = strcmp(starSystem->name, "Sol") == 0 || isMissionAvailable(mission, prev); mission->available = strcmp(starSystem->name, "Sol") == 0 || isMissionAvailable(mission, prev);
if (mission->available) if (mission->available)
{ {
starSystem->availableMissions++; starSystem->availableMissions++;
} }
prev = mission; prev = mission;
} }
if (strcmp(starSystem->name, "Sol") != 0) if (strcmp(starSystem->name, "Sol") != 0)
{ {
game.availableMissions += starSystem->availableMissions; game.availableMissions += starSystem->availableMissions;
} }
sprintf(starSystem->description, "[ %s ] [ Missions %d / %d ]", starSystem->name, starSystem->completedMissions, starSystem->availableMissions); sprintf(starSystem->description, "[ %s ] [ Missions %d / %d ]", starSystem->name, starSystem->completedMissions, starSystem->availableMissions);
} }
} }
@ -184,18 +180,18 @@ void destroyStarSystems(void)
{ {
StarSystem *starSystem; StarSystem *starSystem;
Mission *mission; Mission *mission;
while (game.starSystemHead.next) while (game.starSystemHead.next)
{ {
starSystem = game.starSystemHead.next; starSystem = game.starSystemHead.next;
while (starSystem->missionHead.next) while (starSystem->missionHead.next)
{ {
mission = starSystem->missionHead.next; mission = starSystem->missionHead.next;
starSystem->missionHead.next = mission->next; starSystem->missionHead.next = mission->next;
free(mission); free(mission);
} }
game.starSystemHead.next = starSystem->next; game.starSystemHead.next = starSystem->next;
free(starSystem); free(starSystem);
} }

View File

@ -28,5 +28,6 @@ extern int isMissionAvailable(Mission *mission, Mission *prev);
extern char *getFileLocation(char *filename); extern char *getFileLocation(char *filename);
extern char **getFileList(char *dir, int *count); extern char **getFileList(char *dir, int *count);
extern Mission *loadMissionMeta(char *filename); extern Mission *loadMissionMeta(char *filename);
extern int getJSONValue(cJSON *node, char *name, int defValue);
extern Game game; extern Game game;

View File

@ -49,10 +49,10 @@ float getAngle(int x1, int y1, int x2, int y2)
int getDistance(int x1, int y1, int x2, int y2) int getDistance(int x1, int y1, int x2, int y2)
{ {
int x, y; int x, y;
x = x2 - x1; x = x2 - x1;
y = y2 - y1; y = y2 - y1;
return sqrt(x * x + y *y); return sqrt(x * x + y *y);
} }
@ -76,14 +76,14 @@ void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy)
char *timeToString(long millis, int showHours) char *timeToString(long millis, int showHours)
{ {
static char TIME[MAX_NAME_LENGTH]; static char TIME[MAX_NAME_LENGTH];
int hours, minutes, seconds; int hours, minutes, seconds;
seconds = millis / FPS; seconds = millis / FPS;
minutes = (seconds / 60) % 60; minutes = (seconds / 60) % 60;
hours = seconds / (60 * 60); hours = seconds / (60 * 60);
seconds %= 60; seconds %= 60;
if (showHours) if (showHours)
{ {
sprintf(TIME, "%dh:%02dm:%02ds", hours, minutes, seconds); sprintf(TIME, "%dh:%02dm:%02ds", hours, minutes, seconds);
@ -92,6 +92,33 @@ char *timeToString(long millis, int showHours)
{ {
sprintf(TIME, "%dm %02ds", minutes, seconds); sprintf(TIME, "%dm %02ds", minutes, seconds);
} }
return TIME; return TIME;
} }
char *getJSONValueStr(cJSON *node, char *name, char *defValue)
{
cJSON *child;
if (node)
{
child = cJSON_GetObjectItem(node, name);
if (child)
{
return child->valuestring;
}
}
return defValue;
}
int getJSONValue(cJSON *node, char *name, int defValue)
{
char *result = getJSONValueStr(node, name, defValue);
if (result)
{
return aoti(result);
}
}