From 0a47184707b984b62931f4fcdbc4276f3f78ec70 Mon Sep 17 00:00:00 2001 From: AtomicChicken Date: Wed, 28 Mar 2018 16:01:09 +0200 Subject: [PATCH 1/4] item-trigger: support multiple conditions A significant rewrite allowing the user to specify any combination of itemType, material and contaminant. Previously, only one of the above could be used at a time, which greatly restricted the script's flexibility and limited its usefulness to modders. Also fixed the outdated(?) creature/plant material token format demonstrated in the -help printout, and added a few more examples. --- modtools/item-trigger.lua | 170 +++++++++++++++++++++++++------------- 1 file changed, 112 insertions(+), 58 deletions(-) diff --git a/modtools/item-trigger.lua b/modtools/item-trigger.lua index 1b8cf47a10..1e3c27b4b7 100644 --- a/modtools/item-trigger.lua +++ b/modtools/item-trigger.lua @@ -1,6 +1,7 @@ -- trigger commands based on attacks with certain items --author expwnent --based on itemsyndrome by Putnam +--equipment modes and combined trigger conditions added by AtomicChicken local usage = [====[ modtools/item-trigger @@ -48,14 +49,15 @@ Arguments:: trigger the commmand on items with the given material examples INORGANIC:IRON - CREATURE_MAT:DWARF:BRAIN - PLANT_MAT:MUSHROOM_HELMET_PLUMP:DRINK + CREATURE:DWARF:BRAIN + PLANT:OAK:WOOD -contaminant mat - trigger the command on items with a given material contaminant + trigger the command for items with a given material contaminant examples - INORGANIC:IRON - CREATURE_MAT:DWARF:BRAIN - PLANT_MAT:MUSHROOM_HELMET_PLUMP:DRINK + INORGANIC:GOLD + CREATURE:HUMAN:BLOOD + PLANT:MUSHROOM_HELMET_PLUMP:DRINK + WATER -command [ commandStrs ] specify the command to be executed commandStrs @@ -76,18 +78,13 @@ Arguments:: local eventful = require 'plugins.eventful' local utils = require 'utils' -itemTriggers = itemTriggers or {} -materialTriggers = materialTriggers or {} -contaminantTriggers = contaminantTriggers or {} - +triggers = triggers or {} eventful.enableEvent(eventful.eventType.UNIT_ATTACK,1) -- this event type is cheap, so checking every tick is fine eventful.enableEvent(eventful.eventType.INVENTORY_CHANGE,5) -- this is expensive, but you might still want to set it lower eventful.enableEvent(eventful.eventType.UNLOAD,1) eventful.onUnload.itemTrigger = function() - itemTriggers = {} - materialTriggers = {} - contaminantTriggers = {} + triggers = {} end function processTrigger(command) @@ -146,57 +143,104 @@ function compareInvModes(reqMode,itemMode) end end -function checkMode(table,triggerArg) - for _,command in ipairs(triggerArg) do - if command[""..table.mode..""] then - local reqModeType = command[""..table.mode..""] - local modeType = tonumber(table.modeType) +function checkMode(triggerArgs,table) + local mode = table.mode + for _,argArray in ipairs(triggerArgs) do + if argArray[""..mode..""] then + local modeType = table.modeType + local reqModeType = argArray[""..mode..""] if #reqModeType == 1 then if compareInvModes(reqModeType,modeType) or compareInvModes(reqModeType[1],modeType) then - utils.fillTable(command,table) - processTrigger(command) - utils.unfillTable(command,table) + utils.fillTable(argArray,table) + processTrigger(argArray) + utils.unfillTable(argArray,table) end elseif #reqModeType > 1 then for _,r in ipairs(reqModeType) do if compareInvModes(r,modeType) then - utils.fillTable(command,table) - processTrigger(command) - utils.unfillTable(command,table) + utils.fillTable(argArray,table) + processTrigger(argArray) + utils.unfillTable(argArray,table) end end else - utils.fillTable(command,table) - processTrigger(command) - utils.unfillTable(command,table) + utils.fillTable(argArray,table) + processTrigger(argArray) + utils.unfillTable(argArray,table) end end end end +function checkForTrigger(table) + local itemMatStr = table.itemMat:getToken() + local contaminantStr + if table.contaminantMat then + contaminantStr = table.contaminantMat:getToken() + end + for _,triggerBundle in ipairs(triggers) do + local count = 0 + local trigger = triggerBundle['triggers'] + local triggerCount = 0 + for _,t in pairs(trigger) do + triggerCount = triggerCount+1 + end + if trigger['itemType'] == table.itemType then + count = count+1 + end + if trigger['material'] == itemMatStr then + count = count+1 + end + if trigger['contaminant'] == contaminantStr then + count = count+1 + end + if count == triggerCount then + checkMode(triggerBundle['args'],table) + end + end +end + +function checkForDuplicates(args) + for k,triggerBundle in ipairs(triggers) do + local count = 0 + local trigger = triggerBundle['triggers'] + if trigger['itemType'] == args.itemType then + count = count+1 + end + if trigger['material'] == args.material then + count = count+1 + end + if trigger['contaminant'] == args.contaminant then + count = count+1 + end + if count == 3 then--counts nil values too + return k + end + end +end + function handler(table) local itemMat = dfhack.matinfo.decode(table.item) - local itemMatStr = itemMat:getToken() local itemType = getitemType(table.item) table.itemMat = itemMat table.itemType = itemType - checkMode(table,(itemTriggers[itemType] or {})) - checkMode(table,(materialTriggers[itemMatStr] or {})) - - for _,contaminant in ipairs(table.item.contaminants or {}) do - local contaminantMat = dfhack.matinfo.decode(contaminant.mat_type, contaminant.mat_index) - local contaminantStr = contaminantMat:getToken() - table.contaminantMat = contaminantMat - checkMode(table,(contaminantTriggers[contaminantStr] or {})) - table.contaminantMat = nil + if table.item.contaminants and #table.item.contaminants > 0 then + for _,contaminant in ipairs(table.item.contaminants or {}) do + local contaminantMat = dfhack.matinfo.decode(contaminant.mat_type, contaminant.mat_index) + table.contaminantMat = contaminantMat + checkForTrigger(table) + table.contaminantMat = nil + end + else + checkForTrigger(table) end end function equipHandler(unit, item, mode, modeType) local table = {} - table.mode = mode - table.modeType = modeType + table.mode = tostring(mode) + table.modeType = tonumber(modeType) table.item = df.item.find(item) table.unit = df.unit.find(unit) if table.item and table.unit then -- they must both be not nil or errors will occur after this point with instant reactions. @@ -276,9 +320,7 @@ if args.help then end if args.clear then - itemTriggers = {} - materialTriggers = {} - contaminantTriggers = {} + triggers = {} end if args.checkAttackEvery then @@ -317,25 +359,37 @@ if args.itemType and dfhack.items.findType(args.itemType) == -1 then end local numConditions = (args.material and 1 or 0) + (args.itemType and 1 or 0) + (args.contaminant and 1 or 0) -if numConditions > 1 then - error 'too many conditions defined: not (yet) supported (pester expwnent if you want it)' -elseif numConditions == 0 then - error 'specify a material, weaponType, or contaminant' +if numConditions == 0 then + error 'Specify at least one material, itemType or contaminant.' +end + +local index +if #triggers > 0 then + index = checkForDuplicates(args) end -if args.material then - if not materialTriggers[args.material] then - materialTriggers[args.material] = {} +if not index then + index = #triggers+1 + triggers[index] = {} + local triggerArray = {} + if args.itemType then + triggerArray['itemType'] = args.itemType end - table.insert(materialTriggers[args.material],args) -elseif args.itemType then - if not itemTriggers[args.itemType] then - itemTriggers[args.itemType] = {} + if args.material then + triggerArray['material'] = args.material end - table.insert(itemTriggers[args.itemType],args) -elseif args.contaminant then - if not contaminantTriggers[args.contaminant] then - contaminantTriggers[args.contaminant] = {} + if args.contaminant then + triggerArray['contaminant'] = args.contaminant end - table.insert(contaminantTriggers[args.contaminant],args) + triggers[index]['triggers'] = triggerArray +end + +if not triggers[index]['args'] then + triggers[index]['args'] = {} end +local triggerArgs = triggers[index]['args'] +table.insert(triggerArgs,args) +local argsArray = triggerArgs[#triggerArgs] +argsArray.itemType = nil +argsArray.material = nil +argsArray.contaminant = nil From 90327867c20492650cf54bba778ace4c79ab5f08 Mon Sep 17 00:00:00 2001 From: AtomicChicken Date: Fri, 30 Mar 2018 19:40:38 +0200 Subject: [PATCH 2/4] minor fix --- modtools/item-trigger.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modtools/item-trigger.lua b/modtools/item-trigger.lua index 1e3c27b4b7..9475c013a6 100644 --- a/modtools/item-trigger.lua +++ b/modtools/item-trigger.lua @@ -173,6 +173,7 @@ function checkMode(triggerArgs,table) end function checkForTrigger(table) + local itemTypeStr = table.itemType local itemMatStr = table.itemMat:getToken() local contaminantStr if table.contaminantMat then @@ -185,13 +186,13 @@ function checkForTrigger(table) for _,t in pairs(trigger) do triggerCount = triggerCount+1 end - if trigger['itemType'] == table.itemType then + if itemTypeStr and trigger['itemType'] == itemTypeStr then count = count+1 end - if trigger['material'] == itemMatStr then + if itemMatStr and trigger['material'] == itemMatStr then count = count+1 end - if trigger['contaminant'] == contaminantStr then + if contaminantStr and trigger['contaminant'] == contaminantStr then count = count+1 end if count == triggerCount then From ed50b1cb229a7d1a6d0ffff8aebe2cc46dc66952 Mon Sep 17 00:00:00 2001 From: AtomicChicken Date: Fri, 30 Mar 2018 19:53:47 +0200 Subject: [PATCH 3/4] Update item-trigger.lua --- modtools/item-trigger.lua | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/modtools/item-trigger.lua b/modtools/item-trigger.lua index 9475c013a6..c44150d63b 100644 --- a/modtools/item-trigger.lua +++ b/modtools/item-trigger.lua @@ -78,13 +78,13 @@ Arguments:: local eventful = require 'plugins.eventful' local utils = require 'utils' -triggers = triggers or {} +itemTriggers = itemTriggers or {} eventful.enableEvent(eventful.eventType.UNIT_ATTACK,1) -- this event type is cheap, so checking every tick is fine eventful.enableEvent(eventful.eventType.INVENTORY_CHANGE,5) -- this is expensive, but you might still want to set it lower eventful.enableEvent(eventful.eventType.UNLOAD,1) eventful.onUnload.itemTrigger = function() - triggers = {} + itemTriggers = {} end function processTrigger(command) @@ -179,7 +179,7 @@ function checkForTrigger(table) if table.contaminantMat then contaminantStr = table.contaminantMat:getToken() end - for _,triggerBundle in ipairs(triggers) do + for _,triggerBundle in ipairs(itemTriggers) do local count = 0 local trigger = triggerBundle['triggers'] local triggerCount = 0 @@ -202,7 +202,7 @@ function checkForTrigger(table) end function checkForDuplicates(args) - for k,triggerBundle in ipairs(triggers) do + for k,triggerBundle in ipairs(itemTriggers) do local count = 0 local trigger = triggerBundle['triggers'] if trigger['itemType'] == args.itemType then @@ -321,7 +321,7 @@ if args.help then end if args.clear then - triggers = {} + itemTriggers = {} end if args.checkAttackEvery then @@ -365,13 +365,13 @@ if numConditions == 0 then end local index -if #triggers > 0 then +if #itemTriggers > 0 then index = checkForDuplicates(args) end if not index then - index = #triggers+1 - triggers[index] = {} + index = #itemTriggers+1 + itemTriggers[index] = {} local triggerArray = {} if args.itemType then triggerArray['itemType'] = args.itemType @@ -382,13 +382,13 @@ if not index then if args.contaminant then triggerArray['contaminant'] = args.contaminant end - triggers[index]['triggers'] = triggerArray + itemTriggers[index]['triggers'] = triggerArray end -if not triggers[index]['args'] then - triggers[index]['args'] = {} +if not itemTriggers[index]['args'] then + itemTriggers[index]['args'] = {} end -local triggerArgs = triggers[index]['args'] +local triggerArgs = itemTriggers[index]['args'] table.insert(triggerArgs,args) local argsArray = triggerArgs[#triggerArgs] argsArray.itemType = nil From edca6d9772d2d38ab2e69b2e0b278f28146eaf07 Mon Sep 17 00:00:00 2001 From: AtomicChicken Date: Tue, 3 Apr 2018 16:44:59 +0200 Subject: [PATCH 4/4] minor change replaced ""..mode.."" with tostring(mode), as per lethosor's feedback. --- modtools/item-trigger.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modtools/item-trigger.lua b/modtools/item-trigger.lua index c44150d63b..163a419c26 100644 --- a/modtools/item-trigger.lua +++ b/modtools/item-trigger.lua @@ -146,9 +146,9 @@ end function checkMode(triggerArgs,table) local mode = table.mode for _,argArray in ipairs(triggerArgs) do - if argArray[""..mode..""] then + if argArray[tostring(mode)] then local modeType = table.modeType - local reqModeType = argArray[""..mode..""] + local reqModeType = argArray[tostring(mode)] if #reqModeType == 1 then if compareInvModes(reqModeType,modeType) or compareInvModes(reqModeType[1],modeType) then utils.fillTable(argArray,table)