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 cleanup #542

Merged
merged 1 commit into from
Jan 4, 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
8 changes: 4 additions & 4 deletions BossMod/BossModule/StateMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class Phase(State initialState, string name, float expectedDuration = -1)
public PhaseHint Hint = PhaseHint.None; // special flags for phase
}

public List<Phase> Phases { get; private init; } = phases;
public readonly List<Phase> Phases = phases;

private DateTime _curTime;
private DateTime _activation;
Expand All @@ -68,14 +68,14 @@ public class Phase(State initialState, string name, float expectedDuration = -1)
public float TimeSinceTransition => (float)(_curTime - _lastTransition).TotalSeconds;
public float TimeSinceTransitionClamped => Math.Min(TimeSinceTransition, ActiveState?.Duration ?? 0);

public int ActivePhaseIndex { get; private set; } = -1;
public int ActivePhaseIndex = -1;
public Phase? ActivePhase => Phases.ElementAtOrDefault(ActivePhaseIndex);
public State? ActiveState { get; private set; }
public State? ActiveState;

public void Start(DateTime now)
{
_activation = _curTime = now;
if (Phases.Count > 0)
if (Phases.Count != 0)
TransitionToPhase(0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,22 @@ class IceScreamFrozenSwirl(BossModule module) : Components.GenericAOEs(module)
{
private static readonly AOEShapeRect rect = new(20, 10);
private static readonly AOEShapeCircle circle = new(15);
private readonly List<AOEInstance> _aoesCircle = [];
private readonly List<AOEInstance> _aoesRect = [];
private readonly HashSet<Actor> circleAOE = [];
private readonly HashSet<Actor> rectAOE = [];
private readonly List<AOEInstance> _aoesCircle = new(4), _aoesRect = new(4);
private readonly List<Actor> circleAOE = new(4), rectAOE = new(4);

public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) => _aoesCircle.Take(2).Concat(_aoesRect.Take(2));
public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor)
{
var countCircle = _aoesCircle.Count;
var countRect = _aoesRect.Count;
if (countCircle == 0 && countRect == 0)
return [];
var result = new List<AOEInstance>(4);
for (var i = 0; i < 2 && i < countCircle; ++i)
result.Add(_aoesCircle[i]);
for (var i = 0; i < 2 && i < countRect; ++i)
result.Add(_aoesRect[i]);
return result;
}

public override void OnActorCreated(Actor actor)
{
Expand All @@ -89,10 +99,10 @@ public override void OnTethered(Actor source, ActorTetherInfo tether)
circleAOE.Remove(source);
if (_aoesCircle.Count == 2)
{
foreach (var e in circleAOE)
_aoesCircle.Add(new(circle, e.Position, default, activation1));
for (var i = 0; i < circleAOE.Count; ++i)
_aoesCircle.Add(new(circle, circleAOE[i].Position, default, activation1));
circleAOE.Clear();
_aoesCircle.SortBy(x => x.Activation);
_aoesCircle.Sort((x, y) => x.Activation.CompareTo(y.Activation));
}
}
else if (rectAOE.Contains(source))
Expand All @@ -101,20 +111,23 @@ public override void OnTethered(Actor source, ActorTetherInfo tether)
rectAOE.Remove(source);
if (_aoesRect.Count == 2)
{
foreach (var e in rectAOE)
for (var i = 0; i < rectAOE.Count; ++i)
{
var e = rectAOE[i];
_aoesRect.Add(new(rect, e.Position, e.Rotation, activation1));
}
rectAOE.Clear();
_aoesRect.SortBy(x => x.Activation);
_aoesRect.Sort((x, y) => x.Activation.CompareTo(y.Activation));
}
}
}
}

public override void OnCastFinished(Actor caster, ActorCastInfo spell)
{
if (_aoesRect.Count > 0 && (AID)spell.Action.ID == AID.IceScream)
if (_aoesRect.Count != 0 && (AID)spell.Action.ID == AID.IceScream)
_aoesRect.RemoveAt(0);
else if (_aoesCircle.Count > 0 && (AID)spell.Action.ID == AID.FrozenSwirl)
else if (_aoesCircle.Count != 0 && (AID)spell.Action.ID == AID.FrozenSwirl)
_aoesCircle.RemoveAt(0);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ public D050OrigenicsAerostatStates(D050OrigenicsAerostat module) : base(module)
TrivialPhase()
.ActivateOnEnter<IncendiaryCircle>()
.ActivateOnEnter<GrenadoShot>()
.Raw.Update = () => module.Enemies(OID.Aerostat2).Concat([module.PrimaryActor]).Concat(module.Enemies(OID.OrigenicsSentryS9))
.Concat(module.Enemies(OID.OrigenicsSentryS92)).Concat(module.Enemies(OID.OrigenicsSentryG10)).All(e => e.IsDeadOrDestroyed);
.Raw.Update = () =>
{
var enemies = module.Enemies(D050OrigenicsAerostat.Trash);
for (var i = 0; i < enemies.Count; ++i)
{
var e = enemies[i];
if (!e.IsDeadOrDestroyed)
return false;
}
return true;
};
}
}

Expand All @@ -40,10 +49,10 @@ public class D050OrigenicsAerostat(WorldState ws, Actor primary) : BossModule(ws
{
private static readonly ArenaBoundsComplex arena = new([new Polygon(new(-116, -80), 14.5f, 6, 30.Degrees()), new Rectangle(new(-88, -80), 20, 5.5f),
new Polygon(new(-60, -80), 14.5f, 6, 30.Degrees()), new Rectangle(new(-144, -80), 20, 5.5f)]);
public static readonly uint[] Trash = [(uint)OID.Boss, (uint)OID.Aerostat2, (uint)OID.OrigenicsSentryS9, (uint)OID.OrigenicsSentryS92, (uint)OID.OrigenicsSentryG10];

protected override void DrawEnemies(int pcSlot, Actor pc)
{
Arena.Actor(PrimaryActor);
Arena.Actors(Enemies(OID.Aerostat2).Concat(Enemies(OID.OrigenicsSentryS9)).Concat(Enemies(OID.OrigenicsSentryS92)).Concat(Enemies(OID.OrigenicsSentryG10)));
Arena.Actors(Enemies(Trash));
}
}
107 changes: 78 additions & 29 deletions BossMod/Modules/Dawntrail/Dungeon/D05Origenics/D052Deceiver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public enum OID : uint

public enum AID : uint
{
AutoAttack = 870, // Boss->player, no cast, single-target
AutoAttack1 = 870, // Boss->player, no cast, single-target
AutoAttack2 = 873, // OrigenicsSentryG92->player, no cast, single-target
Teleport = 36362, // Boss->location, no cast, single-target

Expand Down Expand Up @@ -111,7 +111,7 @@ class Electray(BossModule module) : Components.SpreadFromCastTargets(module, Act

class Surge(BossModule module) : Components.Knockback(module)
{
private readonly List<Source> _sources = [];
public readonly List<Source> SourcesList = new(2);
private const float XWest = -187.5f, XEast = -156.5f;
private const int ZRow1 = -122, ZRow2 = -132, ZRow3 = -142, ZRow4 = -152, ZRow5 = -162;
private static readonly WDir offset = new(4, 0);
Expand All @@ -124,16 +124,18 @@ class Surge(BossModule module) : Components.Knockback(module)
private static readonly SafeWall[] walls2B1C = [new(new(XWest, ZRow4), new(XWest, ZRow5)), new(new(XWest, ZRow2), new(XWest, ZRow3)),
new(new(XEast, ZRow3), new(XEast, ZRow4)), new(new(XEast, ZRow1), new(XEast, ZRow2))];
private static readonly AOEShapeCone _shape = new(60, 90.Degrees());
private Func<WPos, float>? distance;

public override IEnumerable<Source> Sources(int slot, Actor actor) => _sources;
public override IEnumerable<Source> Sources(int slot, Actor actor) => SourcesList;

public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID == AID.Surge)
{
var activation = Module.CastFinishAt(spell, 0.8f);
_sources.Add(new(caster.Position, 30, activation, _shape, spell.Rotation + Angle.AnglesCardinals[3], Kind.DirForward, default, GetActiveSafeWalls()));
_sources.Add(new(caster.Position, 30, activation, _shape, spell.Rotation + Angle.AnglesCardinals[0], Kind.DirForward, default, GetActiveSafeWalls()));
var activation = Module.CastFinishAt(spell);
var safewalls = GetActiveSafeWalls();
SourcesList.Add(new(caster.Position, 30, activation, _shape, spell.Rotation + Angle.AnglesCardinals[3], Kind.DirForward, default, safewalls));
SourcesList.Add(new(caster.Position, 30, activation, _shape, spell.Rotation + Angle.AnglesCardinals[0], Kind.DirForward, default, safewalls));
}
}

Expand All @@ -160,50 +162,96 @@ public override void OnCastFinished(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID == AID.Surge)
{
_sources.Clear();
SourcesList.Clear();
distance = null;
++NumCasts;
}
}

public override void AddAIHints(int slot, Actor actor, PartyRolesConfig.Assignment assignment, AIHints hints)
{
var source = Sources(slot, actor).FirstOrDefault();
if (source != default)
if (SourcesList.Count != 0)
{
var forbidden = new List<Func<WPos, float>>();
var safewalls = GetActiveSafeWalls();
for (var i = 0; i < safewalls.Length; ++i)
forbidden.Add(ShapeDistance.InvertedRect(new(Arena.Center.X, safewalls[i].Vertex1.Z - 5), safewalls[i].Vertex1.X == XWest ? -offset : offset, 10, default, 20));
hints.AddForbiddenZone(p => forbidden.Max(f => f(p)), source.Activation);
if (distance == null)
{
var safewalls = GetActiveSafeWalls();
var forbidden = new List<Func<WPos, float>>(4);

var centerX = Arena.Center.X;
for (var i = 0; i < 4; ++i)
{
var safeWall = safewalls[i];
forbidden.Add(ShapeDistance.InvertedRect(new(centerX, safeWall.Vertex1.Z - 5), safeWall.Vertex1.X == XWest ? -offset : offset, 10, default, 20));
}
distance = p =>
{
var maxDistance = float.MinValue;
for (var i = 0; i < 4; ++i)
{
var distance = forbidden[i](p);
if (distance > maxDistance)
{
maxDistance = distance;
}
}
return maxDistance;
};
}
hints.AddForbiddenZone(distance, SourcesList[0].Activation);
}
}
}

class SurgeHint(BossModule module) : Components.GenericAOEs(module)
{
private const string Risk2Hint = "Walk into safespot for knockback!";
private const string StayHint = "Wait inside safespot for knockback!";
private const string Hint = "Wait inside safespot for knockback!";
private static readonly AOEShapeRect rect = new(15.5f, 5);
private readonly List<AOEInstance> _hints = new(4);
private readonly Surge _kb = module.FindComponent<Surge>()!;

public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor) => _hints;

public override IEnumerable<AOEInstance> ActiveAOEs(int slot, Actor actor)
public override void OnCastStarted(Actor caster, ActorCastInfo spell)
{
var component = Module.FindComponent<Surge>()!.Sources(slot, actor).Any();
var activeSafeWalls = Module.FindComponent<Surge>()!.GetActiveSafeWalls();
if (component)
for (var i = 0; i < activeSafeWalls.Length; ++i)
yield return new(rect, new(Arena.Center.X, activeSafeWalls[i].Vertex1.Z - 5), activeSafeWalls[i].Vertex1.X == -187.5f ? Angle.AnglesCardinals[0] : Angle.AnglesCardinals[3], default, Colors.SafeFromAOE, false);
if ((AID)spell.Action.ID == AID.Surge)
{
var activeSafeWalls = _kb.GetActiveSafeWalls();
var centerX = Arena.Center.X;
for (var i = 0; i < 4; ++i)
{
var safewall = activeSafeWalls[i].Vertex1;
_hints.Add(new(rect, new(centerX, safewall.Z - 5), safewall.X == -187.5f ? Angle.AnglesCardinals[0] : Angle.AnglesCardinals[3], default, Colors.SafeFromAOE, false));
}
}
}

public override void OnCastFinished(Actor caster, ActorCastInfo spell)
{
if ((AID)spell.Action.ID == AID.Surge)
_hints.Clear();
}

public override void AddHints(int slot, Actor actor, TextHints hints)
{
base.AddHints(slot, actor, hints);
var activeSafespot = ActiveAOEs(slot, actor).Where(c => c.Shape == rect).ToList();
if (activeSafespot.Count != 0)
AOEInstance[] activeSafespot = [.. ActiveAOEs(slot, actor)];
var len = activeSafespot.Length;
if (len != 0)
{
if (!activeSafespot.Any(c => c.Check(actor.Position)))
hints.Add(Risk2Hint);
var isPositionSafe = false;
for (var i = 0; i < len; ++i)
{
if (activeSafespot[i].Check(actor.Position))
{
isPositionSafe = true;
break;
}
}
if (!isPositionSafe)
{
hints.Add(Hint);
}
else
hints.Add(StayHint, false);
hints.Add(Hint, false);
}
}
}
Expand Down Expand Up @@ -231,6 +279,7 @@ public class D052Deceiver(WorldState ws, Actor primary) : BossModule(ws, primary
protected override void DrawEnemies(int pcSlot, Actor pc)
{
Arena.Actor(PrimaryActor);
Arena.Actors(Enemies(OID.OrigenicsSentryG92).Concat(Enemies(OID.OrigenicsSentryG91)));
Arena.Actors(Enemies(OID.OrigenicsSentryG92));
Arena.Actors(Enemies(OID.OrigenicsSentryG91));
}
}
Loading