--scripts/modtools/interaction-trigger.lua --author expwnent --triggers scripts when a unit does a unit interaction on another --[[=begin modtools/interaction-trigger ============================ This triggers events when a unit uses an interaction on another. It works by scanning the announcements for the correct attack verb, so the attack verb must be specified in the interaction. It includes an option to suppress this announcement after it finds it. =end]] local eventful = require 'plugins.eventful' local utils = require 'utils' attackTriggers = attackTriggers or {} defendTriggers = defendTriggers or {} commands = commands or {} commandCount = commandCount or 0 eventful.enableEvent(eventful.eventType.INTERACTION,1) --cheap, so every tick is fine eventful.enableEvent(eventful.eventType.UNLOAD,1) eventful.onUnload.interactionTrigger = function() attackTriggers = {} defendTriggers = {} commands = {} commandCount = 0 end local function processTrigger(args) local command = {} for _,arg in ipairs(args.command) do if arg == '\\ATTACK_VERB' then table.insert(command,args.attackVerb) elseif arg == '\\DEFEND_VERB' then table.insert(command,args.defendVerb) elseif arg == '\\ATTACKER_ID' then table.insert(command,args.attackerId) elseif arg == '\\DEFENDER_ID' then table.insert(command,args.defenderId) elseif arg == '\\ATTACK_REPORT' then table.insert(command,args.attackReport) elseif arg == '\\DEFEND_REPORT' then table.insert(command,args.defendReport) elseif string.sub(arg,1,1) == '\\' then table.insert(command,string.sub(arg,2)) else table.insert(command,arg) end end dfhack.run_command(table.unpack(command)) end eventful.onInteraction.interactionTrigger = function(attackVerb, defendVerb, attacker, defender, attackReport, defendReport) local extras = {} extras.attackVerb = attackVerb extras.defendVerb = defendVerb extras.attackReport = attackReport extras.defendReport = defendReport extras.attackerId = attacker extras.defenderId = defender local suppressAttack = false local suppressDefend = false local todo = {} for _,trigger in ipairs(attackTriggers[attackVerb] or {}) do todo[trigger] = true end for _,trigger in ipairs(defendTriggers[defendVerb] or {}) do todo[trigger] = true end for k,v in pairs(todo) do command = commands[k] suppressAttack = suppressAttack or command.suppressAttack suppressDefend = suppressDefend or command.suppressDefend utils.fillTable(command,extras) processTrigger(command) utils.unfillTable(command,extras) end local eraseReport = function(unit,report) for i,v in ipairs(unit.reports.log.Combat) do if v == report then unit.reports.log.Combat:erase(i) break end end end if suppressAttack or suppressDefend then attacker = df.unit.find(tonumber(attacker)) defender = df.unit.find(tonumber(defender)) end if suppressAttack then eraseReport(attacker,attackReport) eraseReport(defender,attackReport) end if suppressDefend then eraseReport(attacker,defendReport) eraseReport(defender,defendReport) end --TODO: get rid of combat report on LHS of screen end ---------------------------------------------------- --argument processing validArgs = validArgs or utils.invert({ 'clear', 'help', 'onAttackStr', 'onDefendStr', 'command', 'suppressAttack', 'suppressDefend', }) local args = utils.processArgs({...}, validArgs) if args.help then print([[scripts/modtools/interaction-trigger.lua arguments: -help print this help message -clear unregisters all triggers -onAttackStr str trigger the command when the attack verb is "str". both onAttackStr and onDefendStr MUST be specified -onDefendStr str trigger the command when the defend verb is "str". both onAttackStr and onDefendStr MUST be specified -suppressAttack delete the attack announcement from the combat logs -suppressDefend delete the defend announcement from the combat logs -command [ commandStrs ] specify the command to be executed commandStrs \\ATTACK_VERB \\DEFEND_VERB \\ATTACKER_ID \\DEFENDER_ID \\ATTACK_REPORT \\DEFEND_REPORT \\anything -> \anything anything -> anything You must specify both an attack string and a defend string to guarantee correct performance. Either will trigger the script when it happens, but it will not be triggered twice in a row if both happen. ]]) return end if args.clear then triggers = {} commands = {} commandCount = 0 end if not args.command then return end commands[commandCount] = args if args.onAttackStr then if not attackTriggers[args.onAttackStr] then attackTriggers[args.onAttackStr] = {} end table.insert(attackTriggers[args.onAttackStr],commandCount) end if args.onDefendStr then if not defendTriggers[args.onDefendStr] then defendTriggers[args.onDefendStr] = {} end table.insert(defendTriggers[args.onDefendStr],commandCount) end commandCount = commandCount+1