Skip to content
Open
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
21 changes: 21 additions & 0 deletions DynamicBridge/Checkers/Races.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DynamicBridge.Core
{
public enum Races
{
No_Race = 0,
Hyur = 1,
Elezen = 2,
Lalafell = 3,
Miqote = 4,
Roegadyn = 5,
Au_ra = 6,
Hrothgar = 7,
Viera = 8,
}
}
3 changes: 3 additions & 0 deletions DynamicBridge/Configuration/ApplyRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class ApplyRule
public List<ETime> Times = [];
public List<uint> Worlds = [];
public List<int> Gearsets = [];
public List<Races> Races = [];
public List<string> Players = [];
public List<TimelineSegment> Precise_Times = [
new TimelineSegment((float)0/24,(float)5/24,0),
Expand All @@ -38,6 +39,7 @@ public class ApplyRule
];
public List<string> SelectedPresets = [];
public bool Passthrough = false;
public bool valid = true;
public NotConditions Not = new();

[Serializable]
Expand All @@ -54,6 +56,7 @@ public class NotConditions
public List<ETime> Times = [];
public List<uint> Worlds = [];
public List<int> Gearsets = [];
public List<Races> Races = [];
public List<string> Players = [];
}
}
Expand Down
2 changes: 2 additions & 0 deletions DynamicBridge/Configuration/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public class Config : IEzConfig
public bool Cond_Job = true;
public bool Cond_World = false;
public bool Cond_Gearset = false;
public bool Cond_Race = false;
public bool Cond_Race_Bonus = false;
public bool Cond_Players = false;

public bool Cond_Time_Precise = false;
Expand Down
82 changes: 80 additions & 2 deletions DynamicBridge/DynamicBridge.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DynamicBridge.Configuration;
using DynamicBridge.Configuration;
using DynamicBridge.Core;
using DynamicBridge.Gui;
using DynamicBridge.IPC;
Expand All @@ -20,6 +20,7 @@
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
using Glamourer.Api.Enums;
using System.IO;
using System.IO.Compression;
using System.Linq;
Expand Down Expand Up @@ -315,6 +316,14 @@ private void OnUpdate()
{
foreach(var x in profile.Rules)
{
if (C.Cond_Race)
{
x.valid = CheckValidRace(profile.Presets, x, "Customize,Race");
if (x.Enabled)
{
x.Enabled = x.valid;
}
}
if(
x.Enabled
&&
Expand Down Expand Up @@ -354,7 +363,9 @@ private void OnUpdate()
(!C.Cond_Gearset || ((x.Gearsets.Count == 0 || x.Gearsets.Contains(RaptureGearsetModule.Instance()->CurrentGearsetIndex))
&& (!C.AllowNegativeConditions || !x.Not.Gearsets.Contains(RaptureGearsetModule.Instance()->CurrentGearsetIndex))))
&&
(!C.Cond_Players || (x.Players.Count == 0 || x.Players.Any(rp => GuiPlayers.SimpleNearbyPlayers().Any(sp => rp == sp.Name && C.selectedPlayers.Any(sel => sel.Name == sp.Name && (sel.Distance >= sp.Distance || sel.Distance >= 150f)))))
(!C.Cond_Race || ((x.Races.Count == 0 || x.Races.Any(s => s == (Races)(int)GlamourerManager.GetMyState()["Customize"]["Race"]["Value"]))
&& (!C.AllowNegativeConditions || !x.Not.Races.Any(s => s == (Races)(int)GlamourerManager.GetMyState()["Customize"]["Race"]["Value"]))))
&& (!C.Cond_Players || (x.Players.Count == 0 || x.Players.Any(rp => GuiPlayers.SimpleNearbyPlayers().Any(sp => rp == sp.Name && C.selectedPlayers.Any(sel => sel.Name == sp.Name && (sel.Distance >= sp.Distance || sel.Distance >= 150f)))))
&& (!C.AllowNegativeConditions || !x.Not.Players.Any(rp => GuiPlayers.SimpleNearbyPlayers().Any(sp => rp == sp.Name && C.selectedPlayers.Any(sel => sel.Name == sp.Name && (sel.Distance >= sp.Distance || sel.Distance >= 150f))))))
)
{
Expand Down Expand Up @@ -667,4 +678,71 @@ public void Dispose()
P = null;
C = null;
}

private static bool CheckValidRace(List<Preset> presets, ApplyRule rule, string path)
{
bool valid = true;
List<Races> racesToCheck = rule.Races;
List<Races> notRacesToCheck = rule.Not.Races;
if (racesToCheck.Count + notRacesToCheck.Count == 0)
return true;
foreach(string preset_name in rule.SelectedPresets)
{
foreach(Preset preset in presets)
{
if(preset_name == preset.Name)
{
foreach(string design_name in preset.Glamourer)
{
var design = (GlamourerDesignInfo)Utils.GetDesignByGUID(design_name);
var guid = design.Identifier;
string targetFile = Path.Combine(Svc.PluginInterface.ConfigDirectory.Parent!.FullName,"Glamourer","Designs",$"{guid}.json");
if (File.Exists(targetFile))
{
string jsonContent = File.ReadAllText(targetFile);

var designObject = Newtonsoft.Json.Linq.JObject.Parse(jsonContent);
Newtonsoft.Json.Linq.JToken current = designObject;
string[] keys = path.Split(',');
foreach (var key in keys)
{
current = current?[key];
}
Races design_race = (Races)(int)current["Value"];

bool applied = false;

foreach (var property in ((Newtonsoft.Json.Linq.JObject)designObject[keys[0]]).Properties())
{
if(property.Name != "ModelId" && property.Name != "BodyType")
{
if ((string)designObject[keys[0]][property.Name]["Apply"] == "True")
{
applied = true;
break;
}
}
}

if (applied && !racesToCheck.Contains(design_race) && racesToCheck.Count > 0)
{
valid = false;
}
if (applied && notRacesToCheck.Contains(design_race))
{
valid = false;
}
// PluginLog.Information($"Valid: {valid} | Design: {design.Name} | Race: {design_race} | Applied: {applied} | racesToCheck: {racesToCheck.FirstOrNull()},{!racesToCheck.Contains(design_race)} | notRacesToCheck: {notRacesToCheck.FirstOrNull()},{notRacesToCheck.Contains(design_race)} | Guid: {guid}");
}
else
{
PluginLog.Warning($"Design file '{guid}.json' not found.");
}
}
break;
}
}
}
return valid;
}
}
33 changes: 31 additions & 2 deletions DynamicBridge/Gui/GuiRules.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Dalamud.Interface.Components;
using Dalamud.Interface.Components;
using Dalamud.Interface.Style;
using DynamicBridge.Configuration;
using DynamicBridge.Core;
Expand Down Expand Up @@ -78,6 +78,7 @@ void ButtonsRight()
C.Cond_World,
C.Cond_Zone,
C.Cond_ZoneGroup,
C.Cond_Race,
C.Cond_Players,
];

Expand All @@ -98,6 +99,7 @@ void ButtonsRight()
if(C.Cond_Job) ImGui.TableSetupColumn("Job");
if(C.Cond_World) ImGui.TableSetupColumn("World");
if(C.Cond_Gearset) ImGui.TableSetupColumn("Gearset");
if(C.Cond_Race) ImGui.TableSetupColumn("Race");
if(C.Cond_Players) ImGui.TableSetupColumn("Players");
ImGui.TableSetupColumn("Preset");
ImGui.TableSetupColumn(" ", ImGuiTableColumnFlags.NoResize | ImGuiTableColumnFlags.WidthFixed);
Expand Down Expand Up @@ -133,7 +135,14 @@ void FiltersSelection()
//Sorting
var rowPos = ImGui.GetCursorPos();
ImGui.Checkbox("##enable", ref rule.Enabled);
ImGuiEx.Tooltip("Enable this rule");
if (!rule.valid)
{
ImGuiEx.Tooltip("There is a race/preset conflict, to enable this rule, please resolve.");
}
else
{
ImGuiEx.Tooltip("Enable this rule");
}

ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
Expand Down Expand Up @@ -550,6 +559,26 @@ void FiltersSelection()
}
filterCnt++;

if(C.Cond_Race)
{
ImGui.TableNextColumn();
//Race
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
if(ImGui.BeginCombo("##race", rule.Races.PrintRange(rule.Not.Races, out var fullList), C.ComboSize))
{
FiltersSelection();
foreach(var cond in Enum.GetValues<Races>())
{
if(cond == Races.No_Race) continue;
var name = cond.ToString().Replace("_", "'");
if(Filters[filterCnt].Length > 0 && !name.Contains(Filters[filterCnt], StringComparison.OrdinalIgnoreCase)) continue;
if(OnlySelected[filterCnt] && !rule.Races.Contains(cond)) continue;
DrawSelector(name, cond, rule.Races, rule.Not.Races);
}
ImGui.EndCombo();
}
if(fullList != null) ImGuiEx.Tooltip(UI.AnyNotice + fullList);
}
if (C.Cond_Players)
{
ImGui.TableNextColumn();
Expand Down
57 changes: 57 additions & 0 deletions DynamicBridge/Gui/GuiSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public static void Draw()
() => ImGui.Checkbox($"Job", ref C.Cond_Job),
() => ImGui.Checkbox($"World", ref C.Cond_World),
() => ImGui.Checkbox($"Gearset", ref C.Cond_Gearset),
() => ImGui.Checkbox($"Current Race", ref C.Cond_Race_Bonus),
() => ImGui.Checkbox($"Nearby Players", ref C.Cond_Players),
],
(int)(ImGui.GetContentRegionAvail().X / 180f), ImGuiTableFlags.BordersInner);
Expand All @@ -151,6 +152,62 @@ public static void Draw()
}
ImGuiGroup.EndGroupBox();
}
bool Cond_Race_Bonus_Window = C.Cond_Race_Bonus && !C.Cond_Race;
if (Cond_Race_Bonus_Window)
{
// Measure the longest text line
Vector2 textSize1 = ImGui.CalcTextSize("ARE YOU SURE YOU WANT TO ENABLE THE RACE CONDITION FOR RULES?");
Vector2 textSize2 = ImGui.CalcTextSize("It is VERY easy to be stuck in infinite loops with this condition");
Vector2 textSize3 = ImGui.CalcTextSize("By selecting YES, I yeild my right to ask for help if I can't fix the loop");
float width = Math.Max(textSize1.X, Math.Max(textSize2.X, textSize3.X)) + 40;
float height = textSize1.Y + textSize2.Y + textSize3.Y + textSize3.Y + 100;

ImGui.SetNextWindowSize(new Vector2(width, height), ImGuiCond.Always);

if (ImGui.Begin("ARE YOU SURE", ref Cond_Race_Bonus_Window, ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize))
{
float windowWidth = ImGui.GetWindowSize().X;

float time = (float)ImGui.GetTime();
bool flash = (int)(time * 2) % 2 == 0;
Vector4 textColor = flash ? new Vector4(1f, 0f, 0f, 1f) : new Vector4(1f, 1f, 1f, 1f);

ImGui.SetCursorPosX((windowWidth - textSize1.X) * 0.5f);
ImGui.TextColored(textColor, "ARE YOU SURE YOU WANT TO ENABLE THE RACE CONDITION FOR RULES?");

ImGui.SetCursorPosX((windowWidth - textSize2.X) * 0.5f);
ImGui.Text("It is VERY easy to be stuck in infinite loops with this condition");

ImGui.SetCursorPosX((windowWidth - textSize3.X) * 0.5f);
ImGui.Text("By selecting YES, I yeild my right to ask for help if I can't fix out the loop");

ImGui.NewLine();

float buttonWidth = 80f;
float buttonSpacing = 10f;
float totalButtonWidth = (buttonWidth * 2) + buttonSpacing;

ImGui.SetCursorPosX((windowWidth - totalButtonWidth) * 0.5f);
if (ImGui.Button("NO", new Vector2(buttonWidth, 30)))
{
C.Cond_Race_Bonus = false;
C.Cond_Race = false;
Cond_Race_Bonus_Window = false;
}

ImGui.SameLine();

if (ImGui.Button("YES", new Vector2(buttonWidth, 30)))
{
C.Cond_Race_Bonus = true;
C.Cond_Race = true;
Cond_Race_Bonus_Window = false;
}
}
ImGui.End();
}

if(!C.Cond_Race_Bonus){C.Cond_Race=false;}

if(ImGuiGroup.BeginGroupBox("Integrations"))
{
Expand Down
30 changes: 30 additions & 0 deletions DynamicBridge/IPC/Glamourer/CursedActionManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using ECommons.DalamudServices;
using Glamourer.Api.Enums;
using Glamourer.Api.Helpers;
using Glamourer.Api.IpcSubscribers;
using SharpDX.Win32;
using System;
using System.Collections.Generic;

//I have no idea what I'm doing, I'm just stealing code from everwhere.... But either way, I don't think this is actually very useful. Too many Customize changes.
public class EzStateChanged : IDisposable
{
internal static List<EzStateChanged> Registered = [];
internal EventSubscriber<nint, StateChangeType> Subscriber;

public EzStateChanged(Action<nint, StateChangeType> handler)
{
if (handler == null) throw new ArgumentNullException(nameof(handler));
// Create the subscriber for StateChangedWithType
Subscriber = StateChangedWithType.Subscriber(Svc.PluginInterface, handler);

// Register instance
Registered.Add(this);
}

public void Dispose()
{
Subscriber.Dispose();
Registered.Remove(this);
}
}
14 changes: 14 additions & 0 deletions DynamicBridge/IPC/Glamourer/GlamourerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ public string GetMyCustomization()
}
}

private GetState GetState = new(Svc.PluginInterface);
public Newtonsoft.Json.Linq.JObject GetMyState()
{
try
{
return GetState.Invoke(0).Item2;
}
catch(Exception e)
{
e.Log();
return null;
}
}

private ApplyState ApplyState = new(Svc.PluginInterface);
public void SetMyCustomization(string customization)
{
Expand Down