From f58e659193dfa2a8792c1108f8be236a3968a482 Mon Sep 17 00:00:00 2001 From: expwnent Date: Mon, 30 Jun 2014 08:16:10 -0400 Subject: [PATCH] item-trigger: trigger scripts based on equipping items, unequipping items, and striking enemies with items. Select item by type, material, or by *contaminant* material. --- scripts/modtools/attack-trigger.lua | 127 ------------------ scripts/modtools/item-trigger.lua | 201 ++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 127 deletions(-) delete mode 100644 scripts/modtools/attack-trigger.lua create mode 100644 scripts/modtools/item-trigger.lua diff --git a/scripts/modtools/attack-trigger.lua b/scripts/modtools/attack-trigger.lua deleted file mode 100644 index a1a9545b3..000000000 --- a/scripts/modtools/attack-trigger.lua +++ /dev/null @@ -1,127 +0,0 @@ ---attackTrigger.lua ---author expwnent ---triggers scripts when a unit attacks another with a weapon type, a weapon of a particular material - -local eventful = require 'plugins.eventful' -local utils = require 'utils' -eventful.enableEvent(eventful.eventType.UNIT_ATTACK,1) - -itemTriggers = itemTriggers or {} -materialTriggers = materialTriggers or {} ---itemMaterialTriggers = itemMaterialTriggers or {} - -local function processTrigger(command, attacker, defender) - local command2 = {} - for i,arg in ipairs(command) do - if arg == '\\ATTACKER' then - command2[i] = '' .. attacker.id - elseif arg == '\\DEFENDER' then - command2[i] = '' .. defender.id - else - command2[i] = arg - end - end - print(dfhack.run_command(table.unpack(command2))) -end - -eventful.onUnitAttack.attackTrigger = function(attacker,defender,wound) - attacker = df.unit.find(attacker) - defender = df.unit.find(defender) - - if not attacker then - return - end - - local attackerWeapon - for _,item in ipairs(attacker.inventory) do - if item.mode == df.unit_inventory_item.T_mode.Weapon then - attackerWeapon = item.item - break - end - end - - if not attackerWeapon then - return - end - - local weaponType = attackerWeapon.subtype.subtype --attackerWeapon.subtype.id - - if itemTriggers[weaponType] then - for _,command in pairs(itemTriggers[weaponType]) do - processTrigger(command,attacker,defender) - end - end - --- if materialTriggers[attackerWeapon.mat_type] and materialTriggers[attackerWeapon.mat_type][attackerWeapon.mat_index] then - if materialTriggers[attackerWeapon.mat_index] then - for _,command in pairs(materialTriggers[attackerWeapon.mat_index]) do - processTrigger(command,attacker,defender) - end - end - --- if itemMaterialTriggers[weaponType] and itemMaterialTriggers[weaponType][attackerWeapon.mat_type] and itemMaterialTriggers[weaponType][attackerWeapon.mat_type][attackerWeapon.mat_index] then --- for _,command in pairs(itemMaterialTriggers[weaponType][attackerWeapon.mat_type][attackerWeapon.mat_index]) do --- processTrigger(command,attacker,defender) --- end --- end -end - -local args = utils.processArgs(...) - -if args.clear then - itemTriggers = {} - materialTriggers = {} -end - -if not args.command then - if not args.clear then - error 'specify a command' - end - return -end - -if args.weaponType then - local temp - for _,itemdef in ipairs(df.global.world.raws.itemdefs.weapons) do - if itemdef.id == args.weaponType then - temp = itemdef.subtype - break - end - end - if not temp then - error 'Could not find weapon type.' - end - args.weaponType = temp -end - -if args.material then - local i = 0 - while true do - local mat = dfhack.matinfo.decode(0,i) - if not mat then - error('Could not find material "' .. args.material .. '" after '..i..' materials.') - end - if mat.inorganic.id == args.material then - args.material = mat.index - break - end - i = i+1 - end -end - -if args.material and args.weaponType then - error 'both material and weaponType defined' -end - -if args.material then - if not materialTriggers[args.material] then - materialTriggers[args.material] = {} - end - table.insert(materialTriggers[args.material],args.command) -elseif args.weaponType then - if not itemTriggers[args.weaponType] then - itemTriggers[args.weaponType] = {} - end - table.insert(itemTriggers[args.weaponType],args.command) -end - diff --git a/scripts/modtools/item-trigger.lua b/scripts/modtools/item-trigger.lua new file mode 100644 index 000000000..cfb00bfb7 --- /dev/null +++ b/scripts/modtools/item-trigger.lua @@ -0,0 +1,201 @@ +--attackTrigger.lua +--author expwnent +--based on itemsyndrome by Putnam +--triggers scripts when a unit attacks another with a weapon type, a weapon of a particular material + +local eventful = require 'plugins.eventful' +local utils = require 'utils' +eventful.enableEvent(eventful.eventType.UNIT_ATTACK,1) -- this event type is cheap, so checking every tick is fine +eventful.enableEvent(eventful.eventType.INVENTORY_CHANGE,1000) --this is expensive, but you'll still want to set it lower +eventful.enableEvent(eventful.eventType.INVENTORY_CHANGE,1) + +itemTriggers = itemTriggers or {} +materialTriggers = materialTriggers or {} +contaminantTriggers = contaminantTriggers or {} + +function processTrigger(command) + local command2 = {} + for i,arg in ipairs(command.command) do + if arg == '\\ATTACKER_ID' then + command2[i] = '' .. command.attacker.id + elseif arg == '\\DEFENDER_ID' then + command2[i] = '' .. command.defender.id + elseif arg == '\\ITEM_MATERIAL' then + command2[i] = command.itemMat:getToken() + elseif arg == '\\ITEM_MATERIAL_TYPE' then + command2[i] = command.itemMat['type'] + elseif arg == '\\ITEM_MATERIAL_INDEX' then + command2[i] = command.itemMat.index + elseif arg == '\\ITEM_ID' then + command2[i] = '' .. command.item.id + elseif arg == '\\ITEM_TYPE' then + command2[i] = command.itemType + elseif arg == '\\CONTAMINANT_MATERIAL' then + command2[i] = command.contaminantMat:getToken() + elseif arg == '\\CONTAMINANT_MATERIAL_TYPE' then + command2[i] = command.contaminantMat['type'] + elseif arg == '\\CONTAMINANT_MATERIAL_INDEX' then + command2[i] = command.contaminantMat.index + elseif arg == '\\MODE' then + command2[i] = command.mode + elseif arg == '\\UNIT_ID' then + command2[i] = command.unit.id + elseif string.sub(arg,1,1) == '\\' then + command2[i] = string.sub(command,2) + else + command2[i] = arg + end + end + print(dfhack.run_command(table.unpack(command2))) +end + +function fillTable(table1,table2) + for k,v in pairs(table2) do + table1[k] = v + end +end + +function unfillTable(table1,table2) + for k,v in pairs(table2) do + table1[k] = nil + end +end + +function handler(table) + local itemMat = dfhack.matinfo.decode(table.item) + local itemMatStr = itemMat:getToken() + local itemType = dfhack.items.getSubtypeDef(table.item:getType(),table.item:getSubtype()).id + table.itemMat = itemMat + table.itemType = itemType + + for _,command in ipairs(itemTriggers[itemType] or {}) do + if command[table.mode] then + print('asdf') + fillTable(command,table) + processTrigger(command) + unfillTable(command,table) + end + end + + for _,command in ipairs(materialTriggers[itemMatStr] or {}) do + if command[table.mode] then + print('asdf') + fillTable(command,table) + processTrigger(command) + unfillTable(command,table) + end + end + + for _,contaminant in ipairs(table.item.contaminants) do + local contaminantMat = dfhack.matinfo.decode(contaminant.mat_type, contaminant.mat_index) + local contaminantStr = contaminantMat:getToken() + table.contaminantMat = contaminantMat + for _,command in ipairs(contaminantTriggers[contaminantStr] or {}) do + print('asdf') + fillTable(command,table) + processTrigger(command) + unfillTable(command,table) + end + table.contaminantMat = nil + end +end + +eventful.onInventoryChange.equipmentTrigger = function(unit, item, item_old, item_new) + if item_old and item_new then + return + end + + local isEquip = item_new and not item_old + local mode = (isEquip and 'onEquip') or (not isEquip and 'onUnequip') + local table = {} + table.mode = mode + table.item = df.item.find(item) + table.unit = unit + handler(table) +end + +eventful.onUnitAttack.attackTrigger = function(attacker,defender,wound) + attacker = df.unit.find(attacker) + defender = df.unit.find(defender) + + if not attacker then + return + end + + local attackerWeapon + for _,item in ipairs(attacker.inventory) do + if item.mode == df.unit_inventory_item.T_mode.Weapon then + attackerWeapon = item.item + break + end + end + + if not attackerWeapon then + return + end + + local table = {} + table.attacker = attacker + table.defender = defender + table.item = attackerWeapon + table.mode = 'onStrike' + handler(table) +end + +local args = utils.processArgs(...) + +if args.clear then + itemTriggers = {} + materialTriggers = {} + contaminantTriggers = {} +end + +if args.checkEvery then + if not tonumber(args.checkEvery) then + error('checkEvery must be a number') + end + eventful.enableEvent(eventful.eventType.INVENTORY_CHANGE,tonumber(args.checkEvery)) +end + +if not args.command then + if not args.clear then + error 'specify a command' + end + return +end + +if args.weaponType then + local temp + for _,itemdef in ipairs(df.global.world.raws.itemdefs.weapons) do + if itemdef.id == args.weaponType then + temp = itemdef.subtype + break + end + end + if not temp then + error 'Could not find weapon type.' + end + args.weaponType = temp +end + +if (args.material and 1) + (args.weaponType and 1) + (args.contaminant and 1) > 1 then + error 'too many conditions defined: not (yet) supported (pester expwnent if you want it)' +end + +if args.material then + if not materialTriggers[args.material] then + materialTriggers[args.material] = {} + end + table.insert(materialTriggers[args.material],args) +elseif args.itemType then + if not itemTriggers[args.itemType] then + itemTriggers[args.itemType] = {} + end + table.insert(itemTriggers[args.itemType],args) +elseif args.contaminant then + if not contaminantTriggers[args.contaminant] then + contaminantTriggers[args.contaminant] = {} + end + table.insert(contaminantTriggers[args.contaminant],args) +end +