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;
}