1029 lines
23 KiB
C
1029 lines
23 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "lua.h"
|
|
#include "lauxlib.h"
|
|
|
|
#include "llua.h"
|
|
#include "llua_space.h"
|
|
#include "llua_pilot.h"
|
|
#include "llua_faction.h"
|
|
#include "lluadef.h"
|
|
#include "hook.h"
|
|
#include "mission.h"
|
|
#include "log.h"
|
|
#include "lephisto.h"
|
|
#include "rng.h"
|
|
#include "space.h"
|
|
#include "toolkit.h"
|
|
#include "land.h"
|
|
#include "pilot.h"
|
|
#include "player.h"
|
|
#include "ltime.h"
|
|
#include "xml.h"
|
|
#include "music.h"
|
|
#include "unidiff.h"
|
|
#include "misn_lua.h"
|
|
|
|
/* Similar to lua vars, but with less variety. */
|
|
#define MISN_VAR_NIL 0
|
|
#define MISN_VAR_NUM 1
|
|
#define MISN_VAR_BOOL 2
|
|
#define MISN_VAR_STR 3
|
|
typedef struct misn_var_ {
|
|
char* name;
|
|
char type;
|
|
union {
|
|
double num;
|
|
char* str;
|
|
int b;
|
|
} d;
|
|
} misn_var;
|
|
|
|
/* Variable stack. */
|
|
static misn_var* var_stack = NULL;
|
|
static int var_nstack = 0;
|
|
static int var_mstack = 0;
|
|
|
|
/* Current mission. */
|
|
static Mission* cur_mission = NULL;
|
|
static int misn_delete = 0; /* If 1 delete current mission. */
|
|
|
|
/* Static. */
|
|
static int var_add(misn_var* var);
|
|
static void var_free(misn_var* var);
|
|
static unsigned int hook_generic(lua_State* L, char* stack);
|
|
/* Extern. */
|
|
int misn_run(Mission* misn, char* func);
|
|
int var_save(xmlTextWriterPtr writer);
|
|
int var_load(xmlNodePtr parent);
|
|
/* External. */
|
|
extern void mission_sysMark(void);
|
|
|
|
/* -- Libraries. -- */
|
|
|
|
/* Mission. */
|
|
static int misn_setTitle(lua_State* L);
|
|
static int misn_setDesc(lua_State* L);
|
|
static int misn_setReward(lua_State* L);
|
|
static int misn_setMarker(lua_State* L);
|
|
static int misn_factions(lua_State* L);
|
|
static int misn_accept(lua_State* L);
|
|
static int misn_finish(lua_State* L);
|
|
static int misn_timerStart(lua_State* L);
|
|
static int misn_timerStop(lua_State* L);
|
|
static const luaL_reg misn_methods[] = {
|
|
{ "setTitle", misn_setTitle },
|
|
{ "setDesc", misn_setDesc },
|
|
{ "setReward", misn_setReward },
|
|
{ "setMarker", misn_setMarker },
|
|
{ "factions", misn_factions },
|
|
{ "accept", misn_accept },
|
|
{ "finish", misn_finish },
|
|
{ "timerStart", misn_timerStart },
|
|
{ "timerStop", misn_timerStop },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
/* Var. */
|
|
static int var_peek(lua_State* L);
|
|
static int var_pop(lua_State* L);
|
|
static int var_push(lua_State* L);
|
|
static const luaL_reg var_methods[] = {
|
|
{ "peek", var_peek },
|
|
{ "pop", var_pop},
|
|
{ "push", var_push},
|
|
{0, 0}
|
|
};
|
|
|
|
/* Only conditional. */
|
|
static const luaL_reg var_cond_methods[] = {
|
|
{ "peek", var_peek },
|
|
{0, 0 }
|
|
};
|
|
|
|
/* Player. */
|
|
static int player_getname(lua_State* L);
|
|
static int player_shipname(lua_State* L);
|
|
static int player_freeSpace(lua_State* L);
|
|
static int player_addCargo(lua_State* L);
|
|
static int player_rmCargo(lua_State* L);
|
|
static int player_pay(lua_State* L);
|
|
static int player_msg(lua_State* L);
|
|
static int player_modFaction(lua_State* L);
|
|
static int player_modFactionRaw(lua_State* L);
|
|
static int player_getFaction(lua_State* L);
|
|
static int player_getRating(lua_State* L);
|
|
static int player_getPosition(lua_State* L);
|
|
static int player_getPilot(lua_State* L);
|
|
static const luaL_reg player_methods[] = {
|
|
{ "name", player_getname },
|
|
{ "ship", player_shipname },
|
|
{ "freeCargo", player_freeSpace },
|
|
{ "addCargo", player_addCargo },
|
|
{ "rmCargo", player_rmCargo },
|
|
{ "pay", player_pay },
|
|
{ "msg", player_msg },
|
|
{ "modFaction", player_modFaction },
|
|
{ "modFactionRaw", player_modFactionRaw },
|
|
{ "getFaction", player_getFaction },
|
|
{ "getRating", player_getRating },
|
|
{ "pos", player_getPosition },
|
|
{ "pilot", player_getPilot },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
static const luaL_reg player_cond_methods[] = {
|
|
{ "name", player_getname },
|
|
{ "ship", player_shipname },
|
|
{ "getFaction", player_getFaction },
|
|
{ "getRating", player_getRating },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
/* Hooks. */
|
|
static int hook_land(lua_State* L);
|
|
static int hook_takeoff(lua_State* L);
|
|
static int hook_time(lua_State* L);
|
|
static int hook_enter(lua_State* L);
|
|
static int hook_pilot(lua_State* L);
|
|
static const luaL_reg hook_methods[] = {
|
|
{ "land", hook_land },
|
|
{ "takeoff", hook_takeoff },
|
|
{ "time", hook_time },
|
|
{ "enter", hook_enter },
|
|
{ "pilot", hook_pilot },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
/* Diffs. */
|
|
static int diff_applyL(lua_State* L);
|
|
static int diff_removeL(lua_State* L);
|
|
static int diff_isappliedL(lua_State* L);
|
|
static const luaL_reg diff_methods[] = {
|
|
{ "apply", diff_applyL },
|
|
{ "remove", diff_removeL },
|
|
{ "isApplied", diff_isappliedL },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
static const luaL_reg diff_cond_methods[] = {
|
|
{ "isApplied", diff_isappliedL },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
/* Register all the libaries. */
|
|
int misn_loadLibs(lua_State* L) {
|
|
lua_loadLephisto(L);
|
|
lua_loadMisn(L);
|
|
lua_loadVar(L, 0);
|
|
lua_loadSpace(L, 0);
|
|
lua_loadTime(L, 0);
|
|
lua_loadPlayer(L, 0);
|
|
lua_loadRnd(L);
|
|
lua_loadTk(L);
|
|
lua_loadHook(L);
|
|
lua_loadPilot(L, 0);
|
|
lua_loadMusic(L, 0);
|
|
lua_loadDiff(L, 0);
|
|
lua_loadFaction(L, 0);
|
|
return 0;
|
|
}
|
|
|
|
int misn_loadCondLibs(lua_State* L) {
|
|
lua_loadTime(L, 1);
|
|
lua_loadSpace(L, 1);
|
|
lua_loadVar(L, 1);
|
|
lua_loadPlayer(L, 1);
|
|
lua_loadDiff(L,1);
|
|
return 0;
|
|
}
|
|
|
|
/* Individual libarary loading. */
|
|
int lua_loadMisn(lua_State* L) {
|
|
luaL_register(L, "misn", misn_methods);
|
|
return 0;
|
|
}
|
|
|
|
int lua_loadVar(lua_State* L, int readonly) {
|
|
if(readonly == 0)
|
|
luaL_register(L, "var", var_methods);
|
|
else
|
|
luaL_register(L, "var", var_cond_methods);
|
|
return 0;
|
|
}
|
|
|
|
int lua_loadPlayer(lua_State* L, int readonly) {
|
|
if(readonly == 0)
|
|
luaL_register(L, "player", player_methods);
|
|
else
|
|
luaL_register(L, "player", player_cond_methods);
|
|
return 0;
|
|
}
|
|
|
|
int lua_loadHook(lua_State* L) {
|
|
luaL_register(L, "hook", hook_methods);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @fn int lua_loadDiff(lua_State* L, int readonly)
|
|
*
|
|
* @brief Loads the diff Lua library.
|
|
* @param L Lua State.
|
|
* @param readonly Load read only functions.
|
|
*/
|
|
int lua_loadDiff(lua_State* L, int readonly) {
|
|
if(readonly == 0)
|
|
luaL_register(L, "diff", diff_methods);
|
|
else
|
|
luaL_register(L, "diff", diff_cond_methods);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Run a mission function.
|
|
* -1 on error, 1 on misn.finish() call and 0 normally.
|
|
*/
|
|
int misn_run(Mission* misn, char* func) {
|
|
int i, ret;
|
|
char* err;
|
|
|
|
cur_mission = misn;
|
|
misn_delete = 0;
|
|
|
|
lua_getglobal(misn->L, func);
|
|
if((ret = lua_pcall(misn->L, 0, 0, 0))) {
|
|
/* Did an oops. */
|
|
err = (lua_isstring(misn->L, -1)) ? (char*) lua_tostring(misn->L, -1) : NULL;
|
|
if(strcmp(err, "Mission Done")!=0)
|
|
WARN("Mission '%s' -> '%s' : %s",
|
|
cur_mission->data->name, func, (err) ? err : "Unknown Error");
|
|
else ret = 1;
|
|
}
|
|
|
|
/* Mission is finished. */
|
|
if(misn_delete) {
|
|
mission_cleanup(cur_mission);
|
|
for(i = 0; i < MISSION_MAX; i++)
|
|
if(cur_mission == &player_missions[i]) {
|
|
memmove(&player_missions[i], &player_missions[i+1],
|
|
sizeof(Mission) * (MISSION_MAX-i-1));
|
|
break;
|
|
}
|
|
}
|
|
cur_mission = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Save the mission variables. */
|
|
int var_save(xmlTextWriterPtr writer) {
|
|
int i;
|
|
|
|
xmlw_startElem(writer, "vars");
|
|
|
|
for(i = 0; i < var_nstack; i++) {
|
|
xmlw_startElem(writer, "vars");
|
|
|
|
xmlw_attr(writer, "name", var_stack[i].name);
|
|
|
|
switch(var_stack[i].type) {
|
|
case MISN_VAR_NIL:
|
|
xmlw_attr(writer, "type", "nil");
|
|
break;
|
|
case MISN_VAR_NUM:
|
|
xmlw_attr(writer, "type", "num");
|
|
xmlw_str(writer, "%d", var_stack[i].d.num);
|
|
break;
|
|
case MISN_VAR_BOOL:
|
|
xmlw_attr(writer, "type", "bool");
|
|
xmlw_str(writer, "%d", var_stack[i].d.b);
|
|
break;
|
|
case MISN_VAR_STR:
|
|
xmlw_attr(writer, "type", "str");
|
|
xmlw_str(writer, var_stack[i].d.str);
|
|
break;
|
|
}
|
|
xmlw_endElem(writer); /* var. */
|
|
}
|
|
xmlw_endElem(writer); /* vars. */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Load the vars. */
|
|
int var_load(xmlNodePtr parent) {
|
|
char* str;
|
|
xmlNodePtr node, cur;
|
|
misn_var var;
|
|
|
|
var_cleanup();
|
|
|
|
node = parent->xmlChildrenNode;
|
|
|
|
do {
|
|
if(xml_isNode(node, "vars")) {
|
|
cur = node->xmlChildrenNode;
|
|
|
|
do {
|
|
if(xml_isNode(cur, "var")) {
|
|
xmlr_attr(cur, "name", var.name);
|
|
xmlr_attr(cur, "type", str);
|
|
if(strcmp(str, "nil")==0)
|
|
var.type = MISN_VAR_NIL;
|
|
else if(strcmp(str, "num")==0) {
|
|
var.type = MISN_VAR_NUM;
|
|
var.d.num = atoi(xml_get(cur));
|
|
}
|
|
else if(strcmp(str, "bool")==0) {
|
|
var.type = MISN_VAR_BOOL;
|
|
var.d.b = atoi(xml_get(cur));
|
|
}
|
|
else if(strcmp(str, "str")==0) {
|
|
var.type = MISN_VAR_STR;
|
|
var.d.str = atoi(xml_get(cur));
|
|
} else {
|
|
/* Supeh error checking. */
|
|
WARN("Unknown var type '%s'", str);
|
|
free(var.name);
|
|
continue;
|
|
}
|
|
free(str);
|
|
var_add(&var);
|
|
}
|
|
} while(xml_nextNode(cur));
|
|
}
|
|
} while(xml_nextNode(node));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add a var to the stack, strings will be SHARED, don't free!!! */
|
|
static int var_add(misn_var* new_var) {
|
|
int i;
|
|
|
|
if(var_nstack+1 > var_mstack) {
|
|
/* More memory. */
|
|
var_mstack += 64; /* Overkill much?? */
|
|
var_stack = realloc(var_stack, var_mstack * sizeof(misn_var));
|
|
}
|
|
|
|
/* Check if already exists. */
|
|
for(i = 0; i < var_nstack; i++)
|
|
if(strcmp(new_var->name, var_stack[i].name)==0) {
|
|
var_free(&var_stack[i]);
|
|
memcpy(&var_stack[i], new_var, sizeof(misn_var));
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&var_stack[var_nstack], new_var, sizeof(misn_var));
|
|
var_nstack++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* -- Mission. -- */
|
|
|
|
static int misn_setTitle(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
if(lua_isstring(L, 1)) {
|
|
if(cur_mission->title)
|
|
/* Cleanup the old title. */
|
|
free(cur_mission->title);
|
|
cur_mission->title = strdup((char*)lua_tostring(L, 1));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int misn_setDesc(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
if(lua_isstring(L, 1)) {
|
|
if(cur_mission->desc)
|
|
/* Cleanup the old description. */
|
|
free(cur_mission->desc);
|
|
cur_mission->desc = strdup((char*)lua_tostring(L, 1));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int misn_setReward(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
if(lua_isstring(L, 1)) {
|
|
if(cur_mission->reward != NULL) /* Cleanup old reward. */
|
|
/* Cleanup the old reward. */
|
|
free(cur_mission->reward);
|
|
cur_mission->reward = strdup((char*)lua_tostring(L, 1));
|
|
}
|
|
else LLUA_INVALID_PARAMETER();
|
|
return 0;
|
|
}
|
|
|
|
static int misn_setMarker(lua_State* L) {
|
|
LuaSystem* sys;
|
|
|
|
/* No parameter clears the marker. */
|
|
if(lua_gettop(L)==0) {
|
|
if(cur_mission->sys_marker != NULL)
|
|
free(cur_mission->sys_marker);
|
|
mission_sysMark(); /* Clear the marker. */
|
|
}
|
|
|
|
/* Passing in a Star System. */
|
|
if(lua_issystem(L, 1)) {
|
|
sys = lua_tosystem(L, 1);
|
|
cur_mission->sys_marker = strdup(sys->s->name);
|
|
mission_sysMark(); /* Mark the system. */
|
|
}
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int misn_factions(lua_State* L) {
|
|
int i;
|
|
MissionData* dat;
|
|
LuaFaction f;
|
|
|
|
dat = cur_mission->data;
|
|
|
|
/* We'll push all the factions in table form. */
|
|
lua_newtable(L);
|
|
for(i = 0; i < dat->avail.nfactions; i++) {
|
|
lua_pushnumber(L, i+1); /* Index, starts with 1. */
|
|
f.f = dat->avail.factions[i];
|
|
lua_pushfaction(L, f); /* Value. */
|
|
lua_rawset(L, -3); /* Store the value in the table. */
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int misn_accept(lua_State* L) {
|
|
int i, ret;
|
|
|
|
ret = 0;
|
|
|
|
/* Find the last mission. */
|
|
for(i = 0; i < MISSION_MAX; i++)
|
|
if(player_missions[i].data == NULL) break;
|
|
|
|
/* No missions left. */
|
|
if(i >= MISSION_MAX) ret = 1;
|
|
else {
|
|
memcpy(&player_missions[i], cur_mission, sizeof(Mission));
|
|
memset(cur_mission, 0, sizeof(Mission));
|
|
cur_mission = &player_missions[i];
|
|
}
|
|
lua_pushboolean(L, !ret); /* We'll convert C style return to lua. */
|
|
return 1;
|
|
}
|
|
|
|
static int misn_finish(lua_State* L) {
|
|
int b;
|
|
|
|
if(lua_isboolean(L, 1)) b = lua_toboolean(L, 1);
|
|
else {
|
|
lua_pushstring(L, "Mission Done");
|
|
lua_error(L); /* THERE IS NO RETURN! */
|
|
return 0;
|
|
}
|
|
|
|
misn_delete = 1;
|
|
|
|
if(b && mis_isFlag(cur_mission->data, MISSION_UNIQUE))
|
|
player_missionFinished(mission_getID(cur_mission->data->name));
|
|
|
|
lua_pushstring(L, "Mission Done");
|
|
lua_error(L); /* Should not return.. */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @fn static int misn_timerStart(lua_State* L)
|
|
*
|
|
* @brief number timerStart( string func, number delay )
|
|
*
|
|
* Start a timer.
|
|
* @param func Function to run when timer is up.
|
|
* @param delay Milliseconds to wait for timer.
|
|
* @return The timer being used.
|
|
*/
|
|
static int misn_timerStart(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
int i;
|
|
char* func;
|
|
double delay;
|
|
|
|
/* Parse arguments. */
|
|
if(lua_isstring(L,1))
|
|
func = (char*)lua_tostring(L,1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
if(lua_isnumber(L,2))
|
|
delay = lua_tonumber(L,2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Add timer. */
|
|
for(i = 0; i < MISSION_TIMER_MAX; i++) {
|
|
if(cur_mission->timer[i] == 0.) {
|
|
cur_mission->timer[i] = delay / 1000.;
|
|
cur_mission->tfunc[i] = strdup(func);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* No timer found. */
|
|
if(i >= MISSION_TIMER_MAX) {
|
|
return 0;
|
|
}
|
|
|
|
/* Return the timer id. */
|
|
lua_pushnumber(L, i);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @fn static int misn_timerStop(lua_State* L)
|
|
*
|
|
* @brief timerStop(number t)
|
|
*
|
|
* Stop a timer previously started with timerStart().
|
|
* @param t Timer to stop.
|
|
*/
|
|
static int misn_timerStop(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
int t;
|
|
|
|
/* Parse arguments. */
|
|
if(lua_isnumber(L,1))
|
|
t = (int)lua_tonumber(L,1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Stop the timer. */
|
|
if(cur_mission->timer[t] != 0.) {
|
|
cur_mission->timer[t] = 0.;
|
|
if(cur_mission->tfunc[t] != NULL) {
|
|
free(cur_mission->tfunc[t]);
|
|
cur_mission->tfunc[t] = NULL;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* -- Var. -- */
|
|
|
|
/* Check if a variable exists. */
|
|
int var_checkflag(char* str) {
|
|
int i;
|
|
for(i = 0; i < var_nstack; i++)
|
|
if(strcmp(var_stack[i].name, str)==0)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
static int var_peek(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
int i;
|
|
char* str;
|
|
|
|
if(lua_isstring(L, 1)) str = (char*) lua_tostring(L, 1);
|
|
else {
|
|
LLUA_DEBUG("Trying to peek a var with non-string name");
|
|
return 0;
|
|
}
|
|
|
|
for(i = 0; i < var_nstack; i++)
|
|
if(strcmp(str, var_stack[i].name)==0) {
|
|
switch(var_stack[i].type) {
|
|
case MISN_VAR_NIL:
|
|
lua_pushnil(L);
|
|
break;
|
|
case MISN_VAR_NUM:
|
|
lua_pushnumber(L, var_stack[i].d.num);
|
|
break;
|
|
case MISN_VAR_BOOL:
|
|
lua_pushboolean(L, var_stack[i].d.b);
|
|
break;
|
|
case MISN_VAR_STR:
|
|
lua_pushstring(L, var_stack[i].d.str);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
lua_pushnil(L);
|
|
return 1;
|
|
}
|
|
|
|
static int var_pop(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
int i;
|
|
char* str;
|
|
|
|
if(lua_isstring(L, 1)) str = (char*) lua_tostring(L, 1);
|
|
else {
|
|
LLUA_DEBUG("Trying to pop a var with non-string name");
|
|
return 0;
|
|
}
|
|
|
|
for(i = 0; i < var_nstack; i++)
|
|
if(strcmp(str, var_stack[i].name)==0) {
|
|
var_free(&var_stack[i]);
|
|
memmove(&var_stack[i], &var_stack[i+1], sizeof(misn_var)*(var_nstack-i-1));
|
|
var_stack--;
|
|
return 0;
|
|
}
|
|
LLUA_DEBUG("Var '%s' not found in stack", str);
|
|
return 0;
|
|
}
|
|
|
|
static int var_push(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
char* str;
|
|
misn_var var;
|
|
|
|
if(lua_isstring(L, 1)) str = (char*) lua_tostring(L, 1);
|
|
else {
|
|
LLUA_DEBUG("Trying to push a var with non-string name");
|
|
return 0;
|
|
}
|
|
|
|
var.name = strdup(str);
|
|
|
|
/* Store appropriate data. */
|
|
if(lua_isnil(L, 2))
|
|
var.type = MISN_VAR_NIL;
|
|
else if(lua_isnumber(L, 2)) {
|
|
var.type = MISN_VAR_NUM;
|
|
var.d.num = (double)lua_tonumber(L, 2);
|
|
}
|
|
else if(lua_isboolean(L, 2)) {
|
|
var.type = MISN_VAR_BOOL;
|
|
var.d.b = lua_toboolean(L, 2);
|
|
}
|
|
else if(lua_isstring(L, 2)) {
|
|
var.type = MISN_VAR_STR;
|
|
var.d.str = strdup((char*)lua_tostring(L, 2));
|
|
} else {
|
|
LLUA_DEBUG("Trying to push a var of invalid data type to stack");
|
|
return 0;
|
|
}
|
|
|
|
var_add(&var);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void var_free(misn_var* var) {
|
|
switch(var->type) {
|
|
case MISN_VAR_STR:
|
|
if(var->d.str != NULL) {
|
|
free(var->d.str);
|
|
var->d.str = NULL;
|
|
}
|
|
break;
|
|
case MISN_VAR_NIL:
|
|
case MISN_VAR_NUM:
|
|
case MISN_VAR_BOOL:
|
|
break;
|
|
}
|
|
if(var->name != NULL) {
|
|
free(var->name);
|
|
var->name = NULL;
|
|
}
|
|
}
|
|
|
|
void var_cleanup(void) {
|
|
int i;
|
|
for(i = 0; i < var_nstack; i++)
|
|
var_free(&var_stack[i]);
|
|
|
|
if(var_stack != NULL) free(var_stack);
|
|
var_stack = NULL;
|
|
var_nstack = 0;
|
|
var_mstack = 0;
|
|
}
|
|
|
|
/* -- Player. -- */
|
|
|
|
static int player_getname(lua_State* L) {
|
|
lua_pushstring(L, player_name);
|
|
return 1;
|
|
}
|
|
|
|
static int player_shipname(lua_State* L) {
|
|
lua_pushstring(L, player->name);
|
|
return 1;
|
|
}
|
|
|
|
static int player_freeSpace(lua_State* L) {
|
|
lua_pushnumber(L, pilot_cargoFree(player));
|
|
return 1;
|
|
}
|
|
|
|
static int player_addCargo(lua_State* L) {
|
|
Commodity* cargo;
|
|
int quantity, ret;
|
|
|
|
LLUA_MIN_ARGS(2);
|
|
|
|
if(lua_isstring(L, 2)) cargo = commodity_get((char*) lua_tostring(L, 1));
|
|
else LLUA_INVALID_PARAMETER();
|
|
if(lua_isnumber(L, 2)) quantity = (int)lua_tonumber(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
ret = pilot_addMissionCargo(player, cargo, quantity);
|
|
mission_linkCargo(cur_mission, ret);
|
|
|
|
lua_pushnumber(L, ret);
|
|
return 1;
|
|
}
|
|
|
|
static int player_rmCargo(lua_State* L) {
|
|
int ret;
|
|
unsigned int id;
|
|
|
|
LLUA_MIN_ARGS(1);
|
|
|
|
if(lua_isnumber(L, 1)) id = (unsigned int) lua_tonumber(L, 1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
ret = pilot_rmMissionCargo(player, id);
|
|
mission_unlinkCargo(cur_mission, id);
|
|
|
|
lua_pushboolean(L, !ret);
|
|
return 1;
|
|
}
|
|
|
|
static int player_pay(lua_State* L) {
|
|
int money;
|
|
|
|
LLUA_MIN_ARGS(1);
|
|
|
|
if(lua_isnumber(L, 1)) money = (int) lua_tonumber(L, 1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
player->credits += money;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int player_msg(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
char* str;
|
|
|
|
if(lua_isstring(L, -1)) str = (char*) lua_tostring(L, -1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
player_message(str);
|
|
return 0;
|
|
}
|
|
|
|
static int player_modFaction(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
int f;
|
|
double mod;
|
|
|
|
if(lua_isstring(L, 1)) f = faction_get(lua_tostring(L, 1));
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
if(lua_isnumber(L, 2)) mod = lua_tonumber(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
faction_modPlayer(f, mod);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int player_modFactionRaw(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
int f;
|
|
double mod;
|
|
|
|
if(lua_isstring(L, 1)) f = faction_get(lua_tostring(L,1));
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
if(lua_isnumber(L,2)) mod = lua_tonumber(L,2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
faction_modPlayerRaw(f, mod);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int player_getFaction(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
int f;
|
|
|
|
if(lua_isstring(L, 1)) f = faction_get(lua_tostring(L, 1));
|
|
else LLUA_INVALID_PARAMETER();
|
|
lua_pushnumber(L, faction_getPlayer(f));
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int player_getRating(lua_State* L) {
|
|
lua_pushnumber(L, player_crating);
|
|
lua_pushstring(L, player_rating());
|
|
return 2;
|
|
}
|
|
|
|
/* -- HOOK -- */
|
|
static unsigned int hook_generic(lua_State* L, char* stack) {
|
|
int i;
|
|
char* func;
|
|
|
|
LLUA_MIN_ARGS(1);
|
|
|
|
/* Last parameter must be function to hook. */
|
|
if(lua_isstring(L, -1)) func = (char*)lua_tostring(L, -1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Make sure mission is a player mission. */
|
|
for(i = 0; i < MISSION_MAX; i++)
|
|
if(player_missions[i].id == cur_mission->id)
|
|
break;
|
|
if(i >= MISSION_MAX) {
|
|
WARN("Mission not in stack trying to hook");
|
|
return 0;
|
|
}
|
|
|
|
return hook_add(cur_mission->id, func, stack);
|
|
}
|
|
|
|
static int hook_land(lua_State* L) {
|
|
hook_generic(L, "land");
|
|
return 0;
|
|
}
|
|
|
|
static int hook_takeoff(lua_State* L) {
|
|
hook_generic(L, "takeoff");
|
|
return 0;
|
|
}
|
|
|
|
static int hook_time(lua_State* L) {
|
|
hook_generic(L, "time");
|
|
return 0;
|
|
}
|
|
|
|
static int hook_enter(lua_State* L) {
|
|
hook_generic(L, "enter");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @fn static int player_getPosition(lua_State* L)
|
|
*
|
|
* @brief Vec2 getPos(nil)
|
|
*
|
|
* Get the players position.
|
|
* @return The position of the player.
|
|
*/
|
|
static int player_getPosition(lua_State* L) {
|
|
LuaVector v;
|
|
|
|
vectcpy(&v.vec, &player->solid->pos);
|
|
lua_pushvector(L, v);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @fn static int player_getPilot(lua_State* L)
|
|
*
|
|
* @brief Pilot getPilot(nil)
|
|
*
|
|
* Get the players associated pilot.
|
|
* @return The players pilot.
|
|
*/
|
|
static int player_getPilot(lua_State* L) {
|
|
LuaPilot lp;
|
|
lp.pilot = PLAYER_ID;
|
|
lua_pushpilot(L, lp);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @fn static int hook_pilot(lua_State* L)
|
|
* @ingroup HOOK
|
|
*
|
|
* @brief number pilot(Pilot pilot, string type, string func)
|
|
*
|
|
* Hooks the function to a specific pilot.
|
|
*
|
|
* You can hook to different actions. At the moment hook system only supports:
|
|
* -- "death" : Triggered when pilot dies.
|
|
* -- "board" : Triggered when pilot is boarded.
|
|
* -- "disable" : Triggered when pilot is disabled.
|
|
* -- "jump" : Triggered when pilot jumps to hyperspace.
|
|
*
|
|
* @param pilot Pilot identifier to hook.
|
|
* @param typer One of the supported hook types.
|
|
* @param func Function to run when hook is triggered.
|
|
* @return Hook identifier.
|
|
*/
|
|
static int hook_pilot(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
unsigned int h;
|
|
LuaPilot* p;
|
|
int type;
|
|
char* hook_type;
|
|
|
|
/* First parameter - pilot to hook. */
|
|
if(lua_ispilot(L, 1)) p = lua_topilot(L, 1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Second parameer - Hook name. */
|
|
if(lua_isstring(L, 2)) hook_type = (char*) lua_tostring(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Check to see if hook_type is valid. */
|
|
if(strcmp(hook_type, "death")==0) type = PILOT_HOOK_DEATH;
|
|
else if(strcmp(hook_type, "board")==0) type = PILOT_HOOK_BOARD;
|
|
else if(strcmp(hook_type, "disable")==0) type = PILOT_HOOK_DISABLE;
|
|
else if(strcmp(hook_type, "jump")==0) type = PILOT_HOOK_JUMP;
|
|
else { /* Hook type not valid. */
|
|
LLUA_DEBUG("Invalid pilot hook type: '%s'", hook_type);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Actually add the hook. */
|
|
h = hook_generic(L, hook_type);
|
|
pilot_addHook(pilot_get(p->pilot), type, h);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @defgroup DIFF Universe Diff Lua Bindings.
|
|
*
|
|
* @brief Lua bindings to apply/remove Universe Diffs.
|
|
*
|
|
* Functions should be called like:
|
|
*
|
|
* @code
|
|
* diff.function(parameters)
|
|
* @endcode
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @fn static int diff_applyL(lua_State* L)
|
|
*
|
|
* @brief apply(string name)
|
|
*
|
|
* Applies a diff by name.
|
|
* @param name Name of the diff to apply.
|
|
*/
|
|
static int diff_applyL(lua_State* L) {
|
|
char* name;
|
|
|
|
if(lua_isstring(L, 1)) name = (char*)lua_tostring(L, 1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
diff_apply(name);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @fn static int diff_removeL(lua_State* L)
|
|
*
|
|
* @brief remove(string name)
|
|
*
|
|
* Removes a diff by name.
|
|
* @param name Name of the diff to remove.
|
|
*/
|
|
static int diff_removeL(lua_State* L) {
|
|
char* name;
|
|
|
|
if(lua_isstring(L, 1)) name = (char*)lua_tostring(L, 1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
diff_remove(name);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @fn static int diff_isappliedL(lua_State* L)
|
|
*
|
|
* @brief bool isApplied(string name)
|
|
*
|
|
* Check to see if a diff is currently applied.
|
|
* @param name Name of the diff to check.
|
|
* @return true if it is applied, false if it isn't.
|
|
*/
|
|
static int diff_isappliedL(lua_State* L) {
|
|
char* name;
|
|
if(lua_isstring(L, 1)) name = (char*)lua_tostring(L, 1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
lua_pushboolean(L, diff_isApplied(name));
|
|
return 1;
|
|
}
|
|
/**
|
|
* @}
|
|
*/
|
|
|