Try to handle transformations a bit better, maybe.

This commit is contained in:
Ottermandias 2023-10-23 14:43:11 +02:00
parent 8b8b14f2b6
commit 30c5cd0bdb
4 changed files with 45 additions and 23 deletions

View file

@ -68,7 +68,7 @@ public class ActorPanel
private CustomizeFlag CustomizeApplicationFlags private CustomizeFlag CustomizeApplicationFlags
=> _lockedRedraw ? CustomizeFlagExtensions.AllRelevant & ~CustomizeFlagExtensions.RedrawRequired : CustomizeFlagExtensions.AllRelevant; => _lockedRedraw ? CustomizeFlagExtensions.AllRelevant & ~CustomizeFlagExtensions.RedrawRequired : CustomizeFlagExtensions.AllRelevant;
public void Draw() public unsafe void Draw()
{ {
using var group = ImRaii.Group(); using var group = ImRaii.Group();
(_identifier, _data) = _selector.Selection; (_identifier, _data) = _selector.Selection;
@ -114,12 +114,18 @@ public class ActorPanel
if (!child || !_selector.HasSelection || !_stateManager.GetOrCreate(_identifier, _actor, out _state)) if (!child || !_selector.HasSelection || !_stateManager.GetOrCreate(_identifier, _actor, out _state))
return; return;
var transformationId = _actor.IsCharacter ? _actor.AsCharacter->CharacterData.TransformationId : 0;
if (transformationId != 0)
ImGuiUtil.DrawTextButton($"Currently transformed to Transformation {transformationId}.",
-Vector2.UnitX, Colors.SelectedRed);
DrawApplyToSelf(); DrawApplyToSelf();
ImGui.SameLine(); ImGui.SameLine();
DrawApplyToTarget(); DrawApplyToTarget();
RevertButtons(); RevertButtons();
using var disabled = ImRaii.Disabled(transformationId != 0);
if (_state.ModelData.IsHuman) if (_state.ModelData.IsHuman)
DrawHumanPanel(); DrawHumanPanel();
else else

View file

@ -45,6 +45,9 @@ public readonly unsafe struct Actor : IEquatable<Actor>
public bool IsGPoseOrCutscene public bool IsGPoseOrCutscene
=> Index.Index is >= (int)ScreenActor.CutsceneStart and < (int)ScreenActor.CutsceneEnd; => Index.Index is >= (int)ScreenActor.CutsceneStart and < (int)ScreenActor.CutsceneEnd;
public bool IsTransformed
=> AsCharacter->CharacterData.TransformationId != 0;
public ActorIdentifier GetIdentifier(ActorManager actors) public ActorIdentifier GetIdentifier(ActorManager actors)
=> actors.FromObject(AsObject, out _, true, true, false); => actors.FromObject(AsObject, out _, true, true, false);

View file

@ -92,10 +92,7 @@ public unsafe class FunModule : IDisposable
public void ApplyFun(Actor actor, ref CharacterArmor armor, EquipSlot slot) public void ApplyFun(Actor actor, ref CharacterArmor armor, EquipSlot slot)
{ {
if (!actor.IsCharacter || actor.AsObject->ObjectKind is not (byte)ObjectKind.Player) if (!ValidFunTarget(actor))
return;
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
return; return;
if (_config.DisableFestivals == 0 && _festivalSet != null if (_config.DisableFestivals == 0 && _festivalSet != null
@ -112,10 +109,7 @@ public unsafe class FunModule : IDisposable
public void ApplyFun(Actor actor, Span<CharacterArmor> armor, ref Customize customize) public void ApplyFun(Actor actor, Span<CharacterArmor> armor, ref Customize customize)
{ {
if (!actor.IsCharacter || actor.AsObject->ObjectKind is not (byte)ObjectKind.Player) if (!ValidFunTarget(actor))
return;
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
return; return;
if (_config.DisableFestivals == 0 && _festivalSet != null) if (_config.DisableFestivals == 0 && _festivalSet != null)
@ -140,16 +134,19 @@ public unsafe class FunModule : IDisposable
public void ApplyFun(Actor actor, ref CharacterWeapon weapon, EquipSlot slot) public void ApplyFun(Actor actor, ref CharacterWeapon weapon, EquipSlot slot)
{ {
if (!actor.IsCharacter || actor.AsObject->ObjectKind is not (byte)ObjectKind.Player) if (!ValidFunTarget(actor))
return;
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
return; return;
if (_codes.EnabledWorld) if (_codes.EnabledWorld)
_worldSets.Apply(actor, _rng, ref weapon, slot); _worldSets.Apply(actor, _rng, ref weapon, slot);
} }
private static bool ValidFunTarget(Actor actor)
=> actor.IsCharacter
&& actor.AsObject->ObjectKind is (byte)ObjectKind.Player
&& !actor.IsTransformed
&& actor.AsCharacter->CharacterData.ModelCharaId == 0;
public void ApplyClown(Span<CharacterArmor> armors) public void ApplyClown(Span<CharacterArmor> armors)
{ {
if (!_codes.EnabledClown) if (!_codes.EnabledClown)

View file

@ -13,6 +13,7 @@ using Penumbra.GameData.Structs;
using System; using System;
using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Glamourer.Structs;
namespace Glamourer.State; namespace Glamourer.State;
@ -116,6 +117,9 @@ public class StateListener : IDisposable
/// <summary> The base state changed compared to prior state. </summary> /// <summary> The base state changed compared to prior state. </summary>
Change, Change,
/// <summary> Special case for hat stuff. </summary>
HatHack,
} }
/// <summary> /// <summary>
@ -315,7 +319,6 @@ public class StateListener : IDisposable
_manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateChanged.Source.Game); _manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateChanged.Source.Game);
else else
apply = true; apply = true;
break; break;
case UpdateState.NoChange: case UpdateState.NoChange:
apply = true; apply = true;
@ -359,7 +362,12 @@ public class StateListener : IDisposable
if (actorArmor.Value != armor.Value) if (actorArmor.Value != armor.Value)
{ {
// Update base data in case hat visibility is off. // Update base data in case hat visibility is off.
if (slot is EquipSlot.Head && armor.Value == 0 && actorArmor.Value != state.BaseData.Armor(EquipSlot.Head).Value) if (slot is EquipSlot.Head && armor.Value == 0)
{
if (actor.IsTransformed)
return UpdateState.Transformed;
if (actorArmor.Value != state.BaseData.Armor(EquipSlot.Head).Value)
{ {
var item = _items.Identify(slot, actorArmor.Set, actorArmor.Variant); var item = _items.Identify(slot, actorArmor.Set, actorArmor.Variant);
state.BaseData.SetItem(EquipSlot.Head, item); state.BaseData.SetItem(EquipSlot.Head, item);
@ -367,6 +375,9 @@ public class StateListener : IDisposable
return UpdateState.Change; return UpdateState.Change;
} }
return UpdateState.HatHack;
}
if (!fistWeapon) if (!fistWeapon)
return UpdateState.Transformed; return UpdateState.Transformed;
} }
@ -410,12 +421,10 @@ public class StateListener : IDisposable
if (apply) if (apply)
armor = state.ModelData.ArmorWithState(slot); armor = state.ModelData.ArmorWithState(slot);
break; break;
// Use current model data. // Use current model data.
// Transformed also handles invisible hat state.
case UpdateState.NoChange: case UpdateState.NoChange:
case UpdateState.Transformed when slot is EquipSlot.Head && armor.Value is 0: case UpdateState.HatHack:
armor = state.ModelData.ArmorWithState(slot); armor = state.ModelData.ArmorWithState(slot);
break; break;
case UpdateState.Transformed: break; case UpdateState.Transformed: break;
@ -423,8 +432,15 @@ public class StateListener : IDisposable
} }
/// <summary> Update base data for a single changed weapon slot. </summary> /// <summary> Update base data for a single changed weapon slot. </summary>
private UpdateState UpdateBaseData(Actor actor, ActorState state, EquipSlot slot, CharacterWeapon weapon) private unsafe UpdateState UpdateBaseData(Actor actor, ActorState state, EquipSlot slot, CharacterWeapon weapon)
{ {
if (actor.AsCharacter->CharacterData.TransformationId != 0)
{
var actorWeapon = slot is EquipSlot.MainHand ? actor.GetMainhand() : actor.GetOffhand();
if (weapon.Value != actorWeapon.Value)
return UpdateState.Transformed;
}
var baseData = state.BaseData.Weapon(slot); var baseData = state.BaseData.Weapon(slot);
var change = UpdateState.NoChange; var change = UpdateState.NoChange;