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 @@ <?xml version="1.0" encoding="UTF-8"?> <Fleets> - <fleet name="Test"> + <fleet name="Pirate"> <ai>test</ai> <faction>Independent</faction> <pilots> - <pilot chance='100'>Test</pilot> + <pilot chance='100'>Pirate</pilot> </pilots> </fleet> <fleet name="Merchant Ship"> <ai>merchant</ai> <faction>Merchant</faction> <pilots> - <pilot chance='100'>Ship</pilot> + <pilot chance='100'>Merchant Ship</pilot> </pilots> </fleet> <fleet name="Sml Merchant Convoy"> <ai>merchant</ai> <faction>Merchant</faction> <pilots> - <pilot chance='80'>Ship</pilot> - <pilot chance='80'>Ship</pilot> - <pilot chance='60'>Ship</pilot> - <pilot chance='60'>Ship</pilot> + <pilot chance='80'>Merchant Ship</pilot> + <pilot chance='80'>Merchant Ship</pilot> + <pilot chance='60'>Merchant Ship</pilot> + <pilot chance='60'>Merchant Ship</pilot> </pilots> </fleet> </Fleets> 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 @@ <?xml version="1.0" encoding="UTF-8"?> <Ships> - <ship name="Ship"> + <ship name="Merchant Ship"> <GFX>ship</GFX> <class>1</class> <movement> @@ -26,7 +26,7 @@ <outfit quantity='3'>laser</outfit> </outfits> </ship> - <ship name="Test"> + <ship name="Pirate"> <GFX>ship1</GFX> <class>1</class> <movement> 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 @@ <planet>KonoSphere</planet> </planets> <fleets> - <fleet chance="100">Test</fleet> + <fleet chance="100">Merchant Ship</fleet> <fleet chance="60">Merchant Ship</fleet> <fleet chance="50">Merchant Ship</fleet> <fleet chance="40">Merchant Ship</fleet> - <fleet chance="50">Sml Merchant Convoy</fleet> - <fleet chance="40">Sml Merchant Convoy</fleet> + <fleet chance="50">Pirate</fleet> + <fleet chance="40">Pirate</fleet> </fleets> </ssys> <ssys name="KonoSys"> 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.