261 lines
7.4 KiB
Lua
261 lines
7.4 KiB
Lua
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
|
|
|