Skip to content

Commit de4a4a7

Browse files
Merge pull request #934 from FFXIV-CombatReborn/mergeWIP
Necron ex module
2 parents f415b78 + 45c8ba0 commit de4a4a7

File tree

36 files changed

+1747
-943
lines changed

36 files changed

+1747
-943
lines changed

BossMod/Components/BaitAway.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,22 @@ public override void OnEventCast(Actor caster, ActorCastEvent spell)
476476
}
477477
}
478478
}
479+
480+
public override void Update()
481+
{
482+
if (EndsOnCastEvent)
483+
{
484+
var count = CurrentBaits.Count - 1;
485+
for (var i = count; i >= 0; --i)
486+
{
487+
ref var b = ref CurrentBaits.Ref(i);
488+
if (b.Source.IsDeadOrDestroyed || b.Target.IsDead)
489+
{
490+
CurrentBaits.RemoveAt(i);
491+
}
492+
}
493+
}
494+
}
479495
}
480496

481497
// a variation of BaitAwayCast for charges that end at target

BossMod/Components/StackSpread.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,8 +553,6 @@ public override void DrawArenaBackground(int pcSlot, Actor pc)
553553
public override void DrawArenaForeground(int pcSlot, Actor pc) { }
554554
}
555555

556-
// generic single hit "line stack" component, usually do not have an iconID, instead players get marked by cast event
557-
// usually these have 50 range and 4 halfWidth, but it can be modified
558556
public abstract class GenericBaitStack(BossModule module, uint aid = default, bool onlyShowOutlines = false) : GenericBaitAway(module, aid)
559557
{
560558
// TODO: add logic for min and max stack size

BossMod/Components/TankSwap.cs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,34 @@
33
// generic tank-swap component for multi-hit tankbusters, with optional aoe
44
// assume that target of the first hit is locked when mechanic starts, then subsequent targets are selected based on who the boss targets
55
// TODO: this version assumes that boss cast and first-hit are potentially from different actors; the target lock could also be things like icons, etc - generalize more...
6-
public class TankSwap(BossModule module, uint bossCast, uint firstCast, uint subsequentHit, double timeBetweenHits, AOEShape? shape = null, bool centerAtTarget = false) : GenericBaitAway(module, centerAtTarget: centerAtTarget, damageType: AIHints.PredictedDamageType.Tankbuster)
6+
public class TankSwap(BossModule module, uint bossCast, uint firstCast, uint subsequentHit, double delay1, double delay2, AOEShape? shape = null, bool centerAtTarget = false) : GenericBaitAway(module, centerAtTarget: centerAtTarget, damageType: AIHints.PredictedDamageType.Tankbuster)
77
{
8-
public TankSwap(BossModule module, uint bossCast, uint firstCast, uint subsequentHit, double timeBetweenHits, float radius, bool centerAtTarget = true) : this(module, bossCast, firstCast, subsequentHit, timeBetweenHits, new AOEShapeCircle(radius), centerAtTarget) { }
8+
public TankSwap(BossModule module, uint bossCast, uint firstCast, uint subsequentHit, double delay1, double delay2, float radius, bool centerAtTarget = true) : this(module, bossCast, firstCast, subsequentHit, delay1, delay2, new AOEShapeCircle(radius), centerAtTarget) { }
99

1010
protected Actor? _source;
1111
protected ulong _prevTarget; // before first cast, this is the target of the first hit
12-
protected DateTime _activation;
1312
public readonly AOEShape? Shape = shape;
13+
public readonly double Delay1 = delay1;
14+
public readonly double Delay2 = delay2;
15+
public readonly uint BossCast = bossCast;
16+
public readonly uint FirstCast = firstCast;
17+
public readonly uint SubsequentHit = subsequentHit;
1418

1519
public override void Update()
1620
{
17-
if (_source != null && Shape != null && WorldState.Actors.Find(NumCasts == 0 ? _prevTarget : _source.TargetID) is Actor t)
21+
if (_source != null && Shape != null)
1822
{
19-
if (CurrentBaits.Count != 0)
20-
{
21-
CurrentBaits.Ref(0).Target = t;
22-
}
23-
else
23+
var count = CurrentBaits.Count;
24+
if (count != 0 && WorldState.Actors.Find(_source.TargetID) is Actor t)
2425
{
25-
CurrentBaits.Add(new(Module.PrimaryActor, t, Shape, _activation));
26+
if (count == 1 && NumCasts == 1)
27+
{
28+
CurrentBaits.Ref(0).Target = t;
29+
}
30+
else if (count == 2)
31+
{
32+
CurrentBaits.Ref(1).Target = t;
33+
}
2634
}
2735
}
2836
}
@@ -39,26 +47,34 @@ public override void AddHints(int slot, Actor actor, TextHints hints)
3947
public override void OnCastStarted(Actor caster, ActorCastInfo spell)
4048
{
4149
var id = spell.Action.ID;
42-
if (id == bossCast)
50+
if (id == BossCast)
4351
{
4452
_source = caster;
53+
if (Shape != null && WorldState.Actors.Find(_source.TargetID) is Actor t)
54+
{
55+
AddBait(Delay1);
56+
AddBait(Delay2);
57+
void AddBait(double delay = default) => CurrentBaits.Add(new(caster, t, Shape, Module.CastFinishAt(spell, delay)));
58+
}
4559
}
46-
else if (id == firstCast)
60+
else if (id == FirstCast)
4761
{
4862
NumCasts = 0;
4963
_prevTarget = spell.TargetID;
50-
_activation = Module.CastFinishAt(spell);
5164
}
5265
}
5366

5467
public override void OnEventCast(Actor caster, ActorCastEvent spell)
5568
{
5669
var id = spell.Action.ID;
57-
if (id == firstCast || id == subsequentHit)
70+
if (id == FirstCast || id == SubsequentHit)
5871
{
5972
++NumCasts;
6073
_prevTarget = spell.MainTargetID == caster.InstanceID && spell.Targets.Count != 0 ? spell.Targets.Ref(0).ID : spell.MainTargetID;
61-
_activation = Module.WorldState.FutureTime(timeBetweenHits);
74+
if (CurrentBaits.Count != 0)
75+
{
76+
CurrentBaits.RemoveAt(0);
77+
}
6278
}
6379
}
6480
}

BossMod/Debug/DebugTeleport.cs

Lines changed: 73 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
using Dalamud.Game.ClientState.Keys;
22
using Dalamud.Plugin.Services;
3-
using BossMod.Util;
43
using Dalamud.Bindings.ImGui;
54
using FFXIVClientStructs.FFXIV.Client.System.Framework;
5+
using CSGameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
6+
using FFXIVClientStructs.FFXIV.Client.Game.Control;
67

78
namespace BossMod;
89

910
sealed class DebugTeleport
1011
{
1112
private bool EnableNoClip;
12-
private float NoClipSpeed = 0.001f;
13+
private float NoClipSpeed = 0.0001f;
1314
private Vector3 inputCoordinates;
1415

1516
public unsafe void Draw()
@@ -20,20 +21,22 @@ public unsafe void Draw()
2021
{
2122
Enable();
2223
ImGui.SameLine();
23-
ImGui.SetNextItemWidth(150);
24-
ImGui.InputFloat("No Clip Speed", ref NoClipSpeed, 0.001f);
24+
ImGui.SetNextItemWidth(150f);
25+
ImGui.InputFloat("No Clip Speed", ref NoClipSpeed, 0.0001f, default, "%.4f");
2526
}
2627
else
2728
{
2829
Disable();
2930
}
31+
var localPlayer = Service.ClientState.LocalPlayer;
32+
var pos = localPlayer != null ? localPlayer.Position : Vector3.Zero;
3033
ImGui.Separator();
3134
ImGui.EndGroup();
3235
ImGui.BeginGroup();
3336
ImGui.Text("Current Player Coordinates:");
34-
ImGui.Text("X: " + PlayerEx.Position.X.ToString("F3"));
35-
ImGui.Text("Y: " + PlayerEx.Position.Y.ToString("F3"));
36-
ImGui.Text("Z: " + PlayerEx.Position.Z.ToString("F3"));
37+
ImGui.Text("X: " + pos.X.ToString("F3"));
38+
ImGui.Text("Y: " + pos.Y.ToString("F3"));
39+
ImGui.Text("Z: " + pos.Z.ToString("F3"));
3740
ImGui.EndGroup();
3841
ImGui.Separator();
3942
ImGui.BeginGroup();
@@ -42,33 +45,22 @@ public unsafe void Draw()
4245
{
4346
SetPlayerPosition(inputCoordinates);
4447
}
45-
ImGui.SetNextItemWidth(150);
48+
ImGui.SetNextItemWidth(150f);
4649
ImGui.InputFloat("X Coordinate", ref inputCoordinates.X, 1f);
47-
ImGui.SetNextItemWidth(150);
50+
ImGui.SetNextItemWidth(150f);
4851
ImGui.InputFloat("Y Coordinate", ref inputCoordinates.Y, 1f);
49-
ImGui.SetNextItemWidth(150);
52+
ImGui.SetNextItemWidth(150f);
5053
ImGui.InputFloat("Z Coordinate", ref inputCoordinates.Z, 1f);
5154
ImGui.EndGroup();
5255
}
5356

54-
private void SetPlayerPosition(Vector3 position)
57+
private unsafe void SetPlayerPosition(Vector3 position)
5558
{
56-
try
59+
var p = Service.ClientState.LocalPlayer;
60+
if (p != null)
5761
{
58-
if (Service.ClientState.LocalPlayer != null)
59-
{
60-
// Assuming PlayerEx.SetPosition accepts a Vector3
61-
PlayerEx.SetPosition = position;
62-
Service.Log($"Player position set to: X = {position.X}, Y = {position.Y}, Z = {position.Z}");
63-
}
64-
else
65-
{
66-
Service.Log("LocalPlayer is null. Unable to set position.");
67-
}
68-
}
69-
catch (Exception ex)
70-
{
71-
Service.Log($"An error occurred while setting position: {ex.Message}");
62+
var obj = (CSGameObject*)p.Address;
63+
obj->SetPosition(position.X, position.Y, position.Z);
7264
}
7365
}
7466

@@ -86,41 +78,79 @@ private unsafe void OnUpdate(IFramework framework)
8678
{
8779
if (EnableNoClip && !Framework.Instance()->WindowInactive)
8880
{
89-
if (Service.KeyState.GetRawValue(VirtualKey.SPACE) != 0 || Utils.IsKeyPressed(LimitedKeys.Space))
81+
var p = Service.ClientState.LocalPlayer;
82+
if (p == null)
83+
{
84+
return;
85+
}
86+
var obj = (CSGameObject*)p.Address;
87+
var cameraDirH = CameraManager.Instance()->GetActiveCamera()->DirH;
88+
89+
if (IsKeyPressed(32)) // space to go up
9090
{
9191
Service.KeyState.SetRawValue(VirtualKey.SPACE, 0);
92-
PlayerEx.SetPosition = (PlayerEx.Object.Position.X, PlayerEx.Object.Position.Y + NoClipSpeed, PlayerEx.Object.Position.Z).ToVector3();
92+
var pos = p.Position;
93+
obj->SetPosition(pos.X, pos.Y + NoClipSpeed, pos.Z);
9394
}
94-
if (Service.KeyState.GetRawValue(VirtualKey.LSHIFT) != 0 || Utils.IsKeyPressed(LimitedKeys.LeftShiftKey))
95+
else if (IsKeyPressed(160)) // left shift to go down
9596
{
9697
Service.KeyState.SetRawValue(VirtualKey.LSHIFT, 0);
97-
PlayerEx.SetPosition = (PlayerEx.Object.Position.X, PlayerEx.Object.Position.Y - NoClipSpeed, PlayerEx.Object.Position.Z).ToVector3();
98+
var pos = p.Position;
99+
obj->SetPosition(pos.X, pos.Y - NoClipSpeed, pos.Z);
98100
}
99-
if (Service.KeyState.GetRawValue(VirtualKey.W) != 0 || Utils.IsKeyPressed(LimitedKeys.W))
101+
if (IsKeyPressed(87)) // W to go forward
100102
{
101-
var newPoint = Utils.RotatePoint(PlayerEx.Object.Position.X, PlayerEx.Object.Position.Z, MathF.PI - PlayerEx.CameraEx->DirH, PlayerEx.Object.Position + new Vector3(0, 0, NoClipSpeed));
102103
Service.KeyState.SetRawValue(VirtualKey.W, 0);
103-
PlayerEx.SetPosition = newPoint;
104+
var pos = p.Position;
105+
var newPos = RotatePoint(pos.X, pos.Z, MathF.PI - cameraDirH, pos + new Vector3(0f, 0f, NoClipSpeed));
106+
SetPosition(ref newPos);
104107
}
105-
if (Service.KeyState.GetRawValue(VirtualKey.S) != 0 || Utils.IsKeyPressed(LimitedKeys.S))
108+
else if (IsKeyPressed(83)) // S to go backwards
106109
{
107-
var newPoint = Utils.RotatePoint(PlayerEx.Object.Position.X, PlayerEx.Object.Position.Z, MathF.PI - PlayerEx.CameraEx->DirH, PlayerEx.Object.Position + new Vector3(0, 0, -NoClipSpeed));
108110
Service.KeyState.SetRawValue(VirtualKey.S, 0);
109-
PlayerEx.SetPosition = newPoint;
111+
var pos = p.Position;
112+
var newPos = RotatePoint(pos.X, pos.Z, MathF.PI - cameraDirH, pos + new Vector3(0f, 0f, -NoClipSpeed));
113+
SetPosition(ref newPos);
110114
}
111-
if (Service.KeyState.GetRawValue(VirtualKey.A) != 0 || Utils.IsKeyPressed(LimitedKeys.A))
115+
if (IsKeyPressed(65)) // A to go left
112116
{
113-
var newPoint = Utils.RotatePoint(PlayerEx.Object.Position.X, PlayerEx.Object.Position.Z, MathF.PI - PlayerEx.CameraEx->DirH, PlayerEx.Object.Position + new Vector3(NoClipSpeed, 0, 0));
114117
Service.KeyState.SetRawValue(VirtualKey.A, 0);
115-
PlayerEx.SetPosition = newPoint;
118+
var pos = p.Position;
119+
var newPos = RotatePoint(pos.X, pos.Z, MathF.PI - cameraDirH, pos + new Vector3(NoClipSpeed, 0f, 0f));
120+
SetPosition(ref newPos);
116121
}
117-
if (Service.KeyState.GetRawValue(VirtualKey.D) != 0 || Utils.IsKeyPressed(LimitedKeys.D))
122+
else if (IsKeyPressed(68)) // D to go right
118123
{
119-
var newPoint = Utils.RotatePoint(PlayerEx.Object.Position.X, PlayerEx.Object.Position.Z, MathF.PI - PlayerEx.CameraEx->DirH, PlayerEx.Object.Position + new Vector3(-NoClipSpeed, 0, 0));
120124
Service.KeyState.SetRawValue(VirtualKey.D, 0);
121-
PlayerEx.SetPosition = newPoint;
125+
var pos = p.Position;
126+
var newPos = RotatePoint(pos.X, pos.Z, MathF.PI - cameraDirH, pos + new Vector3(-NoClipSpeed, 0f, 0f));
127+
SetPosition(ref newPos);
128+
}
129+
130+
void SetPosition(ref Vector3 pos) => obj->SetPosition(pos.X, pos.Y, pos.Z);
131+
static Vector3 RotatePoint(float cx, float cy, float angle, Vector3 p)
132+
{
133+
if (angle == default)
134+
{
135+
return p;
136+
}
137+
var (sin, cos) = MathF.SinCos(angle);
138+
139+
p.X -= cx;
140+
p.Z -= cy;
141+
142+
var xnew = p.X * cos - p.Z * sin;
143+
var ynew = p.X * sin + p.Z * cos;
144+
145+
p.X = xnew + cx;
146+
p.Z = ynew + cy;
147+
return p;
148+
}
149+
static bool IsKeyPressed(int key)
150+
{
151+
static bool IsBitSet(short b, int pos) => (b & (1 << pos)) != 0;
152+
return key != 0 && IsBitSet(PInvoke.User32.GetAsyncKeyState(key), 15);
122153
}
123154
}
124155
}
125156
}
126-

BossMod/Framework/ActionManagerEx.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public void FaceDirection(Angle direction)
161161
var player = (Character*)GameObjectManager.Instance()->Objects.IndexSorted[0].Value;
162162
if (player != null)
163163
{
164-
var position = player->Position.ToSystem() + direction.ToDirection().ToVec3();
164+
var position = (Vector3)player->Position + direction.ToDirection().ToVec3();
165165
_inst->AutoFaceTargetPosition(&position);
166166

167167
var pm = (PlayerMove*)player;

BossMod/Framework/IPCProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public IPCProvider(RotationModuleManager autorotation, ActionManagerEx amex, Mov
1313
Register("HasModuleByDataId", (uint dataId) => BossModuleRegistry.FindByOID(dataId) != null);
1414
Register("Configuration", (List<string> args, bool save) => Service.Config.ConsoleCommand(args.AsSpan(), save));
1515

16-
DateTime lastModified = DateTime.Now;
16+
var lastModified = DateTime.Now;
1717
Service.Config.Modified.Subscribe(() => lastModified = DateTime.Now);
1818
Register("Configuration.LastModified", () => lastModified);
1919

0 commit comments

Comments
 (0)