diff --git a/dat/fleet.xml b/dat/fleet.xml index fc5de4b..756a9ce 100644 --- a/dat/fleet.xml +++ b/dat/fleet.xml @@ -1,10 +1,10 @@ - + test Independent - Pirate + Enemy Test @@ -24,4 +24,11 @@ Merchant Ship + + pirate + Pirate + + Merchant Ship + + diff --git a/dat/ship.xml b/dat/ship.xml index e73cf36..7c31634 100644 --- a/dat/ship.xml +++ b/dat/ship.xml @@ -26,7 +26,7 @@ laser - + ship1 1 diff --git a/dat/ssys.xml b/dat/ssys.xml index 93f9d94..2833111 100644 --- a/dat/ssys.xml +++ b/dat/ssys.xml @@ -14,12 +14,13 @@ KonoSphere - Merchant Ship + Enemy Test + Pirate Merchant Ship Merchant Ship Merchant Ship - Pirate - Pirate + Sml Merchant Convoy + Sml Merchant Convoy diff --git a/scripts/ai/merchant.lua b/scripts/ai/merchant.lua index d070991..d5ace3c 100644 --- a/scripts/ai/merchant.lua +++ b/scripts/ai/merchant.lua @@ -4,7 +4,7 @@ control_rate = 2 -- Required "control" function. function control() if taskname() == "none" then - local planet = getrndplanet() + planet = getrndplanet() pushtask(0, "go", planet) end end @@ -13,13 +13,13 @@ end function attacked(attacker) if taskname() ~= "runaway" then -- Let's have some messages. - if attacker == player then - local msg = rng(0,4) - if msg == 0 then say("ARGH! Please don't hurt me.") - elseif msg == 1 then say("HEY! We are simply a merchant vessle.") - elseif msg == 2 then say("LEAVE! ME! ALONE!") - end + num = rng(0,3) + if num == 0 then msg = "Mayday! We are under attack!" + elseif num == 1 then msg = "Requesting assistance! Some scoundral is attacking us!" + elseif num == 2 then msg = "Merchant vessle under attack here! HALP!" end + if msg then broadcast(msg) end + -- So bravely run away! pushtask(0, "runaway", attacker) end @@ -27,17 +27,17 @@ end -- Runs away. function runaway() - local target = gettargetid() - local dir = face(target, 1) + target = gettargetid() + dir = face(target, 1) accel() end -- Fly to the target. function go() - local target = gettarget() - local dir = face(target) - local dist = getdist(target) - local bdist = minbrakedist() + target = gettarget() + dir = face(target) + dist = getdist(target) + bdist = minbrakedist() if dir < 10 and dist > bdist then accel() elseif dir < 10 and dist < bdist then diff --git a/scripts/ai/pirate.lua b/scripts/ai/pirate.lua new file mode 100644 index 0000000..6ac186e --- /dev/null +++ b/scripts/ai/pirate.lua @@ -0,0 +1,71 @@ +--Required control rate. +control_rate = 2 + +-- Required "control" function. +function control() + if taskname() ~= "attack" then + enemy = getenemy() + if enemy ~= -1 then + pushtask(0, "attack", enemy) + else + pushtask(0, "fly") + end + end +end + +-- Required "attacked" function +function attacked(attacker) + task = taskname() + if task ~= "attack" and task ~= "runaway" then + taunt() + pushtask(0, "attack", attacker) + elseif task == "attack" then + if gettargetid() ~= attacker then + pushtask(0, "attack", attacker) + end + end +end + +function taunt() + num = rng(0,4) + if num == 0 then msg = "How dare you attack me?!" + elseif num == 1 then msg = "Aha! You think you can beat ME?!" + elseif num == 2 then msg = "JUST! DIE!" + elseif num == 3 then msg = "Ohh, You're not going to enjoy this!" + end + if msg then comm(attacker, msg) end +end + +-- Run away. +function runaway() + target = gettargerid() + dir = face(target, 1) + accel() +end + +-- Attack. +function attack() + target = gettargetid() + dir = face(target) + dist = getdist(getpos(target)) + + if parmor() < 70 then + poptask() + pushtask(0, "runaway", target) + elseif dir < 10 and dist > 300 then + accel() + elseif dir < 10 and dist < 300 then + shoot() + end +end + +-- Fly to the player. +function fly() + target = 0 + dir = face(target) + dist = getdist(getpos(target)) + if dir < 10 and dist > 300 then + accel() + end +end + diff --git a/scripts/ai/test.lua b/scripts/ai/test.lua index 0f96661..0437106 100644 --- a/scripts/ai/test.lua +++ b/scripts/ai/test.lua @@ -10,32 +10,33 @@ end -- Required "attacked" function. function attacked(attacker) - if taskname() ~= "attack" and task ~= "runaway" then + task = taskname() + if task ~= "attack" and task ~= "runaway" then -- Let's have some taunts. - if attacker == player then - local msg = rng(0,4) - if msg == 0 then say("You will never kill me!") - elseif msg == 1 then say("DIE!") - elseif msg == 2 then say("You won't survive!") - elseif msg == 3 then say("I hate you!") - end + num = rng(0,4) + if num == 0 then msg = "You will never kill me!" + elseif num == 1 then msg = "DIE!" + elseif num == 2 then msg = "You won't survive!" + elseif num == 3 then msg = "I hate you!" end + if msg then comm(attacker, msg) end + pushtask(0, "attack", attacker) end end -- Runs away. function runaway() - local target = gettargetid() - local dir = face(target, 1) + target = gettargetid() + dir = face(target, 1) accel() end -- Attack function attack() - local target = gettargetid() - local dir = face(target) - local dist = getdist(getpos(target)) + target = gettargetid() + dir = face(target) + dist = getdist(getpos(target)) if parmor() < 70 then poptask() @@ -49,9 +50,9 @@ end -- Fly to the player. function fly() - local target = 0 - local dir = face(target) - local dist = getdist(getpos(target)) + target = 0 + dir = face(target) + dist = getdist(getpos(target)) if dir < 10 and dist > 300 then accel() end diff --git a/src/ai.c b/src/ai.c index 108da4a..ece568d 100644 --- a/src/ai.c +++ b/src/ai.c @@ -68,6 +68,10 @@ static int nprofiles = 0; // Current AI Lua interpreter. static lua_State* L = NULL; +// Extern pilot hacks. +extern Pilot** pilot_stack; +extern int pilots; + static int ai_minbrakedist(lua_State* L); // Minimal breaking distance. static int ai_accel(lua_State* L); // Accelerate. @@ -111,7 +115,8 @@ static int ai_settimer(lua_State* L); // settimer(number, number) static int ai_timeup(lua_State* L); // bool timeup(number) // Misc. static int ai_createvect(lua_State* L); // createvect(number, number) -static int ai_say(lua_State* L); // say(string) +static int ai_comm(lua_State* L); // comm(string) +static int ai_broadcast(lua_State* L); // broadcast(string) static int ai_rng(lua_State* L); // rng(number, number) // Current pilot "thinking" and assorted variables. @@ -211,7 +216,8 @@ static int ai_loadProfile(char* filename) { lua_register(L, "timeup", ai_timeup); // Misc. lua_register(L, "createvect", ai_createvect); - lua_register(L, "say", ai_say); + lua_register(L, "comm", ai_comm); + lua_register(L, "broadcast", ai_broadcast); lua_register(L, "rng", ai_rng); @@ -583,7 +589,17 @@ static int ai_shoot(lua_State* L) { // Get the nearest enemy. static int ai_getenemy(lua_State* L) { - lua_pushnumber(L,1); + int i, p; + double d, td; + for(p = -1, i = 0; i < pilots; i++) + if(areEnemies(cur_pilot->faction, pilot_stack[i]->faction)) { + td = vect_dist(&pilot_stack[i]->solid->pos, &cur_pilot->solid->pos); + if((p == -1) || (td < d)) { + d = td; + p = pilot_stack[i]->id; + } + } + lua_pushnumber(L,p); return 1; } @@ -623,11 +639,21 @@ static int ai_createvect(lua_State* L) { } // Have the pilot say something to player. -static int ai_say(lua_State* L) { +static int ai_comm(lua_State* L) { + MIN_ARGS(2); + + if(lua_isnumber(L,1) && (lua_tonumber(L,1)==PLAYER_ID) && lua_isstring(L,2)) + player_message("Comm: %s> \"%s\"", cur_pilot->name, lua_tostring(L,2)); + + return 0; +} + +// Broadcasts to the entire area. +static int ai_broadcast(lua_State* L) { MIN_ARGS(1); if(lua_isstring(L, 1)) - player_message("Comm: %s> \"%s\"", cur_pilot->name, lua_tostring(L, 1)); + player_message("Broadcast: %s> \"%s\"", cur_pilot->name, lua_tostring(L, 1)); return 0; } diff --git a/src/faction.c b/src/faction.c index 7079123..82a6f68 100644 --- a/src/faction.c +++ b/src/faction.c @@ -22,9 +22,21 @@ Faction* faction_stack = NULL; int nfactions = 0; +// Save alliance. +typedef struct { + char* name; + Faction** factions; + int nfactions; +} Alliance; + +// Stack of alliances. +static Alliance* alliances = NULL; +static int nalliances = 0; + static Faction* faction_parse(xmlNodePtr parent); static void alliance_parse(xmlNodePtr parent); static void enemies_parse(xmlNodePtr parent); +static Alliance* alliance_get(char* name); // Return the faction of name "name". Faction* faction_get(const char* name) { @@ -39,6 +51,19 @@ Faction* faction_get(const char* name) { return NULL; } +// Return the alliance of name 'name'. +static Alliance* alliance_get(char* name) { + int i; + for(i = 0; i < nalliances; i++) + if(strcmp(alliances[i].name, name)==0) + break; + + if(i != nalliances) + return alliances+i; + + return NULL; +} + // Return 1 if Faction a and b are enemies. int areEnemies(Faction* a, Faction* b) { int i = 0; @@ -82,67 +107,127 @@ static Faction* faction_parse(xmlNodePtr parent) { // 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; + Alliance* a; + int* i, j, n, m; 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"); + if((node->type == XML_NODE_START) && (strcmp((char*)node->name, XML_ALLIANCE_TAG)==0)) { + // Allocate a new alliance. + alliances = realloc(alliances, sizeof(Alliance)*(++nalliances)); + alliances[nalliances-1].name = (char*)xmlGetProp(node,(xmlChar*)"name"); + alliances[nalliances-1].factions = NULL; + alliances[nalliances-1].nfactions = 0; + + // Parse the current alliance's allies. + cur = node->xmlChildrenNode; + do { + if(strcmp((char*)cur->name, "ally")==0) { + // Add the faction (and pointers to make things simple). + a = alliances + nalliances-1; + i = &a->nfactions; + (*i)++; - // 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)); + // Load the faction. + a->factions = realloc(a->factions, (*i)*sizeof(Faction*)); + a->factions[(*i)-1] = faction_get((char*)cur->children->content); + + if(a->factions[(*i)-1] == NULL) + WARN("Faction %s in alliance %s does not exist in "FACTION_DATA, + (char*)cur->children->content, a->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++) { + for(j = 0; j < (*i); j++) { + a->factions[j]->nallies += (*i)-1; + a->factions[j]->allies = realloc(a->factions[j]->allies, a->factions[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]; + else if(n != j) + a->factions[j]->allies[a->factions[j]->nallies-(*i)+1+m] = a->factions[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; + xmlNodePtr node, cur; + Faction*** f; + Alliance* a; + int i, *j, n, m, x, y, z, e; + char* type; + + i = 0; + f = NULL; + j = NULL; node = parent->xmlChildrenNode; do { - if(node->type == XML_NODE_START) { - if(strcmp((char*)node->name, XML_ENEMIES_TAG)==0) { - - } + if((node->type == XML_NODE_START) && (strcmp((char*)node->name, XML_ENEMIES_TAG)==0)) { + cur = node->xmlChildrenNode; + do { + if(strcmp((char*)cur->name,"enemy")==0) { + type = (char*)xmlGetProp(cur, (xmlChar*)"type"); + + i++; + j = realloc(j, sizeof(int)*i); + f = realloc(f, sizeof(Faction**)*i); + + if(strcmp(type, "alliance")==0) { + // Enemy thing is an alliance. + a = alliance_get((char*)cur->children->content); + if(a == NULL) + WARN("Alliance %s not found in stack", (char*)cur->children->content); + j[i-1] = a->nfactions; + f[i-1] = a->factions; + } + else if(strcmp(type,"faction")==0) { + // Enemy thing is only a faction. + j[i-1] = 1; + f[i-1] = malloc(sizeof(Faction*)); + f[i-1][0] = faction_get((char*)cur->children->content); + if(f[i-1][0] == NULL) + WARN("Faction %s not found in stack", (char*)cur->children->content); + } + free(type); + } + } while((cur = cur->next)); + // Now actually parse and load up the enemies. + for(n = 0; n < i; n++) { + for(m = 0; m < j[n]; m++) { + // Faction. + // Add all the faction enemies to nenemies and alloc. + for(e = 0, x = 0; x < i; x++) + if(x != n) e += j[x]; // Store the total enemies. + // Now allocate the memory. + f[n][m]->nenemies += e; + f[n][m]->enemies = realloc(f[n][m]->enemies, sizeof(Faction*)*f[n][m]->nenemies); + + // Add the actualy enemies. + for(x = 0, z = 0; x < i; x++) + if(x != n) + // Make sure it's not from the same group. + if(x != n) + for(y = 0; y < j[x]; y++, z++) + f[n][m]->enemies[f[n][m]->nenemies-e+z]=f[x][y]; + } + } + // Free al the temp memory. + for(x = 0; x < i; x++) + if(j[x]==1) free(f[x]); // Free the single malloced factions. + free(f); // Free the rest. + free(j); } } while((node = node->next)); } + // Load all the factions. int factions_load(void) { uint32_t bufsize; @@ -184,19 +269,30 @@ int factions_load(void) { free(buf); xmlCleanupParser(); - DEBUG("Loaded %d factions%c", nfactions, (nfactions==1)?' ':'s'); + DEBUG("Loaded %d faction%c", nfactions, (nfactions==1)?' ':'s'); return 0; } void factions_free(void) { int i; + // Free alliances. + for(i = 0; i < nalliances; i++) { + free(alliances[i].name); + free(alliances[i].factions); + } + free(alliances); + alliances = NULL; + nalliances = 0; + + // Free factions. 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); + faction_stack = NULL; nfactions = 0; } diff --git a/src/pilot.c b/src/pilot.c index 1024d35..3b7e442 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -23,7 +23,7 @@ static unsigned int pilot_id = 0; // Stack of pilots - yes, they come in stacks now. -Pilot** pilot_stack = NULL; // Not static, it is used in player.c and weapon.c +Pilot** pilot_stack = NULL; // Not static, it is used in player.c and weapon.c and ai.c int pilots = 0; extern Pilot* player; @@ -389,7 +389,7 @@ int fleet_load(void) { free(buf); xmlCleanupParser(); - DEBUG("Loaded %d fleets%c", nfleets, (nfleets==1)?' ':'s'); + DEBUG("Loaded %d fleet%c", nfleets, (nfleets==1)?' ':'s'); return 0; } diff --git a/src/player.c b/src/player.c index 0fcb03e..8d0734c 100644 --- a/src/player.c +++ b/src/player.c @@ -312,7 +312,7 @@ int gui_init(void) { VY(gui.pos_frame) + gui.gfx_frame->h - 10); // y. // -- Bars. - gui.shield.w = gui.armor.w = gui.energy.w = 128; + gui.shield.w = gui.armor.w = gui.energy.w = 129; gui.shield.h = gui.armor.h = gui.energy.h = 10; vect_csetmin(&gui.pos_shield, VX(gui.pos_frame) + 10, // x diff --git a/src/space.c b/src/space.c index 594d406..7284ad1 100644 --- a/src/space.c +++ b/src/space.c @@ -355,7 +355,7 @@ static StarSystem* system_parse(const xmlNodePtr parent) { MELEMENT(flags&FLAG_ASTEROIDSSET, "asteroids"); // Can be 0. MELEMENT(flags&FLAG_INTEFERENCESET, "inteference"); #undef MELEMENT - DEBUG("Loaded Star System '%s' with %d Planets%s", tmp->name, tmp->nplanets, (tmp->nplanets > 1) ? "s" : ""); + DEBUG("Loaded Star System '%s' with %d Planet%c", tmp->name, tmp->nplanets, (tmp->nplanets == 1) ? ' ' : 's'); return tmp; }