Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function resolvers.calc.talented_ai_tactic(t, e)
- local old_on_added_to_level = e.on_added_to_level
- e.on_added_to_level = function(self, level, x, y)
- if old_on_added_to_level then old_on_added_to_level(self, level, x, y) end
- print(" # talented_ai_tactic resolver function for", e.name, "level=", e.level)
- local tactic_total = t[2] or t.tactic_total or 10 --want tactic weights to total 10
- local weight_power = t[3] or t.weight_power or 0.5 --smooth out tactical weights
- local tacs_offense = {attack=1, attackarea=1}
- local tacs_close = {closein=1, go_melee=1}
- local tacs_defense = {escape=1, defend=1, heal=1, protect=1, disable = 1}
- local tac_types = {type="melee",type = "ranged", type="tank", type="survivor"}
- local tactic, tactical = {}, {total = 0}
- local count = {talents = 0, atk_count = 0, atk_value = 0, total_range = 0,
- atk_melee = 0, melee_value = 0, range_value = 0, atk_range = 0,
- escape = 0, close = 0, def_count = 0, def_value = 0, disable=0}
- local do_count, val
- local tac_count = #table.keys(tacs_offense) + #table.keys(tacs_close) + #table.keys(tacs_defense)
- -- go through all talents, adding up all the tactical weights from the tactical tables weighted by talent level
- local tal
- local get_weight = function(wt)
- local val = 0
- if type(wt) == "function" then
- wt = wt(e, tal, e) -- try to target self for effectiveness
- end
- if type(wt) == "number" then return wt
- elseif type(wt) == "table" then
- for _, n in pairs(wt) do
- val = math.max(val, get_weight(n))
- end
- if val == 0 then val = 2 end
- end
- return tonumber(val) or 0
- end
- for tid, tl in pairs(e.talents) do
- local get_weight2 = function(wt)
- local val = 0
- if type(wt) == "function" then
- wt = wt(e, tal, e) -- try to target self for effectiveness
- end
- if type(wt) == "number" then return wt
- elseif type(wt) == "table" then
- for _, n in pairs(wt) do
- val = math.max(val, get_weight(n))
- end
- if val == 0 then val = 2 end
- end
- return tonumber(val) or 0
- end
- tal = e:getTalentFromId(tid)
- local range = e:getTalentRange(tal)
- if range > 0 then range = range + e:getTalentRadius(tal)*2/3 end
- if tal and tal.tactical then
- print(" # tactical table for talent", tal.name, "range", range)
- table.print(tal.tactical)
- do_count = false
- for tt, wt in pairs(tal.tactical) do
- val = get_weight(wt, e)
- --[[
- val = 0
- if type(wt) == "function" then
- val = wt(e, tal, e) -- try to target self for effectiveness
- end
- if type(wt) == "number" then val = wt
- elseif type(wt) == "table" then
- for _, n in pairs(wt) do
- if type(n) == "number" then val = math.max(val, n) end
- end
- if val == 0 then val = 2 end
- end
- val = tonumber(val) or 0
- --]]
- print(" # ", tt, "wt=", val)
- tactical[tt] = (tactical[tt] or 0) + val -- sum up all the input weights
- if tacs_offense[tt] then
- do_count = true
- count.atk_count = count.atk_count + 1
- val = val * tacs_offense[tt]
- count.atk_value = count.atk_value + val
- count.total_range = count.total_range + range
- if range >= 2 then
- count.atk_range = count.atk_range + 1
- count.range_value = count.range_value + val
- else
- count.atk_melee = count.atk_melee + 1
- count.melee_value = count.melee_value + val
- end
- end
- if tacs_defense[tt] then
- do_count = true
- count.def_count = count.def_count + 1
- count.def_value = count.def_value + tacs_defense[tt] * val
- if tt == "escape" then count.escape = count.escape + 1 end
- end
- if tacs_close[tt] then
- do_count = true
- count.close = count.close + 1
- end
- if do_count then
- count.talents = count.talents + 1
- tactical.total = tactical.total + val
- tactic[tt] = (tactic[tt] or 0) + val -- sum up only relevant weights
- end
- end
- end
- end
- -- collapse tactics ATTACK, ATTACKAREA by range
- -- compute tactical weights{disable=3, escape=0, closein=2, defend=2, protect=2, heal=3, go_melee=1} based on weights
- local ttype = "test"
- -- normalize weights
- count.avg_attack_range = count.total_range/count.atk_count
- local norm_total = 0
- for tt, wt in pairs(tactic) do
- -- tactic[tt] = (tactic[tt]/count.talents)
- -- tactic[tt] = (tactic[tt]/tactical.total) - count.talents
- local ave_weight = (tactic[tt]+count.talents)/count.talents
- local ave_xweight = ave_weight^weight_power - 1
- if ave_xweight > 1/tac_count then
- tactic[tt] = ave_weight
- norm_total = norm_total + ave_weight
- else
- tactic[tt] = nil -- defaults to a weight of 1 in the tactical ai
- end
- end
- for tt, _ in pairs(tactic) do
- tactic[tt] = tactic[tt]*tactic_total/norm_total
- if tactic[tt] < 1 then tactic[tt] = nil end -- defaults to a weight of 1 in the tactical ai
- end
- -- Minimum range?
- if count.atk_range + count.escape > count.atk_melee + count.close and count.range_value /(count.melee_value + 1) > 1.5 then
- tactic.safe_range = math.max(2, math.ceil(count.avg_attack_range/2)) --only for ranged/survivor
- end
- -- compute "tank"/"survivor" based on "escape","defend", and "heal" weights
- tactic.tactical_sum=tactical tactic.count = count
- tactic.type = ttype
- tactic.tac_count = tac_count
- tactic.level = e.level
- for tac, wt in pairs(tactic) do print(" ##", tac, wt) end
- self.ai_tactic_resolved = true
- self.ai_tactic = tactic
- -- self.on_added_to_level = nil
- return tactic
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement