Added modtools/reaction-product-trigger.

develop
expwnent 2015-02-02 02:25:42 -05:00
parent 712892fb71
commit e5e0d93ef1
5 changed files with 170 additions and 14 deletions

@ -500,3 +500,19 @@ namespace DFHack {namespace Lua {
name##_event.invoke(out, 6); \ name##_event.invoke(out, 6); \
} \ } \
} }
#define DEFINE_LUA_EVENT_7(name, handler, arg_type1, arg_type2, arg_type3, arg_type4, arg_type5,arg_type6,arg_type7) \
static DFHack::Lua::Notification name##_event(df::wrap_function(handler, true)); \
void name(color_ostream &out, arg_type1 arg1, arg_type2 arg2, arg_type3 arg3, arg_type4 arg4,arg_type5 arg5, arg_type6 arg6, arg_type7 arg7) { \
handler(out, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
if (auto state = name##_event.state_if_count()) { \
DFHack::Lua::Push(state, arg1); \
DFHack::Lua::Push(state, arg2); \
DFHack::Lua::Push(state, arg3); \
DFHack::Lua::Push(state, arg4); \
DFHack::Lua::Push(state, arg5); \
DFHack::Lua::Push(state, arg6); \
DFHack::Lua::Push(state, arg7); \
name##_event.invoke(out, 7); \
} \
}

@ -94,7 +94,7 @@ static bool is_lua_hook(const std::string &name)
static void handle_fillsidebar(color_ostream &out,df::building_workshopst*,bool *call_native){}; static void handle_fillsidebar(color_ostream &out,df::building_workshopst*,bool *call_native){};
static void handle_postfillsidebar(color_ostream &out,df::building_workshopst*){}; static void handle_postfillsidebar(color_ostream &out,df::building_workshopst*){};
static void handle_reaction_done(color_ostream &out,df::reaction*, df::unit *unit, std::vector<df::item*> *in_items,std::vector<df::reaction_reagent*> *in_reag static void handle_reaction_done(color_ostream &out,df::reaction*, df::reaction_product_itemst*, df::unit *unit, std::vector<df::item*> *in_items,std::vector<df::reaction_reagent*> *in_reag
, std::vector<df::item*> *out_items,bool *call_native){}; , std::vector<df::item*> *out_items,bool *call_native){};
static void handle_contaminate_wound(color_ostream &out,df::item_actual*,df::unit* unit, df::unit_wound* wound, uint8_t a1, int16_t a2){}; static void handle_contaminate_wound(color_ostream &out,df::item_actual*,df::unit* unit, df::unit_wound* wound, uint8_t a1, int16_t a2){};
static void handle_projitem_ci(color_ostream &out,df::proj_itemst*,bool){}; static void handle_projitem_ci(color_ostream &out,df::proj_itemst*,bool){};
@ -105,7 +105,7 @@ static void handle_projunit_cm(color_ostream &out,df::proj_unitst*){};
DEFINE_LUA_EVENT_2(onWorkshopFillSidebarMenu, handle_fillsidebar, df::building_workshopst*,bool* ); DEFINE_LUA_EVENT_2(onWorkshopFillSidebarMenu, handle_fillsidebar, df::building_workshopst*,bool* );
DEFINE_LUA_EVENT_1(postWorkshopFillSidebarMenu, handle_postfillsidebar, df::building_workshopst*); DEFINE_LUA_EVENT_1(postWorkshopFillSidebarMenu, handle_postfillsidebar, df::building_workshopst*);
DEFINE_LUA_EVENT_6(onReactionComplete, handle_reaction_done,df::reaction*, df::unit *, std::vector<df::item*> *,std::vector<df::reaction_reagent*> *,std::vector<df::item*> *,bool *); DEFINE_LUA_EVENT_7(onReactionComplete, handle_reaction_done,df::reaction*, df::reaction_product_itemst*, df::unit *, std::vector<df::item*> *,std::vector<df::reaction_reagent*> *,std::vector<df::item*> *,bool *);
DEFINE_LUA_EVENT_5(onItemContaminateWound, handle_contaminate_wound, df::item_actual*,df::unit* , df::unit_wound* , uint8_t , int16_t ); DEFINE_LUA_EVENT_5(onItemContaminateWound, handle_contaminate_wound, df::item_actual*,df::unit* , df::unit_wound* , uint8_t , int16_t );
//projectiles //projectiles
DEFINE_LUA_EVENT_2(onProjItemCheckImpact, handle_projitem_ci, df::proj_itemst*,bool ); DEFINE_LUA_EVENT_2(onProjItemCheckImpact, handle_projitem_ci, df::proj_itemst*,bool );
@ -298,18 +298,25 @@ struct product_hook : item_product {
int32_t quantity, df::job_skill skill, int32_t quantity, df::job_skill skill,
df::historical_entity *entity, df::world_site *site) df::historical_entity *entity, df::world_site *site)
) { ) {
if (auto product = products[this]) color_ostream_proxy out(Core::getInstance().getConsole());
{ auto product = products[this];
df::reaction* this_reaction=product->react; if ( !product ) {
CoreSuspendClaimer suspend; INTERPOSE_NEXT(produce)(unit, out_items, in_reag, in_items, quantity, skill, entity, site);
color_ostream_proxy out(Core::getInstance().getConsole()); return;
bool call_native=true;
onReactionComplete(out,this_reaction,unit,in_items,in_reag,out_items,&call_native);
if(!call_native)
return;
} }
df::reaction* this_reaction=product->react;
CoreSuspendClaimer suspend;
bool call_native=true;
onReactionComplete(out,this_reaction,(df::reaction_product_itemst*)this,unit,in_items,in_reag,out_items,&call_native);
if(!call_native)
return;
size_t out_item_count = out_items->size();
INTERPOSE_NEXT(produce)(unit, out_items, in_reag, in_items, quantity, skill, entity, site); INTERPOSE_NEXT(produce)(unit, out_items, in_reag, in_items, quantity, skill, entity, site);
if ( out_items->size() == out_item_count )
return;
//if it produced something, call the scripts
onReactionComplete(out,this_reaction,(df::reaction_product_itemst*)this,unit,in_items,in_reag,out_items,NULL);
} }
}; };

@ -44,9 +44,9 @@ local function unregall(state)
_registeredStuff={} _registeredStuff={}
end end
end end
local function onReact(reaction,unit,input_items,input_reagents,output_items,call_native) local function onReact(reaction,reaction_product,unit,input_items,input_reagents,output_items,call_native)
if _registeredStuff.reactionCallbacks and _registeredStuff.reactionCallbacks[reaction.code] then if _registeredStuff.reactionCallbacks and _registeredStuff.reactionCallbacks[reaction.code] then
_registeredStuff.reactionCallbacks[reaction.code](reaction,unit,input_items,input_reagents,output_items,call_native) _registeredStuff.reactionCallbacks[reaction.code](reaction,reaction_product,unit,input_items,input_reagents,output_items,call_native)
end end
end end
local function onPostSidebar(workshop) local function onPostSidebar(workshop)

@ -0,0 +1,129 @@
-- scripts/modtools/reaction-product-trigger.lua
-- author expwnent
-- trigger commands just before and after custom reactions produce items
local eventful = require 'plugins.eventful'
local utils = require 'utils'
--TODO: onUnload
productHooks = productHooks or {}
reactionInputItems = reactionInputItems
eventful.enableEvent(eventful.eventType.UNLOAD,1)
eventful.onUnload.reactionProductTrigger = function()
productHooks = {}
end
--productHooks.before = productHooks.before or {}
--productHooks.after = productHooks.after or {}
local function processArgs(args, reaction, reaction_product, unit, input_items, input_reagents, output_items, buildingId)
local result = {}
for _,arg in ipairs(args) do
if arg == '\\WORKER_ID' then
table.insert(result,tostring(unit.id))
elseif arg == '\\REACTION' then
table.insert(result,reaction.code)
-- elseif arg == '\\REACTION_PRODUCT' then
-- table.insert(result,reaction_product)
elseif arg == '\\INPUT_ITEMS' then
--table.insert(result,'[')
for _,item in ipairs(input_items) do
table.insert(result,tostring(item.id))
end
--table.insert(result,']')
elseif arg == '\\OUTPUT_ITEMS' then
--table.insert(result,'[')
for _,item in ipairs(output_items) do
table.insert(result,tostring(item.id))
end
--table.insert(result,']')
elseif arg == '\\BUILDING_ID' then
table.insert(result,tostring(buildingId))
elseif string.sub(arg,1,1) == '\\' then
table.insert(result,string.sub(arg,2))
else
table.insert(result,arg)
end
end
return result
end
local function afterProduce(reaction,reaction_product,unit,input_items,input_reagents,output_items)
--printall(unit.job.current_job)
local _,buildingId = dfhack.script_environment('modtools/reaction-trigger').getWorkerAndBuilding(unit.job.current_job)
for _,hook in ipairs(productHooks[reaction.code] or {}) do
local command = hook.command
local processed = processArgs(command, reaction, reaction_product, unit, input_items, input_reagents, output_items, buildingId)
dfhack.run_command(table.unpack(processed))
end
end
eventful.onReactionComplete.reactionProductTrigger = function(reaction,reaction_product,unit,input_items,input_reagents,output_items,call_native)
reactionInputItems = input_items
--print(reaction.code)
--print(#output_items)
--print('call_native exists? ' .. tostring(not not call_native))
--print('\n')
if call_native then
--beforeProduce(reaction,unit,input_items,input_reagents,output_items,call_native)
else
afterProduce(reaction,reaction_product,unit,input_items,input_reagents,output_items)
end
reactionInputItems = nil
end
validArgs = validArgs or utils.invert({
'help',
'clear',
'reactionName',
'command',
})
if moduleMode then
return
end
local args = {...} or {}
args = utils.processArgs(args, validArgs)
if args.help then
print([[scripts/modtools/reaction-product-trigger.lua
arguments:
-help
print this help message
-clear
unregister all reaction hooks
-reactionName name
specify the name of the reaction
-command [ commandStrs ]
specify the command to be run on the target(s)
special args
\\WORKER_ID
\\REACTION
\\BUILDING_ID
\\LOCATION
\\INPUT_ITEMS
\\OUTPUT_ITEMS
\\anything -> \anything
anything -> anything
]])
return
end
if args.clear then
productHooks = {}
end
if not args.reactionName then
error('No reactionName.')
end
if not args.command then
error('No command.')
end
productHooks[args.reactionName] = productHooks[args.reactionName] or {}
table.insert(productHooks[args.reactionName], args)

@ -13,7 +13,7 @@ eventful.onUnload.reactionTrigger = function()
reactionHooks = {} reactionHooks = {}
end end
local function getWorkerAndBuilding(job) function getWorkerAndBuilding(job)
local workerId = -1 local workerId = -1
local buildingId = -1 local buildingId = -1
for _,generalRef in ipairs(job.general_refs) do for _,generalRef in ipairs(job.general_refs) do
@ -157,6 +157,10 @@ validArgs = validArgs or utils.invert({
'allowNonworkerTargets', 'allowNonworkerTargets',
'allowMultipleTargets' 'allowMultipleTargets'
}) })
if moduleMode then
return
end
local args = utils.processArgs({...}, validArgs) local args = utils.processArgs({...}, validArgs)
if args.help then if args.help then