326 lines
11 KiB
C#
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);
|
|
}
|
|
}
|