diff --git a/Lua API.rst b/Lua API.rst index 8906d1d44..7315f63a0 100644 --- a/Lua API.rst +++ b/Lua API.rst @@ -2965,6 +2965,10 @@ List of events 1. onReactionComplete(reaction,unit,input_items,input_reagents,output_items,call_native) - auto activates if detects reactions starting with ``LUA_HOOK_``. Is called when reaction finishes. 2. onItemContaminateWound(item,unit,wound,number1,number2) - Is called when item tries to contaminate wound (e.g. stuck in) +3. onProjItemCheckMovement(projectile) - is called when projectile moves +4. onProjItemCheckImpact(projectile,somebool) - is called when projectile hits something +5. onProjUnitCheckMovement(projectile) - is called when projectile moves +6. onProjUnitCheckImpact(projectile,somebool) - is called when projectile hits something Examples -------- @@ -2976,15 +2980,23 @@ Spawn dragon breath on each item attempt to contaminate wound: local flw=dfhack.maps.spawnFlow(unit.pos,6,0,0,50000) end -Reaction complete example" +Reaction complete example: :: - + b=require "plugins.eventful" b.onReactionComplete.one=function(reaction,unit,in_items,in_reag,out_items,call_native) local pos=copyall(unit.pos) dfhack.timeout(100,"ticks",function() dfhack.maps.spawnFlow(pos,6,0,0,50000) end) -- spawn dragonbreath after 100 ticks call_native.value=false --do not call real item creation code end +Granade example: +:: + b=require "plugins.eventful" + b.onProjItemCheckImpact.one=function(projectile) + -- you can check if projectile.item e.g. has correct material + dfhack.maps.spawnFlow(projectile.cur_pos,6,0,0,50000) + end + ======= Scripts ======= diff --git a/Readme.rst b/Readme.rst index 7fb3a5565..60fd1b78f 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2608,33 +2608,3 @@ be bought from caravans. :) To be really useful this needs patches from bug 808, ``tweak fix-dimensions`` and ``tweak advmode-contained``. -Eventful -======== - -This plugin exports some events to lua thus allowing to run lua functions -on DF world events. - -List of events --------------- - -1. onReactionComplete(reaction,unit,input_items,input_reagents,output_items,call_native) - auto activates if detects reactions starting with ``LUA_HOOK_``. Is called when reaction finishes. -2. onItemContaminateWound(item,unit,wound,number1,number2) - Is called when item tries to contaminate wound (e.g. stuck in) - -Examples --------- -Spawn dragon breath on each item attempt to contaminate wound: -:: - - b=require "plugins.eventful" - b.onItemContaminateWound.one=function(item,unit,un_wound,x,y) - local flw=dfhack.maps.spawnFlow(unit.pos,6,0,0,50000) - end - -Reaction complete example" -:: - - b.onReactionComplete.one=function(reaction,unit,in_items,in_reag,out_items,call_native) - local pos=copyall(unit.pos) - dfhack.timeout(100,"ticks",function() dfhack.maps.spawnFlow(pos,6,0,0,50000) end) -- spawn dragonbreath after 100 ticks - call_native.value=false --do not call real item creation code - end diff --git a/plugins/eventful.cpp b/plugins/eventful.cpp index 267f01c29..02df231c4 100644 --- a/plugins/eventful.cpp +++ b/plugins/eventful.cpp @@ -14,6 +14,9 @@ #include "df/reaction_reagent_itemst.h" #include "df/reaction_product_itemst.h" +#include "df/proj_itemst.h" +#include "df/proj_unitst.h" + #include "MiscUtils.h" #include "LuaTools.h" @@ -85,13 +88,26 @@ static bool is_lua_hook(const std::string &name) static void handle_reaction_done(color_ostream &out,df::reaction*, df::unit *unit, std::vector *in_items,std::vector *in_reag , std::vector *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_projitem_ci(color_ostream &out,df::proj_itemst*,bool){}; +static void handle_projitem_cm(color_ostream &out,df::proj_itemst*){}; +static void handle_projunit_ci(color_ostream &out,df::proj_unitst*,bool){}; +static void handle_projunit_cm(color_ostream &out,df::proj_unitst*){}; DEFINE_LUA_EVENT_6(onReactionComplete, handle_reaction_done,df::reaction*, df::unit *, std::vector *,std::vector *,std::vector *,bool *); DEFINE_LUA_EVENT_5(onItemContaminateWound, handle_contaminate_wound, df::item_actual*,df::unit* , df::unit_wound* , uint8_t , int16_t ); +//projectiles +DEFINE_LUA_EVENT_2(onProjItemCheckImpact, handle_projitem_ci, df::proj_itemst*,bool ); +DEFINE_LUA_EVENT_1(onProjItemCheckMovement, handle_projitem_cm, df::proj_itemst*); +DEFINE_LUA_EVENT_2(onProjUnitCheckImpact, handle_projunit_ci, df::proj_unitst*,bool ); +DEFINE_LUA_EVENT_1(onProjUnitCheckMovement, handle_projunit_cm, df::proj_unitst* ); DFHACK_PLUGIN_LUA_EVENTS { DFHACK_LUA_EVENT(onReactionComplete), DFHACK_LUA_EVENT(onItemContaminateWound), + DFHACK_LUA_EVENT(onProjItemCheckImpact), + DFHACK_LUA_EVENT(onProjItemCheckMovement), + DFHACK_LUA_EVENT(onProjUnitCheckImpact), + DFHACK_LUA_EVENT(onProjUnitCheckMovement), DFHACK_LUA_END }; @@ -134,10 +150,49 @@ struct item_hooks :df::item_actual { onItemContaminateWound(out,this,unit,wound,a1,a2); INTERPOSE_NEXT(contaminateWound)(unit,wound,a1,a2); } + }; IMPLEMENT_VMETHOD_INTERPOSE(item_hooks, contaminateWound); +struct proj_item_hook: df::proj_itemst{ + typedef df::proj_itemst interpose_base; + DEFINE_VMETHOD_INTERPOSE(bool,checkImpact,(bool mode)) + { + CoreSuspendClaimer suspend; + color_ostream_proxy out(Core::getInstance().getConsole()); + onProjItemCheckImpact(out,this,mode); + return INTERPOSE_NEXT(checkImpact)(mode); //returns destroy item or not? + } + DEFINE_VMETHOD_INTERPOSE(bool,checkMovement,()) + { + CoreSuspendClaimer suspend; + color_ostream_proxy out(Core::getInstance().getConsole()); + onProjItemCheckMovement(out,this); + return INTERPOSE_NEXT(checkMovement)(); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(proj_item_hook,checkImpact); +IMPLEMENT_VMETHOD_INTERPOSE(proj_item_hook,checkMovement); +struct proj_unit_hook: df::proj_unitst{ + typedef df::proj_unitst interpose_base; + DEFINE_VMETHOD_INTERPOSE(bool,checkImpact,(bool mode)) + { + CoreSuspendClaimer suspend; + color_ostream_proxy out(Core::getInstance().getConsole()); + onProjUnitCheckImpact(out,this,mode); + return INTERPOSE_NEXT(checkImpact)(mode); //returns destroy item or not? + } + DEFINE_VMETHOD_INTERPOSE(bool,checkMovement,()) + { + CoreSuspendClaimer suspend; + color_ostream_proxy out(Core::getInstance().getConsole()); + onProjUnitCheckMovement(out,this); + return INTERPOSE_NEXT(checkMovement)(); + } +}; +IMPLEMENT_VMETHOD_INTERPOSE(proj_unit_hook,checkImpact); +IMPLEMENT_VMETHOD_INTERPOSE(proj_unit_hook,checkMovement); /* * Scan raws for matching reactions. */ @@ -192,6 +247,10 @@ static bool find_reactions(color_ostream &out) static void enable_hooks(bool enable) { INTERPOSE_HOOK(item_hooks,contaminateWound).apply(enable); + INTERPOSE_HOOK(proj_unit_hook,checkImpact).apply(enable); + INTERPOSE_HOOK(proj_unit_hook,checkMovement).apply(enable); + INTERPOSE_HOOK(proj_item_hook,checkImpact).apply(enable); + INTERPOSE_HOOK(proj_item_hook,checkMovement).apply(enable); } static void world_specific_hooks(color_ostream &out,bool enable) { diff --git a/scripts/gui/gm-editor.lua b/scripts/gui/gm-editor.lua index 54a2fc13d..6f3683c55 100644 --- a/scripts/gui/gm-editor.lua +++ b/scripts/gui/gm-editor.lua @@ -215,8 +215,9 @@ function GmEditorUi:onInput(keys) end elseif keys[keybindings.offset.key] then local trg=self:currentTarget() - local size,off=df.sizeof(trg.target:_field(trg.keys[trg.selected])) - dialog.showMessage("Offset",string.format("Size hex=%x,%x dec=%d,%d",size,off,size,off),COLOR_WHITE) + local _,stoff=df.sizeof(trg.target) + local size,off=df.sizeof(trg.target:_field(self:getSelectedKey())) + dialog.showMessage("Offset",string.format("Size hex=%x,%x dec=%d,%d\nRelative hex=%x dec=%d",size,off,size,off,off-stoff,off-stoff),COLOR_WHITE) --elseif keys.CUSTOM_ALT_F then --filter? elseif keys[keybindings.find.key] then self:find()