mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Add preliminary festival handling
This commit is contained in:
parent
301c089d86
commit
dee1860dee
8 changed files with 275 additions and 10 deletions
|
|
@ -27,6 +27,7 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
public bool HideApplyCheckmarks { get; set; } = false;
|
||||
public bool SmallEquip { get; set; } = false;
|
||||
public bool UnlockedItemMode { get; set; } = false;
|
||||
public byte DisableFestivals { get; set; } = 1;
|
||||
public bool EnableGameContextMenu { get; set; } = true;
|
||||
public MainWindow.TabType SelectedTab { get; set; } = MainWindow.TabType.Settings;
|
||||
public DoubleModifier DeleteDesignModifier { get; set; } = new(ModifierHotkey.Control, ModifierHotkey.Shift);
|
||||
|
|
|
|||
73
Glamourer/Gui/GenericPopupWindow.cs
Normal file
73
Glamourer/Gui/GenericPopupWindow.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
public class GenericPopupWindow : Window
|
||||
{
|
||||
private Configuration _config;
|
||||
public bool OpenFestivalPopup { get; internal set; } = false;
|
||||
|
||||
public GenericPopupWindow(Configuration config)
|
||||
: base("Glamourer Popups",
|
||||
ImGuiWindowFlags.NoBringToFrontOnFocus
|
||||
| ImGuiWindowFlags.NoDecoration
|
||||
| ImGuiWindowFlags.NoInputs
|
||||
| ImGuiWindowFlags.NoSavedSettings
|
||||
| ImGuiWindowFlags.NoBackground
|
||||
| ImGuiWindowFlags.NoMove
|
||||
| ImGuiWindowFlags.NoNav
|
||||
| ImGuiWindowFlags.NoTitleBar, true)
|
||||
{
|
||||
_config = config;
|
||||
IsOpen = true;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
if (OpenFestivalPopup)
|
||||
{
|
||||
ImGui.OpenPopup("FestivalPopup");
|
||||
OpenFestivalPopup = false;
|
||||
}
|
||||
|
||||
DrawFestivalPopup();
|
||||
}
|
||||
|
||||
|
||||
private void DrawFestivalPopup()
|
||||
{
|
||||
var viewportSize = ImGui.GetWindowViewport().Size;
|
||||
ImGui.SetNextWindowSize(new Vector2(viewportSize.X / 5, viewportSize.Y / 7));
|
||||
ImGui.SetNextWindowPos(viewportSize / 2, ImGuiCond.Always, new Vector2(0.5f));
|
||||
using var popup = ImRaii.Popup("FestivalPopup", ImGuiWindowFlags.Modal);
|
||||
if (!popup)
|
||||
return;
|
||||
|
||||
ImGuiUtil.TextWrapped(
|
||||
"Glamourer has some festival-specific behaviour that is turned on by default. You can always turn this behaviour on or off in the general settings, and choose your current preference now.");
|
||||
|
||||
var buttonWidth = new Vector2(150 * ImGuiHelpers.GlobalScale, 0);
|
||||
var yPos = ImGui.GetWindowHeight() - 2 * ImGui.GetFrameHeight();
|
||||
var xPos = (ImGui.GetWindowWidth() - ImGui.GetStyle().ItemSpacing.X) / 2 - buttonWidth.X;
|
||||
ImGui.SetCursorPos(new Vector2(xPos, yPos));
|
||||
if (ImGui.Button("Let's Check It Out!", buttonWidth))
|
||||
{
|
||||
_config.DisableFestivals = 0;
|
||||
_config.Save();
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Not Right Now.", buttonWidth))
|
||||
{
|
||||
_config.DisableFestivals = 2;
|
||||
_config.Save();
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,12 +11,13 @@ public class GlamourerWindowSystem : IDisposable
|
|||
private readonly MainWindow _ui;
|
||||
private readonly PenumbraChangedItemTooltip _penumbraTooltip;
|
||||
|
||||
public GlamourerWindowSystem(UiBuilder uiBuilder, MainWindow ui, PenumbraChangedItemTooltip penumbraTooltip)
|
||||
public GlamourerWindowSystem(UiBuilder uiBuilder, MainWindow ui, GenericPopupWindow popups, PenumbraChangedItemTooltip penumbraTooltip)
|
||||
{
|
||||
_uiBuilder = uiBuilder;
|
||||
_ui = ui;
|
||||
_penumbraTooltip = penumbraTooltip;
|
||||
_windowSystem.AddWindow(ui);
|
||||
_windowSystem.AddWindow(popups);
|
||||
_uiBuilder.Draw += _windowSystem.Draw;
|
||||
_uiBuilder.OpenConfigUi += _ui.Toggle;
|
||||
}
|
||||
|
|
@ -26,4 +27,4 @@ public class GlamourerWindowSystem : IDisposable
|
|||
_uiBuilder.Draw -= _windowSystem.Draw;
|
||||
_uiBuilder.OpenConfigUi -= _ui.Toggle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -66,19 +66,21 @@ public unsafe class DebugTab : ITab
|
|||
private readonly PenumbraChangedItemTooltip _penumbraTooltip;
|
||||
|
||||
private readonly StateManager _state;
|
||||
private readonly FunModule _funModule;
|
||||
|
||||
private int _gameObjectIndex;
|
||||
|
||||
public bool IsVisible
|
||||
=> _config.DebugMode;
|
||||
|
||||
public DebugTab(ChangeCustomizeService changeCustomizeService, VisorService visorService, UpdateSlotService updateSlotService, WeaponService weaponService, PenumbraService penumbra,
|
||||
public DebugTab(ChangeCustomizeService changeCustomizeService, VisorService visorService, UpdateSlotService updateSlotService,
|
||||
WeaponService weaponService, PenumbraService penumbra,
|
||||
ActorService actors, ItemManager items, CustomizationService customization, ObjectManager objectManager,
|
||||
DesignFileSystem designFileSystem, DesignManager designManager, StateManager state, Configuration config,
|
||||
PenumbraChangedItemTooltip penumbraTooltip, MetaService metaService, GlamourerIpc ipc, DalamudPluginInterface pluginInterface,
|
||||
AutoDesignManager autoDesignManager, JobService jobs, CodeService code, CustomizeUnlockManager customizeUnlocks,
|
||||
ItemUnlockManager itemUnlocks, DesignConverter designConverter, DatFileService datFileService, InventoryService inventoryService,
|
||||
HumanModelList humans)
|
||||
HumanModelList humans, FunModule funModule)
|
||||
{
|
||||
_changeCustomizeService = changeCustomizeService;
|
||||
_visorService = visorService;
|
||||
|
|
@ -106,6 +108,7 @@ public unsafe class DebugTab : ITab
|
|||
_datFileService = datFileService;
|
||||
_inventoryService = inventoryService;
|
||||
_humans = humans;
|
||||
_funModule = funModule;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> Label
|
||||
|
|
@ -125,6 +128,7 @@ public unsafe class DebugTab : ITab
|
|||
DrawAutoDesigns();
|
||||
DrawInventory();
|
||||
DrawUnlocks();
|
||||
DrawFun();
|
||||
DrawIpc();
|
||||
}
|
||||
|
||||
|
|
@ -1569,6 +1573,35 @@ public unsafe class DebugTab : ITab
|
|||
|
||||
#endregion
|
||||
|
||||
#region Fun
|
||||
|
||||
private void DrawFun()
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Fun Module"))
|
||||
return;
|
||||
|
||||
ImGui.TextUnformatted($"Current Festival: {_funModule.CurrentFestival}");
|
||||
ImGui.TextUnformatted($"Festivals Enabled: {_config.DisableFestivals switch { 1 => "Undecided", 0 => "Enabled", _ => "Disabled" }}");
|
||||
ImGui.TextUnformatted($"Popup Open: {ImGui.IsPopupOpen("FestivalPopup", ImGuiPopupFlags.AnyPopup)}");
|
||||
if (ImGui.Button("Force Christmas"))
|
||||
_funModule.ForceFestival(FunModule.FestivalType.Christmas);
|
||||
if (ImGui.Button("Force Halloween"))
|
||||
_funModule.ForceFestival(FunModule.FestivalType.Halloween);
|
||||
if (ImGui.Button("Force April First"))
|
||||
_funModule.ForceFestival(FunModule.FestivalType.AprilFirst);
|
||||
if (ImGui.Button("Force None"))
|
||||
_funModule.ForceFestival(FunModule.FestivalType.None);
|
||||
if (ImGui.Button("Revert"))
|
||||
_funModule.ResetFestival();
|
||||
if (ImGui.Button("Reset Popup"))
|
||||
{
|
||||
_config.DisableFestivals = 1;
|
||||
_config.Save();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IPC
|
||||
|
||||
private string _gameObjectName = string.Empty;
|
||||
|
|
@ -1600,7 +1633,8 @@ public unsafe class DebugTab : ITab
|
|||
|
||||
ImGuiUtil.DrawTableColumn(GlamourerIpc.LabelGetAllCustomizationFromCharacter);
|
||||
ImGui.TableNextColumn();
|
||||
base64 = GlamourerIpc.GetAllCustomizationFromCharacterSubscriber(_pluginInterface).Invoke(_objectManager.Objects[_gameObjectIndex] as Character);
|
||||
base64 = GlamourerIpc.GetAllCustomizationFromCharacterSubscriber(_pluginInterface)
|
||||
.Invoke(_objectManager.Objects[_gameObjectIndex] as Character);
|
||||
if (base64 != null)
|
||||
ImGuiUtil.CopyOnClickSelectable(base64);
|
||||
else
|
||||
|
|
@ -1624,7 +1658,8 @@ public unsafe class DebugTab : ITab
|
|||
ImGuiUtil.DrawTableColumn(GlamourerIpc.LabelApplyAllToCharacter);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGui.Button("Apply##AllCharacter"))
|
||||
GlamourerIpc.ApplyAllToCharacterSubscriber(_pluginInterface).Invoke(_base64Apply, _objectManager.Objects[_gameObjectIndex] as Character);
|
||||
GlamourerIpc.ApplyAllToCharacterSubscriber(_pluginInterface)
|
||||
.Invoke(_base64Apply, _objectManager.Objects[_gameObjectIndex] as Character);
|
||||
|
||||
ImGuiUtil.DrawTableColumn(GlamourerIpc.LabelApplyOnlyEquipment);
|
||||
ImGui.TableNextColumn();
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ public class SettingsTab : ITab
|
|||
Checkbox("Unlocked Item Mode",
|
||||
"Enable this if you want automatically applied designs to only consider items and customizations you have actually unlocked once, and skip those you have not.",
|
||||
_config.UnlockedItemMode, v => _config.UnlockedItemMode = v);
|
||||
Checkbox("Enable Festival Easter-Eggs",
|
||||
"Glamourer may do some fun things on specific dates. Disable this if you do not want your experience disrupted by this.",
|
||||
_config.DisableFestivals == 0, v => _config.DisableFestivals = v ? (byte)0 : (byte)2);
|
||||
Checkbox("Auto-Reload Gear",
|
||||
"Automatically reload equipment pieces on your own character when changing any mod options in Penumbra in their associated collection.",
|
||||
_config.AutoRedrawEquipOnChanges, _autoRedraw.SetState);
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ public static class ServiceManager
|
|||
.AddSingleton<ActorSelector>()
|
||||
.AddSingleton<ActorPanel>()
|
||||
.AddSingleton<MainWindow>()
|
||||
.AddSingleton<GenericPopupWindow>()
|
||||
.AddSingleton<GlamourerWindowSystem>()
|
||||
.AddSingleton<CustomizationDrawer>()
|
||||
.AddSingleton<EquipmentDrawer>()
|
||||
|
|
|
|||
95
Glamourer/State/FunEquipSet.cs
Normal file
95
Glamourer/State/FunEquipSet.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.State;
|
||||
|
||||
internal class FunEquipSet
|
||||
{
|
||||
public static FunEquipSet? GetSet(FunModule.FestivalType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
FunModule.FestivalType.Halloween => Halloween,
|
||||
FunModule.FestivalType.Christmas => Christmas,
|
||||
FunModule.FestivalType.AprilFirst => AprilFirst,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
public readonly record struct Group(CharacterArmor Head, CharacterArmor Body, CharacterArmor Hands, CharacterArmor Legs,
|
||||
CharacterArmor Feet, StainId[]? Stains = null)
|
||||
{
|
||||
public Group(ushort headS, byte headV, ushort bodyS, byte bodyV, ushort handsS, byte handsV, ushort legsS, byte legsV, ushort feetS,
|
||||
byte feetV, StainId[]? stains = null)
|
||||
: this(new CharacterArmor(headS, headV, 0), new CharacterArmor(bodyS, bodyV, 0), new CharacterArmor(handsS, handsV, 0),
|
||||
new CharacterArmor(legsS, legsV, 0), new CharacterArmor(feetS, feetV, 0), stains)
|
||||
{ }
|
||||
}
|
||||
|
||||
private readonly Group[] _groups;
|
||||
|
||||
public void Apply(StainId[] allStains, Random rng, Span<CharacterArmor> armor)
|
||||
{
|
||||
var groupIdx = rng.Next(0, _groups.Length);
|
||||
var group = _groups[groupIdx];
|
||||
var stains = group.Stains ?? allStains;
|
||||
var stainIdx = rng.Next(0, stains.Length);
|
||||
var stain = stains[stainIdx];
|
||||
Glamourer.Log.Verbose($"Chose group {groupIdx} and stain {stainIdx} for festival costume.");
|
||||
if (group.Head.Set != 0)
|
||||
armor[0] = group.Head.With(stain);
|
||||
if (group.Body.Set != 0)
|
||||
armor[1] = group.Body.With(stain);
|
||||
if (group.Hands.Set != 0)
|
||||
armor[2] = group.Hands.With(stain);
|
||||
if (group.Legs.Set != 0)
|
||||
armor[3] = group.Legs.With(stain);
|
||||
if (group.Feet.Set != 0)
|
||||
armor[4] = group.Feet.With(stain);
|
||||
}
|
||||
|
||||
public static readonly FunEquipSet Christmas = new
|
||||
(
|
||||
new Group(6170, 1, 6170, 1, 6170, 1, 6170, 1, 6170, 1), // Unorthodox Saint
|
||||
new Group(6006, 1, 6170, 1, 6170, 1, 6170, 1, 6170, 1), // Unorthodox Saint
|
||||
new Group(6007, 1, 6170, 1, 6170, 1, 6170, 1, 6170, 1), // Unorthodox Saint
|
||||
new Group(0058, 1, 0058, 1, 6005, 1, 0000, 0, 6005, 1), // Reindeer
|
||||
new Group(6005, 1, 0058, 1, 6005, 1, 0000, 0, 6005, 1), // Reindeer
|
||||
new Group(0231, 1, 0231, 1, 0279, 1, 0231, 1, 0231, 1), // Starlight
|
||||
new Group(0231, 1, 6030, 1, 0279, 1, 0231, 1, 0231, 1), // Starlight
|
||||
new Group(0053, 1, 0053, 1, 0279, 1, 0279, 1, 0053, 1), // Sweet Dream
|
||||
new Group(0136, 1, 0136, 1, 0136, 1, 0000, 0, 0000, 0) // Snowman
|
||||
);
|
||||
|
||||
public static readonly FunEquipSet Halloween = new
|
||||
(
|
||||
new Group(0316, 1, 0316, 1, 0316, 1, 0279, 1, 0316, 1), // Witch
|
||||
new Group(6047, 1, 6047, 1, 6047, 1, 6047, 1, 6047, 1), // Werewolf
|
||||
new Group(6148, 1, 6148, 1, 6148, 1, 6148, 1, 6148, 1), // Wake Doctor
|
||||
new Group(6117, 1, 6117, 1, 6117, 1, 6117, 1, 6117, 1), // Clown
|
||||
new Group(0000, 0, 0137, 1, 0000, 0, 0000, 0, 0000, 0), // Howling Spirit
|
||||
new Group(0000, 0, 0137, 2, 0000, 0, 0000, 0, 0000, 0), // Wailing Spirit
|
||||
new Group(0232, 1, 0232, 1, 0279, 1, 0232, 1, 0232, 1), // Eerie Attire
|
||||
new Group(0232, 1, 6036, 1, 0279, 1, 0232, 1, 0232, 1) // Vampire
|
||||
);
|
||||
|
||||
public static readonly FunEquipSet AprilFirst = new
|
||||
(
|
||||
new Group(6133, 1, 6133, 1, 0000, 0, 0000, 0, 0000, 0), // Gaja
|
||||
new Group(6121, 1, 6121, 1, 0000, 0, 0000, 0, 0000, 0), // Chicken
|
||||
new Group(6103, 1, 6103, 1, 0000, 0, 0000, 0, 0000, 0), // Rabbit
|
||||
new Group(6103, 1, 6103, 2, 0000, 0, 0000, 0, 0000, 0), // Rabbit
|
||||
new Group(6089, 1, 6089, 1, 0000, 0, 0000, 0, 0000, 0), // Toad
|
||||
new Group(0241, 1, 0046, 1, 0000, 0, 0279, 1, 6169, 3), // Chocobo
|
||||
new Group(0046, 1, 0046, 1, 0000, 0, 0279, 1, 6169, 3), // Chocobo
|
||||
new Group(0058, 1, 0058, 1, 0000, 0, 0000, 0, 0000, 0), // Reindeer
|
||||
new Group(0136, 1, 0136, 1, 0136, 1, 0000, 0, 0000, 0), // Snowman
|
||||
new Group(0159, 1, 0000, 0, 0000, 0, 0000, 0, 0000, 0), // Slime Crown
|
||||
new Group(6117, 1, 6117, 1, 6117, 1, 6117, 1, 6117, 1), // Clown
|
||||
new Group(6169, 3, 6169, 3, 0279, 1, 6169, 3, 6169, 3), // Chocobo Pajama
|
||||
new Group(6169, 2, 6169, 2, 0279, 2, 6169, 2, 6169, 2) // Cactuar Pajama
|
||||
);
|
||||
|
||||
private FunEquipSet(params Group[] groups)
|
||||
=> _groups = groups;
|
||||
}
|
||||
|
|
@ -2,31 +2,80 @@
|
|||
using System.Linq;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Gui;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.Services;
|
||||
using OtterGui.Classes;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using CustomizeIndex = Glamourer.Customization.CustomizeIndex;
|
||||
|
||||
namespace Glamourer.State;
|
||||
|
||||
public unsafe class FunModule
|
||||
public unsafe class FunModule : IDisposable
|
||||
{
|
||||
public enum FestivalType
|
||||
{
|
||||
None,
|
||||
Halloween,
|
||||
Christmas,
|
||||
AprilFirst,
|
||||
}
|
||||
|
||||
private readonly ItemManager _items;
|
||||
private readonly CustomizationService _customizations;
|
||||
private readonly Configuration _config;
|
||||
private readonly CodeService _codes;
|
||||
private readonly Random _rng;
|
||||
private readonly GenericPopupWindow _popupWindow;
|
||||
private readonly StainId[] _stains;
|
||||
|
||||
public FunModule(CodeService codes, CustomizationService customizations, ItemManager items)
|
||||
public FestivalType CurrentFestival { get; private set; } = FestivalType.None;
|
||||
private FunEquipSet? _festivalSet;
|
||||
|
||||
private void OnDayChange(int day, int month, int _)
|
||||
{
|
||||
CurrentFestival = (day, month) switch
|
||||
{
|
||||
(1, 4) => FestivalType.AprilFirst,
|
||||
(24, 12) => FestivalType.Christmas,
|
||||
(25, 12) => FestivalType.Christmas,
|
||||
(26, 12) => FestivalType.Christmas,
|
||||
(31, 10) => FestivalType.Halloween,
|
||||
(01, 11) => FestivalType.Halloween,
|
||||
_ => FestivalType.None,
|
||||
};
|
||||
_festivalSet = FunEquipSet.GetSet(CurrentFestival);
|
||||
_popupWindow.OpenFestivalPopup = _festivalSet != null && _config.DisableFestivals == 1;
|
||||
}
|
||||
|
||||
internal void ForceFestival(FestivalType type)
|
||||
{
|
||||
CurrentFestival = type;
|
||||
_festivalSet = FunEquipSet.GetSet(CurrentFestival);
|
||||
_popupWindow.OpenFestivalPopup = _festivalSet != null && _config.DisableFestivals == 1;
|
||||
}
|
||||
|
||||
internal void ResetFestival()
|
||||
=> OnDayChange(DateTime.UtcNow.Day, DateTime.UtcNow.Month, DateTime.UtcNow.Year);
|
||||
|
||||
public FunModule(CodeService codes, CustomizationService customizations, ItemManager items, Configuration config,
|
||||
GenericPopupWindow popupWindow)
|
||||
{
|
||||
_codes = codes;
|
||||
_customizations = customizations;
|
||||
_items = items;
|
||||
_config = config;
|
||||
_popupWindow = popupWindow;
|
||||
_rng = new Random();
|
||||
_stains = _items.Stains.Keys.Prepend((StainId)0).ToArray();
|
||||
ResetFestival();
|
||||
DayChangeTracker.DayChanged += OnDayChange;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
=> DayChangeTracker.DayChanged -= OnDayChange;
|
||||
|
||||
public void ApplyFun(Actor actor, ref CharacterArmor armor, EquipSlot slot)
|
||||
{
|
||||
if (actor.AsObject->ObjectKind is not (byte)ObjectKind.Player || !actor.IsCharacter)
|
||||
|
|
@ -47,8 +96,15 @@ public unsafe class FunModule
|
|||
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
|
||||
return;
|
||||
|
||||
ApplyEmperor(armor);
|
||||
ApplyClown(armor);
|
||||
if (_config.DisableFestivals == 0 && _festivalSet != null)
|
||||
{
|
||||
_festivalSet.Apply(_stains, _rng, armor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyEmperor(armor);
|
||||
ApplyClown(armor);
|
||||
}
|
||||
|
||||
ApplyOops(ref customize);
|
||||
ApplyIndividual(ref customize);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue