dfhack/library/lua/syndrome-util.lua

186 lines
5.2 KiB
Lua

--lua/syndrome-util.lua
--author expwnent
--some utilities for adding syndromes to units
local _ENV = mkmodule("syndrome-util")
local utils = require("utils")
function findUnitSyndrome(unit,syn_id)
for index,syndrome in ipairs(unit.syndromes.active) do
if syndrome['type'] == syn_id then
return syndrome
end
end
return nil
end
--usage: syndromeUtil.ResetPolicy.DoNothing, syndromeUtil.ResetPolicy.ResetDuration, etc
ResetPolicy = ResetPolicy or utils.invert({
"DoNothing",
"ResetDuration",
"AddDuration",
"NewInstance"
})
function eraseSyndromeData(unit,syndromeId,oldestFirst)
for i = (oldestFirst and 0) or #unit.body.wounds-1,(oldestFirst and #unit.body.wounds-1) or 0,(oldestFirst and 1) or -1 do
if unit.body.wounds[i].syndrome_id == syndromeId then
unit.body.wounds:erase(i)
break
end
end
end
function eraseSyndrome(unit,syndromeId,oldestFirst)
local i1
local iN
local d
if oldestFirst then
i1 = 0
iN = #unit.syndromes.active-1
d = 1
else
i1 = #unit.syndromes.active-1
iN = 0
d = -1
end
local syndromes = unit.syndromes.active
for i=i1,iN,d do
if syndromes[i]['type'] == syndromeId then
eraseSyndromeData(unit,syndromeId,oldestFirst)
syndromes:erase(i)
return true
end
end
return false
end
local function eraseSyndromeClassHelper(unit,synclass)
for i,unitSyndrome in ipairs(unit.syndromes.active) do
local syndrome = df.syndrome.find(unitSyndrome.type)
for _,class in ipairs(syndrome.syn_class) do
if class.value == synclass then
eraseSyndromeData(unit,syndrome.id)
unit.syndromes.active:erase(i)
return true
end
end
end
return false
end
function eraseSyndromeClass(unit,synclass)
local count=0
while eraseSyndromeClassHelper(unit,synclass) do
count = count+1
end
return count
end
function eraseSyndromes(unit,syndromeId)
local count=0
while eraseSyndrome(unit,syndromeId,true) do
count = count+1
end
return count
end
--target is a df.unit, syndrome is a df.syndrome, resetPolicy is one of syndromeUtil.ResetPolicy
--if the target has an instance of the syndrome already, the reset policy takes effect
--returns true if the unit did not have the syndrome before calling and false otherwise
function infectWithSyndrome(target,syndrome,resetPolicy)
local oldSyndrome = findUnitSyndrome(target,syndrome.id)
if oldSyndrome == nil or resetPolicy == nil or resetPolicy == ResetPolicy.NewInstance then
local unitSyndrome = df.unit_syndrome:new()
unitSyndrome.type = syndrome.id
unitSyndrome.year = df.global.cur_year
unitSyndrome.year_time = df.global.cur_year_tick
unitSyndrome.ticks = 0
unitSyndrome.wound_id = -1
for k,v in ipairs(syndrome.ce) do
local symptom = df.unit_syndrome.T_symptoms:new()
symptom.quantity = 0
symptom.delay = 0
symptom.ticks = 0
symptom.flags.active = true
unitSyndrome.symptoms:insert("#",symptom)
end
target.syndromes.active:insert("#",unitSyndrome)
elseif resetPolicy == ResetPolicy.DoNothing then
elseif resetPolicy == ResetPolicy.ResetDuration then
for k,symptom in ipairs(oldSyndrome.symptoms) do
symptom.ticks = 0
end
oldSyndrome.ticks = 0
elseif resetPolicy == ResetPolicy.AddDuration then
for k,symptom in ipairs(oldSyndrome.symptoms) do
--really it's syndrome.ce[k].end, but lua doesn't like that because keywords
if syndrome.ce[k]["end"] ~= -1 then
symptom.ticks = symptom.ticks - syndrome.ce[k]["end"]
end
end
else qerror("Bad reset policy: " .. resetPolicy)
end
return (oldSyndrome == nil)
end
function isValidTarget(unit,syndrome)
--mostly copied from itemsyndrome, which is based on autoSyndrome
if
#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
then
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 unitCasteName = 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 affectedCreature = creature.value
local affectedCaste = syndrome.syn_affected_caste[caste].value
if affectedCreature == unitRaceName and (affectedCaste == unitCasteName or affectedCaste == "ALL") 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 immuneCreature = creature.value
local immuneCaste = syndrome.syn_immune_caste[caste].value
if immuneCreature == unitRaceName and (immuneCaste == unitCasteName or immuneCaste == "ALL") then
affected = false
end
end
return affected
end
function infectWithSyndromeIfValidTarget(target,syndrome,resetPolicy)
if isValidTarget(target,syndrome) then
infectWithSyndrome(target,syndrome,resetPolicy)
return true
else
return false
end
end
return _ENV