diff --git a/dat/faction.xml b/dat/faction.xml
index 5b6f3d2..7679d98 100644
--- a/dat/faction.xml
+++ b/dat/faction.xml
@@ -16,9 +16,12 @@
- Player
Neutral
Pirate
+
+ Pirate
+ Player
+
diff --git a/dat/ship.xml b/dat/ship.xml
index 7c31634..698c3a1 100644
--- a/dat/ship.xml
+++ b/dat/ship.xml
@@ -5,7 +5,7 @@
1
400
- 360
+ 180
360
@@ -23,7 +23,7 @@
20
- laser
+ laser
@@ -31,7 +31,7 @@
1
180
- 360
+ 130
260
diff --git a/scripts/ai/merchant.lua b/scripts/ai/merchant.lua
index d5ace3c..1459aa6 100644
--- a/scripts/ai/merchant.lua
+++ b/scripts/ai/merchant.lua
@@ -51,7 +51,7 @@ function stop()
brake()
if isstopped() then
poptask()
- settimer(0, rng(3000, 5000))
+ settimer(0, rng(8000, 15000))
pushtask(0, "land")
end
end
diff --git a/scripts/ai/pirate.lua b/scripts/ai/pirate.lua
index 3d2d199..a8cc666 100644
--- a/scripts/ai/pirate.lua
+++ b/scripts/ai/pirate.lua
@@ -3,9 +3,23 @@ control_rate = 2
-- Required "control" function.
function control()
- if taskname() ~= "attack" then
+ task = taskname()
+ if task ~= "attack" and task ~= "runaway" then
+ -- If getenemy() is 0, there is no enemy around.
enemy = getenemy()
- if enemy ~= -1 then
+ if enemy ~= 0 then
+ -- Taunts.
+ num = rng(0,4)
+ if num == 0 then msg "Prepare to be boarded!"
+ elseif num == 1 then msg = "Whoa! Lookie we I found here!"
+ elseif num == 2 then msg = "What's a ship like you doing in a place like this?"
+ end
+ comm(enemy,msg)
+
+ -- Make hostile to the enemy (mainly, player! YOU!).
+ hostile(enemy)
+
+ -- Go ahead and attack.
pushtask(0, "attack", enemy)
else
pushtask(0, "fly")
@@ -36,22 +50,24 @@ function taunt()
if msg then comm(attacker, msg) end
end
--- Run away.
+-- Run away from the target.
function runaway()
target = gettargerid()
dir = face(target, 1)
accel()
end
--- Attack.
+-- Attack the target.
function attack()
target = gettargetid()
dir = face(target)
dist = getdist(getpos(target))
+ -- We need to know when to run away.
if parmor() < 70 then
poptask()
pushtask(0, "runaway", target)
+ -- Try to obliterate the target.
elseif dir < 10 and dist > 300 then
accel()
elseif dir < 10 and dist < 300 then
@@ -59,9 +75,9 @@ function attack()
end
end
--- Fly to the player.
+-- Fly to the player. Pointless until hyperspace is implemented.
function fly()
- target = 0
+ target = player
dir = face(target)
dist = getdist(getpos(target))
if dir < 10 and dist > 300 then
diff --git a/scripts/ai/test.lua b/scripts/ai/test.lua
index 0437106..f09b92a 100644
--- a/scripts/ai/test.lua
+++ b/scripts/ai/test.lua
@@ -50,7 +50,7 @@ end
-- Fly to the player.
function fly()
- target = 0
+ target = player
dir = face(target)
dist = getdist(getpos(target))
if dir < 10 and dist > 300 then
diff --git a/src/ai.c b/src/ai.c
index b78d120..bf9fd2f 100644
--- a/src/ai.c
+++ b/src/ai.c
@@ -56,9 +56,9 @@
// Don't run the function if (n) params aren't passed.
#define MIN_ARGS(n) if(lua_gettop(L) < n) return 0
-#define MIN_DIR_ERR 5.0*M_PI/180.
-#define MAX_DIR_ERR 2.5*M_PI/180.
-#define MIN_VEL_ERR 2.5
+#define MIN_DIR_ERR 1.0*M_PI/180.
+#define MAX_DIR_ERR 0.1*M_PI/180.
+#define MIN_VEL_ERR 0.5
// file info.
#define AI_PREFIX "../scripts/ai/"
@@ -112,6 +112,7 @@ static int ai_getrndplanet(lua_State* L); // pointer getrndplanet()
// Combat.
static int ai_shoot(lua_State* L); // shoot(number) number = 1,2,3.
static int ai_getenemy(lua_State* L); // number getenemy().
+static int ai_hostile(lua_State* L); // hostile(number).
// Timers.
static int ai_settimer(lua_State* L); // settimer(number, number)
static int ai_timeup(lua_State* L); // bool timeup(number)
@@ -213,6 +214,7 @@ static int ai_loadProfile(char* filename) {
// Combat.
lua_register(L, "shoot", ai_shoot);
lua_register(L, "getenemy", ai_getenemy);
+ lua_register(L, "hostile", ai_hostile);
// Timers.
lua_register(L, "settimer", ai_settimer);
lua_register(L, "timeup", ai_timeup);
@@ -395,25 +397,54 @@ static int ai_gettargetid(lua_State* L) {
// Get the pilots armor.
static int ai_armor(lua_State* L) {
- lua_pushnumber(L, cur_pilot->armor);
+ double d;
+
+ if(lua_isnumber(L,1)) d = pilot_get((unsigned int)lua_tonumber(L,1))->armor;
+ else d = cur_pilot->armor;
+
+ lua_pushnumber(L, d);
return 1;
}
// Get pilots shield.
static int ai_shield(lua_State* L) {
- lua_pushnumber(L, cur_pilot->shield);
+ double d;
+
+ if(lua_isnumber(L,1)) d = pilot_get((unsigned int)lua_tonumber(L,1))->shield;
+ else d = cur_pilot->shield;
+
+ lua_pushnumber(L, d);
return 1;
}
// Get the pilot's armor in percentage.
static int ai_parmor(lua_State* L) {
- lua_pushnumber(L, cur_pilot->armor / cur_pilot->armor_max * 100.);
+ double d;
+ Pilot* p;
+
+ if(lua_isnumber(L,1)) {
+ p = pilot_get((unsigned int)lua_tonumber(L,1));
+ d = p->armor / p->armor_max * 100.;
+ }
+ else d = cur_pilot->armor / cur_pilot->armor_max * 100.;
+
+ lua_pushnumber(L, d);
return 1;
}
// Get the pilot's shield in percentage.
static int ai_pshield(lua_State* L) {
- lua_pushnumber(L, cur_pilot->shield / cur_pilot->shield_max * 100.);
+ double d;
+ Pilot* p;
+
+ if(lua_isnumber(L,1)) {
+ p = pilot_get((unsigned int)lua_tonumber(L,1));
+ d = p->shield / p->shield_max * 100.;
+ }
+ else d = cur_pilot->shield / cur_pilot->shield_max * 100.;
+
+ lua_pushnumber(L, d);
+
return 1;
}
@@ -449,7 +480,7 @@ static int ai_minbrakedist(lua_State* L) {
double time = VMOD(cur_pilot->solid->vel) /
(cur_pilot->ship->thrust / cur_pilot->solid->mass);
- double dist = VMOD(cur_pilot->solid->vel) * (time + cur_pilot->ship->turn/360.) -
+ double dist = VMOD(cur_pilot->solid->vel) * (time + cur_pilot->ship->turn/180.) -
0.5 * (cur_pilot->ship->thrust / cur_pilot->solid->mass)*time*time;
lua_pushnumber(L, dist); // return
@@ -520,9 +551,15 @@ static int ai_face(lua_State* L) {
// This is generally good for coming to a halt.
static int ai_brake(lua_State* L) {
(void)L; // Just a hack to avoid -W -Wall warnings.
- double diff = angle_diff(cur_pilot->solid->dir, VANGLE(cur_pilot->solid->vel));
- pilot_turn = 10*diff;
- if(diff < MAX_DIR_ERR && VMOD(cur_pilot->solid->vel) > MIN_VEL_ERR)
+ double diff, d;
+
+ d = cur_pilot->solid->dir+M_PI;
+ if(d >= 2*M_PI) d = fmodf(d, 2*M_PI);
+
+ diff = angle_diff(d, VANGLE(cur_pilot->solid->vel));
+ pilot_turn = -10*diff;
+
+ if(ABS(diff) < MAX_DIR_ERR && VMOD(cur_pilot->solid->vel) > MIN_VEL_ERR)
pilot_acc = 1.;
return 0;
}
@@ -595,6 +632,16 @@ static int ai_getenemy(lua_State* L) {
return 1;
}
+// Set the enemy hostile. (Simply notifies of an impending attack).
+static int ai_hostile(lua_State* L) {
+ MIN_ARGS(1);
+
+ if(lua_isnumber(L,1) && ((unsigned int)lua_tonumber(L,1) == PLAYER_ID))
+ pilot_setFlag(cur_pilot, PILOT_HOSTILE);
+
+ return 0;
+}
+
// Set the timer.
static int ai_settimer(lua_State* L) {
MIN_ARGS(2);
diff --git a/src/faction.c b/src/faction.c
index 82a6f68..c7a7450 100644
--- a/src/faction.c
+++ b/src/faction.c
@@ -161,15 +161,15 @@ static void enemies_parse(xmlNodePtr parent) {
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) && (strcmp((char*)node->name, XML_ENEMIES_TAG)==0)) {
+ i = 0;
+ f = NULL;
+ j = NULL;
+
cur = node->xmlChildrenNode;
do {
if(strcmp((char*)cur->name,"enemy")==0) {
diff --git a/src/physics.c b/src/physics.c
index b98dfe4..03882f1 100644
--- a/src/physics.c
+++ b/src/physics.c
@@ -132,8 +132,8 @@ static void simple_update(Solid* obj, const double dt) {
#define RK4_MIN_H 0.01 // Minimal pass we want.
static void rk4_update(Solid* obj, const double dt) {
// Make sure angle doesn't flip.
- obj->dir += M_PI/360.*obj->dir_vel*dt;
- if(obj->dir > 2*M_PI) obj->dir -= 2*M_PI;
+ obj->dir += M_PI/180.*obj->dir_vel*dt;
+ if(obj->dir >= 2*M_PI) obj->dir -= 2*M_PI;
if(obj->dir < 0.) obj->dir += 2*M_PI;
int N = (dt > RK4_MIN_H) ? (int)(dt/RK4_MIN_H) : 1;
diff --git a/src/pilot.c b/src/pilot.c
index 15b63ad..32a0947 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -20,7 +20,7 @@
#define FLEET_DATA "../dat/fleet.xml"
// Stack of pilot id's to assure uniqueness.
-static unsigned int pilot_id = 0;
+static unsigned int pilot_id = PLAYER_ID;
// Stack of pilots - yes, they come in stacks now.
Pilot** pilot_stack = NULL; // Not static, it is used in player.c and weapon.c and ai.c
@@ -41,7 +41,7 @@ void pilot_render(Pilot* pilot);
static void pilot_free(Pilot* p);
static Fleet* fleet_parse(const xmlNodePtr parent);
-// Get the next pilot based on player_id.
+// Get the next pilot based on id.
unsigned int pilot_getNext(const unsigned int id) {
// Regular search.
int i;
@@ -49,20 +49,37 @@ unsigned int pilot_getNext(const unsigned int id) {
if(pilot_stack[i]->id == id)
break;
- if(i == pilots-1) return 0;
+ if(i == pilots-1) return PLAYER_ID;
return pilot_stack[i+1]->id;
}
// Get the nearest enemy to the pilot -- Tamir's (insightful) request.
-unsigned int pilot_getNearest(Pilot* p) {
- int i, tp;
+unsigned int pilot_getNearest(const Pilot* p) {
+ unsigned int tp;
+ int i;
double d, td;
- for(tp = -1, i = 0; i < pilots; i++)
+ for(tp = 0, d = 0., i = 0; i < pilots; i++)
if(areEnemies(p->faction, pilot_stack[i]->faction)) {
td = vect_dist(&pilot_stack[i]->solid->pos, &p->solid->pos);
- if((tp == -1) || (td < d)) {
+ if((!tp) || (td < d)) {
+ d = td;
+ tp = pilot_stack[i]->id;
+ }
+ }
+ return tp;
+}
+
+// Get the nearest hostile enemy to the player.
+unsigned pilot_getHostile(void) {
+ unsigned int tp;
+ int i;
+ double d, td;
+ for(tp = PLAYER_ID, d = 0., i = 0; i < pilots; i++)
+ if(pilot_isFlag(pilot_stack[i], PILOT_HOSTILE)) {
+ td = vect_dist(&pilot_stack[i]->solid->pos, &player->solid->pos);
+ if((tp == PLAYER_ID) || (td < d)) {
d = td;
tp = pilot_stack[i]->id;
}
@@ -80,7 +97,6 @@ Pilot* pilot_get(const unsigned int id) {
return NULL;
if(id == 0) return player;
- DEBUG("id = %d", id);
#if 0
// Dichotomical search.
int i, n;
@@ -177,7 +193,7 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi
const double dir, const Vec2* pos, const Vec2* vel, const int flags) {
if(flags & PILOT_PLAYER) // Player is ID 0
- pilot->id = 0;
+ pilot->id = PLAYER_ID;
else
pilot->id = ++pilot_id; // New unique pilot id based on pilot_id, Can't be 0.
diff --git a/src/pilot.h b/src/pilot.h
index 6b46843..532b2d9 100644
--- a/src/pilot.h
+++ b/src/pilot.h
@@ -6,7 +6,7 @@
#include "faction.h"
#include "ship.h"
-#define PLAYER_ID 0
+#define PLAYER_ID 1
// Aproximation for pilot size.
#define PILOT_SIZE_APROX 0.8
@@ -21,6 +21,9 @@
// Dynamic.
#define PILOT_HOSTILE (1<<1) // Pilot is hostile to the player.
+// Just makes life simpler.
+#define pilot_isPlayer(p) ((p)->flags & PILOT_PLAYER)
+
typedef struct {
Outfit* outfit; // Associated outfit.
unsigned int quantity; // Number of outfits of this type that the pilot has.
@@ -79,8 +82,9 @@ typedef struct {
// Grabing pilot crap.
extern Pilot* player; // The player.
Pilot* pilot_get(unsigned int id);
-unsigned int pilot_getNext(unsigned int id);
-unsigned int pilot_getNearest(Pilot* p);
+unsigned int pilot_getNext(const unsigned int id);
+unsigned int pilot_getNearest(const Pilot* p);
+unsigned int pilot_getHostile(void); // Only for the player.
Fleet* fleet_get(const char* name);
// MISC.
diff --git a/src/player.c b/src/player.c
index 31dd77f..655db0f 100644
--- a/src/player.c
+++ b/src/player.c
@@ -31,7 +31,7 @@ Pilot* player = NULL; // extern in pilot.h
static double player_turn = 0.; // Turn velocity from input.
static double player_acc = 0.; // Accel velocity from input.
static int player_primary = 0; // Player is shooting primary weapon.
-static unsigned int player_target = 0; // Targetted pilot.
+static unsigned int player_target = PLAYER_ID; // Targetted pilot.
// Pilot stuff for GUI.
extern Pilot** pilot_stack;
@@ -141,7 +141,7 @@ void player_render(void) {
Vec2 v;
// Render the player target graphics.
- if(player_target) {
+ if(player_target != PLAYER_ID) {
p = pilot_get(player_target);
vect_csetmin(&v, VX(p->solid->pos) - p->ship->gfx_space->sw * PILOT_SIZE_APROX/2.,
@@ -219,7 +219,7 @@ void player_render(void) {
gui_renderBar(&cEnergy, &gui.pos_energy, &gui.energy, player->energy / player->energy_max);
// Target.
- if(player_target) {
+ if(player_target != PLAYER_ID) {
p = pilot_get(player_target);
gl_blitStatic(p->ship->gfx_target, &gui.pos_target);
@@ -452,7 +452,7 @@ static void input_key(int keynum, double value, int abs) {
if(value == KEY_PRESS) player_target = pilot_getNext(player_target);
}
else if(strcmp(player_input[keynum]->name, "target_nearest")==0) {
- if(value == KEY_PRESS) player_target = pilot_getNearest(player);
+ if(value == KEY_PRESS) player_target = pilot_getHostile();
}
// Zoom in.
else if(strcmp(player_input[keynum]->name, "mapzoomin")==0) {
diff --git a/src/weapon.c b/src/weapon.c
index 42330f5..a6c4051 100644
--- a/src/weapon.c
+++ b/src/weapon.c
@@ -128,7 +128,7 @@ 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 != PLAYER_ID)
+ if(!pilot_isPlayer(pilot_stack[i]))
// Inform the ai it has been attacked. Useless if we are player.
ai_attacked(pilot_stack[i], w->parent);
if(w->parent == PLAYER_ID) // Make hostile to player.