From 79914919e5a9c11d1924aa396594ec46a0054d0c Mon Sep 17 00:00:00 2001 From: Florian Stinglmayr Date: Thu, 11 May 2023 20:43:48 +0200 Subject: [PATCH] add combat zone detection through SupercruiseDestinationDrop --- .../SupercruiseDestinationDropParser.cs | 14 ++++ EDPlayerJournal/BGS/TransactionParser.cs | 70 +++++++++++-------- .../BGS/TransactionParserContext.cs | 59 +++++++++++++++- EDPlayerJournal/BGS/TransactionParserPart.cs | 2 +- 4 files changed, 113 insertions(+), 32 deletions(-) create mode 100644 EDPlayerJournal/BGS/Parsers/SupercruiseDestinationDropParser.cs diff --git a/EDPlayerJournal/BGS/Parsers/SupercruiseDestinationDropParser.cs b/EDPlayerJournal/BGS/Parsers/SupercruiseDestinationDropParser.cs new file mode 100644 index 0000000..0fc52a8 --- /dev/null +++ b/EDPlayerJournal/BGS/Parsers/SupercruiseDestinationDropParser.cs @@ -0,0 +1,14 @@ +using EDPlayerJournal.Entries; + +namespace EDPlayerJournal.BGS.Parsers; + +internal class SupercruiseDestinationDropParser : ITransactionParserPart { + public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { + SupercruiseDestinationDropEntry? drop = entry as SupercruiseDestinationDropEntry; + if (drop == null || drop.Type == null) { + return; + } + + context.CurrentInstanceType = drop.Type; + } +} diff --git a/EDPlayerJournal/BGS/TransactionParser.cs b/EDPlayerJournal/BGS/TransactionParser.cs index c9ad6f7..354c845 100644 --- a/EDPlayerJournal/BGS/TransactionParser.cs +++ b/EDPlayerJournal/BGS/TransactionParser.cs @@ -1,4 +1,5 @@ -using EDPlayerJournal.Entries; +using EDPlayerJournal.BGS.Parsers; +using EDPlayerJournal.Entries; namespace EDPlayerJournal.BGS; @@ -35,7 +36,7 @@ public class TransactionList : List { /// by itself generate any transactions. Location is the best information gatherer here /// as we are getting controlling faction, system factions, address and station name. /// -internal class LocationParser : TransactionParserPart { +internal class LocationParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { LocationEntry? entry = e as LocationEntry; if (entry == null) { @@ -72,7 +73,7 @@ internal class LocationParser : TransactionParserPart { } } -internal class FSDJumpParser : TransactionParserPart { +internal class FSDJumpParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { FSDJumpEntry? entry = e as FSDJumpEntry; if (entry == null) { @@ -89,6 +90,8 @@ internal class FSDJumpParser : TransactionParserPart { context.DiscernCombatZone(transactions, e); context.ResetCombatZone(); + context.LeftInstance(); + context.CurrentSystem = entry.StarSystem; context.CurrentSystemAddress = entry.SystemAddress; @@ -105,7 +108,7 @@ internal class FSDJumpParser : TransactionParserPart { } } -internal class DockedParser : TransactionParserPart { +internal class DockedParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { DockedEntry? entry = e as DockedEntry; if (entry == null) { @@ -135,7 +138,7 @@ internal class DockedParser : TransactionParserPart { /// With ship targeted we might find out to which faction a given NPC belonged. This is /// useful later when said NPC gets killed or murdered. /// -internal class ShipTargetedParser : TransactionParserPart { +internal class ShipTargetedParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { ShipTargetedEntry? entry = e as ShipTargetedEntry; if (entry == null) { @@ -170,7 +173,7 @@ internal class ShipTargetedParser : TransactionParserPart { /// Commit crime can result in a transaction, especially if the crime committed is /// murder. /// -internal class CommitCrimeParser : TransactionParserPart { +internal class CommitCrimeParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { CommitCrimeEntry? entry = e as CommitCrimeEntry; if (entry == null) { @@ -226,7 +229,7 @@ internal class CommitCrimeParser : TransactionParserPart { } } -internal class MissionsParser : TransactionParserPart { +internal class MissionsParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { MissionsEntry? missions = entry as MissionsEntry; @@ -255,7 +258,7 @@ internal class MissionsParser : TransactionParserPart { } } -internal class MissionAcceptedParser : TransactionParserPart { +internal class MissionAcceptedParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { MissionAcceptedEntry? entry = e as MissionAcceptedEntry; if (entry == null) { @@ -281,7 +284,7 @@ internal class MissionAcceptedParser : TransactionParserPart { } } -internal class MissionCompletedParser : TransactionParserPart { +internal class MissionCompletedParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { MissionCompletedEntry? entry = e as MissionCompletedEntry; if (entry == null || entry.Mission == null) { @@ -396,7 +399,7 @@ internal class MissionCompletedParser : TransactionParserPart { } } -internal class MissionFailedParser : TransactionParserPart { +internal class MissionFailedParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { Mission? mission; Location? accepted_location; @@ -451,7 +454,7 @@ internal class MissionFailedParser : TransactionParserPart { } } -internal class SellExplorationDataParser : TransactionParserPart { +internal class SellExplorationDataParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { SellExplorationDataEntry? entry = e as SellExplorationDataEntry; if (entry == null) { @@ -475,7 +478,7 @@ internal class SellExplorationDataParser : TransactionParserPart { } } -internal class SellOrganicDataParser : TransactionParserPart { +internal class SellOrganicDataParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { // If exo biology is ignored, simply do nothing if (options.IgnoreExoBiology) { @@ -504,7 +507,7 @@ internal class SellOrganicDataParser : TransactionParserPart { } } -internal class MultiSellExplorationDataParser : TransactionParserPart { +internal class MultiSellExplorationDataParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { MultiSellExplorationDataEntry? entry = e as MultiSellExplorationDataEntry; if (entry == null) { @@ -528,7 +531,7 @@ internal class MultiSellExplorationDataParser : TransactionParserPart { } } -internal class RedeemVoucherParser : TransactionParserPart { +internal class RedeemVoucherParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { RedeemVoucherEntry? entry = e as RedeemVoucherEntry; if (entry == null) { @@ -585,7 +588,7 @@ internal class RedeemVoucherParser : TransactionParserPart { } } -internal class SellMicroResourcesParser : TransactionParserPart { +internal class SellMicroResourcesParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { SellMicroResourcesEntry? entry = e as SellMicroResourcesEntry; if (entry == null) { @@ -609,7 +612,7 @@ internal class SellMicroResourcesParser : TransactionParserPart { } } -internal class SearchAndRescueParser : TransactionParserPart { +internal class SearchAndRescueParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { SearchAndRescueEntry? entry = e as SearchAndRescueEntry; if (entry == null) { @@ -633,7 +636,7 @@ internal class SearchAndRescueParser : TransactionParserPart { } } -internal class MarketBuyParser : TransactionParserPart { +internal class MarketBuyParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { MarketBuyEntry? entry = e as MarketBuyEntry; if (entry == null) { @@ -668,7 +671,7 @@ internal class MarketBuyParser : TransactionParserPart { } } -internal class MarketSellParser : TransactionParserPart { +internal class MarketSellParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { long profit = 0; @@ -704,7 +707,7 @@ internal class MarketSellParser : TransactionParserPart { } } -internal class FactionKillBondParser : TransactionParserPart { +internal class FactionKillBondParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { FactionKillBondEntry? entry = e as FactionKillBondEntry; if (entry == null) { @@ -737,7 +740,7 @@ internal class FactionKillBondParser : TransactionParserPart { } } -internal class EmbarkDisembarkParser : TransactionParserPart { +internal class EmbarkDisembarkParser : ITransactionParserPart { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { if (e.Is(Events.Embark)) { context.IsOnFoot = false; @@ -747,23 +750,27 @@ internal class EmbarkDisembarkParser : TransactionParserPart { } } -internal class SupercruiseEntryParser : TransactionParserPart { +internal class SupercruiseEntryParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { // After a super cruise entry we are no longer on foot. context.IsOnFoot = false; context.DiscernCombatZone(transactions, entry); context.ResetCombatZone(); + // Supercruise entry means you left the current local instance + context.LeftInstance(); } } -internal class ShutdownParser : TransactionParserPart { +internal class ShutdownParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { context.DiscernCombatZone(transactions, entry); context.ResetCombatZone(); + // Shutdown (logout) means you left the instance + context.LeftInstance(); } } -internal class CapShipBondParser : TransactionParserPart { +internal class CapShipBondParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { if (entry.GetType() != typeof(CapShipBondEntry)) { return; @@ -773,7 +780,7 @@ internal class CapShipBondParser : TransactionParserPart { } } -internal class FileHeaderParser : TransactionParserPart { +internal class FileHeaderParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { FileHeaderEntry? fileheader = entry as FileHeaderEntry; @@ -785,7 +792,7 @@ internal class FileHeaderParser : TransactionParserPart { } } -internal class ReceiveTextParser : TransactionParserPart { +internal class ReceiveTextParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { ReceiveTextEntry? receivetext = entry as ReceiveTextEntry; @@ -803,22 +810,24 @@ internal class ReceiveTextParser : TransactionParserPart { } } -internal class DiedParser : TransactionParserPart { +internal class DiedParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { // You can't complete a combat zone if you die in it. Others might keep it open // for you, but still you will not have completed it unless you jump back in. context.ResetCombatZone(); + // Dying also moves you back to another instance + context.LeftInstance(); } } -internal class DropshipDeployParser : TransactionParserPart { +internal class DropshipDeployParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { // On drop ship deploy we are now on foot context.IsOnFoot = true; } } -internal class CommanderParser : TransactionParserPart { +internal class CommanderParser : ITransactionParserPart { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { // A commander entry happens when you log out, and log back in again // for example when switching from Open, to Solo or PG. @@ -828,7 +837,7 @@ internal class CommanderParser : TransactionParserPart { } public class TransactionParser { - private static Dictionary ParserParts { get; } = new() + private static Dictionary ParserParts { get; } = new() { { Events.CapShipBond, new CapShipBondParser() }, { Events.Commander, new CommanderParser() }, @@ -857,6 +866,7 @@ public class TransactionParser { { Events.SellOrganicData, new SellOrganicDataParser() }, { Events.ShipTargeted, new ShipTargetedParser() }, { Events.Shutdown, new ShutdownParser() }, + { Events.SupercruiseDestinationDrop, new SupercruiseDestinationDropParser() }, { Events.SupercruiseEntry, new SupercruiseEntryParser() }, }; @@ -894,7 +904,7 @@ public class TransactionParser { continue; } - TransactionParserPart transactionParserPart = ParserParts[entry.Event]; + ITransactionParserPart transactionParserPart = ParserParts[entry.Event]; transactionParserPart.Parse(entry, context, options, transactions); } diff --git a/EDPlayerJournal/BGS/TransactionParserContext.cs b/EDPlayerJournal/BGS/TransactionParserContext.cs index 6c8c0f6..6170d17 100644 --- a/EDPlayerJournal/BGS/TransactionParserContext.cs +++ b/EDPlayerJournal/BGS/TransactionParserContext.cs @@ -33,6 +33,13 @@ internal class TransactionParserContext { /// 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. /// @@ -100,6 +107,14 @@ internal class TransactionParserContext { /// public Dictionary BuyCost = new(); + /// + /// Called when the player leaves an instance, either through logout, FSD jump or + /// supercruise instance. + /// + public void LeftInstance() { + CurrentInstanceType = null; + } + public void DiscernCombatZone(TransactionList transactions, Entry e) { string? grade = CombatZones.DifficultyLow; string cztype; @@ -108,7 +123,8 @@ internal class TransactionParserContext { if (HighestCombatBond == null && LastRecordedAwardingFaction == null && - HaveSeenAXWarzoneNPC == false) { + HaveSeenAXWarzoneNPC == false && + CurrentInstanceType == null) { return; } @@ -123,6 +139,47 @@ internal class TransactionParserContext { } 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) { diff --git a/EDPlayerJournal/BGS/TransactionParserPart.cs b/EDPlayerJournal/BGS/TransactionParserPart.cs index 00ebecf..12031d9 100644 --- a/EDPlayerJournal/BGS/TransactionParserPart.cs +++ b/EDPlayerJournal/BGS/TransactionParserPart.cs @@ -2,7 +2,7 @@ namespace EDPlayerJournal.BGS; -internal interface TransactionParserPart { +internal interface ITransactionParserPart { /// /// Parse a given entry of the entry type specified when declaring to implement this /// interface. You must add your transaction to the passed list in case you did have