Skip to content

Commit

Permalink
some quest module improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
CarnifexOptimus committed Jan 30, 2025
1 parent 7e1ecfe commit 0699ab3
Show file tree
Hide file tree
Showing 26 changed files with 362 additions and 133 deletions.
2 changes: 1 addition & 1 deletion BossMod/BossModule/AIHintsBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void Update(AIHints hints, int playerSlot, float maxCastTime)
FillEnemies(hints, playerAssignment == PartyRolesConfig.Assignment.MT || playerAssignment == PartyRolesConfig.Assignment.OT && !_ws.Party.WithoutSlot(false, false, true).Any(p => p != player && p.Role == Role.Tank));
if (activeModule != null)
{
activeModule.CalculateAIHints(playerSlot, player, playerAssignment, hints);
activeModule.CalculateAIHints(playerSlot, ref player, ref playerAssignment, ref hints);
}
else
{
Expand Down
144 changes: 96 additions & 48 deletions BossMod/BossModule/BossModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public List<Actor> Enemies(ReadOnlySpan<uint> enemies)
}
return null;
}
private int componentCount;

public void ActivateComponent<T>() where T : BossComponent
{
Expand All @@ -74,7 +73,6 @@ public void ActivateComponent<T>() where T : BossComponent
}
var comp = New<T>.Create(this);
Components.Add(comp);
++componentCount;

// execute callbacks for existing state
foreach (var actor in WorldState.Actors)
Expand All @@ -83,28 +81,44 @@ public void ActivateComponent<T>() where T : BossComponent
if (nonPlayer)
{
comp.OnActorCreated(actor);
if (actor.CastInfo?.IsSpell() ?? false)
comp.OnCastStarted(actor, actor.CastInfo);
ref var castinfo = ref actor.CastInfo;
if (castinfo?.IsSpell() ?? false)
comp.OnCastStarted(actor, castinfo);
}
ref var tether = ref actor.Tether;
if (tether.ID != 0)
comp.OnTethered(actor, tether);
var len = actor.Statuses.Length;
for (var i = 0; i < len; ++i)
{
ref var status = ref actor.Statuses[i];
if (status.ID != 0)
comp.OnStatusGain(actor, status);
}
if (actor.Tether.ID != 0)
comp.OnTethered(actor, actor.Tether);
for (var i = 0; i < actor.Statuses.Length; ++i)
if (actor.Statuses[i].ID != 0)
comp.OnStatusGain(actor, actor.Statuses[i]);
}
}

public void DeactivateComponent<T>() where T : BossComponent
{
var count = Components.RemoveAll(x => x is T);
componentCount -= count;
if (count == 0)
var count = Components.Count;
var removed = false;
for (var i = 0; i < count; ++i)
{
var comp = Components[i];
if (comp is T)
{
Components.Remove(comp);
removed = true;
break;
}
}
if (!removed)
ReportError(null, $"State {StateMachine.ActiveState?.ID:X}: Could not find a component of type {typeof(T)} to deactivate");
}

public void ClearComponents(Predicate<BossComponent> condition)
{
componentCount -= Components.RemoveAll(condition);
Components.RemoveAll(condition);
}

protected BossModule(WorldState ws, Actor primary, WPos center, ArenaBounds bounds)
Expand Down Expand Up @@ -164,7 +178,8 @@ public void Update()
if (StateMachine.ActiveState != null)
{
UpdateModule();
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].Update();
}
}
Expand All @@ -185,22 +200,23 @@ public void Draw(Angle cameraAzimuth, int pcSlot, bool includeText, bool include
DrawGlobalHints(CalculateGlobalHints());

if (WindowConfig.ShowPlayerHints)
DrawPlayerHints(pcHints);
DrawPlayerHints(ref pcHints);
}
if (includeArena)
{
Arena.Begin(cameraAzimuth);
DrawArena(pcSlot, pc, pcHints.Any(h => h.Item2));
DrawArena(pcSlot, ref pc, pcHints.Any(h => h.Item2));
MiniArena.End();
}
}

public virtual void DrawArena(int pcSlot, Actor pc, bool haveRisks)
public virtual void DrawArena(int pcSlot, ref Actor pc, bool haveRisks)
{
// draw background
DrawArenaBackground(pcSlot, pc);

for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].DrawArenaBackground(pcSlot, pc);

// draw borders
Expand All @@ -212,11 +228,11 @@ public virtual void DrawArena(int pcSlot, Actor pc, bool haveRisks)
DrawWaymarks();

// draw non-player alive party members
DrawPartyMembers(pcSlot, pc);
DrawPartyMembers(pcSlot, ref pc);

// draw foreground
DrawArenaForeground(pcSlot, pc);
for (var i = 0; i < componentCount; ++i)
for (var i = 0; i < count; ++i)
Components[i].DrawArenaForeground(pcSlot, pc);
if (WindowConfig.ShowMeleeRangeIndicator)
{
Expand All @@ -232,32 +248,36 @@ public virtual void DrawArena(int pcSlot, Actor pc, bool haveRisks)
public BossComponent.TextHints CalculateHintsForRaidMember(int slot, Actor actor)
{
BossComponent.TextHints hints = [];
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].AddHints(slot, actor, hints);
return hints;
}

public BossComponent.MovementHints CalculateMovementHintsForRaidMember(int slot, Actor actor)
public BossComponent.MovementHints CalculateMovementHintsForRaidMember(int slot, ref Actor actor)
{
BossComponent.MovementHints hints = [];
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].AddMovementHints(slot, actor, hints);
return hints;
}

public BossComponent.GlobalHints CalculateGlobalHints()
{
BossComponent.GlobalHints hints = [];
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].AddGlobalHints(hints);
return hints;
}

public void CalculateAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints)
public void CalculateAIHints(int slot, ref Actor actor, ref PartyRolesConfig.Assignment assignment, ref AIHints hints)
{
hints.PathfindMapCenter = Center;
hints.PathfindMapBounds = Bounds;
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].AddAIHints(slot, actor, assignment, hints);
CalculateModuleAIHints(slot, actor, assignment, hints);
if (!WindowConfig.AllowAutomaticActions && AI.AIManager.Instance?.Beh == null)
Expand Down Expand Up @@ -304,7 +324,7 @@ private void DrawGlobalHints(BossComponent.GlobalHints hints)
ImGui.NewLine();
}

private void DrawPlayerHints(BossComponent.TextHints hints)
private void DrawPlayerHints(ref BossComponent.TextHints hints)
{
foreach ((var hint, var risk) in hints)
{
Expand Down Expand Up @@ -337,11 +357,11 @@ private void DrawWaymark(Vector3? pos, string text, uint color)
}
}

private void DrawPartyMembers(int pcSlot, Actor pc)
private void DrawPartyMembers(int pcSlot, ref Actor pc)
{
foreach (var (slot, player) in Raid.WithSlot().Exclude(pcSlot))
{
var (prio, color) = CalculateHighestPriority(pcSlot, pc, slot, player);
var (prio, color) = CalculateHighestPriority(pcSlot, ref pc, slot, player);

var isFocus = WorldState.Client.FocusTargetId == player.InstanceID;
if (prio == BossComponent.PlayerPriority.Irrelevant && !WindowConfig.ShowIrrelevantPlayers && !(isFocus && WindowConfig.ShowFocusTargetPlayer))
Expand Down Expand Up @@ -382,11 +402,12 @@ private void DrawPartyMembers(int pcSlot, Actor pc)
}
}

private (BossComponent.PlayerPriority, uint) CalculateHighestPriority(int pcSlot, Actor pc, int playerSlot, Actor player)
private (BossComponent.PlayerPriority, uint) CalculateHighestPriority(int pcSlot, ref Actor pc, int playerSlot, Actor player)
{
uint color = 0;
var highestPrio = BossComponent.PlayerPriority.Irrelevant;
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
{
uint subColor = 0;
var subPrio = Components[i].CalcPriority(pcSlot, pc, playerSlot, player, ref subColor);
Expand All @@ -403,109 +424,136 @@ private void OnActorCreated(Actor actor)
{
RelevantEnemies.GetValueOrDefault(actor.OID)?.Add(actor);
if (actor.Type is not ActorType.Player and not ActorType.Pet and not ActorType.Chocobo and not ActorType.Buddy)
for (var i = 0; i < componentCount; ++i)
{
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnActorCreated(actor);
}
}

private void OnActorDestroyed(Actor actor)
{
RelevantEnemies.GetValueOrDefault(actor.OID)?.Remove(actor);
if (actor.Type is not ActorType.Player and not ActorType.Pet and not ActorType.Chocobo and not ActorType.Buddy)
for (var i = 0; i < componentCount; ++i)
{
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnActorDestroyed(actor);
}
}

private void OnActorCastStarted(Actor actor)
{
if (actor.Type is not ActorType.Player and not ActorType.Pet and not ActorType.Chocobo and not ActorType.Buddy && (actor.CastInfo?.IsSpell() ?? false))
for (var i = 0; i < componentCount; ++i)
{
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnCastStarted(actor, actor.CastInfo);
}
}

private void OnActorCastFinished(Actor actor)
{
if (actor.Type is not ActorType.Player and not ActorType.Pet and not ActorType.Chocobo and not ActorType.Buddy && (actor.CastInfo?.IsSpell() ?? false))
for (var i = 0; i < componentCount; ++i)
{
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnCastFinished(actor, actor.CastInfo);
}
}

private void OnActorTethered(Actor actor)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnTethered(actor, actor.Tether);
}

private void OnActorUntethered(Actor actor)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnUntethered(actor, actor.Tether);
}

private void OnActorStatusGain(Actor actor, int index)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnStatusGain(actor, actor.Statuses[index]);
}

private void OnActorStatusLose(Actor actor, int index)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnStatusLose(actor, actor.Statuses[index]);
}

private void OnActorIcon(Actor actor, uint iconID, ulong targetID)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnEventIcon(actor, iconID, targetID);
}

private void OnActorCastEvent(Actor actor, ActorCastEvent cast)
{
if (actor.Type is not ActorType.Player and not ActorType.Pet and not ActorType.Chocobo and not ActorType.Buddy && cast.IsSpell())
for (var i = 0; i < componentCount; ++i)
{
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnEventCast(actor, cast);
}
}

private void OnActorEState(Actor actor, ushort state)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnActorEState(actor, state);
}

private void OnActorEAnim(Actor actor, ushort p1, ushort p2)
{
var state = ((uint)p1 << 16) | p2;
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnActorEAnim(actor, state);
}

private void OnActorPlayActionTimelineEvent(Actor actor, ushort id)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnActorPlayActionTimelineEvent(actor, id);
}

private void OnActorNpcYell(Actor actor, ushort id)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnActorNpcYell(actor, id);
}

private void OnActorModelStateChange(Actor actor)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnActorModelStateChange(actor, actor.ModelState.ModelState, actor.ModelState.AnimState1, actor.ModelState.AnimState2);
}

private void OnEnvControl(WorldState.OpEnvControl op)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnEventEnvControl(op.Index, op.State);
}

private void OnDirectorUpdate(WorldState.OpDirectorUpdate op)
{
for (var i = 0; i < componentCount; ++i)
var count = Components.Count;
for (var i = 0; i < count; ++i)
Components[i].OnEventDirectorUpdate(op.UpdateID, op.Param1, op.Param2, op.Param3, op.Param4);
}
}
2 changes: 1 addition & 1 deletion BossMod/BossModule/BossModuleMainWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public override void PreOpenCheck()
ForceMainWindow = _mgr.Config.TrishaMode; // NoBackground flag without ForceMainWindow works incorrectly for whatever reason

if (_mgr.Config.ShowWorldArrows && _mgr.ActiveModule != null && _mgr.WorldState.Party[PartyState.PlayerSlot] is var pc && pc != null)
DrawMovementHints(_mgr.ActiveModule.CalculateMovementHintsForRaidMember(PartyState.PlayerSlot, pc), pc.PosRot.Y);
DrawMovementHints(_mgr.ActiveModule.CalculateMovementHintsForRaidMember(PartyState.PlayerSlot, ref pc), pc.PosRot.Y);
}

public override void OnOpen()
Expand Down
2 changes: 2 additions & 0 deletions BossMod/BossModule/SimpleBossModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

public override bool CheckReset() => !PrimaryActor.InCombat;

protected override bool CheckPull() => base.CheckPull() && (Center - Raid.Player()!.Position).LengthSq() < 900;

protected override void UpdateModule()
{
Arena.Center = WorldState.Party.Player()?.Position ?? default;
Expand Down
Loading

0 comments on commit 0699ab3

Please sign in to comment.