Skip to content

Commit

Permalink
moved redirection event to parser helper + added usage for player red…
Browse files Browse the repository at this point in the history
…iretion in EvtcParser.cs
  • Loading branch information
EliphasNUIT committed Jul 15, 2023
1 parent 80f9932 commit 90f8d5d
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 20 deletions.
28 changes: 8 additions & 20 deletions GW2EIEvtcParser/EvtcParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ public ParsedEvtcLog ParseLog(ParserController operation, FileInfo evtc, out Par
{
throw new EvtcFileException("File " + evtc.FullName + " does not exist");
}
if (!ParserHelper.IsSupportedFormat(evtc.Name))
if (!IsSupportedFormat(evtc.Name))
{
throw new EvtcFileException("Not EVTC");
}
ParsedEvtcLog evtcLog;
using (var fs = new FileStream(evtc.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
if (ParserHelper.IsCompressedFormat(evtc.Name))
if (IsCompressedFormat(evtc.Name))
{
using (var arch = new ZipArchive(fs, ZipArchiveMode.Read))
{
Expand Down Expand Up @@ -386,20 +386,20 @@ private void ParseAgentData(BinaryReader reader, ParserController operation)
// 68 bytes: name
string name = GetString(reader, 68, false);
//Save
ParserHelper.Spec agentProf = ParserHelper.ProfToSpec(GetAgentProfString(prof, isElite, operation));
ParserHelper.Spec agentProf = ProfToSpec(GetAgentProfString(prof, isElite, operation));
AgentItem.AgentType type;
ushort ID = 0;
switch (agentProf)
{
case ParserHelper.Spec.NPC:
case Spec.NPC:
// NPC
if (!ushort.TryParse(prof.ToString().PadLeft(5, '0'), out ID))
{
ID = 0;
}
type = AgentItem.AgentType.NPC;
break;
case ParserHelper.Spec.Gadget:
case Spec.Gadget:
// Gadget
if (!ushort.TryParse((prof & 0x0000ffff).ToString().PadLeft(5, '0'), out ID))
{
Expand Down Expand Up @@ -710,10 +710,10 @@ private static bool UpdateAgentData(AgentItem ag, long logTime, ushort instid, b
private void FindAgentMaster(long logTime, ushort masterInstid, ulong minionAgent)
{
AgentItem master = _agentData.GetAgentByInstID(masterInstid, logTime);
if (master != ParserHelper._unknownAgent)
if (master != _unknownAgent)
{
AgentItem minion = _agentData.GetAgent(minionAgent, logTime);
if (minion != ParserHelper._unknownAgent && minion.Master == null)
if (minion != _unknownAgent && minion.Master == null)
{
minion.SetMaster(master);
}
Expand All @@ -740,20 +740,8 @@ private void CompletePlayers(ParserController operation)
if (p.Character == player.Character) // same character, can be fused
{
skip = true;
ulong agent = p.AgentItem.Agent;
operation.UpdateProgressWithCancellationCheck("Merging player");
foreach (CombatItem c in _combatItems)
{
if (c.DstMatchesAgent(player.AgentItem, _enabledExtensions))
{
c.OverrideDstAgent(agent);
}
if (c.SrcMatchesAgent(player.AgentItem, _enabledExtensions))
{
c.OverrideSrcAgent(agent);
}
}
_agentData.SwapMasters(player.AgentItem, p.AgentItem);
RedirectAllEvents(_combatItems, _enabledExtensions, _agentData, player.AgentItem, p.AgentItem);
p.AgentItem.OverrideAwareTimes(Math.Min(p.AgentItem.FirstAware, player.AgentItem.FirstAware), Math.Max(p.AgentItem.LastAware, player.AgentItem.LastAware));
break;
}
Expand Down
159 changes: 159 additions & 0 deletions GW2EIEvtcParser/ParserHelpers/ParserHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using GW2EIEvtcParser.EIData;
using GW2EIEvtcParser.Extensions;
using GW2EIEvtcParser.ParsedData;
using GW2EIEvtcParser.ParserHelpers;
using static GW2EIEvtcParser.ArcDPSEnums;
Expand Down Expand Up @@ -258,6 +259,164 @@ public static Exception GetFinalException(Exception ex)
return final;
}



internal delegate bool ExtraRedirection(CombatItem evt, AgentItem from, AgentItem to);
/// <summary>
/// Method used to redirect a subset of events from redirectFrom to to
/// </summary>
/// <param name="combatData"></param>
/// <param name="extensions"></param>
/// <param name="agentData"></param>
/// <param name="redirectFrom">AgentItem the events need to be redirected from</param>
/// <param name="stateCopyFroms">AgentItems from where last known states (hp, position, etc) will be copied from</param>
/// <param name="to">AgentItem the events need to be redirected to</param>
/// <param name="extraRedirections">function to handle special conditions, given event either src or dst matches from</param>
internal static void RedirectEventsAndCopyPreviousStates(List<CombatItem> combatData, IReadOnlyDictionary<uint, AbstractExtensionHandler> extensions, AgentData agentData, AgentItem redirectFrom, List<AgentItem> stateCopyFroms, AgentItem to, ExtraRedirection extraRedirections = null)
{
// Redirect combat events
foreach (CombatItem evt in combatData)
{
if (to.InAwareTimes(evt.Time))
{
var srcMatchesAgent = evt.SrcMatchesAgent(redirectFrom, extensions);
var dstMatchesAgent = evt.DstMatchesAgent(redirectFrom, extensions);
if (extraRedirections != null && !extraRedirections(evt, redirectFrom, to))
{
continue;
}
if (srcMatchesAgent)
{
evt.OverrideSrcAgent(to.Agent);
}
if (dstMatchesAgent)
{
evt.OverrideDstAgent(to.Agent);
}
}
}
var toCopy = new List<CombatItem>();
Func<CombatItem, bool> canCopy = (evt) => stateCopyFroms.Any(x => evt.SrcMatchesAgent(x));
CombatItem lastBreakbarStateToCopy = combatData.LastOrDefault(x => x.IsStateChange == StateChange.BreakbarState && canCopy(x) && x.Time <= to.FirstAware);
if (lastBreakbarStateToCopy != null)
{
toCopy.Add(lastBreakbarStateToCopy);
}
CombatItem lastPositionToCopy = combatData.LastOrDefault(x => x.IsStateChange == StateChange.Position && canCopy(x) && x.Time <= to.FirstAware);
if (lastPositionToCopy != null)
{
toCopy.Add(lastPositionToCopy);
}
CombatItem lastRotationToCopy = combatData.LastOrDefault(x => x.IsStateChange == StateChange.Rotation && canCopy(x) && x.Time <= to.FirstAware);
if (lastRotationToCopy != null)
{
toCopy.Add(lastRotationToCopy);
}
CombatItem lastVelocityToCopy = combatData.LastOrDefault(x => x.IsStateChange == StateChange.Velocity && canCopy(x) && x.Time <= to.FirstAware);
if (lastVelocityToCopy != null)
{
toCopy.Add(lastVelocityToCopy);
}
CombatItem lastMaxHealthUpdateToCopy = combatData.LastOrDefault(x => x.IsStateChange == StateChange.MaxHealthUpdate && canCopy(x) && x.Time <= to.FirstAware);
if (lastMaxHealthUpdateToCopy != null)
{
toCopy.Add(lastMaxHealthUpdateToCopy);
}
CombatItem lastHealthUpdateToCopy = combatData.LastOrDefault(x => x.IsStateChange == StateChange.HealthUpdate && canCopy(x) && x.Time <= to.FirstAware);
if (lastHealthUpdateToCopy != null)
{
toCopy.Add(lastHealthUpdateToCopy);
}
CombatItem lastBreakbarUpdateToCopy = combatData.LastOrDefault(x => x.IsStateChange == StateChange.BreakbarPercent && canCopy(x) && x.Time <= to.FirstAware);
if (lastBreakbarUpdateToCopy != null)
{
toCopy.Add(lastBreakbarUpdateToCopy);
}
CombatItem lastBarrierUpdateToCopy = combatData.LastOrDefault(x => x.IsStateChange == StateChange.BarrierUpdate && canCopy(x) && x.Time <= to.FirstAware);
if (lastBarrierUpdateToCopy != null)
{
toCopy.Add(lastBarrierUpdateToCopy);
}
CombatItem lastCombatStatusUpdateToCopy = combatData.LastOrDefault(x => (x.IsStateChange == StateChange.EnterCombat || x.IsStateChange == StateChange.ExitCombat) && canCopy(x) && x.Time <= to.FirstAware);
if (lastCombatStatusUpdateToCopy != null)
{
toCopy.Add(lastCombatStatusUpdateToCopy);
}
CombatItem lastStatusEventToCopy = combatData.LastOrDefault(x => (x.IsStateChange == StateChange.Spawn || x.IsStateChange == StateChange.Despawn || x.IsStateChange == StateChange.ChangeDead || x.IsStateChange == StateChange.ChangeDown || x.IsStateChange == StateChange.ChangeUp) && canCopy(x) && x.Time <= to.FirstAware);
if (lastStatusEventToCopy != null)
{
toCopy.Add(lastStatusEventToCopy);
}
foreach (CombatItem c in toCopy)
{
var cExtra = new CombatItem(c);
cExtra.OverrideTime(to.FirstAware);
cExtra.OverrideSrcAgent(to.Agent);
combatData.Add(cExtra);
}
// Copy attack targets
var attackTargets = combatData.Where(x => x.IsStateChange == StateChange.AttackTarget && x.DstMatchesAgent(redirectFrom)).ToList();
foreach (CombatItem c in attackTargets)
{
var cExtra = new CombatItem(c);
cExtra.OverrideTime(to.FirstAware);
cExtra.OverrideDstAgent(to.Agent);
combatData.Add(cExtra);
}
// Redirect NPC masters
foreach (AgentItem ag in agentData.GetAgentByType(AgentItem.AgentType.NPC))
{
if (ag.Master == redirectFrom && to.InAwareTimes(ag.FirstAware))
{
ag.SetMaster(to);
}
}
// Redirect Gadget masters
foreach (AgentItem ag in agentData.GetAgentByType(AgentItem.AgentType.Gadget))
{
if (ag.Master == redirectFrom && to.InAwareTimes(ag.FirstAware))
{
ag.SetMaster(to);
}
}
}

/// <summary>
/// Method used to redirect all events from redirectFrom to to
/// </summary>
/// <param name="combatData"></param>
/// <param name="extensions"></param>
/// <param name="agentData"></param>
/// <param name="redirectFrom">AgentItem the events need to be redirected from</param>
/// <param name="to">AgentItem the events need to be redirected to</param>
/// <param name="extraRedirections">function to handle special conditions, given event either src or dst matches from</param>
internal static void RedirectAllEvents(IReadOnlyList<CombatItem> combatData, IReadOnlyDictionary<uint, AbstractExtensionHandler> extensions, AgentData agentData, AgentItem redirectFrom, AgentItem to, ExtraRedirection extraRedirections = null)
{
// Redirect combat events
foreach (CombatItem evt in combatData)
{
var srcMatchesAgent = evt.SrcMatchesAgent(redirectFrom, extensions);
var dstMatchesAgent = evt.DstMatchesAgent(redirectFrom, extensions);
if (!dstMatchesAgent && !srcMatchesAgent)
{
continue;
}
if (extraRedirections != null && !extraRedirections(evt, redirectFrom, to))
{
continue;
}
if (srcMatchesAgent)
{
evt.OverrideSrcAgent(to.Agent);
}
if (dstMatchesAgent)
{
evt.OverrideDstAgent(to.Agent);
}
}
agentData.SwapMasters(redirectFrom, to);
}

/// <summary>
/// Dictionary to find the <see cref="Spec"/> Specialization / Profession given a <see cref="string"/> as reference.
/// </summary>
Expand Down

0 comments on commit 90f8d5d

Please sign in to comment.