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.