EDBGS/EDPlayerJournal/BGS/TransactionParserContext.cs

326 lines
11 KiB
C#

using EDPlayerJournal.Entries;
namespace EDPlayerJournal.BGS;
internal class TransactionParserContext {
/// <summary>
/// List of commander names seen in the logs. May be empty.
/// </summary>
public List<string> Commanders { get; } = new();
/// <summary>
/// Name of the current system the player is in.
/// </summary>
public string? CurrentSystem { get; set; }
/// <summary>
/// 64 bit address of the current system.
/// </summary>
public ulong? CurrentSystemAddress { get; set; }
/// <summary>
/// Controlling faction of the current system.
/// </summary>
public string? ControllingFaction { get; set; }
/// <summary>
/// Name of the current station the player is docked at.
/// </summary>
public string? CurrentStation { get; set; }
/// <summary>
/// Faction that owns the current station.
/// </summary>
public string? StationOwner { get; set; }
/// <summary>
/// Whether the player is currently on foot, or in an SRV/ship.
/// </summary>
public bool IsOnFoot { get; set; } = false;
/// <summary>
/// Type of the current instance after a SupercruiseDestinationDropEntry.
/// This is null if there is no current instance, or the current instance
/// is not known.
/// </summary>
public string? CurrentInstanceType { get; set; } = null;
/// <summary>
/// Last faction that awarded the player with combat bonds.
/// </summary>
public string? LastRecordedAwardingFaction { get; set; }
/// <summary>
/// Highest combat bond seen so far.
/// </summary>
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;
/// <summary>
/// Current Odyssey settlement.
/// </summary>
public string? Settlement { get; set; } = null;
/// <summary>
/// Returns true if the current session is legacy
/// </summary>
public bool IsLegacy { get; set; } = false;
/// <summary>
/// How many on foot kills were done.
/// </summary>
public ulong OnFootKills { get; set; } = 0;
/// <summary>
/// How many ship kills were done.
/// </summary>
public ulong ShipKills { get; set; } = 0;
/// <summary>
/// Thargoid scouts killed
/// </summary>
public ulong ThargoidScoutKills { get; set; } = 0;
/// <summary>
/// Thargoid interceptor kills
/// </summary>
public ulong ThargoidInterceptorKills { get; set; } = 0;
/// <summary>
/// Whether we have seen an AX warzone NPC talk to us with ReceiveText
/// </summary>
public bool HaveSeenAXWarzoneNPC { get; set; } = false;
/// <summary>
/// A list of accepted missions index by their mission ID
/// </summary>
public Dictionary<ulong, Mission> AcceptedMissions { get; } = new();
public Dictionary<ulong, Location> AcceptedMissionLocation { get; } = new();
/// <summary>
/// A way to lookup a system by its system id
/// </summary>
public Dictionary<ulong, string> SystemsByID { get; } = new();
/// <summary>
/// A list of factions present in the given star system
/// </summary>
public Dictionary<string, List<Faction>> SystemFactions { get; } = new();
/// <summary>
/// To which faction a given named NPC belonged to.
/// </summary>
public Dictionary<string, string> NPCFaction { get; } = new();
/// <summary>
/// Buy costs for a given commodity
/// </summary>
public Dictionary<string, long> BuyCost = new();
/// <summary>
/// Called when the player leaves an instance, either through logout, FSD jump or
/// supercruise instance.
/// </summary>
public void LeftInstance() {
CurrentInstanceType = null;
Settlement = null;
}
public void DiscernCombatZone(TransactionList transactions, Entry e) {
string? grade = CombatZones.DifficultyLow;
string cztype;
ulong highest = HighestCombatBond ?? 0;
string? faction = LastRecordedAwardingFaction;
if (HighestCombatBond == null &&
LastRecordedAwardingFaction == null &&
HaveSeenAXWarzoneNPC == false &&
CurrentInstanceType == null) {
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)) {
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 {
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<bool>() {
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<Faction>? 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);
}
}