This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
vwowrla/VWoWRLAHelper/event_handler.lua

261 lines
7.4 KiB
Lua
Raw Normal View History

2016-03-06 17:42:18 -05:00
wipe_or_timeout_period = 60
active_encounter = {}
previous_successful_encounters = {}
function undo_swstats_fixlogstring(combat_log_line)
return string.gsub(combat_log_line, " 's", "'s")
end
function sanitize_entity_name(entity_name)
local fixed_name = problem_entity_name_to_fixed_name.problem_to_fixed[entity_name]
if fixed_name then
return fixed_name
else
return entity_name
end
end
function get_original_entity_name(fixed_entity_name)
local original_name = problem_entity_name_to_fixed_name.fixed_to_problem[fixed_entity_name]
if original_name then
return original_name
else
return fixed_entity_name
end
end
function sanitize_entity_names(combat_log_line)
local fixed_line = combat_log_line
for problem_name, fixed_name in pairs(problem_entity_name_to_fixed_name.problem_to_fixed) do
fixed_line = string.gsub(fixed_line, problem_name, fixed_name)
end
return fixed_line
end
function parse_combat_log_line(combat_log_line)
local found_matcher, match
for i, matcher in ipairs(vwowrla_combat_log_patterns) do
for j, pattern in ipairs(matcher.pattern) do
local _, _, m1, m2, m3, m4, m5, m6 = string.find(combat_log_line, pattern)
if m1 then
-- found a matching line. dont need to test anymore patterns.
-- if fn does not exist, don't worry, just return nil (it's probably an ignored pattern)
if matcher.fn then
local result = matcher.fn({m1, m2, m3, m4, m5, m6})
result.event = matcher.event
result.line = combat_log_line
result.timestamp = time()
return result
else
return nil
end
end
end
end
-- no match found
print("*** UNRECOGNIZED LINE***")
print(" >", event, combat_log_line)
return nil
end
function process_parsed_combat_log_line(parsed_line)
if parsed_line.source_name then
parsed_line.source_name = get_original_entity_name(parsed_line.source_name)
end
if parsed_line.source then
parsed_line.source = get_original_entity_name(parsed_line.source)
end
if parsed_line.target_name then
parsed_line.target_name = get_original_entity_name(parsed_line.target_name)
end
end
function in_active_encounter()
return not (active_encounter.name == nil)
end
function touch_entity(entity_name, timestamp)
if not active_encounter.entities[entity_name] then
active_encounter.entities[entity_name] = {
last_activity_at = timestamp,
deaths = {},
resurrections = {}
}
else
active_encounter.entities[entity_name].last_activity_at = timestamp
end
end
function kill_entity(entity_name, timestamp)
active_encounter.entities[entity_name].last_activity_at = timestamp
table.insert(active_encounter.entities[entity_name].deaths, timestamp)
end
function handle_line(parsed_line)
local ev = parsed_line.event
if ev == "ignored" or ev == "other-damage" then
-- nop
elseif ev == "death" then
kill_entity(parsed_line.source_name, parsed_line.timestamp)
else
if parsed_line.source_name then touch_entity(parsed_line.source_name, parsed_line.timestamp) end
if parsed_line.target_name then touch_entity(parsed_line.target_name, parsed_line.timestamp) end
end
end
function count_dead(entity_name)
local entity = active_encounter.entities[entity_name]
if entity then
local num_deaths = table.getn(entity.deaths)
local num_resurrects = table.getn(entity.resurrections)
return num_deaths - num_resurrects
else
return 0
end
end
function find_defined_encounter(entity_name)
for encounter_name, encounter in pairs(defined_encounters) do
for encounter_entity, entity_props in pairs(encounter.entities) do
if entity_name == encounter_entity then return encounter_name end
end
end
return nil
end
function determine_encounter_from_combat_event(parsed_line)
local encounter_name
encounter_name = find_defined_encounter(parsed_line.source_name)
if not encounter_name then encounter_name = find_defined_encounter(parsed_line.target_name) end
return encounter_name
end
function has_previous_successful_encounter(encounter_name)
if not encounter_name then return false end
for i, name in ipairs(previous_successful_encounters) do
if name == encounter_name then return true end
end
return false
end
function aura_is_non_combat_starting(aura_name)
if not aura_name then return false end
for i, name in ipairs(non_combat_starting_auras) do
if name == aura_name then return true end
end
return false
end
function detect_encounter_triggered(parsed_line)
local encounter_name = determine_encounter_from_combat_event(parsed_line)
if not encounter_name then return nil end
if (not has_previous_successful_encounter(encounter_name)) and (not aura_is_non_combat_starting(parsed_line.aura_name)) then
local encounter = defined_encounters[encounter_name]
if encounter.trigger_on_attack then
if parsed_line.attack then return encounter_name end
else
return encounter_name
end
end
return nil
end
function are_all_encounter_mobs_dead()
local encounter = defined_encounters[active_encounter.name]
for entity_name, props in pairs(encounter.entities) do
local num_dead = count_dead(entity_name)
if props.must_kill_count then
if num_dead < props.must_kill_count then return false end
else
if num_dead < props.count then return false end
end
end
return true
end
function has_active_encounter_wiped_or_timed_out(parsed_line)
local timestamp = parsed_line.timestamp
local encounter = defined_encounters[active_encounter.name]
for entity_name, props in pairs(encounter.entities) do
local entity = active_encounter.entities[entity_name]
if entity then
if (timestamp - entity.last_activity_at) < wipe_or_timeout_period then return false end
end
end
return true
end
function detect_encounter_end(parsed_line)
if are_all_encounter_mobs_dead() then
return "killed"
elseif has_active_encounter_wiped_or_timed_out(parsed_line) then
return "wipe-or-timeout"
else
return nil
end
end
function begin_encounter(encounter_name, parsed_line)
local datetime = date()
active_encounter = {
name = encounter_name,
entities = {},
started_at = datetime,
started_at_timestamp = parsed_line.timestamp
}
print("Beginning encounter \"" .. encounter_name .. "\" detected on line: " .. parsed_line.line)
take_raid_buff_snapshot(encounter_name)
end
function end_encounter(parsed_line, end_reason)
local wipe_or_timeout = (end_reason == "wipe-or-timeout")
print("Ending encounter \"" .. active_encounter.name .. "\" detected on line: " .. parsed_line.line)
if wipe_or_timeout then
print("Encounter ending due to wipe or trigger entity activity timeout (unsuccessful encounter kill attempt).")
end
if not wipe_or_timeout then
table.insert(previous_successful_encounters, active_encounter.name);
end
active_encounter = {}
end
function active_encounter_processing(parsed_line)
handle_line(parsed_line)
local end_reason = detect_encounter_end(parsed_line)
if end_reason then
end_encounter(parsed_line, end_reason)
end
end
function out_of_encounter_processing(parsed_line)
local encounter_name = detect_encounter_triggered(parsed_line)
if encounter_name then
begin_encounter(encounter_name, parsed_line)
handle_line(parsed_line)
end
end
function vwowrla_process_combat_event(combat_log_line)
if not combat_log_line then return end
combat_log_line = undo_swstats_fixlogstring(sanitize_entity_names(combat_log_line))
local parsed = parse_combat_log_line(combat_log_line)
if parsed then
process_parsed_combat_log_line(parsed)
if in_active_encounter() then
active_encounter_processing(parsed)
else
out_of_encounter_processing(parsed)
end
end
end