Files
7d2dXG/Mods/0A-KFCommonUtilityLib/Scripts/Items/ModularActions/ActionModuleAlternative.cs
Nathaniel Cosford 062dfab2cd Patched
2025-05-30 01:04:40 +09:30

262 lines
12 KiB
C#

using GUI_2;
using HarmonyLib;
using KFCommonUtilityLib.Scripts.Attributes;
using KFCommonUtilityLib.Scripts.StaticManagers;
using KFCommonUtilityLib.Scripts.Utilities;
using System.Collections;
using Unity.Mathematics;
[TypeTarget(typeof(ItemActionAttack)), TypeDataTarget(typeof(AlternativeData))]
public class ActionModuleAlternative
{
internal static ItemValue InventorySetItemTemp;
[HarmonyPatch(nameof(ItemAction.StartHolding)), MethodTargetPrefix]
private bool Prefix_StartHolding(ItemActionData _data, AlternativeData __customData)
{
//__customData.Init();
int prevMode = __customData.mapping.CurMode;
__customData.UpdateUnlockState(_data.invData.itemValue);
if (prevMode != __customData.mapping.CurMode && _data.invData.holdingEntity is EntityPlayerLocal player)
{
MultiActionManager.FireToggleModeEvent(player, __customData.mapping);
}
MultiActionManager.SetMappingForEntity(_data.invData.holdingEntity.entityId, __customData.mapping);
if (_data.invData.holdingEntity is EntityPlayerLocal)
{
MultiActionManager.inputCD = math.max(0.5f, MultiActionManager.inputCD);
//ThreadManager.StartCoroutine(DelaySetExecutionIndex(_data.invData.holdingEntity, __customData.mapping));
}
return true;
}
//[MethodTargetPostfix(nameof(ItemActionAttack.StartHolding))]
//private void Postfix_StartHolding(AlternativeData __customData)
//{
// __customData.UpdateMuzzleTransformOverride();
// __customData.OverrideMuzzleTransform(__customData.mapping.CurMode);
//}
private static IEnumerator DelaySetExecutionIndex(EntityAlive player, MultiActionMapping mapping)
{
yield return null;
yield return null;
if (GameManager.Instance.GetGameStateManager().IsGameStarted())
player?.emodel?.avatarController?.UpdateInt(MultiActionUtils.ExecutingActionIndexHash, mapping.CurActionIndex);
}
[HarmonyPatch(nameof(ItemActionRanged.CancelReload)), MethodTargetPrefix]
private bool Prefix_CancelReload(ItemActionData _actionData, AlternativeData __customData)
{
if (__customData.mapping == null)
return true;
int actionIndex = __customData.mapping.CurActionIndex;
if (ConsoleCmdReloadLog.LogInfo)
Log.Out($"cancel reload {actionIndex}");
if (actionIndex == 0)
return true;
_actionData.invData.holdingEntity.inventory.holdingItem.Actions[actionIndex].CancelReload(_actionData.invData.holdingEntity.inventory.holdingItemData.actionData[actionIndex]);
return false;
}
[HarmonyPatch(nameof(ItemAction.CancelAction)), MethodTargetPrefix]
private bool Prefix_CancelAction(ItemActionData _actionData, AlternativeData __customData)
{
if (__customData.mapping == null)
return true;
int actionIndex = __customData.mapping.CurActionIndex;
if (ConsoleCmdReloadLog.LogInfo)
Log.Out($"cancel action {actionIndex}");
if (actionIndex == 0)
return true;
_actionData.invData.holdingEntity.inventory.holdingItem.Actions[actionIndex].CancelAction(_actionData.invData.holdingEntity.inventory.holdingItemData.actionData[actionIndex]);
return false;
}
[HarmonyPatch(nameof(ItemAction.IsStatChanged)), MethodTargetPrefix]
private bool Prefix_IsStatChanged(ref bool __result)
{
var mapping = MultiActionManager.GetMappingForEntity(GameManager.Instance.World.GetPrimaryPlayerId());
__result |= mapping != null && mapping.CheckDisplayMode();
return false;
}
//[MethodTargetPostfix(nameof(ItemActionAttack.StopHolding))]
//private void Postfix_StopHolding(AlternativeData __customData)
//{
// //moved to harmony patch
// //MultiActionManager.SetMappingForEntity(_data.invData.holdingEntity.entityId, null);
// __customData.mapping.SaveMeta();
//}
//todo: change to action specific property
[HarmonyPatch(nameof(ItemAction.OnModificationsChanged)), MethodTargetPostfix]
private void Postfix_OnModificationChanged(ItemActionData _data, ItemActionAttack __instance, AlternativeData __customData)
{
__instance.Properties.ParseString("ToggleActionSound", ref __customData.toggleSound);
__customData.toggleSound = _data.invData.itemValue.GetPropertyOverrideForAction("ToggleActionSound", __customData.toggleSound, __instance.ActionIndex);
__customData.mapping.toggleSound = __customData.toggleSound;
}
[HarmonyPatch(nameof(ItemAction.SetupRadial)), MethodTargetPrefix]
private bool Prefix_SetupRadial(XUiC_Radial _xuiRadialWindow, EntityPlayerLocal _epl)
{
var mapping = MultiActionManager.GetMappingForEntity(_epl.entityId);
if (mapping != null)
{
var radialContextItem = new AlternativeRadialContextItem(mapping, _xuiRadialWindow, _epl);
_xuiRadialWindow.SetCommonData(UIUtils.GetButtonIconForAction(_epl.playerInput.Reload), handleRadialCommand, radialContextItem, radialContextItem.PreSelectedIndex, false, radialValidTest);
}
return false;
}
private bool radialValidTest(XUiC_Radial _sender, XUiC_Radial.RadialContextAbs _context)
{
AlternativeRadialContextItem radialContextItem = _context as AlternativeRadialContextItem;
if (radialContextItem == null)
{
return false;
}
EntityPlayerLocal entityPlayer = _sender.xui.playerUI.entityPlayer;
return radialContextItem.mapping == MultiActionManager.GetMappingForEntity(entityPlayer.entityId) && radialContextItem.mapping.CurActionIndex == radialContextItem.ActionIndex;
}
//redirect reload call to shared meta action, which then sets ItemActionIndex animator param to its action index
//for example if action 3 share meta with action 0, then ItemActionIndex is set to 0 on reload begin.
//since event param item action data is set to the shared meta action data, all reload related passive calculation and trigger events goes there.
private void handleRadialCommand(XUiC_Radial _sender, int _commandIndex, XUiC_Radial.RadialContextAbs _context)
{
AlternativeRadialContextItem radialContextItem = _context as AlternativeRadialContextItem;
if (radialContextItem == null)
{
return;
}
EntityPlayerLocal entityPlayer = _sender.xui.playerUI.entityPlayer;
if (radialContextItem.mapping == MultiActionManager.GetMappingForEntity(entityPlayer.entityId) && radialContextItem.mapping.CurActionIndex == radialContextItem.ActionIndex)
{
entityPlayer.MinEventContext.ItemActionData = entityPlayer.inventory.holdingItemData.actionData?[radialContextItem.ActionIndex];
(entityPlayer.inventory.holdingItem.Actions?[radialContextItem.ActionIndex] as ItemActionRanged)?.SwapSelectedAmmo(entityPlayer, _commandIndex);
}
}
public class AlternativeData
{
public MultiActionMapping mapping;
public string toggleSound;
public ItemInventoryData invData;
//private bool inited = false;
private readonly bool[] unlocked = new bool[MultiActionIndice.MAX_ACTION_COUNT];
//public Transform[] altMuzzleTrans = new Transform[MultiActionIndice.MAX_ACTION_COUNT];
//public Transform[] altMuzzleTransDBarrel = new Transform[MultiActionIndice.MAX_ACTION_COUNT];
public AlternativeData(ItemActionData actionData, ItemInventoryData invData, int actionIndex, ActionModuleAlternative module)
{
this.invData = invData;
Init();
}
//public void UpdateMuzzleTransformOverride()
//{
// for (int i = 0; i < MultiActionIndice.MAX_ACTION_COUNT; i++)
// {
// int curActionIndex = mapping.indices.GetActionIndexForMode(i);
// if (curActionIndex < 0)
// {
// break;
// }
// var rangedData = invData.actionData[curActionIndex] as ItemActionRanged.ItemActionDataRanged;
// if (rangedData != null)
// {
// if (rangedData.IsDoubleBarrel)
// {
// altMuzzleTrans[i] = AnimationRiggingManager.GetTransformOverrideByName($"Muzzle_L{curActionIndex}", rangedData.invData.model) ?? rangedData.muzzle;
// altMuzzleTransDBarrel[i] = AnimationRiggingManager.GetTransformOverrideByName($"Muzzle_R{curActionIndex}", rangedData.invData.model) ?? rangedData.muzzle2;
// }
// else
// {
// altMuzzleTrans[i] = AnimationRiggingManager.GetTransformOverrideByName($"Muzzle{curActionIndex}", rangedData.invData.model) ?? rangedData.muzzle;
// }
// }
// }
//}
public void Init()
{
//if (inited)
// return;
//inited = true;
MultiActionIndice indices = MultiActionManager.GetActionIndiceForItemID(invData.item.Id);
mapping = new MultiActionMapping(this, indices, invData.holdingEntity, InventorySetItemTemp, toggleSound, invData.slotIdx, unlocked);
UpdateUnlockState(InventorySetItemTemp);
}
public void UpdateUnlockState(ItemValue itemValue)
{
//if (!inited)
// return;
unlocked[0] = true;
for (int i = 1; i < mapping.ModeCount; i++)
{
bool flag = true;
int actionIndex = mapping.indices.GetActionIndexForMode(i);
ItemAction action = itemValue.ItemClass.Actions[actionIndex];
action.Properties.ParseBool("ActionUnlocked", ref flag);
if (bool.TryParse(itemValue.GetPropertyOverride($"ActionUnlocked_{actionIndex}", flag.ToString()), out bool overrideFlag))
flag = overrideFlag;
unlocked[i] = flag;
}
//by the time we check unlock state, ItemValue in inventory slot might not be ready yet
mapping.SaveMeta(itemValue);
mapping.CurMode = mapping.CurMode;
mapping.ReadMeta(itemValue);
}
public bool IsActionUnlocked(int actionIndex)
{
int mode = mapping.indices.GetModeForAction(actionIndex);
if (mode >= MultiActionIndice.MAX_ACTION_COUNT || mode < 0)
return false;
return unlocked[mode];
}
// public void OverrideMuzzleTransform(int mode)
// {
// var rangedData = invData.actionData[mapping.indices.GetActionIndexForMode(mode)] as ItemActionRanged.ItemActionDataRanged;
// if (rangedData != null)
// {
// if (rangedData.IsDoubleBarrel)
// {
// rangedData.muzzle = altMuzzleTrans[mode];
// rangedData.muzzle2 = altMuzzleTransDBarrel[mode];
// }
// else
// {
// rangedData.muzzle = altMuzzleTrans[mode];
// }
// }
//#if DEBUG
// Log.Out($"setting muzzle transform for action {rangedData.indexInEntityOfAction} to {rangedData.muzzle.name}\n{StackTraceUtility.ExtractStackTrace()}");
//#endif
// }
}
//todo: don't setup for every mode, and use reload animation from shared action
public class AlternativeRadialContextItem : XUiC_Radial.RadialContextAbs
{
public MultiActionMapping mapping;
public int ActionIndex { get; private set; }
public int PreSelectedIndex { get; private set; }
public AlternativeRadialContextItem(MultiActionMapping mapping, XUiC_Radial _xuiRadialWindow, EntityPlayerLocal _epl)
{
this.mapping = mapping;
ActionIndex = mapping.CurActionIndex;
PreSelectedIndex = mapping.SetupRadial(_xuiRadialWindow, _epl);
}
}
}