[Add] Game now tries to load mission properly, excpet lua needs more bindings. ;)

This commit is contained in:
Allanis 2013-03-31 19:00:05 +01:00
parent fc0a6776c2
commit 6fc39a69e0
7 changed files with 191 additions and 25 deletions

View File

@ -49,11 +49,12 @@ endif
# DATA.
DATA_AI = $(shell find ../scripts/ai/ -name '*.lua')
DATA_GFX = $(shell find ../gfx/ -name '*.png')
DATA_XML = $(shell find ../dat/ -name '*.xml' -o -name '*.ttf')
DATA_SND = $(shell find ../snd/ -name '*.ogg' -o -name '*.wav')
DATA_GFX = $(shell find ../gfx/ -name '*.png')
DATA_XML = $(shell find ../dat/ -name '*.xml' -o -name '*.ttf')
DATA_SND = $(shell find ../snd/ -name '*.ogg' -o -name '*.wav')
DATA_MISN = $(shell find ../dat/missions/ -name '*.lua')
DATA = data
DATAFILES = $(VERSIONFILE) $(DATA_AI) $(DATA_GFX) $(DATA_XML) $(DATA_SND)
DATAFILES = $(VERSIONFILE) $(DATA_AI) $(DATA_GFX) $(DATA_XML) $(DATA_SND) $(DATA_MISN)
# TARGETS.
%.o: %.c %.h

View File

@ -1,5 +1,8 @@
<Missions>
<mission name="Welcome">
<flags>
<unique>1</unique>
</flags>
<lua>welcome</lua>
<avail>
<location>None</location>

View File

@ -22,7 +22,7 @@ end
function accept()
player.addCargo(carg_type, carg_mass)
toolkit.msg("Mission Accepted",
string.format("The workers load the %d tons of %s onto your ship."
string.format("The workers load the %d tons of %s onto your ship.",
carg_mass, carg_type))
end

View File

@ -176,7 +176,7 @@ int faction_ofAlliance(int f, int a) {
return 0;
}
aa = &alliances[a];
aa = &alliances[a-ALLIANCE_OFFSET];
for(i = 0; i < aa->nfactions; i++)
if(aa->factions[i] == f)

View File

@ -6,6 +6,7 @@
#include "music.h"
#include "economy.h"
#include "hook.h"
#include "mission.h"
#include "land.h"
// Global/main window.
@ -37,13 +38,29 @@
#define MUSIC_TAKEOFF "liftoff"
#define MUSIC_LAND "agriculture"
int landed = 0;
// We use visited flags to not duplicate missions generated.
#define VISITED_LAND (1<<0)
#define VISITED_COMMODITY (1<<1)
#define VISITED_BAR (1<<2)
#define VISITED_OUTFITS (1<<3)
#define VISITED_SHIPYARD (1<<4)
#define visited(f) (land_visited |= (f))
#define has_visited(f) (land_visited & (f))
static unsigned int land_visited = 0;
// Land variables.
int landed = 0;
Planet* land_planet = NULL;
// Mission computer stack.
static Mission* mission_computer = NULL;
static int mission_ncomputer = 0;
// Window stuff.
static int land_wid = 0; // Primary land window.
// For the second opened land window
static int secondary_wid = 0;
static int terciary_wid = 0; // For fancy things like news, your ship etc..
Planet* land_planet = NULL;
// Commodity excahnge.
static void commodity_exchange(void);
@ -121,6 +138,11 @@ static void commodity_exchange(void) {
goods, land_planet->ncommodities, 0, commodity_update);
commodity_update(NULL);
if(!has_visited(VISITED_COMMODITY)) {
// TODO: mission check.
visited(VISITED_COMMODITY);
}
}
static void commodity_exchange_close(char* str) {
@ -250,6 +272,11 @@ static void outfits(void) {
// Write the outfits stuff.
outfits_update(NULL);
if(!has_visited(VISITED_OUTFITS)) {
// TODO: mission check.
visited(VISITED_OUTFITS);
}
}
static void outfits_close(char* str) {
@ -436,6 +463,11 @@ static void shipyard(void) {
// Write the shipyard stuff.
shipyard_update(NULL);
if(!has_visited(VISITED_SHIPYARD)) {
// TODO: mission check.
visited(VISITED_SHIPYARD);
}
}
static void shipyard_close(char* str) {
@ -693,6 +725,11 @@ static void spaceport_bar(void) {
BAR_WIDTH-40, BAR_HEIGHT - 40 - BUTTON_HEIGHT, 0,
"txtDescription", &gl_smallFont, &cBlack,
land_planet->bar_description);
if(!has_visited(VISITED_BAR)) {
// TODO: mission check.
visited(VISITED_BAR);
}
}
static void spaceport_bar_close(char* str) {
@ -767,16 +804,26 @@ void land(Planet* p) {
landed = 1;
hooks_run("land");
// Generate mission computer stuff.
mission_computer = missions_computer(&mission_ncomputer,
land_planet->faction, land_planet->name, cur_system->name);
if(!has_visited(VISITED_LAND)) {
// TODO: mission check.
visited(VISITED_LAND);
}
}
// Takeoff from the planet.
void takeoff(void) {
int sw, sh, i;
if(!landed) return;
music_load(MUSIC_TAKEOFF);
music_play();
int sw, sh;
sw = land_planet->gfx_space->w;
sh = land_planet->gfx_space->h;
@ -799,6 +846,14 @@ void takeoff(void) {
land_planet = NULL;
window_destroy(land_wid);
landed = 0;
land_visited = 0;
hooks_run("takeoff");
// Cleanup mission computer.
for(i = 0; i < mission_ncomputer; i++)
mission_free(&mission_computer[i]);
free(mission_computer);
mission_computer = NULL;
mission_ncomputer = 0;
}

View File

@ -19,6 +19,9 @@
#define MISSION_DATA "../dat/mission.xml"
#define MISSION_LUA_PATH "../dat/missions/"
#define luaL_dobuffer(L, b, n, s) \
(luaL_loadbuffer(L, b, n, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
// Current player missions.
static unsigned int mission_id = 0;
Mission player_missions[MISSION_MAX];
@ -31,13 +34,49 @@ static int mission_nstack = 0;
extern int misn_run(Mission* misn, char* func);
// Static.
static int mission_init(Mission* mission, MissionData* misn);
static void mission_cleanup(Mission* misn);
static void mission_free(MissionData* mission);
static void mission_freeData(MissionData* mission);
static int mission_matchFaction(MissionData* misn, int faction);
static int mission_location(char* loc);
static MissionData* mission_parse(const xmlNodePtr parent);
// Create a mission.
int mission_create(MissionData* misn) {
// Initialize a mission.
static int mission_init(Mission* mission, MissionData* misn) {
char* buf;
uint32_t bufsize;
mission->id = ++mission_id;
mission->data = misn;
// Init lua.
mission->L = luaL_newstate();
if(mission->L == NULL) {
ERR("Unable to create a new lua state.");
return -1;
}
luaopen_string(mission->L); // string.format can be very useful.
misn_loadLibs(mission->L); // Load our custom libraries.
buf = pack_readfile(DATA, misn->lua, &bufsize);
if(luaL_dobuffer(mission->L, buf, bufsize, misn->lua) != 0) {
ERR("Error loading AI file: %s", misn->lua);
ERR("%s", lua_tostring(mission->L, -1));
WARN("Most likely Lua file has improper syntax, please check it");
return -1;
}
free(buf);
// Run create function.
misn_run(mission, "create");
return mission->id;
}
// Add a mission to the player, you can free the current mission safely.
int mission_add(Mission* mission) {
int i;
// Find last mission.
@ -47,17 +86,11 @@ int mission_create(MissionData* misn) {
// No missions left.
if(i >= MISSION_MAX) return -1;
player_missions[i].id = ++mission_id;
player_missions[i].data = misn;
// Copy it over.
memcpy(&player_missions[i], mission, sizeof(Mission));
memset(mission, 0, sizeof(Mission));
// Init lua.
player_missions[i].L = luaL_newstate();
luaopen_string(player_missions[i].L); // String.format can be useful..
misn_loadLibs(player_missions[i].L); // Load our custom libraries.
misn_run(&player_missions[i], "create");
return 0;
return player_missions[i].id;
}
// Clean up a mission.
@ -71,7 +104,7 @@ static void mission_cleanup(Mission* misn) {
}
// Free a mission.
static void mission_free(MissionData* mission) {
static void mission_freeData(MissionData* mission) {
if(mission->name) {
free(mission->name);
mission->name = NULL;
@ -91,6 +124,66 @@ static void mission_free(MissionData* mission) {
}
}
// Free an active mission.
void mission_free(Mission* mission) {
if(mission->id == 0) return;
if(mission->title) {
free(mission->title);
mission->title = NULL;
}
if(mission->desc) {
free(mission->desc);
mission->desc = NULL;
}
if(mission->reward) {
free(mission->reward);
mission->reward = NULL;
}
if(mission->L) {
lua_close(mission->L);
mission->L = NULL;
}
}
// Does mission match faction requirement?
static int mission_matchFaction(MissionData* misn, int faction) {
int i;
for(i = 0; i < misn->avail.nfactions; i++) {
if(faction_isFaction(misn->avail.factions[i]) &&
(faction == misn->avail.factions[i]))
return 1;
else if(faction_ofAlliance(faction, misn->avail.factions[i]))
return 1;
}
return 0;
}
// Generate missions for the computer - special case.
Mission* missions_computer(int* n, int faction, char* planet, char* system) {
int i, m;
Mission* tmp;
MissionData* misn;
m = 0;
for(i = 0; i < mission_nstack; i++) {
misn = &mission_stack[i];
if((misn->avail.loc == MIS_AVAIL_COMPUTER) &&
(((misn->avail.planet && strcmp(misn->avail.planet, planet)==0)) ||
(misn->avail.system && (strcmp(misn->avail.system, system)==0)) ||
mission_matchFaction(misn, faction))) {
tmp = realloc(tmp, sizeof(Mission) * ++m);
mission_init(&tmp[m-1], misn);
}
}
(*n) = m;
return tmp;
}
// Return location based on string.
static int mission_location(char* loc) {
if(strcmp(loc, "None")==0) return MIS_AVAIL_NONE;
@ -126,7 +219,14 @@ static MissionData* mission_parse(const xmlNodePtr parent) {
tmp->lua = strdup(str);
str[0] = '\0';
}
else if(xml_isNode(node, "avail")) {
else if(xml_isNode(node, "flags")) { // Set the various flags.
cur = node->children;
do {
if(xml_isNode(cur, "unique"))
mis_setFlag(tmp, MISSION_UNIQUE);
} while((cur = cur->next));
}
else if(xml_isNode(node, "avail")) { // Mission availability.
cur = node->children;
do {
if(xml_isNode(cur, "location"))
@ -206,7 +306,7 @@ void missions_free(void) {
// Free the mission data.
for(i = 0; i < mission_nstack; i++)
mission_free(&mission_stack[i]);
mission_freeData(&mission_stack[i]);
free(mission_stack);
mission_stack = NULL;
mission_nstack = 0;

View File

@ -14,6 +14,8 @@
#define mis_setFlag(m,f) ((m)->flags |= (f))
#define mis_rmFlag(m,f) ((m)->flags ^= (f))
#define MISSION_UNIQUE 1 // Unique missions can't be repeated.
// Static mission data.
typedef struct MissionData_ {
char* name; // the name of the mission.
@ -53,6 +55,11 @@ typedef struct Mission_ {
#define MISSION_MAX 6 // No sense in the player having unlimited missions..
extern Mission player_mission[MISSION_MAX];
// For mission computer.
Mission* missions_computer(int* n, int faction, char* planet, char* system);
// Player accepted mission - mission computer.
void mission_accept(Mission* misn);
// Load/Quit.
int missions_load(void);
void missions_free(void);