using EDPlayerJournal.Entries; namespace EDPlayerJournal.BGS; internal class TransactionParserContext { /// /// List of commander names seen in the logs. May be empty. /// public List Commanders { get; } = new(); /// /// Name of the current system the player is in. /// public string? CurrentSystem { get; set; } /// /// 64 bit address of the current system. /// public ulong? CurrentSystemAddress { get; set; } /// /// Controlling faction of the current system. /// public string? ControllingFaction { get; set; } /// /// Name of the current station the player is docked at. /// public string? CurrentStation { get; set; } /// /// Faction that owns the current station. /// public string? StationOwner { get; set; } /// /// Whether the player is currently on foot, or in an SRV/ship. /// public bool IsOnFoot { get; set; } = false; /// /// Type of the current instance after a SupercruiseDestinationDropEntry. /// This is null if there is no current instance, or the current instance /// is not known. /// public string? CurrentInstanceType { get; set; } = null; /// /// Last faction that awarded the player with combat bonds. /// public string? LastRecordedAwardingFaction { get; set; } /// /// Highest combat bond seen so far. /// public ulong? HighestCombatBond { get; set; } public bool HaveSeenCapShip { get; set; } = false; public bool HaveSeenAlliedCaptain { get; set; } = false; public bool HaveSeenEnemyCaptain { get; set; } = false; public bool HaveSeenSpecOps { get; set; } = false; public bool HaveSeenAlliedCorrespondent { get; set; } = false; public bool HaveSeenEnemyCorrespondent { get; set; } = false; public bool? SelfDestruct { get; set; } = null; /// /// Current Odyssey settlement. /// public string? Settlement { get; set; } = null; /// /// Returns true if the current session is legacy /// public bool IsLegacy { get; set; } = false; /// /// How many on foot kills were done. /// public ulong OnFootKills { get; set; } = 0; /// /// How many ship kills were done. /// public ulong ShipKills { get; set; } = 0; /// /// Thargoid scouts killed /// public ulong ThargoidScoutKills { get; set; } = 0; /// /// Thargoid interceptor kills /// public ulong ThargoidInterceptorKills { get; set; } = 0; /// /// Whether we have seen an AX warzone NPC talk to us with ReceiveText /// public bool HaveSeenAXWarzoneNPC { get; set; } = false; /// /// A list of accepted missions index by their mission ID /// public Dictionary AcceptedMissions { get; } = new(); public Dictionary AcceptedMissionLocation { get; } = new(); /// /// A way to lookup a system by its system id /// public Dictionary SystemsByID { get; } = new(); /// /// A list of factions present in the given star system /// public Dictionary> SystemFactions { get; } = new(); /// /// To which faction a given named NPC belonged to. /// public Dictionary NPCFaction { get; } = new(); /// /// Buy costs for a given commodity /// public Dictionary BuyCost = new(); /// /// Called when the player leaves an instance, either through logout, FSD jump or /// supercruise instance. /// public void LeftInstance() { CurrentInstanceType = null; Settlement = null; } private bool HadCombatZone() { if (CurrentInstanceType != null && Instances.IsInstance(CurrentInstanceType, Instances.PowerWarzoneMedium)) { return true; } if (HighestCombatBond == null && LastRecordedAwardingFaction == null && HaveSeenAXWarzoneNPC == false && CurrentInstanceType == null) { return false; } return true; } public void DiscernCombatZone(TransactionList transactions, Entry e) { string? grade = CombatZones.DifficultyLow; string cztype; ulong highest = HighestCombatBond ?? 0; string? faction = LastRecordedAwardingFaction; if (!HadCombatZone()) { return; } if (OnFootKills > 0 || IsOnFoot == true) { cztype = CombatZones.GroundCombatZone; // High on foot combat zones have enforcers that bring 80k a pop if (highest >= 60000) { grade = CombatZones.DifficultyHigh; } else if (highest >= 30000) { // In medium conflict zones, the enforcers are worth 30k grade = CombatZones.DifficultyMedium; } else { grade = CombatZones.DifficultyLow; } } else if (CurrentInstanceType != null) { if (!Instances.IsWarzone(CurrentInstanceType)) { return; } if (LastRecordedAwardingFaction == null && (Instances.IsHumanWarzone(CurrentInstanceType) || Instances.IsPowerWarzone(CurrentInstanceType))) { transactions.AddIncomplete(new CombatZone(), "Could not discern for whom you fought for, " + "as it seems you haven't killed anyone in the ship combat zone.", e); return; } // If we have information about the current instance being a warship use that // information to determine the warzone. if (Instances.IsInstance(CurrentInstanceType, Instances.WarzoneLow)) { cztype = CombatZones.ShipCombatZone; grade = CombatZones.DifficultyLow; } else if (Instances.IsInstance(CurrentInstanceType, Instances.WarzoneMedium)) { cztype = CombatZones.ShipCombatZone; grade = CombatZones.DifficultyMedium; } else if (Instances.IsInstance(CurrentInstanceType, Instances.WarzoneHigh)) { cztype = CombatZones.ShipCombatZone; grade = CombatZones.DifficultyHigh; } else if (Instances.IsInstance(CurrentInstanceType, Instances.WarzoneThargoidLow)) { cztype = CombatZones.AXCombatZone; grade = CombatZones.DifficultyLow; } else if (Instances.IsInstance(CurrentInstanceType, Instances.WarzoneThargoidMedium)) { cztype = CombatZones.AXCombatZone; grade = CombatZones.DifficultyMedium; } else if (Instances.IsInstance(CurrentInstanceType, Instances.WarzoneThargoidHigh)) { cztype = CombatZones.AXCombatZone; grade = CombatZones.DifficultyHigh; } else if (Instances.IsInstance(CurrentInstanceType, Instances.WarzoneThargoidVeryHigh)) { cztype = CombatZones.AXCombatZone; grade = CombatZones.DifficultyVeryHigh; } else if (Instances.IsInstance(CurrentInstanceType, Instances.PowerWarzoneMedium)) { cztype = CombatZones.PowerCombatZone; grade = CombatZones.DifficultyMedium; } else { transactions.AddIncomplete(new CombatZone(), "Unknown conflict zone difficulty", e); return; } } else if (ShipKills > 0 && !IsOnFoot) { // Ship combat zones can be identified by the amount of kills if (ShipKills > 20) { grade = CombatZones.DifficultyHigh; } else if (ShipKills > 10) { grade = CombatZones.DifficultyMedium; } // Cap ship, means a high conflict zone if (HaveSeenCapShip) { grade = CombatZones.DifficultyHigh; } else { int warzoneNpcs = new List() { HaveSeenEnemyCaptain, HaveSeenEnemyCorrespondent, HaveSeenSpecOps } .Where(x => x == true) .Count() ; if (warzoneNpcs >= 1 && grade == CombatZones.DifficultyLow) { grade = CombatZones.DifficultyMedium; } } cztype = CombatZones.ShipCombatZone; } else if ((ThargoidScoutKills > 0 && ThargoidInterceptorKills > 0) || HaveSeenAXWarzoneNPC == true) { // Could be a thargoid combat zones if interceptors and scouts are there cztype = CombatZones.AXCombatZone; // Still unknown grade = null; } else { transactions.AddIncomplete(new CombatZone(), "Failed to discern combat zone type", e); return; } CombatZone zone = new CombatZone() { System = CurrentSystem, Faction = faction, IsLegacy = IsLegacy, Settlement = Settlement, Grade = grade, Type = cztype, // Sad truth is, if HaveSeenXXX is false, we just don't know for certain CapitalShip = HaveSeenCapShip ? true : null, SpecOps = HaveSeenSpecOps ? true : null, EnemyCorrespondent = HaveSeenEnemyCorrespondent ? true : null, AlliedCorrespondent = HaveSeenAlliedCorrespondent ? true : null, EnemyCaptain = HaveSeenEnemyCaptain ? true : null, AlliedCaptain = HaveSeenAlliedCaptain ? true : null, }; zone.Entries.Add(e); transactions.Add(zone); } public void RecordCombatBond(FactionKillBondEntry e) { if (HighestCombatBond == null || e.Reward > HighestCombatBond) { HighestCombatBond = e.Reward; } LastRecordedAwardingFaction = e.AwardingFaction; if (IsOnFoot) { ++OnFootKills; } else { ++ShipKills; } } public void ResetCombatZone() { HighestCombatBond = null; HaveSeenCapShip = false; HaveSeenAlliedCaptain = false; HaveSeenEnemyCaptain = false; HaveSeenAlliedCorrespondent = false; HaveSeenEnemyCorrespondent = false; HaveSeenSpecOps = false; LastRecordedAwardingFaction = null; OnFootKills = 0; ShipKills = 0; ThargoidInterceptorKills = 0; ThargoidScoutKills = 0; HaveSeenAXWarzoneNPC = false; } public void BoughtCargo(string? cargo, long? cost) { if (cargo == null || cost == null) { return; } BuyCost[cargo] = cost.Value; } public List? GetFactions(string? system) { if (system == null || !SystemFactions.ContainsKey(system)) { return null; } return SystemFactions[system]; } public void MissionAccepted(MissionAcceptedEntry? entry) { if (entry == null) { return; } MissionAccepted(entry.Mission); } public void MissionAccepted(Mission? mission) { if (CurrentSystem == null || CurrentSystemAddress == null) { throw new Exception("Mission accepted without knowing where."); } if (mission == null) { throw new Exception("Mission is null"); } AcceptedMissions.TryAdd(mission.MissionID, mission); Location location = new() { StarSystem = CurrentSystem, SystemAddress = CurrentSystemAddress.Value, Station = (CurrentStation ?? ""), }; AcceptedMissionLocation.TryAdd(mission.MissionID, location); } }