diff --git a/src/battle/capitalShips.c b/src/battle/capitalShips.c index deccb14..4e9106f 100644 --- a/src/battle/capitalShips.c +++ b/src/battle/capitalShips.c @@ -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; diff --git a/src/battle/capitalShips.h b/src/battle/capitalShips.h index fe5ba42..621a5b3 100644 --- a/src/battle/capitalShips.h +++ b/src/battle/capitalShips.h @@ -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; diff --git a/src/battle/fighters.c b/src/battle/fighters.c index b85f38d..24053e2 100644 --- a/src/battle/fighters.c +++ b/src/battle/fighters.c @@ -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; diff --git a/src/battle/fighters.h b/src/battle/fighters.h index efe0b55..c26e414 100644 --- a/src/battle/fighters.h +++ b/src/battle/fighters.h @@ -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; diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index 1a294fb..2aa111b 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -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); } diff --git a/src/galaxy/mission.h b/src/galaxy/mission.h index ca482bd..be7b5e1 100644 --- a/src/galaxy/mission.h +++ b/src/galaxy/mission.h @@ -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; diff --git a/src/galaxy/starSystems.c b/src/galaxy/starSystems.c index 3ae00ec..341d7f5 100644 --- a/src/galaxy/starSystems.c +++ b/src/galaxy/starSystems.c @@ -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); } diff --git a/src/galaxy/starSystems.h b/src/galaxy/starSystems.h index 1bd7f51..7c4d9f3 100644 --- a/src/galaxy/starSystems.h +++ b/src/galaxy/starSystems.h @@ -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; diff --git a/src/system/util.c b/src/system/util.c index d315a2f..534c4f3 100644 --- a/src/system/util.c +++ b/src/system/util.c @@ -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); + } +}