[Add] Ai profile support.
This commit is contained in:
parent
dbfef7b7f0
commit
58e7c9b3d7
@ -1,18 +1,21 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Fleets>
|
<Fleets>
|
||||||
<fleet name="Test">
|
<fleet name="Test">
|
||||||
|
<ai>test</ai>
|
||||||
<faction>Independent</faction>
|
<faction>Independent</faction>
|
||||||
<pilots>
|
<pilots>
|
||||||
<pilot chance='100'>Test</pilot>
|
<pilot chance='100'>Test</pilot>
|
||||||
</pilots>
|
</pilots>
|
||||||
</fleet>
|
</fleet>
|
||||||
<fleet name="Merchant Ship">
|
<fleet name="Merchant Ship">
|
||||||
|
<ai>merchant</ai>
|
||||||
<faction>Merchant</faction>
|
<faction>Merchant</faction>
|
||||||
<pilots>
|
<pilots>
|
||||||
<pilot chance='100'>Ship</pilot>
|
<pilot chance='100'>Ship</pilot>
|
||||||
</pilots>
|
</pilots>
|
||||||
</fleet>
|
</fleet>
|
||||||
<fleet name="Sml Merchant Convoy">
|
<fleet name="Sml Merchant Convoy">
|
||||||
|
<ai>merchant</ai>
|
||||||
<faction>Merchant</faction>
|
<faction>Merchant</faction>
|
||||||
<pilots>
|
<pilots>
|
||||||
<pilot chance='80'>Ship</pilot>
|
<pilot chance='80'>Ship</pilot>
|
||||||
|
41
scripts/ai/merchant.lua
Normal file
41
scripts/ai/merchant.lua
Normal 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
|
||||||
|
|
@ -10,6 +10,15 @@ end
|
|||||||
function attacked(attacker)
|
function attacked(attacker)
|
||||||
task = taskname()
|
task = taskname()
|
||||||
if task ~= "attack" and task ~= "runaway" then
|
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)
|
pushtask(0, "attack", attacker)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -20,10 +29,6 @@ function runaway()
|
|||||||
dir = face(target, 1)
|
dir = face(target, 1)
|
||||||
accel()
|
accel()
|
||||||
dist = getdist(getpos(target))
|
dist = getdist(getpos(target))
|
||||||
|
|
||||||
if dist > 800 then
|
|
||||||
say("So long Biatch!!")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Attack
|
-- Attack
|
||||||
|
149
src/ai.c
149
src/ai.c
@ -1,7 +1,6 @@
|
|||||||
// Woot, LUA!!!!!!
|
// Woot, LUA!!!!!!
|
||||||
#include <lua.h>
|
#include "lauxlib.h"
|
||||||
#include <lauxlib.h>
|
#include "lualib.h"
|
||||||
#include <lualib.h>
|
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
@ -12,6 +11,8 @@
|
|||||||
#include "physics.h"
|
#include "physics.h"
|
||||||
#include "pack.h"
|
#include "pack.h"
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
|
#include "space.h"
|
||||||
|
#include "faction.h"
|
||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
|
|
||||||
// == AI ======================================================
|
// == AI ======================================================
|
||||||
@ -47,6 +48,7 @@
|
|||||||
|
|
||||||
// Call the AI function with name f.
|
// 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.
|
// Don't run the function if (n) params aren't passed.
|
||||||
#define MIN_ARGS(n) if(lua_gettop(L) < n) return 0
|
#define MIN_ARGS(n) if(lua_gettop(L) < n) return 0
|
||||||
@ -54,10 +56,21 @@
|
|||||||
#define MAX_DIR_ERR 5.0*M_PI/180.
|
#define MAX_DIR_ERR 5.0*M_PI/180.
|
||||||
#define MIN_VEL_ERR 2.5
|
#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_minbrakedist(lua_State* L); // Minimal breaking distance.
|
||||||
static int ai_accel(lua_State* L); // Accelerate.
|
static int ai_accel(lua_State* L); // Accelerate.
|
||||||
|
|
||||||
// Internal C routines.
|
// Internal C routines.
|
||||||
|
static int ai_loadProfile(char* filename);
|
||||||
static void ai_freetask(Task* t);
|
static void ai_freetask(Task* t);
|
||||||
// External C routines.
|
// External C routines.
|
||||||
void ai_attacked(Pilot* attacked, const unsigned int attacker); // weapon.c
|
void ai_attacked(Pilot* attacked, const unsigned int attacker); // weapon.c
|
||||||
@ -74,7 +87,7 @@ static int ai_shield(lua_State* L); // shield()
|
|||||||
static int ai_parmor(lua_State* L); // parmor()
|
static int ai_parmor(lua_State* L); // parmor()
|
||||||
static int ai_pshield(lua_State* L); // pshield()
|
static int ai_pshield(lua_State* L); // pshield()
|
||||||
static int ai_getdistance(lua_State* L); // Number getdist(Vec2)
|
static int ai_getdistance(lua_State* L); // Number getdist(Vec2)
|
||||||
static int ai_getpos(lua_State* L); // getpos(number/pilot)
|
static int ai_getpos(lua_State* L); // getpos(number)
|
||||||
static int ai_minbrakedist(lua_State* L); // Number minbrakedist()
|
static int ai_minbrakedist(lua_State* L); // Number minbrakedist()
|
||||||
// Boolean expressions.
|
// Boolean expressions.
|
||||||
static int ai_ismaxvel(lua_State* L); // Boolean ismaxvel()
|
static int ai_ismaxvel(lua_State* L); // Boolean ismaxvel()
|
||||||
@ -86,17 +99,16 @@ 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_turn(lua_State* L); // turn(number); abs(number) <= 1.
|
||||||
static int ai_face(lua_State* L); // face(number/pointer)
|
static int ai_face(lua_State* L); // face(number/pointer)
|
||||||
static int ai_brake(lua_State* L); // Brake()
|
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.
|
// Combat.
|
||||||
static int ai_shoot(lua_State* L); // shoot(number) number = 1,2,3.
|
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_getenemy(lua_State* L); // number getenemy().
|
||||||
// Misc.
|
// Misc.
|
||||||
static int ai_createvect(lua_State* L); // createvect(number, number)
|
static int ai_createvect(lua_State* L); // createvect(number, number)
|
||||||
static int ai_say(lua_State* L); // say(string)
|
static int ai_say(lua_State* L); // say(string)
|
||||||
static int ai_rng(lua_State* L); // rng(number, number)
|
static int ai_rng(lua_State* L); // rng(number, number)
|
||||||
|
|
||||||
// Global Lua interpreter.
|
|
||||||
static lua_State* L = NULL;
|
|
||||||
|
|
||||||
// Current pilot "thinking" and assorted variables.
|
// Current pilot "thinking" and assorted variables.
|
||||||
static Pilot* cur_pilot = NULL;
|
static Pilot* cur_pilot = NULL;
|
||||||
static double pilot_acc = 0.;
|
static double pilot_acc = 0.;
|
||||||
@ -111,14 +123,52 @@ void ai_destroy(Pilot* p) {
|
|||||||
|
|
||||||
// Init the AI stuff. Which is basically Lua.
|
// Init the AI stuff. Which is basically Lua.
|
||||||
int ai_init(void) {
|
int ai_init(void) {
|
||||||
L = luaL_newstate();
|
char** files;
|
||||||
if(L == NULL) {
|
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");
|
ERR("Unable to create a new Lua state");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
L = profiles[nprofiles-1].L;
|
||||||
|
|
||||||
// Open the standard Lua libraries.
|
// Open the standard Lua libraries.
|
||||||
luaL_openlibs(L);
|
//luaL_openlibs(L);
|
||||||
|
|
||||||
|
// Constants.
|
||||||
|
lua_regnumber("player", PLAYER_ID); // Player id.
|
||||||
|
|
||||||
// Register C funstions in Lua.
|
// Register C funstions in Lua.
|
||||||
// Tasks.
|
// Tasks.
|
||||||
@ -145,6 +195,8 @@ int ai_init(void) {
|
|||||||
lua_register(L, "turn", ai_turn);
|
lua_register(L, "turn", ai_turn);
|
||||||
lua_register(L, "face", ai_face);
|
lua_register(L, "face", ai_face);
|
||||||
lua_register(L, "brake", ai_brake);
|
lua_register(L, "brake", ai_brake);
|
||||||
|
lua_register(L, "getnearestplanet", ai_getnearestplanet);
|
||||||
|
lua_register(L, "getrndplanet", ai_getrndplanet);
|
||||||
// Combat.
|
// Combat.
|
||||||
lua_register(L, "shoot", ai_shoot);
|
lua_register(L, "shoot", ai_shoot);
|
||||||
lua_register(L, "getenemy", ai_getenemy);
|
lua_register(L, "getenemy", ai_getenemy);
|
||||||
@ -153,10 +205,11 @@ int ai_init(void) {
|
|||||||
lua_register(L, "say", ai_say);
|
lua_register(L, "say", ai_say);
|
||||||
lua_register(L, "rng", ai_rng);
|
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) {
|
if(luaL_dostring(L, buf) != 0) {
|
||||||
ERR("loading AI file: %s", "../scripts/ai/test.lua");
|
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.");
|
WARN("Most likely Lua file has improper syntax, please check it.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -166,6 +219,19 @@ int ai_init(void) {
|
|||||||
return 0;
|
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
|
// Clean up global AI
|
||||||
void ai_exit(void) {
|
void ai_exit(void) {
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
@ -174,6 +240,7 @@ void ai_exit(void) {
|
|||||||
// Heart of hearts of the ai!! Brains of the pilot.
|
// Heart of hearts of the ai!! Brains of the pilot.
|
||||||
void ai_think(Pilot* pilot) {
|
void ai_think(Pilot* pilot) {
|
||||||
cur_pilot = pilot; // Set current pilot being processed.
|
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.
|
// Clean up some variables.
|
||||||
pilot_acc = pilot_turn = 0.;
|
pilot_acc = pilot_turn = 0.;
|
||||||
@ -202,6 +269,7 @@ void ai_think(Pilot* pilot) {
|
|||||||
// Pilot is attacked.
|
// Pilot is attacked.
|
||||||
void ai_attacked(Pilot* attacked, const unsigned int attacker) {
|
void ai_attacked(Pilot* attacked, const unsigned int attacker) {
|
||||||
cur_pilot = attacked;
|
cur_pilot = attacked;
|
||||||
|
L = cur_pilot->ai->L;
|
||||||
lua_getglobal(L, "attacked");
|
lua_getglobal(L, "attacked");
|
||||||
lua_pushnumber(L, attacker);
|
lua_pushnumber(L, attacker);
|
||||||
lua_pcall(L, 1, 0, 0);
|
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);
|
t->ID = (unsigned int) lua_tonumber(L, 3);
|
||||||
}
|
}
|
||||||
else if(lua_islightuserdata(L, 3)) {
|
else if(lua_islightuserdata(L, 3)) {
|
||||||
|
// Only pointer valid is Vec2* in Lua.
|
||||||
t->dtype = TYPE_PTR;
|
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
|
} else
|
||||||
t->dtype = TYPE_NULL;
|
t->dtype = TYPE_NULL;
|
||||||
}
|
}
|
||||||
@ -325,7 +395,7 @@ static int ai_pshield(lua_State* L) {
|
|||||||
static int ai_getdistance(lua_State* L) {
|
static int ai_getdistance(lua_State* L) {
|
||||||
MIN_ARGS(1);
|
MIN_ARGS(1);
|
||||||
Vec2* vect = (Vec2*)lua_topointer(L,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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +403,6 @@ static int ai_getdistance(lua_State* L) {
|
|||||||
static int ai_getpos(lua_State* L) {
|
static int ai_getpos(lua_State* L) {
|
||||||
Pilot* p;
|
Pilot* p;
|
||||||
if(lua_isnumber(L, 1)) p = pilot_get((int)lua_tonumber(L,1)); // Pilot ID.
|
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.
|
else p = cur_pilot; // Default to ones self.
|
||||||
|
|
||||||
lua_pushlightuserdata(L, &p->solid->pos);
|
lua_pushlightuserdata(L, &p->solid->pos);
|
||||||
@ -432,6 +501,56 @@ static int ai_brake(lua_State* L) {
|
|||||||
return 0;
|
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.
|
// Pew pew.. Says the pilot.
|
||||||
static int ai_shoot(lua_State* L) {
|
static int ai_shoot(lua_State* L) {
|
||||||
int n = 1;
|
int n = 1;
|
||||||
|
10
src/ai.h
10
src/ai.h
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "lua.h"
|
||||||
|
|
||||||
typedef enum { TYPE_NULL, TYPE_INT, TYPE_PTR } TaskData;
|
typedef enum { TYPE_NULL, TYPE_INT, TYPE_PTR } TaskData;
|
||||||
|
|
||||||
@ -14,6 +15,15 @@ typedef struct Task {
|
|||||||
};
|
};
|
||||||
} Task;
|
} Task;
|
||||||
|
|
||||||
|
// Ai profile.
|
||||||
|
typedef struct {
|
||||||
|
char* name;
|
||||||
|
lua_State* L;
|
||||||
|
} AI_Profile;
|
||||||
|
|
||||||
|
// Misc.
|
||||||
|
AI_Profile* ai_getProfile(char* name);
|
||||||
|
|
||||||
int ai_init(void);
|
int ai_init(void);
|
||||||
void ai_exit(void);
|
void ai_exit(void);
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ int factions_load(void) {
|
|||||||
free(buf);
|
free(buf);
|
||||||
xmlCleanupParser();
|
xmlCleanupParser();
|
||||||
|
|
||||||
DEBUG("Loaded %d factions", nfactions);
|
DEBUG("Loaded %d factions%c", nfactions, (nfactions==1)?' ':'s');
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ int main(int argc, char** argv) {
|
|||||||
space_load();
|
space_load();
|
||||||
|
|
||||||
// Testing.
|
// 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);
|
gl_bindCamera(&player->solid->pos);
|
||||||
space_init("SaraSys");
|
space_init("SaraSys");
|
||||||
|
|
||||||
|
22
src/pack.c
22
src/pack.c
@ -294,30 +294,28 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi
|
|||||||
// Load the filenames int the packfile to filenames.
|
// Load the filenames int the packfile to filenames.
|
||||||
// filenames should be freed after use
|
// filenames should be freed after use
|
||||||
// On error if filenames is (char**)-1.
|
// 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; }
|
#define READ(f,b,n) if(read(f,b,n)!=n) { ERR("Too few bytes read. Expected more."); return NULL; }
|
||||||
void pack_listfiles(const char* packfile, char** filenames, uint32_t* nfiles) {
|
char** pack_listfiles(const char* packfile, uint32_t* nfiles) {
|
||||||
int fd, j;
|
int fd, j;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
char** filenames;
|
||||||
char* buf = malloc(sizeof(magic));
|
char* buf = malloc(sizeof(magic));
|
||||||
|
|
||||||
*nfiles = 0;
|
*nfiles = 0;
|
||||||
filenames = malloc(sizeof(char*));
|
|
||||||
filenames = (char**)-1;
|
|
||||||
|
|
||||||
fd = open(packfile, O_RDONLY);
|
fd = open(packfile, O_RDONLY);
|
||||||
if(fd == -1) {
|
if(fd == -1) {
|
||||||
ERR("opening %s: %s", packfile, strerror(errno));
|
ERR("opening %s: %s", packfile, strerror(errno));
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
READ(fd, buf, sizeof(magic)); // Make sure it is a packfile.
|
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);
|
ERR("File %s is not a valid packfile", packfile);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
free(buf);
|
|
||||||
|
|
||||||
READ(fd, &nfiles, 4);
|
READ(fd, nfiles, 4);
|
||||||
filenames = realloc(filenames,(*nfiles+1)*sizeof(char*));
|
filenames = malloc(((*nfiles)+1)*sizeof(char*));
|
||||||
for(i = 0; i < *nfiles; i++) {
|
for(i = 0; i < *nfiles; i++) {
|
||||||
// Start searching files.
|
// Start searching files.
|
||||||
j = 0;
|
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.
|
READ(fd, &filenames[i][j], 1); // Get the name.
|
||||||
while(filenames[i][j++] != '\0')
|
while(filenames[i][j++] != '\0')
|
||||||
READ(fd, &filenames[i][j], 1);
|
READ(fd, &filenames[i][j], 1);
|
||||||
|
READ(fd, buf, 4); // skip the location.
|
||||||
}
|
}
|
||||||
filenames[i] = NULL;
|
free(buf);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
return filenames;
|
||||||
}
|
}
|
||||||
#undef READ
|
#undef READ
|
||||||
|
|
||||||
|
@ -19,5 +19,5 @@ int pack_close(Packfile* file);
|
|||||||
|
|
||||||
// Fancy stuff.
|
// Fancy stuff.
|
||||||
void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesize);
|
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);
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@ double vect_angle(const Vec2* ref, const Vec2* v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vect_cadd(Vec2* v, const double x, const double y) {
|
void vect_cadd(Vec2* v, const double x, const double y) {
|
||||||
v->x -= x;
|
v->x += x;
|
||||||
v->y -= y;
|
v->y += y;
|
||||||
v->mod = MOD(v->x, v->y);
|
v->mod = MOD(v->x, v->y);
|
||||||
v->angle = ANGLE(v->x, v->y);
|
v->angle = ANGLE(v->x, v->y);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#define MOD(x,y) (sqrt((x)*(x) + (y)*(y)))
|
#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 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
|
// Misc
|
||||||
double angle_diff(const double ref, double a);
|
double angle_diff(const double ref, double a);
|
||||||
|
14
src/pilot.c
14
src/pilot.c
@ -161,8 +161,8 @@ static void pilot_update(Pilot* pilot, const double dt) {
|
|||||||
// pos : Initial position.
|
// pos : Initial position.
|
||||||
// flags : Tweaking the pilot.
|
// flags : Tweaking the pilot.
|
||||||
// ========================================================
|
// ========================================================
|
||||||
void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, const double dir, const Vec2* pos,
|
void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profile* ai,
|
||||||
const Vec2* vel, const int flags) {
|
const double dir, const Vec2* pos, const Vec2* vel, const int flags) {
|
||||||
|
|
||||||
if(flags & PILOT_PLAYER) // Player is ID 0
|
if(flags & PILOT_PLAYER) // Player is ID 0
|
||||||
pilot->id = 0;
|
pilot->id = 0;
|
||||||
@ -175,6 +175,9 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, const do
|
|||||||
// Faction.
|
// Faction.
|
||||||
pilot->faction = faction;
|
pilot->faction = faction;
|
||||||
|
|
||||||
|
// AI.
|
||||||
|
pilot->ai = ai;
|
||||||
|
|
||||||
// Solid.
|
// Solid.
|
||||||
pilot->solid = solid_create(ship->mass, dir, pos, vel);
|
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.
|
// 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) {
|
const Vec2* pos, const Vec2* vel, const int flags) {
|
||||||
Pilot* dyn = MALLOC_L(Pilot);
|
Pilot* dyn = MALLOC_L(Pilot);
|
||||||
if(dyn == NULL) {
|
if(dyn == NULL) {
|
||||||
WARN("Unable to allocate memory.");
|
WARN("Unable to allocate memory.");
|
||||||
return 0;
|
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) {
|
if(flags & PILOT_PLAYER) {
|
||||||
// Player.
|
// Player.
|
||||||
@ -311,6 +314,8 @@ static Fleet* fleet_parse(const xmlNodePtr parent) {
|
|||||||
// Load all the data.
|
// Load all the data.
|
||||||
if(strcmp((char*)node->name, "faction")==0)
|
if(strcmp((char*)node->name, "faction")==0)
|
||||||
tmp->faction = faction_get((char*)node->children->content);
|
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) {
|
else if(strcmp((char*)node->name, "pilots")==0) {
|
||||||
cur = node->children;
|
cur = node->children;
|
||||||
while((cur = cur->next)) {
|
while((cur = cur->next)) {
|
||||||
@ -340,6 +345,7 @@ static Fleet* fleet_parse(const xmlNodePtr parent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#define MELEMENT(o,s) if((o) == NULL) WARN("Fleet '%s' missing '"s"' element", tmp->name)
|
#define MELEMENT(o,s) if((o) == NULL) WARN("Fleet '%s' missing '"s"' element", tmp->name)
|
||||||
|
MELEMENT(tmp->ai, "ai");
|
||||||
MELEMENT(tmp->faction, "faction");
|
MELEMENT(tmp->faction, "faction");
|
||||||
MELEMENT(tmp->pilots, "pilots");
|
MELEMENT(tmp->pilots, "pilots");
|
||||||
#undef MELEMENT
|
#undef MELEMENT
|
||||||
|
11
src/pilot.h
11
src/pilot.h
@ -51,6 +51,7 @@ typedef struct Pilot {
|
|||||||
unsigned int flags; // Used for AI etc.
|
unsigned int flags; // Used for AI etc.
|
||||||
|
|
||||||
// AI.
|
// AI.
|
||||||
|
AI_Profile* ai; // Ai personality profile.
|
||||||
Task* task; // Current action.
|
Task* task; // Current action.
|
||||||
} Pilot;
|
} Pilot;
|
||||||
|
|
||||||
@ -65,6 +66,8 @@ typedef struct {
|
|||||||
char* name; // Fleet name, used as an identifier.
|
char* name; // Fleet name, used as an identifier.
|
||||||
Faction* faction; // Faction of the fleet.
|
Faction* faction; // Faction of the fleet.
|
||||||
|
|
||||||
|
AI_Profile* ai; // A useable profile.
|
||||||
|
|
||||||
FleetPilot* pilots; // The pilots in the fleet.
|
FleetPilot* pilots; // The pilots in the fleet.
|
||||||
int npilots; // Total number of pilots.
|
int npilots; // Total number of pilots.
|
||||||
} Fleet;
|
} 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);
|
void pilot_hit(Pilot* p, const double damage_shield, const double damage_armor);
|
||||||
|
|
||||||
// Creation.
|
// Creation.
|
||||||
void pilot_init(Pilot* dest, Ship* ship, char* name, Faction* faction, const double dir,
|
void pilot_init(Pilot* dest, Ship* ship, char* name, Faction* faction, AI_Profile* ai,
|
||||||
const Vec2* pos, const Vec2* vel, const int flags);
|
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,
|
unsigned int pilot_create(Ship* ship, char* name, Faction* faction, AI_Profile* ai,
|
||||||
const Vec2* pos, const Vec2* vel, const int flags);
|
const double dir, const Vec2* pos, const Vec2* vel, const int flags);
|
||||||
|
|
||||||
// Init/Cleanup.
|
// Init/Cleanup.
|
||||||
void pilot_destroy(Pilot* p);
|
void pilot_destroy(Pilot* p);
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include "pilot.h"
|
#include "pilot.h"
|
||||||
|
|
||||||
|
#define PLAYER_ID 0
|
||||||
|
|
||||||
extern Pilot* pilot;
|
extern Pilot* pilot;
|
||||||
|
|
||||||
typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;
|
typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;
|
||||||
|
63
src/space.c
63
src/space.c
@ -4,12 +4,10 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "physics.h"
|
#include "physics.h"
|
||||||
#include "opengl.h"
|
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
#include "pilot.h"
|
|
||||||
#include "pack.h"
|
#include "pack.h"
|
||||||
#include "faction.h"
|
|
||||||
#include "space.h"
|
#include "space.h"
|
||||||
|
#include "faction.h"
|
||||||
|
|
||||||
#define XML_NODE_START 1
|
#define XML_NODE_START 1
|
||||||
#define XML_NODE_TEST 3
|
#define XML_NODE_TEST 3
|
||||||
@ -32,65 +30,9 @@
|
|||||||
#define FLAG_ASTEROIDSSET (1<<2)
|
#define FLAG_ASTEROIDSSET (1<<2)
|
||||||
#define FLAG_INTEFERENCESET (1<<3)
|
#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 StarSystem* systems = NULL;
|
||||||
static int nsystems = 0;
|
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.
|
#define STAR_BUF 100 // Area to leave around screen, more = less repitition.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -223,6 +165,7 @@ void space_init(const char* sysname) {
|
|||||||
pilot_create(cur_system->fleets[i].fleet->pilots[j].ship,
|
pilot_create(cur_system->fleets[i].fleet->pilots[j].ship,
|
||||||
cur_system->fleets[i].fleet->pilots[j].name,
|
cur_system->fleets[i].fleet->pilots[j].name,
|
||||||
cur_system->fleets[i].fleet->faction,
|
cur_system->fleets[i].fleet->faction,
|
||||||
|
cur_system->fleets[i].fleet->ai,
|
||||||
vect_angle(&v,&vn),
|
vect_angle(&v,&vn),
|
||||||
&v,
|
&v,
|
||||||
NULL,
|
NULL,
|
||||||
|
61
src/space.h
61
src/space.h
@ -1,7 +1,68 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "faction.h"
|
||||||
|
#include "opengl.h"
|
||||||
|
#include "pilot.h"
|
||||||
|
|
||||||
#define MIN_HYPERSPACE_DIST 1500
|
#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.
|
// Load/Exit.
|
||||||
void space_init(const char* sysname);
|
void space_init(const char* sysname);
|
||||||
int space_load(void);
|
int space_load(void);
|
||||||
|
@ -158,12 +158,15 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
|
|||||||
|
|
||||||
switch(outfit->type) {
|
switch(outfit->type) {
|
||||||
case OUTFIT_TYPE_BOLT:
|
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;
|
rdir += RNG(-outfit->accuracy/2., outfit->accuracy/2.)/180.*M_PI;
|
||||||
if((rdir > 2.*M_PI) || (rdir < 0.)) rdir = fmod(rdir, 2.*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);
|
w->solid = solid_create(mass, rdir, pos, &v);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
// Just dump it where the player is.
|
||||||
w->solid = solid_create(mass, dir, pos, vel);
|
w->solid = solid_create(mass, dir, pos, vel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user