2022-09-03 23:45:16 +00:00
|
|
|
using System.Numerics;
|
|
|
|
using Dalamud.Game;
|
2022-09-09 09:42:46 +00:00
|
|
|
using Dalamud.Game.ClientState.Conditions;
|
2022-09-04 03:32:38 +00:00
|
|
|
using Dalamud.Logging;
|
2022-09-05 08:02:34 +00:00
|
|
|
using Lumina.Excel.GeneratedSheets;
|
2022-09-03 23:45:16 +00:00
|
|
|
using Newtonsoft.Json;
|
2022-09-04 05:03:59 +00:00
|
|
|
using OrangeGuidanceTomestone.Helpers;
|
2022-09-03 23:45:16 +00:00
|
|
|
|
|
|
|
namespace OrangeGuidanceTomestone;
|
|
|
|
|
|
|
|
internal class Messages : IDisposable {
|
2022-09-06 04:24:32 +00:00
|
|
|
internal static readonly string[] VfxPaths = {
|
|
|
|
"bg/ffxiv/fst_f1/common/vfx/eff/b0941trp1a_o.avfx",
|
|
|
|
"bg/ffxiv/fst_f1/common/vfx/eff/b0941trp1b_o.avfx",
|
|
|
|
"bg/ffxiv/fst_f1/common/vfx/eff/b0941trp1c_o.avfx",
|
|
|
|
"bg/ffxiv/fst_f1/common/vfx/eff/b0941trp1d_o.avfx",
|
|
|
|
"bg/ffxiv/fst_f1/common/vfx/eff/b0941trp1e_o.avfx",
|
2022-09-09 09:39:33 +00:00
|
|
|
"bg/ex2/02_est_e3/common/vfx/eff/b0941trp1f_o.avfx",
|
2022-09-06 04:24:32 +00:00
|
|
|
};
|
2022-09-03 23:45:16 +00:00
|
|
|
|
2022-09-09 09:42:46 +00:00
|
|
|
|
2022-09-03 23:45:16 +00:00
|
|
|
private Plugin Plugin { get; }
|
|
|
|
|
2022-09-04 02:23:35 +00:00
|
|
|
private SemaphoreSlim CurrentMutex { get; } = new(1, 1);
|
2022-09-04 02:52:18 +00:00
|
|
|
private Dictionary<Guid, Message> Current { get; } = new();
|
2022-09-03 23:45:16 +00:00
|
|
|
private Queue<Message> SpawnQueue { get; } = new();
|
|
|
|
|
2022-09-05 08:02:34 +00:00
|
|
|
private HashSet<uint> Trials { get; } = new();
|
|
|
|
private HashSet<uint> DeepDungeons { get; } = new();
|
|
|
|
|
2022-09-09 09:42:46 +00:00
|
|
|
private bool CutsceneActive {
|
|
|
|
get {
|
|
|
|
var condition = this.Plugin.Condition;
|
|
|
|
return condition[ConditionFlag.OccupiedInCutSceneEvent]
|
|
|
|
|| condition[ConditionFlag.WatchingCutscene78];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool GposeActive {
|
|
|
|
get {
|
|
|
|
var condition = this.Plugin.Condition;
|
|
|
|
return condition[ConditionFlag.WatchingCutscene];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-09 09:49:52 +00:00
|
|
|
private bool _inCutscene;
|
|
|
|
private bool _inGpose;
|
|
|
|
|
2022-09-03 23:45:16 +00:00
|
|
|
internal Messages(Plugin plugin) {
|
|
|
|
this.Plugin = plugin;
|
|
|
|
|
2022-09-05 08:02:34 +00:00
|
|
|
foreach (var cfc in this.Plugin.DataManager.GetExcelSheet<ContentFinderCondition>()!) {
|
2022-09-06 02:45:45 +00:00
|
|
|
// Trials, Raids, and Ultimate Raids
|
|
|
|
if (cfc.ContentType.Row is 4 or 5 or 28) {
|
|
|
|
// "Raids" - but we only want non-alliance raids
|
|
|
|
if (cfc.ContentType.Row == 5 && cfc.ContentMemberType.Row == 4) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-09-05 08:02:34 +00:00
|
|
|
this.Trials.Add(cfc.TerritoryType.Row);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfc.ContentType.Row == 21) {
|
|
|
|
this.DeepDungeons.Add(cfc.TerritoryType.Row);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-04 20:39:09 +00:00
|
|
|
if (this.Plugin.Config.ApiKey != string.Empty) {
|
|
|
|
this.SpawnVfx();
|
|
|
|
}
|
2022-09-03 23:45:16 +00:00
|
|
|
|
2022-09-09 09:49:52 +00:00
|
|
|
this.Plugin.Framework.Update += this.RemoveConditionally;
|
2022-09-03 23:45:16 +00:00
|
|
|
this.Plugin.Framework.Update += this.HandleSpawnQueue;
|
|
|
|
this.Plugin.ClientState.Login += this.SpawnVfx;
|
|
|
|
this.Plugin.ClientState.Logout += this.RemoveVfx;
|
|
|
|
this.Plugin.ClientState.TerritoryChanged += this.SpawnVfx;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose() {
|
|
|
|
this.Plugin.ClientState.TerritoryChanged -= this.SpawnVfx;
|
|
|
|
this.Plugin.ClientState.Logout -= this.RemoveVfx;
|
|
|
|
this.Plugin.ClientState.Login -= this.SpawnVfx;
|
|
|
|
this.Plugin.Framework.Update -= this.HandleSpawnQueue;
|
2022-09-09 09:49:52 +00:00
|
|
|
this.Plugin.Framework.Update -= this.RemoveConditionally;
|
2022-09-04 02:11:18 +00:00
|
|
|
|
2022-09-05 08:02:34 +00:00
|
|
|
this.RemoveVfx();
|
2022-09-03 23:45:16 +00:00
|
|
|
}
|
|
|
|
|
2022-09-09 09:49:52 +00:00
|
|
|
private void RemoveConditionally(Framework framework) {
|
|
|
|
var nowCutscene = this.CutsceneActive;
|
|
|
|
var cutsceneChanged = this._inCutscene != nowCutscene;
|
|
|
|
if (this.Plugin.Config.DisableInCutscene && cutsceneChanged) {
|
|
|
|
if (nowCutscene) {
|
|
|
|
this.RemoveVfx();
|
|
|
|
} else {
|
|
|
|
this.SpawnVfx();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var nowGpose = this.GposeActive;
|
|
|
|
var gposeChanged = this._inGpose != nowGpose;
|
2022-09-09 09:52:10 +00:00
|
|
|
if (this.Plugin.Config.DisableInGpose && gposeChanged) {
|
2022-09-09 09:49:52 +00:00
|
|
|
if (nowGpose) {
|
|
|
|
this.RemoveVfx();
|
|
|
|
} else {
|
|
|
|
this.SpawnVfx();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this._inCutscene = nowCutscene;
|
|
|
|
this._inGpose = nowGpose;
|
|
|
|
}
|
|
|
|
|
2022-09-03 23:45:16 +00:00
|
|
|
private unsafe void HandleSpawnQueue(Framework framework) {
|
|
|
|
if (!this.SpawnQueue.TryDequeue(out var message)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-05 08:02:34 +00:00
|
|
|
PluginLog.Debug($"spawning vfx for {message.Id}");
|
2022-09-04 21:02:13 +00:00
|
|
|
var rotation = Quaternion.CreateFromYawPitchRoll(message.Yaw, 0, 0);
|
2022-09-06 04:24:32 +00:00
|
|
|
var path = message.Glyph < 0 || message.Glyph >= VfxPaths.Length
|
|
|
|
? VfxPaths[0]
|
|
|
|
: VfxPaths[message.Glyph];
|
|
|
|
if (this.Plugin.Vfx.SpawnStatic(message.Id, path, message.Position, rotation) == null) {
|
2022-09-05 08:02:34 +00:00
|
|
|
PluginLog.Debug("trying again");
|
2022-09-04 02:52:18 +00:00
|
|
|
this.SpawnQueue.Enqueue(message);
|
|
|
|
}
|
2022-09-03 23:45:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void SpawnVfx(object? sender, EventArgs e) {
|
|
|
|
this.SpawnVfx();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void SpawnVfx(object? sender, ushort e) {
|
|
|
|
this.SpawnVfx();
|
|
|
|
}
|
|
|
|
|
2022-09-04 05:10:48 +00:00
|
|
|
internal void SpawnVfx() {
|
2022-09-03 23:45:16 +00:00
|
|
|
var territory = this.Plugin.ClientState.TerritoryType;
|
2022-09-04 23:43:58 +00:00
|
|
|
if (territory == 0 || this.Plugin.Config.BannedTerritories.Contains(territory)) {
|
2022-09-03 23:45:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-05 08:02:34 +00:00
|
|
|
if (this.Plugin.Config.DisableTrials && this.Trials.Contains(territory)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.Plugin.Config.DisableDeepDungeon && this.DeepDungeons.Contains(territory)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-09 09:42:46 +00:00
|
|
|
if (this.Plugin.Config.DisableInCutscene && this.CutsceneActive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.Plugin.Config.DisableInGpose && this.GposeActive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-03 23:45:16 +00:00
|
|
|
this.RemoveVfx(null, null);
|
|
|
|
|
|
|
|
Task.Run(async () => {
|
2022-09-04 05:03:59 +00:00
|
|
|
var resp = await ServerHelper.SendRequest(
|
|
|
|
this.Plugin.Config.ApiKey,
|
|
|
|
HttpMethod.Get,
|
2022-09-05 10:52:32 +00:00
|
|
|
$"/messages/{territory}"
|
2022-09-04 05:03:59 +00:00
|
|
|
);
|
2022-09-03 23:45:16 +00:00
|
|
|
var json = await resp.Content.ReadAsStringAsync();
|
|
|
|
var messages = JsonConvert.DeserializeObject<Message[]>(json)!;
|
2022-09-04 02:23:35 +00:00
|
|
|
|
|
|
|
await this.CurrentMutex.WaitAsync();
|
2022-09-04 02:52:18 +00:00
|
|
|
this.Current.Clear();
|
2022-09-04 02:23:35 +00:00
|
|
|
|
2022-09-03 23:45:16 +00:00
|
|
|
foreach (var message in messages) {
|
2022-09-04 02:52:18 +00:00
|
|
|
this.Current[message.Id] = message;
|
2022-09-03 23:45:16 +00:00
|
|
|
this.SpawnQueue.Enqueue(message);
|
|
|
|
}
|
2022-09-04 02:52:18 +00:00
|
|
|
|
|
|
|
this.CurrentMutex.Release();
|
2022-09-03 23:45:16 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private void RemoveVfx(object? sender, EventArgs? e) {
|
2022-09-04 23:46:23 +00:00
|
|
|
this.RemoveVfx();
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void RemoveVfx() {
|
2022-09-03 23:45:16 +00:00
|
|
|
this.Plugin.Vfx.RemoveAll();
|
|
|
|
}
|
2022-09-04 02:23:35 +00:00
|
|
|
|
2022-09-05 08:02:34 +00:00
|
|
|
internal void Clear() {
|
|
|
|
this.CurrentMutex.Wait();
|
|
|
|
this.Current.Clear();
|
|
|
|
this.CurrentMutex.Release();
|
|
|
|
}
|
|
|
|
|
2022-09-04 02:52:18 +00:00
|
|
|
internal IEnumerable<Message> Nearby() {
|
2022-09-04 02:23:35 +00:00
|
|
|
if (this.Plugin.ClientState.LocalPlayer is not { } player) {
|
|
|
|
return Array.Empty<Message>();
|
|
|
|
}
|
|
|
|
|
|
|
|
var position = player.Position;
|
|
|
|
|
2022-09-04 02:52:18 +00:00
|
|
|
this.CurrentMutex.Wait();
|
|
|
|
var nearby = this.Current
|
|
|
|
.Values
|
2022-09-04 05:20:58 +00:00
|
|
|
.Where(msg => Math.Abs(msg.Position.Y - position.Y) <= 1f)
|
|
|
|
.Where(msg => Vector3.Distance(msg.Position, position) <= 2f)
|
2022-09-04 02:52:18 +00:00
|
|
|
.ToList();
|
|
|
|
this.CurrentMutex.Release();
|
|
|
|
|
|
|
|
return nearby;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Add(Message message) {
|
2022-09-04 05:19:30 +00:00
|
|
|
this.CurrentMutex.Wait();
|
2022-09-04 02:52:18 +00:00
|
|
|
this.Current[message.Id] = message;
|
2022-09-04 05:19:30 +00:00
|
|
|
this.CurrentMutex.Release();
|
2022-09-04 02:52:18 +00:00
|
|
|
this.SpawnQueue.Enqueue(message);
|
2022-09-04 02:23:35 +00:00
|
|
|
}
|
2022-09-04 05:19:30 +00:00
|
|
|
|
|
|
|
internal void Remove(Guid id) {
|
|
|
|
this.CurrentMutex.Wait();
|
|
|
|
this.Current.Remove(id);
|
|
|
|
this.CurrentMutex.Release();
|
|
|
|
}
|
2022-09-03 23:45:16 +00:00
|
|
|
}
|