Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some quest module improvements #585

Merged
merged 1 commit into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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