Added getJSONValue to aid with optional JSON data.
This commit is contained in:
parent
b6012a2e21
commit
95cb35d5a1
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue