diff --git a/dat/faction.xml b/dat/faction.xml index 95ca975..1bf5e8d 100644 --- a/dat/faction.xml +++ b/dat/faction.xml @@ -8,8 +8,16 @@ </faction> <faction name = "Pirate"> </faction> - <alliances> - </alliances> - <enemies> - </enemies> + <Alliances> + <alliance name = "Neutral"> + <ally>Independent</ally> + <ally>Merchant</ally> + </alliance> + </Alliances> + <Enemies> + <enemies> + <enemy type = "alliance">Neutral</enemy> + <enemy type = "faction">Pirate</enemy> + </enemies> + </Enemies> </Factions> diff --git a/src/faction.c b/src/faction.c index 0c7fdbe..28725bb 100644 --- a/src/faction.c +++ b/src/faction.c @@ -10,8 +10,12 @@ #define XML_NODE_START 1 #define XML_NODE_TEXT 3 -#define XML_FACTION_ID "Factions" // XML section id. -#define XML_FACTION_TAG "faction" +#define XML_FACTION_ID "Factions" // XML section id. +#define XML_FACTION_TAG "faction" +#define XML_ALLIANCE_ID "Alliances" +#define XML_ALLIANCE_TAG "alliance" +#define XML_ENEMIES_ID "Enemies" +#define XML_ENEMIES_TAG "enemies" #define FACTION_DATA "../dat/faction.xml" @@ -19,6 +23,8 @@ Faction* faction_stack = NULL; int nfactions = 0; static Faction* faction_parse(xmlNodePtr parent); +static void alliance_parse(xmlNodePtr parent); +static void enemies_parse(xmlNodePtr parent); // Return the faction of name "name". Faction* faction_get(const char* name) { @@ -36,21 +42,31 @@ Faction* faction_get(const char* name) { // Return 1 if Faction a and b are enemies. int areEnemies(Faction* a, Faction* b) { int i = 0; - while(a->enemies[i] != NULL && b != a->enemies[i]) i++; + for(i = 0; i < a->nenemies; i++) + if(a->enemies[i] == b) + return 1; + for(i = 0; i < b->nenemies; i++) + if(b->enemies[i] == a) + return 1; - if(a->enemies[i] == NULL) return 0; - return 1; + return 0; } // Return 1 if Faction a and b are allies. int areAllies(Faction* a, Faction* b) { int i = 0; - while(a->allies[i] != NULL && b != a->allies[i]) i++; + for(i = 0; i < a->nallies; i++) + if(a->allies[i] == b) + return 1; + for(i = 0; i < b->nallies; i++) + if(b->allies[i] == a) + return 1; + + return 0; - if(a->allies[i] == NULL) return 0; - return 1; } +// Parses a single faction, but does not set the allies/enemies. static Faction* faction_parse(xmlNodePtr parent) { Faction* tmp = CALLOC_L(Faction); tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name"); @@ -58,6 +74,70 @@ static Faction* faction_parse(xmlNodePtr parent) { return tmp; } +// We set allies/enemies here, in the faction_stack. +static void alliance_parse(xmlNodePtr parent) { + Faction** f = NULL; + int i, j, n, m; + i = 0; + char* name = NULL; + xmlNodePtr node, cur; + + node = parent->xmlChildrenNode; + + do { + if(node->type == XML_NODE_START) { + if(strcmp((char*)node->name, XML_ALLIANCE_TAG)==0) { + name = (char*)xmlGetProp(node, (xmlChar*)"name"); + + // Parse the current alliance's allies. + cur = node->xmlChildrenNode; + do { + if(strcmp((char*)cur->name, "ally")==0) { + f = realloc(f, (++i)*sizeof(Faction*)); + f[i-1] = faction_get((char*)cur->children->content); + if(f[i-1] == NULL) + WARN("Faction %s in alliance %s does not exist in "FACTION_DATA, + (char*)cur->children->content, name); + } + }while((cur = cur->next)); + + // Set the crap needed by faction_stack. + for(j = 0; j < i; j++) { + f[j]->nallies += i-1; + f[j]->allies = realloc(f[j]->allies, f[j]->nallies*sizeof(Faction*)); + for(n = 0, m = 0; n < i; n++, m++) { + // Add as ally for all factions exept self. + if(n == j) m--; + else if(n != j) f[j]->allies[f[j]->nallies-i+1+m] = f[n]; + } + } + // Free up some memory. + if(f) { + free(f); + f = NULL; + i = 0; + } + if(name) free(name); + } + } + } while((node = node->next)); +} + +static void enemies_parse(xmlNodePtr parent) { + xmlNodePtr node; + + node = parent->xmlChildrenNode; + + do { + if(node->type == XML_NODE_START) { + if(strcmp((char*)node->name, XML_ENEMIES_TAG)==0) { + + } + } + } while((node = node->next)); +} + +// Load all the factions. int factions_load(void) { uint32_t bufsize; char* buf = pack_readfile(DATA, FACTION_DATA, &bufsize); @@ -80,11 +160,17 @@ int factions_load(void) { } do { - if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_FACTION_TAG) == 0) { - tmp = faction_parse(node); - faction_stack = realloc(faction_stack, sizeof(Faction)*(++nfactions)); - memcpy(faction_stack+nfactions-1, tmp, sizeof(Faction)); - free(tmp); + if(node->type == XML_NODE_START) { + if(strcmp((char*)node->name, XML_FACTION_TAG)==0) { + tmp = faction_parse(node); + faction_stack = realloc(faction_stack, sizeof(Faction)*(++nfactions)); + memcpy(faction_stack+nfactions-1, tmp, sizeof(Faction)); + free(tmp); + } + else if(strcmp((char*)node->name, XML_ALLIANCE_ID)==0) + alliance_parse(node); + else if(strcmp((char*)node->name, XML_ENEMIES_ID)==0) + enemies_parse(node); } } while((node = node->next)); @@ -99,8 +185,11 @@ int factions_load(void) { void factions_free(void) { int i; - for(i = 0; i < nfactions; i++) + for(i = 0; i < nfactions; i++) { free(faction_stack[i].name); + if(faction_stack[i].nallies > 0) free(faction_stack[i].allies); + if(faction_stack[i].nenemies > 0) free(faction_stack[i].enemies); + } free(faction_stack); nfactions = 0; } diff --git a/src/faction.h b/src/faction.h index 55cdf40..c239fb9 100644 --- a/src/faction.h +++ b/src/faction.h @@ -4,7 +4,9 @@ typedef struct Faction { char* name; struct Faction** enemies; + int nenemies; struct Faction** allies; + int nallies; } Faction; Faction* faction_get(const char* name); diff --git a/src/main.c b/src/main.c index 65a2d8e..5d66954 100644 --- a/src/main.c +++ b/src/main.c @@ -253,16 +253,15 @@ int main(int argc, char** argv) { space_load(); // Testing. - pilot_create(ship_get("Ship"), "Player", 0., NULL, NULL, PILOT_PLAYER); + pilot_create(ship_get("Ship"), "Player", faction_get("Player"), 0., NULL, NULL, PILOT_PLAYER); gl_bindCamera(&player->solid->pos); space_init("SaraSys"); - pilot_create(ship_get("Test"), NULL, 2., NULL, NULL, 0); - + // Welcome message. player_message("Welcome to "APPNAME"!"); player_message(" v%d.%d.%d", VMAJOR, VMINOR, VREV); - time = SDL_GetTicks(); + time = SDL_GetTicks(); // Init the time. // Main looops. SDL_Event event; diff --git a/src/pilot.c b/src/pilot.c index bccc2ce..8874eae 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -43,9 +43,15 @@ static Fleet* fleet_parse(const xmlNodePtr parent); // Get the next pilot based on player_id. unsigned int pilot_getNext(const unsigned int id) { - int i, n; - for(i = 0, n = pilots/2; n > 0; n /= 2) - i += (pilot_stack[i+n]->id > id) ? 0 : n; + // Regular search. + int i; + for(i = 0; i < pilots; i++) + if(pilot_stack[i]->id == id) + break; + // Dichotomical search. + //int i, n; + //for(i = 0, n = pilots/2; n > 0; n /= 2) + //i += (pilot_stack[i+n]->id > id) ? 0 : n; if(i == pilots-1) return 0; @@ -55,18 +61,21 @@ unsigned int pilot_getNext(const unsigned int id) { // Pull a pilot out of the pilot_stack based on id. Pilot* pilot_get(const unsigned int id) { // Regular search. -#if 0 - for(int i = 0; i < pilots; i++) + int i; + for(i = 0; i < pilots; i++) if(pilot_stack[i]->id == id) return pilot_stack[i]; return NULL; -#endif + if(id == 0) return player; + DEBUG("id = %d", id); +#if 0 // Dichotomical search. int i, n; for(i = 0, n = pilots/2; n > 0; n /= 2) i += (pilot_stack[i+n]->id > id) ? 0 : n; return (pilot_stack[i]->id == id) ? pilot_stack[i] : NULL; +#endif } // Mkay, this is how we shoot. Listen up. @@ -153,7 +162,7 @@ static void pilot_update(Pilot* pilot, const double dt) { // pos : Initial position. // flags : Tweaking the pilot. // ======================================================== -void pilot_init(Pilot* pilot, Ship* ship, char* name, const double dir, const Vec2* pos, +void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, const double dir, const Vec2* pos, const Vec2* vel, const int flags) { if(flags & PILOT_PLAYER) // Player is ID 0 @@ -164,6 +173,10 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, const double dir, const Ve pilot->ship = ship; pilot->name = strdup((name == NULL) ? ship->name : name); + // Faction. + pilot->faction = faction; + + // Solid. pilot->solid = solid_create(ship->mass, dir, pos, vel); // Max shields armor. @@ -211,14 +224,14 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, const double dir, const Ve } // Create a new pilot - Params are same as pilot_init. Return pilot's id. -unsigned int pilot_create(Ship* ship, char* name, const double dir, +unsigned int pilot_create(Ship* ship, char* name, Faction* faction, const double dir, const Vec2* pos, const Vec2* vel, const int flags) { Pilot* dyn = MALLOC_L(Pilot); if(dyn == NULL) { WARN("Unable to allocate memory."); return 0; } - pilot_init(dyn, ship, name, dir, pos, vel, flags); + pilot_init(dyn, ship, name, faction, dir, pos, vel, flags); if(flags & PILOT_PLAYER) { // Player. diff --git a/src/pilot.h b/src/pilot.h index c8aa366..1f5a866 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -24,6 +24,8 @@ typedef struct Pilot { unsigned int id; // Pilots id. char* name; // Pilot's name (if unique). + Faction* faction; + // Object characteristics. Ship* ship; // Pilots ship. Solid* solid; // Associated solid (physics). @@ -71,10 +73,10 @@ void pilot_shoot(Pilot* p, const int secondary); void pilot_hit(Pilot* p, const double damage_shield, const double damage_armor); // Creation. -void pilot_init(Pilot* dest, Ship* ship, char* name, const double dir, +void pilot_init(Pilot* dest, Ship* ship, char* name, Faction* faction, const double dir, const Vec2* pos, const Vec2* vel, const int flags); -unsigned int pilot_create(Ship* ship, char* name, const double dir, +unsigned int pilot_create(Ship* ship, char* name, Faction* faction, const double dir, const Vec2* pos, const Vec2* vel, const int flags); // Init/Cleanup. diff --git a/src/player.c b/src/player.c index 69263d4..0fa0d44 100644 --- a/src/player.c +++ b/src/player.c @@ -262,6 +262,8 @@ void player_render(void) { // Target. if(player_target) { + p = pilot_get(player_target); + gl_blitStatic(p->ship->gfx_target, &gui.pos_target); if(p->armor < p->armor_max * PILOT_DISABLED) // Disable the pilot. @@ -424,13 +426,16 @@ static void input_key(int keynum, double value, int abs) { if(value == KEY_PRESS) player_primary = 1; else if(value == KEY_RELEASE) player_primary = 0; } + // Targetting. else if(strcmp(player_input[keynum]->name, "target")==0) { if(value == KEY_PRESS) player_target = pilot_getNext(player_target); } + // Zoom in. else if(strcmp(player_input[keynum]->name, "mapzoomin")==0) { if(value == KEY_PRESS && gui.radar.res < RADAR_RES_MAX) gui.radar.res += RADAR_RES_INTERVAL; } + // Zoom out. else if(strcmp(player_input[keynum]->name, "mapzoomout")==0) { if(value == KEY_PRESS && gui.radar.res > RADAR_RES_MIN) gui.radar.res -= RADAR_RES_INTERVAL; diff --git a/src/space.c b/src/space.c index e39c2bc..bf8077f 100644 --- a/src/space.c +++ b/src/space.c @@ -195,20 +195,33 @@ static PlanetClass planetclass_get(const char a) { // Init the system. void space_init(const char* sysname) { - int i; + int i, j; for(i = 0; i < nsystems; i++) if(strcmp(sysname, systems[i].name)==0) break; if(i == nsystems) ERR("System %s not found in stack", sysname); cur_system = systems+i; + // Set up stars. nstars = (cur_system->stars*gl_screen.w*gl_screen.h+STAR_BUF*STAR_BUF)/(800*640); - stars = malloc(sizeof(Star)*nstars); + stars = realloc(stars, sizeof(Star)*nstars); // Should realloc this, not malloc. for(i = 0; i < nstars; i++) { stars[i].brightness = (double)RNG(50, 200)/256.; stars[i].x = (double)RNG(-STAR_BUF, gl_screen.w + STAR_BUF); stars[i].y = (double)RNG(-STAR_BUF, gl_screen.h + STAR_BUF); } + // Set up fleets -> pilots. + for(i = 0; i < cur_system->nfleets; i++) + if(RNG(0,100) <= cur_system->fleets[i].chance) // Check fleet. + for(j = 0; j < cur_system->fleets[i].fleet->npilots; j++) + if(RNG(0,100) <= cur_system->fleets[i].fleet->pilots[j].chance) + pilot_create(cur_system->fleets[i].fleet->pilots[j].ship, + cur_system->fleets[i].fleet->pilots[j].name, + cur_system->fleets[i].fleet->faction, + RNG(0,360), + NULL, + NULL, + 0); } // Load the planets of name 'name'. diff --git a/src/weapon.c b/src/weapon.c index 0a8885a..ed497d3 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -116,6 +116,7 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { int i; for(i = 0; i < pilots; i++) { if((w->parent != pilot_stack[i]->id) && // The pilot hasn't shoot it. + !areAllies(pilot_get(w->parent)->faction, pilot_stack[i]->faction) && (DIST(w->solid->pos, pilot_stack[i]->solid->pos) < (PILOT_SIZE_APROX * w->outfit->gfx_space->sw/2. + pilot_stack[i]->ship->gfx_space->sw/2.))) { pilot_hit(pilot_stack[i], w->outfit->damage_shield, w->outfit->damage_armor);