mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-09 09:24:39 +01:00
Start
This commit is contained in:
parent
1a409d475a
commit
c7430e59b3
35 changed files with 1118 additions and 376 deletions
|
|
@ -11,15 +11,6 @@ namespace Glamourer.State;
|
|||
|
||||
public class ActorState
|
||||
{
|
||||
public enum MetaIndex
|
||||
{
|
||||
Wetness = EquipFlagExtensions.NumEquipFlags + CustomizationExtensions.NumIndices,
|
||||
HatState,
|
||||
VisorState,
|
||||
WeaponState,
|
||||
ModelId,
|
||||
}
|
||||
|
||||
public readonly ActorIdentifier Identifier;
|
||||
|
||||
public bool AllowsRedraw(ICondition condition)
|
||||
|
|
@ -77,47 +68,14 @@ 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>
|
||||
private readonly StateChanged.Source[] _sources = Enumerable
|
||||
.Repeat(StateChanged.Source.Game,
|
||||
EquipFlagExtensions.NumEquipFlags
|
||||
+ CustomizationExtensions.NumIndices
|
||||
+ 5
|
||||
+ CrestExtensions.AllRelevantSet.Count
|
||||
+ CustomizeParameterExtensions.AllFlags.Count).ToArray();
|
||||
public readonly StateSource Source = new();
|
||||
|
||||
internal ActorState(ActorIdentifier identifier)
|
||||
=> Identifier = identifier.CreatePermanent();
|
||||
|
||||
public ref StateChanged.Source this[EquipSlot slot, bool stain]
|
||||
=> ref _sources[slot.ToIndex() + (stain ? EquipFlagExtensions.NumEquipFlags / 2 : 0)];
|
||||
|
||||
public ref StateChanged.Source this[CrestFlag slot]
|
||||
=> ref _sources[EquipFlagExtensions.NumEquipFlags + CustomizationExtensions.NumIndices + 5 + slot.ToInternalIndex()];
|
||||
|
||||
public ref StateChanged.Source this[CustomizeIndex type]
|
||||
=> ref _sources[EquipFlagExtensions.NumEquipFlags + (int)type];
|
||||
|
||||
public ref StateChanged.Source this[MetaIndex index]
|
||||
=> ref _sources[(int)index];
|
||||
|
||||
public ref StateChanged.Source this[CustomizeParameterFlag flag]
|
||||
=> ref _sources[
|
||||
EquipFlagExtensions.NumEquipFlags
|
||||
+ CustomizationExtensions.NumIndices + 5
|
||||
+ CrestExtensions.AllRelevantSet.Count
|
||||
+ flag.ToInternalIndex()];
|
||||
|
||||
public void RemoveFixedDesignSources()
|
||||
{
|
||||
for (var i = 0; i < _sources.Length; ++i)
|
||||
{
|
||||
if (_sources[i] is StateChanged.Source.Fixed)
|
||||
_sources[i] = StateChanged.Source.Manual;
|
||||
}
|
||||
}
|
||||
|
||||
public CustomizeParameterFlag OnlyChangedParameters()
|
||||
=> CustomizeParameterExtensions.AllFlags.Where(f => this[f] is not StateChanged.Source.Game).Aggregate((CustomizeParameterFlag) 0, (a, b) => a | b);
|
||||
=> CustomizeParameterExtensions.AllFlags.Where(f => Source[f] is not StateChanged.Source.Game)
|
||||
.Aggregate((CustomizeParameterFlag)0, (a, b) => a | b);
|
||||
|
||||
public bool UpdateTerritory(ushort territory)
|
||||
{
|
||||
|
|
@ -127,4 +85,4 @@ public class ActorState
|
|||
LastTerritory = territory;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -118,7 +118,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[slot, false] is not StateChanged.Source.Ipc,
|
||||
ChangeArmor(data, slot, state.ModelData.Armor(slot), state.Source[slot, false] is not StateChanged.Source.Ipc,
|
||||
state.ModelData.IsHatVisible());
|
||||
|
||||
return data;
|
||||
|
|
|
|||
|
|
@ -61,21 +61,21 @@ public class StateEditor
|
|||
state.ModelData.SetHatVisible(true);
|
||||
state.ModelData.SetWeaponVisible(true);
|
||||
state.ModelData.SetVisor(false);
|
||||
state[ActorState.MetaIndex.ModelId] = source;
|
||||
state[ActorState.MetaIndex.HatState] = source;
|
||||
state[ActorState.MetaIndex.WeaponState] = source;
|
||||
state[ActorState.MetaIndex.VisorState] = source;
|
||||
state.Source[MetaIndex.ModelId] = source;
|
||||
state.Source[MetaIndex.HatState] = source;
|
||||
state.Source[MetaIndex.WeaponState] = source;
|
||||
state.Source[MetaIndex.VisorState] = source;
|
||||
foreach (var slot in EquipSlotExtensions.FullSlots)
|
||||
{
|
||||
state[slot, true] = source;
|
||||
state[slot, false] = source;
|
||||
state.Source[slot, true] = source;
|
||||
state.Source[slot, false] = source;
|
||||
}
|
||||
|
||||
state[CustomizeIndex.Clan] = source;
|
||||
state[CustomizeIndex.Gender] = source;
|
||||
state.Source[CustomizeIndex.Clan] = source;
|
||||
state.Source[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[index] = source;
|
||||
state.Source[index] = source;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -83,7 +83,7 @@ public class StateEditor
|
|||
return false;
|
||||
|
||||
state.ModelData.LoadNonHuman(modelId, customize, equipData);
|
||||
state[ActorState.MetaIndex.ModelId] = source;
|
||||
state.Source[MetaIndex.ModelId] = source;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -98,7 +98,7 @@ public class StateEditor
|
|||
return false;
|
||||
|
||||
state.ModelData.Customize[idx] = value;
|
||||
state[idx] = source;
|
||||
state.Source[idx] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ public class StateEditor
|
|||
foreach (var type in Enum.GetValues<CustomizeIndex>())
|
||||
{
|
||||
if (applied.HasFlag(type.ToFlag()))
|
||||
state[type] = source;
|
||||
state.Source[type] = source;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -144,12 +144,12 @@ public class StateEditor
|
|||
_gPose.AddActionOnLeave(() =>
|
||||
{
|
||||
if (old.Type == state.BaseData.Item(slot).Type)
|
||||
ChangeItem(state, slot, old, state[slot, false], out _, key);
|
||||
ChangeItem(state, slot, old, state.Source[slot, false], out _, key);
|
||||
});
|
||||
}
|
||||
|
||||
state.ModelData.SetItem(slot, item);
|
||||
state[slot, false] = source;
|
||||
state.Source[slot, false] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -174,14 +174,14 @@ public class StateEditor
|
|||
_gPose.AddActionOnLeave(() =>
|
||||
{
|
||||
if (old.Type == state.BaseData.Item(slot).Type)
|
||||
ChangeEquip(state, slot, old, oldS, state[slot, false], out _, out _, key);
|
||||
ChangeEquip(state, slot, old, oldS, state.Source[slot, false], out _, out _, key);
|
||||
});
|
||||
}
|
||||
|
||||
state.ModelData.SetItem(slot, item);
|
||||
state.ModelData.SetStain(slot, stain);
|
||||
state[slot, false] = source;
|
||||
state[slot, true] = source;
|
||||
state.Source[slot, false] = source;
|
||||
state.Source[slot, true] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ public class StateEditor
|
|||
return false;
|
||||
|
||||
state.ModelData.SetStain(slot, stain);
|
||||
state[slot, true] = source;
|
||||
state.Source[slot, true] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ public class StateEditor
|
|||
return false;
|
||||
|
||||
state.ModelData.SetCrest(slot, crest);
|
||||
state[slot] = source;
|
||||
state.Source[slot] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -218,20 +218,20 @@ public class StateEditor
|
|||
return false;
|
||||
|
||||
state.ModelData.Parameters.Set(flag, value);
|
||||
state[flag] = source;
|
||||
state.Source[flag] = source;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ChangeMetaState(ActorState state, ActorState.MetaIndex index, bool value, StateChanged.Source source, out bool oldValue,
|
||||
public bool ChangeMetaState(ActorState state, MetaIndex index, bool value, StateChanged.Source source, out bool oldValue,
|
||||
uint key = 0)
|
||||
{
|
||||
(var setter, oldValue) = index switch
|
||||
{
|
||||
ActorState.MetaIndex.Wetness => ((Func<bool, bool>)(v => state.ModelData.SetIsWet(v)), state.ModelData.IsWet()),
|
||||
ActorState.MetaIndex.HatState => ((Func<bool, bool>)(v => state.ModelData.SetHatVisible(v)), state.ModelData.IsHatVisible()),
|
||||
ActorState.MetaIndex.VisorState => ((Func<bool, bool>)(v => state.ModelData.SetVisor(v)), state.ModelData.IsVisorToggled()),
|
||||
ActorState.MetaIndex.WeaponState => ((Func<bool, bool>)(v => state.ModelData.SetWeaponVisible(v)),
|
||||
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."),
|
||||
};
|
||||
|
|
@ -240,7 +240,7 @@ public class StateEditor
|
|||
return false;
|
||||
|
||||
setter(value);
|
||||
state[index] = source;
|
||||
state.Source[index] = source;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ public class StateListener : IDisposable
|
|||
var set = _customizations.Manager.GetSet(model.Clan, model.Gender);
|
||||
foreach (var index in CustomizationExtensions.AllBasic)
|
||||
{
|
||||
if (state[index] is not StateChanged.Source.Fixed)
|
||||
if (state.Source[index] is not StateChanged.Source.Fixed)
|
||||
{
|
||||
var newValue = customize[index];
|
||||
var oldValue = model[index];
|
||||
|
|
@ -213,7 +213,7 @@ public class StateListener : IDisposable
|
|||
&& _manager.TryGetValue(identifier, out var state))
|
||||
{
|
||||
HandleEquipSlot(actor, state, slot, ref armor);
|
||||
locked = state[slot, false] is StateChanged.Source.Ipc;
|
||||
locked = state.Source[slot, false] is StateChanged.Source.Ipc;
|
||||
}
|
||||
|
||||
_funModule.ApplyFunToSlot(actor, ref armor, slot);
|
||||
|
|
@ -240,7 +240,7 @@ public class StateListener : IDisposable
|
|||
continue;
|
||||
|
||||
var changed = changedItem.Weapon(stain);
|
||||
if (current.Value == changed.Value && state[slot, false] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
if (current.Value == changed.Value && state.Source[slot, false] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
{
|
||||
_manager.ChangeItem(state, slot, currentItem, StateChanged.Source.Game);
|
||||
_manager.ChangeStain(state, slot, current.Stain, StateChanged.Source.Game);
|
||||
|
|
@ -251,7 +251,7 @@ public class StateListener : IDisposable
|
|||
_applier.ChangeWeapon(objects, slot, currentItem, stain);
|
||||
break;
|
||||
default:
|
||||
_applier.ChangeArmor(objects, slot, current.ToArmor(), state[slot, false] is not StateChanged.Source.Ipc,
|
||||
_applier.ChangeArmor(objects, slot, current.ToArmor(), state.Source[slot, false] is not StateChanged.Source.Ipc,
|
||||
state.ModelData.IsHatVisible());
|
||||
break;
|
||||
}
|
||||
|
|
@ -285,12 +285,12 @@ 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[slot, false] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
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);
|
||||
else
|
||||
apply = true;
|
||||
|
||||
if (state[slot, true] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
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);
|
||||
else
|
||||
apply = true;
|
||||
|
|
@ -384,12 +384,12 @@ public class StateListener : IDisposable
|
|||
// Update model state if not on fixed design.
|
||||
case UpdateState.Change:
|
||||
var apply = false;
|
||||
if (state[slot, false] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
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);
|
||||
else
|
||||
apply = true;
|
||||
|
||||
if (state[slot, true] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
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);
|
||||
else
|
||||
apply = true;
|
||||
|
|
@ -418,7 +418,7 @@ public class StateListener : IDisposable
|
|||
switch (UpdateBaseCrest(actor, state, slot, value))
|
||||
{
|
||||
case UpdateState.Change:
|
||||
if (state[slot] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc)
|
||||
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);
|
||||
else
|
||||
value = state.ModelData.Crest(slot);
|
||||
|
|
@ -564,7 +564,7 @@ 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[ActorState.MetaIndex.VisorState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
if (state.Source[MetaIndex.VisorState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
value = state.ModelData.IsVisorToggled();
|
||||
else
|
||||
_manager.ChangeVisorState(state, value, StateChanged.Source.Game);
|
||||
|
|
@ -597,7 +597,7 @@ 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[ActorState.MetaIndex.HatState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
if (state.Source[MetaIndex.HatState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
value = state.ModelData.IsHatVisible();
|
||||
else
|
||||
_manager.ChangeHatState(state, value, StateChanged.Source.Game);
|
||||
|
|
@ -630,7 +630,7 @@ 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[ActorState.MetaIndex.WeaponState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
if (state.Source[MetaIndex.WeaponState] is StateChanged.Source.Fixed or StateChanged.Source.Ipc)
|
||||
value = state.ModelData.IsWeaponVisible();
|
||||
else
|
||||
_manager.ChangeWeaponState(state, value, StateChanged.Source.Game);
|
||||
|
|
@ -732,7 +732,7 @@ public class StateListener : IDisposable
|
|||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
{
|
||||
var newValue = data[flag];
|
||||
switch (state[flag])
|
||||
switch (state.Source[flag])
|
||||
{
|
||||
case StateChanged.Source.Game:
|
||||
if (state.BaseData.Parameters.Set(flag, newValue))
|
||||
|
|
@ -755,7 +755,7 @@ public class StateListener : IDisposable
|
|||
break;
|
||||
case StateChanged.Source.Pending:
|
||||
state.BaseData.Parameters.Set(flag, newValue);
|
||||
state[flag] = StateChanged.Source.Manual;
|
||||
state.Source[flag] = StateChanged.Source.Manual;
|
||||
if (_config.UseAdvancedParameters)
|
||||
model.ApplySingleParameterData(flag, state.ModelData.Parameters);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -329,49 +329,49 @@ public class StateManager(
|
|||
/// <summary> Change hat visibility. </summary>
|
||||
public void ChangeHatState(ActorState state, bool value, StateChanged.Source source, uint key = 0)
|
||||
{
|
||||
if (!_editor.ChangeMetaState(state, ActorState.MetaIndex.HatState, value, source, out var old, key))
|
||||
if (!_editor.ChangeMetaState(state, MetaIndex.HatState, value, source, out var old, key))
|
||||
return;
|
||||
|
||||
var actors = _applier.ChangeHatState(state, source is StateChanged.Source.Manual or StateChanged.Source.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, ActorState.MetaIndex.HatState));
|
||||
_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, ActorState.MetaIndex.WeaponState, value, source, out var old, key))
|
||||
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, ActorState.MetaIndex.WeaponState));
|
||||
_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, ActorState.MetaIndex.VisorState, value, source, out var old, key))
|
||||
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, ActorState.MetaIndex.VisorState));
|
||||
_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, ActorState.MetaIndex.Wetness, value, source, out var old, key))
|
||||
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[ActorState.MetaIndex.Wetness], state, actors, (old, value, ActorState.MetaIndex.Wetness));
|
||||
_event.Invoke(StateChanged.Type.Other, state.Source[MetaIndex.Wetness], state, actors, (old, value, MetaIndex.Wetness));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -385,16 +385,16 @@ public class StateManager(
|
|||
|
||||
var redraw = oldModelId != design.DesignData.ModelId || !design.DesignData.IsHuman;
|
||||
if (design.DoApplyWetness())
|
||||
_editor.ChangeMetaState(state, ActorState.MetaIndex.Wetness, design.DesignData.IsWet(), source, out _, key);
|
||||
_editor.ChangeMetaState(state, MetaIndex.Wetness, design.DesignData.IsWet(), source, out _, key);
|
||||
|
||||
if (state.ModelData.IsHuman)
|
||||
{
|
||||
if (design.DoApplyHatVisible())
|
||||
_editor.ChangeMetaState(state, ActorState.MetaIndex.HatState, design.DesignData.IsHatVisible(), source, out _, key);
|
||||
_editor.ChangeMetaState(state, MetaIndex.HatState, design.DesignData.IsHatVisible(), source, out _, key);
|
||||
if (design.DoApplyWeaponVisible())
|
||||
_editor.ChangeMetaState(state, ActorState.MetaIndex.WeaponState, design.DesignData.IsWeaponVisible(), source, out _, key);
|
||||
_editor.ChangeMetaState(state, MetaIndex.WeaponState, design.DesignData.IsWeaponVisible(), source, out _, key);
|
||||
if (design.DoApplyVisorToggle())
|
||||
_editor.ChangeMetaState(state, ActorState.MetaIndex.VisorState, design.DesignData.IsVisorToggled(), source, out _, key);
|
||||
_editor.ChangeMetaState(state, MetaIndex.VisorState, design.DesignData.IsVisorToggled(), source, out _, key);
|
||||
|
||||
var flags = state.AllowsRedraw(_condition)
|
||||
? design.ApplyCustomize
|
||||
|
|
@ -419,13 +419,13 @@ public class StateManager(
|
|||
if (!state.ModelData.Customize.Highlights)
|
||||
_editor.ChangeParameter(state, CustomizeParameterFlag.HairHighlight,
|
||||
state.ModelData.Parameters[CustomizeParameterFlag.HairDiffuse],
|
||||
state[CustomizeParameterFlag.HairDiffuse], out _, key);
|
||||
state.Source[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[ActorState.MetaIndex.Wetness], state, actors, design);
|
||||
_event.Invoke(StateChanged.Type.Design, state.Source[MetaIndex.Wetness], state, actors, design);
|
||||
return;
|
||||
|
||||
void HandleEquip(EquipSlot slot, bool applyPiece, bool applyStain)
|
||||
|
|
@ -455,7 +455,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[slot, false] is not StateChanged.Source.Ipc,
|
||||
_applier.ChangeArmor(actors, slot, state.ModelData.Armor(slot), state.Source[slot, false] is not StateChanged.Source.Ipc,
|
||||
state.ModelData.IsHatVisible());
|
||||
}
|
||||
|
||||
|
|
@ -489,22 +489,22 @@ public class StateManager(
|
|||
state.ModelData = state.BaseData;
|
||||
state.ModelData.SetIsWet(false);
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>())
|
||||
state[index] = StateChanged.Source.Game;
|
||||
state.Source[index] = StateChanged.Source.Game;
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.FullSlots)
|
||||
{
|
||||
state[slot, true] = StateChanged.Source.Game;
|
||||
state[slot, false] = StateChanged.Source.Game;
|
||||
state.Source[slot, true] = StateChanged.Source.Game;
|
||||
state.Source[slot, false] = StateChanged.Source.Game;
|
||||
}
|
||||
|
||||
foreach (var type in Enum.GetValues<ActorState.MetaIndex>())
|
||||
state[type] = StateChanged.Source.Game;
|
||||
foreach (var type in Enum.GetValues<MetaIndex>())
|
||||
state.Source[type] = StateChanged.Source.Game;
|
||||
|
||||
foreach (var slot in CrestExtensions.AllRelevantSet)
|
||||
state[slot] = StateChanged.Source.Game;
|
||||
state.Source[slot] = StateChanged.Source.Game;
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
state[flag] = StateChanged.Source.Game;
|
||||
state.Source[flag] = StateChanged.Source.Game;
|
||||
|
||||
var actors = ActorData.Invalid;
|
||||
if (source is StateChanged.Source.Manual or StateChanged.Source.Ipc)
|
||||
|
|
@ -523,7 +523,7 @@ public class StateManager(
|
|||
state.ModelData.Parameters = state.BaseData.Parameters;
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
state[flag] = StateChanged.Source.Game;
|
||||
state.Source[flag] = StateChanged.Source.Game;
|
||||
|
||||
var actors = ActorData.Invalid;
|
||||
if (source is StateChanged.Source.Manual or StateChanged.Source.Ipc)
|
||||
|
|
@ -538,69 +538,69 @@ public class StateManager(
|
|||
if (!state.Unlock(key))
|
||||
return;
|
||||
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>().Where(i => state[i] is StateChanged.Source.Fixed))
|
||||
foreach (var index in Enum.GetValues<CustomizeIndex>().Where(i => state.Source[i] is StateChanged.Source.Fixed))
|
||||
{
|
||||
state[index] = StateChanged.Source.Game;
|
||||
state.Source[index] = StateChanged.Source.Game;
|
||||
state.ModelData.Customize[index] = state.BaseData.Customize[index];
|
||||
}
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.FullSlots)
|
||||
{
|
||||
if (state[slot, true] is StateChanged.Source.Fixed)
|
||||
if (state.Source[slot, true] is StateChanged.Source.Fixed)
|
||||
{
|
||||
state[slot, true] = StateChanged.Source.Game;
|
||||
state.Source[slot, true] = StateChanged.Source.Game;
|
||||
state.ModelData.SetStain(slot, state.BaseData.Stain(slot));
|
||||
}
|
||||
|
||||
if (state[slot, false] is StateChanged.Source.Fixed)
|
||||
if (state.Source[slot, false] is StateChanged.Source.Fixed)
|
||||
{
|
||||
state[slot, false] = StateChanged.Source.Game;
|
||||
state.Source[slot, false] = StateChanged.Source.Game;
|
||||
state.ModelData.SetItem(slot, state.BaseData.Item(slot));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var slot in CrestExtensions.AllRelevantSet)
|
||||
{
|
||||
if (state[slot] is StateChanged.Source.Fixed)
|
||||
if (state.Source[slot] is StateChanged.Source.Fixed)
|
||||
{
|
||||
state[slot] = StateChanged.Source.Game;
|
||||
state.Source[slot] = StateChanged.Source.Game;
|
||||
state.ModelData.SetCrest(slot, state.BaseData.Crest(slot));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
{
|
||||
switch (state[flag])
|
||||
switch (state.Source[flag])
|
||||
{
|
||||
case StateChanged.Source.Fixed:
|
||||
case StateChanged.Source.Manual when !respectManualPalettes:
|
||||
state[flag] = StateChanged.Source.Game;
|
||||
state.Source[flag] = StateChanged.Source.Game;
|
||||
state.ModelData.Parameters[flag] = state.BaseData.Parameters[flag];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state[ActorState.MetaIndex.HatState] is StateChanged.Source.Fixed)
|
||||
if (state.Source[MetaIndex.HatState] is StateChanged.Source.Fixed)
|
||||
{
|
||||
state[ActorState.MetaIndex.HatState] = StateChanged.Source.Game;
|
||||
state.Source[MetaIndex.HatState] = StateChanged.Source.Game;
|
||||
state.ModelData.SetHatVisible(state.BaseData.IsHatVisible());
|
||||
}
|
||||
|
||||
if (state[ActorState.MetaIndex.VisorState] is StateChanged.Source.Fixed)
|
||||
if (state.Source[MetaIndex.VisorState] is StateChanged.Source.Fixed)
|
||||
{
|
||||
state[ActorState.MetaIndex.VisorState] = StateChanged.Source.Game;
|
||||
state.Source[MetaIndex.VisorState] = StateChanged.Source.Game;
|
||||
state.ModelData.SetVisor(state.BaseData.IsVisorToggled());
|
||||
}
|
||||
|
||||
if (state[ActorState.MetaIndex.WeaponState] is StateChanged.Source.Fixed)
|
||||
if (state.Source[MetaIndex.WeaponState] is StateChanged.Source.Fixed)
|
||||
{
|
||||
state[ActorState.MetaIndex.WeaponState] = StateChanged.Source.Game;
|
||||
state.Source[MetaIndex.WeaponState] = StateChanged.Source.Game;
|
||||
state.ModelData.SetWeaponVisible(state.BaseData.IsWeaponVisible());
|
||||
}
|
||||
|
||||
if (state[ActorState.MetaIndex.Wetness] is StateChanged.Source.Fixed)
|
||||
if (state.Source[MetaIndex.Wetness] is StateChanged.Source.Fixed)
|
||||
{
|
||||
state[ActorState.MetaIndex.Wetness] = StateChanged.Source.Game;
|
||||
state.Source[MetaIndex.Wetness] = StateChanged.Source.Game;
|
||||
state.ModelData.SetIsWet(state.BaseData.IsWet());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
58
Glamourer/State/StateSource.cs
Normal file
58
Glamourer/State/StateSource.cs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
using Glamourer.GameData;
|
||||
using Penumbra.GameData.Enums;
|
||||
using static Glamourer.Events.StateChanged;
|
||||
|
||||
namespace Glamourer.State;
|
||||
|
||||
public enum MetaIndex
|
||||
{
|
||||
Wetness = EquipFlagExtensions.NumEquipFlags + CustomizationExtensions.NumIndices,
|
||||
HatState,
|
||||
VisorState,
|
||||
WeaponState,
|
||||
ModelId,
|
||||
}
|
||||
|
||||
public readonly struct StateSource
|
||||
{
|
||||
public static readonly int Size = EquipFlagExtensions.NumEquipFlags
|
||||
+ CustomizationExtensions.NumIndices
|
||||
+ 5
|
||||
+ CrestExtensions.AllRelevantSet.Count
|
||||
+ CustomizeParameterExtensions.AllFlags.Count;
|
||||
|
||||
|
||||
private readonly Source[] _data = Enumerable.Repeat(Source.Game, Size).ToArray();
|
||||
|
||||
public StateSource()
|
||||
{ }
|
||||
|
||||
public ref Source this[EquipSlot slot, bool stain]
|
||||
=> ref _data[slot.ToIndex() + (stain ? EquipFlagExtensions.NumEquipFlags / 2 : 0)];
|
||||
|
||||
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 void RemoveFixedDesignSources()
|
||||
{
|
||||
for (var i = 0; i < _data.Length; ++i)
|
||||
{
|
||||
if (_data[i] is Source.Fixed)
|
||||
_data[i] = Source.Manual;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue