[Add] Outfit loading.. Not fully done yet.

This commit is contained in:
Allanis 2013-02-04 17:44:53 +00:00
parent c10b1f24fb
commit b13ecc66bb
16 changed files with 295 additions and 61 deletions

View File

@ -14,9 +14,9 @@ CSDL = $(shell sdl-config --cflags)
CXML = $(shell xml2-config --cflags)
CTTF = $(shell freetype-config --cflags)
CGL =
CFLAGS = -Wall $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(VERSION)
CFLAGS = $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(VERSION)
ifdef DEBUG
CFLAGS += -g3 -DDEBUG -DLUA_USE_APICHECK
CFLAGS += -W -Wall -g3 -DDEBUG -DLUA_USE_APICHECK
else
CFLAGS += -O2
endif

View File

@ -2,21 +2,19 @@
<Outfits>
<outfit name="laser">
<general>
<max>0</max>
<type>1</type>
<tech>0</tech>
<max>5</max>
<tech>2</tech>
<mass>1</mass>
</general>
<sound>laser</sound>
<GFX>
<game>laser_green</game>
</GFX>
<parameters>
<parameter>7</parameter>
<parameter>7</parameter>
<parameter>600</parameter>
<parameter>400</parameter>
<parameter>18</parameter>
<parameter>500</parameter>
</parameters>
<specific type = "1">
<sound>laser.wav</sound>
<gfx>lasergreen.png</gfx>
<speed>450</speed>
<accuracy>30</accuracy>
<damage>
<armor>20</armor>
<shield>10</shield>
</damage>
</specific>
</outfit>
</Outfits>

BIN
gfx/outfit/lasergreen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -3,14 +3,14 @@ control_rate = 2
-- Required "control" function.
function control()
pusttask(0, "follow");
pushtask(0, "follow");
end
function follow()
target =1
dir = face(target)
dist = getdist(getpos(targer))
if dir < 10 and dist > 100 then
dist = getdist(getpos(target))
if -dir < 10 and dist > 100 then
accel(dist/100-1)
end
end

View File

@ -217,6 +217,7 @@ static int ai_pushtask(lua_State* L) {
// Pop the current task.
static int ai_poptask(lua_State* L) {
(void)L; // Just a hack to avoid -W -Wall warnings.
Task* t = cur_pilot->task;
cur_pilot->task = t->next;
t->next = NULL;
@ -231,7 +232,7 @@ static int ai_taskname(lua_State* L) {
return 1;
}
// Grab the targer pointer.
// Grab the target pointer.
static int ai_gettarget(lua_State* L) {
lua_pushlightuserdata(L, cur_pilot->task->target);
return 1;
@ -315,7 +316,7 @@ static int ai_face(lua_State* L) {
if(lua_isnumber(L,1)) v = &get_pilot((unsigned int)lua_tonumber(L,1))->solid->pos;
else if(lua_islightuserdata(L,1)) v = (Vec2*)lua_topointer(L,1);
double mod = 10;
double mod = -10;
if(lua_gettop(L) > 1 && lua_isnumber(L,2))
switch((int)lua_tonumber(L,2)) {
case 0: break;
@ -333,6 +334,7 @@ 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)

View File

@ -1,6 +1,6 @@
#pragma once
struct Task {
typedef struct Task {
struct Task* next;
char* name;
@ -8,8 +8,7 @@ struct Task {
void* target; // Vec2 etc.
unsigned int ID; // Pilot ID etc.
};
};
typedef struct Task Task;
} Task;
int ai_init(void);
void ai_exit(void);

View File

@ -17,6 +17,7 @@
#include "space.h"
#include "rng.h"
#include "ai.h"
#include "outfit.h"
#include "pilot.h"
#define WINDOW_CAPTION "Lephisto"
@ -219,6 +220,7 @@ int main(int argc, char** argv) {
gl_fontInit(NULL, NULL, 16);
// Data loading.
outfit_load();
ships_load();
space_load();
@ -249,6 +251,7 @@ int main(int argc, char** argv) {
space_exit(); // Clean up the universe!!!
pilots_free(); // Free the pilots, they where locked up D:
ships_free();
outfit_free();
gl_freeFont(NULL);

View File

@ -8,3 +8,8 @@
extern char* data; // Modifiable datafile.
#define DATA data // Data file.
// Max filename path.
#ifndef PATH_MAX
# define PATH_MAX 100
#endif

View File

@ -551,7 +551,7 @@ int gl_init(void) {
// Some openGL options.
glClearColor(0., 0., 0., 1.);
glDisable(GL_DEPTH_TEST); // Set for doing 2D shidazles.
//glEnable(GL_TEXTURE_2D);
//glEnable(GL_TEXTURE_2D); // Don't enable globally, it will break non-texture blits.
glDisable(GL_LIGHTING); // No lighting, it is done when rendered.
glMatrixMode(GL_PROJECTION);
glMatrixMode(GL_PROJECTION);

190
src/outfit.c Normal file
View File

@ -0,0 +1,190 @@
#include <libxml/parser.h>
#include <math.h>
#include <string.h>
#include "main.h"
#include "log.h"
#include "outfit.h"
#define XML_NODE_START 1
#define XML_NODE_TEXT 3
#define XML_OUTFIT_ID "Outfits"
#define XML_OUTFIT_TAG "outfit"
#define OUTFIT_DATA "../dat/outfit.xml"
#define OUTFIT_GFX "../gfx/outfit/"
static Outfit* outfit_stack = NULL;
static int outfits = 0;
static Outfit* outfit_parse(const xmlNodePtr parent);
static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent);
// Return an outfit.
Outfit* outfit_get(const char* name) {
int i;
for(i = 0; i < outfits; i++)
if(strcmp(name, outfit_stack[i].name)==0)
return &outfit_stack[i];
return NULL;
}
// Return 1 if outfit is a weapon.
int outfit_isweapon(const Outfit* o) {
return (o->type > OUTFIT_TYPE_NULL && o->type <= OUTFIT_TYPE_MISSILE_SWARM_SMART);
}
const char* outfit_typename[] = {
"NULL",
"Bolt Cannon",
"Beam Cannon",
"Dumb Missile",
"Seeker Missile",
"Smart Missile",
"Swam Missile",
"Smart Swarm Missile"
};
const char* outfit_getType(const Outfit* o) {
return outfit_typename[o->type];
}
// Parses the specific area for a weapon and loads it into outfit.
static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
xmlNodePtr cur, node;
node = parent->xmlChildrenNode;
char str[PATH_MAX] = "\0";
while((node = node->next)) {
// Load all the things.
if(strcmp((char*)node->name, "speed")==0)
tmp->speed = (double)atoi((char*)node->children->content);
else if(strcmp((char*)node->name, "accuracy")==0)
tmp->accuracy = atof((char*)node->children->content)*M_PI/180.; // to rad.
else if(strcmp((char*)node->name, "gfx")==0) {
snprintf(str, strlen((char*)node->children->content)+sizeof(OUTFIT_GFX),
OUTFIT_GFX"%s", (char*)node->children->content);
tmp->gfx_space = gl_newSprite(str, 6, 6);
}
if(strcmp((char*)node->name, "damage")==0) {
cur = node->children;
while((cur = cur->next)) {
if(strcmp((char*)cur->name, "armor")==0)
tmp->damage_armor = atof((char*)cur->children->content);
else if(strcmp((char*)cur->name, "shield")==0)
tmp->damage_shield = atof((char*)cur->children->content);
}
}
}
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->speed, "speed");
MELEMENT(tmp->accuracy, "tech");
MELEMENT(tmp->damage_armor, "armor' from element 'damage");
MELEMENT(tmp->damage_shield, "shield' from element 'damage");
#undef MELEMENT
}
// Parse and return Outfits from parent node.
static Outfit* outfit_parse(const xmlNodePtr parent) {
Outfit* tmp = CALLOC_L(Outfit);
xmlNodePtr cur, node;
xmlChar* prop;
tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name"); // Already mallocs.
node = parent->xmlChildrenNode;
while((node = node->next)) {
// Load all the things.
if(strcmp((char*)node->name, "general")==0) {
cur = node->children;
while((cur = cur->next)) {
if(strcmp((char*)cur->name, "max")==0)
tmp->max = atoi((char*)cur->children->content);
else if(strcmp((char*)cur->name, "tech")==0)
tmp->tech = atoi((char*)cur->children->content);
else if(strcmp((char*)cur->name, "mass")== 0)
tmp->mass = atoi((char*)cur->children->content);
}
}
else if(strcmp((char*)node->name, "specific")==0) {
// Has to be processed seperately.
prop = xmlGetProp(node,(xmlChar*)"type");
if(prop == NULL)
ERR("Outfit '%s' element 'specific' missing property 'type'", tmp->name);
tmp->type = atoi((char*)prop);
free(prop);
switch(tmp->type) {
case OUTFIT_TYPE_NULL:
WARN("Outfit '%s' is of type NONE", tmp->name);
break;
case OUTFIT_TYPE_BOLT:
outfit_parseSWeapon(tmp, node);
break;
default:
break;
}
}
}
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->max, "max");
MELEMENT(tmp->tech, "tech");
MELEMENT(tmp->mass, "mass");
MELEMENT(tmp->type, "type");
#undef MELEMENT
DEBUG("Loaded outfit '%s' of type '%s'", tmp->name, outfit_getType(tmp));
return tmp;
}
// Load all the outfits into the outfit stack.
int outfit_load(void) {
uint32_t bufsize;
char* buf = pack_readfile(DATA, OUTFIT_DATA, &bufsize);
Outfit* tmp;
xmlNodePtr node;
xmlDocPtr doc = xmlParseMemory(buf, bufsize);
node = doc->xmlChildrenNode;
if(strcmp((char*)node->name, XML_OUTFIT_ID)) {
ERR("Malformed "OUTFIT_DATA" file: missing root element '"XML_OUTFIT_ID"'");
return -1;
}
node = node->xmlChildrenNode; // First system node.
if(node == NULL) {
ERR("Malformed "OUTFIT_DATA" file: does not contain elements");
return -1;
}
do {
if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_OUTFIT_TAG)==0) {
tmp = outfit_parse(node);
outfit_stack = realloc(outfit_stack, sizeof(Outfit)*(++outfits));
memcpy(outfit_stack+outfits-1, tmp, sizeof(Outfit));
free(tmp);
}
} while((node = node->next));
xmlFreeDoc(doc);
free(buf);
xmlCleanupParser();
return 0;
}
// Frees the outfit stack.
void outfit_free(void) {
int i;
for(i = 0; i < outfits; i++) {
if(outfit_isweapon(&outfit_stack[i]) && outfit_stack[i].gfx_space)
gl_freeTexture(outfit_stack[i].gfx_space);
free(outfit_stack[i].name);
}
free(outfit_stack);
}

45
src/outfit.h Normal file
View File

@ -0,0 +1,45 @@
#pragma once
#include "opengl.h"
// Outfit types.
typedef enum {
OUTFIT_TYPE_NULL,
OUTFIT_TYPE_BOLT,
OUTFIT_TYPE_BEAM,
OUTFIT_TYPE_MISSILE_DUMB,
OUTFIT_TYPE_MISSILE_SEEK,
OUTFIT_TYPE_MISSILE_SEEK_SMART,
OUTFIT_TYPE_MISSILE_SWARM,
OUTFIT_TYPE_MISSILE_SWARM_SMART
} OutfitType;
// An outfit depends a lot on the type.
typedef struct {
char* name;
int max;
int tech;
int mass;
gl_texture gfx_store;
OutfitType type;
union {
struct {
double speed;
double accuracy;
double damage_armor, damage_shield;
gl_texture* gfx_space;
};
};
} Outfit;
Outfit* outfit_get(const char* name);
int outfit_isweapon(const Outfit* o);
const char* outfit_getType(const Outfit* o);
// Load/free outfit stack.
int outfit_load(void);
void outfit_free(void);

View File

@ -80,7 +80,8 @@ int pack_check(const char* filename) {
int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles) {
void* buf;
struct stat file;
int i, namesize;
uint32_t i;
int namesize;
int outfd, infd;
uint32_t indexsize, pointer;
int bytes;
@ -163,8 +164,8 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
ERR("Too few bytes read. Expected more."); \
free(buf); return -1; }
int pack_open(Packfile* file, const char* packfile, const char* filename) {
int i, j;
uint32_t nfiles;
int j;
uint32_t nfiles, i;
char* buf = malloc(MAX_FILENAME);
file->start = file->end = 0;
@ -201,7 +202,7 @@ int pack_open(Packfile* file, const char* packfile, const char* filename) {
if(file->start) {
// Go to the beginning of the file.
if(lseek(file->fd, file->start, SEEK_SET) != file->start) {
if((uint32_t)lseek(file->fd, file->start, SEEK_SET) != file->start) {
ERR("Failure to seek to file start: %s", strerror(errno));
return -1;
}

View File

@ -16,7 +16,7 @@ static int pilots = 0;
// External.
extern void ai_destroy(Pilot* p); // Ai.
extern void player_think(Pilot* pilot, const double dt); // Player.c
extern void player_think(Pilot* pilot); // Player.c
extern void ai_think(Pilot* pilot); // Ai.c
// Internal.
static void pilot_update(Pilot* pilot, const double dt);
@ -89,7 +89,7 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, const Vec2* vel, const Vec
pilot->task = NULL;
if(flags & PILOT_PLAYER) {
pilot->think = (void*)player_think; // Players don't need to thing! :P
pilot->think = player_think; // Players don't need to thing! :P
pilot->properties |= PILOT_PLAYER;
player = pilot;
} else

View File

@ -7,7 +7,7 @@
#define PILOT_PLAYER 1 // Pilot is a player.
// Primary pilot structure.
struct Pilot {
typedef struct Pilot {
unsigned int id; // Pilots id.
char* name; // Pilot's name (if unique).
@ -25,8 +25,7 @@ struct Pilot {
// AI.
void (*think)(struct Pilot*); // Ai thinking for the pilot.
Task* task; // Current action.
};
typedef struct Pilot Pilot;
} Pilot;
extern Pilot* player; // The player.
Pilot* get_pilot(unsigned int id);

View File

@ -11,7 +11,7 @@
typedef struct {
char* name; // Keybinding name, taken from keybindNames[]
KeybindType type; // type, defined in player.h.
int key; // Key/axis/button event number.
unsigned int key; // Key/axis/button event number.
double reverse; // 1. if normal, -1 if reversed, only useful for joystick axis.
} Keybind;
static Keybind** player_input; // Contains the players keybindings.
@ -24,7 +24,7 @@ static double player_acc = 0.; // Accel velocity from input.
// Used in pilot.c
// Basically uses keyboard input instead of AI input.
void player_think(Pilot* player, const double dt) {
void player_think(Pilot* player) {
player->solid->dir_vel = 0.;
if(player_turn)
player->solid->dir_vel -= player->ship->turn * player_turn;
@ -109,16 +109,16 @@ static void input_key(int keynum, double value, int abs) {
// --Events--
static void input_joyaxis(int axis, int value);
static void input_joydown(int button);
static void input_joyup(int button);
static void input_joyaxis(const unsigned int axis, const int value);
static void input_joydown(const unsigned int button);
static void input_joyup(const unsigned int button);
static void input_keydown(SDLKey key);
static void input_keyup(SDLKey key);
// Joystick.
// Axis.
static void input_joyaxis(int axis, int value) {
static void input_joyaxis(const unsigned int axis, const int value) {
int i;
for(i = 0; keybindNames[i]; i++)
if(player_input[i]->type == KEYBIND_JAXIS && player_input[i]->key == axis) {
@ -128,7 +128,7 @@ static void input_joyaxis(int axis, int value) {
}
// Joystick button down.
static void input_joydown(int button) {
static void input_joydown(const unsigned int button) {
int i;
for(i = 0; keybindNames[i]; i++)
if(player_input[i]->type == KEYBIND_JBUTTON && player_input[i]->key == button) {
@ -138,7 +138,7 @@ static void input_joydown(int button) {
}
// Joystick button up.
static void input_joyup(int button) {
static void input_joyup(const unsigned int button) {
int i;
for(i = 0; keybindNames[i]; i++)
if(player_input[i]->type == KEYBIND_JBUTTON && player_input[i]->key == button) {

View File

@ -10,8 +10,6 @@
#include "pack.h"
#include "space.h"
#define MAX_PATH_NAME 30 // Max size of the path.
#define XML_NODE_START 1
#define XML_NODE_TEST 3
@ -22,7 +20,7 @@
#define XML_SYSTEM_TAG "ssys"
#define PLANET_DATA "../dat/planet.xml"
#define SPACE_DATA "../dat/ssys.xml"
#define SYSTEM_DATA "../dat/ssys.xml"
#define PLANET_GFX "../gfx/planet/"
@ -103,7 +101,7 @@ void space_init(const char* sysname) {
if(strcmp(sysname, systems[i].name)==0)
break;
if(i == nsystems) ERR("System %s not found in stack", sysname);
cur_system = systems++;
cur_system = systems+i;
nstars = (cur_system->stars*gl_screen.w*gl_screen.h+STAR_BUF*STAR_BUF)/(800*640);
stars = malloc(sizeof(Star)*nstars);
@ -118,7 +116,7 @@ void space_init(const char* sysname) {
static Planet* planet_get(const char* name) {
Planet* tmp = NULL;
char str[MAX_PATH_NAME] = "\0";
char str[PATH_MAX] = "\0";
char* tstr;
uint32_t flags = 0;
@ -274,7 +272,7 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
// Load the ENTIRE universe into RAM. -- WOAH! -- Wasn't that bad. :P
int space_load(void) {
uint32_t bufsize;
char* buf = pack_readfile(DATA, SPACE_DATA, &bufsize);
char* buf = pack_readfile(DATA, SYSTEM_DATA, &bufsize);
StarSystem* tmp;
@ -283,25 +281,20 @@ int space_load(void) {
node = doc->xmlChildrenNode;
if(strcmp((char*)node->name, XML_SYSTEM_ID)) {
ERR("Malformed "SPACE_DATA" file: missing root element '"XML_SYSTEM_ID"'");
ERR("Malformed "SYSTEM_DATA" file: missing root element '"XML_SYSTEM_ID"'");
return -1;
}
node = node->xmlChildrenNode; // First system node.
if(node == NULL) {
ERR("Malformed "SPACE_DATA" file: does not contain elements");
ERR("Malformed "SYSTEM_DATA" file: does not contain elements");
return -1;
}
do {
if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_SYSTEM_TAG)==0) {
if(systems == NULL) {
systems = tmp = system_parse(node);
nsystems = 1;
} else {
tmp = system_parse(node);
systems = realloc(systems, sizeof(StarSystem)*(++nsystems));
memcpy(systems+nsystems-1, tmp, sizeof(StarSystem));
free(tmp);
}
tmp = system_parse(node);
systems = realloc(systems, sizeof(StarSystem)*(++nsystems));
memcpy(systems+nsystems-1, tmp, sizeof(StarSystem));
free(tmp);
}
} while((node = node->next));
@ -339,7 +332,6 @@ void space_render(double dt) {
// Render the planets.
void planets_render(void) {
int i;
Vec2 v;
for(i = 0; i < cur_system->nplanets; i++)
gl_blitSprite(cur_system->planets[i].gfx_space, &cur_system->planets[i].pos, 0, 0);
}