-- Assigns claspects based on personality
personality_weights = {
aspects = {
breath = {
ANXIETY = -3,
ANGER = 0,
DEPRESSION = -2,
SELF_CONSCIOUSNESS = -5,
IMMODERATION = 2,
VULNERABILITY = 0,
FRIENDLINESS = 2,
GREGARIOUSNESS = 3,
ASSERTIVENESS = 1,
ACTIVITY_LEVEL = 2,
ASSERTIVENESS = 3,
EXCITEMENT_SEEKING = 6,
CHEERFULNESS = 4,
IMAGINATION = 1,
ARTISTIC_INTEREST = 1,
EMOTIONALITY = 1,
ADVENTUROUSNESS = 6,
INTELLECTUAL_CURIOUSITY = 1,
LIBERALISM = 0,
TRUST = 1,
STRAIGHTFORWARDNESS = 2,
ALTRUISM = 1,
COOPERATION = 2,
MODESTY = 0,
SYMPATHY = 0,
SELF_EFFICACY = 5,
ORDERLINESS = -2,
DUTIFULNESS = -3,
ACHIEVEMENT_STRIVING = 1,
SELF_DISCIPLINE = -1,
CAUTIOUSNESS = 1},
--23 more of that--
}
local function getTotal(tbl)
local total = {0,0}
for k,v in ipairs(tbl) do
if v>0
then
total[1]=v+total[1]
else
total[2]=v+total[2]
end
end
return total
end
local function getSignlessTotal(tbl)
local total
for k,v in ipairs(tbl) do
total=v+total
end
return total
end
local function getWeightAverages()
local weightAverages={{0,0},{0,0}}
for k,aspect in ipairs(personality_weights.aspects) do
local total = getTotal(aspect)
for i=1,2 do
weightAverages[1][i]=weightAverages[1][i]+total[i]
end
end
for i=1,2 do
weightAverages[1][i]=weightAverages[1][i]/12
end
for k,class in ipairs(personality_weights.classes) do
local total = getTotal(class)
for i=1,2 do
weightAverages[2][i]=weightAverages[2][i]+total[i]
end
end
for i=1,2 do
weightAverages[2][i]=weightAverages[2][i]/12
end
return weightAverages
end
function fixWeights() --this is here so I don't have to think about my weights meaning anything :D What's important is that they stay similar relative to one another, which this preserves.
local weightAverages=getWeightAverages()
for k,aspect in pairs(personality_weights.aspects) do
local total=getTotal(aspect)
for kk,trait in pairs(aspect) do
if trait>0
then
trait=(weightAverages[1][1]/total)*trait
else
trait=(weightAverages[1][2]/total)*trait --no check for 0 specifically because the equation will come out to 0 anyway
end
end
end
for k,class in ipairs(personality_weights.classes) do
local total=getTotal(class)
for kk,trait in ipairs(class) do
if trait>0
then
trait=(weightAverages[2][1]/total)*trait
else
trait=(weightAverages[2][2]/total)*trait --no check for 0 specifically because the equation will come out to 0 anyway
end
end
end
end
fixWeights()
local function returnFirstInTable(tbl,k)
for k,v in ipairs(tbl) do
if k then return k else return v end
end
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 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. I have used this so much ;_;
if df.isnull(target) then
return nil
end
if alreadyHasSyndrome(target,syn_id) then
return true --I can omit the reset because they aren't going to ever lose their claspect
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=1
newSyndrome.unk1=1
for k,v in ipairs(target_syndrome.ce) do
local sympt=df.unit_syndrome.T_symptoms:new()
sympt.ticks=1
sympt.flags=2
newSyndrome.symptoms:insert("#",sympt)
end
target.syndromes.active:insert("#",newSyndrome)
return true
end
function assignClaspect(unit,creatureClass,creatureAspect) --Putting all of the claspect combos into a single table would be... problematic.
for k,v in ipairs(df.global.world.raws.syndromes.all) do
if string.find(v.syn_name,creatureClass) and string.find(v.syn_name,creatureAspect) then
assignSyndrome(unit,k)
end
end
end
function unitAlreadyHasClaspect(unit)
for _,syndrome in ipairs(unit.syndromes.active) do
if string.find(df.global.world.raws.syndromes.all[syndrome.type].name,"hero") then return true end
end
return false
end
function makeClaspect(unit)
if unitAlreadyHasClaspect(unit) then return nil end
local personality=unit.status.current_soul.traits
local creatureWeights={{},{}}
for i=1,2 do
for claspect in pairs(personality_weights[i]) do
for trait in pairs(claspect) do --my favorite part is how this would probably work the same if I replaced "aspect" with "personality"
creatureWeights[i][claspect][trait]=personality[trait]*claspect[trait]
end
end
table.sort(creatureWeights[i],function(a,b) return getSignlessTotal(a)>getSignlessTotal(b) end)
end
local creatureAspect = returnFirstInTable(creatureWeights[1],true)
local creatureClass = returnFirstInTable(creatureWeights[2],true)
assignClaspect(unit,creatureClass,creatureAspect)
end
dfhack.onStateChange.claspect = function(code)
if code==SC_WORLD_LOADED then
dfhack.timeout(1,'ticks',monthlyClaspectAssign)
end
end
function monthlyClaspectAssign()
for _,unit in ipairs(df.global.world.units.active) do
makeClaspect(unit)
end
end
dfhack.onStateChange.claspect()
Wrote this (what is basically Fortbent 6 by itself) in one day. Woohoo!
Next step: determining if it works! That returnFirstInTable function is especially suspect.