laferrierejc

itemsyndromer4.lua

Dec 28th, 2013
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.57 KB | None | 0 0
  1. -- 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.
  2.  
  3. local args = {...}
  4.  
  5. local function printItemSyndromeHelp()
  6. print("Arguments (non case-sensitive):")
  7. print(' "help": displays this dialogue.')
  8. print(" ")
  9. print(' "disable": disables the script.')
  10. print(" ")
  11. print(' "debugon/debugoff": debug mode.')
  12. print(" ")
  13. print(' "contaminantson/contaminantsoff": toggles searching for contaminants.')
  14. print(' Disabling speeds itemsyndrome up greatly.')
  15. print(' "transformReEquipOn/TransformReEquipOff": toggles transformation auto-reequip.')
  16. end
  17.  
  18. itemsyndromedebug=false
  19.  
  20. function processArgs(args)
  21. for k,v in ipairs(args) do
  22. v=v:lower()
  23. if v == "help" then printItemSyndromeHelp() return end
  24. if v == "debugon" then itemsyndromedebug = true end
  25. if v == "debugoff" then itemsyndromedebug = false end
  26. if v == "contaminantson" then itemsyndromecontaminants = true end
  27. if v == "contaminantsoff" then itemsyndromecontaminants = false end
  28. if v == "transformreequipon" then transformationReEquip = true end
  29. if v == "transformreequipoff" then transformationReEquip = false end
  30. end
  31. end
  32.  
  33. processArgs(args)
  34.  
  35. local function getMaterial(item)
  36. local material = dfhack.matinfo.decode(item) and dfhack.matinfo.decode(item) or false
  37. if not material then return nil end
  38. if material.mode ~= "inorganic" then
  39. return nil
  40. else
  41. 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
  42. end
  43. end
  44.  
  45. local function findItemSyndromeInorganic()
  46. local allInorganics = {}
  47. for matID,material in ipairs(df.global.world.raws.inorganics) do
  48. 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!
  49. end
  50. if itemsyndromedebug then printall(allInorganics) end
  51. if #allInorganics>0 then return allInorganics else return nil end
  52. end
  53.  
  54. local function getAllItemSyndromeMats(itemSyndromeMatIDs)
  55. local allActualInorganics = {}
  56. for _,itemSyndromeMatID in ipairs(itemSyndromeMatIDs) do
  57. table.insert(allActualInorganics,df.global.world.raws.inorganics[itemSyndromeMatID].material)
  58. end
  59. if itemsyndromedebug then printall(allActualInorganics) end
  60. return allActualInorganics
  61. end
  62.  
  63. local function syndromeIsDfHackSyndrome(syndrome)
  64. for k,v in ipairs(syndrome.syn_class) do
  65. if v.value=="DFHACK_ITEM_SYNDROME" then return true end
  66. end
  67. return false
  68. end
  69.  
  70. local function itemHasNoSubtype(item)
  71. local subtypedItemTypes =
  72. {
  73. df.item_armorst,
  74. df.item_weaponst,
  75. df.item_helmst,
  76. df.item_shoesst,
  77. df.item_shieldst,
  78. df.item_glovest,
  79. df.item_pantsst,
  80. df.item_toolst,
  81. df.item_siegeammost,
  82. df.item_ammost,
  83. df.item_trapcompst,
  84. df.item_instrumentst,
  85. df.item_toyst}
  86. for _,v in ipairs(subtypedItemTypes) do
  87. if v:is_instance(item) then return false end
  88. end
  89. return true
  90. end
  91.  
  92. local function itemHasSyndrome(item)
  93. if itemHasNoSubtype(item) or not itemSyndromeMats then return nil end
  94. local allItemSyndromes={}
  95. for _,material in ipairs(itemSyndromeMats) do
  96. for __,syndrome in ipairs(material.syndrome) do
  97. if syndrome.syn_name == item.subtype.name then table.insert(allItemSyndromes,syndrome) end
  98. end
  99. end
  100. return #allItemSyndromes>0 and allItemSyndromes or false
  101. end
  102.  
  103. local function alreadyHasSyndrome(unit,syn_id)
  104. for _,syndrome in ipairs(unit.syndromes.active) do
  105. if syndrome.type == syn_id then return true end
  106. end
  107. return false
  108. end
  109.  
  110. local function eraseSyndrome(target,syn_id)
  111. for i=#target.syndromes.active-1,0,-1 do
  112. if target.syndromes.active[i].type==syn_id then target.syndromes.active:erase(i) end
  113. end
  114. end
  115.  
  116. 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.
  117. if target==nil then
  118. return nil
  119. end
  120. if alreadyHasSyndrome(target,syn_id) then
  121. local syndrome
  122. for k,v in ipairs(target.syndromes.active) do
  123. if v.type == syn_id then syndrome = v end
  124. end
  125. if not syndrome then return nil end
  126. syndrome.ticks=1
  127. return true
  128. end
  129. local newSyndrome=df.unit_syndrome:new()
  130. local target_syndrome=df.syndrome.find(syn_id)
  131. newSyndrome.type=target_syndrome.id
  132. newSyndrome.year=df.global.cur_year
  133. newSyndrome.year_time=df.global.cur_year_tick
  134. newSyndrome.ticks=1
  135. newSyndrome.unk1=1
  136. for k,v in ipairs(target_syndrome.ce) do
  137. local sympt=df.unit_syndrome.T_symptoms:new()
  138. sympt.ticks=1
  139. sympt.flags=2
  140. newSyndrome.symptoms:insert("#",sympt)
  141. end
  142. target.syndromes.active:insert("#",newSyndrome)
  143. if itemsyndromedebug then
  144. print("Assigned syndrome #" ..syn_id.." to unit.")
  145. end
  146. return true
  147. end
  148.  
  149. local function syndromeIsIndiscriminate(syndrome)
  150. 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)
  151. end
  152.  
  153. local function creatureIsAffected(unit,syndrome)
  154. if syndromeIsIndiscriminate(syndrome) then return true end
  155. local affected = false
  156. local unitraws = df.creature_raw.find(unit.race)
  157. local casteraws = unitraws.caste[unit.caste]
  158. local unitracename = unitraws.creature_id
  159. local castename = casteraws.caste_id
  160. local unitclasses = casteraws.creature_class
  161. for _,unitclass in ipairs(unitclasses) do
  162. for _,syndromeclass in ipairs(syndrome.syn_affected_class) do
  163. if unitclass.value==syndromeclass.value then affected = true end
  164. end
  165. end
  166. for caste,creature in ipairs(syndrome.syn_affected_creature) do
  167. local affected_creature = creature.value
  168. local affected_caste = syndrome.syn_affected_caste[caste].value --slightly evil, but oh well, hehe.
  169. if affected_creature == unitracename and affected_caste == castename then affected = true end
  170. end
  171. for _,unitclass in ipairs(unitclasses) do
  172. for _,syndromeclass in ipairs(syndrome.syn_immune_class) do
  173. if unitclass.value==syndromeclass.value then affected = false end
  174. end
  175. end
  176. for caste,creature in ipairs(syndrome.syn_immune_creature) do
  177. local immune_creature = creature.value
  178. local immune_caste = syndrome.syn_immune_caste[caste].value
  179. if immune_creature == unitracename and immune_caste == castename then affected = false end
  180. end
  181. if itemsyndromedebug then
  182. if not affected then print ("Creature is not affected.") else print("Creature is affected") end
  183. end
  184. return affected
  185. end
  186.  
  187. local function getValidPositions(syndrome)
  188. local returnTable={AffectsHauler=false,AffectsStuckins=false,IsArmorOnly=false,IsWieldedOnly=false,OnlyAffectsStuckins=false}
  189. for k,v in ipairs(syndrome.syn_class) do
  190. if v:find('DFHACK') then
  191. if v.value=="DFHACK_AFFECTS_HAULER" then returnTable.AffectsHauler=true end
  192. if v.value=="DFHACK_AFFECTS_STUCKIN" then returnTable.AffectsStuckins=true end
  193. if v.value=="DFHACK_STUCKINS_ONLY" then returnTable.OnlyAffectsStuckins=true end
  194. if v.value=="DFHACK_WIELDED_ONLY" then returnTable.IsWieldedOnly=true end
  195. if v.value=="DFHACK_ARMOR_ONLY" then returnTable.IsArmorOnly=true end
  196. end
  197. end
  198. return returnTable
  199. end
  200.  
  201. local function itemIsInValidPosition(item_inv, syndrome)
  202. local item = getValidPositions(syndrome)
  203. return 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))
  204. end
  205.  
  206. local function syndromeIsTransformation(syndrome)
  207. for _,effect in ipairs(syndrome.ce) do
  208. if df.creature_interaction_effect_body_transformationst:is_instance(effect) then return true end
  209. end
  210. return false
  211. end
  212.  
  213. local function rememberInventory(unit)
  214. local invCopy = {}
  215. for inv_id,item_inv in ipairs(unit.inventory) do
  216. invCopy[inv_id+1] = {}
  217. local itemToWorkOn = invCopy[inv_id+1]
  218. itemToWorkOn.item = item_inv.item
  219. itemToWorkOn.mode = item_inv.mode
  220. itemToWorkOn.body_part_id = item_inv.body_part_id
  221. end
  222. return invCopy
  223. end
  224.  
  225. local function moveAllToInventory(unit,invTable)
  226. for _,item_inv in ipairs(invTable) do
  227. dfhack.items.moveToInventory(item_inv.item,unit,item_inv.mode,item_inv.body_part_id)
  228. end
  229. end
  230.  
  231. local function addOrRemoveSyndromeDepending(unit,item_inv,syndrome)
  232. if syndromeIsDfHackSyndrome(syndrome) and creatureIsAffected(unit,syndrome) and itemIsInValidPosition(item_inv, syndrome) then
  233. if item_inv then
  234. assignSyndrome(unit,syndrome.id)
  235. else
  236. eraseSyndrome(unit,syndrome.id)
  237. end
  238. end
  239. end
  240.  
  241. eventful=require('plugins.eventful')
  242.  
  243. eventful.enableEvent(eventful.eventType.INVENTORY_CHANGE,5)
  244.  
  245. local function checkAndAddSyndrome(unit_id,new_equip,item_id)
  246. local item = df.item.find(item_id)
  247. local unit = df.unit.find(unit_id)
  248. if unit.flags1.dead then return false end
  249. if itemsyndromedebug then print("Checking unit #" .. unit_id) end
  250. local transformation = false
  251. if itemsyndromedebug then print("checking item #" .. item_id .." on unit #" .. unit_id) end
  252. local itemMaterial=getMaterial(item)
  253. if itemMaterial then
  254. for k,syndrome in ipairs(itemMaterial.syndrome) do
  255. if itemsyndromedebug then print("item has a syndrome, checking if item is valid for application...") end
  256. if syndromeIsTransformation(syndrome) then
  257. unitInventory = rememberInventory(unit)
  258. transformation = true
  259. end
  260. addOrRemoveSyndromeDepending(unit,new_equip,syndrome)
  261. end
  262. end
  263. local itemSyndromes = itemHasSyndrome(item)
  264. if itemSyndromes then
  265. if itemsyndromedebug then print("Item itself has a syndrome, checking if item is in correct position and creature is affected") end
  266. for k,syndrome in ipairs(itemSyndromes) do
  267. if syndromeIsTransformation(syndrome) then
  268. unitInventory = rememberInventory(unit)
  269. transformation = true
  270. end
  271. addOrRemoveSyndromeDepending(unit,new_equip,syndrome)
  272. end
  273. end
  274. if itemsyndromecontaminants and item.contaminants then
  275. if itemsyndromedebug then print("Item has contaminants. Checking for syndromes...") end
  276. for _,contaminant in ipairs(item.contaminants) do
  277. local contaminantMaterial=getMaterial(contaminant)
  278. if contaminantMaterial then
  279. for k,syndrome in ipairs(contaminantMaterial.syndrome) do
  280. if itemsyndromedebug then print("Checking syndrome #" .. k .. "on contaminant #" .. _ .. " on item #" .. item_id .. " on unit #" .. unit_id ..".") end
  281. if syndromeIsTransformation(syndrome) then
  282. unitInventory = rememberInventory(unit)
  283. transformation =true
  284. end
  285. addOrRemoveSyndromeDepending(unit,new_equip,syndrome)
  286. end
  287. end
  288. end
  289. end
  290. if transformation and transformationReEquip then dfhack.timeout(2,"ticks",function() moveAllToInventory(unit,unitInventory) end) end
  291. end
  292.  
  293. eventful.onInventoryChange.itemsyndrome=function(unit_id,item_id,old_equip,new_equip)
  294. checkAndAddSyndrome(unit_id,new_equip,item_id)
  295. end
  296.  
  297. dfhack.onStateChange.itemsyndrome=function(code)
  298. if code==SC_WORLD_LOADED then
  299. itemSyndromeMatIDs = findItemSyndromeInorganic()
  300. if itemSyndromeMatIDs then itemSyndromeMats = getAllItemSyndromeMats(itemSyndromeMatIDs) end
  301. end
  302. end
  303.  
  304. if disable then
  305. eventful.onInventoryChange.itemsyndrome=nil
  306. print("Disabled itemsyndrome.")
  307. disable = false
  308. else
  309. print("Enabled itemsyndrome.")
  310. end
Advertisement
Add Comment
Please, Sign In to add comment