diff --git a/dat/missions/cargo.lua b/dat/missions/cargo.lua index 2d669b0..ea9ba8a 100644 --- a/dat/missions/cargo.lua +++ b/dat/missions/cargo.lua @@ -1,3 +1,4 @@ +-- Create the mission. function create() -- Target destination. planet = space.getPlanet(misn.factions()) @@ -11,7 +12,26 @@ function create() carg.type = rnd.setDesc(string.format( "%s needs a rush delivery of %d tons of %s by %s.", planet, carg_mass, carg_type, "SOMEDAY")) - misn_setReward(string.format("%d Scred", - carg_mass * 1000 + rnd.int(0, 5000))) + misn_reward = carg_mass * 1000 + rnd.int(0, 5000) + misn.setReward(string.format("%d Scred" misn_reward)) + + -- Set the hooks. + hook.land("land") +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." + carg_mass, carg_type)) +end + +function land() + if planet.name() == planet then + player.rmCargo(carg_type, carg_mass) + player.pay(misn_reward) + toolkit.msg("Mission Accomplished", + string.format("The workers unload the %s at the docks.", carg_type)) + end end diff --git a/src/hook.c b/src/hook.c new file mode 100644 index 0000000..0d94a83 --- /dev/null +++ b/src/hook.c @@ -0,0 +1,106 @@ +#include +#include + +#include "log.h" +#include "lephisto.h" +#include "hook.h" + +// The hook. +typedef struct Hook_ { + int id; + lua_State* L; + char* parent; + char* func; + char* stack; +} Hook; + +// The stack. +static int hook_id = 0; // Unique hook id. +static Hook* hook_stack = NULL; +static int hook_mstack = 0; +static int hook_nstack = 0; + +int hook_run(Hook* hook) { + lua_State* L; + + L = hook->L; + + lua_getglobal(L, hook->func); + if(lua_pcall(L, 0, 0, 0)) + // Error has accured. + WARN("Hook [%s] '%s' -> '%s' : %s", hook->stack, + hook->parent, hook->func, lua_tostring(L, -1)); + + return 0; +} + +// Add/Remove hooks. +int hook_add(lua_State* L, char* parent, char* func, char* stack) { + Hook* new_hook; + + // If the memory must grow. + if(hook_nstack+1 > hook_mstack) { + hook_stack = realloc(hook_stack, (hook_mstack+5)*sizeof(Hook)); + hook_mstack += 5; + } + + // Create the new hook. + new_hook = &hook_stack[hook_nstack]; + new_hook->id = ++hook_id; + new_hook->L = L; + new_hook->parent = parent; + new_hook->func = func; + new_hook->stack = stack; + + hook_nstack++; + + return new_hook->id; +} + +void hook_rm(int id) { + int l, m, h; + l = 0; + h = hook_nstack-1; + + while(l <= h) { + m = (l+h)/2; + if(hook_stack[m].id > id) h = m-1; + else if(hook_stack[m].id < id) l = m+1; + else break; + } + + if(m == (hook_nstack-1)) return; + + // Move it! + memmove(&hook_stack[m+1], &hook_stack[m+2], hook_nstack-(m+1)); + hook_nstack--; +} + +void hook_rmParent(char* parent) { + int i; + for(i = 0; i < hook_nstack; i++) + if(strcmp(parent, hook_stack[i].parent) == 0) { + hook_rm(hook_stack[i].id); + i--; + } +} + +// Run all hooks off the stack. +int hooks_run(char* stack) { + int i; + for(i = 0; i < hook_nstack; i++) + if(strcmp(stack, hook_stack[i].stack)==0) + hook_run(&hook_stack[i]); + + return 0; +} + +// Clean upi after ourselves. +void hook_cleanup(void) { + free(hook_stack); + hook_stack = NULL; + // Sane defaults just in case. + hook_nstack = 0; + hook_mstack = 0; +} + diff --git a/src/hook.h b/src/hook.h new file mode 100644 index 0000000..18385c0 --- /dev/null +++ b/src/hook.h @@ -0,0 +1,14 @@ +#pragma once +#include "lua.h" + +// Add/Run hooks. +int hook_add(lua_State* L, char* parent, char* func, char* stack); +void hook_rm(int id); +void hook_rmParent(char* parent); + +// Run hook. +int hooks_run(char* stack); + +// Destroy hook. +void hook_cleanup(void); + diff --git a/src/misn_lua.c b/src/misn_lua.c index 98ab2a2..a1f5ece 100644 --- a/src/misn_lua.c +++ b/src/misn_lua.c @@ -1,6 +1,7 @@ #include "lua.h" #include "lauxlib.h" +#include "hook.h" #include "mission.h" #include "log.h" #include "lephisto.h" @@ -42,11 +43,18 @@ static const luaL_Reg rnd_methods[] = { { 0, 0 } }; +static int hook_land(lua_State* L); +static const luaL_Reg hook_methods[] = { + { "land", hook_land }, + { 0, 0 }, +}; + // Register all the libaries. int misn_loadLibs(lua_State* L) { luaL_register(L, "misn", misn_methods); luaL_register(L, "space", space_methods); luaL_register(L, "rnd", rnd_methods); + luaL_register(L, "hook", hook_methods); return 0; } @@ -131,3 +139,19 @@ static rnd_int(lua_State* L) { return 1; } +// -- HOOK -- +static int hook_land(lua_State* L) { + char* parent, *func; + + MIN_ARGS(1); + + parent = cur_mission->data->name; + if(lua_isstring(L, -1)) func = (char*)lua_tostring(L, -1); + else { + WARN("Mission %s: trying to push non-valid function hook", parent); + return 0; + } + hook_add(L, parent, func, "land"); + return 0; +} +