add combat zone detection through SupercruiseDestinationDrop

This commit is contained in:
Florian Stinglmayr 2023-05-11 20:43:48 +02:00
parent c23e8627f6
commit 79914919e5
4 changed files with 113 additions and 32 deletions

View File

@ -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;
}
}

View File

@ -1,4 +1,5 @@
using EDPlayerJournal.Entries; using EDPlayerJournal.BGS.Parsers;
using EDPlayerJournal.Entries;
namespace EDPlayerJournal.BGS; namespace EDPlayerJournal.BGS;
@ -35,7 +36,7 @@ public class TransactionList : List<Transaction> {
/// by itself generate any transactions. Location is the best information gatherer here /// by itself generate any transactions. Location is the best information gatherer here
/// as we are getting controlling faction, system factions, address and station name. /// as we are getting controlling faction, system factions, address and station name.
/// </summary> /// </summary>
internal class LocationParser : TransactionParserPart { internal class LocationParser : ITransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
LocationEntry? entry = e as LocationEntry; LocationEntry? entry = e as LocationEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
FSDJumpEntry? entry = e as FSDJumpEntry; FSDJumpEntry? entry = e as FSDJumpEntry;
if (entry == null) { if (entry == null) {
@ -89,6 +90,8 @@ internal class FSDJumpParser : TransactionParserPart {
context.DiscernCombatZone(transactions, e); context.DiscernCombatZone(transactions, e);
context.ResetCombatZone(); context.ResetCombatZone();
context.LeftInstance();
context.CurrentSystem = entry.StarSystem; context.CurrentSystem = entry.StarSystem;
context.CurrentSystemAddress = entry.SystemAddress; 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
DockedEntry? entry = e as DockedEntry; DockedEntry? entry = e as DockedEntry;
if (entry == null) { 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 /// 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. /// useful later when said NPC gets killed or murdered.
/// </summary> /// </summary>
internal class ShipTargetedParser : TransactionParserPart { internal class ShipTargetedParser : ITransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
ShipTargetedEntry? entry = e as ShipTargetedEntry; ShipTargetedEntry? entry = e as ShipTargetedEntry;
if (entry == null) { if (entry == null) {
@ -170,7 +173,7 @@ internal class ShipTargetedParser : TransactionParserPart {
/// Commit crime can result in a transaction, especially if the crime committed is /// Commit crime can result in a transaction, especially if the crime committed is
/// murder. /// murder.
/// </summary> /// </summary>
internal class CommitCrimeParser : TransactionParserPart { internal class CommitCrimeParser : ITransactionParserPart {
public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
CommitCrimeEntry? entry = e as CommitCrimeEntry; CommitCrimeEntry? entry = e as CommitCrimeEntry;
if (entry == null) { 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) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MissionsEntry? missions = entry as MissionsEntry; 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MissionAcceptedEntry? entry = e as MissionAcceptedEntry; MissionAcceptedEntry? entry = e as MissionAcceptedEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MissionCompletedEntry? entry = e as MissionCompletedEntry; MissionCompletedEntry? entry = e as MissionCompletedEntry;
if (entry == null || entry.Mission == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
Mission? mission; Mission? mission;
Location? accepted_location; 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
SellExplorationDataEntry? entry = e as SellExplorationDataEntry; SellExplorationDataEntry? entry = e as SellExplorationDataEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// If exo biology is ignored, simply do nothing // If exo biology is ignored, simply do nothing
if (options.IgnoreExoBiology) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MultiSellExplorationDataEntry? entry = e as MultiSellExplorationDataEntry; MultiSellExplorationDataEntry? entry = e as MultiSellExplorationDataEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
RedeemVoucherEntry? entry = e as RedeemVoucherEntry; RedeemVoucherEntry? entry = e as RedeemVoucherEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
SellMicroResourcesEntry? entry = e as SellMicroResourcesEntry; SellMicroResourcesEntry? entry = e as SellMicroResourcesEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
SearchAndRescueEntry? entry = e as SearchAndRescueEntry; SearchAndRescueEntry? entry = e as SearchAndRescueEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
MarketBuyEntry? entry = e as MarketBuyEntry; MarketBuyEntry? entry = e as MarketBuyEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
long profit = 0; 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
FactionKillBondEntry? entry = e as FactionKillBondEntry; FactionKillBondEntry? entry = e as FactionKillBondEntry;
if (entry == null) { 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) { public void Parse(Entry e, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
if (e.Is(Events.Embark)) { if (e.Is(Events.Embark)) {
context.IsOnFoot = false; 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) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// After a super cruise entry we are no longer on foot. // After a super cruise entry we are no longer on foot.
context.IsOnFoot = false; context.IsOnFoot = false;
context.DiscernCombatZone(transactions, entry); context.DiscernCombatZone(transactions, entry);
context.ResetCombatZone(); 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) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
context.DiscernCombatZone(transactions, entry); context.DiscernCombatZone(transactions, entry);
context.ResetCombatZone(); 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) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
if (entry.GetType() != typeof(CapShipBondEntry)) { if (entry.GetType() != typeof(CapShipBondEntry)) {
return; 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) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
FileHeaderEntry? fileheader = entry as FileHeaderEntry; 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) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
ReceiveTextEntry? receivetext = entry as ReceiveTextEntry; 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) { 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 // 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. // for you, but still you will not have completed it unless you jump back in.
context.ResetCombatZone(); 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) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// On drop ship deploy we are now on foot // On drop ship deploy we are now on foot
context.IsOnFoot = true; context.IsOnFoot = true;
} }
} }
internal class CommanderParser : TransactionParserPart { internal class CommanderParser : ITransactionParserPart {
public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) { public void Parse(Entry entry, TransactionParserContext context, TransactionParserOptions options, TransactionList transactions) {
// A commander entry happens when you log out, and log back in again // A commander entry happens when you log out, and log back in again
// for example when switching from Open, to Solo or PG. // for example when switching from Open, to Solo or PG.
@ -828,7 +837,7 @@ internal class CommanderParser : TransactionParserPart {
} }
public class TransactionParser { public class TransactionParser {
private static Dictionary<string, TransactionParserPart> ParserParts { get; } = new() private static Dictionary<string, ITransactionParserPart> ParserParts { get; } = new()
{ {
{ Events.CapShipBond, new CapShipBondParser() }, { Events.CapShipBond, new CapShipBondParser() },
{ Events.Commander, new CommanderParser() }, { Events.Commander, new CommanderParser() },
@ -857,6 +866,7 @@ public class TransactionParser {
{ Events.SellOrganicData, new SellOrganicDataParser() }, { Events.SellOrganicData, new SellOrganicDataParser() },
{ Events.ShipTargeted, new ShipTargetedParser() }, { Events.ShipTargeted, new ShipTargetedParser() },
{ Events.Shutdown, new ShutdownParser() }, { Events.Shutdown, new ShutdownParser() },
{ Events.SupercruiseDestinationDrop, new SupercruiseDestinationDropParser() },
{ Events.SupercruiseEntry, new SupercruiseEntryParser() }, { Events.SupercruiseEntry, new SupercruiseEntryParser() },
}; };
@ -894,7 +904,7 @@ public class TransactionParser {
continue; continue;
} }
TransactionParserPart transactionParserPart = ParserParts[entry.Event]; ITransactionParserPart transactionParserPart = ParserParts[entry.Event];
transactionParserPart.Parse(entry, context, options, transactions); transactionParserPart.Parse(entry, context, options, transactions);
} }

View File

@ -33,6 +33,13 @@ internal class TransactionParserContext {
/// </summary> /// </summary>
public bool IsOnFoot { get; set; } = false; 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> /// <summary>
/// Last faction that awarded the player with combat bonds. /// Last faction that awarded the player with combat bonds.
/// </summary> /// </summary>
@ -100,6 +107,14 @@ internal class TransactionParserContext {
/// </summary> /// </summary>
public Dictionary<string, long> BuyCost = new(); 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;
}
public void DiscernCombatZone(TransactionList transactions, Entry e) { public void DiscernCombatZone(TransactionList transactions, Entry e) {
string? grade = CombatZones.DifficultyLow; string? grade = CombatZones.DifficultyLow;
string cztype; string cztype;
@ -108,7 +123,8 @@ internal class TransactionParserContext {
if (HighestCombatBond == null && if (HighestCombatBond == null &&
LastRecordedAwardingFaction == null && LastRecordedAwardingFaction == null &&
HaveSeenAXWarzoneNPC == false) { HaveSeenAXWarzoneNPC == false &&
CurrentInstanceType == null) {
return; return;
} }
@ -123,6 +139,47 @@ internal class TransactionParserContext {
} else { } else {
grade = CombatZones.DifficultyLow; 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) { } else if (ShipKills > 0 && !IsOnFoot) {
// Ship combat zones can be identified by the amount of kills // Ship combat zones can be identified by the amount of kills
if (ShipKills > 20) { if (ShipKills > 20) {

View File

@ -2,7 +2,7 @@
namespace EDPlayerJournal.BGS; namespace EDPlayerJournal.BGS;
internal interface TransactionParserPart { internal interface ITransactionParserPart {
/// <summary> /// <summary>
/// Parse a given entry of the entry type specified when declaring to implement this /// 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 /// interface. You must add your transaction to the passed list in case you did have