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
=> _lockedRedraw ? CustomizeFlagExtensions.AllRelevant & ~CustomizeFlagExtensions.RedrawRequired : CustomizeFlagExtensions.AllRelevant;
public void Draw()
public unsafe void Draw()
{
using var group = ImRaii.Group();
(_identifier, _data) = _selector.Selection;
@ -114,12 +114,18 @@ public class ActorPanel
if (!child || !_selector.HasSelection || !_stateManager.GetOrCreate(_identifier, _actor, out _state))
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();
ImGui.SameLine();
DrawApplyToTarget();
RevertButtons();
using var disabled = ImRaii.Disabled(transformationId != 0);
if (_state.ModelData.IsHuman)
DrawHumanPanel();
else

View file

@ -45,6 +45,9 @@ public readonly unsafe struct Actor : IEquatable<Actor>
public bool IsGPoseOrCutscene
=> Index.Index is >= (int)ScreenActor.CutsceneStart and < (int)ScreenActor.CutsceneEnd;
public bool IsTransformed
=> AsCharacter->CharacterData.TransformationId != 0;
public ActorIdentifier GetIdentifier(ActorManager actors)
=> 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)
{
if (!actor.IsCharacter || actor.AsObject->ObjectKind is not (byte)ObjectKind.Player)
return;
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
if (!ValidFunTarget(actor))
return;
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)
{
if (!actor.IsCharacter || actor.AsObject->ObjectKind is not (byte)ObjectKind.Player)
return;
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
if (!ValidFunTarget(actor))
return;
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)
{
if (!actor.IsCharacter || actor.AsObject->ObjectKind is not (byte)ObjectKind.Player)
return;
if (actor.AsCharacter->CharacterData.ModelCharaId != 0)
if (!ValidFunTarget(actor))
return;
if (_codes.EnabledWorld)
_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)
{
if (!_codes.EnabledClown)

View file

@ -13,6 +13,7 @@ using Penumbra.GameData.Structs;
using System;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin.Services;
using Glamourer.Structs;
namespace Glamourer.State;
@ -116,6 +117,9 @@ public class StateListener : IDisposable
/// <summary> The base state changed compared to prior state. </summary>
Change,
/// <summary> Special case for hat stuff. </summary>
HatHack,
}
/// <summary>
@ -315,7 +319,6 @@ public class StateListener : IDisposable
_manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateChanged.Source.Game);
else
apply = true;
break;
case UpdateState.NoChange:
apply = true;
@ -359,7 +362,12 @@ public class StateListener : IDisposable
if (actorArmor.Value != armor.Value)
{
// 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);
state.BaseData.SetItem(EquipSlot.Head, item);
@ -367,6 +375,9 @@ public class StateListener : IDisposable
return UpdateState.Change;
}
return UpdateState.HatHack;
}
if (!fistWeapon)
return UpdateState.Transformed;
}
@ -410,12 +421,10 @@ public class StateListener : IDisposable
if (apply)
armor = state.ModelData.ArmorWithState(slot);
break;
// Use current model data.
// Transformed also handles invisible hat state.
case UpdateState.NoChange:
case UpdateState.Transformed when slot is EquipSlot.Head && armor.Value is 0:
case UpdateState.HatHack:
armor = state.ModelData.ArmorWithState(slot);
break;
case UpdateState.Transformed: break;
@ -423,8 +432,15 @@ public class StateListener : IDisposable
}
/// <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 change = UpdateState.NoChange;