mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Update OtterGui
This commit is contained in:
parent
6130bae81d
commit
6ecf06a671
23 changed files with 142 additions and 254 deletions
|
|
@ -11,7 +11,6 @@ using Glamourer.Interop.Structs;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Glamourer.Unlocks;
|
using Glamourer.Unlocks;
|
||||||
using OtterGui.Classes;
|
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
@ -27,7 +26,7 @@ public class AutoDesignApplier : IDisposable
|
||||||
private readonly JobService _jobs;
|
private readonly JobService _jobs;
|
||||||
private readonly EquippedGearset _equippedGearset;
|
private readonly EquippedGearset _equippedGearset;
|
||||||
private readonly ActorManager _actors;
|
private readonly ActorManager _actors;
|
||||||
private readonly CustomizeService _customizations;
|
private readonly CustomizeService _customizations;
|
||||||
private readonly CustomizeUnlockManager _customizeUnlocks;
|
private readonly CustomizeUnlockManager _customizeUnlocks;
|
||||||
private readonly ItemUnlockManager _itemUnlocks;
|
private readonly ItemUnlockManager _itemUnlocks;
|
||||||
private readonly AutomationChanged _event;
|
private readonly AutomationChanged _event;
|
||||||
|
|
@ -80,7 +79,7 @@ public class AutoDesignApplier : IDisposable
|
||||||
_jobs.JobChanged -= OnJobChange;
|
_jobs.JobChanged -= OnJobChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnWeaponLoading(Actor actor, EquipSlot slot, Ref<CharacterWeapon> weapon)
|
private void OnWeaponLoading(Actor actor, EquipSlot slot, ref CharacterWeapon weapon)
|
||||||
{
|
{
|
||||||
if (_jobChangeState == null || !_config.EnableAutoDesigns)
|
if (_jobChangeState == null || !_config.EnableAutoDesigns)
|
||||||
return;
|
return;
|
||||||
|
|
@ -89,27 +88,33 @@ public class AutoDesignApplier : IDisposable
|
||||||
if (id == _jobChangeState.Identifier)
|
if (id == _jobChangeState.Identifier)
|
||||||
{
|
{
|
||||||
var current = _jobChangeState.BaseData.Item(slot);
|
var current = _jobChangeState.BaseData.Item(slot);
|
||||||
if (slot is EquipSlot.MainHand)
|
switch (slot)
|
||||||
{
|
{
|
||||||
if (_jobChangeMainhand.TryGetValue(current.Type, out var data))
|
case EquipSlot.MainHand:
|
||||||
{
|
{
|
||||||
Glamourer.Log.Verbose(
|
if (_jobChangeMainhand.TryGetValue(current.Type, out var data))
|
||||||
$"Changing Mainhand from {_jobChangeState.ModelData.Weapon(EquipSlot.MainHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.MainHand)} to {data.Item1} for 0x{actor.Address:X}.");
|
{
|
||||||
_state.ChangeItem(_jobChangeState, EquipSlot.MainHand, data.Item1, data.Item2);
|
Glamourer.Log.Verbose(
|
||||||
weapon.Value = _jobChangeState.ModelData.Weapon(EquipSlot.MainHand);
|
$"Changing Mainhand from {_jobChangeState.ModelData.Weapon(EquipSlot.MainHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.MainHand)} to {data.Item1} for 0x{actor.Address:X}.");
|
||||||
}
|
_state.ChangeItem(_jobChangeState, EquipSlot.MainHand, data.Item1, data.Item2);
|
||||||
}
|
weapon = _jobChangeState.ModelData.Weapon(EquipSlot.MainHand);
|
||||||
else if (slot is EquipSlot.OffHand && current.Type == _jobChangeState.BaseData.MainhandType.Offhand())
|
}
|
||||||
{
|
|
||||||
if (_jobChangeOffhand.TryGetValue(current.Type, out var data))
|
|
||||||
{
|
|
||||||
Glamourer.Log.Verbose(
|
|
||||||
$"Changing Offhand from {_jobChangeState.ModelData.Weapon(EquipSlot.OffHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.OffHand)} to {data.Item1} for 0x{actor.Address:X}.");
|
|
||||||
_state.ChangeItem(_jobChangeState, EquipSlot.OffHand, data.Item1, data.Item2);
|
|
||||||
weapon.Value = _jobChangeState.ModelData.Weapon(EquipSlot.OffHand);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResetJobChange();
|
break;
|
||||||
|
}
|
||||||
|
case EquipSlot.OffHand when current.Type == _jobChangeState.BaseData.MainhandType.Offhand():
|
||||||
|
{
|
||||||
|
if (_jobChangeOffhand.TryGetValue(current.Type, out var data))
|
||||||
|
{
|
||||||
|
Glamourer.Log.Verbose(
|
||||||
|
$"Changing Offhand from {_jobChangeState.ModelData.Weapon(EquipSlot.OffHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.OffHand)} to {data.Item1} for 0x{actor.Address:X}.");
|
||||||
|
_state.ChangeItem(_jobChangeState, EquipSlot.OffHand, data.Item1, data.Item2);
|
||||||
|
weapon = _jobChangeState.ModelData.Weapon(EquipSlot.OffHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetJobChange();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -123,21 +128,32 @@ public class AutoDesignApplier : IDisposable
|
||||||
if (!_config.EnableAutoDesigns || set == null)
|
if (!_config.EnableAutoDesigns || set == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
void RemoveOld(ActorIdentifier[]? identifiers)
|
switch (type)
|
||||||
{
|
{
|
||||||
if (identifiers == null)
|
case AutomationChanged.Type.ToggleSet when !set.Enabled:
|
||||||
return;
|
case AutomationChanged.Type.DeletedDesign when set.Enabled:
|
||||||
|
// The automation set was disabled or deleted, no other for those identifiers can be enabled, remove existing Fixed Locks.
|
||||||
foreach (var id in identifiers)
|
RemoveOld(set.Identifiers);
|
||||||
{
|
break;
|
||||||
if (id.Type is IdentifierType.Player && id.HomeWorld == WorldId.AnyWorld)
|
case AutomationChanged.Type.ChangeIdentifier when set.Enabled:
|
||||||
foreach (var state in _state.Where(kvp => kvp.Key.PlayerName == id.PlayerName).Select(kvp => kvp.Value))
|
// Remove fixed state from the old identifiers assigned and the old enabled set, if any.
|
||||||
state.RemoveFixedDesignSources();
|
var (oldIds, _, oldSet) = ((ActorIdentifier[], ActorIdentifier, AutoDesignSet?))bonusData!;
|
||||||
else if (_state.TryGetValue(id, out var state))
|
RemoveOld(oldIds);
|
||||||
state.RemoveFixedDesignSources();
|
ApplyNew(set); // Does not need to disable oldSet because same identifiers.
|
||||||
}
|
break;
|
||||||
|
case AutomationChanged.Type.ToggleSet: // Does not need to disable old states because same identifiers.
|
||||||
|
case AutomationChanged.Type.ChangedBase:
|
||||||
|
case AutomationChanged.Type.AddedDesign:
|
||||||
|
case AutomationChanged.Type.MovedDesign:
|
||||||
|
case AutomationChanged.Type.ChangedDesign:
|
||||||
|
case AutomationChanged.Type.ChangedConditions:
|
||||||
|
case AutomationChanged.Type.ChangedType:
|
||||||
|
ApplyNew(set);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
void ApplyNew(AutoDesignSet? newSet)
|
void ApplyNew(AutoDesignSet? newSet)
|
||||||
{
|
{
|
||||||
if (newSet is not { Enabled: true })
|
if (newSet is not { Enabled: true })
|
||||||
|
|
@ -174,28 +190,19 @@ public class AutoDesignApplier : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type)
|
void RemoveOld(ActorIdentifier[]? identifiers)
|
||||||
{
|
{
|
||||||
case AutomationChanged.Type.ToggleSet when !set.Enabled:
|
if (identifiers == null)
|
||||||
case AutomationChanged.Type.DeletedDesign when set.Enabled:
|
return;
|
||||||
// The automation set was disabled or deleted, no other for those identifiers can be enabled, remove existing Fixed Locks.
|
|
||||||
RemoveOld(set.Identifiers);
|
foreach (var id in identifiers)
|
||||||
break;
|
{
|
||||||
case AutomationChanged.Type.ChangeIdentifier when set.Enabled:
|
if (id.Type is IdentifierType.Player && id.HomeWorld == WorldId.AnyWorld)
|
||||||
// Remove fixed state from the old identifiers assigned and the old enabled set, if any.
|
foreach (var state in _state.Where(kvp => kvp.Key.PlayerName == id.PlayerName).Select(kvp => kvp.Value))
|
||||||
var (oldIds, _, oldSet) = ((ActorIdentifier[], ActorIdentifier, AutoDesignSet?))bonusData!;
|
state.RemoveFixedDesignSources();
|
||||||
RemoveOld(oldIds);
|
else if (_state.TryGetValue(id, out var state))
|
||||||
ApplyNew(set); // Does not need to disable oldSet because same identifiers.
|
state.RemoveFixedDesignSources();
|
||||||
break;
|
}
|
||||||
case AutomationChanged.Type.ToggleSet: // Does not need to disable old states because same identifiers.
|
|
||||||
case AutomationChanged.Type.ChangedBase:
|
|
||||||
case AutomationChanged.Type.AddedDesign:
|
|
||||||
case AutomationChanged.Type.MovedDesign:
|
|
||||||
case AutomationChanged.Type.ChangedDesign:
|
|
||||||
case AutomationChanged.Type.ChangedConditions:
|
|
||||||
case AutomationChanged.Type.ChangedType:
|
|
||||||
ApplyNew(set);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ public class DesignManager
|
||||||
|
|
||||||
Glamourer.Log.Information(
|
Glamourer.Log.Information(
|
||||||
$"Loaded {_designs.Count} designs in {stopwatch.ElapsedMilliseconds} ms.{(skipped > 0 ? $" Skipped loading {skipped} designs due to errors." : string.Empty)}");
|
$"Loaded {_designs.Count} designs in {stopwatch.ElapsedMilliseconds} ms.{(skipped > 0 ? $" Skipped loading {skipped} designs due to errors." : string.Empty)}");
|
||||||
_event.Invoke(DesignChanged.Type.ReloadedAll, null!);
|
_event.Invoke(DesignChanged.Type.ReloadedAll, null!, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Whether an Undo for the given design is possible. </summary>
|
/// <summary> Whether an Undo for the given design is possible. </summary>
|
||||||
|
|
@ -176,7 +176,7 @@ public class DesignManager
|
||||||
--d.Index;
|
--d.Index;
|
||||||
_designs.RemoveAt(design.Index);
|
_designs.RemoveAt(design.Index);
|
||||||
_saveService.ImmediateDelete(design);
|
_saveService.ImmediateDelete(design);
|
||||||
_event.Invoke(DesignChanged.Type.Deleted, design);
|
_event.Invoke(DesignChanged.Type.Deleted, design, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Rename a design. </summary>
|
/// <summary> Rename a design. </summary>
|
||||||
|
|
@ -723,7 +723,7 @@ public class DesignManager
|
||||||
if (!message.IsNullOrEmpty())
|
if (!message.IsNullOrEmpty())
|
||||||
Glamourer.Log.Debug(message);
|
Glamourer.Log.Debug(message);
|
||||||
_saveService.ImmediateSave(design);
|
_saveService.ImmediateSave(design);
|
||||||
_event.Invoke(DesignChanged.Type.Created, design);
|
_event.Invoke(DesignChanged.Type.Created, design, null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using Glamourer.Automation;
|
||||||
using Glamourer.Automation;
|
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
@ -12,8 +11,8 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is additional data depending on the type of change. </item>
|
/// <item>Parameter is additional data depending on the type of change. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class AutomationChanged : EventWrapper<Action<AutomationChanged.Type, AutoDesignSet?, object?>,
|
public sealed class AutomationChanged()
|
||||||
AutomationChanged.Priority>
|
: EventWrapper<AutomationChanged.Type, AutoDesignSet?, object?, AutomationChanged.Priority>(nameof(AutomationChanged))
|
||||||
{
|
{
|
||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
|
|
@ -65,11 +64,4 @@ public sealed class AutomationChanged : EventWrapper<Action<AutomationChanged.Ty
|
||||||
/// <seealso cref="AutoDesignApplier.OnAutomationChange"/>
|
/// <seealso cref="AutoDesignApplier.OnAutomationChange"/>
|
||||||
AutoDesignApplier,
|
AutoDesignApplier,
|
||||||
}
|
}
|
||||||
|
|
||||||
public AutomationChanged()
|
|
||||||
: base(nameof(AutomationChanged))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Type type, AutoDesignSet? set, object? data)
|
|
||||||
=> Invoke(this, type, set, data);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Gui;
|
using Glamourer.Gui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
|
@ -13,7 +12,8 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is any additional data depending on the type of change. </item>
|
/// <item>Parameter is any additional data depending on the type of change. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DesignChanged : EventWrapper<Action<DesignChanged.Type, Design, object?>, DesignChanged.Priority>
|
public sealed class DesignChanged()
|
||||||
|
: EventWrapper<DesignChanged.Type, Design, object?, DesignChanged.Priority>(nameof(DesignChanged))
|
||||||
{
|
{
|
||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
|
|
@ -98,11 +98,4 @@ public sealed class DesignChanged : EventWrapper<Action<DesignChanged.Type, Desi
|
||||||
/// <seealso cref="RevertDesignCombo.OnDesignChange"/>
|
/// <seealso cref="RevertDesignCombo.OnDesignChange"/>
|
||||||
DesignCombo = -2,
|
DesignCombo = -2,
|
||||||
}
|
}
|
||||||
|
|
||||||
public DesignChanged()
|
|
||||||
: base(nameof(DesignChanged))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Type type, Design design, object? data = null)
|
|
||||||
=> Invoke(this, type, design, data);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
@ -13,18 +12,12 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is the job id of the associated job. </item>
|
/// <item>Parameter is the job id of the associated job. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EquippedGearset : EventWrapper<Action<string, int, int, byte, byte>, EquippedGearset.Priority>
|
public sealed class EquippedGearset()
|
||||||
|
: EventWrapper<string, int, int, byte, byte, EquippedGearset.Priority>(nameof(EquippedGearset))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="Automation.AutoDesignApplier.OnEquippedGearset"/>
|
/// <seealso cref="Automation.AutoDesignApplier.OnEquippedGearset"/>
|
||||||
AutoDesignApplier = 0,
|
AutoDesignApplier = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public EquippedGearset()
|
|
||||||
: base(nameof(EquippedGearset))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(string name, int id, int lastId, byte glamour, byte jobId)
|
|
||||||
=> Invoke(this, name, id, lastId, glamour, jobId);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ using OtterGui.Classes;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
public sealed class GPoseService : EventWrapper<Action<bool>, GPoseService.Priority>
|
public sealed class GPoseService : EventWrapper<bool, GPoseService.Priority>
|
||||||
{
|
{
|
||||||
private readonly IFramework _framework;
|
private readonly IFramework _framework;
|
||||||
private readonly IClientState _state;
|
private readonly IClientState _state;
|
||||||
|
|
@ -56,7 +56,7 @@ public sealed class GPoseService : EventWrapper<Action<bool>, GPoseService.Prior
|
||||||
return;
|
return;
|
||||||
|
|
||||||
InGPose = inGPose;
|
InGPose = inGPose;
|
||||||
Invoke(this, InGPose);
|
Invoke(InGPose);
|
||||||
var actions = InGPose ? _onEnter : _onLeave;
|
var actions = InGPose ? _onEnter : _onLeave;
|
||||||
foreach (var action in actions)
|
foreach (var action in actions)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using Glamourer.Interop.Structs;
|
using Glamourer.Interop.Structs;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
|
||||||
|
|
@ -11,22 +10,12 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is the new state. </item>
|
/// <item>Parameter is the new state. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class HeadGearVisibilityChanged : EventWrapper<Action<Actor, Ref<bool>>, HeadGearVisibilityChanged.Priority>
|
public sealed class HeadGearVisibilityChanged()
|
||||||
|
: EventWrapperRef2<Actor, bool, HeadGearVisibilityChanged.Priority>(nameof(HeadGearVisibilityChanged))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnHeadGearVisibilityChange"/>
|
/// <seealso cref="State.StateListener.OnHeadGearVisibilityChange"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public HeadGearVisibilityChanged()
|
|
||||||
: base(nameof(HeadGearVisibilityChanged))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Actor actor, ref bool state)
|
|
||||||
{
|
|
||||||
var value = new Ref<bool>(state);
|
|
||||||
Invoke(this, actor, value);
|
|
||||||
state = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
@ -11,18 +10,12 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is an array of slots updated and corresponding item ids and stains. </item>
|
/// <item>Parameter is an array of slots updated and corresponding item ids and stains. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class MovedEquipment : EventWrapper<Action<(EquipSlot, uint, StainId)[]>, MovedEquipment.Priority>
|
public sealed class MovedEquipment()
|
||||||
|
: EventWrapper<(EquipSlot, uint, StainId)[], MovedEquipment.Priority>(nameof(MovedEquipment))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnMovedEquipment"/>
|
/// <seealso cref="State.StateListener.OnMovedEquipment"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public MovedEquipment()
|
|
||||||
: base(nameof(MovedEquipment))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke((EquipSlot, uint, StainId)[] items)
|
|
||||||
=> Invoke(this, items);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is the timestamp of the unlock. </item>
|
/// <item>Parameter is the timestamp of the unlock. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ObjectUnlocked : EventWrapper<Action<ObjectUnlocked.Type, uint, DateTimeOffset>, ObjectUnlocked.Priority>
|
public sealed class ObjectUnlocked()
|
||||||
|
: EventWrapper<ObjectUnlocked.Type, uint, DateTimeOffset, ObjectUnlocked.Priority>(nameof(ObjectUnlocked))
|
||||||
{
|
{
|
||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
|
|
@ -25,11 +26,4 @@ public sealed class ObjectUnlocked : EventWrapper<Action<ObjectUnlocked.Type, ui
|
||||||
/// <remarks> Currently used as a hack to make the unlock table dirty in it. If anything else starts using this, rework. </remarks>
|
/// <remarks> Currently used as a hack to make the unlock table dirty in it. If anything else starts using this, rework. </remarks>
|
||||||
UnlockTable = 0,
|
UnlockTable = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectUnlocked()
|
|
||||||
: base(nameof(ObjectUnlocked))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Type type, uint id, DateTimeOffset timestamp)
|
|
||||||
=> Invoke(this, type, id, timestamp);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
@ -6,18 +5,12 @@ namespace Glamourer.Events;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggered when Penumbra is reloaded.
|
/// Triggered when Penumbra is reloaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class PenumbraReloaded : EventWrapper<Action, PenumbraReloaded.Priority>
|
public sealed class PenumbraReloaded()
|
||||||
|
: EventWrapper<PenumbraReloaded.Priority>(nameof(PenumbraReloaded))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="Interop.ChangeCustomizeService.Restore"/>
|
/// <seealso cref="Interop.ChangeCustomizeService.Restore"/>
|
||||||
ChangeCustomizeService = 0,
|
ChangeCustomizeService = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public PenumbraReloaded()
|
|
||||||
: base(nameof(PenumbraReloaded))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke()
|
|
||||||
=> Invoke(this);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,24 +15,12 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is the return value the function should return, if it is ulong.MaxValue, the original will be called and returned. </item>
|
/// <item>Parameter is the return value the function should return, if it is ulong.MaxValue, the original will be called and returned. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SlotUpdating : EventWrapper<Action<Model, EquipSlot, Ref<CharacterArmor>, Ref<ulong>>, SlotUpdating.Priority>
|
public sealed class SlotUpdating()
|
||||||
|
: EventWrapperRef34<Model, EquipSlot, CharacterArmor, ulong, SlotUpdating.Priority>(nameof(SlotUpdating))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnSlotUpdating"/>
|
/// <seealso cref="State.StateListener.OnSlotUpdating"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlotUpdating()
|
|
||||||
: base(nameof(SlotUpdating))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Model model, EquipSlot slot, ref CharacterArmor armor, ref ulong returnValue)
|
|
||||||
{
|
|
||||||
var value = new Ref<CharacterArmor>(armor);
|
|
||||||
var @return = new Ref<ulong>(returnValue);
|
|
||||||
Invoke(this, model, slot, value, @return);
|
|
||||||
armor = value;
|
|
||||||
returnValue = @return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
using System;
|
|
||||||
using Glamourer.Interop.Structs;
|
using Glamourer.Interop.Structs;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using Penumbra.GameData.Actors;
|
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
|
|
@ -15,7 +13,8 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is any additional data depending on the type of change. </item>
|
/// <item>Parameter is any additional data depending on the type of change. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class StateChanged : EventWrapper<Action<StateChanged.Type, StateChanged.Source, ActorState, ActorData, object?>, StateChanged.Priority>
|
public sealed class StateChanged()
|
||||||
|
: EventWrapper<StateChanged.Type, StateChanged.Source, ActorState, ActorData, object?, StateChanged.Priority>(nameof(StateChanged))
|
||||||
{
|
{
|
||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
|
|
@ -62,11 +61,4 @@ public sealed class StateChanged : EventWrapper<Action<StateChanged.Type, StateC
|
||||||
{
|
{
|
||||||
GlamourerIpc = int.MinValue,
|
GlamourerIpc = int.MinValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
public StateChanged()
|
|
||||||
: base(nameof(StateChanged))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Type type, Source source, ActorState state, ActorData actors, object? data = null)
|
|
||||||
=> Invoke(this, type, source, state, actors, data);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Designs;
|
|
||||||
using Glamourer.Gui;
|
using Glamourer.Gui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
|
||||||
|
|
@ -12,8 +11,8 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is the design to select if the tab is the designs tab. </item>
|
/// <item>Parameter is the design to select if the tab is the designs tab. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class TabSelected : EventWrapper<Action<MainWindow.TabType, Design?>,
|
public sealed class TabSelected()
|
||||||
TabSelected.Priority>
|
: EventWrapper<MainWindow.TabType, Design?, TabSelected.Priority>(nameof(TabSelected))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
|
|
@ -23,11 +22,4 @@ public sealed class TabSelected : EventWrapper<Action<MainWindow.TabType, Design
|
||||||
/// <seealso cref="Gui.MainWindow.OnTabSelected"/>
|
/// <seealso cref="Gui.MainWindow.OnTabSelected"/>
|
||||||
MainWindow = 1,
|
MainWindow = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
public TabSelected()
|
|
||||||
: base(nameof(TabSelected))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(MainWindow.TabType type, Design? design)
|
|
||||||
=> Invoke(this, type, design);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using Glamourer.Interop.Structs;
|
using Glamourer.Interop.Structs;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
|
||||||
|
|
@ -12,22 +11,12 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is whether to call the original function. </item>
|
/// <item>Parameter is whether to call the original function. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class VisorStateChanged : EventWrapper<Action<Model, Ref<bool>>, VisorStateChanged.Priority>
|
public sealed class VisorStateChanged()
|
||||||
|
: EventWrapperRef2<Model, bool, VisorStateChanged.Priority>(nameof(VisorStateChanged))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnVisorChange"/>
|
/// <seealso cref="State.StateListener.OnVisorChange"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public VisorStateChanged()
|
|
||||||
: base(nameof(VisorStateChanged))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Model model, ref bool state)
|
|
||||||
{
|
|
||||||
var value = new Ref<bool>(state);
|
|
||||||
Invoke(this, model, value);
|
|
||||||
state = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using Glamourer.Interop.Structs;
|
using Glamourer.Interop.Structs;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
@ -14,7 +13,8 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is the model values to change the weapon to. </item>
|
/// <item>Parameter is the model values to change the weapon to. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class WeaponLoading : EventWrapper<Action<Actor, EquipSlot, Ref<CharacterWeapon>>, WeaponLoading.Priority>
|
public sealed class WeaponLoading()
|
||||||
|
: EventWrapperRef3<Actor, EquipSlot, CharacterWeapon, WeaponLoading.Priority>(nameof(WeaponLoading))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
|
|
@ -24,15 +24,4 @@ public sealed class WeaponLoading : EventWrapper<Action<Actor, EquipSlot, Ref<Ch
|
||||||
/// <seealso cref="Automation.AutoDesignApplier.OnWeaponLoading"/>
|
/// <seealso cref="Automation.AutoDesignApplier.OnWeaponLoading"/>
|
||||||
AutoDesignApplier = -1,
|
AutoDesignApplier = -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
public WeaponLoading()
|
|
||||||
: base(nameof(WeaponLoading))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Actor actor, EquipSlot slot, ref CharacterWeapon weapon)
|
|
||||||
{
|
|
||||||
var value = new Ref<CharacterWeapon>(weapon);
|
|
||||||
Invoke(this, actor, slot, value);
|
|
||||||
weapon = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using Glamourer.Interop.Structs;
|
using Glamourer.Interop.Structs;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
|
||||||
|
|
@ -11,22 +10,11 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is the new state. </item>
|
/// <item>Parameter is the new state. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class WeaponVisibilityChanged : EventWrapper<Action<Actor, Ref<bool>>, WeaponVisibilityChanged.Priority>
|
public sealed class WeaponVisibilityChanged() : EventWrapperRef2<Actor, bool, WeaponVisibilityChanged.Priority>(nameof(WeaponVisibilityChanged))
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnWeaponVisibilityChange"/>
|
/// <seealso cref="State.StateListener.OnWeaponVisibilityChange"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public WeaponVisibilityChanged()
|
|
||||||
: base(nameof(WeaponVisibilityChanged))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void Invoke(Actor actor, ref bool state)
|
|
||||||
{
|
|
||||||
var value = new Ref<bool>(state);
|
|
||||||
Invoke(this, actor, value);
|
|
||||||
state = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ using Glamourer.Gui;
|
||||||
using Glamourer.Interop;
|
using Glamourer.Interop;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using OtterGui.Log;
|
using OtterGui.Log;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
|
|
@ -34,6 +33,8 @@ public class Glamourer : IDalamudPlugin
|
||||||
{
|
{
|
||||||
_services = ServiceManagerA.CreateProvider(pluginInterface, Log);
|
_services = ServiceManagerA.CreateProvider(pluginInterface, Log);
|
||||||
Messager = _services.GetService<MessageService>();
|
Messager = _services.GetService<MessageService>();
|
||||||
|
_services.EnsureRequiredServices();
|
||||||
|
|
||||||
_services.GetService<VisorService>();
|
_services.GetService<VisorService>();
|
||||||
_services.GetService<WeaponService>();
|
_services.GetService<WeaponService>();
|
||||||
_services.GetService<ScalingService>();
|
_services.GetService<ScalingService>();
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Glamourer.Interop;
|
||||||
/// Changes in Race, body type or Gender are probably ignored.
|
/// Changes in Race, body type or Gender are probably ignored.
|
||||||
/// This operates on draw objects, not game objects.
|
/// This operates on draw objects, not game objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe class ChangeCustomizeService : EventWrapper<Action<Model, Ref<CustomizeArray>>, ChangeCustomizeService.Priority>
|
public unsafe class ChangeCustomizeService : EventWrapperRef2<Model, CustomizeArray, ChangeCustomizeService.Priority>
|
||||||
{
|
{
|
||||||
private readonly PenumbraReloaded _penumbraReloaded;
|
private readonly PenumbraReloaded _penumbraReloaded;
|
||||||
private readonly IGameInteropProvider _interop;
|
private readonly IGameInteropProvider _interop;
|
||||||
|
|
@ -79,11 +79,7 @@ public unsafe class ChangeCustomizeService : EventWrapper<Action<Model, Ref<Cust
|
||||||
private bool ChangeCustomizeDetour(Human* human, byte* data, byte skipEquipment)
|
private bool ChangeCustomizeDetour(Human* human, byte* data, byte skipEquipment)
|
||||||
{
|
{
|
||||||
if (!InUpdate.InMethod)
|
if (!InUpdate.InMethod)
|
||||||
{
|
Invoke(human, ref *(CustomizeArray*)data);
|
||||||
var customize = new Ref<CustomizeArray>(*(CustomizeArray*)data);
|
|
||||||
Invoke(this, (Model)human, customize);
|
|
||||||
*(CustomizeArray*)data = customize.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _changeCustomizeHook.Original(human, data, skipEquipment);
|
return _changeCustomizeHook.Original(human, data, skipEquipment);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Hooking;
|
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
|
|
@ -15,10 +14,10 @@ namespace Glamourer.Interop;
|
||||||
/// <list type="number">
|
/// <list type="number">
|
||||||
/// <item>Parameter is the model with an update. </item>
|
/// <item>Parameter is the model with an update. </item>
|
||||||
/// <item>Parameter is the equipment slot changed. </item>
|
/// <item>Parameter is the equipment slot changed. </item>
|
||||||
/// <item>Parameter is the whether the crest will be shown. </item>
|
/// <item>Parameter is whether the crest will be shown. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed unsafe class CrestService : EventWrapper<Action<Actor, CrestFlag, Ref<bool>>, CrestService.Priority>
|
public sealed unsafe class CrestService : EventWrapperRef3<Actor, CrestFlag, bool, CrestService.Priority>
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
|
|
@ -72,9 +71,9 @@ public sealed unsafe class CrestService : EventWrapper<Action<Actor, CrestFlag,
|
||||||
var actor = (Actor)character;
|
var actor = (Actor)character;
|
||||||
foreach (var slot in CrestExtensions.AllRelevantSet)
|
foreach (var slot in CrestExtensions.AllRelevantSet)
|
||||||
{
|
{
|
||||||
var newValue = new Ref<bool>(((CrestFlag)crestFlags).HasFlag(slot));
|
var newValue = ((CrestFlag)crestFlags).HasFlag(slot);
|
||||||
Invoke(this, actor, slot, newValue);
|
Invoke(actor, slot, ref newValue);
|
||||||
crestFlags = (byte)(newValue.Value ? crestFlags | (byte)slot : crestFlags & (byte)~slot);
|
crestFlags = (byte)(newValue ? crestFlags | (byte)slot : crestFlags & (byte)~slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
Glamourer.Log.Verbose(
|
Glamourer.Log.Verbose(
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ public static class ServiceManagerA
|
||||||
{
|
{
|
||||||
public static ServiceManager CreateProvider(DalamudPluginInterface pi, Logger log)
|
public static ServiceManager CreateProvider(DalamudPluginInterface pi, Logger log)
|
||||||
{
|
{
|
||||||
EventWrapper.ChangeLogger(log);
|
EventWrapperBase.ChangeLogger(log);
|
||||||
var services = new ServiceManager(log)
|
var services = new ServiceManager(log)
|
||||||
.AddExistingService(log)
|
.AddExistingService(log)
|
||||||
.AddMeta()
|
.AddMeta()
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ public class StateListener : IDisposable
|
||||||
ProtectRestrictedGear(equipDataPtr, customize.Race, customize.Gender);
|
ProtectRestrictedGear(equipDataPtr, customize.Race, customize.Gender);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void OnCustomizeChange(Model model, Ref<CustomizeArray> customize)
|
private unsafe void OnCustomizeChange(Model model, ref CustomizeArray customize)
|
||||||
{
|
{
|
||||||
if (!model.IsHuman)
|
if (!model.IsHuman)
|
||||||
return;
|
return;
|
||||||
|
|
@ -151,7 +151,7 @@ public class StateListener : IDisposable
|
||||||
|| !_manager.TryGetValue(identifier, out var state))
|
|| !_manager.TryGetValue(identifier, out var state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateCustomize(actor, state, ref customize.Value, false);
|
UpdateCustomize(actor, state, ref customize, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCustomize(Actor actor, ActorState state, ref CustomizeArray customize, bool checkTransform)
|
private void UpdateCustomize(Actor actor, ActorState state, ref CustomizeArray customize, bool checkTransform)
|
||||||
|
|
@ -199,7 +199,7 @@ public class StateListener : IDisposable
|
||||||
/// A draw model loads a new equipment piece.
|
/// A draw model loads a new equipment piece.
|
||||||
/// Update base data, apply or update model data, and protect against restricted gear.
|
/// Update base data, apply or update model data, and protect against restricted gear.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnSlotUpdating(Model model, EquipSlot slot, Ref<CharacterArmor> armor, Ref<ulong> returnValue)
|
private void OnSlotUpdating(Model model, EquipSlot slot, ref CharacterArmor armor, ref ulong returnValue)
|
||||||
{
|
{
|
||||||
var actor = _penumbra.GameObjectFromDrawObject(model);
|
var actor = _penumbra.GameObjectFromDrawObject(model);
|
||||||
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
||||||
|
|
@ -212,16 +212,16 @@ public class StateListener : IDisposable
|
||||||
if (actor.Identifier(_actors, out var identifier)
|
if (actor.Identifier(_actors, out var identifier)
|
||||||
&& _manager.TryGetValue(identifier, out var state))
|
&& _manager.TryGetValue(identifier, out var state))
|
||||||
{
|
{
|
||||||
HandleEquipSlot(actor, state, slot, ref armor.Value);
|
HandleEquipSlot(actor, state, slot, ref armor);
|
||||||
locked = state[slot, false] is StateChanged.Source.Ipc;
|
locked = state[slot, false] is StateChanged.Source.Ipc;
|
||||||
}
|
}
|
||||||
|
|
||||||
_funModule.ApplyFunToSlot(actor, ref armor.Value, slot);
|
_funModule.ApplyFunToSlot(actor, ref armor, slot);
|
||||||
if (!_config.UseRestrictedGearProtection || locked)
|
if (!_config.UseRestrictedGearProtection || locked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var customize = model.GetCustomize();
|
var customize = model.GetCustomize();
|
||||||
(_, armor.Value) = _items.RestrictedGear.ResolveRestricted(armor, slot, customize.Race, customize.Gender);
|
(_, armor) = _items.RestrictedGear.ResolveRestricted(armor, slot, customize.Race, customize.Gender);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMovedEquipment((EquipSlot, uint, StainId)[] items)
|
private void OnMovedEquipment((EquipSlot, uint, StainId)[] items)
|
||||||
|
|
@ -264,20 +264,20 @@ public class StateListener : IDisposable
|
||||||
/// Update base data, apply or update model data.
|
/// Update base data, apply or update model data.
|
||||||
/// Verify consistent weapon types.
|
/// Verify consistent weapon types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnWeaponLoading(Actor actor, EquipSlot slot, Ref<CharacterWeapon> weapon)
|
private void OnWeaponLoading(Actor actor, EquipSlot slot, ref CharacterWeapon weapon)
|
||||||
{
|
{
|
||||||
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Fist weapon gauntlet hack.
|
// Fist weapon gauntlet hack.
|
||||||
if (slot is EquipSlot.OffHand && weapon.Value.Variant == 0 && weapon.Value.Weapon.Id != 0 && _lastFistOffhand.Weapon.Id != 0)
|
if (slot is EquipSlot.OffHand && weapon.Variant == 0 && weapon.Weapon.Id != 0 && _lastFistOffhand.Weapon.Id != 0)
|
||||||
weapon.Value = _lastFistOffhand;
|
weapon = _lastFistOffhand;
|
||||||
|
|
||||||
if (!actor.Identifier(_actors, out var identifier)
|
if (!actor.Identifier(_actors, out var identifier)
|
||||||
|| !_manager.TryGetValue(identifier, out var state))
|
|| !_manager.TryGetValue(identifier, out var state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ref var actorWeapon = ref weapon.Value;
|
ref var actorWeapon = ref weapon;
|
||||||
var baseType = state.BaseData.Item(slot).Type;
|
var baseType = state.BaseData.Item(slot).Type;
|
||||||
var apply = false;
|
var apply = false;
|
||||||
switch (UpdateBaseData(actor, state, slot, actorWeapon))
|
switch (UpdateBaseData(actor, state, slot, actorWeapon))
|
||||||
|
|
@ -311,25 +311,16 @@ public class StateListener : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fist Weapon Offhand hack.
|
// Fist Weapon Offhand hack.
|
||||||
if (slot is EquipSlot.MainHand && weapon.Value.Skeleton.Id is > 1600 and < 1651)
|
if (slot is EquipSlot.MainHand && weapon.Skeleton.Id is > 1600 and < 1651)
|
||||||
_lastFistOffhand = new CharacterWeapon((PrimaryId)(weapon.Value.Skeleton.Id + 50), weapon.Value.Weapon, weapon.Value.Variant,
|
_lastFistOffhand = new CharacterWeapon((PrimaryId)(weapon.Skeleton.Id + 50), weapon.Weapon, weapon.Variant,
|
||||||
weapon.Value.Stain);
|
weapon.Stain);
|
||||||
|
|
||||||
_funModule.ApplyFunToWeapon(actor, ref weapon.Value, slot);
|
_funModule.ApplyFunToWeapon(actor, ref weapon, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Update base data for a single changed equipment slot. </summary>
|
/// <summary> Update base data for a single changed equipment slot. </summary>
|
||||||
private UpdateState UpdateBaseData(Actor actor, ActorState state, EquipSlot slot, CharacterArmor armor)
|
private UpdateState UpdateBaseData(Actor actor, ActorState state, EquipSlot slot, CharacterArmor armor)
|
||||||
{
|
{
|
||||||
bool FistWeaponGauntletHack()
|
|
||||||
{
|
|
||||||
if (slot is not EquipSlot.Hands)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var offhand = actor.GetOffhand();
|
|
||||||
return offhand.Variant == 0 && offhand.Weapon.Id != 0 && armor.Set.Id == offhand.Weapon.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
var actorArmor = actor.GetArmor(slot);
|
var actorArmor = actor.GetArmor(slot);
|
||||||
var fistWeapon = FistWeaponGauntletHack();
|
var fistWeapon = FistWeaponGauntletHack();
|
||||||
|
|
||||||
|
|
@ -373,6 +364,15 @@ public class StateListener : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
return change;
|
return change;
|
||||||
|
|
||||||
|
bool FistWeaponGauntletHack()
|
||||||
|
{
|
||||||
|
if (slot is not EquipSlot.Hands)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var offhand = actor.GetOffhand();
|
||||||
|
return offhand.Variant == 0 && offhand.Weapon.Id != 0 && armor.Set.Id == offhand.Weapon.Id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Handle a full equip slot update for base data and model data. </summary>
|
/// <summary> Handle a full equip slot update for base data and model data. </summary>
|
||||||
|
|
@ -406,7 +406,7 @@ public class StateListener : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCrestChange(Actor actor, CrestFlag slot, Ref<bool> value)
|
private void OnCrestChange(Actor actor, CrestFlag slot, ref bool value)
|
||||||
{
|
{
|
||||||
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
||||||
return;
|
return;
|
||||||
|
|
@ -415,17 +415,17 @@ public class StateListener : IDisposable
|
||||||
|| !_manager.TryGetValue(identifier, out var state))
|
|| !_manager.TryGetValue(identifier, out var state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (UpdateBaseCrest(actor, state, slot, value.Value))
|
switch (UpdateBaseCrest(actor, state, slot, value))
|
||||||
{
|
{
|
||||||
case UpdateState.Change:
|
case UpdateState.Change:
|
||||||
if (state[slot] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
if (state[slot] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||||
_manager.ChangeCrest(state, slot, state.BaseData.Crest(slot), StateChanged.Source.Game);
|
_manager.ChangeCrest(state, slot, state.BaseData.Crest(slot), StateChanged.Source.Game);
|
||||||
else
|
else
|
||||||
value.Value = state.ModelData.Crest(slot);
|
value = state.ModelData.Crest(slot);
|
||||||
break;
|
break;
|
||||||
case UpdateState.NoChange:
|
case UpdateState.NoChange:
|
||||||
case UpdateState.HatHack:
|
case UpdateState.HatHack:
|
||||||
value.Value = state.ModelData.Crest(slot);
|
value = state.ModelData.Crest(slot);
|
||||||
break;
|
break;
|
||||||
case UpdateState.Transformed: break;
|
case UpdateState.Transformed: break;
|
||||||
}
|
}
|
||||||
|
|
@ -540,7 +540,7 @@ public class StateListener : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Handle visor state changes made by the game. </summary>
|
/// <summary> Handle visor state changes made by the game. </summary>
|
||||||
private void OnVisorChange(Model model, Ref<bool> value)
|
private void OnVisorChange(Model model, ref bool value)
|
||||||
{
|
{
|
||||||
// Skip updates when in customize update.
|
// Skip updates when in customize update.
|
||||||
if (ChangeCustomizeService.InUpdate.InMethod)
|
if (ChangeCustomizeService.InUpdate.InMethod)
|
||||||
|
|
@ -565,19 +565,19 @@ public class StateListener : IDisposable
|
||||||
// if base state changed, either overwrite the actual value if we have fixed values,
|
// if base state changed, either overwrite the actual value if we have fixed values,
|
||||||
// or overwrite the stored model state with the new one.
|
// or overwrite the stored model state with the new one.
|
||||||
if (state[ActorState.MetaIndex.VisorState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
if (state[ActorState.MetaIndex.VisorState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||||
value.Value = state.ModelData.IsVisorToggled();
|
value = state.ModelData.IsVisorToggled();
|
||||||
else
|
else
|
||||||
_manager.ChangeVisorState(state, value, StateChanged.Source.Game);
|
_manager.ChangeVisorState(state, value, StateChanged.Source.Game);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if base state did not change, overwrite the value with the model state one.
|
// if base state did not change, overwrite the value with the model state one.
|
||||||
value.Value = state.ModelData.IsVisorToggled();
|
value = state.ModelData.IsVisorToggled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Handle Hat Visibility changes. These act on the game object. </summary>
|
/// <summary> Handle Hat Visibility changes. These act on the game object. </summary>
|
||||||
private void OnHeadGearVisibilityChange(Actor actor, Ref<bool> value)
|
private void OnHeadGearVisibilityChange(Actor actor, ref bool value)
|
||||||
{
|
{
|
||||||
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
||||||
return;
|
return;
|
||||||
|
|
@ -598,19 +598,19 @@ public class StateListener : IDisposable
|
||||||
// if base state changed, either overwrite the actual value if we have fixed values,
|
// if base state changed, either overwrite the actual value if we have fixed values,
|
||||||
// or overwrite the stored model state with the new one.
|
// or overwrite the stored model state with the new one.
|
||||||
if (state[ActorState.MetaIndex.HatState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
if (state[ActorState.MetaIndex.HatState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||||
value.Value = state.ModelData.IsHatVisible();
|
value = state.ModelData.IsHatVisible();
|
||||||
else
|
else
|
||||||
_manager.ChangeHatState(state, value, StateChanged.Source.Game);
|
_manager.ChangeHatState(state, value, StateChanged.Source.Game);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if base state did not change, overwrite the value with the model state one.
|
// if base state did not change, overwrite the value with the model state one.
|
||||||
value.Value = state.ModelData.IsHatVisible();
|
value = state.ModelData.IsHatVisible();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Handle Weapon Visibility changes. These act on the game object. </summary>
|
/// <summary> Handle Weapon Visibility changes. These act on the game object. </summary>
|
||||||
private void OnWeaponVisibilityChange(Actor actor, Ref<bool> value)
|
private void OnWeaponVisibilityChange(Actor actor, ref bool value)
|
||||||
{
|
{
|
||||||
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
||||||
return;
|
return;
|
||||||
|
|
@ -631,14 +631,14 @@ public class StateListener : IDisposable
|
||||||
// if base state changed, either overwrite the actual value if we have fixed values,
|
// if base state changed, either overwrite the actual value if we have fixed values,
|
||||||
// or overwrite the stored model state with the new one.
|
// or overwrite the stored model state with the new one.
|
||||||
if (state[ActorState.MetaIndex.WeaponState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
if (state[ActorState.MetaIndex.WeaponState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||||
value.Value = state.ModelData.IsWeaponVisible();
|
value = state.ModelData.IsWeaponVisible();
|
||||||
else
|
else
|
||||||
_manager.ChangeWeaponState(state, value, StateChanged.Source.Game);
|
_manager.ChangeWeaponState(state, value, StateChanged.Source.Game);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if base state did not change, overwrite the value with the model state one.
|
// if base state did not change, overwrite the value with the model state one.
|
||||||
value.Value = state.ModelData.IsWeaponVisible();
|
value = state.ModelData.IsWeaponVisible();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -476,7 +476,7 @@ public class StateManager(
|
||||||
actors = ApplyAll(state, redraw, true);
|
actors = ApplyAll(state, redraw, true);
|
||||||
Glamourer.Log.Verbose(
|
Glamourer.Log.Verbose(
|
||||||
$"Reset entire state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
|
$"Reset entire state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||||
_event.Invoke(StateChanged.Type.Reset, StateChanged.Source.Manual, state, actors);
|
_event.Invoke(StateChanged.Type.Reset, StateChanged.Source.Manual, state, actors, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetStateFixed(ActorState state, uint key = 0)
|
public void ResetStateFixed(ActorState state, uint key = 0)
|
||||||
|
|
|
||||||
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit e58c3c1240cda9d2d2b54f5ab7b8c729c1251fd4
|
Subproject commit e4a82619332aade2748a381956a1ab8934de6211
|
||||||
Loading…
Add table
Add a link
Reference in a new issue