Last active
July 25, 2022 23:51
-
-
Save Putnam3145/7005730 to your computer and use it in GitHub Desktop.
**Obsoleted by DFHack's item-trigger**. Itemsyndrome. Usage is given when "itemsyndrome help" is used. Updated for DFHack 0.34.11 r4. lso updated with Boltgun's changes to the assignment function.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Checks for inventory changes and applies or removes syndromes that items or their materials have. Use "disable" (minus quotes) to disable and "help" to get help. | |
local args = {...} | |
local function printItemSyndromeHelp() | |
print("Arguments (non case-sensitive):") | |
print(' "help": displays this dialogue.') | |
print(" ") | |
print(' "disable": disables the script.') | |
print(" ") | |
print(' "debugon/debugoff": debug mode.') | |
print(" ") | |
print(' "contaminantson/contaminantsoff": toggles searching for contaminants.') | |
print(' Disabling speeds itemsyndrome up greatly.') | |
print(' "transformReEquipOn/TransformReEquipOff": toggles transformation auto-reequip.') | |
end | |
itemsyndromedebug=false | |
function processArgs(args) | |
for k,v in ipairs(args) do | |
v=v:lower() | |
if v == "help" then printItemSyndromeHelp() return end | |
if v == "debugon" then itemsyndromedebug = true end | |
if v == "debugoff" then itemsyndromedebug = false end | |
if v == "contaminantson" then itemsyndromecontaminants = true end | |
if v == "contaminantsoff" then itemsyndromecontaminants = false end | |
if v == "transformreequipon" then transformationReEquip = true end | |
if v == "transformreequipoff" then transformationReEquip = false end | |
end | |
end | |
processArgs(args) | |
local function getMaterial(item) | |
local material = dfhack.matinfo.decode(item) and dfhack.matinfo.decode(item) or false | |
if not material then return nil end | |
if material.mode ~= "inorganic" then | |
return nil | |
else | |
return material.material --the "material" thing up there contains a bit more info which is all pretty important but impertinent, like the creature that the material comes from | |
end | |
end | |
local function findItemSyndromeInorganic() | |
local allInorganics = {} | |
for matID,material in ipairs(df.global.world.raws.inorganics) do | |
if string.find(material.id,"DFHACK_ITEMSYNDROME_MATERIAL_") then table.insert(allInorganics,matID) end --the last underscore is needed to prevent duped raws; I want good modder courtesy if it kills me, dammit! | |
end | |
if itemsyndromedebug then printall(allInorganics) end | |
if #allInorganics>0 then return allInorganics else return nil end | |
end | |
local function getAllItemSyndromeMats(itemSyndromeMatIDs) | |
local allActualInorganics = {} | |
for _,itemSyndromeMatID in ipairs(itemSyndromeMatIDs) do | |
table.insert(allActualInorganics,df.global.world.raws.inorganics[itemSyndromeMatID].material) | |
end | |
if itemsyndromedebug then printall(allActualInorganics) end | |
return allActualInorganics | |
end | |
local function syndromeIsDfHackSyndrome(syndrome) | |
for k,v in ipairs(syndrome.syn_class) do | |
if v.value=="DFHACK_ITEM_SYNDROME" then | |
if itemsyndromedebug then print('Syndrome is DFHack syndrome, checking if creature is affected...') end | |
return true | |
end | |
end | |
if itemsyndromedebug then print('Syndrome is not DFHack syndrome. Cancelling.') end | |
return false | |
end | |
local function itemHasNoSubtype(item) | |
return item:getSubtype()==-1 | |
end | |
local function itemHasSyndrome(item) | |
if itemHasNoSubtype(item) or not itemSyndromeMats then return nil end | |
local allItemSyndromes={} | |
for _,material in ipairs(itemSyndromeMats) do | |
for __,syndrome in ipairs(material.syndrome) do | |
if syndrome.syn_name == item.subtype.name then table.insert(allItemSyndromes,syndrome) end | |
end | |
end | |
return #allItemSyndromes>0 and allItemSyndromes or false | |
end | |
local function alreadyHasSyndrome(unit,syn_id) | |
for _,syndrome in ipairs(unit.syndromes.active) do | |
if syndrome.type == syn_id then return true end | |
end | |
return false | |
end | |
local function eraseSyndrome(target,syn_id) | |
for i=#target.syndromes.active-1,0,-1 do | |
if target.syndromes.active[i].type==syn_id then target.syndromes.active:erase(i) end | |
end | |
end | |
local function assignSyndrome(target,syn_id) --taken straight from here, but edited so I can understand it better: https://gist.github.com/warmist/4061959/. Also implemented expwnent's changes for compatibility with syndromeTrigger. | |
if target==nil then | |
return nil | |
end | |
if alreadyHasSyndrome(target,syn_id) then | |
local syndrome | |
for k,v in ipairs(target.syndromes.active) do | |
if v.type == syn_id then syndrome = v end | |
end | |
if not syndrome then return nil end | |
syndrome.ticks=1 | |
return true | |
end | |
local newSyndrome=df.unit_syndrome:new() | |
local target_syndrome=df.syndrome.find(syn_id) | |
newSyndrome.type=target_syndrome.id | |
newSyndrome.year=df.global.cur_year | |
newSyndrome.year_time=df.global.cur_year_tick | |
newSyndrome.ticks=0 | |
newSyndrome.unk1=0 | |
--newSyndrome.flags=0 | |
for k,v in ipairs(target_syndrome.ce) do | |
local sympt=df.unit_syndrome.T_symptoms:new() | |
sympt.unk1=0 | |
sympt.unk2=0 | |
sympt.ticks=0 | |
sympt.flags=2 | |
newSyndrome.symptoms:insert("#",sympt) | |
end | |
target.syndromes.active:insert("#",newSyndrome) | |
if itemsyndromedebug then | |
print("Assigned syndrome #" ..syn_id.." to unit.") | |
end | |
return true | |
end | |
local function syndromeIsIndiscriminate(syndrome) | |
return (#syndrome.syn_affected_class==0 and #syndrome.syn_affected_creature==0 and #syndrome.syn_affected_caste==0 and #syndrome.syn_immune_class==0 and #syndrome.syn_immune_creature==0 and #syndrome.syn_immune_caste==0) | |
end | |
local function creatureIsAffected(unit,syndrome) | |
if syndromeIsIndiscriminate(syndrome) then | |
if itemsyndromedebug then | |
print("Creature is affected, checking if item is in valid position...") | |
end | |
return true | |
end | |
local affected = false | |
local unitraws = df.creature_raw.find(unit.race) | |
local casteraws = unitraws.caste[unit.caste] | |
local unitracename = unitraws.creature_id | |
local castename = casteraws.caste_id | |
local unitclasses = casteraws.creature_class | |
for _,unitclass in ipairs(unitclasses) do | |
for _,syndromeclass in ipairs(syndrome.syn_affected_class) do | |
if unitclass.value==syndromeclass.value then affected = true end | |
end | |
end | |
for caste,creature in ipairs(syndrome.syn_affected_creature) do | |
local affected_creature = creature.value | |
local affected_caste = syndrome.syn_affected_caste[caste].value --slightly evil, but oh well, hehe. | |
if affected_creature == unitracename and affected_caste == castename then affected = true end | |
end | |
for _,unitclass in ipairs(unitclasses) do | |
for _,syndromeclass in ipairs(syndrome.syn_immune_class) do | |
if unitclass.value==syndromeclass.value then affected = false end | |
end | |
end | |
for caste,creature in ipairs(syndrome.syn_immune_creature) do | |
local immune_creature = creature.value | |
local immune_caste = syndrome.syn_immune_caste[caste].value | |
if immune_creature == unitracename and immune_caste == castename then affected = false end | |
end | |
if itemsyndromedebug then | |
if not affected then print("Creature is not affected. Cancelling.") else print("Creature is affected, checking if item is in valid position...") end | |
end | |
return affected | |
end | |
local function getValidPositions(syndrome) | |
local returnTable={AffectsHauler=false,AffectsStuckins=false,IsArmorOnly=false,IsWieldedOnly=false,OnlyAffectsStuckins=false} | |
for k,v in ipairs(syndrome.syn_class) do | |
if v.value:find('DFHACK') then | |
if v.value=="DFHACK_AFFECTS_HAULER" then returnTable.AffectsHauler=true end | |
if v.value=="DFHACK_AFFECTS_STUCKIN" then returnTable.AffectsStuckins=true end | |
if v.value=="DFHACK_STUCKINS_ONLY" then returnTable.OnlyAffectsStuckins=true end | |
if v.value=="DFHACK_WIELDED_ONLY" then returnTable.IsWieldedOnly=true end | |
if v.value=="DFHACK_ARMOR_ONLY" then returnTable.IsArmorOnly=true end | |
end | |
end | |
return returnTable | |
end | |
local function itemIsInValidPosition(item_inv, syndrome) | |
local item = getValidPositions(syndrome) | |
if not item_inv then print("You shouldn't see this error! At all! Putnam f'd up! Tell her off!") return false end | |
local isInValidPosition=not ((item_inv.mode == 0 and not item.AffectsHauler) or (item_inv.mode == 7 and not item.AffectsStuckins) or (item_inv.mode ~= 2 and item.IsArmorOnly) or (item_inv.mode ~=1 and item.IsWieldedOnly) or (item_inv.mode ~=7 and item.OnlyAffectsStuckins)) | |
if itemsyndromedebug then print(isInValidPosition and 'Item is in correct position.' or 'Item is not in correct position.') end | |
return isInValidPosition | |
end | |
local function syndromeIsTransformation(syndrome) | |
for _,effect in ipairs(syndrome.ce) do | |
if df.creature_interaction_effect_body_transformationst:is_instance(effect) then return true end | |
end | |
return false | |
end | |
local function rememberInventory(unit) | |
local invCopy = {} | |
for inv_id,item_inv in ipairs(unit.inventory) do | |
invCopy[inv_id+1] = {} | |
local itemToWorkOn = invCopy[inv_id+1] | |
itemToWorkOn.item = item_inv.item | |
itemToWorkOn.mode = item_inv.mode | |
itemToWorkOn.body_part_id = item_inv.body_part_id | |
end | |
return invCopy | |
end | |
local function moveAllToInventory(unit,invTable) | |
for _,item_inv in ipairs(invTable) do | |
dfhack.items.moveToInventory(item_inv.item,unit,item_inv.mode,item_inv.body_part_id) | |
end | |
end | |
local function syndromeIsOnUnequip(syndrome) | |
for k,v in ipairs(syndrome.syn_class) do | |
if v.value:upper()=='DFHACK_ON_UNEQUIP' then return true end | |
end | |
return false | |
end | |
local function addOrRemoveSyndromeDepending(unit,old_equip,new_equip,syndrome) | |
local item_inv=new_equip or old_equip | |
if syndromeIsOnUnequip(syndrome) then | |
if itemsyndromedebug then print('Syndrome is applied on unequip.') end | |
if syndromeIsDfHackSyndrome(syndrome) and creatureIsAffected(unit,syndrome) and itemIsInValidPosition(item_inv,syndrome) then | |
if not new_equip then | |
assignSyndrome(unit,syndrome.id) | |
else | |
eraseSyndrome(unit,syndrome.id) | |
end | |
end | |
else | |
if itemsyndromedebug then print('Syndrome is applied on equip.') end | |
if syndromeIsDfHackSyndrome(syndrome) and creatureIsAffected(unit,syndrome) and itemIsInValidPosition(item_inv,syndrome) then | |
if new_equip then | |
assignSyndrome(unit,syndrome.id) | |
else | |
eraseSyndrome(unit,syndrome.id) | |
end | |
end | |
end | |
end | |
eventful=require('plugins.eventful') | |
eventful.enableEvent(eventful.eventType.INVENTORY_CHANGE,5) | |
eventful.onInventoryChange.itemsyndrome=function(unit_id,item_id,old_equip,new_equip) | |
local item = df.item.find(item_id) | |
if not item then return false end | |
local unit = df.unit.find(unit_id) | |
if unit.flags1.dead then return false end | |
if itemsyndromedebug then print("Checking unit #" .. unit_id) end | |
local transformation = false | |
if itemsyndromedebug then print("checking item #" .. item_id .." on unit #" .. unit_id) end | |
local itemMaterial=getMaterial(item) | |
if itemMaterial then | |
for k,syndrome in ipairs(itemMaterial.syndrome) do | |
if itemsyndromedebug then print("item has a syndrome, checking if syndrome is valid for application...") end | |
if syndromeIsTransformation(syndrome) then | |
unitInventory = rememberInventory(unit) | |
transformation = true | |
end | |
addOrRemoveSyndromeDepending(unit,old_equip,new_equip,syndrome) | |
end | |
end | |
local itemSyndromes = itemHasSyndrome(item) | |
if itemSyndromes then | |
if itemsyndromedebug then print("Item itself has a syndrome, checking if item is in correct position and creature is affected") end | |
for k,syndrome in ipairs(itemSyndromes) do | |
if syndromeIsTransformation(syndrome) then | |
unitInventory = rememberInventory(unit) | |
transformation = true | |
end | |
addOrRemoveSyndromeDepending(unit,old_equip,new_equip,syndrome) | |
end | |
end | |
if itemsyndromecontaminants and item.contaminants then | |
if itemsyndromedebug then print("Item has contaminants. Checking for syndromes...") end | |
for _,contaminant in ipairs(item.contaminants) do | |
local contaminantMaterial=getMaterial(contaminant) | |
if contaminantMaterial then | |
for k,syndrome in ipairs(contaminantMaterial.syndrome) do | |
if itemsyndromedebug then print("Checking syndrome #" .. k .. "on contaminant #" .. _ .. " on item #" .. item_id .. " on unit #" .. unit_id ..".") end | |
if syndromeIsTransformation(syndrome) then | |
unitInventory = rememberInventory(unit) | |
transformation =true | |
end | |
addOrRemoveSyndromeDepending(unit,old_equip,new_equip,syndrome) | |
end | |
end | |
end | |
end | |
if transformation and transformationReEquip then dfhack.timeout(2,"ticks",function() moveAllToInventory(unit,unitInventory) end) end | |
end | |
dfhack.onStateChange.itemsyndrome=function(code) | |
if code==SC_WORLD_LOADED then | |
itemSyndromeMatIDs = findItemSyndromeInorganic() | |
if itemSyndromeMatIDs then itemSyndromeMats = getAllItemSyndromeMats(itemSyndromeMatIDs) end | |
end | |
end | |
if disable then | |
eventful.onInventoryChange.itemsyndrome=nil | |
print("Disabled itemsyndrome.") | |
disable = false | |
else | |
print("Enabled itemsyndrome.") | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Huzzah! I've updated SWP with this version. (I'm assuming equip-on-transform happening by default was causing some discomfort somewhere?)
Many thanks,
~T