Code: Select all
local helper = wesnoth.require "lua/helper.lua"
wesnoth.wml_actions.get_global_variable { namespace="optimother_deterministic_offense", from_global="enabled", to_local="detoff_enabled" }
local enabled = wesnoth.get_variable( "detoff_enabled" )
if enabled == true then
wesnoth.wml_actions.event {
name="recruit" ,
id="detoff_recruit_event",
first_time_only=false,
{ "detoff_recruit", {
{ "filter" , { id="$unit.id" }},
} }
}
wesnoth.wml_actions.event {
name="attack" ,
id="detoff_attack_event",
first_time_only=false,
{ "detoff_attack", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}
wesnoth.wml_actions.event {
name="attacker hits" ,
id="detoff_attacker_hits_event",
first_time_only=false,
{ "detoff_attacker_hits", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}
wesnoth.wml_actions.event {
name="attacker misses" ,
id="detoff_attacker_misses_event",
first_time_only=false,
{ "detoff_attacker_misses", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}
wesnoth.wml_actions.event {
name="defender hits" ,
id="detoff_defender_hits_event",
first_time_only=false,
{ "detoff_defender_hits", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}
wesnoth.wml_actions.event {
name="defender misses" ,
id="detoff_defender_misses_event",
first_time_only=false,
{ "detoff_defender_misses", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}
wesnoth.wml_actions.event {
name="attack_end" ,
id="detoff_attack_end_event",
first_time_only=false,
{ "detoff_attack_end", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}
else
wesnoth.wml_actions.event { id="detoff_recruit_event", remove=true }
wesnoth.wml_actions.event { id="detoff_attack_event", remove=true }
wesnoth.wml_actions.event { id="detoff_attacker_hits_event", remove=true }
wesnoth.wml_actions.event { id="detoff_attacker_misses_event", remove=true }
wesnoth.wml_actions.event { id="detoff_defender_hits_event", remove=true }
wesnoth.wml_actions.event { id="detoff_defender_misses_event", remove=true }
wesnoth.wml_actions.event { id="detoff_attack_end_event", remove=true }
end
wesnoth.wml_actions.set_menu_item { id="detoff_control_off" ,
description="Disable deterministic offense" ,
{ "show_if" , {{ "variable", { name="detoff_enabled", equals=true }}}},
{ "command" , {
{ "event", {id="detoff_recruit_event", remove=true }},
{ "event", {id="detoff_attack_event", remove=true }},
{ "event", {id="detoff_attacker_hits_event", remove=true }},
{ "event", {id="detoff_attacker_misses_event", remove=true }},
{ "event", {id="detoff_defender_hits_event", remove=true }},
{ "event", {id="detoff_defender_misses_event", remove=true }},
{ "event", {id="detoff_attack_end_event", remove=true }},
{ "set_variable", {
name="detoff_enabled",
value=false
}},
{ "set_global_variable" ,{
namespace="optimother_deterministic_offense",
to_global="enabled",
from_local="detoff_enabled",
immediate=true
}}
} }
}
wesnoth.wml_actions.set_menu_item{ id="detoff_control" ,
description="Enable deterministic offense" ,
{ "show_if" , {
{ "not" , {
{ "variable" ,{
name="detoff_enabled",
equals=true
}}
}}
}},
{ "command" , {
{"event", {
name="recruit" ,
id="detoff_recruit_event",
first_time_only=false,
{ "detoff_recruit", {
{ "filter" , { id="$unit.id" }},
} }
}},
{"event", {
name="attack" ,
id="detoff_attack_event",
first_time_only=false,
{ "detoff_attack", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}},
{"event", {
name="attacker hits" ,
id="detoff_attacker_hits_event",
first_time_only=false,
{ "detoff_attacker_hits", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}},
{"event", {
name="attacker misses" ,
id="detoff_attacker_misses_event",
first_time_only=false,
{ "detoff_attacker_misses", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}},
{"event", {
name="defender hits" ,
id="detoff_defender_hits_event",
first_time_only=false,
{ "detoff_defender_hits", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}},
{"event", {
name="defender misses" ,
id="detoff_defender_misses_event",
first_time_only=false,
{ "detoff_defender_misses", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}},
{"event", {
name="attack_end" ,
id="detoff_attack_end_event",
first_time_only=false,
{ "detoff_attack_end", {
{ "filter" , { id="$unit.id" }},
{ "filter_second" , { id="$second_unit.id" }}
} }
}},
{ "set_variable", {
name="detoff_enabled",
value=true
}},
{ "set_global_variable" ,{
namespace="optimother_deterministic_offense",
to_global="enabled",
from_local="detoff_enabled",
immediate=true
}}
} }
}
-- local old_unit_status = wesnoth.theme_items.unit_status
-- function wesnoth.theme_items.unit_status()
-- local s = old_unit_status()
-- if enabled then
-- local u = wesnoth.get_displayed_unit()
-- if u then
-- table.insert(s, { "element", {
-- text = "off "
-- -- tooltip = _".."
-- } })
-- table.insert(s, { "element", {
-- text = tostring(u.variables.offense)
-- -- tooltip = _".."
-- } })
-- end
-- end
-- return s
-- end
local function wesnoth_random(min, max)
if not max then min, max = 1, min end
wesnoth.fire("set_variable", { name = "LUA_random", rand = string.format("%d..%d", min, max) })
local res = wesnoth.get_variable "LUA_random"
wesnoth.set_variable "LUA_random"
return res
end
function odo_next_initial_offence(side)
-- local off_key = "detoff_side_offense_" .. tostring(side)
-- local curr_offense = wesnoth.get_variable( off_key ) or 120
-- curr_offense = curr_offense - 20
-- if curr_offense < 1 then
-- curr_offense = curr_offense + 100
-- end
-- wesnoth.set_variable(off_key, curr_offense)
-- return curr_offense
return wesnoth_random(1, 100)
end
function wesnoth.wml_actions.detoff_recruit(cfg)
local filter = helper.get_child(cfg, "filter")
local unit = wesnoth.get_units(filter)[1]
-- wesnoth.message("Recruited unit " .. tostring(curr_offense))
unit.variables.offense = odo_next_initial_offence(unit.side)
end
local dbg = ""
function odo_log(msg)
dbg = dbg .. msg .. "\n"
end
function odo_attacker()
return wesnoth.get_unit(wesnoth.current.event_context.x1, wesnoth.current.event_context.y1)
end
function odo_defender()
return wesnoth.get_unit(wesnoth.current.event_context.x2, wesnoth.current.event_context.y2)
end
function odo_defense(unit, wpn, consider_marksman)
local defense = 100 - wesnoth.unit_defense(unit, wesnoth.get_terrain(unit.x, unit.y))
local specials = wpn and helper.get_child(wpn, "specials")
local cth = specials and helper.get_child(specials, "chance_to_hit")
if cth and cth.id == "magical" then
defense = 30
end
if consider_marksman and cth and cth.id == "marksman" and defense > 40 then
defense = 40
end
-- TODO add support for feral trait
return defense
end
function odo_attacker_defense()
return odo_defense(odo_attacker(), helper.get_child(wesnoth.current.event_context, "second_weapon"), false)
end
function odo_defender_defense()
return odo_defense(odo_defender(), helper.get_child(wesnoth.current.event_context, "weapon"), true)
end
function odo_set_chance(unit, probability)
local chance_def = {id="detoff_effect"}
-- seems like wesnoth is taking maximum value
if probability == 0 then
chance_def.multiply = 0
chance_def.cumulative = true
else
chance_def.value = probability
end
odo_log("setting probability " .. tostring(unit.id) .. " to " .. tostring(probability))
wesnoth.add_modification(unit, "object", {{"effect",
{
apply_to="attack",
remove_specials="detoff_effect",
{"set_specials",
{
mode="append",
{"chance_to_hit", chance_def}
}
}
}
}})
end
function odo_cleanup(unit)
wesnoth.add_modification(unit, "object", {{"effect",
{
apply_to="attack",
remove_specials="detoff_effect",
}
}})
end
function odo_update_offense(unit, sign)
odo_log("updating chances for " .. tostring(unit.id) .. ": " .. tostring(unit.variables.offense) .. " += " .. tostring(sign) .. "*" .. tostring(unit.variables.enemy_defense))
local diff = unit.variables.enemy_defense * sign
unit.variables.offense = (unit.variables.offense or odo_next_initial_offence(unit.side)) + diff
if unit.variables.offense > 100 then
-- wesnoth.message("> 100!")
-- this can happen after attack end
unit.variables.offense = unit.variables.offense - 100
elseif unit.variables.offense > 0 then
-- wesnoth.message("> 0 < 100")
odo_set_chance(unit, 100)
else
-- wesnoth.message("< 0")
odo_set_chance(unit, 0)
unit.variables.offense = unit.variables.offense + 100
end
end
function wesnoth.wml_actions.detoff_attack(cfg)
dbg = ""
local a = odo_attacker()
local b = odo_defender()
a.variables.enemy_defense = odo_defender_defense()
b.variables.enemy_defense = odo_attacker_defense()
odo_log("attacker " .. a.id .. " (o/d) ".. tostring(a.variables.offense) .. "/ " .. tostring(b.variables.enemy_defense))
odo_log("defender " .. b.id .. " (o/d) ".. tostring(b.variables.offense) .. "/ " .. tostring(a.variables.enemy_defense))
odo_update_offense(a, -1)
odo_update_offense(b, -1)
end
function wesnoth.wml_actions.detoff_attacker_hits(cfg)
local a = odo_attacker()
odo_log("attacker hit: " .. a.id)
odo_update_offense(a, -1)
end
function wesnoth.wml_actions.detoff_attacker_misses(cfg)
local a = odo_attacker()
odo_log("attacker miss: " .. a.id)
odo_update_offense(a, -1)
end
function wesnoth.wml_actions.detoff_defender_hits(cfg)
local b = odo_defender()
odo_log("defender hit: " .. b.id)
odo_update_offense(b, -1)
end
function wesnoth.wml_actions.detoff_defender_misses(cfg)
local b = odo_defender()
odo_log("defender miss: " .. b.id)
odo_update_offense(b, -1)
end
function wesnoth.wml_actions.detoff_attack_end(cfg)
local a = odo_attacker()
local b = odo_defender()
odo_update_offense(a, 1)
odo_update_offense(b, 1)
odo_cleanup(a)
odo_cleanup(b)
-- wesnoth.message(dbg)
end