|
local class_gossip = { |
|
["PDAEmailsClass"] = "Emails", |
|
["PDANotesClass"] = "Notes", |
|
["PDAQuestsClass"] = "Quests", |
|
} |
|
|
|
local function GetAlteredMode(mode) |
|
if mode == "IModeExploration" then |
|
if gv_CurrentSectorId and gv_Sectors[gv_CurrentSectorId].conflict then |
|
mode = "IModeExploration-Conflict" |
|
end |
|
end |
|
|
|
return mode |
|
end |
|
|
|
function OnMsg.DialogOpen(dlg, init_mode) |
|
if dlg:IsKindOf("InGameInterface") then |
|
NetGossip("Open", GetAlteredMode(init_mode), GetCurrentPlaytime()) |
|
end |
|
local gossip = class_gossip[dlg.class] |
|
if gossip then |
|
NetGossip(gossip, "Open", GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
if dlg:IsKindOf("SatelliteConflictClass") then |
|
local context = dlg:GetContext() |
|
if context.autoResolve then |
|
local sector = context and context.sector or context |
|
if sector and sector.Id and IsAutoResolveEnabled(sector.Id) then |
|
NetGossip("AutoResolve", "Open", sector.Id, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
end |
|
end |
|
|
|
function OnMsg.AutoResolveChoice(sector_id, choice) |
|
NetGossip("AutoResolve", "Choice", sector_id, choice, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.AutoResolvedConflict(sector_id, player_outcome) |
|
NetGossip("AutoResolve", "Outcome", sector_id, player_outcome, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.DialogClose(dlg, result) |
|
if dlg:IsKindOf("InGameInterface") then |
|
NetGossip("Close", GetAlteredMode(dlg.mode), GetCurrentPlaytime()) |
|
end |
|
local gossip = class_gossip[dlg.class] |
|
if gossip then |
|
NetGossip(gossip, "Close", GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
|
|
|
|
function OnMsg.DialogSetMode(dlg, mode, mode_param, old_mode) |
|
if dlg:IsKindOf("InGameInterface") then |
|
NetGossip("ChangeMode", GetAlteredMode(old_mode), GetAlteredMode(mode), GetCurrentPlaytime()) |
|
end |
|
end |
|
|
|
|
|
function OnMsg.IGIModeChanging(old_mode, mode) |
|
NetGossip("ChangeMode", GetAlteredMode(old_mode), GetAlteredMode(mode), GetCurrentPlaytime()) |
|
end |
|
|
|
function OnMsg.ConflictEnd() |
|
local dlg = GetInGameInterface() |
|
if dlg.Mode == "IModeExploration" then |
|
NetGossip("ChangeMode", GetAlteredMode("IModeExploration-Conflict"), "IModeExploration", GetCurrentPlaytime()) |
|
end |
|
end |
|
|
|
function OnMsg.GameStateChanged(changed) |
|
NetGossip("GameStateChanged", changed, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.NewMap() |
|
local map_size = point(terrain.GetMapSize()) |
|
NetGossip("map-Zulu", GetMapName(), MapLoadRandom, map_size, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.NewGame() |
|
NetGossip("AssetsRevision", AssetsRevision, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
local active_rules = Game and Game.game_rules or empy_table |
|
local all_rules = table.keys(GameRuleDefs, "sorted") |
|
NetGossip("NewGameRules", active_rules, all_rules, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.SectorSideChanged(sector_id, old_side, new_side) |
|
NetGossip("SectorSideChanged", sector_id, old_side, new_side, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
GameVar("gv_MidGame", false) |
|
|
|
local s_ErnySurroundingSectors = {"H2", "G1", "G2", "G3", "G4", "G5", "H5", "I5", "I4", "J4", "J3", "J2", "J1"} |
|
local s_IsErnySourroundingSector = {} |
|
for _, sector in ipairs(s_ErnySurroundingSectors) do |
|
s_ErnySurroundingSectors[sector] = true |
|
end |
|
|
|
function OnMsg.SquadSectorChanged(squad) |
|
if not gv_MidGame and s_ErnySurroundingSectors[squad.CurrentSector] then |
|
local team = table.find_value(g_Teams, "side", squad.Side) |
|
if team and team.control == "UI" then |
|
gv_MidGame = true |
|
local campaign = GetCurrentCampaignPreset() |
|
NetGossip("CampaignStage", campaign and campaign.id, "mid", GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
local team = table.find_value(g_Teams, "side", squad.Side) |
|
local control = team and team.control or "" |
|
NetGossip("SquadSectorChanged", squad.UniqueId, squad.CurrentSector, squad.PreviousSector, squad.Side, control, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.QuestParamChanged(quest_id, var_id, prev_val, new_val) |
|
if quest_id == "04_Betrayal" and var_id == "TriggerWorldFlip" and not prev_val and new_val then |
|
local campaign = GetCurrentCampaignPreset() |
|
NetGossip("CampaignStage", campaign and campaign.id, "late", GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
if var_id == "Failed" or var_id == "Given" or var_id == "Completed" then |
|
if new_val then |
|
NetGossip("Quest", quest_id, var_id, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
if quest_id == "06_Endgame" and var_id == "Completed" then |
|
local outcome = {} |
|
local quest = QuestGetState(quest_id) |
|
for key, value in pairs(quest) do |
|
if value and string.starts_with(key, "Outro_") then |
|
table.insert(outcome, key) |
|
end |
|
end |
|
NetGossip("GameEnd", outcome, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
elseif var_id == "NotStarted" then |
|
if not new_val then |
|
NetGossip("Quest", quest_id, "Started", GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
end |
|
|
|
function OnMsg.OpenPDA() |
|
NetGossip("PDA", "Open", GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.ClosePDA() |
|
NetGossip("PDA", "Close", GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
GameVar("gv_LastSatelliteSnapshot", 0) |
|
|
|
function OnMsg.NewHour() |
|
gv_LastSatelliteSnapshot = (gv_LastSatelliteSnapshot < 6) and (gv_LastSatelliteSnapshot + 1) or 1 |
|
|
|
local mercs = gv_Squads and g_CurrentSquad and gv_Squads[g_CurrentSquad] and gv_Squads[g_CurrentSquad].units or empty_table |
|
local units, mercs_data = {}, {controlled_mercs = 0} |
|
for _, merc in ipairs(mercs) do |
|
local unit = g_Units[merc] |
|
if IsValid(unit) then |
|
table.insert(units, unit) |
|
table.insert(mercs_data, {merc_id = unit.session_id, level = unit:GetLevel()}) |
|
end |
|
end |
|
local meds_amount, _, meds_list = GetMedsAndOwners(units) |
|
for merc, amount in pairs(meds_list) do |
|
local merc_data = table.find_value(mercs_data, "merc_id", merc) |
|
mercs_data.meds = amount |
|
end |
|
local squad_locs = {controlled_squads = 0, squad_side = {}} |
|
for _, squad in pairs(gv_Squads or empty_table) do |
|
squad_locs[squad.UniqueId] = squad.CurrentSector |
|
squad_locs.squad_side[squad.UniqueId] = squad.Side |
|
local team = table.find_value(g_Teams, "side", squad.Side) |
|
if team and team.control == "UI" then |
|
squad_locs.controlled_squads = squad_locs.controlled_squads + 1 |
|
mercs_data.controlled_mercs = mercs_data.controlled_mercs + #(squad.units or empty_table) |
|
end |
|
end |
|
|
|
if gv_LastSatelliteSnapshot == 1 then |
|
|
|
local game_settings = {GameDifficulty = Game.game_difficulty, ForgivingMode = IsGameRuleActive("ForgivingMode") or false} |
|
NetGossip("SatelliteSnapshot", "Mercs", mercs_data, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
NetGossip("SatelliteSnapshot", "Money", Game and Game.Money, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
NetGossip("SatelliteSnapshot", "Game", game_settings, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
NetGossip("SatelliteSnapshot", "SquadLocations", squad_locs, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
local function GetCombatData(combat, end_combat) |
|
local combat_data = { |
|
combat_id = combat.combat_id, |
|
sector_id = gv_CurrentSectorId, |
|
morale = g_Teams[g_CurrentTeam].morale, |
|
stealth_attack_start = combat.stealth_attack_start or nil, |
|
last_attack_kill = combat.last_attack_kill or nil, |
|
dead = {} |
|
} |
|
|
|
local total_hp_loss, total_hp_healed = 0, 0 |
|
for _, unit in ipairs(g_Units) do |
|
if unit:IsMerc() then |
|
local weapon1, weapon2 = unit:GetActiveWeapons() |
|
table.insert(combat_data, { |
|
merc_id = unit.session_id, |
|
vital_status = unit:IsDead() and "Dead" or "Alive", |
|
hp = unit.HitPoints, |
|
max_hp = unit.MaxHitPoints, |
|
weapon1 = weapon1 and weapon1.class, |
|
weapon2 = weapon2 and weapon2.class, |
|
hp_loss = end_combat and combat.hp_loss[unit.session_id] or nil, |
|
hp_healed = end_combat and combat.hp_healed[unit.session_id] or nil, |
|
level = unit:GetLevel(), |
|
side = unit.team and unit.team.side or nil, |
|
}) |
|
end |
|
total_hp_loss = total_hp_loss + (combat.hp_loss and combat.hp_loss[unit.session_id] or 0) |
|
total_hp_healed = total_hp_healed + (combat.hp_healed and combat.hp_healed[unit.session_id] or 0) |
|
if unit:IsDead() then |
|
table.insert(combat_data.dead, { |
|
merc_id = unit.session_id, |
|
loc = unit:GetPos(), |
|
raw_damage = unit.on_die_hit_descr and unit.on_die_hit_descr.raw_damage or nil, |
|
}) |
|
end |
|
end |
|
|
|
if end_combat then |
|
local team = GetCampaignPlayerTeam() |
|
combat_data.outcome = (not team or team:IsDefeated()) and "Defeated" or "Victorious" |
|
combat_data.turns = combat.current_turn |
|
combat_data.combat_time = combat.combat_time |
|
combat_data.total_hp_loss = total_hp_loss |
|
combat_data.total_hp_healed = total_hp_healed |
|
combat_data.out_of_ammo = next(combat.out_of_ammo or empty_table) and combat.out_of_ammo or nil |
|
end |
|
|
|
return combat_data |
|
end |
|
|
|
function OnMsg.CombatStart(_, combat) |
|
NetGossip("Combat", "Start", GetCombatData(combat), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.CombatEnd(combat) |
|
NetGossip("Combat", "End", GetCombatData(combat, "end combat"), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.OnHeal(patient, hp, medkit, healer) |
|
if IsKindOf(patient, "Unit") then |
|
NetGossip("Heal", patient.session_id, hp, medkit and medkit.class, IsKindOf(healer, "Unit") and healer.session_id, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
|
|
function OnMsg.TurnEnded(team, turn) |
|
local mercs_data = {} |
|
for _, unit in ipairs(g_Units) do |
|
if IsMerc(unit) then |
|
local protected = not not unit:GetStatusEffect("Protected") |
|
local entry = g_Combat and g_Combat.turn_dist_travelled and g_Combat.turn_dist_travelled[unit.session_id] |
|
table.insert(mercs_data, { |
|
merc_id = unit.session_id, |
|
loc = unit:GetPos(), |
|
in_cover = protected, |
|
stance = unit.stance, |
|
dist_travelled = entry and entry.total_dist |
|
}) |
|
end |
|
end |
|
NetGossip("TurnEnded", turn, mercs_data, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.StatIncreased(unit, stat, amount, reason) |
|
if reason == "FieldExperience" then |
|
|
|
NetGossip("StatIncreased", unit.session_id, stat, amount, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
|
|
function OnMsg.OutOfAmmo(unit, weapon, fired, jammed) |
|
NetGossip("OutOfAmmo", unit.session_id, weapon.class, fired and "Fired" or nil, jammed and "Jammed" or nil, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.TrapDisarm(trap, unit, success) |
|
if success then |
|
NetGossip("Trap", "Disarm", gv_CurrentSectorId, trap.class, trap:GetPos(), unit.session_id, unit:GetPos(), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
else |
|
NetGossip("Trap", "Trigger", gv_CurrentSectorId, trap.class, trap:GetPos(), unit.session_id, unit:GetPos(), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
|
|
local function GetMercStatusData(merc) |
|
local merc_data = {merc_id = merc.session_id} |
|
local perks = merc:GetAttributes() |
|
for _, perk in ipairs(perks) do |
|
merc_data[perk.id] = merc[perk.id] |
|
end |
|
merc_data.Level = merc:GetLevel() |
|
|
|
return merc_data |
|
end |
|
|
|
function OnMsg.MercHireStatusChanged(merc, old_status, new_status) |
|
if new_status == "Hired" then |
|
NetGossip("Merc", "Hired", GetMercStatusData(merc), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
if old_status == "Hired" and (new_status == "Available" or new_status == "Dead" or not new_status) then |
|
NetGossip("Merc", "CareerEnd", GetMercStatusData(merc), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
|
|
function OnMsg.CampaignEnd(campaign_name) |
|
for _, unit in ipairs(g_Units) do |
|
if unit:IsMerc() then |
|
NetGossip("Merc", "CareerEnd", GetMercStatusData(unit), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
end |
|
end |
|
|
|
function OnMsg.DifficultyChange() |
|
NetGossip("Game", "Difficulty", Game.game_difficulty, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.ChangeGameRule(rule, value) |
|
NetGossip("Game", "Rule", rule, value, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.OperationChanged(merc, prev_operation, operation, interrupted) |
|
local squad = merc.Squad and gv_Squads[merc.Squad] |
|
local loc = squad and squad.CurrentSector |
|
NetGossip("SatViewActivity", merc.session_id, prev_operation and prev_operation.id, operation and operation.id, loc, interrupted, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.UnitLeveledUp(unit) |
|
NetGossip("LevelUp", unit.session_id, unit:GetLevel(), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.RunCombatAction(action_id, unit, ap) |
|
NetGossip("RunCombatAction", action_id, unit.session_id, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.PerksLearned(unit, perks) |
|
NetGossip("PerksLearned", unit.session_id, perks, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.Attack(action, results, attack_args) |
|
local attacker = attack_args.obj |
|
local target = attack_args.target |
|
if not IsValid(target) then return end |
|
local attack_pos = IsValid(attacker) and attacker:GetPos() or (IsPoint(attacker) and attacker) |
|
local target_pos = IsValid(target) and target:GetPos() or (IsPoint(target) and target) |
|
if not attack_pos and results.explosion then |
|
attack_pos = results.start_pos |
|
end |
|
local attacker_is_unit = IsKindOf(attacker, "Unit") |
|
local target_is_unit = IsKindOf(target, "Unit") |
|
local attack_descr = { |
|
attack_type = (type(action) == "string") and action or (action.id or "Unknown"), |
|
attacker = attacker_is_unit and attacker.session_id or nil, |
|
attacker_type = attacker.Affiliation, |
|
attacker_side = attacker_is_unit and attacker.team and attacker.team.side or nil, |
|
target = target_is_unit and target.session_id or nil, |
|
target_side = target_is_unit and target.team and target.team.side or nil, |
|
aim_ap = attack_args.aim, |
|
weapon = attack_args.weapon and attack_args.weapon.class, |
|
weapon_type = attack_args.weapon and attack_args.weapon.WeaponType, |
|
body_part_aim = attack_args.target_spot_group, |
|
total_damage = results.total_damage, |
|
attack_pos = attack_pos or nil, |
|
target_pos = target_pos or nil, |
|
sector = gv_CurrentSectorId, |
|
} |
|
NetGossip("Attack", attack_descr, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function GossipVR(response_data, unitName) |
|
NetGossip("VoiceResponse", "Play", response_data.id, response_data.group, unitName, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.GenerateLoot(loot_def, items, result) |
|
NetGossip("GenerateLoot", GameTime(), loot_def.id, table.imap(items, "class"), GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.CashInItem(item, amount, total_money) |
|
NetGossip("CashInItem", item.class, total_money, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.UnitDied(unit, attacker, results) |
|
NetGossip("UnitDied", unit.session_id, attacker and attacker.session_id, results, gv_CurrentSectorId, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |
|
|
|
function OnMsg.ThrowGrenade(unit, grenade, attacks) |
|
NetGossip("ThrowGrenade", unit.session_id, grenade and grenade.class, attacks, gv_CurrentSectorId, GetCurrentPlaytime(), Game and Game.CampaignTime) |
|
end |