function AIBiasCombo() local items = {} ForEachPreset("AIArchetype", function(item) for _, action in ipairs(item.SignatureActions) do local id = action.BiasId if id and id ~= "" then table.insert_unique(items, id) end end for _, behavior in ipairs(item.Behaviors) do local id = behavior.BiasId if id and id ~= "" then table.insert_unique(items, id) end for _, action in ipairs(behavior.SignatureActions) do local id = action.BiasId if id and id ~= "" then table.insert_unique(items, id) end end end end) return items end DefineClass.AIBiasModification = { __parents = { "PropertyObject" }, properties = { { id = "BiasId", editor = "choice", default = false, items = AIBiasCombo, }, { id = "Effect", editor = "choice", default = "modify", items = { "modify", "disable", "priority" }, }, { id = "Value", editor = "number", default = 0, no_edit = function(self) return self.Effect ~= "modify" end, }, { id = "Period", editor = "number", default = 1, help = "in turns", }, { id = "ApplyTo", editor = "choice", default = "Self", items = { "Self", "Team" }, }, }, } function AIBiasModification:GetEditorView() if self.BiasId and self.BiasId ~= "" then if self.Effect == "modify" then return string.format("%s %+d%% to %s for %d turns", self.BiasId, self.Value, self.ApplyTo, self.Period) elseif self.Effect == "priority" then return string.format("Make %s Priority to %s for %d turns", self.BiasId, self.ApplyTo, self.Period) elseif self.Effect == "disable" then return string.format("Disable %s for %s for %d turns", self.BiasId, self.ApplyTo, self.Period) end end return self.class end DefineClass.AIBiasObj = { __parents = { "PropertyObject" }, properties = { { id = "BiasId", name = "Bias Id", editor = "combo", default = false, items = AIBiasCombo }, { id = "Weight", editor = "number", default = 100, }, { id = "Priority", editor = "bool", default = false, }, { id = "OnActivationBiases", name = "OnActivation Biases", editor = "nested_list", default = false, base_class = "AIBiasModification", inclusive = true, }, }, } MapVar("g_AIBiases", {}) function AIBiasObj:OnActivate(unit) for _, mod in ipairs(self.OnActivationBiases or empty_table) do local id = mod.BiasId if id then local bias = g_AIBiases[id] or {} g_AIBiases[id] = bias local list if mod.ApplyTo == "Self" then list = bias[unit] or {} bias[unit] = list else list = bias[unit.team] or {} bias[unit.team] = list end list[#list + 1] = { end_turn = g_Combat.current_turn + mod.Period, value = mod.Value, disable = mod.Effect == "disable", priority = mod.Effect == "priority", } end end end function AIUpdateBiases() for id, item_mods in pairs(g_AIBiases) do for obj, mods in pairs(item_mods) do local total = 0 mods.disable = false mods.priority = false for i = #mods, 1, -1 do if mods[i].end_turn < g_Combat.current_turn then table.remove(mods, i) else total = total + mods[i].value mods.disable = mods.disable or mods[i].disable mods.priority = mods.priority or mods[i].priority end end mods.total = total end end end function AIGetBias(id, unit) local weight_mod, disable, priority = 100, false, false if id and id ~= "" then local mods = g_AIBiases[id] or empty_table if mods[unit] then weight_mod = weight_mod + mods[unit].total disable = disable or mods[unit].disable priority = priority or mods[unit].priority end if mods[unit.team] then weight_mod = weight_mod + mods[unit.team].total disable = disable or mods[unit.team].disable priority = priority or mods[unit.team].priority end end disable = disable or (weight_mod <= 0) return weight_mod, disable, priority end function AIAltArchetypeBelowHpPercent(unit, alt_archetype, threshold) local archetype = unit.archetype if MulDivRound(unit.HitPoints, 100, unit.MaxHitPoints) < threshold then archetype = alt_archetype end return archetype end function AIAltArchetypeOnAllyDeath(unit, alt_archetype, count) local archetype = unit.archetype local last_dead = unit:GetEffectValue("aa_num_team_dead") or 0 local dead = 0 count = count or 1 for _, other in ipairs(unit.team and unit.team.units) do dead = dead + 1 end if dead >= last_dead + count then unit:SetEffectValue("aa_num_team_dead", dead) archetype = alt_archetype end return archetype end function AIAltArchetypeOnNoEnemyDeath(unit, alt_archetype) local archetype = unit.archetype local last_dead = unit:GetEffectValue("aa_num_dead_enemies") or 0 local dead = 0 local unit_team = unit.team if unit_team then for _, team in ipairs(g_Teams) do if unit_team:IsEnemySide(team) then for _, other in ipairs(team.units) do if other:IsDead() then dead = dead + 1 end end end end end unit:SetEffectValue("aa_num_dead_enemies", dead) if dead == last_dead then archetype = alt_archetype end return archetype end