[Add] Ai profile support.

This commit is contained in:
Allanis 2013-02-09 00:53:37 +00:00
parent dbfef7b7f0
commit 58e7c9b3d7
17 changed files with 353 additions and 157 deletions

View File

@ -1,18 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Fleets>
<fleet name="Test">
<ai>test</ai>
<faction>Independent</faction>
<pilots>
<pilot chance='100'>Test</pilot>
</pilots>
</fleet>
<fleet name="Merchant Ship">
<ai>merchant</ai>
<faction>Merchant</faction>
<pilots>
<pilot chance='100'>Ship</pilot>
</pilots>
</fleet>
<fleet name="Sml Merchant Convoy">
<ai>merchant</ai>
<faction>Merchant</faction>
<pilots>
<pilot chance='80'>Ship</pilot>

41
scripts/ai/merchant.lua Normal file
View File

@ -0,0 +1,41 @@
-- Required control rate.
control_rate = 2
-- Required "control" function.
function control()
pushtask(0, "fly")
end
-- Required "attacked" function.
function attacked(attacker)
task = taskname()
if task ~= "runaway" then
-- Let's have some messages.
if attacker == player then
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
end
pushtask(0, "runaway", attacker)
end
end
-- Runs away.
function runaway()
target = gettargetid()
dir = face(target, 1)
accel()
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

View File

@ -10,6 +10,15 @@ end
function attacked(attacker)
task = taskname()
if task ~= "attack" and task ~= "runaway" then
-- Let's have some taunts.
if attacker == player then
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
end
pushtask(0, "attack", attacker)
end
end
@ -20,10 +29,6 @@ function runaway()
dir = face(target, 1)
accel()
dist = getdist(getpos(target))
if dist > 800 then
say("So long Biatch!!")
end
end
-- Attack

247
src/ai.c
View File

@ -1,7 +1,6 @@
// Woot, LUA!!!!!!
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "lauxlib.h"
#include "lualib.h"
#include <math.h>
@ -12,6 +11,8 @@
#include "physics.h"
#include "pack.h"
#include "rng.h"
#include "space.h"
#include "faction.h"
#include "ai.h"
// == AI ======================================================
@ -46,7 +47,8 @@
// ============================================================
// Call the AI function with name f.
#define AI_LCALL(f) (lua_getglobal(L, f), lua_pcall(L, 0, 0, 0))
#define AI_LCALL(f) (lua_getglobal(L, f), lua_pcall(L, 0, 0, 0))
#define lua_regnumber(s,n) (lua_pushnumber(L,n), lua_setglobal(L,s))
// Don't run the function if (n) params aren't passed.
#define MIN_ARGS(n) if(lua_gettop(L) < n) return 0
@ -54,48 +56,58 @@
#define MAX_DIR_ERR 5.0*M_PI/180.
#define MIN_VEL_ERR 2.5
// file info.
#define AI_PREFIX "../scripts/ai/"
#define AI_SUFFIX ".lua"
// AI profiles.
static AI_Profile* profiles = NULL;
static int nprofiles = 0;
// Current AI Lua interpreter.
static lua_State* L = NULL;
static int ai_minbrakedist(lua_State* L); // Minimal breaking distance.
static int ai_accel(lua_State* L); // Accelerate.
// Internal C routines.
static int ai_loadProfile(char* filename);
static void ai_freetask(Task* t);
// External C routines.
void ai_attacked(Pilot* attacked, const unsigned int attacker); // weapon.c
// Ai routines for Lua.
// Tasks.
static int ai_pushtask(lua_State* L); // pushtask(string, number/pointer, number)
static int ai_poptask(lua_State* L); // poptask()
static int ai_taskname(lua_State* L); // Number taskname.
static int ai_pushtask(lua_State* L); // pushtask(string, number/pointer, number)
static int ai_poptask(lua_State* L); // poptask()
static int ai_taskname(lua_State* L); // Number taskname.
// Consult values.
static int ai_gettarget(lua_State* L); // Pointer gettarget()
static int ai_gettargetid(lua_State* L); // Number gettargetis()
static int ai_armor(lua_State* L); // armor()
static int ai_shield(lua_State* L); // shield()
static int ai_parmor(lua_State* L); // parmor()
static int ai_pshield(lua_State* L); // pshield()
static int ai_getdistance(lua_State* L); // Number getdist(Vec2)
static int ai_getpos(lua_State* L); // getpos(number/pilot)
static int ai_minbrakedist(lua_State* L); // Number minbrakedist()
static int ai_gettarget(lua_State* L); // Pointer gettarget()
static int ai_gettargetid(lua_State* L); // Number gettargetis()
static int ai_armor(lua_State* L); // armor()
static int ai_shield(lua_State* L); // shield()
static int ai_parmor(lua_State* L); // parmor()
static int ai_pshield(lua_State* L); // pshield()
static int ai_getdistance(lua_State* L); // Number getdist(Vec2)
static int ai_getpos(lua_State* L); // getpos(number)
static int ai_minbrakedist(lua_State* L); // Number minbrakedist()
// Boolean expressions.
static int ai_ismaxvel(lua_State* L); // Boolean ismaxvel()
static int ai_isstopped(lua_State* L); // Boolean isstopped()
static int ai_isenemy(lua_State* L); // bool isenemy(number).
static int ai_isally(lua_State* L); // bool isally(number).
static int ai_ismaxvel(lua_State* L); // Boolean ismaxvel()
static int ai_isstopped(lua_State* L); // Boolean isstopped()
static int ai_isenemy(lua_State* L); // bool isenemy(number).
static int ai_isally(lua_State* L); // bool isally(number).
// Movement.
static int ai_accel(lua_State* L); // accel(number); nuimber <= 1.
static int ai_turn(lua_State* L); // turn(number); abs(number) <= 1.
static int ai_face(lua_State* L); // face(number/pointer)
static int ai_brake(lua_State* L); // Brake()
static int ai_accel(lua_State* L); // accel(number); nuimber <= 1.
static int ai_turn(lua_State* L); // turn(number); abs(number) <= 1.
static int ai_face(lua_State* L); // face(number/pointer)
static int ai_brake(lua_State* L); // Brake()
static int ai_getnearestplanet(lua_State* L); // pointer getnearestplanet()
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); // pointer getenemy().
static int ai_shoot(lua_State* L); // shoot(number) number = 1,2,3.
static int ai_getenemy(lua_State* L); // number getenemy().
// Misc.
static int ai_createvect(lua_State* L); // createvect(number, number)
static int ai_say(lua_State* L); // say(string)
static int ai_rng(lua_State* L); // rng(number, number)
// Global Lua interpreter.
static lua_State* L = NULL;
static int ai_createvect(lua_State* L); // createvect(number, number)
static int ai_say(lua_State* L); // say(string)
static int ai_rng(lua_State* L); // rng(number, number)
// Current pilot "thinking" and assorted variables.
static Pilot* cur_pilot = NULL;
@ -111,52 +123,93 @@ void ai_destroy(Pilot* p) {
// Init the AI stuff. Which is basically Lua.
int ai_init(void) {
L = luaL_newstate();
if(L == NULL) {
char** files;
uint32_t nfiles, i;
// Get the file list.
files = pack_listfiles(data, &nfiles);
// Load the profiles.
for(i = 0; i < nfiles; i++)
if((strncmp(files[i], AI_PREFIX, strlen(AI_PREFIX))==0 &&
strncmp(files[i] + strlen(files[i]) - strlen(AI_SUFFIX),
AI_SUFFIX, strlen(AI_SUFFIX))==0))
if(ai_loadProfile(files[i]))
WARN("Error loading AI profile '%s'", files[i]);
// Free the char allocated by pack.
for(i = 0; i < nfiles; i++)
free(files[i]);
free(files);
DEBUG("Loaded %d AI profile%c", nprofiles, (nprofiles==1)?' ':'s');
return 0;
}
// Init an IA_Profile and add it to the stack.
static int ai_loadProfile(char* filename) {
char* buf;
profiles = realloc(profiles, sizeof(AI_Profile)*(++nprofiles));
profiles[nprofiles-1].name = strndup(filename+strlen(AI_PREFIX),
strlen(filename)-strlen(AI_PREFIX)-strlen(AI_SUFFIX));
profiles[nprofiles-1].L = luaL_newstate();
if(profiles[nprofiles-1].L == NULL) {
ERR("Unable to create a new Lua state");
return -1;
}
L = profiles[nprofiles-1].L;
// Open the standard Lua libraries.
luaL_openlibs(L);
//luaL_openlibs(L);
// Constants.
lua_regnumber("player", PLAYER_ID); // Player id.
// Register C funstions in Lua.
// Tasks.
lua_register(L, "pushtask", ai_pushtask);
lua_register(L, "poptask", ai_poptask);
lua_register(L, "taskname", ai_taskname);
lua_register(L, "pushtask", ai_pushtask);
lua_register(L, "poptask", ai_poptask);
lua_register(L, "taskname", ai_taskname);
// Consult.
lua_register(L, "gettarget", ai_gettarget);
lua_register(L, "gettargetid", ai_gettargetid);
lua_register(L, "armor", ai_armor);
lua_register(L, "shield", ai_shield);
lua_register(L, "parmor", ai_parmor);
lua_register(L, "pshield", ai_pshield);
lua_register(L, "getdist", ai_getdistance);
lua_register(L, "getpos", ai_getpos);
lua_register(L, "minbrakedist", ai_minbrakedist);
lua_register(L, "gettarget", ai_gettarget);
lua_register(L, "gettargetid", ai_gettargetid);
lua_register(L, "armor", ai_armor);
lua_register(L, "shield", ai_shield);
lua_register(L, "parmor", ai_parmor);
lua_register(L, "pshield", ai_pshield);
lua_register(L, "getdist", ai_getdistance);
lua_register(L, "getpos", ai_getpos);
lua_register(L, "minbrakedist", ai_minbrakedist);
// Boolean.
lua_register(L, "ismaxvel", ai_ismaxvel);
lua_register(L, "isstopped", ai_isstopped);
lua_register(L, "isenemy", ai_isenemy);
lua_register(L, "isally", ai_isally);
lua_register(L, "ismaxvel", ai_ismaxvel);
lua_register(L, "isstopped", ai_isstopped);
lua_register(L, "isenemy", ai_isenemy);
lua_register(L, "isally", ai_isally);
// Movement.
lua_register(L, "accel", ai_accel);
lua_register(L, "turn", ai_turn);
lua_register(L, "face", ai_face);
lua_register(L, "brake", ai_brake);
lua_register(L, "accel", ai_accel);
lua_register(L, "turn", ai_turn);
lua_register(L, "face", ai_face);
lua_register(L, "brake", ai_brake);
lua_register(L, "getnearestplanet", ai_getnearestplanet);
lua_register(L, "getrndplanet", ai_getrndplanet);
// Combat.
lua_register(L, "shoot", ai_shoot);
lua_register(L, "getenemy", ai_getenemy);
lua_register(L, "shoot", ai_shoot);
lua_register(L, "getenemy", ai_getenemy);
// Misc.
lua_register(L, "createvect", ai_createvect);
lua_register(L, "say", ai_say);
lua_register(L, "rng", ai_rng);
lua_register(L, "createvect", ai_createvect);
lua_register(L, "say", ai_say);
lua_register(L, "rng", ai_rng);
char* buf = pack_readfile(DATA, "../scripts/ai/test.lua", NULL);
buf = pack_readfile(DATA, filename, NULL);
if(luaL_dostring(L, buf) != 0) {
ERR("loading AI file: %s", "../scripts/ai/test.lua");
ERR("%s", lua_tostring(L, -1));
WARN("Most likely Lua file has improper syntax, please check it.");
return -1;
}
@ -166,6 +219,19 @@ int ai_init(void) {
return 0;
}
// Get the AI_Profile with name.
AI_Profile* ai_getProfile(char* name) {
if(profiles == NULL) return NULL;
int i;
for(i = 0; i < nprofiles; i++)
if(strcmp(name, profiles[i].name)==0)
return &profiles[i];
WARN("AI Profile '%s' not found in AI stack", name);
return NULL;
}
// Clean up global AI
void ai_exit(void) {
lua_close(L);
@ -174,6 +240,7 @@ void ai_exit(void) {
// Heart of hearts of the ai!! Brains of the pilot.
void ai_think(Pilot* pilot) {
cur_pilot = pilot; // Set current pilot being processed.
L = cur_pilot->ai->L; // Set the AI profile to the current pilot's.
// Clean up some variables.
pilot_acc = pilot_turn = 0.;
@ -202,6 +269,7 @@ void ai_think(Pilot* pilot) {
// Pilot is attacked.
void ai_attacked(Pilot* attacked, const unsigned int attacker) {
cur_pilot = attacked;
L = cur_pilot->ai->L;
lua_getglobal(L, "attacked");
lua_pushnumber(L, attacker);
lua_pcall(L, 1, 0, 0);
@ -241,8 +309,10 @@ static int ai_pushtask(lua_State* L) {
t->ID = (unsigned int) lua_tonumber(L, 3);
}
else if(lua_islightuserdata(L, 3)) {
// Only pointer valid is Vec2* in Lua.
t->dtype = TYPE_PTR;
t->target = (void*)lua_topointer(L, 3);
t->target = MALLOC_L(Vec2);
vectcpy(t->target, (Vec2*)lua_topointer(L,3));
} else
t->dtype = TYPE_NULL;
}
@ -325,7 +395,7 @@ static int ai_pshield(lua_State* L) {
static int ai_getdistance(lua_State* L) {
MIN_ARGS(1);
Vec2* vect = (Vec2*)lua_topointer(L,1);
lua_pushnumber(L, DIST(*vect, cur_pilot->solid->pos));
lua_pushnumber(L, vect_dist(vect, &cur_pilot->solid->pos));
return 1;
}
@ -333,7 +403,6 @@ static int ai_getdistance(lua_State* L) {
static int ai_getpos(lua_State* L) {
Pilot* p;
if(lua_isnumber(L, 1)) p = pilot_get((int)lua_tonumber(L,1)); // Pilot ID.
else if(lua_islightuserdata(L, 1)) p = (Pilot*)lua_topointer(L, 1); // Pilot pointer.
else p = cur_pilot; // Default to ones self.
lua_pushlightuserdata(L, &p->solid->pos);
@ -432,6 +501,56 @@ static int ai_brake(lua_State* L) {
return 0;
}
// Return the nearest friendly planet's position to the pilot.
static int ai_getnearestplanet(lua_State* L) {
if(cur_system->nplanets == 0) return 0; // No planets.
double dist, d;
int i, j;
// Cycle through planets.
for(dist = 0., j = -1, i = 0; i < cur_system->nplanets; i++) {
d = vect_dist(&cur_system->planets[i].pos, &cur_pilot->solid->pos);
if((!areEnemies(cur_pilot->faction, cur_system->planets[i].faction)) &&
(d < dist)) {
// Closer friendly planet.
j = i;
dist = d;
}
}
// No friendly planet found.
if(j == -1) return 0;
lua_pushlightuserdata(L, &cur_system->planets[j].pos);
return 1;
}
// Return a random friendly planet's position to the pilot.
static int ai_getrndplanet(lua_State* L) {
if(cur_system->nplanets == 0) return 0; // No planets.
Planet** planets;
int nplanets, i;
planets = malloc(sizeof(Planet*) * cur_system->nplanets);
for(nplanets = 0, i = 0; i < cur_system->nplanets; i++)
if(!areEnemies(cur_pilot->faction, cur_system->planets[i].faction))
planets[nplanets++] = &cur_system->planets[i];
// No planet to land on found.
if(nplanets == 0) {
free(planets);
return 0;
}
// We can actually get a random planet now.
i = RNG(0,nplanets-1);
lua_pushlightuserdata(L, &planets[i]->pos);
free(planets);
return 1;
}
// Pew pew.. Says the pilot.
static int ai_shoot(lua_State* L) {
int n = 1;

View File

@ -1,4 +1,5 @@
#pragma once
#include "lua.h"
typedef enum { TYPE_NULL, TYPE_INT, TYPE_PTR } TaskData;
@ -14,6 +15,15 @@ typedef struct Task {
};
} Task;
// Ai profile.
typedef struct {
char* name;
lua_State* L;
} AI_Profile;
// Misc.
AI_Profile* ai_getProfile(char* name);
int ai_init(void);
void ai_exit(void);

View File

@ -178,7 +178,7 @@ int factions_load(void) {
free(buf);
xmlCleanupParser();
DEBUG("Loaded %d factions", nfactions);
DEBUG("Loaded %d factions%c", nfactions, (nfactions==1)?' ':'s');
return 0;
}

View File

@ -253,7 +253,7 @@ int main(int argc, char** argv) {
space_load();
// Testing.
pilot_create(ship_get("Ship"), "Player", faction_get("Player"), 0., NULL, NULL, PILOT_PLAYER);
pilot_create(ship_get("Ship"), "Player", faction_get("Player"), NULL, 0., NULL, NULL, PILOT_PLAYER);
gl_bindCamera(&player->solid->pos);
space_init("SaraSys");

View File

@ -294,30 +294,28 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi
// Load the filenames int the packfile to filenames.
// filenames should be freed after use
// On error if filenames is (char**)-1.
#define READ(f,b,n) if(read(f,b,n)!=n) { ERR("Too few bytes read. Expected more."); return; }
void pack_listfiles(const char* packfile, char** filenames, uint32_t* nfiles) {
#define READ(f,b,n) if(read(f,b,n)!=n) { ERR("Too few bytes read. Expected more."); return NULL; }
char** pack_listfiles(const char* packfile, uint32_t* nfiles) {
int fd, j;
uint32_t i;
char** filenames;
char* buf = malloc(sizeof(magic));
*nfiles = 0;
filenames = malloc(sizeof(char*));
filenames = (char**)-1;
fd = open(packfile, O_RDONLY);
if(fd == -1) {
ERR("opening %s: %s", packfile, strerror(errno));
return;
return NULL;
}
READ(fd, buf, sizeof(magic)); // Make sure it is a packfile.
if(memcpy(buf, &magic, sizeof(magic))) {
if(memcmp(buf, &magic, sizeof(magic))) {
ERR("File %s is not a valid packfile", packfile);
return;
return NULL;
}
free(buf);
READ(fd, &nfiles, 4);
filenames = realloc(filenames,(*nfiles+1)*sizeof(char*));
READ(fd, nfiles, 4);
filenames = malloc(((*nfiles)+1)*sizeof(char*));
for(i = 0; i < *nfiles; i++) {
// Start searching files.
j = 0;
@ -325,9 +323,11 @@ void pack_listfiles(const char* packfile, char** filenames, uint32_t* nfiles) {
READ(fd, &filenames[i][j], 1); // Get the name.
while(filenames[i][j++] != '\0')
READ(fd, &filenames[i][j], 1);
READ(fd, buf, 4); // skip the location.
}
filenames[i] = NULL;
free(buf);
close(fd);
return filenames;
}
#undef READ

View File

@ -19,5 +19,5 @@ int pack_close(Packfile* file);
// Fancy stuff.
void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesize);
void pack_listfiles(const char* packfile, char** filenames, uint32_t* nfiles);
char** pack_listfiles(const char* packfile, uint32_t* nfiles);

View File

@ -58,8 +58,8 @@ double vect_angle(const Vec2* ref, const Vec2* v) {
}
void vect_cadd(Vec2* v, const double x, const double y) {
v->x -= x;
v->y -= y;
v->x += x;
v->y += y;
v->mod = MOD(v->x, v->y);
v->angle = ANGLE(v->x, v->y);
}

View File

@ -9,7 +9,7 @@
#define MOD(x,y) (sqrt((x)*(x) + (y)*(y)))
#define ANGLE(x,y)(((x)==0.) ? 0. : (((x)<0.)?atan((y)/(x))+M_PI:atan((y)/(x))))
#define DIST(v,u) MOD((v).x-(u).x, (v).y-(u).y)
#define vect_dist(v,u) MOD((v)->x-(u)->x, (v)->y-(u)->y)
// Misc
double angle_diff(const double ref, double a);

View File

@ -161,8 +161,8 @@ static void pilot_update(Pilot* pilot, const double dt) {
// pos : Initial position.
// flags : Tweaking the pilot.
// ========================================================
void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, const double dir, const Vec2* pos,
const Vec2* vel, const int flags) {
void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profile* ai,
const double dir, const Vec2* pos, const Vec2* vel, const int flags) {
if(flags & PILOT_PLAYER) // Player is ID 0
pilot->id = 0;
@ -175,6 +175,9 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, const do
// Faction.
pilot->faction = faction;
// AI.
pilot->ai = ai;
// Solid.
pilot->solid = solid_create(ship->mass, dir, pos, vel);
@ -218,14 +221,14 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, const do
}
// Create a new pilot - Params are same as pilot_init. Return pilot's id.
unsigned int pilot_create(Ship* ship, char* name, Faction* faction, const double dir,
unsigned int pilot_create(Ship* ship, char* name, Faction* faction, AI_Profile* ai, const double dir,
const Vec2* pos, const Vec2* vel, const int flags) {
Pilot* dyn = MALLOC_L(Pilot);
if(dyn == NULL) {
WARN("Unable to allocate memory.");
return 0;
}
pilot_init(dyn, ship, name, faction, dir, pos, vel, flags);
pilot_init(dyn, ship, name, faction, ai, dir, pos, vel, flags);
if(flags & PILOT_PLAYER) {
// Player.
@ -311,6 +314,8 @@ static Fleet* fleet_parse(const xmlNodePtr parent) {
// Load all the data.
if(strcmp((char*)node->name, "faction")==0)
tmp->faction = faction_get((char*)node->children->content);
else if(strcmp((char*)node->name, "ai")==0)
tmp->ai = ai_getProfile((char*)node->children->content);
else if(strcmp((char*)node->name, "pilots")==0) {
cur = node->children;
while((cur = cur->next)) {
@ -340,9 +345,10 @@ static Fleet* fleet_parse(const xmlNodePtr parent) {
}
}
#define MELEMENT(o,s) if((o) == NULL) WARN("Fleet '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->faction, "faction");
MELEMENT(tmp->pilots, "pilots");
#undef MELEMENT
MELEMENT(tmp->ai, "ai");
MELEMENT(tmp->faction, "faction");
MELEMENT(tmp->pilots, "pilots");
#undef MELEMENT
return tmp;
}

View File

@ -51,6 +51,7 @@ typedef struct Pilot {
unsigned int flags; // Used for AI etc.
// AI.
AI_Profile* ai; // Ai personality profile.
Task* task; // Current action.
} Pilot;
@ -65,6 +66,8 @@ typedef struct {
char* name; // Fleet name, used as an identifier.
Faction* faction; // Faction of the fleet.
AI_Profile* ai; // A useable profile.
FleetPilot* pilots; // The pilots in the fleet.
int npilots; // Total number of pilots.
} Fleet;
@ -80,11 +83,11 @@ void pilot_shoot(Pilot* p, const int secondary);
void pilot_hit(Pilot* p, const double damage_shield, const double damage_armor);
// Creation.
void pilot_init(Pilot* dest, Ship* ship, char* name, Faction* faction, const double dir,
const Vec2* pos, const Vec2* vel, const int flags);
void pilot_init(Pilot* dest, Ship* ship, char* name, Faction* faction, AI_Profile* ai,
const double dir, const Vec2* pos, const Vec2* vel, const int flags);
unsigned int pilot_create(Ship* ship, char* name, Faction* faction, const double dir,
const Vec2* pos, const Vec2* vel, const int flags);
unsigned int pilot_create(Ship* ship, char* name, Faction* faction, AI_Profile* ai,
const double dir, const Vec2* pos, const Vec2* vel, const int flags);
// Init/Cleanup.
void pilot_destroy(Pilot* p);

View File

@ -2,6 +2,8 @@
#include <SDL.h>
#include "pilot.h"
#define PLAYER_ID 0
extern Pilot* pilot;
typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;

View File

@ -4,12 +4,10 @@
#include "log.h"
#include "physics.h"
#include "opengl.h"
#include "rng.h"
#include "pilot.h"
#include "pack.h"
#include "faction.h"
#include "space.h"
#include "faction.h"
#define XML_NODE_START 1
#define XML_NODE_TEST 3
@ -32,65 +30,9 @@
#define FLAG_ASTEROIDSSET (1<<2)
#define FLAG_INTEFERENCESET (1<<3)
// Planet types. I didn't take them from Star Trek, I promise.
typedef enum {
PLANET_CLASS_NULL = 0,
PLANET_CLASS_A, // Geothermal.
PLANET_CLASS_B, // Geomorteus.
PLANET_CLASS_C, // Geoinactive.
PLANET_CLASS_D, // Asteroid/Moon.
PLANET_CLASS_E, // Geoplastic.
PLANET_CLASS_F, // Geometallic.
PLANET_CLASS_G, // GroCrystaline.
PLANET_CLASS_H, // Desert.
PLANET_CLASS_I, // Gas Supergiant.
PLANET_CLASS_J, // Gas Giant.
PLANET_CLASS_K, // Adaptable.
PLANET_CLASS_L, // Marginal.
PLANET_CLASS_M, // Terrestrial.
PLANET_CLASS_N, // Reducing.
PLANET_CLASS_O, // Pelagic.
PLANET_CLASS_P, // Glaciated.
PLANET_CLASS_Q, // Variable.
PLANET_CLASS_R, // Rogue.
PLANET_CLASS_S, // Ultragiant.
PLANET_CLASS_T, // Ultragiant.
PLANET_CLASS_X, // Demon.
PLANET_CLASS_Y, // Demon.
PLANET_CLASS_Z // Demon.
} PlanetClass;
typedef struct {
char* name; // Planet name
Vec2 pos; // Position in star system.
PlanetClass class; // Planet type.
Faction* faction; // Planet faction.
gl_texture* gfx_space; // Graphics in space.
} Planet;
// Star systems.
typedef struct {
Fleet* fleet; // Fleet to appear.
int chance; // Chance of fleet appearing in the system.
} SystemFleet;
typedef struct {
char* name; // Star system identifier.
Vec2 pos; // Position.
int stars, asteroids; // Un numero!
double interference; // Un uh.. Percentage.
Planet* planets; // Planets.
int nplanets; // Total number of planets.
SystemFleet* fleets; // Fleets that can appear in the current system.
int nfleets; // Total number of fleets.
} StarSystem;
static StarSystem* systems = NULL;
static int nsystems = 0;
static StarSystem* cur_system = NULL; // Current star system.
StarSystem* cur_system = NULL; // Current star system.
#define STAR_BUF 100 // Area to leave around screen, more = less repitition.
typedef struct {
@ -223,6 +165,7 @@ void space_init(const char* sysname) {
pilot_create(cur_system->fleets[i].fleet->pilots[j].ship,
cur_system->fleets[i].fleet->pilots[j].name,
cur_system->fleets[i].fleet->faction,
cur_system->fleets[i].fleet->ai,
vect_angle(&v,&vn),
&v,
NULL,

View File

@ -1,7 +1,68 @@
#pragma once
#include "faction.h"
#include "opengl.h"
#include "pilot.h"
#define MIN_HYPERSPACE_DIST 1500
// Planet types. I didn't take them from Star Trek, I promise.
typedef enum {
PLANET_CLASS_NULL = 0,
PLANET_CLASS_A, // Geothermal.
PLANET_CLASS_B, // Geomorteus.
PLANET_CLASS_C, // Geoinactive.
PLANET_CLASS_D, // Asteroid/Moon.
PLANET_CLASS_E, // Geoplastic.
PLANET_CLASS_F, // Geometallic.
PLANET_CLASS_G, // GroCrystaline.
PLANET_CLASS_H, // Desert.
PLANET_CLASS_I, // Gas Supergiant.
PLANET_CLASS_J, // Gas Giant.
PLANET_CLASS_K, // Adaptable.
PLANET_CLASS_L, // Marginal.
PLANET_CLASS_M, // Terrestrial.
PLANET_CLASS_N, // Reducing.
PLANET_CLASS_O, // Pelagic.
PLANET_CLASS_P, // Glaciated.
PLANET_CLASS_Q, // Variable.
PLANET_CLASS_R, // Rogue.
PLANET_CLASS_S, // Ultragiant.
PLANET_CLASS_T, // Ultragiant.
PLANET_CLASS_X, // Demon.
PLANET_CLASS_Y, // Demon.
PLANET_CLASS_Z // Demon.
} PlanetClass;
typedef struct {
char* name; // Planet name
Vec2 pos; // Position in star system.
PlanetClass class; // Planet type.
Faction* faction; // Planet faction.
gl_texture* gfx_space; // Graphics in space.
} Planet;
// Star systems.
typedef struct {
Fleet* fleet; // Fleet to appear.
int chance; // Chance of fleet appearing in the system.
} SystemFleet;
typedef struct {
char* name; // Star system identifier.
Vec2 pos; // Position.
int stars, asteroids; // Un numero!
double interference; // Un uh.. Percentage.
Planet* planets; // Planets.
int nplanets; // Total number of planets.
SystemFleet* fleets; // Fleets that can appear in the current system.
int nfleets; // Total number of fleets.
} StarSystem;
extern StarSystem* cur_system; // Current star system.
// Load/Exit.
void space_init(const char* sysname);
int space_load(void);

View File

@ -158,12 +158,15 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
switch(outfit->type) {
case OUTFIT_TYPE_BOLT:
// Need accuracy and speed based on player. -- Another contribution from VLack.
rdir += RNG(-outfit->accuracy/2., outfit->accuracy/2.)/180.*M_PI;
if((rdir > 2.*M_PI) || (rdir < 0.)) rdir = fmod(rdir, 2.*M_PI);
vect_cset(&v, VX(*vel)+outfit->speed*cos(rdir), VANGLE(*vel)+outfit->speed*sin(rdir));
vectcpy(&v, vel);
vect_cadd(&v, outfit->speed*cos(rdir), outfit->speed*sin(rdir));
w->solid = solid_create(mass, rdir, pos, &v);
break;
default:
// Just dump it where the player is.
w->solid = solid_create(mass, dir, pos, vel);
break;
}