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

View File

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

View File

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

View File

@ -53,6 +53,8 @@ extern void updateChallengeMissions(void);
extern char *getBackgroundTextureName(int n);
extern char *getPlanetTextureName(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 Entity *player;

View File

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

View File

@ -28,5 +28,6 @@ extern int isMissionAvailable(Mission *mission, Mission *prev);
extern char *getFileLocation(char *filename);
extern char **getFileList(char *dir, int *count);
extern Mission *loadMissionMeta(char *filename);
extern int getJSONValue(cJSON *node, char *name, int defValue);
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 x, y;
x = x2 - x1;
y = y2 - y1;
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)
{
static char TIME[MAX_NAME_LENGTH];
int hours, minutes, seconds;
seconds = millis / FPS;
minutes = (seconds / 60) % 60;
hours = seconds / (60 * 60);
seconds %= 60;
if (showHours)
{
sprintf(TIME, "%dh:%02dm:%02ds", hours, minutes, seconds);
@ -92,6 +92,33 @@ char *timeToString(long millis, int showHours)
{
sprintf(TIME, "%dm %02ds", minutes, seconds);
}
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);
}
}