diff --git a/dat/fleet.xml b/dat/fleet.xml
index f54c612..fc5de4b 100644
--- a/dat/fleet.xml
+++ b/dat/fleet.xml
@@ -1,27 +1,27 @@
-
+
test
Independent
- Test
+ Pirate
merchant
Merchant
- Ship
+ Merchant Ship
merchant
Merchant
- Ship
- Ship
- Ship
- Ship
+ Merchant Ship
+ Merchant Ship
+ Merchant Ship
+ Merchant Ship
diff --git a/dat/ship.xml b/dat/ship.xml
index 909d47c..e73cf36 100644
--- a/dat/ship.xml
+++ b/dat/ship.xml
@@ -1,6 +1,6 @@
-
+
ship
1
@@ -26,7 +26,7 @@
laser
-
+
ship1
1
diff --git a/dat/ssys.xml b/dat/ssys.xml
index a3643cc..93f9d94 100644
--- a/dat/ssys.xml
+++ b/dat/ssys.xml
@@ -14,12 +14,12 @@
KonoSphere
- Test
+ Merchant Ship
Merchant Ship
Merchant Ship
Merchant Ship
- Sml Merchant Convoy
- Sml Merchant Convoy
+ Pirate
+ Pirate
diff --git a/scripts/ai/merchant.lua b/scripts/ai/merchant.lua
index e087480..59bea4a 100644
--- a/scripts/ai/merchant.lua
+++ b/scripts/ai/merchant.lua
@@ -3,13 +3,14 @@ control_rate = 2
-- Required "control" function.
function control()
- pushtask(0, "fly")
+ if taskname() == "none" then
+ pushtask(0, "fly")
+ end
end
-- Required "attacked" function.
function attacked(attacker)
- task = taskname()
- if task ~= "runaway" then
+ if taskname() ~= "runaway" then
-- Let's have some messages.
if attacker == player then
msg = rng(0,4)
@@ -18,6 +19,7 @@ function attacked(attacker)
elseif msg == 2 then say("LEAVE! ME! ALONE!")
end
end
+ -- So bravely run away!
pushtask(0, "runaway", attacker)
end
end
diff --git a/scripts/ai/skeleton b/scripts/ai/skeleton
new file mode 100644
index 0000000..b0212e1
--- /dev/null
+++ b/scripts/ai/skeleton
@@ -0,0 +1,10 @@
+--Required control rate.
+control_rate = 2
+
+-- Required "control" function.
+function control()
+end
+
+-- Required "attacked" function
+function attacked(attacker)
+end
diff --git a/scripts/ai/test.lua b/scripts/ai/test.lua
index 7b15387..38ec016 100644
--- a/scripts/ai/test.lua
+++ b/scripts/ai/test.lua
@@ -3,13 +3,14 @@ control_rate = 2
-- Required "control" function.
function control()
- pushtask(0, "fly")
+ if taskname() == "none" then
+ pushtask(0, "fly")
+ end
end
-- Required "attacked" function.
function attacked(attacker)
- task = taskname()
- if task ~= "attack" and task ~= "runaway" then
+ if taskname() ~= "attack" and task ~= "runaway" then
-- Let's have some taunts.
if attacker == player then
msg = rng(0,4)
@@ -28,7 +29,6 @@ function runaway()
target = gettargetid()
dir = face(target, 1)
accel()
- dist = getdist(getpos(target))
end
-- Attack
diff --git a/src/ai.c b/src/ai.c
index f50f905..b75baf9 100644
--- a/src/ai.c
+++ b/src/ai.c
@@ -208,7 +208,7 @@ static int ai_loadProfile(char* filename) {
buf = pack_readfile(DATA, filename, NULL);
if(luaL_dostring(L, buf) != 0) {
- ERR("loading AI file: %s", "../scripts/ai/test.lua");
+ ERR("loading AI file: %s", filename);
ERR("%s", lua_tostring(L, -1));
WARN("Most likely Lua file has improper syntax, please check it.");
return -1;
@@ -244,12 +244,15 @@ void ai_think(Pilot* pilot) {
// Clean up some variables.
pilot_acc = pilot_turn = 0.;
- //pilot_primary = 0;
+ pilot_primary = 0;
- if(cur_pilot->task == NULL)
- // Idle git!
- AI_LCALL("control");
- else
+ // Control function if pilot is idle or tick is up.
+ if((cur_pilot->tcontrol < SDL_GetTicks()) || (cur_pilot->task == NULL)) {
+ AI_LCALL("control"); // Run control.
+ lua_getglobal(L, "control_rate");
+ cur_pilot->tcontrol = SDL_GetTicks() + 1000*(int)lua_tonumber(L, -1);
+ }
+ if(cur_pilot->task != NULL)
// Pilot has a currently running task.
AI_LCALL(cur_pilot->task->name);
@@ -381,13 +384,13 @@ static int ai_shield(lua_State* L) {
// Get the pilot's armor in percentage.
static int ai_parmor(lua_State* L) {
- lua_pushnumber(L, cur_pilot->armor / cur_pilot->ship->armor * 100.);
+ lua_pushnumber(L, cur_pilot->armor / cur_pilot->armor_max * 100.);
return 1;
}
// Get the pilot's shield in percentage.
static int ai_pshield(lua_State* L) {
- lua_pushnumber(L, cur_pilot->shield / cur_pilot->ship->shield * 100.);
+ lua_pushnumber(L, cur_pilot->shield / cur_pilot->shield_max * 100.);
return 1;
}
@@ -587,7 +590,7 @@ static int ai_say(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("Comm: %s> \"%s\"", cur_pilot->name, lua_tostring(L, 1));
return 0;
}
diff --git a/src/main.c b/src/main.c
index d0a5bf2..1a90ce3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -253,7 +253,7 @@ int main(int argc, char** argv) {
space_load();
// Testing.
- pilot_create(ship_get("Ship"), "Player", faction_get("Player"), NULL, 0., NULL, NULL, PILOT_PLAYER);
+ pilot_create(ship_get("Merchant Ship"), "Player", faction_get("Player"), NULL, 0., NULL, NULL, PILOT_PLAYER);
gl_bindCamera(&player->solid->pos);
space_init("SaraSys");
diff --git a/src/pilot.c b/src/pilot.c
index a294d3e..1024d35 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -176,7 +176,9 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi
pilot->faction = faction;
// AI.
- pilot->ai = ai;
+ pilot->ai = ai;
+ pilot->tcontrol = 0;
+ pilot->flags = 0;
// Solid.
pilot->solid = solid_create(ship->mass, dir, pos, vel);
@@ -387,7 +389,7 @@ int fleet_load(void) {
free(buf);
xmlCleanupParser();
- DEBUG("Loaded %d fleets", nfleets);
+ DEBUG("Loaded %d fleets%c", nfleets, (nfleets==1)?' ':'s');
return 0;
}
diff --git a/src/pilot.h b/src/pilot.h
index be2a1e6..c26af71 100644
--- a/src/pilot.h
+++ b/src/pilot.h
@@ -11,13 +11,13 @@
#define PILOT_DISABLED 0.2 // Based on armor percentage.
// Flags.
-// Creation.
-#define PILOT_PLAYER (1<<0) // Pilot is a player.
-// Dynamic.
#define pilot_isFlag(p,f) (p->flags & f)
#define pilot_setFlag(p,f) (p->flags |= f)
#define pilot_rmFlag(p,f) (p->flags ^= f)
-#define PILOT_ATTACKED (1<<9) // Pilot is under attack.
+// Creation.
+#define PILOT_PLAYER (1<<0) // Pilot is a player.
+// Dynamic.
+#define PILOT_HOSTILE (1<<1) // Pilot is hostile to the player.
typedef struct {
Outfit* outfit; // Associated outfit.
@@ -52,6 +52,7 @@ typedef struct Pilot {
// AI.
AI_Profile* ai; // Ai personality profile.
+ unsigned int tcontrol; // Timer for control tick.
Task* task; // Current action.
} Pilot;
diff --git a/src/player.c b/src/player.c
index 0fa0d44..0fcb03e 100644
--- a/src/player.c
+++ b/src/player.c
@@ -48,11 +48,13 @@ typedef struct {
double r, g, b, a;
} Color;
#define COLOR(x) glColor4d((x).r, (x).g, (x).b, (x).a)
-// Factions.
-Color cRadar_player = { .r = 0.4, .g = 0.8, .b = 0.9, .a = 1. };
-Color cRadar_inert = { .r = 0.6, .g = 0.6, .b = 0.6, .a = 1. };
-Color cRadar_neut = { .r = 0.9, .g = 1.0, .b = 0.3, .a = 1. };
-Color cRadar_friend = { .r = 0.0, .g = 1.0, .b = 0.0, .a = 1. };
+// Standard colors.
+Color cInert = { .r = 0.6, .g = 0.6, .b = 0.6, .a = 1. };
+Color cNeutral = { .r = 0.9, .g = 1.0, .b = 0.3, .a = 1. };
+Color cFriend = { .r = 0.0, .g = 1.0, .b = 0.0, .a = 1. };
+Color cHostile = { .r = 0.9, .g = 0.2, .b = 0.2, .a = 1. };
+
+Color cRadar_player = { .r = 0.4, .g = 0.8, .b = 0.4, .a = 1. };
Color cRadar_targ = { .r = 0.0, .g = 0.7, .b = 1.0, .a = 1. };
Color cRadar_weap = { .r = 0.8, .g = 0.2, .b = 0.2, .a = 1. };
// Bars.
@@ -107,7 +109,11 @@ typedef struct {
} Msg;
static Msg* msg_stack;
+// External.
extern void pilot_render(Pilot* pilot); // Extern is in Pilot.*
+// Internal.
+void gui_renderPilot(Pilot* p);
+void gui_renderBar(Color* c, Vec2* p, Rect* r, double w);
void player_message(const char* fmt, ...) {
va_list ap;
@@ -129,8 +135,7 @@ void player_message(const char* fmt, ...) {
// Render the player.
void player_render(void) {
- int i;
- double x, y, sx, sy;
+ int i, j;
Pilot* p;
Vec2 v;
@@ -164,7 +169,7 @@ void player_render(void) {
switch(gui.radar.shape) {
case RADAR_RECT:
// Planets.
- COLOR(cRadar_friend);
+ COLOR(cFriend);
planets_minimap(gui.radar.res, gui.radar.w, gui.radar.h);
// Weapons.
@@ -172,36 +177,20 @@ void player_render(void) {
COLOR(cRadar_weap);
weapon_minimap(gui.radar.res, gui.radar.w, gui.radar.h);
glEnd(); // Put end to those points.
- for(i = 1; i < pilots; i++) {
- p = pilot_stack[i];
- x = (p->solid->pos.x - player->solid->pos.x) / gui.radar.res;
- y = (p->solid->pos.y - player->solid->pos.y) / gui.radar.res;
- sx = PILOT_SIZE_APROX/2. * p->ship->gfx_space->sw / gui.radar.res;
- sy = PILOT_SIZE_APROX/2. * p->ship->gfx_space->sh / gui.radar.res;
-
- if(sx < 1.) sx = 1.;
- if(sy < 1.) sy = 1.;
-
- if((ABS(x) > gui.radar.w / 2+sx) || (ABS(y) > gui.radar.h / 2. + sy))
- continue; // Pilot isn't in range.
-
- glBegin(GL_QUADS);
- // Colors.
- if(p->id == player_target) COLOR(cRadar_targ);
- else COLOR(cRadar_neut);
- glVertex2d(MAX(x-sx, -gui.radar.w/2.), MIN(y+sx, gui.radar.w/2.)); // top left.
- glVertex2d(MIN(x+sx, gui.radar.w/2.), MIN(y+sy, gui.radar.h/2.)); // Top right.
- glVertex2d(MIN(x+sx, gui.radar.w/2.), MAX(y-sy, -gui.radar.h/2.)); // Bottom right.
- glVertex2d(MAX(x-sx, -gui.radar.w/2.), MAX(y-sy, -gui.radar.h/2.)); // Bottom left.
- glEnd(); // The Quads.
+ for(j = 0, i = 1; i < pilots; i++) {
+ // Skip the player.
+ if(pilot_stack[i]->id == player_target) j = i;
+ else gui_renderPilot(pilot_stack[i]);
}
+ // Render the targetted pilot.
+ if(j != 0) gui_renderPilot(pilot_stack[j]);
glBegin(GL_POINTS); // For ze player.
break;
case RADAR_CIRCLE:
glBegin(GL_POINTS);
for(i = 1; i < pilots; i++) {
p = pilot_stack[i];
- COLOR(cRadar_neut);
+ COLOR(cNeutral);
glVertex2d((p->solid->pos.x - player->solid->pos.x) / gui.radar.res,
(p->solid->pos.y - player->solid->pos.y) / gui.radar.res);
}
@@ -224,41 +213,9 @@ void player_render(void) {
glPopMatrix(); // GL_PROJECTION.
// Health.
- glBegin(GL_QUADS); // Shield.
- COLOR(cShield);
- x = VX(gui.pos_shield) - gl_screen.w/2.;
- y = VY(gui.pos_shield) - gl_screen.h/2.;
- sx = player->shield / player->shield_max * gui.shield.w;
- sy = gui.shield.h;
- glVertex2d(x, y);
- glVertex2d(x+sx, y);
- glVertex2d(x+sx, y-sy);
- glVertex2d(x, y-sy);
- glEnd();
-
- glBegin(GL_QUADS); // Armor.
- COLOR(cArmor);
- x = VX(gui.pos_armor) - gl_screen.w/2.;
- y = VY(gui.pos_armor) - gl_screen.h/2.;
- sx = player->armor / player->armor_max * gui.armor.w;
- sy = gui.armor.h;
- glVertex2d(x, y);
- glVertex2d(x+sx, y);
- glVertex2d(x+sx, y-sy);
- glVertex2d(x, y-sy);
- glEnd();
-
- glBegin(GL_QUADS); // Energy.
- COLOR(cEnergy);
- x = VX(gui.pos_energy) - gl_screen.w/2.;
- y = VY(gui.pos_energy) - gl_screen.h/2.;
- sx = player->energy / player->energy_max * gui.energy.w;
- sy = gui.energy.h;
- glVertex2d(x, y);
- glVertex2d(x+sx, y);
- glVertex2d(x+sx, y-sy);
- glVertex2d(x, y-sy);
- glEnd();
+ gui_renderBar(&cShield, &gui.pos_shield, &gui.shield, player->shield / player->shield_max);
+ gui_renderBar(&cArmor, &gui.pos_armor, &gui.armor, player->armor / player->armor_max);
+ gui_renderBar(&cEnergy, &gui.pos_energy, &gui.energy, player->energy / player->energy_max);
// Target.
if(player_target) {
@@ -288,6 +245,51 @@ void player_render(void) {
}
}
+// Renders a pilot.
+void gui_renderPilot(Pilot* p) {
+ int x, y, sx, sy;
+
+ x = (p->solid->pos.x - player->solid->pos.x) / gui.radar.res;
+ y = (p->solid->pos.y - player->solid->pos.y) / gui.radar.res;
+ sx = PILOT_SIZE_APROX/2. * p->ship->gfx_space->sw / gui.radar.res;
+ sy = PILOT_SIZE_APROX/2. * p->ship->gfx_space->sh / gui.radar.res;
+ if(sx < 1.) sx = 1.;
+ if(sy < 1.) sy = 1.;
+
+ if((ABS(x) > gui.radar.w/2+sx) || (ABS(y) > gui.radar.h/2.+sy))
+ return; // Pilot isn't in range.
+
+ glBegin(GL_QUADS);
+ // Colors.
+ if(p->id == player_target) COLOR(cRadar_targ);
+ else if(pilot_isFlag(p, PILOT_HOSTILE)) COLOR(cHostile);
+ else COLOR(cNeutral);
+
+ // Image.
+ glVertex2d(MAX(x-sx, -gui.radar.w/2.), MIN(y+sy, gui.radar.h/2)); // Top left.
+ glVertex2d(MIN(x+sx, gui.radar.w/2.), MIN(y+sy, gui.radar.h/2)); // Top right.
+ glVertex2d(MIN(x+sx, gui.radar.w/2.), MAX(y-sy, -gui.radar.h/2)); // Bottom right.
+ glVertex2d(MAX(x-sx, -gui.radar.w/2.), MAX(y-sy, -gui.radar.h/2)); // Bottom left.
+ glEnd();
+}
+
+// Render a bar.
+void gui_renderBar(Color* c, Vec2* p, Rect* r, double w) {
+ int x, y, sx, sy;
+
+ glBegin(GL_QUADS);
+ COLOR(*c);
+ x = VX(*p) - gl_screen.w/2.;
+ y = VY(*p) - gl_screen.h/2.;
+ sx = w * r->w;
+ sy = r->h;
+ glVertex2d(x, y);
+ glVertex2d(x+sx, y);
+ glVertex2d(x+sx, y-sy);
+ glVertex2d(x, y-sy);
+ glEnd();
+}
+
// Init GUI.
int gui_init(void) {
// -- Targeting.
diff --git a/src/weapon.c b/src/weapon.c
index c22d289..0a19ff8 100644
--- a/src/weapon.c
+++ b/src/weapon.c
@@ -128,9 +128,11 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
CollideSprite(w->outfit->gfx_space, wsx, wsy, &w->solid->pos,
pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos)) {
- if(i != 0)
+ if(i != 0) {
// Inform the ai it has been attacked. Useless if we are player.
ai_attacked(pilot_stack[i], w->parent);
+ pilot_setFlag(pilot_stack[i], PILOT_HOSTILE);
+ }
// Inform the ship that it should take some damage.
pilot_hit(pilot_stack[i], w->outfit->damage_shield, w->outfit->damage_armor);
// No need for the weapon particle anymore.