mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-16 04:27:43 +01:00
Reworked all of the meta, made StateIndex its own thing.
This commit is contained in:
parent
70e4833fb5
commit
1ad70541d3
36 changed files with 747 additions and 657 deletions
|
|
@ -68,13 +68,13 @@ public class ActorState
|
|||
=> Unlock(1337);
|
||||
|
||||
/// <summary> This contains whether a change to the base data was made by the game, the user via manual input or through automatic application. </summary>
|
||||
public readonly StateSource Source = new();
|
||||
public StateSources Sources = new();
|
||||
|
||||
internal ActorState(ActorIdentifier identifier)
|
||||
=> Identifier = identifier.CreatePermanent();
|
||||
|
||||
public CustomizeParameterFlag OnlyChangedParameters()
|
||||
=> CustomizeParameterExtensions.AllFlags.Where(f => Source[f] is not StateChanged.Source.Game)
|
||||
=> CustomizeParameterExtensions.AllFlags.Where(f => Sources[f] is not StateSource.Game)
|
||||
.Aggregate((CustomizeParameterFlag)0, (a, b) => a | b);
|
||||
|
||||
public bool UpdateTerritory(ushort territory)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Glamourer.Events;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
|
|
@ -118,7 +119,7 @@ public class StateApplier(
|
|||
// If the source is not IPC we do not want to apply restrictions.
|
||||
var data = GetData(state);
|
||||
if (apply)
|
||||
ChangeArmor(data, slot, state.ModelData.Armor(slot), state.Source[slot, false] is not StateChanged.Source.Ipc,
|
||||
ChangeArmor(data, slot, state.ModelData.Armor(slot), state.Sources[slot, false] is not StateSource.Ipc,
|
||||
state.ModelData.IsHatVisible());
|
||||
|
||||
return data;
|
||||
|
|
@ -200,67 +201,44 @@ public class StateApplier(
|
|||
_weapon.LoadWeapon(actor, EquipSlot.OffHand, weapon.Weapon().With(stain));
|
||||
}
|
||||
|
||||
/// <summary> Change the visor state of actors only on the draw object. </summary>
|
||||
public void ChangeVisor(ActorData data, bool value)
|
||||
/// <summary> Change a meta state. </summary>
|
||||
public unsafe void ChangeMetaState(ActorData data, MetaIndex index, bool value)
|
||||
{
|
||||
foreach (var actor in data.Objects.Where(a => a.Model.IsHuman))
|
||||
_visor.SetVisorState(actor.Model, value);
|
||||
switch (index)
|
||||
{
|
||||
case MetaIndex.Wetness:
|
||||
{
|
||||
foreach (var actor in data.Objects.Where(a => a.IsCharacter))
|
||||
actor.AsCharacter->IsGPoseWet = value;
|
||||
return;
|
||||
}
|
||||
case MetaIndex.HatState:
|
||||
{
|
||||
foreach (var actor in data.Objects.Where(a => a.IsCharacter))
|
||||
_metaService.SetHatState(actor, value);
|
||||
return;
|
||||
}
|
||||
case MetaIndex.WeaponState:
|
||||
{
|
||||
foreach (var actor in data.Objects.Where(a => a.IsCharacter))
|
||||
_metaService.SetWeaponState(actor, value);
|
||||
return;
|
||||
}
|
||||
case MetaIndex.VisorState:
|
||||
{
|
||||
foreach (var actor in data.Objects.Where(a => a.Model.IsHuman))
|
||||
_visor.SetVisorState(actor.Model, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ChangeVisor(ActorData, bool)"/>
|
||||
public ActorData ChangeVisor(ActorState state, bool apply)
|
||||
/// <inheritdoc cref="ChangeMetaState(ActorData, MetaIndex, bool)"/>
|
||||
public ActorData ChangeMetaState(ActorState state, MetaIndex index, bool apply)
|
||||
{
|
||||
var data = GetData(state);
|
||||
if (apply)
|
||||
ChangeVisor(data, state.ModelData.IsVisorToggled());
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary> Change the forced wetness state on actors. </summary>
|
||||
public unsafe void ChangeWetness(ActorData data, bool value)
|
||||
{
|
||||
foreach (var actor in data.Objects.Where(a => a.IsCharacter))
|
||||
actor.AsCharacter->IsGPoseWet = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ChangeWetness(ActorData, bool)"/>
|
||||
public ActorData ChangeWetness(ActorState state, bool apply)
|
||||
{
|
||||
var data = GetData(state);
|
||||
if (apply)
|
||||
ChangeWetness(data, state.ModelData.IsWet());
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary> Change the hat-visibility state on actors. </summary>
|
||||
public void ChangeHatState(ActorData data, bool value)
|
||||
{
|
||||
foreach (var actor in data.Objects.Where(a => a.IsCharacter))
|
||||
_metaService.SetHatState(actor, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ChangeHatState(ActorData, bool)"/>
|
||||
public ActorData ChangeHatState(ActorState state, bool apply)
|
||||
{
|
||||
var data = GetData(state);
|
||||
if (apply)
|
||||
ChangeHatState(data, state.ModelData.IsHatVisible());
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary> Change the weapon-visibility state on actors. </summary>
|
||||
public void ChangeWeaponState(ActorData data, bool value)
|
||||
{
|
||||
foreach (var actor in data.Objects.Where(a => a.IsCharacter))
|
||||
_metaService.SetWeaponState(actor, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ChangeWeaponState(ActorData, bool)"/>
|
||||
public ActorData ChangeWeaponState(ActorState state, bool apply)
|
||||
{
|
||||
var data = GetData(state);
|
||||
if (apply)
|
||||
ChangeWeaponState(data, state.ModelData.IsWeaponVisible());
|
||||
ChangeMetaState(data, index, state.ModelData.GetMeta(index));
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public class StateEditor(CustomizeService customizations, HumanModelList humans,
|
|||
{
|
||||
/// <summary> Change the model id. If the actor is changed from a human to another human, customize and equipData are unused. </summary>
|
||||
/// <remarks> We currently only allow changing things to humans, not humans to monsters. </remarks>
|
||||
public bool ChangeModelId(ActorState state, uint modelId, in CustomizeArray customize, nint equipData, StateChanged.Source source,
|
||||
public bool ChangeModelId(ActorState state, uint modelId, in CustomizeArray customize, nint equipData, StateSource source,
|
||||
out uint oldModelId, uint key = 0)
|
||||
{
|
||||
oldModelId = state.ModelData.ModelId;
|
||||
|
|
@ -45,21 +45,21 @@ public class StateEditor(CustomizeService customizations, HumanModelList humans,
|
|||
state.ModelData.SetHatVisible(true);
|
||||
state.ModelData.SetWeaponVisible(true);
|
||||
state.ModelData.SetVisor(false);
|
||||
state.Source[MetaIndex.ModelId] = source;
|
||||
state.Source[MetaIndex.HatState] = source;
|
||||
state.Source[MetaIndex.WeaponState] = source;
|
||||
state.Source[MetaIndex.VisorState] = source;
|
||||
state.Sources[MetaIndex.ModelId] = source;
|
||||
state.Sources[MetaIndex.HatState] = source;
|
||||
state.Sources[MetaIndex.WeaponState] = source;
|
||||
state.Sources[MetaIndex.VisorState] = source;
|
||||
foreach (var slot in EquipSlotExtensions.FullSlots)
|
||||
{
|
||||
state.Source[slot, true] = source;
|
||||
state.Source[slot, false] = source;
|
||||
state.Sources[slot, true] = source;
|
||||
state.Sources[slot, false] = source;
|
||||
}
|
||||
|
||||
state.Source[CustomizeIndex.Clan] = source;
|
||||
state.Source[CustomizeIndex.Gender] = source;
|
||||
state.Sources[CustomizeIndex.Clan] = source;
|
||||
state.Sources[CustomizeIndex.Gender] = source;
|
||||
var set = customizations.Manager.GetSet(state.ModelData.Customize.Clan, state.ModelData.Customize.Gender);
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>().Where(set.IsAvailable))
|
||||
state.Source[index] = source;
|
||||
state.Sources[index] = source;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -67,14 +67,14 @@ public class StateEditor(CustomizeService customizations, HumanModelList humans,
|
|||
return false;
|
||||
|
||||
state.ModelData.LoadNonHuman(modelId, customize, equipData);
|
||||
state.Source[MetaIndex.ModelId] = source;
|
||||
state.Sources[MetaIndex.ModelId] = source;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Change a customization value. </summary>
|
||||
public bool ChangeCustomize(ActorState state, CustomizeIndex idx, CustomizeValue value, StateChanged.Source source,
|
||||
public bool ChangeCustomize(ActorState state, CustomizeIndex idx, CustomizeValue value, StateSource source,
|
||||
out CustomizeValue old, uint key = 0)
|
||||
{
|
||||
old = state.ModelData.Customize[idx];
|
||||
|
|
@ -82,12 +82,12 @@ public class StateEditor(CustomizeService customizations, HumanModelList humans,
|
|||
return false;
|
||||
|
||||
state.ModelData.Customize[idx] = value;
|
||||
state.Source[idx] = source;
|
||||
state.Sources[idx] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Change an entire customization array according to flags. </summary>
|
||||
public bool ChangeHumanCustomize(ActorState state, in CustomizeArray customizeInput, CustomizeFlag applyWhich, StateChanged.Source source,
|
||||
public bool ChangeHumanCustomize(ActorState state, in CustomizeArray customizeInput, CustomizeFlag applyWhich, StateSource source,
|
||||
out CustomizeArray old, out CustomizeFlag changed, uint key = 0)
|
||||
{
|
||||
old = state.ModelData.Customize;
|
||||
|
|
@ -104,14 +104,14 @@ public class StateEditor(CustomizeService customizations, HumanModelList humans,
|
|||
foreach (var type in Enum.GetValues<CustomizeIndex>())
|
||||
{
|
||||
if (applied.HasFlag(type.ToFlag()))
|
||||
state.Source[type] = source;
|
||||
state.Sources[type] = source;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Change a single piece of equipment without stain. </summary>
|
||||
public bool ChangeItem(ActorState state, EquipSlot slot, EquipItem item, StateChanged.Source source, out EquipItem oldItem, uint key = 0)
|
||||
public bool ChangeItem(ActorState state, EquipSlot slot, EquipItem item, StateSource source, out EquipItem oldItem, uint key = 0)
|
||||
{
|
||||
oldItem = state.ModelData.Item(slot);
|
||||
if (!state.CanUnlock(key))
|
||||
|
|
@ -128,17 +128,17 @@ public class StateEditor(CustomizeService customizations, HumanModelList humans,
|
|||
gPose.AddActionOnLeave(() =>
|
||||
{
|
||||
if (old.Type == state.BaseData.Item(slot).Type)
|
||||
ChangeItem(state, slot, old, state.Source[slot, false], out _, key);
|
||||
ChangeItem(state, slot, old, state.Sources[slot, false], out _, key);
|
||||
});
|
||||
}
|
||||
|
||||
state.ModelData.SetItem(slot, item);
|
||||
state.Source[slot, false] = source;
|
||||
state.Sources[slot, false] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Change a single piece of equipment including stain. </summary>
|
||||
public bool ChangeEquip(ActorState state, EquipSlot slot, EquipItem item, StainId stain, StateChanged.Source source, out EquipItem oldItem,
|
||||
public bool ChangeEquip(ActorState state, EquipSlot slot, EquipItem item, StainId stain, StateSource source, out EquipItem oldItem,
|
||||
out StainId oldStain, uint key = 0)
|
||||
{
|
||||
oldItem = state.ModelData.Item(slot);
|
||||
|
|
@ -158,43 +158,43 @@ public class StateEditor(CustomizeService customizations, HumanModelList humans,
|
|||
gPose.AddActionOnLeave(() =>
|
||||
{
|
||||
if (old.Type == state.BaseData.Item(slot).Type)
|
||||
ChangeEquip(state, slot, old, oldS, state.Source[slot, false], out _, out _, key);
|
||||
ChangeEquip(state, slot, old, oldS, state.Sources[slot, false], out _, out _, key);
|
||||
});
|
||||
}
|
||||
|
||||
state.ModelData.SetItem(slot, item);
|
||||
state.ModelData.SetStain(slot, stain);
|
||||
state.Source[slot, false] = source;
|
||||
state.Source[slot, true] = source;
|
||||
state.Sources[slot, false] = source;
|
||||
state.Sources[slot, true] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Change only the stain of an equipment piece. </summary>
|
||||
public bool ChangeStain(ActorState state, EquipSlot slot, StainId stain, StateChanged.Source source, out StainId oldStain, uint key = 0)
|
||||
public bool ChangeStain(ActorState state, EquipSlot slot, StainId stain, StateSource source, out StainId oldStain, uint key = 0)
|
||||
{
|
||||
oldStain = state.ModelData.Stain(slot);
|
||||
if (!state.CanUnlock(key))
|
||||
return false;
|
||||
|
||||
state.ModelData.SetStain(slot, stain);
|
||||
state.Source[slot, true] = source;
|
||||
state.Sources[slot, true] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Change the crest of an equipment piece. </summary>
|
||||
public bool ChangeCrest(ActorState state, CrestFlag slot, bool crest, StateChanged.Source source, out bool oldCrest, uint key = 0)
|
||||
public bool ChangeCrest(ActorState state, CrestFlag slot, bool crest, StateSource source, out bool oldCrest, uint key = 0)
|
||||
{
|
||||
oldCrest = state.ModelData.Crest(slot);
|
||||
if (!state.CanUnlock(key))
|
||||
return false;
|
||||
|
||||
state.ModelData.SetCrest(slot, crest);
|
||||
state.Source[slot] = source;
|
||||
state.Sources[slot] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Change the customize flags of a character. </summary>
|
||||
public bool ChangeParameter(ActorState state, CustomizeParameterFlag flag, CustomizeParameterValue value, StateChanged.Source source,
|
||||
public bool ChangeParameter(ActorState state, CustomizeParameterFlag flag, CustomizeParameterValue value, StateSource source,
|
||||
out CustomizeParameterValue oldValue, uint key = 0)
|
||||
{
|
||||
oldValue = state.ModelData.Parameters[flag];
|
||||
|
|
@ -202,29 +202,20 @@ public class StateEditor(CustomizeService customizations, HumanModelList humans,
|
|||
return false;
|
||||
|
||||
state.ModelData.Parameters.Set(flag, value);
|
||||
state.Source[flag] = source;
|
||||
state.Sources[flag] = source;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ChangeMetaState(ActorState state, MetaIndex index, bool value, StateChanged.Source source, out bool oldValue,
|
||||
public bool ChangeMetaState(ActorState state, MetaIndex index, bool value, StateSource source, out bool oldValue,
|
||||
uint key = 0)
|
||||
{
|
||||
(var setter, oldValue) = index switch
|
||||
{
|
||||
MetaIndex.Wetness => ((Func<bool, bool>)(v => state.ModelData.SetIsWet(v)), state.ModelData.IsWet()),
|
||||
MetaIndex.HatState => ((Func<bool, bool>)(v => state.ModelData.SetHatVisible(v)), state.ModelData.IsHatVisible()),
|
||||
MetaIndex.VisorState => ((Func<bool, bool>)(v => state.ModelData.SetVisor(v)), state.ModelData.IsVisorToggled()),
|
||||
MetaIndex.WeaponState => ((Func<bool, bool>)(v => state.ModelData.SetWeaponVisible(v)),
|
||||
state.ModelData.IsWeaponVisible()),
|
||||
_ => throw new Exception("Invalid MetaIndex."),
|
||||
};
|
||||
|
||||
oldValue = state.ModelData.GetMeta(index);
|
||||
if (!state.CanUnlock(key))
|
||||
return false;
|
||||
|
||||
setter(value);
|
||||
state.Source[index] = source;
|
||||
state.ModelData.SetMeta(index, value);
|
||||
state.Sources[index] = source;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
235
Glamourer/State/StateIndex.cs
Normal file
235
Glamourer/State/StateIndex.cs
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
using Glamourer.Designs;
|
||||
using Glamourer.GameData;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.State;
|
||||
|
||||
public readonly record struct StateIndex(int Value) : IEqualityOperators<StateIndex, StateIndex, bool>
|
||||
{
|
||||
public static readonly StateIndex Invalid = new(-1);
|
||||
|
||||
public static implicit operator StateIndex(EquipFlag flag)
|
||||
=> flag switch
|
||||
{
|
||||
EquipFlag.Head => new StateIndex(EquipHead),
|
||||
EquipFlag.Body => new StateIndex(EquipBody),
|
||||
EquipFlag.Hands => new StateIndex(EquipHands),
|
||||
EquipFlag.Legs => new StateIndex(EquipLegs),
|
||||
EquipFlag.Feet => new StateIndex(EquipFeet),
|
||||
EquipFlag.Ears => new StateIndex(EquipEars),
|
||||
EquipFlag.Neck => new StateIndex(EquipNeck),
|
||||
EquipFlag.Wrist => new StateIndex(EquipWrist),
|
||||
EquipFlag.RFinger => new StateIndex(EquipRFinger),
|
||||
EquipFlag.LFinger => new StateIndex(EquipLFinger),
|
||||
EquipFlag.Mainhand => new StateIndex(EquipMainhand),
|
||||
EquipFlag.Offhand => new StateIndex(EquipOffhand),
|
||||
EquipFlag.HeadStain => new StateIndex(StainHead),
|
||||
EquipFlag.BodyStain => new StateIndex(StainBody),
|
||||
EquipFlag.HandsStain => new StateIndex(StainHands),
|
||||
EquipFlag.LegsStain => new StateIndex(StainLegs),
|
||||
EquipFlag.FeetStain => new StateIndex(StainFeet),
|
||||
EquipFlag.EarsStain => new StateIndex(StainEars),
|
||||
EquipFlag.NeckStain => new StateIndex(StainNeck),
|
||||
EquipFlag.WristStain => new StateIndex(StainWrist),
|
||||
EquipFlag.RFingerStain => new StateIndex(StainRFinger),
|
||||
EquipFlag.LFingerStain => new StateIndex(StainLFinger),
|
||||
EquipFlag.MainhandStain => new StateIndex(StainMainhand),
|
||||
EquipFlag.OffhandStain => new StateIndex(StainOffhand),
|
||||
_ => Invalid,
|
||||
};
|
||||
|
||||
public static implicit operator StateIndex(CustomizeIndex index)
|
||||
=> index switch
|
||||
{
|
||||
CustomizeIndex.Race => new StateIndex(CustomizeRace),
|
||||
CustomizeIndex.Gender => new StateIndex(CustomizeGender),
|
||||
CustomizeIndex.BodyType => new StateIndex(CustomizeBodyType),
|
||||
CustomizeIndex.Height => new StateIndex(CustomizeHeight),
|
||||
CustomizeIndex.Clan => new StateIndex(CustomizeClan),
|
||||
CustomizeIndex.Face => new StateIndex(CustomizeFace),
|
||||
CustomizeIndex.Hairstyle => new StateIndex(CustomizeHairstyle),
|
||||
CustomizeIndex.Highlights => new StateIndex(CustomizeHighlights),
|
||||
CustomizeIndex.SkinColor => new StateIndex(CustomizeSkinColor),
|
||||
CustomizeIndex.EyeColorRight => new StateIndex(CustomizeEyeColorRight),
|
||||
CustomizeIndex.HairColor => new StateIndex(CustomizeHairColor),
|
||||
CustomizeIndex.HighlightsColor => new StateIndex(CustomizeHighlightsColor),
|
||||
CustomizeIndex.FacialFeature1 => new StateIndex(CustomizeFacialFeature1),
|
||||
CustomizeIndex.FacialFeature2 => new StateIndex(CustomizeFacialFeature2),
|
||||
CustomizeIndex.FacialFeature3 => new StateIndex(CustomizeFacialFeature3),
|
||||
CustomizeIndex.FacialFeature4 => new StateIndex(CustomizeFacialFeature4),
|
||||
CustomizeIndex.FacialFeature5 => new StateIndex(CustomizeFacialFeature5),
|
||||
CustomizeIndex.FacialFeature6 => new StateIndex(CustomizeFacialFeature6),
|
||||
CustomizeIndex.FacialFeature7 => new StateIndex(CustomizeFacialFeature7),
|
||||
CustomizeIndex.LegacyTattoo => new StateIndex(CustomizeLegacyTattoo),
|
||||
CustomizeIndex.TattooColor => new StateIndex(CustomizeTattooColor),
|
||||
CustomizeIndex.Eyebrows => new StateIndex(CustomizeEyebrows),
|
||||
CustomizeIndex.EyeColorLeft => new StateIndex(CustomizeEyeColorLeft),
|
||||
CustomizeIndex.EyeShape => new StateIndex(CustomizeEyeShape),
|
||||
CustomizeIndex.SmallIris => new StateIndex(CustomizeSmallIris),
|
||||
CustomizeIndex.Nose => new StateIndex(CustomizeNose),
|
||||
CustomizeIndex.Jaw => new StateIndex(CustomizeJaw),
|
||||
CustomizeIndex.Mouth => new StateIndex(CustomizeMouth),
|
||||
CustomizeIndex.Lipstick => new StateIndex(CustomizeLipstick),
|
||||
CustomizeIndex.LipColor => new StateIndex(CustomizeLipColor),
|
||||
CustomizeIndex.MuscleMass => new StateIndex(CustomizeMuscleMass),
|
||||
CustomizeIndex.TailShape => new StateIndex(CustomizeTailShape),
|
||||
CustomizeIndex.BustSize => new StateIndex(CustomizeBustSize),
|
||||
CustomizeIndex.FacePaint => new StateIndex(CustomizeFacePaint),
|
||||
CustomizeIndex.FacePaintReversed => new StateIndex(CustomizeFacePaintReversed),
|
||||
CustomizeIndex.FacePaintColor => new StateIndex(CustomizeFacePaintColor),
|
||||
_ => Invalid,
|
||||
};
|
||||
|
||||
public static implicit operator StateIndex(MetaIndex meta)
|
||||
=> new((int)meta);
|
||||
|
||||
public static implicit operator StateIndex(CrestFlag crest)
|
||||
=> crest switch
|
||||
{
|
||||
CrestFlag.OffHand => new StateIndex(CrestOffhand),
|
||||
CrestFlag.Head => new StateIndex(CrestHead),
|
||||
CrestFlag.Body => new StateIndex(CrestBody),
|
||||
_ => Invalid,
|
||||
};
|
||||
|
||||
public static implicit operator StateIndex(CustomizeParameterFlag param)
|
||||
=> param switch
|
||||
{
|
||||
CustomizeParameterFlag.SkinDiffuse => new StateIndex(ParamSkinDiffuse),
|
||||
CustomizeParameterFlag.MuscleTone => new StateIndex(ParamMuscleTone),
|
||||
CustomizeParameterFlag.SkinSpecular => new StateIndex(ParamSkinSpecular),
|
||||
CustomizeParameterFlag.LipDiffuse => new StateIndex(ParamLipDiffuse),
|
||||
CustomizeParameterFlag.HairDiffuse => new StateIndex(ParamHairDiffuse),
|
||||
CustomizeParameterFlag.HairSpecular => new StateIndex(ParamHairSpecular),
|
||||
CustomizeParameterFlag.HairHighlight => new StateIndex(ParamHairHighlight),
|
||||
CustomizeParameterFlag.LeftEye => new StateIndex(ParamLeftEye),
|
||||
CustomizeParameterFlag.RightEye => new StateIndex(ParamRightEye),
|
||||
CustomizeParameterFlag.FeatureColor => new StateIndex(ParamFeatureColor),
|
||||
CustomizeParameterFlag.FacePaintUvMultiplier => new StateIndex(ParamFacePaintUvMultiplier),
|
||||
CustomizeParameterFlag.FacePaintUvOffset => new StateIndex(ParamFacePaintUvOffset),
|
||||
CustomizeParameterFlag.DecalColor => new StateIndex(ParamDecalColor),
|
||||
_ => Invalid,
|
||||
};
|
||||
|
||||
public const int EquipHead = 0;
|
||||
public const int EquipBody = 1;
|
||||
public const int EquipHands = 2;
|
||||
public const int EquipLegs = 3;
|
||||
public const int EquipFeet = 4;
|
||||
public const int EquipEars = 5;
|
||||
public const int EquipNeck = 6;
|
||||
public const int EquipWrist = 7;
|
||||
public const int EquipRFinger = 8;
|
||||
public const int EquipLFinger = 9;
|
||||
public const int EquipMainhand = 10;
|
||||
public const int EquipOffhand = 11;
|
||||
|
||||
public const int StainHead = 12;
|
||||
public const int StainBody = 13;
|
||||
public const int StainHands = 14;
|
||||
public const int StainLegs = 15;
|
||||
public const int StainFeet = 16;
|
||||
public const int StainEars = 17;
|
||||
public const int StainNeck = 18;
|
||||
public const int StainWrist = 19;
|
||||
public const int StainRFinger = 20;
|
||||
public const int StainLFinger = 21;
|
||||
public const int StainMainhand = 22;
|
||||
public const int StainOffhand = 23;
|
||||
|
||||
public const int CustomizeRace = 24;
|
||||
public const int CustomizeGender = 25;
|
||||
public const int CustomizeBodyType = 26;
|
||||
public const int CustomizeHeight = 27;
|
||||
public const int CustomizeClan = 28;
|
||||
public const int CustomizeFace = 29;
|
||||
public const int CustomizeHairstyle = 30;
|
||||
public const int CustomizeHighlights = 31;
|
||||
public const int CustomizeSkinColor = 32;
|
||||
public const int CustomizeEyeColorRight = 33;
|
||||
public const int CustomizeHairColor = 34;
|
||||
public const int CustomizeHighlightsColor = 35;
|
||||
public const int CustomizeFacialFeature1 = 36;
|
||||
public const int CustomizeFacialFeature2 = 37;
|
||||
public const int CustomizeFacialFeature3 = 38;
|
||||
public const int CustomizeFacialFeature4 = 39;
|
||||
public const int CustomizeFacialFeature5 = 40;
|
||||
public const int CustomizeFacialFeature6 = 41;
|
||||
public const int CustomizeFacialFeature7 = 42;
|
||||
public const int CustomizeLegacyTattoo = 43;
|
||||
public const int CustomizeTattooColor = 44;
|
||||
public const int CustomizeEyebrows = 45;
|
||||
public const int CustomizeEyeColorLeft = 46;
|
||||
public const int CustomizeEyeShape = 47;
|
||||
public const int CustomizeSmallIris = 48;
|
||||
public const int CustomizeNose = 49;
|
||||
public const int CustomizeJaw = 50;
|
||||
public const int CustomizeMouth = 51;
|
||||
public const int CustomizeLipstick = 52;
|
||||
public const int CustomizeLipColor = 53;
|
||||
public const int CustomizeMuscleMass = 54;
|
||||
public const int CustomizeTailShape = 55;
|
||||
public const int CustomizeBustSize = 56;
|
||||
public const int CustomizeFacePaint = 57;
|
||||
public const int CustomizeFacePaintReversed = 58;
|
||||
public const int CustomizeFacePaintColor = 59;
|
||||
|
||||
public const int MetaWetness = 60;
|
||||
public const int MetaHatState = 61;
|
||||
public const int MetaVisorState = 62;
|
||||
public const int MetaWeaponState = 63;
|
||||
public const int MetaModelId = 64;
|
||||
|
||||
public const int CrestHead = 65;
|
||||
public const int CrestBody = 66;
|
||||
public const int CrestOffhand = 67;
|
||||
|
||||
public const int ParamSkinDiffuse = 68;
|
||||
public const int ParamMuscleTone = 69;
|
||||
public const int ParamSkinSpecular = 70;
|
||||
public const int ParamLipDiffuse = 71;
|
||||
public const int ParamHairDiffuse = 72;
|
||||
public const int ParamHairSpecular = 73;
|
||||
public const int ParamHairHighlight = 74;
|
||||
public const int ParamLeftEye = 75;
|
||||
public const int ParamRightEye = 76;
|
||||
public const int ParamFeatureColor = 77;
|
||||
public const int ParamFacePaintUvMultiplier = 78;
|
||||
public const int ParamFacePaintUvOffset = 79;
|
||||
public const int ParamDecalColor = 80;
|
||||
|
||||
public const int Size = 81;
|
||||
}
|
||||
|
||||
public static class StateExtensions
|
||||
{
|
||||
public static StateIndex ToState(this EquipSlot slot, bool stain = false)
|
||||
=> (slot, stain) switch
|
||||
{
|
||||
(EquipSlot.Head, true) => new StateIndex(StateIndex.EquipHead),
|
||||
(EquipSlot.Body, true) => new StateIndex(StateIndex.EquipBody),
|
||||
(EquipSlot.Hands, true) => new StateIndex(StateIndex.EquipHands),
|
||||
(EquipSlot.Legs, true) => new StateIndex(StateIndex.EquipLegs),
|
||||
(EquipSlot.Feet, true) => new StateIndex(StateIndex.EquipFeet),
|
||||
(EquipSlot.Ears, true) => new StateIndex(StateIndex.EquipEars),
|
||||
(EquipSlot.Neck, true) => new StateIndex(StateIndex.EquipNeck),
|
||||
(EquipSlot.Wrists, true) => new StateIndex(StateIndex.EquipWrist),
|
||||
(EquipSlot.RFinger, true) => new StateIndex(StateIndex.EquipRFinger),
|
||||
(EquipSlot.LFinger, true) => new StateIndex(StateIndex.EquipLFinger),
|
||||
(EquipSlot.MainHand, true) => new StateIndex(StateIndex.EquipMainhand),
|
||||
(EquipSlot.OffHand, true) => new StateIndex(StateIndex.EquipOffhand),
|
||||
(EquipSlot.Head, false) => new StateIndex(StateIndex.StainHead),
|
||||
(EquipSlot.Body, false) => new StateIndex(StateIndex.StainBody),
|
||||
(EquipSlot.Hands, false) => new StateIndex(StateIndex.StainHands),
|
||||
(EquipSlot.Legs, false) => new StateIndex(StateIndex.StainLegs),
|
||||
(EquipSlot.Feet, false) => new StateIndex(StateIndex.StainFeet),
|
||||
(EquipSlot.Ears, false) => new StateIndex(StateIndex.StainEars),
|
||||
(EquipSlot.Neck, false) => new StateIndex(StateIndex.StainNeck),
|
||||
(EquipSlot.Wrists, false) => new StateIndex(StateIndex.StainWrist),
|
||||
(EquipSlot.RFinger, false) => new StateIndex(StateIndex.StainRFinger),
|
||||
(EquipSlot.LFinger, false) => new StateIndex(StateIndex.StainLFinger),
|
||||
(EquipSlot.MainHand, false) => new StateIndex(StateIndex.StainMainhand),
|
||||
(EquipSlot.OffHand, false) => new StateIndex(StateIndex.StainOffhand),
|
||||
_ => StateIndex.Invalid,
|
||||
};
|
||||
}
|
||||
|
|
@ -164,21 +164,21 @@ public class StateListener : IDisposable
|
|||
var model = state.ModelData.Customize;
|
||||
if (customize.Gender != model.Gender || customize.Clan != model.Clan)
|
||||
{
|
||||
_manager.ChangeCustomize(state, in customize, CustomizeFlagExtensions.AllRelevant, StateChanged.Source.Game);
|
||||
_manager.ChangeCustomize(state, in customize, CustomizeFlagExtensions.AllRelevant, StateSource.Game);
|
||||
return;
|
||||
}
|
||||
|
||||
var set = _customizations.Manager.GetSet(model.Clan, model.Gender);
|
||||
foreach (var index in CustomizationExtensions.AllBasic)
|
||||
{
|
||||
if (state.Source[index] is not StateChanged.Source.Fixed)
|
||||
if (state.Sources[index] is not StateSource.Fixed)
|
||||
{
|
||||
var newValue = customize[index];
|
||||
var oldValue = model[index];
|
||||
if (newValue != oldValue)
|
||||
{
|
||||
if (set.Validate(index, newValue, out _, model.Face))
|
||||
_manager.ChangeCustomize(state, index, newValue, StateChanged.Source.Game);
|
||||
_manager.ChangeCustomize(state, index, newValue, StateSource.Game);
|
||||
else
|
||||
customize[index] = oldValue;
|
||||
}
|
||||
|
|
@ -214,7 +214,7 @@ public class StateListener : IDisposable
|
|||
&& _manager.TryGetValue(identifier, out var state))
|
||||
{
|
||||
HandleEquipSlot(actor, state, slot, ref armor);
|
||||
locked = state.Source[slot, false] is StateChanged.Source.Ipc;
|
||||
locked = state.Sources[slot, false] is StateSource.Ipc;
|
||||
}
|
||||
|
||||
_funModule.ApplyFunToSlot(actor, ref armor, slot);
|
||||
|
|
@ -241,10 +241,10 @@ public class StateListener : IDisposable
|
|||
continue;
|
||||
|
||||
var changed = changedItem.Weapon(stain);
|
||||
if (current.Value == changed.Value && state.Source[slot, false] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
if (current.Value == changed.Value && state.Sources[slot, false] is not StateSource.Fixed and not StateSource.Ipc)
|
||||
{
|
||||
_manager.ChangeItem(state, slot, currentItem, StateChanged.Source.Game);
|
||||
_manager.ChangeStain(state, slot, current.Stain, StateChanged.Source.Game);
|
||||
_manager.ChangeItem(state, slot, currentItem, StateSource.Game);
|
||||
_manager.ChangeStain(state, slot, current.Stain, StateSource.Game);
|
||||
switch (slot)
|
||||
{
|
||||
case EquipSlot.MainHand:
|
||||
|
|
@ -252,7 +252,7 @@ public class StateListener : IDisposable
|
|||
_applier.ChangeWeapon(objects, slot, currentItem, stain);
|
||||
break;
|
||||
default:
|
||||
_applier.ChangeArmor(objects, slot, current.ToArmor(), state.Source[slot, false] is not StateChanged.Source.Ipc,
|
||||
_applier.ChangeArmor(objects, slot, current.ToArmor(), state.Sources[slot, false] is not StateSource.Ipc,
|
||||
state.ModelData.IsHatVisible());
|
||||
break;
|
||||
}
|
||||
|
|
@ -286,13 +286,13 @@ public class StateListener : IDisposable
|
|||
// Do nothing. But this usually can not happen because the hooked function also writes to game objects later.
|
||||
case UpdateState.Transformed: break;
|
||||
case UpdateState.Change:
|
||||
if (state.Source[slot, false] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
_manager.ChangeItem(state, slot, state.BaseData.Item(slot), StateChanged.Source.Game);
|
||||
if (state.Sources[slot, false] is not StateSource.Fixed and not StateSource.Ipc)
|
||||
_manager.ChangeItem(state, slot, state.BaseData.Item(slot), StateSource.Game);
|
||||
else
|
||||
apply = true;
|
||||
|
||||
if (state.Source[slot, true] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
_manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateChanged.Source.Game);
|
||||
if (state.Sources[slot, true] is not StateSource.Fixed and not StateSource.Ipc)
|
||||
_manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateSource.Game);
|
||||
else
|
||||
apply = true;
|
||||
break;
|
||||
|
|
@ -385,13 +385,13 @@ public class StateListener : IDisposable
|
|||
// Update model state if not on fixed design.
|
||||
case UpdateState.Change:
|
||||
var apply = false;
|
||||
if (state.Source[slot, false] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
_manager.ChangeItem(state, slot, state.BaseData.Item(slot), StateChanged.Source.Game);
|
||||
if (state.Sources[slot, false] is not StateSource.Fixed and not StateSource.Ipc)
|
||||
_manager.ChangeItem(state, slot, state.BaseData.Item(slot), StateSource.Game);
|
||||
else
|
||||
apply = true;
|
||||
|
||||
if (state.Source[slot, true] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
_manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateChanged.Source.Game);
|
||||
if (state.Sources[slot, true] is not StateSource.Fixed and not StateSource.Ipc)
|
||||
_manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateSource.Game);
|
||||
else
|
||||
apply = true;
|
||||
|
||||
|
|
@ -419,8 +419,8 @@ public class StateListener : IDisposable
|
|||
switch (UpdateBaseCrest(actor, state, slot, value))
|
||||
{
|
||||
case UpdateState.Change:
|
||||
if (state.Source[slot] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
_manager.ChangeCrest(state, slot, state.BaseData.Crest(slot), StateChanged.Source.Game);
|
||||
if (state.Sources[slot] is not StateSource.Fixed and not StateSource.Ipc)
|
||||
_manager.ChangeCrest(state, slot, state.BaseData.Crest(slot), StateSource.Game);
|
||||
else
|
||||
value = state.ModelData.Crest(slot);
|
||||
break;
|
||||
|
|
@ -565,10 +565,10 @@ public class StateListener : IDisposable
|
|||
{
|
||||
// if base state changed, either overwrite the actual value if we have fixed values,
|
||||
// or overwrite the stored model state with the new one.
|
||||
if (state.Source[MetaIndex.VisorState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
if (state.Sources[MetaIndex.VisorState] is StateSource.Fixed or StateSource.Ipc)
|
||||
value = state.ModelData.IsVisorToggled();
|
||||
else
|
||||
_manager.ChangeVisorState(state, value, StateChanged.Source.Game);
|
||||
_manager.ChangeMeta(state, MetaIndex.VisorState, value, StateSource.Game);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -598,10 +598,10 @@ public class StateListener : IDisposable
|
|||
{
|
||||
// if base state changed, either overwrite the actual value if we have fixed values,
|
||||
// or overwrite the stored model state with the new one.
|
||||
if (state.Source[MetaIndex.HatState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
if (state.Sources[MetaIndex.HatState] is StateSource.Fixed or StateSource.Ipc)
|
||||
value = state.ModelData.IsHatVisible();
|
||||
else
|
||||
_manager.ChangeHatState(state, value, StateChanged.Source.Game);
|
||||
_manager.ChangeMeta(state, MetaIndex.HatState, value, StateSource.Game);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -631,10 +631,10 @@ public class StateListener : IDisposable
|
|||
{
|
||||
// if base state changed, either overwrite the actual value if we have fixed values,
|
||||
// or overwrite the stored model state with the new one.
|
||||
if (state.Source[MetaIndex.WeaponState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
if (state.Sources[MetaIndex.WeaponState] is StateSource.Fixed or StateSource.Ipc)
|
||||
value = state.ModelData.IsWeaponVisible();
|
||||
else
|
||||
_manager.ChangeWeaponState(state, value, StateChanged.Source.Game);
|
||||
_manager.ChangeMeta(state, MetaIndex.WeaponState, value, StateSource.Game);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -700,9 +700,9 @@ public class StateListener : IDisposable
|
|||
return;
|
||||
|
||||
var data = new ActorData(gameObject, _creatingIdentifier.ToName());
|
||||
_applier.ChangeHatState(data, _creatingState.ModelData.IsHatVisible());
|
||||
_applier.ChangeWeaponState(data, _creatingState.ModelData.IsWeaponVisible());
|
||||
_applier.ChangeWetness(data, _creatingState.ModelData.IsWet());
|
||||
_applier.ChangeMetaState(data, MetaIndex.HatState, _creatingState.ModelData.IsHatVisible());
|
||||
_applier.ChangeMetaState(data, MetaIndex.Wetness, _creatingState.ModelData.IsWet());
|
||||
_applier.ChangeMetaState(data, MetaIndex.WeaponState, _creatingState.ModelData.IsWeaponVisible());
|
||||
|
||||
ApplyParameters(_creatingState, drawObject);
|
||||
}
|
||||
|
|
@ -733,30 +733,30 @@ public class StateListener : IDisposable
|
|||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
{
|
||||
var newValue = data[flag];
|
||||
switch (state.Source[flag])
|
||||
switch (state.Sources[flag])
|
||||
{
|
||||
case StateChanged.Source.Game:
|
||||
case StateSource.Game:
|
||||
if (state.BaseData.Parameters.Set(flag, newValue))
|
||||
_manager.ChangeCustomizeParameter(state, flag, newValue, StateChanged.Source.Game);
|
||||
_manager.ChangeCustomizeParameter(state, flag, newValue, StateSource.Game);
|
||||
break;
|
||||
case StateChanged.Source.Manual:
|
||||
case StateSource.Manual:
|
||||
if (state.BaseData.Parameters.Set(flag, newValue))
|
||||
_manager.ChangeCustomizeParameter(state, flag, newValue, StateChanged.Source.Game);
|
||||
_manager.ChangeCustomizeParameter(state, flag, newValue, StateSource.Game);
|
||||
else if (_config.UseAdvancedParameters)
|
||||
model.ApplySingleParameterData(flag, state.ModelData.Parameters);
|
||||
break;
|
||||
case StateChanged.Source.Fixed:
|
||||
case StateSource.Fixed:
|
||||
state.BaseData.Parameters.Set(flag, newValue);
|
||||
if (_config.UseAdvancedParameters)
|
||||
model.ApplySingleParameterData(flag, state.ModelData.Parameters);
|
||||
break;
|
||||
case StateChanged.Source.Ipc:
|
||||
case StateSource.Ipc:
|
||||
state.BaseData.Parameters.Set(flag, newValue);
|
||||
model.ApplySingleParameterData(flag, state.ModelData.Parameters);
|
||||
break;
|
||||
case StateChanged.Source.Pending:
|
||||
case StateSource.Pending:
|
||||
state.BaseData.Parameters.Set(flag, newValue);
|
||||
state.Source[flag] = StateChanged.Source.Manual;
|
||||
state.Sources[flag] = StateSource.Manual;
|
||||
if (_config.UseAdvancedParameters)
|
||||
model.ApplySingleParameterData(flag, state.ModelData.Parameters);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -207,58 +207,58 @@ public class StateManager(
|
|||
#region Change Values
|
||||
|
||||
/// <summary> Turn an actor human. </summary>
|
||||
public void TurnHuman(ActorState state, StateChanged.Source source, uint key = 0)
|
||||
public void TurnHuman(ActorState state, StateSource source, uint key = 0)
|
||||
=> ChangeModelId(state, 0, CustomizeArray.Default, nint.Zero, source, key);
|
||||
|
||||
/// <summary> Turn an actor to. </summary>
|
||||
public void ChangeModelId(ActorState state, uint modelId, CustomizeArray customize, nint equipData, StateChanged.Source source,
|
||||
public void ChangeModelId(ActorState state, uint modelId, CustomizeArray customize, nint equipData, StateSource source,
|
||||
uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeModelId(state, modelId, customize, equipData, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ForceRedraw(state, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
var actors = _applier.ForceRedraw(state, source is StateSource.Manual or StateSource.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set model id in state {state.Identifier.Incognito(null)} from {old} to {modelId}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Model, source, state, actors, (old, modelId));
|
||||
}
|
||||
|
||||
/// <summary> Change a customization value. </summary>
|
||||
public void ChangeCustomize(ActorState state, CustomizeIndex idx, CustomizeValue value, StateChanged.Source source, uint key = 0)
|
||||
public void ChangeCustomize(ActorState state, CustomizeIndex idx, CustomizeValue value, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeCustomize(state, idx, value, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeCustomize(state, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
var actors = _applier.ChangeCustomize(state, source is StateSource.Manual or StateSource.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set {idx.ToDefaultName()} customizations in state {state.Identifier.Incognito(null)} from {old.Value} to {value.Value}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Customize, source, state, actors, (old, value, idx));
|
||||
}
|
||||
|
||||
/// <summary> Change an entire customization array according to flags. </summary>
|
||||
public void ChangeCustomize(ActorState state, in CustomizeArray customizeInput, CustomizeFlag apply, StateChanged.Source source,
|
||||
public void ChangeCustomize(ActorState state, in CustomizeArray customizeInput, CustomizeFlag apply, StateSource source,
|
||||
uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeHumanCustomize(state, customizeInput, apply, source, out var old, out var applied, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeCustomize(state, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
var actors = _applier.ChangeCustomize(state, source is StateSource.Manual or StateSource.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set {applied} customizations in state {state.Identifier.Incognito(null)} from {old} to {customizeInput}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.EntireCustomize, source, state, actors, (old, applied));
|
||||
}
|
||||
|
||||
/// <summary> Change a single piece of equipment without stain. </summary>
|
||||
/// <remarks> Do not use this in the same frame as ChangeStain, use <see cref="ChangeEquip(ActorState,EquipSlot,EquipItem,StainId,StateChanged.Source,uint)"/> instead. </remarks>
|
||||
public void ChangeItem(ActorState state, EquipSlot slot, EquipItem item, StateChanged.Source source, uint key = 0)
|
||||
/// <remarks> Do not use this in the same frame as ChangeStain, use <see cref="ChangeEquip(ActorState,EquipSlot,EquipItem,StainId,StateSource,uint)"/> instead. </remarks>
|
||||
public void ChangeItem(ActorState state, EquipSlot slot, EquipItem item, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeItem(state, slot, item, source, out var old, key))
|
||||
return;
|
||||
|
||||
var type = slot.ToIndex() < 10 ? StateChanged.Type.Equip : StateChanged.Type.Weapon;
|
||||
var actors = type is StateChanged.Type.Equip
|
||||
? _applier.ChangeArmor(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc)
|
||||
: _applier.ChangeWeapon(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc,
|
||||
? _applier.ChangeArmor(state, slot, source is StateSource.Manual or StateSource.Ipc)
|
||||
: _applier.ChangeWeapon(state, slot, source is StateSource.Manual or StateSource.Ipc,
|
||||
item.Type != (slot is EquipSlot.MainHand ? state.BaseData.MainhandType : state.BaseData.OffhandType));
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}). [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
|
|
@ -266,15 +266,15 @@ public class StateManager(
|
|||
}
|
||||
|
||||
/// <summary> Change a single piece of equipment including stain. </summary>
|
||||
public void ChangeEquip(ActorState state, EquipSlot slot, EquipItem item, StainId stain, StateChanged.Source source, uint key = 0)
|
||||
public void ChangeEquip(ActorState state, EquipSlot slot, EquipItem item, StainId stain, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeEquip(state, slot, item, stain, source, out var old, out var oldStain, key))
|
||||
return;
|
||||
|
||||
var type = slot.ToIndex() < 10 ? StateChanged.Type.Equip : StateChanged.Type.Weapon;
|
||||
var actors = type is StateChanged.Type.Equip
|
||||
? _applier.ChangeArmor(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc)
|
||||
: _applier.ChangeWeapon(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc,
|
||||
? _applier.ChangeArmor(state, slot, source is StateSource.Manual or StateSource.Ipc)
|
||||
: _applier.ChangeWeapon(state, slot, source is StateSource.Manual or StateSource.Ipc,
|
||||
item.Type != (slot is EquipSlot.MainHand ? state.BaseData.MainhandType : state.BaseData.OffhandType));
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}) and its stain from {oldStain.Id} to {stain.Id}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
|
|
@ -283,25 +283,25 @@ public class StateManager(
|
|||
}
|
||||
|
||||
/// <summary> Change only the stain of an equipment piece. </summary>
|
||||
/// <remarks> Do not use this in the same frame as ChangeEquip, use <see cref="ChangeEquip(ActorState,EquipSlot,EquipItem,StainId,StateChanged.Source,uint)"/> instead. </remarks>
|
||||
public void ChangeStain(ActorState state, EquipSlot slot, StainId stain, StateChanged.Source source, uint key = 0)
|
||||
/// <remarks> Do not use this in the same frame as ChangeEquip, use <see cref="ChangeEquip(ActorState,EquipSlot,EquipItem,StainId,StateSource,uint)"/> instead. </remarks>
|
||||
public void ChangeStain(ActorState state, EquipSlot slot, StainId stain, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeStain(state, slot, stain, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeStain(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
var actors = _applier.ChangeStain(state, slot, source is StateSource.Manual or StateSource.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set {slot.ToName()} stain in state {state.Identifier.Incognito(null)} from {old.Id} to {stain.Id}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Stain, source, state, actors, (old, stain, slot));
|
||||
}
|
||||
|
||||
/// <summary> Change the crest of an equipment piece. </summary>
|
||||
public void ChangeCrest(ActorState state, CrestFlag slot, bool crest, StateChanged.Source source, uint key = 0)
|
||||
public void ChangeCrest(ActorState state, CrestFlag slot, bool crest, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeCrest(state, slot, crest, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeCrests(state, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
var actors = _applier.ChangeCrests(state, source is StateSource.Manual or StateSource.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set {slot.ToLabel()} crest in state {state.Identifier.Incognito(null)} from {old} to {crest}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Crest, source, state, actors, (old, crest, slot));
|
||||
|
|
@ -309,7 +309,7 @@ public class StateManager(
|
|||
|
||||
/// <summary> Change the crest of an equipment piece. </summary>
|
||||
public void ChangeCustomizeParameter(ActorState state, CustomizeParameterFlag flag, CustomizeParameterValue value,
|
||||
StateChanged.Source source, uint key = 0)
|
||||
StateSource source, uint key = 0)
|
||||
{
|
||||
// Also apply main color to highlights when highlights is off.
|
||||
if (!state.ModelData.Customize.Highlights && flag is CustomizeParameterFlag.HairDiffuse)
|
||||
|
|
@ -319,63 +319,27 @@ public class StateManager(
|
|||
return;
|
||||
|
||||
var @new = state.ModelData.Parameters[flag];
|
||||
var actors = _applier.ChangeParameters(state, flag, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
var actors = _applier.ChangeParameters(state, flag, source is StateSource.Manual or StateSource.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set {flag} crest in state {state.Identifier.Incognito(null)} from {old} to {@new}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Parameter, source, state, actors, (old, @new, flag));
|
||||
}
|
||||
|
||||
/// <summary> Change hat visibility. </summary>
|
||||
public void ChangeHatState(ActorState state, bool value, StateChanged.Source source, uint key = 0)
|
||||
/// <summary> Change meta state. </summary>
|
||||
public void ChangeMeta(ActorState state, MetaIndex meta, bool value, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeMetaState(state, MetaIndex.HatState, value, source, out var old, key))
|
||||
if (!_editor.ChangeMetaState(state, meta, value, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeHatState(state, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
var actors = _applier.ChangeMetaState(state, meta, source is StateSource.Manual or StateSource.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set Head Gear Visibility in state {state.Identifier.Incognito(null)} from {old} to {value}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Other, source, state, actors, (old, value, MetaIndex.HatState));
|
||||
}
|
||||
|
||||
/// <summary> Change weapon visibility. </summary>
|
||||
public void ChangeWeaponState(ActorState state, bool value, StateChanged.Source source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeMetaState(state, MetaIndex.WeaponState, value, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeWeaponState(state, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set Weapon Visibility in state {state.Identifier.Incognito(null)} from {old} to {value}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Other, source, state, actors, (old, value, MetaIndex.WeaponState));
|
||||
}
|
||||
|
||||
/// <summary> Change visor state. </summary>
|
||||
public void ChangeVisorState(ActorState state, bool value, StateChanged.Source source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeMetaState(state, MetaIndex.VisorState, value, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeVisor(state, source is StateChanged.Source.Manual or StateChanged.Source.Ipc);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set Visor State in state {state.Identifier.Incognito(null)} from {old} to {value}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Other, source, state, actors, (old, value, MetaIndex.VisorState));
|
||||
}
|
||||
|
||||
/// <summary> Set GPose Wetness. </summary>
|
||||
public void ChangeWetness(ActorState state, bool value, StateChanged.Source source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeMetaState(state, MetaIndex.Wetness, value, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeWetness(state, true);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set Wetness in state {state.Identifier.Incognito(null)} from {old} to {value}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Other, state.Source[MetaIndex.Wetness], state, actors, (old, value, MetaIndex.Wetness));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void ApplyDesign(DesignBase design, ActorState state, StateChanged.Source source, uint key = 0)
|
||||
public void ApplyDesign(DesignBase design, ActorState state, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeModelId(state, design.DesignData.ModelId, design.DesignData.Customize, design.GetDesignDataRef().GetEquipmentPtr(),
|
||||
source,
|
||||
|
|
@ -383,16 +347,16 @@ public class StateManager(
|
|||
return;
|
||||
|
||||
var redraw = oldModelId != design.DesignData.ModelId || !design.DesignData.IsHuman;
|
||||
if (design.DoApplyWetness())
|
||||
if (design.DoApplyMeta(MetaIndex.Wetness))
|
||||
_editor.ChangeMetaState(state, MetaIndex.Wetness, design.DesignData.IsWet(), source, out _, key);
|
||||
|
||||
if (state.ModelData.IsHuman)
|
||||
{
|
||||
if (design.DoApplyHatVisible())
|
||||
if (design.DoApplyMeta(MetaIndex.HatState))
|
||||
_editor.ChangeMetaState(state, MetaIndex.HatState, design.DesignData.IsHatVisible(), source, out _, key);
|
||||
if (design.DoApplyWeaponVisible())
|
||||
if (design.DoApplyMeta(MetaIndex.WeaponState))
|
||||
_editor.ChangeMetaState(state, MetaIndex.WeaponState, design.DesignData.IsWeaponVisible(), source, out _, key);
|
||||
if (design.DoApplyVisorToggle())
|
||||
if (design.DoApplyMeta(MetaIndex.VisorState))
|
||||
_editor.ChangeMetaState(state, MetaIndex.VisorState, design.DesignData.IsVisorToggled(), source, out _, key);
|
||||
|
||||
var flags = state.AllowsRedraw(_condition)
|
||||
|
|
@ -407,8 +371,8 @@ public class StateManager(
|
|||
foreach (var slot in CrestExtensions.AllRelevantSet.Where(design.DoApplyCrest))
|
||||
_editor.ChangeCrest(state, slot, design.DesignData.Crest(slot), source, out _, key);
|
||||
|
||||
var paramSource = source is StateChanged.Source.Manual
|
||||
? StateChanged.Source.Pending
|
||||
var paramSource = source is StateSource.Manual
|
||||
? StateSource.Pending
|
||||
: source;
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.AllFlags.Where(design.DoApplyParameter))
|
||||
|
|
@ -418,13 +382,13 @@ public class StateManager(
|
|||
if (!state.ModelData.Customize.Highlights)
|
||||
_editor.ChangeParameter(state, CustomizeParameterFlag.HairHighlight,
|
||||
state.ModelData.Parameters[CustomizeParameterFlag.HairDiffuse],
|
||||
state.Source[CustomizeParameterFlag.HairDiffuse], out _, key);
|
||||
state.Sources[CustomizeParameterFlag.HairDiffuse], out _, key);
|
||||
}
|
||||
|
||||
var actors = ApplyAll(state, redraw, false);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Applied design to {state.Identifier.Incognito(null)}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
_event.Invoke(StateChanged.Type.Design, state.Source[MetaIndex.Wetness], state, actors, design);
|
||||
_event.Invoke(StateChanged.Type.Design, state.Sources[MetaIndex.Wetness], state, actors, design);
|
||||
return;
|
||||
|
||||
void HandleEquip(EquipSlot slot, bool applyPiece, bool applyStain)
|
||||
|
|
@ -442,7 +406,7 @@ public class StateManager(
|
|||
|
||||
private ActorData ApplyAll(ActorState state, bool redraw, bool withLock)
|
||||
{
|
||||
var actors = _applier.ChangeWetness(state, true);
|
||||
var actors = _applier.ChangeMetaState(state, MetaIndex.Wetness, true);
|
||||
if (redraw)
|
||||
{
|
||||
if (withLock)
|
||||
|
|
@ -454,7 +418,7 @@ public class StateManager(
|
|||
_applier.ChangeCustomize(actors, state.ModelData.Customize);
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
_applier.ChangeArmor(actors, slot, state.ModelData.Armor(slot), state.Source[slot, false] is not StateChanged.Source.Ipc,
|
||||
_applier.ChangeArmor(actors, slot, state.ModelData.Armor(slot), state.Sources[slot, false] is not StateSource.Ipc,
|
||||
state.ModelData.IsHatVisible());
|
||||
}
|
||||
|
||||
|
|
@ -466,9 +430,9 @@ public class StateManager(
|
|||
|
||||
if (state.ModelData.IsHuman)
|
||||
{
|
||||
_applier.ChangeHatState(actors, state.ModelData.IsHatVisible());
|
||||
_applier.ChangeWeaponState(actors, state.ModelData.IsWeaponVisible());
|
||||
_applier.ChangeVisor(actors, state.ModelData.IsVisorToggled());
|
||||
_applier.ChangeMetaState(actors, MetaIndex.HatState, state.ModelData.IsHatVisible());
|
||||
_applier.ChangeMetaState(actors, MetaIndex.WeaponState, state.ModelData.IsWeaponVisible());
|
||||
_applier.ChangeMetaState(actors, MetaIndex.VisorState, state.ModelData.IsVisorToggled());
|
||||
_applier.ChangeCrests(actors, state.ModelData.CrestVisibility);
|
||||
_applier.ChangeParameters(actors, state.OnlyChangedParameters(), state.ModelData.Parameters, state.IsLocked);
|
||||
}
|
||||
|
|
@ -476,7 +440,7 @@ public class StateManager(
|
|||
return actors;
|
||||
}
|
||||
|
||||
public void ResetState(ActorState state, StateChanged.Source source, uint key = 0)
|
||||
public void ResetState(ActorState state, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!state.Unlock(key))
|
||||
return;
|
||||
|
|
@ -488,25 +452,25 @@ public class StateManager(
|
|||
state.ModelData = state.BaseData;
|
||||
state.ModelData.SetIsWet(false);
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>())
|
||||
state.Source[index] = StateChanged.Source.Game;
|
||||
state.Sources[index] = StateSource.Game;
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.FullSlots)
|
||||
{
|
||||
state.Source[slot, true] = StateChanged.Source.Game;
|
||||
state.Source[slot, false] = StateChanged.Source.Game;
|
||||
state.Sources[slot, true] = StateSource.Game;
|
||||
state.Sources[slot, false] = StateSource.Game;
|
||||
}
|
||||
|
||||
foreach (var type in Enum.GetValues<MetaIndex>())
|
||||
state.Source[type] = StateChanged.Source.Game;
|
||||
state.Sources[type] = StateSource.Game;
|
||||
|
||||
foreach (var slot in CrestExtensions.AllRelevantSet)
|
||||
state.Source[slot] = StateChanged.Source.Game;
|
||||
state.Sources[slot] = StateSource.Game;
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
state.Source[flag] = StateChanged.Source.Game;
|
||||
state.Sources[flag] = StateSource.Game;
|
||||
|
||||
var actors = ActorData.Invalid;
|
||||
if (source is StateChanged.Source.Manual or StateChanged.Source.Ipc)
|
||||
if (source is StateSource.Manual or StateSource.Ipc)
|
||||
actors = ApplyAll(state, redraw, true);
|
||||
|
||||
Glamourer.Log.Verbose(
|
||||
|
|
@ -514,7 +478,7 @@ public class StateManager(
|
|||
_event.Invoke(StateChanged.Type.Reset, source, state, actors, null);
|
||||
}
|
||||
|
||||
public void ResetAdvancedState(ActorState state, StateChanged.Source source, uint key = 0)
|
||||
public void ResetAdvancedState(ActorState state, StateSource source, uint key = 0)
|
||||
{
|
||||
if (!state.Unlock(key) || !state.ModelData.IsHuman)
|
||||
return;
|
||||
|
|
@ -522,10 +486,10 @@ public class StateManager(
|
|||
state.ModelData.Parameters = state.BaseData.Parameters;
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
state.Source[flag] = StateChanged.Source.Game;
|
||||
state.Sources[flag] = StateSource.Game;
|
||||
|
||||
var actors = ActorData.Invalid;
|
||||
if (source is StateChanged.Source.Manual or StateChanged.Source.Ipc)
|
||||
if (source is StateSource.Manual or StateSource.Ipc)
|
||||
actors = _applier.ChangeParameters(state, CustomizeParameterExtensions.All, true);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Reset advanced customization state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
|
|
@ -537,69 +501,69 @@ public class StateManager(
|
|||
if (!state.Unlock(key))
|
||||
return;
|
||||
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>().Where(i => state.Source[i] is StateChanged.Source.Fixed))
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>().Where(i => state.Sources[i] is StateSource.Fixed))
|
||||
{
|
||||
state.Source[index] = StateChanged.Source.Game;
|
||||
state.Sources[index] = StateSource.Game;
|
||||
state.ModelData.Customize[index] = state.BaseData.Customize[index];
|
||||
}
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.FullSlots)
|
||||
{
|
||||
if (state.Source[slot, true] is StateChanged.Source.Fixed)
|
||||
if (state.Sources[slot, true] is StateSource.Fixed)
|
||||
{
|
||||
state.Source[slot, true] = StateChanged.Source.Game;
|
||||
state.Sources[slot, true] = StateSource.Game;
|
||||
state.ModelData.SetStain(slot, state.BaseData.Stain(slot));
|
||||
}
|
||||
|
||||
if (state.Source[slot, false] is StateChanged.Source.Fixed)
|
||||
if (state.Sources[slot, false] is StateSource.Fixed)
|
||||
{
|
||||
state.Source[slot, false] = StateChanged.Source.Game;
|
||||
state.Sources[slot, false] = StateSource.Game;
|
||||
state.ModelData.SetItem(slot, state.BaseData.Item(slot));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var slot in CrestExtensions.AllRelevantSet)
|
||||
{
|
||||
if (state.Source[slot] is StateChanged.Source.Fixed)
|
||||
if (state.Sources[slot] is StateSource.Fixed)
|
||||
{
|
||||
state.Source[slot] = StateChanged.Source.Game;
|
||||
state.Sources[slot] = StateSource.Game;
|
||||
state.ModelData.SetCrest(slot, state.BaseData.Crest(slot));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
{
|
||||
switch (state.Source[flag])
|
||||
switch (state.Sources[flag])
|
||||
{
|
||||
case StateChanged.Source.Fixed:
|
||||
case StateChanged.Source.Manual when !respectManualPalettes:
|
||||
state.Source[flag] = StateChanged.Source.Game;
|
||||
case StateSource.Fixed:
|
||||
case StateSource.Manual when !respectManualPalettes:
|
||||
state.Sources[flag] = StateSource.Game;
|
||||
state.ModelData.Parameters[flag] = state.BaseData.Parameters[flag];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.Source[MetaIndex.HatState] is StateChanged.Source.Fixed)
|
||||
if (state.Sources[MetaIndex.HatState] is StateSource.Fixed)
|
||||
{
|
||||
state.Source[MetaIndex.HatState] = StateChanged.Source.Game;
|
||||
state.Sources[MetaIndex.HatState] = StateSource.Game;
|
||||
state.ModelData.SetHatVisible(state.BaseData.IsHatVisible());
|
||||
}
|
||||
|
||||
if (state.Source[MetaIndex.VisorState] is StateChanged.Source.Fixed)
|
||||
if (state.Sources[MetaIndex.VisorState] is StateSource.Fixed)
|
||||
{
|
||||
state.Source[MetaIndex.VisorState] = StateChanged.Source.Game;
|
||||
state.Sources[MetaIndex.VisorState] = StateSource.Game;
|
||||
state.ModelData.SetVisor(state.BaseData.IsVisorToggled());
|
||||
}
|
||||
|
||||
if (state.Source[MetaIndex.WeaponState] is StateChanged.Source.Fixed)
|
||||
if (state.Sources[MetaIndex.WeaponState] is StateSource.Fixed)
|
||||
{
|
||||
state.Source[MetaIndex.WeaponState] = StateChanged.Source.Game;
|
||||
state.Sources[MetaIndex.WeaponState] = StateSource.Game;
|
||||
state.ModelData.SetWeaponVisible(state.BaseData.IsWeaponVisible());
|
||||
}
|
||||
|
||||
if (state.Source[MetaIndex.Wetness] is StateChanged.Source.Fixed)
|
||||
if (state.Sources[MetaIndex.Wetness] is StateSource.Fixed)
|
||||
{
|
||||
state.Source[MetaIndex.Wetness] = StateChanged.Source.Game;
|
||||
state.Sources[MetaIndex.Wetness] = StateSource.Game;
|
||||
state.ModelData.SetIsWet(state.BaseData.IsWet());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,49 +1,75 @@
|
|||
using Glamourer.GameData;
|
||||
using Penumbra.GameData.Enums;
|
||||
using static Glamourer.Events.StateChanged;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.State;
|
||||
|
||||
public readonly struct StateSource
|
||||
public enum StateSource : byte
|
||||
{
|
||||
public static readonly int Size = EquipFlagExtensions.NumEquipFlags
|
||||
+ CustomizationExtensions.NumIndices
|
||||
+ 5
|
||||
+ CrestExtensions.AllRelevantSet.Count
|
||||
+ CustomizeParameterExtensions.AllFlags.Count;
|
||||
Game,
|
||||
Manual,
|
||||
Fixed,
|
||||
Ipc,
|
||||
|
||||
// Only used for CustomizeParameters.
|
||||
Pending,
|
||||
}
|
||||
|
||||
public unsafe struct StateSources
|
||||
{
|
||||
public const int Size = (StateIndex.Size + 1) / 2;
|
||||
private fixed byte _data[Size];
|
||||
|
||||
|
||||
private readonly Source[] _data = Enumerable.Repeat(Source.Game, Size).ToArray();
|
||||
|
||||
public StateSource()
|
||||
public StateSources()
|
||||
{ }
|
||||
|
||||
public ref Source this[EquipSlot slot, bool stain]
|
||||
=> ref _data[slot.ToIndex() + (stain ? EquipFlagExtensions.NumEquipFlags / 2 : 0)];
|
||||
public StateSource this[StateIndex index]
|
||||
{
|
||||
get
|
||||
{
|
||||
var val = _data[index.Value / 2];
|
||||
return (StateSource)((index.Value & 1) == 1 ? val >> 4 : val & 0x0F);
|
||||
}
|
||||
set
|
||||
{
|
||||
var val = _data[index.Value / 2];
|
||||
if ((index.Value & 1) == 1)
|
||||
val = (byte)((val & 0x0F) | ((byte)value << 4));
|
||||
else
|
||||
val = (byte)((val & 0xF0) | (byte)value);
|
||||
_data[index.Value / 2] = val;
|
||||
}
|
||||
}
|
||||
|
||||
public ref Source this[CrestFlag slot]
|
||||
=> ref _data[EquipFlagExtensions.NumEquipFlags + CustomizationExtensions.NumIndices + 5 + slot.ToInternalIndex()];
|
||||
|
||||
public ref Source this[CustomizeIndex type]
|
||||
=> ref _data[EquipFlagExtensions.NumEquipFlags + (int)type];
|
||||
|
||||
public ref Source this[MetaIndex index]
|
||||
=> ref _data[(int)index];
|
||||
|
||||
public ref Source this[CustomizeParameterFlag flag]
|
||||
=> ref _data[
|
||||
EquipFlagExtensions.NumEquipFlags
|
||||
+ CustomizationExtensions.NumIndices
|
||||
+ 5
|
||||
+ CrestExtensions.AllRelevantSet.Count
|
||||
+ flag.ToInternalIndex()];
|
||||
public StateSource this[EquipSlot slot, bool stain]
|
||||
{
|
||||
get => this[slot.ToState(stain)];
|
||||
set => this[slot.ToState(stain)] = value;
|
||||
}
|
||||
|
||||
public void RemoveFixedDesignSources()
|
||||
{
|
||||
for (var i = 0; i < _data.Length; ++i)
|
||||
for (var i = 0; i < Size; ++i)
|
||||
{
|
||||
if (_data[i] is Source.Fixed)
|
||||
_data[i] = Source.Manual;
|
||||
var value = _data[i];
|
||||
switch (value)
|
||||
{
|
||||
case (byte)StateSource.Fixed | ((byte)StateSource.Fixed << 4):
|
||||
_data[i] = (byte)StateSource.Manual | ((byte)StateSource.Manual << 4);
|
||||
break;
|
||||
|
||||
case (byte)StateSource.Game | ((byte)StateSource.Fixed << 4):
|
||||
case (byte)StateSource.Manual | ((byte)StateSource.Fixed << 4):
|
||||
case (byte)StateSource.Ipc | ((byte)StateSource.Fixed << 4):
|
||||
case (byte)StateSource.Pending | ((byte)StateSource.Fixed << 4):
|
||||
_data[i] = (byte)((value & 0x0F) | ((byte)StateSource.Manual << 4));
|
||||
break;
|
||||
case (byte)StateSource.Fixed:
|
||||
case ((byte)StateSource.Manual << 4) | (byte)StateSource.Fixed:
|
||||
case ((byte)StateSource.Ipc << 4) | (byte)StateSource.Fixed:
|
||||
case ((byte)StateSource.Pending << 4) | (byte)StateSource.Fixed:
|
||||
_data[i] = (byte)((value & 0xF0) | (byte)StateSource.Manual);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue