Upload from upload_mods.ps1
This commit is contained in:
1731
Harmony/AnimationRiggingPatches.cs
Normal file
1731
Harmony/AnimationRiggingPatches.cs
Normal file
@@ -0,0 +1,1731 @@
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using KFCommonUtilityLib.Scripts.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using System.Xml.Linq;
|
||||
using UniLinq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.Animations.Rigging;
|
||||
|
||||
[HarmonyPatch]
|
||||
static class AnimationRiggingPatches
|
||||
{
|
||||
[HarmonyPatch(typeof(SDCSUtils), nameof(SDCSUtils.setupEquipmentCommon))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_setupEquipmentCommon_SDCSUtils(GameObject _rigObj, out bool __state)
|
||||
{
|
||||
__state = false;
|
||||
if (_rigObj.TryGetComponent<Animator>(out var animator))
|
||||
{
|
||||
__state = true;
|
||||
animator.UnbindAllStreamHandles();
|
||||
animator.UnbindAllSceneHandles();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(SDCSUtils), nameof(SDCSUtils.setupEquipmentCommon))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_setupEquipmentCommon_SDCSUtils(GameObject _rigObj, bool __state)
|
||||
{
|
||||
if (__state && _rigObj.TryGetComponent<Animator>(out var animator))
|
||||
{
|
||||
animator.Rebind();
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(SDCSUtils), nameof(SDCSUtils.setupRig))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_setupRig_SDCSUtils(ref RuntimeAnimatorController animController, ref GameObject _rigObj)
|
||||
{
|
||||
if (_rigObj && _rigObj.TryGetComponent<AnimationGraphBuilder>(out var builder) && builder.HasWeaponOverride)
|
||||
{
|
||||
animController = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(UMACharacterBodyAnimator), nameof(UMACharacterBodyAnimator.assignLayerWeights))]
|
||||
//[HarmonyPrefix]
|
||||
//private static bool Prefix_assignLayerWeights_UMACharacterBodyAnimator(UMACharacterBodyAnimator __instance)
|
||||
//{
|
||||
// if (__instance.Animator && __instance.Animator.TryGetComponent<AnimationGraphBuilder>(out var builder) && builder.HasWeaponOverride)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarSDCSController), nameof(AvatarSDCSController.setLayerWeights))]
|
||||
//[HarmonyPrefix]
|
||||
//private static bool Prefix_setLayerWeights_AvatarSDCSController(AvatarSDCSController __instance)
|
||||
//{
|
||||
// if (__instance.anim && __instance.anim.TryGetComponent<AnimationGraphBuilder>(out var builder) && builder.HasWeaponOverride)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.OnModificationsChanged))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnModificationChanged_ItemActionRanged(ItemActionData _data)
|
||||
{
|
||||
ItemActionRanged.ItemActionDataRanged rangedData = (ItemActionRanged.ItemActionDataRanged)_data;
|
||||
if (rangedData.IsDoubleBarrel)
|
||||
{
|
||||
rangedData.muzzle = AnimationRiggingManager.GetTransformOverrideByName(rangedData.invData.model, "Muzzle_L");
|
||||
rangedData.muzzle2 = AnimationRiggingManager.GetTransformOverrideByName(rangedData.invData.model, "Muzzle_R");
|
||||
}
|
||||
else
|
||||
{
|
||||
rangedData.muzzle = AnimationRiggingManager.GetTransformOverrideByName(rangedData.invData.model, "Muzzle");
|
||||
}
|
||||
rangedData.Laser = AnimationRiggingManager.GetTransformOverrideByName(rangedData.invData.model, "laser");
|
||||
|
||||
ItemActionLauncher.ItemActionDataLauncher launcherData = _data as ItemActionLauncher.ItemActionDataLauncher;
|
||||
if (launcherData != null)
|
||||
{
|
||||
launcherData.projectileJoint = AnimationRiggingManager.GetTransformOverrideByName(launcherData.invData.model, "ProjectileJoint");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// attachment path patch, only apply to MinEventActionSetTransformActive!
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyPatch(typeof(MinEventActionSetTransformActive), nameof(MinEventActionSetTransformActive.Execute))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Execute_MinEventActionSetTransformActive(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
var mtd_find = AccessTools.Method(typeof(GameUtils), nameof(GameUtils.FindDeepChild));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_find))
|
||||
{
|
||||
codes.RemoveAt(i);
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.Self)),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.GetAttachmentReferenceOverrideTransform))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(MinEventActionSetTransformChildrenActive), nameof(MinEventActionSetTransformChildrenActive.Execute))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Execute_MinEventActionSetTransformChildrenActive(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
var mtd_find = AccessTools.Method(typeof(GameUtils), nameof(GameUtils.FindDeepChildActive));
|
||||
var fld_trans = AccessTools.Field(typeof(MinEventActionSetTransformChildrenActive), nameof(MinEventActionSetTransformChildrenActive.transformPath));
|
||||
for (int i = 1; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_find) && codes[i - 1].LoadsField(fld_trans))
|
||||
{
|
||||
codes.RemoveAt(i);
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.Self)),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.GetAttachmentReferenceOverrideTransformActive))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(MinEventActionAddPart), nameof(MinEventActionAddPart.Execute))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Execute_MinEventActionAddPart(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
var mtd_idx = AccessTools.PropertyGetter(typeof(Inventory), nameof(Inventory.holdingItemIdx));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_idx))
|
||||
{
|
||||
codes.InsertRange(i + 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(MinEventActionAddPart),nameof(MinEventActionAddPart.partName)),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.GetAddPartTransformOverride))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(MinEventActionAttachPrefabToHeldItem), nameof(MinEventActionAttachPrefabToHeldItem.Execute))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Execute_MinEventActionAttachPrefabToHeldItem(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
var mtd_find = AccessTools.Method(typeof(GameUtils), nameof(GameUtils.FindDeepChild));
|
||||
var fld_trans = AccessTools.Field(typeof(MinEventParams), nameof(MinEventParams.Transform));
|
||||
var mtd_layer = AccessTools.Method(typeof(Utils), nameof(Utils.SetLayerRecursively));
|
||||
|
||||
var lbd_targets = generator.DeclareLocal(typeof(AnimationTargetsAbs));
|
||||
|
||||
for (int i = 1; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Stloc_0)
|
||||
{
|
||||
if (codes[i - 1].Calls(mtd_find))
|
||||
{
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.GetAddPartTransformOverride))
|
||||
});
|
||||
codes.RemoveAt(i - 1);
|
||||
i += 1;
|
||||
}
|
||||
else if (codes[i - 1].LoadsField(fld_trans))
|
||||
{
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(MinEventActionAttachPrefabToHeldItem), nameof(MinEventActionAttachPrefabToHeldItem.parent_transform)),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.GetAddPartTransformOverride))
|
||||
});
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
else if (codes[i].opcode == OpCodes.Stloc_2)
|
||||
{
|
||||
var lbl = generator.DefineLabel();
|
||||
var lbls = codes[i + 1].ExtractLabels();
|
||||
codes[i + 1].WithLabels(lbl);
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1).WithLabels(lbls),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.Transform)),
|
||||
new CodeInstruction(OpCodes.Ldnull),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(UnityEngine.Object), "op_Inequality")),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, lbl),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.Transform)),
|
||||
CodeInstruction.Call(typeof(Transform), nameof(Transform.GetComponent), new Type[0], new Type[]{ typeof(AnimationTargetsAbs)}),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_targets)
|
||||
});
|
||||
i += 9;
|
||||
}
|
||||
else if (codes[i].opcode == OpCodes.Stloc_S && ((LocalBuilder)codes[i].operand).LocalIndex == 4)
|
||||
{
|
||||
codes.RemoveAt(i - 1);
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_targets),
|
||||
new CodeInstruction(OpCodes.Ldloc_2),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingPatches), nameof(CreateOrMoveAttachment))
|
||||
});
|
||||
i += 2;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_layer))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_targets),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 4),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingPatches), nameof(CheckAttachmentRefMerge))
|
||||
});
|
||||
i += 3;
|
||||
}
|
||||
else if (codes[i].opcode == OpCodes.Stloc_S && ((LocalBuilder)codes[i].operand).LocalIndex == 5)
|
||||
{
|
||||
var lbl = generator.DefineLabel();
|
||||
var lbls = codes[i + 1].ExtractLabels();
|
||||
codes[i + 1].WithLabels(lbl);
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_3).WithLabels(lbls),
|
||||
CodeInstruction.Call(typeof(Transform), nameof(Transform.GetComponent), new Type[0], new Type[]{ typeof(IgnoreTint)}),
|
||||
new CodeInstruction(OpCodes.Ldnull),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(UnityEngine.Object), "op_Inequality")),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, lbl),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
});
|
||||
i += 6;
|
||||
}
|
||||
}
|
||||
codes.InsertRange(0, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldnull),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_targets)
|
||||
});
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static GameObject CreateOrMoveAttachment(GameObject go, AnimationTargetsAbs targets, string name)
|
||||
{
|
||||
GameObject res = null;
|
||||
if (targets)
|
||||
{
|
||||
res = targets.GetPrefab(name);
|
||||
}
|
||||
if (!res)
|
||||
{
|
||||
res = GameObject.Instantiate(go);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void CheckAttachmentRefMerge(AnimationTargetsAbs targets, GameObject attachmentReference)
|
||||
{
|
||||
if (targets)
|
||||
{
|
||||
targets.AttachPrefab(attachmentReference);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// reload logging patch
|
||||
/// </summary>
|
||||
/// <param name="stateInfo"></param>
|
||||
[HarmonyPatch(typeof(AnimatorRangedReloadState), nameof(AnimatorRangedReloadState.OnStateEnter))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnStateEnter_AnimatorRangedReloadState(AnimatorStateInfo stateInfo)
|
||||
{
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
{
|
||||
Log.Out(string.Format("ANIMATION LENGTH: length {0} speed {1} speedMultiplier {2} original length {3}", stateInfo.length, stateInfo.speed, stateInfo.speedMultiplier, stateInfo.length * stateInfo.speedMultiplier));
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.OnHoldingItemChanged))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnHoldingItemChanged_EntityAlive(EntityAlive __instance)
|
||||
{
|
||||
AnimationRiggingManager.OnHoldingItemIndexChanged(__instance as EntityPlayer);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.OnHoldingItemChanged))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnHoldingItemChanged_EntityPlayerLocal(EntityPlayerLocal __instance)
|
||||
{
|
||||
AnimationRiggingManager.OnHoldingItemIndexChanged(__instance);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.SaveAndCleanupWorld))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SaveAndCleanupWorld_GameManager()
|
||||
{
|
||||
AnimationRiggingManager.Clear();
|
||||
}
|
||||
|
||||
private static void ParseTakeOverReloadTime(XElement _node)
|
||||
{
|
||||
string itemName = _node.GetAttribute("name");
|
||||
if (string.IsNullOrEmpty(itemName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ItemClass item = ItemClass.GetItemClass(itemName);
|
||||
if (item.Properties.GetBool("TakeOverReloadTime"))
|
||||
{
|
||||
AnimationRiggingManager.AddReloadTimeTakeOverItem(item.Name);
|
||||
//Log.Out($"take over reload time: {item.Name} {item.Id}");
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClassesFromXml), nameof(ItemClassesFromXml.parseItem))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_parseItem_ItemClassesFromXml(XElement _node)
|
||||
{
|
||||
ParseTakeOverReloadTime(_node);
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.StopHolding))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_StopHolding_ItemClass(Transform _modelTransform)
|
||||
//{
|
||||
// if (_modelTransform != null && _modelTransform.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
// {
|
||||
// targets.SetEnabled(false);
|
||||
// }
|
||||
//}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.createHeldItem))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_createHeldItem_Inventory(Inventory __instance, Transform __result)
|
||||
{
|
||||
if (__result && __result.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
{
|
||||
if (GameManager.IsDedicatedServer || !(__instance.entity is EntityPlayer player))
|
||||
{
|
||||
targets.Destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player is EntityPlayerLocal localPlayer)
|
||||
{
|
||||
targets.Init(localPlayer.emodel.avatarController.GetActiveModelRoot(), localPlayer.bFirstPersonView);
|
||||
}
|
||||
else
|
||||
{
|
||||
targets.DestroyFpv();
|
||||
targets.Init(player.emodel.avatarController.GetActiveModelRoot(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.ForceHoldingItemUpdate))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_ForceHoldingItemUpdate(Inventory __instance)
|
||||
{
|
||||
if (__instance.entity is EntityPlayer)
|
||||
AnimationRiggingManager.OnClearInventorySlot(__instance, __instance.holdingItemIdx);
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ItemActionEffects))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ItemActionEffects_ItemActionRanged(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_fpv = AccessTools.Field(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.bFirstPersonView));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_fpv))
|
||||
{
|
||||
codes.InsertRange(i + 4, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, codes[i + 3].operand),
|
||||
new CodeInstruction(OpCodes.Ldarg_2),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ItemActionAttack), nameof(ItemActionAttack.particlesMuzzleFire))),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ItemActionAttack), nameof(ItemActionAttack.particlesMuzzleFireFpv))),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ItemActionAttack), nameof(ItemActionAttack.particlesMuzzleSmoke))),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ItemActionAttack), nameof(ItemActionAttack.particlesMuzzleSmokeFpv))),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.SpawnFpvParticles))),
|
||||
new CodeInstruction(OpCodes.Brtrue_S, codes[i - 5].operand)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
//FieldInfo fld_muzzle = AccessTools.Field(typeof(ItemActionRanged.ItemActionDataRanged), nameof(ItemActionRanged.ItemActionDataRanged.muzzle));
|
||||
//FieldInfo fld_muzzle2 = AccessTools.Field(typeof(ItemActionRanged.ItemActionDataRanged), nameof(ItemActionRanged.ItemActionDataRanged.muzzle2));
|
||||
//MethodInfo mtd_getmuzzle = AccessTools.Method(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.GetMuzzleOverrideFPV));
|
||||
//MethodInfo mtd_getmuzzle2 = AccessTools.Method(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.GetMuzzle2OverrideFPV));
|
||||
//for (int i = 0; i < codes.Count; i++)
|
||||
//{
|
||||
// if (codes[i].LoadsField(fld_muzzle))
|
||||
// {
|
||||
// codes.InsertRange(i + 1, new[]
|
||||
// {
|
||||
// new CodeInstruction(OpCodes.Ldloc_S, 4),
|
||||
// new CodeInstruction(OpCodes.Call, mtd_getmuzzle)
|
||||
// });
|
||||
// }
|
||||
// else if (codes[i].LoadsField(fld_muzzle2))
|
||||
// {
|
||||
// codes.InsertRange(i + 1, new[]
|
||||
// {
|
||||
// new CodeInstruction(OpCodes.Ldloc_S, 4),
|
||||
// new CodeInstruction(OpCodes.Call, mtd_getmuzzle2)
|
||||
// });
|
||||
// }
|
||||
//}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.clearSlotByIndex))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_clearSlotByIndex(Inventory __instance, int _idx)
|
||||
{
|
||||
if (__instance.entity is EntityPlayer)
|
||||
AnimationRiggingManager.OnClearInventorySlot(__instance, _idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.Update))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Update_AvatarMultiBodyController(AvatarMultiBodyController __instance)
|
||||
{
|
||||
AnimationRiggingManager.UpdatePlayerAvatar(__instance);
|
||||
if (__instance is AvatarLocalPlayerController avatarLocalPlayer)
|
||||
{
|
||||
//if ((avatarLocalPlayer.entity as EntityPlayerLocal).bFirstPersonView && !avatarLocalPlayer.entity.inventory.GetIsFinishedSwitchingHeldItem())
|
||||
//{
|
||||
// avatarLocalPlayer.UpdateInt(AvatarController.weaponHoldTypeHash, -1, false);
|
||||
// avatarLocalPlayer.UpdateBool("Holstered", false, false);
|
||||
// avatarLocalPlayer.FPSArms.Animator.Play("idle", 0, 0f);
|
||||
//}
|
||||
var mapping = MultiActionManager.GetMappingForEntity(__instance.entity.entityId);
|
||||
if (mapping != null)
|
||||
{
|
||||
avatarLocalPlayer.UpdateInt(MultiActionUtils.ExecutingActionIndexHash, mapping.CurActionIndex, true);
|
||||
}
|
||||
|
||||
if (__instance.entity.inventory?.holdingItemData?.actionData != null)
|
||||
{
|
||||
foreach (var actionData in __instance.entity.inventory.holdingItemData.actionData)
|
||||
{
|
||||
if (actionData is IModuleContainerFor<ActionModuleFireModeSelector.FireModeData> data)
|
||||
{
|
||||
avatarLocalPlayer.UpdateInt(ActionModuleFireModeSelector.FireModeParamHashes[actionData.indexInEntityOfAction], data.Instance.currentFireMode, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__instance.entity.AttachedToEntity)
|
||||
{
|
||||
__instance.SetVehicleAnimation(AvatarController.vehiclePoseHash, __instance.entity.vehiclePoseMode);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController.Update))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Update_LegacyAvatarController(LegacyAvatarController __instance)
|
||||
{
|
||||
AnimationRiggingManager.UpdatePlayerAvatar(__instance);
|
||||
if (__instance.entity && __instance.entity.AttachedToEntity)
|
||||
{
|
||||
__instance.SetVehicleAnimation(AvatarController.vehiclePoseHash, __instance.entity.vehiclePoseMode);
|
||||
}
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController.LateUpdate))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_LateUpdate_AvatarLocalPlayerController(AvatarLocalPlayerController __instance)
|
||||
//{
|
||||
// var targets = AnimationRiggingManager.GetRigTargetsFromPlayer(__instance.entity as EntityPlayer);
|
||||
// if (targets && !targets.Destroyed)
|
||||
// {
|
||||
// targets.UpdateTpvSpineRotation(__instance.entity as EntityPlayer);
|
||||
// }
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarSDCSController), nameof(AvatarSDCSController.LateUpdate))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_LateUpdate_AvatarSDCSController(AvatarSDCSController __instance)
|
||||
//{
|
||||
// var targets = AnimationRiggingManager.GetRigTargetsFromPlayer(__instance.entity as EntityPlayer);
|
||||
// if (targets && !targets.Destroyed)
|
||||
// {
|
||||
// targets.UpdateTpvSpineRotation(__instance.entity as EntityPlayer);
|
||||
// }
|
||||
//}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.StartAnimationReloading))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_StartAnimationReloding_AvatarController(AvatarMultiBodyController __instance)
|
||||
{
|
||||
__instance.Entity?.FireEvent(CustomEnums.onReloadAboutToStart);
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.StartAnimationReloading))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_StartAnimationReloading_AvatarMultibodyController(AvatarMultiBodyController __instance)
|
||||
{
|
||||
if (__instance.HeldItemTransform != null && __instance.HeldItemTransform.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
{
|
||||
EntityAlive entity = __instance.Entity;
|
||||
ItemValue holdingItemItemValue = entity.inventory.holdingItemItemValue;
|
||||
//#if DEBUG
|
||||
// float x = 1, y = 1;
|
||||
// var tags = entity.inventory.holdingItem.ItemTags;
|
||||
// var tags_prev = tags;
|
||||
// MultiActionManager.ModifyItemTags(entity.inventory.holdingItemItemValue, entity.MinEventContext.ItemActionData, ref tags);
|
||||
// entity.Progression.ModifyValue(PassiveEffects.ReloadSpeedMultiplier, ref x, ref y, tags);
|
||||
// Log.Out($"item {entity.inventory.holdingItem.Name} action index {entity.MinEventContext.ItemActionData.indexInEntityOfAction} progression base {x} perc {y} has tag {tags.Test_AnySet(FastTags.Parse("perkMachineGunner"))} \ntags prev {tags_prev} \ntags after {tags}");
|
||||
//#endif
|
||||
float reloadSpeed = EffectManager.GetValue(PassiveEffects.ReloadSpeedMultiplier, holdingItemItemValue, 1f, entity);
|
||||
float reloadSpeedRatio = EffectManager.GetValue(CustomEnums.ReloadSpeedRatioFPV2TPV, holdingItemItemValue, 1f, entity);
|
||||
|
||||
float partialReloadMultiplier = EffectManager.GetValue(CustomEnums.PartialReloadCount, holdingItemItemValue, 0, entity);
|
||||
float partialReloadRatio = 1f;
|
||||
if (partialReloadMultiplier <= 0)
|
||||
{
|
||||
partialReloadMultiplier = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int magSize = (int)EffectManager.GetValue(PassiveEffects.MagazineSize, holdingItemItemValue, ((ItemActionRanged)entity.inventory.holdingItem.Actions[MultiActionManager.GetActionIndexForEntity(entity)]).BulletsPerMagazine, entity);
|
||||
//how many partial reload is required to fill an empty mag
|
||||
partialReloadRatio = Mathf.Ceil(magSize / partialReloadMultiplier);
|
||||
//how many partial reload is required to finish this reload
|
||||
partialReloadMultiplier = Mathf.Ceil((magSize - holdingItemItemValue.Meta) / partialReloadMultiplier);
|
||||
//reload time percentage of this reload
|
||||
partialReloadRatio = partialReloadMultiplier / partialReloadRatio;
|
||||
}
|
||||
|
||||
float localMultiplier, remoteMultiplier;
|
||||
bool isFPV = entity as EntityPlayerLocal != null && (entity as EntityPlayerLocal).emodel.IsFPV;
|
||||
bool takeOverReloadTime = AnimationRiggingManager.IsReloadTimeTakeOverItem(holdingItemItemValue.type);
|
||||
|
||||
if (isFPV && !takeOverReloadTime)
|
||||
{
|
||||
localMultiplier = reloadSpeed / reloadSpeedRatio;
|
||||
}
|
||||
else if (!isFPV && takeOverReloadTime)
|
||||
{
|
||||
localMultiplier = reloadSpeed * reloadSpeedRatio / partialReloadMultiplier;
|
||||
}
|
||||
else if(isFPV && takeOverReloadTime)
|
||||
{
|
||||
localMultiplier = reloadSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
localMultiplier = reloadSpeed * partialReloadRatio;
|
||||
}
|
||||
|
||||
if (takeOverReloadTime)
|
||||
{
|
||||
remoteMultiplier = reloadSpeed * reloadSpeedRatio / partialReloadMultiplier;
|
||||
}
|
||||
else
|
||||
{
|
||||
remoteMultiplier = reloadSpeed * partialReloadRatio;
|
||||
}
|
||||
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
Log.Out($"Set reload multiplier: isFPV {isFPV}, reloadSpeed {reloadSpeed}, reloadSpeedRatio {reloadSpeedRatio}, finalMultiplier {localMultiplier}, remoteMultiplier {remoteMultiplier}, partialMultiplier {partialReloadMultiplier}, partialRatio {partialReloadRatio}");
|
||||
|
||||
__instance.UpdateFloat(AvatarController.reloadSpeedHash, localMultiplier, false);
|
||||
SetDataFloat(__instance, (AvatarController.DataTypes)AvatarController.reloadSpeedHash, remoteMultiplier, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sets float only on remote clients but not on local client.
|
||||
/// </summary>
|
||||
/// <param name="__instance"></param>
|
||||
/// <param name="_type"></param>
|
||||
/// <param name="_value"></param>
|
||||
/// <param name="_netsync"></param>
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.SetDataFloat))]
|
||||
[HarmonyReversePatch(HarmonyReversePatchType.Original)]
|
||||
private static void SetDataFloat(AvatarController __instance, AvatarController.DataTypes _type, float _value, bool _netsync = true)
|
||||
{
|
||||
IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
if (instructions == null)
|
||||
return null;
|
||||
|
||||
var codes = instructions.ToList();
|
||||
codes.RemoveRange(0, 5);
|
||||
codes[0].labels.Clear();
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsConstant(AnimParamData.ValueTypes.DataFloat))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Ldc_I4;
|
||||
codes[i].operand = (int)AnimParamData.ValueTypes.Float;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
_ = Transpiler(null);
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.StartAnimationAttack))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_StartAnimationAttack_AvatarMultiBodyController(AvatarMultiBodyController __instance)
|
||||
//{
|
||||
// if (__instance is AvatarLocalPlayerController)
|
||||
// AnimationRiggingManager.FpvWeaponFire();
|
||||
//}
|
||||
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.SetFirstPersonView))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_SetFirstPersonView_EntityPlayerLocal(EntityPlayerLocal __instance, bool _bFirstPersonView)
|
||||
{
|
||||
var targets = AnimationRiggingManager.GetRigTargetsFromPlayer(__instance);
|
||||
if (_bFirstPersonView != __instance.bFirstPersonView && targets && !targets.Destroyed && targets.IsAnimationSet)
|
||||
{
|
||||
//targets.SetEnabled(false);
|
||||
//targets.GraphBuilder.SetCurrentTarget(null);
|
||||
Log.Out($"Switch view destroy slot {__instance.inventory.holdingItemIdx}");
|
||||
targets.Destroy();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController.SwitchModelAndView))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SwitchModelAndView_AvatarLocalPlayerController(AvatarLocalPlayerController __instance, bool _bFPV)
|
||||
{
|
||||
if (_bFPV)
|
||||
{
|
||||
__instance.hasTurnRate = false;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController.SetInRightHand))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SetInRightHand_AvatarLocalPlayerController(Transform _transform, AvatarLocalPlayerController __instance)
|
||||
{
|
||||
if (_transform != null && _transform.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed && targets.ItemCurrent)
|
||||
{
|
||||
//targets.SetEnabled(true);
|
||||
targets.GraphBuilder.SetCurrentTarget(targets);
|
||||
}
|
||||
else if (__instance.PrimaryBody?.Animator && __instance.PrimaryBody.Animator.TryGetComponent<AnimationGraphBuilder>(out var builder))
|
||||
{
|
||||
builder.SetCurrentTarget(null);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController.SetInRightHand))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SetInRightHand_LegacyAvatarController(Transform _transform, LegacyAvatarController __instance)
|
||||
{
|
||||
if (_transform != null && _transform.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed && targets.ItemCurrent)
|
||||
{
|
||||
//targets.SetEnabled(true);
|
||||
targets.GraphBuilder.SetCurrentTarget(targets);
|
||||
}
|
||||
else if (__instance.anim && __instance.anim.TryGetComponent<AnimationGraphBuilder>(out var builder))
|
||||
{
|
||||
builder.SetCurrentTarget(null);
|
||||
}
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(Inventory), nameof(Inventory.setHoldingItemTransform))]
|
||||
//[HarmonyPrefix]
|
||||
//private static bool Prefix_setHoldingItemTransform_Inventory(Inventory __instance)
|
||||
//{
|
||||
// if (__instance.lastdrawnHoldingItemTransform && __instance.lastdrawnHoldingItemTransform.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
// {
|
||||
// targets.SetEnabled(false);
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
|
||||
[HarmonyPatch(typeof(vp_FPWeapon), nameof(vp_FPWeapon.Start))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Start_vp_FPWeapon(vp_FPWeapon __instance)
|
||||
{
|
||||
var player = __instance.GetComponentInParent<EntityPlayerLocal>();
|
||||
if (player && player.inventory != null)
|
||||
{
|
||||
for (int i = 0; i < player.inventory.models.Length; i++)
|
||||
{
|
||||
Transform model = player.inventory.models[i];
|
||||
if (model != null && model.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
{
|
||||
if (i == player.inventory.holdingItemIdx)
|
||||
{
|
||||
player.inventory.ForceHoldingItemUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
targets.Init(__instance.transform, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region temporary fix for arm glitch on switching weapon
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.updateHoldingItem))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_updateHoldingItem_Inventory(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_setparent = AccessTools.Method(typeof(Transform), nameof(Transform.SetParent), new[] { typeof(Transform), typeof(bool) });
|
||||
var mtd_startholding = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.StartHolding));
|
||||
var mtd_showrighthand = AccessTools.Method(typeof(Inventory), nameof(Inventory.ShowRightHand));
|
||||
var mtd_holdingchanged = AccessTools.Method(typeof(EntityAlive), nameof(EntityAlive.OnHoldingItemChanged));
|
||||
var prop_holdingitem = AccessTools.PropertyGetter(typeof(Inventory), nameof(Inventory.holdingItem));
|
||||
var fld_transform = AccessTools.Field(typeof(MinEventParams), nameof(MinEventParams.Transform));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_setparent))
|
||||
{
|
||||
codes[i - 1].opcode = OpCodes.Ldc_I4_1;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_startholding))
|
||||
{
|
||||
for (int j = i - 1; j >= 0; j--)
|
||||
{
|
||||
if (codes[j].Calls(prop_holdingitem))
|
||||
{
|
||||
for (int k = i + 1; k < codes.Count; k++)
|
||||
{
|
||||
if (codes[k].StoresField(fld_transform))
|
||||
{
|
||||
codes.InsertRange(k + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_0).WithLabels(codes[k + 1].ExtractLabels()),
|
||||
CodeInstruction.LoadField(typeof(CustomEnums), nameof(CustomEnums.onSelfHoldingItemAssemble)),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(Inventory), nameof(Inventory.entity)),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.MinEventContext)),
|
||||
CodeInstruction.Call(typeof(ItemValue), nameof(ItemValue.FireEvent)),
|
||||
});
|
||||
k += 6;
|
||||
}
|
||||
else if (codes[k].Calls(mtd_showrighthand))
|
||||
{
|
||||
codes.InsertRange(k + 1, codes.GetRange(j - 1, i - j + 2));
|
||||
codes[i + 1].WithLabels(codes[j - 1].ExtractLabels());
|
||||
codes.RemoveRange(j - 1, i - j + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
i += 6;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_holdingchanged))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(codes[i + 1].ExtractLabels()),
|
||||
CodeInstruction.Call(typeof(Inventory), nameof(Inventory.syncHeldItem))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.setHoldingItemTransform))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setHoldingItemTransform_Inventory(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
var mtd_sync = AccessTools.Method(typeof(Inventory), nameof(Inventory.syncHeldItem));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_sync))
|
||||
{
|
||||
codes[i + 1].WithLabels(codes[i - 1].ExtractLabels());
|
||||
codes.RemoveRange(i - 1, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
|
||||
//private static Coroutine delayShowWeaponCo;
|
||||
//private static IEnumerator DelayShowWeapon(Camera camera)
|
||||
//{
|
||||
// Log.Out($"Delay show weapon!");
|
||||
// camera.cullingMask &= ~(1 << 10);
|
||||
// yield return new WaitForSeconds(0.5f);
|
||||
// if (camera)
|
||||
// {
|
||||
// camera.cullingMask |= 1 << 10;
|
||||
// }
|
||||
// delayShowWeaponCo = null;
|
||||
// Log.Out($"Show weapon!");
|
||||
// yield break;
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(Inventory), nameof(Inventory.setHeldItemByIndex))]
|
||||
//[HarmonyPrefix]
|
||||
//private static bool Prefix_setHeldItemByIndex_Inventory(Inventory __instance, out bool __state)
|
||||
//{
|
||||
// __state = __instance.holdingItemData?.model && __instance.holdingItemData.model.GetComponent<RigTargets>();
|
||||
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(Inventory), nameof(Inventory.setHeldItemByIndex))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_setHeldItemByIndex_Inventory(Inventory __instance, bool __state)
|
||||
//{
|
||||
// if (__state && __instance.entity is EntityPlayerLocal player && player.bFirstPersonView && (!__instance.holdingItemData?.model || !__instance.holdingItemData.model.GetComponent<RigTargets>()))
|
||||
// {
|
||||
// if (delayShowWeaponCo != null)
|
||||
// {
|
||||
// ThreadManager.StopCoroutine(delayShowWeaponCo);
|
||||
// }
|
||||
|
||||
// if (__instance.holdingItemIdx == __instance.DUMMY_SLOT_IDX)
|
||||
// {
|
||||
// player.ShowHoldingItem(true);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// delayShowWeaponCo = ThreadManager.StartCoroutine(DelayShowWeapon(player.playerCamera));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.ShowHoldingItem))]
|
||||
//[HarmonyPrefix]
|
||||
//private static bool Prefix_ShowHoldingItem_EntityPlayerLocal(bool show)
|
||||
//{
|
||||
// if (delayShowWeaponCo != null)
|
||||
// {
|
||||
// if (show)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// ThreadManager.StopCoroutine(delayShowWeaponCo);
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
/*
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.setHoldingItemTransform))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_setHoldingItemTransform_Inventory(Transform _t, Inventory __instance)
|
||||
{
|
||||
if (_t != null && _t.TryGetComponent<RigTargets>(out var targets) && !targets.Destroyed)
|
||||
{
|
||||
targets.SetEnabled(__instance.entity.emodel.IsFPV);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.SetItem), new[] {typeof(int), typeof(ItemValue), typeof(int), typeof(bool)})]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetItem_Inventory(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
MethodInfo mtd_update = AccessTools.Method(typeof(Inventory), nameof(Inventory.updateHoldingItem));
|
||||
foreach (var code in instructions)
|
||||
{
|
||||
yield return code;
|
||||
if (code.Calls(mtd_update))
|
||||
{
|
||||
yield return new CodeInstruction(OpCodes.Ldarg_0);
|
||||
yield return new CodeInstruction(OpCodes.Ldc_I4_1);
|
||||
yield return new CodeInstruction(OpCodes.Ldc_R4, 0f);
|
||||
yield return CodeInstruction.Call(typeof(Inventory), nameof(Inventory.ShowHeldItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.ShowWeaponCamera))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_ShowWeaponCamera_EntityPlayerLocal(EntityPlayerLocal __instance, bool show)
|
||||
{
|
||||
if (__instance.bFirstPersonView)
|
||||
{
|
||||
__instance.weaponCamera.cullingMask &= ~(1 << 10);
|
||||
if (delayShowWeaponCo != null)
|
||||
{
|
||||
ThreadManager.StopCoroutine(delayShowWeaponCo);
|
||||
}
|
||||
if (show)
|
||||
{
|
||||
delayShowWeaponCo = ThreadManager.StartCoroutine(DelayShowWeapon(__instance.weaponCamera));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
#endregion
|
||||
|
||||
[HarmonyPatch(typeof(World), nameof(World.SpawnEntityInWorld))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_SpawnEntityInWorld_World(Entity _entity)
|
||||
{
|
||||
if (_entity is EntityItem _entityItem)
|
||||
{
|
||||
var targets = _entityItem.GetComponentInChildren<AnimationTargetsAbs>(true);
|
||||
if (targets && !targets.Destroyed)
|
||||
{
|
||||
targets.Destroy();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(World), nameof(World.SpawnEntityInWorld))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SpawnEntityInWorld_World(Entity _entity)
|
||||
{
|
||||
if (_entity is EntityPlayer player && !(_entity is EntityPlayerLocal) && player.inventory != null)
|
||||
{
|
||||
foreach (var model in player.inventory.models)
|
||||
{
|
||||
if (model && model.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
{
|
||||
targets.DestroyFpv();
|
||||
targets.Init(player.emodel.avatarController.GetActiveModelRoot(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityItem), nameof(EntityItem.createMesh))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_createMesh_EntityItem(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
codes[codes.Count - 1].WithLabels(codes[codes.Count - 11].labels);
|
||||
codes.RemoveRange(codes.Count - 11, 10);
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityItem), nameof(EntityItem.createMesh))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_createMesh_EntityItem(EntityItem __instance)
|
||||
{
|
||||
if (__instance.itemTransform)
|
||||
{
|
||||
__instance.itemTransform.tag = "Item";
|
||||
if (__instance.itemTransform.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
{
|
||||
targets.Destroy();
|
||||
}
|
||||
}
|
||||
__instance.meshRenderers = __instance.itemTransform.GetComponentsInChildren<Renderer>(true);
|
||||
__instance.VisiblityCheck(0, false);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EModelBase), nameof(EModelBase.SwitchModelAndView))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SwitchModelAndView_EModelBase(EModelBase __instance)
|
||||
{
|
||||
if (__instance.entity is EntityPlayerLocal player && player.inventory != null)
|
||||
{
|
||||
foreach (var model in player.inventory.models)
|
||||
{
|
||||
if (model && model.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
{
|
||||
targets.Init(player.emodel.avatarController.GetActiveModelRoot(), player.bFirstPersonView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.Detach))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Detach_EntityAlive(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_inv = AccessTools.Field(typeof(EntityAlive), nameof(EntityAlive.inventory));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].StoresField(fld_inv))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingPatches), nameof(AnimationRiggingPatches.DetachInitInventory))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static void DetachInitInventory(EntityAlive __instance)
|
||||
{
|
||||
if (!(__instance is EntityPlayer player))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (__instance.inventory != null)
|
||||
{
|
||||
foreach (var model in __instance.inventory.models)
|
||||
{
|
||||
if (model && model.TryGetComponent<AnimationTargetsAbs>(out var targets) && !targets.Destroyed)
|
||||
{
|
||||
targets.Init(__instance.emodel.avatarController.GetActiveModelRoot(), player is EntityPlayerLocal localPlayer ? localPlayer.bFirstPersonView : false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(SDCSUtils), nameof(SDCSUtils.cleanupEquipment))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_cleanupEquipment_SDCSUtils(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_removeat = AccessTools.Method(typeof(List<RigLayer>), nameof(List<RigLayer>.RemoveAt));
|
||||
var mtd_destroy = AccessTools.Method(typeof(GameUtils), nameof(GameUtils.DestroyAllChildrenBut), new[] {typeof(Transform), typeof(List<string>)});
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_removeat))
|
||||
{
|
||||
codes.InsertRange(i - 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_2),
|
||||
new CodeInstruction(OpCodes.Ldloc_3),
|
||||
CodeInstruction.Call(typeof(List<RigLayer>), "get_Item"),
|
||||
CodeInstruction.Call(typeof(RigLayer), "get_name"),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.ShouldExcludeRig)),
|
||||
new CodeInstruction(OpCodes.Brtrue_S, codes[i - 3].operand)
|
||||
});
|
||||
i += 6;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_destroy))
|
||||
{
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Dup),
|
||||
CodeInstruction.Call(typeof(AnimationRiggingManager), nameof(AnimationRiggingManager.GetExcludeRigs)),
|
||||
CodeInstruction.Call(typeof(List<string>), nameof(List<string>.AddRange)),
|
||||
});
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.SwapSelectedAmmo))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_SwapSelectedAmmo_ItemActionRanged(ItemActionRanged __instance, EntityAlive _entity, int _ammoIndex)
|
||||
{
|
||||
if (_ammoIndex == (int)_entity.inventory.holdingItemItemValue.SelectedAmmoTypeIndex && __instance is IModuleContainerFor<ActionModuleInspectable> inspectable && _entity is EntityPlayerLocal player)
|
||||
{
|
||||
ItemActionRanged.ItemActionDataRanged _actionData = _entity.inventory.holdingItemData.actionData[__instance.ActionIndex] as ItemActionRanged.ItemActionDataRanged;
|
||||
if (!_entity.MovementRunning && !_entity.AimingGun && !player.bLerpCameraFlag && _actionData != null && !_entity.inventory.holdingItem.IsActionRunning(_entity.inventory.holdingItemData) && !__instance.CanReload(_actionData) && (_entity.inventory.holdingItemItemValue.Meta > 0 || inspectable.Instance.allowEmptyInspect))
|
||||
{
|
||||
_entity.emodel.avatarController._setTrigger("weaponInspect", true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ExecuteAction))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_ExecuteAction_ItemActionRanged(ItemActionRanged __instance, ItemActionData _actionData)
|
||||
{
|
||||
if (_actionData is ItemActionRanged.ItemActionDataRanged rangedData)
|
||||
{
|
||||
int burstCount = __instance.GetBurstCount(_actionData);
|
||||
_actionData.invData.holdingEntity.emodel.avatarController._setBool("TriggerPulled", rangedData.bPressed && rangedData.curBurstCount < burstCount, true);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.LateInitAll))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_LateInitAll_ItemClass()
|
||||
{
|
||||
AnimationRiggingManager.ParseItemIDs();
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Animator), nameof(Animator.Rebind), new Type[0])]
|
||||
[HarmonyReversePatch(HarmonyReversePatchType.Original)]
|
||||
public static void RebindNoDefault(this Animator __instance)
|
||||
{
|
||||
IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
if (instructions == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
foreach (var ins in instructions)
|
||||
{
|
||||
if (ins.opcode == OpCodes.Ldc_I4_1)
|
||||
{
|
||||
yield return new CodeInstruction(OpCodes.Ldc_I4_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return ins;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = Transpiler(null);
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(ItemActionDynamic), nameof(ItemActionDynamic.GetExecuteActionGrazeTarget))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_Test2(WorldRayHitInfo[] __result)
|
||||
//{
|
||||
// Log.Out($"World ray info count: {__result.Length}");
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(ItemActionDynamic), nameof(ItemActionDynamic.hitTarget))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_hittest(ItemActionData _actionData, WorldRayHitInfo hitInfo, bool _isGrazingHit = false)
|
||||
//{
|
||||
// Log.Out($"HIT TARGET! IsGrazing: {_isGrazingHit}\n{StackTraceUtility.ExtractStackTrace()}");
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController._setTrigger))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_AvatarLocalPlayerController_SetTrigger(int _pid, AvatarLocalPlayerController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.SetTrigger(_pid, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController._resetTrigger))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_AvatarLocalPlayerController_ResetTrigger(int _pid, AvatarLocalPlayerController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.ResetTrigger(_pid, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController._setFloat))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_AvatarLocalPlayerController_SetFloat(int _pid, float _value, AvatarLocalPlayerController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.SetFloat(_pid, _value, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController._setBool))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_AvatarLocalPlayerController_SetBool(int _pid, bool _value, AvatarLocalPlayerController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.SetBool(_pid, _value, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController._setInt))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_AvatarLocalPlayerController_SetInt(int _pid, int _value, AvatarLocalPlayerController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.SetInt(_pid, _value, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController._setTrigger))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_LegacyAvatarController_SetTrigger(int _propertyHash, LegacyAvatarController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.SetTrigger(_propertyHash, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController._resetTrigger))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_LegacyAvatarController_ResetTrigger(int _propertyHash, LegacyAvatarController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.ResetTrigger(_propertyHash, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController._setFloat))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_LegacyAvatarController_SetFloat(int _propertyHash, float _value, LegacyAvatarController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.SetFloat(_propertyHash, _value, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController._setBool))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_LegacyAvatarController_SetBool(int _propertyHash, bool _value, LegacyAvatarController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.SetBool(_propertyHash, _value, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController._setInt))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_LegacyAvatarController_SetInt(int _propertyHash, int _value, LegacyAvatarController __instance)
|
||||
//{
|
||||
// AnimationRiggingManager.SetInt(_propertyHash, _value, __instance.entity as EntityPlayer);
|
||||
//}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarLocalPlayerController), nameof(AvatarLocalPlayerController._resetTrigger), typeof(int), typeof(bool))]
|
||||
[HarmonyReversePatch(HarmonyReversePatchType.Original)]
|
||||
public static void VanillaResetTrigger(AvatarLocalPlayerController __instance, int _pid, bool _netsync = true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.TryGetTrigger), new[] { typeof(int), typeof(bool) }, new[] { ArgumentType.Normal, ArgumentType.Out })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_TryGetTrigger_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.TryGetBool), new[] { typeof(int), typeof(bool) }, new[] { ArgumentType.Normal, ArgumentType.Out })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_TryGetBool_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.TryGetInt), new[] { typeof(int), typeof(int) }, new[] { ArgumentType.Normal, ArgumentType.Out })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_TryGetInt_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedInt)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.TryGetFloat), new[] { typeof(int), typeof(float) }, new[] { ArgumentType.Normal, ArgumentType.Out })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_TryGetFloat_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetFloat), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedFloat)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.TryGetTrigger), new[] { typeof(int), typeof(bool) }, new[] { ArgumentType.Normal, ArgumentType.Out })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_TryGetTrigger_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.TryGetBool), new[] { typeof(int), typeof(bool) }, new[] { ArgumentType.Normal, ArgumentType.Out })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_TryGetBool_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.TryGetInt), new[] { typeof(int), typeof(int) }, new[] { ArgumentType.Normal, ArgumentType.Out })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_TryGetInt_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedInt)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.TryGetFloat), new[] { typeof(int), typeof(float) }, new[] { ArgumentType.Normal, ArgumentType.Out })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_TryGetFloat_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetFloat), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedFloat)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController._setBool), new[] { typeof(int), typeof(bool), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setBool_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetBool), new[] { typeof(int), typeof(bool) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedBool)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController._setTrigger), new[] { typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setTrigger_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetTrigger), new[] { typeof(int)}),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedTrigger)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController._resetTrigger), new[] { typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_resetTrigger_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.ResetTrigger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.ResetWrappedTrigger)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController._setInt), new[] { typeof(int), typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setInt_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedInt)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetInteger), new[] { typeof(int), typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedInt)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController._setFloat), new[] { typeof(int), typeof(float), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setFloat_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetFloat), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedFloat)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetFloat), new[] { typeof(int), typeof(float) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedFloat)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarCharacterController), nameof(AvatarCharacterController._setBool), new[] { typeof(int), typeof(bool), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setBool_AvatarCharacterController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetBool), new[] { typeof(int), typeof(bool) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedBool)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarCharacterController), nameof(AvatarCharacterController._setTrigger), new[] { typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setTrigger_AvatarCharacterController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetTrigger), new[] { typeof(int)}),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedTrigger)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarCharacterController), nameof(AvatarCharacterController._resetTrigger), new[] { typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_resetTrigger_AvatarCharacterController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.ResetTrigger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.ResetWrappedTrigger)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarCharacterController), nameof(AvatarCharacterController._setInt), new[] { typeof(int), typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setInt_AvatarCharacterController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetInteger), new[] { typeof(int), typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedInt)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarCharacterController), nameof(AvatarCharacterController._setFloat), new[] { typeof(int), typeof(float), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setFloat_AvatarCharacterController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetFloat), new[] { typeof(int), typeof(float) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedFloat)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController._setBool), new[] { typeof(int), typeof(bool), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setBool_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetBool), new[] { typeof(int), typeof(bool) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedBool)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController._setTrigger), new[] { typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setTrigger_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetTrigger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedTrigger)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController._resetTrigger), new[] { typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_resetTrigger_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.ResetTrigger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.ResetWrappedTrigger)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController._setInt), new[] { typeof(int), typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setInt_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedInt)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetInteger), new[] { typeof(int), typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedInt)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController._setFloat), new[] { typeof(int), typeof(float), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setFloat_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetFloat), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedFloat)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetFloat), new[] { typeof(int), typeof(float) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedFloat)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.GetParameterName))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_GetParameterName_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.PropertyGetter(typeof(Animator), nameof(Animator.parameters)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedParameters)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.SyncAnimParameters))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SyncAnimParameters_AvatarController(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.MethodReplacer(
|
||||
AccessTools.PropertyGetter(typeof(Animator), nameof(Animator.parameters)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedParameters)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedInt)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetFloat), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedFloat)))
|
||||
.ToList();
|
||||
|
||||
//var lbd_wrapper = generator.DeclareLocal(typeof(IAnimatorWrapper));
|
||||
|
||||
//var fld_anim = AccessTools.Field(typeof(AvatarController), nameof(AvatarController.anim));
|
||||
|
||||
//for (int i = 1; i < codes.Count; i++)
|
||||
//{
|
||||
// if (codes[i].opcode == OpCodes.Stloc_0)
|
||||
// {
|
||||
// codes.InsertRange(i + 1, new[]
|
||||
// {
|
||||
// new CodeInstruction(OpCodes.Ldarg_0),
|
||||
// CodeInstruction.LoadField(typeof(AvatarController), nameof(AvatarController.anim)),
|
||||
// CodeInstruction.Call(typeof(KFExtensions), nameof(KFExtensions.GetAnimatorWrapper)),
|
||||
// new CodeInstruction(OpCodes.Stloc_S, lbd_wrapper)
|
||||
// });
|
||||
// i += 4;
|
||||
// }
|
||||
// else if (codes[i].opcode == OpCodes.Ldloc_3 && codes[i - 1].LoadsField(fld_anim))
|
||||
// {
|
||||
// codes.Insert(i - 2, new CodeInstruction(OpCodes.Ldloc_S, lbd_wrapper).WithLabels(codes[i - 2].ExtractLabels()));
|
||||
// codes.RemoveRange(i - 1, 2);
|
||||
// i--;
|
||||
// }
|
||||
//}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarSDCSController), nameof(AvatarSDCSController.LateUpdate))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_LateUpdate_AvatarSDCSController(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var mtd_getbool = AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(int) });
|
||||
var mtd_getint = AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(int) });
|
||||
var mtd_getfloat = AccessTools.Method(typeof(Animator), nameof(Animator.GetFloat), new[] { typeof(int) });
|
||||
var mtd_istransition = AccessTools.Method(typeof(Animator),nameof(Animator.IsInTransition), new[] { typeof(int) });
|
||||
var mtd_updatespine = AccessTools.Method(typeof(LegacyAvatarController), nameof(LegacyAvatarController.updateSpineRotation));
|
||||
var fld_reload = AccessTools.Field(typeof(AvatarController), nameof(AvatarController.reloadHash));
|
||||
var mtd_getvanillabool = AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool));
|
||||
var mtd_getvanillaint = AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedInt));
|
||||
var mtd_getvanillafloat = AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedFloat));
|
||||
var mtd_isvanillatransition = AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.IsVanillaInTransition));
|
||||
var codes = instructions.Manipulator(ins => ins.opcode == OpCodes.Ldstr, ins =>
|
||||
{
|
||||
switch (ins.operand)
|
||||
{
|
||||
case "Reload":
|
||||
ins.opcode = OpCodes.Ldsfld;
|
||||
ins.operand = fld_reload;
|
||||
break;
|
||||
}
|
||||
}).MethodReplacer(AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(string) }), mtd_getbool)
|
||||
.MethodReplacer(AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(string) }), mtd_getint)
|
||||
.MethodReplacer(AccessTools.Method(typeof(Animator), nameof(Animator.GetFloat), new[] { typeof(string) }), mtd_getfloat)
|
||||
.MethodReplacer(AccessTools.Method(typeof(Animator), nameof(Animator.SetBool), new[] { typeof(string), typeof(bool) }), AccessTools.Method(typeof(Animator), nameof(Animator.SetBool), new[] { typeof(int), typeof(bool) }))
|
||||
.MethodReplacer(mtd_getbool, mtd_getvanillabool)
|
||||
.MethodReplacer(mtd_getint, mtd_getvanillaint)
|
||||
.MethodReplacer(mtd_getfloat, mtd_getvanillafloat)
|
||||
.MethodReplacer(mtd_istransition, mtd_isvanillatransition)
|
||||
.ToList();
|
||||
|
||||
//var lbd_wrapper = generator.DeclareLocal(typeof(IAnimatorWrapper));
|
||||
|
||||
//for (var i = 0; i < codes.Count; i++)
|
||||
//{
|
||||
// if (codes[i].Calls(mtd_updatespine))
|
||||
// {
|
||||
// codes.InsertRange(i + 1, new[]
|
||||
// {
|
||||
// new CodeInstruction(OpCodes.Ldarg_0),
|
||||
// CodeInstruction.LoadField(typeof(AvatarController), nameof(AvatarController.anim)),
|
||||
// CodeInstruction.Call(typeof(KFExtensions), nameof(KFExtensions.GetItemAnimatorWrapper)),
|
||||
// new CodeInstruction(OpCodes.Stloc_S, lbd_wrapper)
|
||||
// });
|
||||
// i += 4;
|
||||
// }
|
||||
// else if (codes[i].Calls(mtd_getvanillabool) || codes[i].Calls(mtd_getvanillafloat) || codes[i].Calls(mtd_getvanillaint) || codes[i].Calls(mtd_isvanillatransition))
|
||||
// {
|
||||
// codes.Insert(i - 3, new CodeInstruction(OpCodes.Ldloc_S, lbd_wrapper).WithLabels(codes[i - 3].ExtractLabels()));
|
||||
// codes.RemoveRange(i - 2, 2);
|
||||
// i--;
|
||||
// }
|
||||
//}
|
||||
//foreach (var code in codes)
|
||||
//{
|
||||
// Log.Out(code.ToString());
|
||||
//}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarSDCSController), nameof(AvatarSDCSController.updateLayerStateInfo))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_updateLayerStateInfo_AvatarSDCSController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetCurrentAnimatorStateInfo)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetCurrentVanillaStateInfo)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarUMAController), nameof(AvatarUMAController.updateLayerStateInfo))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_updateLayerStateInfo_AvatarUMAController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetCurrentAnimatorStateInfo)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetCurrentVanillaStateInfo)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController.updateLayerStateInfo))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_updateLayerStateInfo_LegacyAvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetCurrentAnimatorStateInfo)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetCurrentVanillaStateInfo)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarSDCSController), nameof(AvatarSDCSController.setLayerWeights))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setLayerWeights_AvatarSDCSController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
int id = Animator.StringToHash("MinibikeIdle");
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetLayerWeight)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetVanillaLayerWeight)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.IsInTransition)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.IsVanillaInTransition)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetBool), new[] { typeof(string) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedBool)))
|
||||
.Manipulator(ins => ins.opcode == OpCodes.Ldstr, ins => { ins.opcode = OpCodes.Ldc_I4; ins.operand = id; });
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(LegacyAvatarController), nameof(LegacyAvatarController.setLayerWeights))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setLayerWeights_LegacyAvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetLayerWeight)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetVanillaLayerWeight)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarUMAController), nameof(AvatarUMAController.setLayerWeights))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_setLayerWeights_AvatarUMAController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetLayerWeight)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetVanillaLayerWeight)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedInt)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.IsInTransition)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.IsVanillaInTransition)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(UMACharacterBodyAnimator), nameof(UMACharacterBodyAnimator.assignLayerWeights))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_assignLayerWeights_UMACharacterBodyAnimator(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetLayerWeight)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetVanillaLayerWeight)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.GetInteger), new[] { typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.GetWrappedInt)))
|
||||
.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.IsInTransition)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.IsVanillaInTransition)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.Update))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Update_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetLayerWeight)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetVanillaLayerWeight)));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarController), nameof(AvatarController.InitHitDuration))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_InitHitDuration_AvatarController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetLayerWeight)),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetVanillaLayerWeight)));
|
||||
}
|
||||
|
||||
private static int drunkHash = Animator.StringToHash("drunk");
|
||||
[HarmonyPatch(typeof(FirstPersonAnimator), nameof(FirstPersonAnimator.SetDrunk))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetDrunk_FirstPersonAnimator(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetFloat), new[] { typeof(string), typeof(float) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedFloat)))
|
||||
.Manipulator(ins => ins.LoadsConstant("drunk"),
|
||||
ins =>
|
||||
{
|
||||
ins.opcode = OpCodes.Ldsfld;
|
||||
ins.operand = AccessTools.Field(typeof(AnimationRiggingPatches), nameof(AnimationRiggingPatches.drunkHash));
|
||||
});
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.SetVehicleAnimation))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetVehicleAnimation_AvatarMultiBodyController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
return instructions.MethodReplacer(
|
||||
AccessTools.Method(typeof(Animator), nameof(Animator.SetInteger), new[] { typeof(string), typeof(int) }),
|
||||
AccessTools.Method(typeof(KFExtensions), nameof(KFExtensions.SetWrappedInt)));
|
||||
}
|
||||
//BodyAnimator.LateUpdate
|
||||
//UMACharacterBodyAnimator.LateUpdate
|
||||
//BodyAnimator.cacheLayerStateInfo
|
||||
//UMACharacterBodyAnimator.cacheLayerStateInfo
|
||||
//not used
|
||||
}
|
||||
51
Harmony/BackgroundInventoryUpdatePatch.cs
Normal file
51
Harmony/BackgroundInventoryUpdatePatch.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public class BackgroundInventoryUpdatePatch
|
||||
{
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.clearSlotByIndex))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_clearSlotByIndex_Inventory(Inventory __instance, int _idx)
|
||||
{
|
||||
BackgroundInventoryUpdateManager.UnregisterUpdater(__instance.entity, _idx);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.OnEntityDeath))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnEntityDeath_EntityAlive(EntityAlive __instance)
|
||||
{
|
||||
BackgroundInventoryUpdateManager.UnregisterUpdater(__instance);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.OnUpdate))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnUpdate_Inventory(Inventory __instance)
|
||||
{
|
||||
BackgroundInventoryUpdateManager.Update(__instance.entity);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.SaveAndCleanupWorld))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SaveAndCleanupWorld_GameManager()
|
||||
{
|
||||
BackgroundInventoryUpdateManager.Cleanup();
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.AttachToEntity))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_AttachToEntity_EntityAlive(EntityAlive __instance)
|
||||
{
|
||||
BackgroundInventoryUpdateManager.DisableUpdater(__instance);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.Detach))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Detach_EntityAlive(EntityAlive __instance)
|
||||
{
|
||||
BackgroundInventoryUpdateManager.EnableUpdater(__instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
174
Harmony/DamagePatches.cs
Normal file
174
Harmony/DamagePatches.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using HarmonyLib;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using UniLinq;
|
||||
using UnityEngine;
|
||||
|
||||
[HarmonyPatch]
|
||||
public static class DamagePatches
|
||||
{
|
||||
[HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.damageEntityLocal))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_damageEntityLocal_EntityAlive(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_calc = AccessTools.Method(typeof(Equipment), nameof(Equipment.CalcDamage));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_calc))
|
||||
{
|
||||
codes[i] = CodeInstruction.Call(typeof(DamagePatches), nameof(DamagePatches.CalcEquipmentDamage));
|
||||
codes.RemoveRange(i - 12, 12);
|
||||
codes.InsertRange(i - 12, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.MinEventContext)),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.Other))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionAttack), nameof(ItemActionAttack.Hit))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Hit_ItemActionAttack(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
var mtd_getdamagegroup = AccessTools.Method(typeof(DamageSource), nameof(DamageSource.GetEntityDamageEquipmentSlotGroup));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_getdamagegroup))
|
||||
{
|
||||
codes.InsertRange(i + 3, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, codes[i - 2].operand),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, codes[i - 1].operand),
|
||||
CodeInstruction.Call(typeof(DamageSource), nameof(DamageSource.GetEntityDamageBodyPart)),
|
||||
CodeInstruction.Call(typeof(DamagePatches), nameof(DamagePatches.GetBodyPartTags)),
|
||||
CodeInstruction.Call(typeof(FastTags<TagGroup.Global>), "op_BitwiseOr")
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static void CalcEquipmentDamage(Equipment equipment, ref DamageResponse damageResponse, EntityAlive attacker)
|
||||
{
|
||||
damageResponse.ArmorDamage = damageResponse.Strength;
|
||||
if (damageResponse.Source.DamageTypeTag.Test_AnySet(Equipment.physicalDamageTypes))
|
||||
{
|
||||
if (damageResponse.Strength > 0)
|
||||
{
|
||||
float totalPhysicalArmorResistPercent = GetTotalPhysicalArmorResistPercent(equipment, in damageResponse, attacker) * .01f;
|
||||
damageResponse.ArmorDamage = Utils.FastMax((totalPhysicalArmorResistPercent > 0f) ? 1 : 0, Mathf.RoundToInt((float)damageResponse.Strength * totalPhysicalArmorResistPercent));
|
||||
damageResponse.Strength -= damageResponse.ArmorDamage;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
damageResponse.Strength = Mathf.RoundToInt(Utils.FastMax(0f, (float)damageResponse.Strength * (1f - EffectManager.GetValue(PassiveEffects.ElementalDamageResist, null, 0f, equipment.m_entity, null, damageResponse.Source.DamageTypeTag) * .01f)));
|
||||
damageResponse.ArmorDamage = Mathf.RoundToInt((float)Utils.FastMax(0, damageResponse.ArmorDamage - damageResponse.Strength));
|
||||
}
|
||||
}
|
||||
|
||||
private static float GetTotalPhysicalArmorResistPercent(Equipment equipment, in DamageResponse damageResponse, EntityAlive attacker)
|
||||
{
|
||||
if (!equipment?.m_entity)
|
||||
return 0f;
|
||||
FastTags<TagGroup.Global> bodyPartTags = GetBodyPartTags(damageResponse.HitBodyPart);
|
||||
float resist = EffectManager.GetValue(PassiveEffects.PhysicalDamageResist, null, 0f, equipment.m_entity, null, Equipment.coreDamageResist | bodyPartTags);
|
||||
if (attacker)
|
||||
{
|
||||
attacker.MinEventContext.Other = equipment.m_entity;
|
||||
attacker.MinEventContext.ItemValue = damageResponse.Source.AttackingItem ?? ItemValue.None;
|
||||
if (damageResponse.Source.AttackingItem != null)
|
||||
{
|
||||
if (damageResponse.Source.AttackingItem.ItemClass.Actions[1] is ItemActionProjectile)
|
||||
{
|
||||
return MultiActionReversePatches.ProjectileGetValue(PassiveEffects.TargetArmor, damageResponse.Source.AttackingItem, resist, attacker, null, damageResponse.Source.AttackingItem.ItemClass.ItemTags | bodyPartTags);
|
||||
}
|
||||
return EffectManager.GetValue(PassiveEffects.TargetArmor, damageResponse.Source.AttackingItem, resist, attacker, null, damageResponse.Source.AttackingItem.ItemClass.ItemTags | bodyPartTags);
|
||||
}
|
||||
return EffectManager.GetValue(PassiveEffects.TargetArmor, null, resist, attacker, null, bodyPartTags);
|
||||
}
|
||||
return resist;
|
||||
}
|
||||
|
||||
public static FastTags<TagGroup.Global> GetBodyPartTags(EnumBodyPartHit bodyparts)
|
||||
{
|
||||
if ((bodyparts & EnumBodyPartHit.LeftUpperArm) > EnumBodyPartHit.None)
|
||||
{
|
||||
return LeftUpperArmTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.LeftLowerArm) > EnumBodyPartHit.None)
|
||||
{
|
||||
return LeftLowerArmTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.RightUpperArm) > EnumBodyPartHit.None)
|
||||
{
|
||||
return RightUpperArmTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.RightLowerArm) > EnumBodyPartHit.None)
|
||||
{
|
||||
return RightLowerArmTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.LeftUpperLeg) > EnumBodyPartHit.None)
|
||||
{
|
||||
return LeftUpperLegTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.LeftLowerLeg) > EnumBodyPartHit.None)
|
||||
{
|
||||
return LeftLowerLegTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.RightUpperLeg) > EnumBodyPartHit.None)
|
||||
{
|
||||
return RightUpperLegTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.RightLowerLeg) > EnumBodyPartHit.None)
|
||||
{
|
||||
return RightLowerLegTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.Head) > EnumBodyPartHit.None)
|
||||
{
|
||||
return HeadTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.Torso) > EnumBodyPartHit.None)
|
||||
{
|
||||
return TorsoTags;
|
||||
}
|
||||
if ((bodyparts & EnumBodyPartHit.Special) > EnumBodyPartHit.None)
|
||||
{
|
||||
return SpecialTags;
|
||||
}
|
||||
return FastTags<TagGroup.Global>.none;
|
||||
}
|
||||
|
||||
private static FastTags<TagGroup.Global> TorsoTags = FastTags<TagGroup.Global>.Parse("torso");
|
||||
private static FastTags<TagGroup.Global> HeadTags = FastTags<TagGroup.Global>.Parse("head");
|
||||
private static FastTags<TagGroup.Global> SpecialTags = FastTags<TagGroup.Global>.Parse("special");
|
||||
private static FastTags<TagGroup.Global> ArmsTags = FastTags<TagGroup.Global>.Parse("arms");
|
||||
private static FastTags<TagGroup.Global> UpperArmsTags = FastTags<TagGroup.Global>.Parse("upperArms");
|
||||
private static FastTags<TagGroup.Global> LowerArmsTags = FastTags<TagGroup.Global>.Parse("lowerArms");
|
||||
private static FastTags<TagGroup.Global> LeftArmTags = FastTags<TagGroup.Global>.Parse("leftArms");
|
||||
private static FastTags<TagGroup.Global> RightArmTags = FastTags<TagGroup.Global>.Parse("rightArms");
|
||||
private static FastTags<TagGroup.Global> LeftUpperArmTags = FastTags<TagGroup.Global>.Parse("leftUpperArms") | LeftArmTags | UpperArmsTags | ArmsTags;
|
||||
private static FastTags<TagGroup.Global> LeftLowerArmTags = FastTags<TagGroup.Global>.Parse("leftLowerArms") | LeftArmTags | LowerArmsTags | ArmsTags;
|
||||
private static FastTags<TagGroup.Global> RightUpperArmTags = FastTags<TagGroup.Global>.Parse("rightUpperArms") | RightArmTags | UpperArmsTags | ArmsTags;
|
||||
private static FastTags<TagGroup.Global> RightLowerArmTags = FastTags<TagGroup.Global>.Parse("rightLowerArms") | RightArmTags | LowerArmsTags | ArmsTags;
|
||||
private static FastTags<TagGroup.Global> LegsTags = FastTags<TagGroup.Global>.Parse("legs");
|
||||
private static FastTags<TagGroup.Global> UpperLegsTags = FastTags<TagGroup.Global>.Parse("upperLegs");
|
||||
private static FastTags<TagGroup.Global> LowerLegsTags = FastTags<TagGroup.Global>.Parse("lowerLegs");
|
||||
private static FastTags<TagGroup.Global> LeftLegTags = FastTags<TagGroup.Global>.Parse("leftLegs");
|
||||
private static FastTags<TagGroup.Global> RightLegTags = FastTags<TagGroup.Global>.Parse("rightLegs");
|
||||
private static FastTags<TagGroup.Global> LeftUpperLegTags = FastTags<TagGroup.Global>.Parse("leftUpperLegs") | LeftLegTags | UpperLegsTags | LegsTags;
|
||||
private static FastTags<TagGroup.Global> LeftLowerLegTags = FastTags<TagGroup.Global>.Parse("leftLowerLegs") | LeftLegTags | LowerLegsTags | LegsTags;
|
||||
private static FastTags<TagGroup.Global> RightUpperLegTags = FastTags<TagGroup.Global>.Parse("rightUpperLegs") | RightLegTags | UpperLegsTags | LegsTags;
|
||||
private static FastTags<TagGroup.Global> RightLowerLegTags = FastTags<TagGroup.Global>.Parse("rightLowerLegs") | RightLegTags | LowerLegsTags | LegsTags;
|
||||
}
|
||||
21
Harmony/DisplayMetaAsBuffPatch.cs
Normal file
21
Harmony/DisplayMetaAsBuffPatch.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using HarmonyLib;
|
||||
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public static class DisplayMetaAsBuffPatch
|
||||
{
|
||||
[HarmonyPatch(typeof(XUiM_PlayerBuffs), nameof(XUiM_PlayerBuffs.GetBuffDisplayInfo))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_GetBuffDisplayInfo_XUiM_PlayerBuffs(EntityUINotification notification, ref string __result)
|
||||
{
|
||||
if (notification is DisplayAsBuffEntityUINotification && notification.Buff != null)
|
||||
{
|
||||
__result = notification.CurrentValue.ToString();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Harmony/FPVLegPatches.cs
Normal file
34
Harmony/FPVLegPatches.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using HarmonyLib;
|
||||
using System.Collections.Generic;
|
||||
using UniLinq;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
//[HarmonyPatch]
|
||||
public static class FPVLegPatches
|
||||
{
|
||||
[HarmonyPatch(typeof(SDCSUtils), nameof(SDCSUtils.CreateVizTP))]
|
||||
[HarmonyPrefix]
|
||||
private static void Prefix_SDCSUtils_CreateTP(EntityAlive entity, ref bool isFPV, out bool __state)
|
||||
{
|
||||
__state = isFPV;
|
||||
if (entity is EntityPlayerLocal)
|
||||
{
|
||||
entity.emodel.IsFPV = false;
|
||||
isFPV = false;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(SDCSUtils), nameof(SDCSUtils.CreateVizTP))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SDCSUtils_CreateTP(EntityAlive entity, ref bool isFPV, bool __state)
|
||||
{
|
||||
if (entity is EntityPlayerLocal)
|
||||
{
|
||||
entity.emodel.IsFPV = __state;
|
||||
isFPV = __state;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Harmony/HideMarkerOnAimPatch.cs
Normal file
45
Harmony/HideMarkerOnAimPatch.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
[HarmonyPatch]
|
||||
public class HideMarkerOnAimPatch
|
||||
{
|
||||
[HarmonyPatch(typeof(XUiC_OnScreenIcons), nameof(XUiC_OnScreenIcons.Init))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Init_XUiC_OnScreenIcons(XUiC_OnScreenIcons __instance)
|
||||
{
|
||||
GameObject iconParent = new GameObject("AllIconParent");
|
||||
iconParent.transform.SetParent(__instance.ViewComponent.UiTransform);
|
||||
iconParent.transform.localScale = Vector3.one;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_OnScreenIcons), nameof(XUiC_OnScreenIcons.CreateIcon))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_CreateIcon_XUiC_OnScreenIcons(XUiC_OnScreenIcons __instance)
|
||||
{
|
||||
if (__instance.ViewComponent?.UiTransform)
|
||||
{
|
||||
__instance.screenIconList[__instance.screenIconList.Count - 1].Transform.SetParent(__instance.ViewComponent.UiTransform.Find("AllIconParent"));
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_OnScreenIcons), nameof(XUiC_OnScreenIcons.Update))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_Update_XUiC_OnScreenIcons(XUiC_OnScreenIcons __instance)
|
||||
{
|
||||
GameObject iconParent = __instance.ViewComponent.UiTransform.Find("AllIconParent").gameObject;
|
||||
if (!iconParent)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (__instance.xui.playerUI.entityPlayer.bAimingGun)
|
||||
{
|
||||
iconParent.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
iconParent.SetActive(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
96
Harmony/Init.cs
Normal file
96
Harmony/Init.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using GearsAPI.Settings;
|
||||
using GearsAPI.Settings.Global;
|
||||
using GearsAPI.Settings.World;
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using KFCommonUtilityLib.Scripts.Utilities;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class CommonUtilityLibInit : IModApi
|
||||
{
|
||||
private static bool inited = false;
|
||||
internal static Harmony HarmonyInstance { get; private set; }
|
||||
public void InitMod(Mod _modInstance)
|
||||
{
|
||||
if (inited)
|
||||
return;
|
||||
inited = true;
|
||||
Log.Out(" Loading Patch: " + GetType());
|
||||
unsafe
|
||||
{
|
||||
Log.Out($"size of MultiActionIndice: {sizeof(MultiActionIndice)} marshal size: {Marshal.SizeOf<MultiActionIndice>()}");
|
||||
Log.Out($"{AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.StartHolding)).FullDescription()}");
|
||||
}
|
||||
//QualitySettings.streamingMipmapsMemoryBudget = 4096;
|
||||
DelayLoadModuleManager.RegisterDelayloadDll("FullautoLauncher", "FullautoLauncherAnimationRiggingCompatibilityPatch");
|
||||
//DelayLoadModuleManager.RegisterDelayloadDll("SMXcore", "SMXMultiActionCompatibilityPatch");
|
||||
//DelayLoadModuleManager.RegisterDelayloadDll("SCore", "SCoreEntityHitCompatibilityPatch");
|
||||
CustomEffectEnumManager.RegisterEnumType<MinEventTypes>();
|
||||
CustomEffectEnumManager.RegisterEnumType<PassiveEffects>();
|
||||
|
||||
ModuleManagers.ClearOutputFolder();
|
||||
ItemClassModuleManager.Init();
|
||||
ItemActionModuleManager.Init();
|
||||
|
||||
ModEvents.GameAwake.RegisterHandler(CommonUtilityPatch.InitShotStates);
|
||||
ModEvents.GameAwake.RegisterHandler(CustomEffectEnumManager.InitDefault);
|
||||
ModEvents.GameAwake.RegisterHandler(DelayLoadModuleManager.DelayLoad);
|
||||
//ModEvents.GameAwake.RegisterHandler(AssemblyLocator.Init);
|
||||
ModEvents.GameAwake.RegisterHandler(MultiActionUtils.SetMinEventArrays);
|
||||
ModEvents.GameStartDone.RegisterHandler(RegisterKFEnums);
|
||||
//DOES NOT WORK ON MULTIPLAYER? Patch to ItemClass.LateInitAll
|
||||
//ModEvents.GameStartDone.RegisterHandler(AnimationRiggingManager.ParseItemIDs);
|
||||
ModEvents.GameStartDone.RegisterHandler(MultiActionManager.PostloadCleanup);
|
||||
//ModEvents.GameStartDone.RegisterHandler(CustomEffectEnumManager.PrintResults);
|
||||
//ModEvents.GameUpdate.RegisterHandler(CommonUtilityPatch.ForceUpdateGC);
|
||||
HarmonyInstance = new Harmony(GetType().ToString());
|
||||
HarmonyInstance.PatchAll(Assembly.GetExecutingAssembly());
|
||||
}
|
||||
|
||||
private static void RegisterKFEnums()
|
||||
{
|
||||
CustomEnums.onSelfMagzineDeplete = CustomEffectEnumManager.RegisterOrGetEnum<MinEventTypes>("onSelfMagzineDeplete");
|
||||
CustomEnums.onReloadAboutToStart = CustomEffectEnumManager.RegisterOrGetEnum<MinEventTypes>("onReloadAboutToStart");
|
||||
CustomEnums.onRechargeValueUpdate = CustomEffectEnumManager.RegisterOrGetEnum<MinEventTypes>("onRechargeValueUpdate");
|
||||
CustomEnums.onSelfItemSwitchMode = CustomEffectEnumManager.RegisterOrGetEnum<MinEventTypes>("onSelfItemSwitchMode");
|
||||
CustomEnums.onSelfBurstModeChanged = CustomEffectEnumManager.RegisterOrGetEnum<MinEventTypes>("onSelfBurstModeChanged");
|
||||
CustomEnums.onSelfFirstCVarSync = CustomEffectEnumManager.RegisterOrGetEnum<MinEventTypes>("onSelfFirstCVarSync");
|
||||
CustomEnums.onSelfHoldingItemAssemble = CustomEffectEnumManager.RegisterOrGetEnum<MinEventTypes>("onSelfHoldingItemAssemble");
|
||||
|
||||
CustomEnums.ReloadSpeedRatioFPV2TPV = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("ReloadSpeedRatioFPV2TPV");
|
||||
CustomEnums.RecoilSnappiness = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("RecoilSnappiness");
|
||||
CustomEnums.RecoilReturnSpeed = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("RecoilReturnSpeed");
|
||||
//CustomEnums.ProjectileImpactDamagePercentBlock = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("ProjectileImpactDamagePercentBlock");
|
||||
//CustomEnums.ProjectileImpactDamagePercentEntity = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("ProjectileImpactDamagePercentEntity");
|
||||
CustomEnums.PartialReloadCount = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("PartialReloadCount");
|
||||
|
||||
CustomEnums.CustomTaggedEffect = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("CustomTaggedEffect");
|
||||
CustomEnums.KickDegreeHorizontalModifier = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("KickDegreeHorizontalModifier");
|
||||
CustomEnums.KickDegreeVerticalModifier = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("KickDegreeVerticalModifier");
|
||||
CustomEnums.WeaponErgonomics = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("WeaponErgonomics");
|
||||
CustomEnums.RecoilCameraShakeStrength = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("RecoilCameraShakeStrength");
|
||||
CustomEnums.BurstShotInterval = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("BurstShotInterval");
|
||||
CustomEnums.MaxWeaponSpread = CustomEffectEnumManager.RegisterOrGetEnum<PassiveEffects>("MaxWeaponSpread");
|
||||
}
|
||||
}
|
||||
|
||||
public class GearsImpl : IGearsModApi
|
||||
{
|
||||
public void InitMod(IGearsMod modInstance)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnGlobalSettingsLoaded(IModGlobalSettings modSettings)
|
||||
{
|
||||
RecoilManager.InitRecoilSettings(modSettings);
|
||||
}
|
||||
|
||||
public void OnWorldSettingsLoaded(IModWorldSettings worldSettings)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
73
Harmony/InvariableRPMPatches.cs
Normal file
73
Harmony/InvariableRPMPatches.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public static class InvariableRPMPatches
|
||||
{
|
||||
//added as a transpiler so that it's applied before all post processing
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.OnHoldingUpdate))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_OnHoldingUpdate_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_getvalue = AccessTools.Method(typeof(EffectManager), nameof(EffectManager.GetValue));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_getvalue))
|
||||
{
|
||||
int start = -1;
|
||||
for (int j = i; j >= 0; j--)
|
||||
{
|
||||
if (codes[j].opcode == OpCodes.Stloc_0)
|
||||
{
|
||||
start = j + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start >= 0)
|
||||
{
|
||||
codes.InsertRange(i + 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(InvariableRPMPatches), nameof(InvariableRPMPatches.CalcFixedRPM))
|
||||
});
|
||||
codes.RemoveRange(start, i - start + 2);
|
||||
Log.Out("Invariable RPM Patch applied!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static float CalcFixedRPM(ItemActionRanged rangedAction, ItemActionRanged.ItemActionDataRanged rangedData)
|
||||
{
|
||||
float res;
|
||||
if (rangedAction is IModuleContainerFor<ActionModuleInvariableRPM> actionModule)
|
||||
{
|
||||
float rpm = 60f / rangedData.OriginalDelay;
|
||||
float perc = 1f;
|
||||
var tags = rangedData.invData.item.ItemTags;
|
||||
MultiActionManager.ModifyItemTags(rangedData.invData.itemValue, rangedData, ref tags);
|
||||
rangedData.invData.item.Effects.ModifyValue(rangedData.invData.holdingEntity, PassiveEffects.RoundsPerMinute, ref rpm, ref perc, rangedData.invData.itemValue.Quality, tags);
|
||||
res = rpm * perc;
|
||||
//Log.Out($"fixed RPM {res}");
|
||||
}
|
||||
else
|
||||
{
|
||||
res = EffectManager.GetValue(PassiveEffects.RoundsPerMinute, rangedData.invData.itemValue, 60f / rangedData.OriginalDelay, rangedData.invData.holdingEntity);
|
||||
}
|
||||
res = 60f / res;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Harmony/ItemActionModulePatch.cs
Normal file
41
Harmony/ItemActionModulePatch.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using HarmonyLib;
|
||||
using HarmonyLib.Public.Patching;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using System.Reflection;
|
||||
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public static class ItemActionModulePatch
|
||||
{
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.StartGame))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_StartGame_GameManager()
|
||||
{
|
||||
ItemActionModuleManager.InitNew();
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.Init))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Init_ItemClass(ItemClass __instance)
|
||||
{
|
||||
ItemActionModuleManager.CheckItem(__instance);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.LateInitAll))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_LateInitAll_ItemClass()
|
||||
{
|
||||
ItemActionModuleManager.FinishAndLoad();
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PatchManager), "GetRealMethod")]
|
||||
[HarmonyReversePatch]
|
||||
public static MethodBase GetRealMethod(MethodInfo method, bool useReplacement)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
343
Harmony/ModularPatches.cs
Normal file
343
Harmony/ModularPatches.cs
Normal file
@@ -0,0 +1,343 @@
|
||||
using HarmonyLib;
|
||||
using HarmonyLib.Public.Patching;
|
||||
using System.Collections.Generic;
|
||||
using UniLinq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System;
|
||||
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public static class ModularPatches
|
||||
{
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.StartGame))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_StartGame_GameManager()
|
||||
{
|
||||
ModuleManagers.InitNew();
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.Init))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Init_ItemClass(ItemClass __instance)
|
||||
{
|
||||
ItemClassModuleManager.CheckItem(__instance);
|
||||
ItemActionModuleManager.CheckItem(__instance);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.worldInfoCo), MethodType.Enumerator)]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_worldInfoCo_GameManager(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_all = AccessTools.Method(typeof(WorldStaticData), nameof(WorldStaticData.AllConfigsReceivedAndLoaded));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_all))
|
||||
{
|
||||
codes.Insert(i + 2, CodeInstruction.Call(typeof(ModuleManagers), nameof(ModuleManagers.FinishAndLoad)).WithLabels(codes[i + 2].ExtractLabels()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ConnectionManager), nameof(ConnectionManager.ServerReady))]
|
||||
[HarmonyPrefix]
|
||||
private static void Prefix_ServerReady_ConnectionManager()
|
||||
{
|
||||
ModuleManagers.FinishAndLoad();
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(WorldStaticData), nameof(WorldStaticData.ReloadAllXmlsSync))]
|
||||
[HarmonyPrefix]
|
||||
private static void Prefix_ReloadAllXmlsSync_WorldStaticData()
|
||||
{
|
||||
ModuleManagers.InitNew();
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(WorldStaticData), nameof(WorldStaticData.ReloadAllXmlsSync))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_ReloadAllXmlsSync_WorldStaticData()
|
||||
{
|
||||
ModuleManagers.FinishAndLoad();
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.Disconnect))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Disconnect_GameManager()
|
||||
{
|
||||
ModuleManagers.Cleanup();
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PatchManager), "GetRealMethod")]
|
||||
[HarmonyReversePatch]
|
||||
public static MethodBase GetRealMethod(MethodInfo method, bool useReplacement)
|
||||
{
|
||||
IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
if (instructions == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new CodeInstruction[]
|
||||
{
|
||||
CodeInstruction.LoadField(typeof(PatchManager), "ReplacementToOriginals"),
|
||||
CodeInstruction.LoadField(typeof(PatchManager), "ReplacementToOriginalsMono"),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.Call(typeof(ModularPatches), nameof(ModularPatches.GetPatched)),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
};
|
||||
}
|
||||
_ = Transpiler(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static MethodBase GetPatched(ConditionalWeakTable<MethodBase, MethodBase> ReplacementToOriginals, Dictionary<long, MethodBase[]> ReplacementToOriginalsMono, MethodInfo method)
|
||||
{
|
||||
MethodInfo methodInfo = method.Identifiable();
|
||||
ConditionalWeakTable<MethodBase, MethodBase> replacementToOriginals = ReplacementToOriginals;
|
||||
lock (replacementToOriginals)
|
||||
{
|
||||
foreach (var pair in replacementToOriginals)
|
||||
{
|
||||
if (pair.Value == method)
|
||||
{
|
||||
Log.Out($"Found method replacement {pair.Key.FullDescription()} for method {method.FullDescription()}");
|
||||
return pair.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (AccessTools.IsMonoRuntime)
|
||||
{
|
||||
long num = (long)method.MethodHandle.GetFunctionPointer();
|
||||
Dictionary<long, MethodBase[]> replacementToOriginalsMono = ReplacementToOriginalsMono;
|
||||
lock (replacementToOriginalsMono)
|
||||
{
|
||||
foreach (var pair in replacementToOriginalsMono)
|
||||
{
|
||||
if (pair.Value[0] == method)
|
||||
{
|
||||
Log.Out($"Found MONO method replacement {pair.Value[1].FullDescription()} for method {method.FullDescription()}");
|
||||
return pair.Value[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PatchManager), nameof(PatchManager.ToPatchInfo))]
|
||||
[HarmonyReversePatch]
|
||||
public static PatchInfo ToPatchInfoDontAdd(this MethodBase methodBase)
|
||||
{
|
||||
IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
if (instructions == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var codes = instructions.ToList();
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Dup)
|
||||
{
|
||||
codes[i - 1].WithLabels(codes[i - 3].ExtractLabels());
|
||||
codes.RemoveAt(i + 2);
|
||||
codes.RemoveAt(i);
|
||||
codes.RemoveRange(i - 3, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
_ = Transpiler(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PatchInfo), "AddTranspilers")]
|
||||
[HarmonyReversePatch]
|
||||
public static void AddTranspilers(this PatchInfo self, string owner, params HarmonyMethod[] methods)
|
||||
{
|
||||
}
|
||||
|
||||
public static PatchInfo Copy(this PatchInfo self)
|
||||
{
|
||||
var res = new PatchInfo();
|
||||
res.prefixes = new Patch[self.prefixes.Length];
|
||||
res.postfixes = new Patch[self.postfixes.Length];
|
||||
res.transpilers = new Patch[self.transpilers.Length];
|
||||
res.finalizers = new Patch[self.finalizers.Length];
|
||||
res.ilmanipulators = new Patch[self.ilmanipulators.Length];
|
||||
Array.Copy(self.prefixes, res.prefixes, res.prefixes.Length);
|
||||
Array.Copy(self.postfixes, res.postfixes, res.postfixes.Length);
|
||||
Array.Copy(self.transpilers, res.transpilers, res.transpilers.Length);
|
||||
Array.Copy(self.finalizers, res.finalizers, res.finalizers.Length);
|
||||
Array.Copy(self.ilmanipulators, res.ilmanipulators, res.ilmanipulators.Length);
|
||||
return res;
|
||||
}
|
||||
|
||||
//public static MethodBase GetOriginalMethod(this HarmonyMethod attr)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// MethodType? methodType = attr.methodType;
|
||||
// if (methodType != null)
|
||||
// {
|
||||
// switch (methodType.GetValueOrDefault())
|
||||
// {
|
||||
// case MethodType.Normal:
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// return AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes, null);
|
||||
// case MethodType.Getter:
|
||||
// {
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// PropertyInfo propertyInfo = AccessTools.DeclaredIndexer(attr.declaringType, attr.argumentTypes);
|
||||
// return (propertyInfo != null) ? propertyInfo.GetGetMethod(true) : null;
|
||||
// }
|
||||
// PropertyInfo propertyInfo2 = AccessTools.DeclaredProperty(attr.declaringType, attr.methodName);
|
||||
// return (propertyInfo2 != null) ? propertyInfo2.GetGetMethod(true) : null;
|
||||
// }
|
||||
// case MethodType.Setter:
|
||||
// {
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// PropertyInfo propertyInfo3 = AccessTools.DeclaredIndexer(attr.declaringType, attr.argumentTypes);
|
||||
// return (propertyInfo3 != null) ? propertyInfo3.GetSetMethod(true) : null;
|
||||
// }
|
||||
// PropertyInfo propertyInfo4 = AccessTools.DeclaredProperty(attr.declaringType, attr.methodName);
|
||||
// return (propertyInfo4 != null) ? propertyInfo4.GetSetMethod(true) : null;
|
||||
// }
|
||||
// case MethodType.Constructor:
|
||||
// return AccessTools.DeclaredConstructor(attr.declaringType, attr.argumentTypes, false);
|
||||
// case MethodType.StaticConstructor:
|
||||
// return AccessTools.GetDeclaredConstructors(attr.declaringType, null).FirstOrDefault((ConstructorInfo c) => c.IsStatic);
|
||||
// case MethodType.Enumerator:
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// return AccessTools.EnumeratorMoveNext(AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes, null));
|
||||
// case MethodType.Async:
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// return AccessTools.AsyncMoveNext(AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes, null));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (AmbiguousMatchException ex)
|
||||
// {
|
||||
// throw new Exception("Ambiguous match for HarmonyMethod[" + attr.ToString() + "]", ex.InnerException ?? ex);
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//public static MethodBase GetBaseMethod(this HarmonyMethod attr)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// MethodType? methodType = attr.methodType;
|
||||
// if (methodType != null)
|
||||
// {
|
||||
// switch (methodType.GetValueOrDefault())
|
||||
// {
|
||||
// case MethodType.Normal:
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// return AccessTools.Method(attr.declaringType, attr.methodName, attr.argumentTypes, null);
|
||||
// case MethodType.Getter:
|
||||
// {
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// PropertyInfo propertyInfo = AccessTools.Indexer(attr.declaringType, attr.argumentTypes);
|
||||
// return (propertyInfo != null) ? propertyInfo.GetGetMethod(true) : null;
|
||||
// }
|
||||
// PropertyInfo propertyInfo2 = AccessTools.Property(attr.declaringType, attr.methodName);
|
||||
// return (propertyInfo2 != null) ? propertyInfo2.GetGetMethod(true) : null;
|
||||
// }
|
||||
// case MethodType.Setter:
|
||||
// {
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// PropertyInfo propertyInfo3 = AccessTools.Indexer(attr.declaringType, attr.argumentTypes);
|
||||
// return (propertyInfo3 != null) ? propertyInfo3.GetSetMethod(true) : null;
|
||||
// }
|
||||
// PropertyInfo propertyInfo4 = AccessTools.Property(attr.declaringType, attr.methodName);
|
||||
// return (propertyInfo4 != null) ? propertyInfo4.GetSetMethod(true) : null;
|
||||
// }
|
||||
// case MethodType.Constructor:
|
||||
// return AccessTools.Constructor(attr.declaringType, attr.argumentTypes, false);
|
||||
// case MethodType.StaticConstructor:
|
||||
// return AccessTools.GetDeclaredConstructors(attr.declaringType, null).FirstOrDefault((ConstructorInfo c) => c.IsStatic);
|
||||
// case MethodType.Enumerator:
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// return AccessTools.EnumeratorMoveNext(AccessTools.Method(attr.declaringType, attr.methodName, attr.argumentTypes, null));
|
||||
// case MethodType.Async:
|
||||
// if (attr.methodName == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// return AccessTools.AsyncMoveNext(AccessTools.Method(attr.declaringType, attr.methodName, attr.argumentTypes, null));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (AmbiguousMatchException ex)
|
||||
// {
|
||||
// throw new Exception("Ambiguous match for HarmonyMethod[" + attr.ToString() + "]", ex.InnerException ?? ex);
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
public static class PatchToolsPatches
|
||||
{
|
||||
public static MethodBase TargetMethod()
|
||||
{
|
||||
return AccessTools.DeclaredMethod(AccessTools.TypeByName("HarmonyLib.PatchTools"), "GetOriginalMethod");
|
||||
}
|
||||
|
||||
[HarmonyReversePatch]
|
||||
public static MethodBase GetOriginalMethod(this HarmonyMethod attr)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
[HarmonyReversePatch]
|
||||
public static MethodBase GetBaseMethod(this HarmonyMethod attr)
|
||||
{
|
||||
IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
if (instructions == null)
|
||||
return null;
|
||||
return instructions.MethodReplacer(AccessTools.Method(typeof(AccessTools), nameof(AccessTools.DeclaredMethod), new[] { typeof(Type), typeof(string), typeof(Type[]), typeof(Type[]) }),
|
||||
AccessTools.Method(typeof(AccessTools), nameof(AccessTools.Method), new[] { typeof(Type), typeof(string), typeof(Type[]), typeof(Type[]) }))
|
||||
.MethodReplacer(AccessTools.Method(typeof(AccessTools), nameof(AccessTools.DeclaredIndexer)),
|
||||
AccessTools.Method(typeof(AccessTools), nameof(AccessTools.Indexer)))
|
||||
.MethodReplacer(AccessTools.Method(typeof(AccessTools), nameof(AccessTools.DeclaredProperty), new[] { typeof(Type), typeof(string) }),
|
||||
AccessTools.Method(typeof(AccessTools), nameof(AccessTools.Property), new[] { typeof(Type), typeof(string) }))
|
||||
.MethodReplacer(AccessTools.Method(typeof(AccessTools), nameof(AccessTools.DeclaredConstructor)),
|
||||
AccessTools.Method(typeof(AccessTools), nameof(AccessTools.Constructor)));
|
||||
}
|
||||
_ = Transpiler(null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
2909
Harmony/MultiActionPatches.cs
Normal file
2909
Harmony/MultiActionPatches.cs
Normal file
@@ -0,0 +1,2909 @@
|
||||
using GameEvent.SequenceActions;
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib.Scripts.NetPackages;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using KFCommonUtilityLib.Scripts.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using UniLinq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
//done?: patch all accesses to ItemClass.Actions so that they process all actions
|
||||
//done?: patch ItemClass.ExecuteAction, MinEvent triggers
|
||||
//done: replace GameManager.ItemReload*
|
||||
//done: patch ItemActionRanged.ConsumeAmmo
|
||||
//todo: patch passive effect handling and trigger effect firing, in ItemValue.ModifyValue set action index from tags
|
||||
//todo: patch trigger action index enum/ or just let it use secondary and tag check?
|
||||
//todo: handle ItemActionAttack.GetDamageEntity/GetDamageBlock and call sites actionIndex
|
||||
//todo: sell, assemble, scrap remove ammo
|
||||
|
||||
//nope, not gonna work
|
||||
//try old style action toggle,
|
||||
//replace meta and ammo index when toggling, => solves ammo issue
|
||||
//provide requirement for checking current mode, => solves effect group condition issue
|
||||
//replace hardcoded action index with current mode => bulk patch is enough?
|
||||
//ItemClass subclass? maybe not
|
||||
//is inventory update on remote client really needed? put off
|
||||
|
||||
//todo: figure out when is meta and ammo index used, how to set their value in minimum patches
|
||||
//ExecuteAction, Reload, what's more?
|
||||
//safe to work within ItemAction scope
|
||||
//even if meta and ammo index is set accordingly, better keep checking them in reload script
|
||||
[HarmonyPatch]
|
||||
public static class MultiActionPatches
|
||||
{
|
||||
#region Run Correct ItemAction
|
||||
|
||||
#region Ranged Reload
|
||||
//Replace reload action index with animator item action index parameter
|
||||
//set MinEventParams.ItemActionData before getting passive value
|
||||
[HarmonyPatch(typeof(AnimatorRangedReloadState), nameof(AnimatorRangedReloadState.OnStateEnter))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_OnStateEnter_AnimatorRangedReloadState(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_index = generator.DeclareLocal(typeof(int));
|
||||
|
||||
FieldInfo fld_action = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.Actions));
|
||||
FieldInfo fld_actionData = AccessTools.Field(typeof(ItemInventoryData), nameof(ItemInventoryData.actionData));
|
||||
FieldInfo fld_meta = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.Meta));
|
||||
FieldInfo fld_ammoindex = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.SelectedAmmoTypeIndex));
|
||||
MethodInfo mtd_getvalue = AccessTools.Method(typeof(EffectManager), nameof(EffectManager.GetValue));
|
||||
bool firstRet = true;
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if ((code.LoadsField(fld_action) || code.LoadsField(fld_actionData)) && codes[i + 1].opcode == OpCodes.Ldc_I4_0)
|
||||
{
|
||||
//get correct ItemAction and data
|
||||
codes[i + 1].opcode = OpCodes.Ldloc_S;
|
||||
codes[i + 1].operand = lbd_index;
|
||||
}
|
||||
else if (code.Calls(mtd_getvalue))
|
||||
{
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(AnimatorRangedReloadState), "actionData"),
|
||||
CodeInstruction.LoadField(typeof(ItemActionData), nameof(ItemActionData.invData)),
|
||||
CodeInstruction.LoadField(typeof(ItemInventoryData), nameof(ItemInventoryData.holdingEntity)),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.MinEventContext)),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(AnimatorRangedReloadState), "actionData"),
|
||||
CodeInstruction.StoreField(typeof(MinEventParams), nameof(MinEventParams.ItemActionData))
|
||||
});
|
||||
break;
|
||||
}
|
||||
else if (code.opcode == OpCodes.Ret && firstRet)
|
||||
{
|
||||
firstRet = false;
|
||||
var insert = new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.GetActionIndexForEntity)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_index)
|
||||
};
|
||||
insert[0].MoveLabelsFrom(codes[i + 1]);
|
||||
codes.InsertRange(i + 1, insert);
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AnimatorRangedReloadState), nameof(AnimatorRangedReloadState.OnStateExit))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_OnStateExit_AnimatorRangedReloadState(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
MethodInfo mtd_getvalue = AccessTools.Method(typeof(EffectManager), nameof(EffectManager.GetValue));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.Calls(mtd_getvalue))
|
||||
{
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(AnimatorRangedReloadState), nameof(AnimatorRangedReloadState.actionData)),
|
||||
CodeInstruction.LoadField(typeof(ItemActionData), nameof(ItemActionData.invData)),
|
||||
CodeInstruction.LoadField(typeof(ItemInventoryData), nameof(ItemInventoryData.holdingEntity)),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.MinEventContext)),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(AnimatorRangedReloadState), nameof(AnimatorRangedReloadState.actionData)),
|
||||
CodeInstruction.StoreField(typeof(MinEventParams), nameof(MinEventParams.ItemActionData))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region Aiming
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.IsAimingGunPossible))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_IsAimingGunPossible_EntityPlayerLocal(ref bool __result, EntityPlayerLocal __instance)
|
||||
{
|
||||
__result = true;
|
||||
for (int i = 0; i < __instance.inventory.holdingItem.Actions.Length; i++)
|
||||
{
|
||||
ItemAction action = __instance.inventory.holdingItem.Actions[i];
|
||||
ItemActionData actionData = __instance.inventory.holdingItemData.actionData[i];
|
||||
__result &= (action == null || action.IsAimingGunPossible(actionData));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region Cancel bow draw
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.TryCancelBowDraw))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_TryCancelBowDraw(EntityPlayerLocal __instance)
|
||||
{
|
||||
for (int i = 0; i < __instance.inventory.holdingItem.Actions.Length; i++)
|
||||
{
|
||||
ItemAction action = __instance.inventory.holdingItem.Actions[i];
|
||||
ItemActionData actionData = __instance.inventory.holdingItemData.actionData[i];
|
||||
if (action is ItemActionCatapult catapult)
|
||||
{
|
||||
action.CancelAction(actionData);
|
||||
actionData.HasExecuted = false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region Consume wheel scroll
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.ConsumeScrollWheel))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_ConsumeScrollWheel_ItemClass(ItemClass __instance, ItemInventoryData _data, float _scrollWheelInput, PlayerActionsLocal _playerInput, ref bool __result)
|
||||
{
|
||||
__result = false;
|
||||
for (int i = 0; i < __instance.Actions.Length; i++)
|
||||
{
|
||||
ItemAction action = __instance.Actions[i];
|
||||
if (action != null && action.ConsumeScrollWheel(_data.actionData[i], _scrollWheelInput, _playerInput))
|
||||
{
|
||||
__result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region Create modifier data for more actions
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.CreateInventoryData))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_CreateInventoryData_ItemClass(ItemInventoryData __result, ItemClass __instance)
|
||||
{
|
||||
int prevCount = __result.actionData.Count;
|
||||
while (__result.actionData.Count < __instance.Actions.Length)
|
||||
{
|
||||
__result.actionData.Add(null);
|
||||
}
|
||||
for (; prevCount < __instance.Actions.Length; prevCount++)
|
||||
{
|
||||
if (__instance.Actions[prevCount] != null)
|
||||
__result.actionData[prevCount] = __instance.Actions[prevCount].CreateModifierData(__result, prevCount);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//todo: should I patch ItemClass.ExecuteAction for melee actions?
|
||||
|
||||
//KEEP
|
||||
#region IsFocusBlockInside?
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.IsFocusBlockInside))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_IsFocusBlockInside_ItemClass(ItemClass __instance, ref bool __result)
|
||||
{
|
||||
__result = __instance.Actions.All(action => action != null && action.IsFocusBlockInside());
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region IsHUDDisabled
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.IsHUDDisabled))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_IsHUDDisabled_ItemClass(ItemClass __instance, ref bool __result, ItemInventoryData _data)
|
||||
{
|
||||
__result = false;
|
||||
for (int i = 0; i < __instance.Actions.Length; i++)
|
||||
{
|
||||
__result |= __instance.Actions[i] != null && __instance.Actions[i].IsHUDDisabled(_data.actionData[i]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region OnHUD
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.OnHUD))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_OnHUD_ItemClass(ItemInventoryData _data, int _x, int _y, ItemClass __instance)
|
||||
{
|
||||
for (int i = 0; i < __instance.Actions.Length; i++)
|
||||
{
|
||||
__instance.Actions[i]?.OnHUD(_data.actionData[i], _x, _y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.GetCrosshairType))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_GetCrosshairType_ItemClass(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_index = generator.DeclareLocal(typeof(int));
|
||||
|
||||
FieldInfo fld_action = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.Actions));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.LoadsField(fld_action) && codes[i + 1].opcode == OpCodes.Ldc_I4_0)
|
||||
{
|
||||
codes[i + 1].opcode = OpCodes.Ldloc_S;
|
||||
codes[i + 1].operand = lbd_index;
|
||||
}
|
||||
}
|
||||
|
||||
codes.InsertRange(0, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(ItemInventoryData), nameof(ItemInventoryData.holdingEntity)),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.GetActionIndexForEntity)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_index)
|
||||
});
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region OnScreenOverlay
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.OnScreenOverlay))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_OnScreenOverlay_ItemClass(ItemInventoryData _data, ItemClass __instance)
|
||||
{
|
||||
for (int i = 0; i < __instance.Actions.Length; i++)
|
||||
{
|
||||
__instance.Actions[i]?.OnScreenOverlay(_data.actionData[i]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region inventory related
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.GetHoldingGun))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_GetHoldingGun_Inventory(Inventory __instance, ref ItemActionAttack __result)
|
||||
{
|
||||
__result = __instance.holdingItem.Actions[MultiActionManager.GetActionIndexForEntity(__instance.entity)] as ItemActionAttack ?? __instance.holdingItem.Actions[0] as ItemActionAttack;
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.GetHoldingDynamicMelee))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_GetHoldingDynamicMelee_Inventory(Inventory __instance, ref ItemActionDynamic __result)
|
||||
{
|
||||
__result = __instance.holdingItem.Actions[MultiActionManager.GetActionIndexForEntity(__instance.entity)] as ItemActionDynamic ?? __instance.holdingItem.Actions[0] as ItemActionDynamic;
|
||||
return false;
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(Inventory), "clearSlotByIndex")]
|
||||
//[HarmonyPrefix]
|
||||
//private static bool Prefix_clearSlotByIndex_Inventory(int _idx, Inventory __instance, EntityAlive ___entity)
|
||||
//{
|
||||
// if (__instance.holdingItemIdx == _idx && ___entity != null && !___entity.isEntityRemote)
|
||||
// {
|
||||
// var mapping = MultiActionManager.GetMappingForEntity(___entity.entityId);
|
||||
// mapping?.SaveMeta();
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
#endregion
|
||||
|
||||
#region GameManager.ItemReload*
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.SetAmmoType))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetAmmoType_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
MethodInfo mtd_reloadserver = AccessTools.Method(typeof(GameManager), nameof(GameManager.ItemReloadServer));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.Calls(mtd_reloadserver))
|
||||
{
|
||||
codes.RemoveAt(i);
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemAction), nameof(ItemAction.ActionIndex)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.FixedItemReloadServer))
|
||||
});
|
||||
codes.RemoveAt(i - 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.SwapAmmoType))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SwapAmmoType_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
MethodInfo mtd_reloadserver = AccessTools.Method(typeof(GameManager), nameof(GameManager.ItemReloadServer));
|
||||
FieldInfo fld_actiondata = AccessTools.Field(typeof(ItemInventoryData), nameof(ItemInventoryData.actionData));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.Calls(mtd_reloadserver))
|
||||
{
|
||||
codes.RemoveAt(i);
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemAction), nameof(ItemAction.ActionIndex)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.FixedItemReloadServer))
|
||||
});
|
||||
codes[i - 4].MoveLabelsFrom(codes[i - 5]);
|
||||
codes.RemoveAt(i - 5);
|
||||
break;
|
||||
}
|
||||
else if (code.LoadsField(fld_actiondata))
|
||||
{
|
||||
codes.RemoveAt(i + 1);
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemAction), nameof(ItemAction.ActionIndex))
|
||||
});
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.SwapAmmoType))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SwapAmmoType_ItemActionLauncher(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
FieldInfo fld_actiondata = AccessTools.Field(typeof(ItemInventoryData), nameof(ItemInventoryData.actionData));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.LoadsField(fld_actiondata))
|
||||
{
|
||||
codes.RemoveAt(i + 1);
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemAction), nameof(ItemAction.ActionIndex))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.SwapSelectedAmmo))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SwapSelectedAmmo_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
MethodInfo mtd_reloadserver = AccessTools.Method(typeof(GameManager), nameof(GameManager.ItemReloadServer));
|
||||
MethodInfo mtd_canreload = AccessTools.Method(typeof(ItemActionAttack), nameof(ItemActionAttack.CanReload));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.Calls(mtd_reloadserver))
|
||||
{
|
||||
codes.RemoveAt(i);
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemAction), nameof(ItemAction.ActionIndex)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.FixedItemReloadServer))
|
||||
});
|
||||
codes.RemoveAt(i - 3);
|
||||
break;
|
||||
}
|
||||
else if (code.Calls(mtd_canreload))
|
||||
{
|
||||
codes.RemoveAt(i - 2);
|
||||
codes.InsertRange(i - 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemAction), nameof(ItemAction.ActionIndex))
|
||||
});
|
||||
codes.RemoveRange(i - 9, 3);
|
||||
codes.Insert(i - 9, new CodeInstruction(OpCodes.Ldarg_0));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.loadNewAmmunition))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_loadNewAmmunition_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_actiondata = AccessTools.Field(typeof(ItemInventoryData), nameof(ItemInventoryData.actionData));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_actiondata))
|
||||
{
|
||||
codes.RemoveAt(i + 1);
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_3),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.GetActionIndexForEntity))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region Launcher logic
|
||||
#region Launcher projectile meta and action index
|
||||
[HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.StartHolding))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_StartHolding_ItemActionLauncher(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_meta = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.Meta));
|
||||
var mtd_delete = AccessTools.Method(typeof(ItemActionLauncher), nameof(ItemActionLauncher.DeleteProjectiles));
|
||||
var prop_itemvalue = AccessTools.PropertyGetter(typeof(ItemInventoryData), nameof(ItemInventoryData.itemValue));
|
||||
var lbd_meta = generator.DeclareLocal(typeof(int));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_delete))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(ItemActionData), nameof(ItemActionData.invData)),
|
||||
new CodeInstruction(OpCodes.Callvirt, prop_itemvalue),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(ItemActionData), nameof(ItemActionData.indexInEntityOfAction)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetMetaByActionIndex)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_meta)
|
||||
});
|
||||
i += 7;
|
||||
}
|
||||
else if (codes[i].LoadsField(fld_meta))
|
||||
{
|
||||
codes.Insert(i + 1, new CodeInstruction(OpCodes.Ldloc_S, lbd_meta));
|
||||
codes.RemoveRange(i - 3, 4);
|
||||
i -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.instantiateProjectile))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_instantiateProjectile_ItemActionLauncher_MetaIndex(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_ammoindex = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.SelectedAmmoTypeIndex));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_ammoindex))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = AccessTools.Method(typeof(MultiActionUtils), nameof(MultiActionUtils.GetSelectedAmmoIndexByActionIndex));
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(ItemActionData), nameof(ItemActionData.indexInEntityOfAction))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.instantiateProjectile))]
|
||||
[HarmonyTranspiler]
|
||||
//use custom script
|
||||
private static IEnumerable<CodeInstruction> Transpiler_instantiateProjectile_ItemActionLauncher_ReplaceScript(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
MethodInfo mtd_addcomponent = AccessTools.Method(typeof(GameObject), nameof(GameObject.AddComponent), Array.Empty<Type>());
|
||||
MethodInfo mtd_addcomponentprev = mtd_addcomponent.MakeGenericMethod(typeof(ProjectileMoveScript));
|
||||
MethodInfo mtd_addcomponentnew = mtd_addcomponent.MakeGenericMethod(typeof(CustomProjectileMoveScript));
|
||||
foreach (var code in instructions)
|
||||
{
|
||||
if (code.Calls(mtd_addcomponentprev))
|
||||
{
|
||||
Log.Out("replacing launcher projectile script...");
|
||||
code.operand = mtd_addcomponentnew;
|
||||
}
|
||||
yield return code;
|
||||
}
|
||||
}
|
||||
|
||||
//copy ItemValue to projectile
|
||||
[HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.instantiateProjectile))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_instantiateProjectile_ItemActionLauncher(Transform __result)
|
||||
{
|
||||
var script = __result.GetComponent<ProjectileMoveScript>();
|
||||
var projectileValue = script.itemValueProjectile;
|
||||
var launcherValue = script.itemValueLauncher;
|
||||
projectileValue.Activated = (byte)(Mathf.Clamp01(script.actionData.strainPercent) * byte.MaxValue);
|
||||
MultiActionUtils.CopyLauncherValueToProjectile(launcherValue, projectileValue, script.actionData.indexInEntityOfAction);
|
||||
}
|
||||
|
||||
//
|
||||
[HarmonyPatch(typeof(ProjectileMoveScript), nameof(ProjectileMoveScript.Fire))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_Fire_ProjectileMoveScript(ProjectileMoveScript __instance, Vector3 _idealStartPosition, Vector3 _flyDirection, Entity _firingEntity, int _hmOverride, float _radius)
|
||||
{
|
||||
if (_firingEntity is EntityAlive entityAlive)
|
||||
entityAlive.MinEventContext.ItemActionData = __instance.actionData;
|
||||
if (__instance is CustomProjectileMoveScript)
|
||||
{
|
||||
__instance.ProjectileFire(_idealStartPosition, _flyDirection, _firingEntity, _hmOverride, _radius);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region FireEvent patches, set params
|
||||
//KEEP
|
||||
#region Ranged ExecuteAction FireEvent params
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.ExecuteAction))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_ExecuteAction_ItemClass(ref int _actionIdx, ItemInventoryData _data, PlayerActionsLocal _playerActions)
|
||||
{
|
||||
|
||||
if (_actionIdx != 0 || _playerActions == null || !(_data.holdingEntity is EntityPlayerLocal player))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
_actionIdx = MultiActionManager.GetActionIndexForEntity(player);
|
||||
player.MinEventContext.ItemActionData = _data.actionData[_actionIdx];
|
||||
return true;
|
||||
}
|
||||
|
||||
//why? ask TFP the fuck they are doing
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ExecuteAction))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ExecuteAction_ItemActionRanged(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
FieldInfo fld_itemactiondata = AccessTools.Field(typeof(MinEventParams), nameof(MinEventParams.ItemActionData));
|
||||
MethodInfo mtd_reloadserver = AccessTools.Method(typeof(IGameManager), nameof(IGameManager.ItemReloadServer));
|
||||
FieldInfo fld_gamemanager = AccessTools.Field(typeof(ItemInventoryData), nameof(ItemInventoryData.gameManager));
|
||||
MethodInfo mtd_getkickback = AccessTools.Method(typeof(ItemActionAttack), nameof(ItemActionAttack.GetKickbackForce));
|
||||
MethodInfo mtd_getmaxammo = AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.GetMaxAmmoCount));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.StoresField(fld_itemactiondata))
|
||||
{
|
||||
codes.Insert(i, new CodeInstruction(OpCodes.Ldarg_1));
|
||||
codes.RemoveRange(i - 5, 5);
|
||||
i -= 4;
|
||||
}
|
||||
else if (code.Calls(mtd_reloadserver))
|
||||
{
|
||||
int j = i;
|
||||
while (!codes[j].LoadsField(fld_gamemanager))
|
||||
{
|
||||
j--;
|
||||
}
|
||||
codes.RemoveAt(i);
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.LoadField(typeof(ItemActionData), nameof(ItemActionData.indexInEntityOfAction)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.FixedItemReloadServer))
|
||||
});
|
||||
codes.RemoveRange(j - 2, 3);
|
||||
i--;
|
||||
}
|
||||
//else if (code.Calls(mtd_getmaxammo))
|
||||
//{
|
||||
// int j = i + 1;
|
||||
// for (; j < codes.Count; j++)
|
||||
// {
|
||||
// if (codes[j].Calls(mtd_getkickback))
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (j < codes.Count)
|
||||
// {
|
||||
// var jumpto = codes[j - 2];
|
||||
// var label = generator.DefineLabel();
|
||||
// jumpto.labels.Add(label);
|
||||
// codes.Insert(i - 2, new CodeInstruction(OpCodes.Br_S, label));
|
||||
// codes[i - 2].MoveLabelsFrom(codes[i - 1]);
|
||||
// i++;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ItemAction.CancelAction
|
||||
[HarmonyPatch(typeof(ItemActionCatapult), nameof(ItemActionCatapult.CancelAction))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_CancelAction_ItemActionCatapult(ItemActionData _actionData)
|
||||
{
|
||||
_actionData.invData.holdingEntity.MinEventContext.ItemActionData = _actionData;
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ItemActionDynamicMelee.Raycast
|
||||
[HarmonyPatch(typeof(ItemActionDynamicMelee), nameof(ItemActionDynamicMelee.Raycast))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_Raycast_ItemActionDynamicMelee(ItemActionDynamic.ItemActionDynamicData _actionData)
|
||||
{
|
||||
_actionData.invData.holdingEntity.MinEventContext.ItemActionData = _actionData;
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Inventory.FireEvent, set current action
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.FireEvent))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_FireEvent_Inventory(Inventory __instance)
|
||||
{
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(__instance.entity);
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Inventory.syncHeldItem, set current action
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.syncHeldItem))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_syncHeldItem_Inventory(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_test = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AnySet));
|
||||
var fld_itemvalue = AccessTools.Field(typeof(MinEventParams), nameof(MinEventParams.ItemValue));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].StoresField(fld_itemvalue) && codes[i - 7].Calls(mtd_test))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(Inventory), nameof(Inventory.entity)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.SetMinEventParamsByEntityInventory))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ItemValue.FireEvent, read current action
|
||||
[HarmonyPatch(typeof(ItemValue), nameof(ItemValue.FireEvent))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_FireEvent_ItemValue(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_index = generator.DeclareLocal(typeof(int));
|
||||
|
||||
FieldInfo fld_action = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.Actions));
|
||||
FieldInfo fld_ammoindex = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.SelectedAmmoTypeIndex));
|
||||
MethodInfo mtd_fireevent = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.FireEvent));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.LoadsField(fld_action) && codes[i + 1].opcode == OpCodes.Ldc_I4_0)
|
||||
{
|
||||
codes[i + 1].opcode = OpCodes.Ldloc_S;
|
||||
codes[i + 1].operand = lbd_index;
|
||||
if (codes[i - 9].opcode == OpCodes.Ret)
|
||||
{
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_2),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetActionIndexByEventParams)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_index)
|
||||
});
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
else if (code.LoadsField(fld_ammoindex))
|
||||
{
|
||||
code.opcode = OpCodes.Call;
|
||||
code.operand = AccessTools.Method(typeof(MultiActionUtils), nameof(MultiActionUtils.GetSelectedAmmoIndexByActionIndex));
|
||||
codes.Insert(i, new CodeInstruction(OpCodes.Ldloc_S, lbd_index));
|
||||
i++;
|
||||
}
|
||||
//action exclude mods
|
||||
else if (code.Calls(mtd_fireevent) && codes[i + 1].opcode != OpCodes.Ldloc_0)
|
||||
{
|
||||
for (int j = i; j >= 0; j--)
|
||||
{
|
||||
if (codes[j].opcode == OpCodes.Brfalse_S || codes[j].opcode == OpCodes.Brfalse)
|
||||
{
|
||||
var label = codes[j].operand;
|
||||
codes.InsertRange(j + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemValue), nameof(ItemValue.type)),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, codes[j + 2].operand),
|
||||
new CodeInstruction(codes[j + 3].opcode, codes[j + 3].operand),
|
||||
new CodeInstruction(OpCodes.Ldelem_Ref),
|
||||
CodeInstruction.LoadField(typeof(ItemValue), nameof(ItemValue.type)),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_index),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.ShouldExcludeTrigger)),
|
||||
new CodeInstruction(OpCodes.Brtrue_S, label)
|
||||
});
|
||||
i += 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//onSelfEquipStop, onSelfHoldingItemCreated, onSelfEquipStart are not available for individual action,
|
||||
|
||||
//some are already set in update or execute action
|
||||
|
||||
#endregion
|
||||
|
||||
#region EffectManager.GetValue patches, set params
|
||||
//set correct action index for ItemValue
|
||||
[HarmonyPatch(typeof(ItemValue), nameof(ItemValue.ModifyValue))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ModifyValue_ItemValue(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_index = generator.DeclareLocal(typeof(int));
|
||||
|
||||
FieldInfo fld_action = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.Actions));
|
||||
FieldInfo fld_ammoindex = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.SelectedAmmoTypeIndex));
|
||||
FieldInfo fld_mods = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.Modifications));
|
||||
FieldInfo fld_cos = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.CosmeticMods));
|
||||
MethodInfo mtd_modify = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.ModifyValue));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.opcode == OpCodes.Stloc_1)
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetActionIndexByEntityEventParams)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_index)
|
||||
});
|
||||
}
|
||||
else if (code.LoadsField(fld_action) && codes[i + 1].opcode == OpCodes.Ldc_I4_0)
|
||||
{
|
||||
codes[i + 1].opcode = OpCodes.Ldloc_S;
|
||||
codes[i + 1].operand = lbd_index;
|
||||
}
|
||||
else if (code.LoadsField(fld_ammoindex))
|
||||
{
|
||||
code.opcode = OpCodes.Call;
|
||||
code.operand = AccessTools.Method(typeof(MultiActionUtils), nameof(MultiActionUtils.GetSelectedAmmoIndexByActionIndex));
|
||||
codes.Insert(i, new CodeInstruction(OpCodes.Ldloc_S, lbd_index));
|
||||
i++;
|
||||
}
|
||||
else if (code.Calls(mtd_modify))
|
||||
{
|
||||
for (int j = i; j >= 0; j--)
|
||||
{
|
||||
if (codes[j].opcode == OpCodes.Brfalse_S || codes[j].opcode == OpCodes.Brfalse)
|
||||
{
|
||||
var label = codes[j].operand;
|
||||
codes.InsertRange(j + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemValue), nameof(ItemValue.type)),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, codes[j + 2].operand),
|
||||
new CodeInstruction(codes[j + 3].opcode, codes[j + 3].operand),
|
||||
new CodeInstruction(OpCodes.Ldelem_Ref),
|
||||
CodeInstruction.LoadField(typeof(ItemValue), nameof(ItemValue.type)),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_index),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.ShouldExcludePassive)),
|
||||
new CodeInstruction(OpCodes.Brtrue_S, label)
|
||||
});
|
||||
i += 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
//only current mode should execute OnHUD
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.OnHUD))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_OnHUD_EntityPlayerLocal(EntityPlayerLocal __instance, out ItemActionData __state)
|
||||
{
|
||||
__state = __instance.MinEventContext.ItemActionData;
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(__instance);
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.OnHUD))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnHUD_EntityPlayerLocal(EntityPlayerLocal __instance, ItemActionData __state)
|
||||
{
|
||||
__instance.MinEventContext.ItemActionData = __state;
|
||||
}
|
||||
|
||||
//for passive value calc
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.guiDrawCrosshair))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_guiDrawCrosshair_EntityPlayerLocal(EntityPlayerLocal __instance)
|
||||
{
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(__instance);
|
||||
return true;
|
||||
}
|
||||
|
||||
//draw crosshair for current action
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.guiDrawCrosshair))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_guiDrawCrosshair_EntityPlayerLocal(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_index = generator.DeclareLocal(typeof(int));
|
||||
|
||||
FieldInfo fld_actiondata = AccessTools.Field(typeof(ItemInventoryData), nameof(ItemInventoryData.actionData));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Stloc_1)
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.GetActionIndexForEntity)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_index)
|
||||
});
|
||||
i += 3;
|
||||
}
|
||||
else if (codes[i].LoadsField(fld_actiondata) && codes[i + 1].opcode == OpCodes.Ldc_I4_0)
|
||||
{
|
||||
codes[i + 1].opcode = OpCodes.Ldloc_S;
|
||||
codes[i + 1].operand = lbd_index;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemAction), nameof(ItemAction.ExecuteBuffActions))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_ExecuteBuffActions_ItemAction(int instigatorId, out (EntityAlive entity, ItemActionData actionData) __state)
|
||||
{
|
||||
__state = default;
|
||||
EntityAlive entity = GameManager.Instance.World.GetEntity(instigatorId) as EntityAlive;
|
||||
if (entity != null)
|
||||
{
|
||||
__state.entity = entity;
|
||||
__state.actionData = entity.MinEventContext.ItemActionData;
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(entity);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemAction), nameof(ItemAction.ExecuteBuffActions))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_ExecuteBuffActions_ItemAction((EntityAlive entity, ItemActionData actionData) __state, bool __runOriginal)
|
||||
{
|
||||
if (__runOriginal && __state.entity != null)
|
||||
__state.entity.MinEventContext.ItemActionData = __state.actionData;
|
||||
}
|
||||
|
||||
//ItemAction.GetDismemberChance already set
|
||||
//ItemActionDynamic.GetExecuteActionTarget not needed
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ItemActionEffects))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_ItemActionEffects_ItemActionLauncher(ItemActionData _actionData, out ItemActionData __state)
|
||||
{
|
||||
__state = _actionData.invData.holdingEntity.MinEventContext.ItemActionData;
|
||||
_actionData.invData.holdingEntity.MinEventContext.ItemActionData = _actionData;
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ItemActionEffects))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_ItemActionEffects_ItemActionLauncher(ItemActionData _actionData, ItemActionData __state)
|
||||
{
|
||||
_actionData.invData.holdingEntity.MinEventContext.ItemActionData = __state;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.ClampAmmoCount))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_ClampAmmoCount_ItemActionLauncher(ItemActionLauncher.ItemActionDataLauncher actionData, out ItemActionData __state)
|
||||
{
|
||||
__state = actionData.invData.holdingEntity.MinEventContext.ItemActionData;
|
||||
actionData.invData.holdingEntity.MinEventContext.ItemActionData = actionData;
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionLauncher), nameof(ItemActionLauncher.ClampAmmoCount))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_ClampAmmoCount_ItemActionLauncher(ItemActionLauncher.ItemActionDataLauncher actionData, ItemActionData __state)
|
||||
{
|
||||
actionData.invData.holdingEntity.MinEventContext.ItemActionData = __state;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EffectManager.GetValuesAndSources patches, set params
|
||||
|
||||
[HarmonyPatch(typeof(EntityStats), nameof(EntityStats.Update))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_Update_EntityStats(EntityStats __instance)
|
||||
{
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(__instance.m_entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
//set correct action index for ItemValue
|
||||
[HarmonyPatch(typeof(ItemValue), nameof(ItemValue.GetModifiedValueData))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_GetModifiedValueData_ItemValue(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_index = generator.DeclareLocal(typeof(int));
|
||||
|
||||
FieldInfo fld_action = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.Actions));
|
||||
FieldInfo fld_ammoindex = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.SelectedAmmoTypeIndex));
|
||||
FieldInfo fld_mods = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.Modifications));
|
||||
FieldInfo fld_cos = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.CosmeticMods));
|
||||
MethodInfo mtd_getvalue = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.GetModifiedValueData));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.opcode == OpCodes.Stloc_0)
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_3),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetActionIndexByEntityEventParams)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_index)
|
||||
});
|
||||
}
|
||||
else if (code.LoadsField(fld_action) && codes[i + 1].opcode == OpCodes.Ldc_I4_0)
|
||||
{
|
||||
codes[i + 1].opcode = OpCodes.Ldloc_S;
|
||||
codes[i + 1].operand = lbd_index;
|
||||
}
|
||||
else if (code.LoadsField(fld_ammoindex))
|
||||
{
|
||||
code.opcode = OpCodes.Call;
|
||||
code.operand = AccessTools.Method(typeof(MultiActionUtils), nameof(MultiActionUtils.GetSelectedAmmoIndexByActionIndex));
|
||||
codes.Insert(i, new CodeInstruction(OpCodes.Ldloc_S, lbd_index));
|
||||
i++;
|
||||
}
|
||||
else if (code.Calls(mtd_getvalue) && codes[i + 1].opcode != OpCodes.Ldloc_0)
|
||||
{
|
||||
for (int j = i; j >= 0; j--)
|
||||
{
|
||||
if (codes[j].opcode == OpCodes.Brfalse_S || codes[j].opcode == OpCodes.Brfalse)
|
||||
{
|
||||
var label = codes[j].operand;
|
||||
codes.InsertRange(j + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemValue), nameof(ItemValue.type)),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, codes[j + 2].operand),
|
||||
new CodeInstruction(codes[j + 3].opcode, codes[j + 3].operand),
|
||||
new CodeInstruction(OpCodes.Ldelem_Ref),
|
||||
CodeInstruction.LoadField(typeof(ItemValue), nameof(ItemValue.type)),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_index),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.ShouldExcludePassive)),
|
||||
new CodeInstruction(OpCodes.Brtrue_S, label)
|
||||
});
|
||||
i += 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region Misc
|
||||
//load correct property for melee
|
||||
[HarmonyPatch(typeof(AnimatorMeleeAttackState), nameof(AnimatorMeleeAttackState.OnStateEnter))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_OnStateEnter_AnimatorMeleeAttackState(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
var fld_actionindex = AccessTools.Field(typeof(AnimatorMeleeAttackState), nameof(AnimatorMeleeAttackState.actionIndex));
|
||||
MethodInfo mtd_getvalue = AccessTools.Method(typeof(EffectManager), nameof(EffectManager.GetValue));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.LoadsField(fld_actionindex) && codes[i + 2].opcode == OpCodes.Ldstr)
|
||||
{
|
||||
string property = codes[i + 2].operand.ToString();
|
||||
property = property.Split('.')[1];
|
||||
codes.RemoveRange(i + 1, 4);
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldstr, property),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetPropertyName))
|
||||
});
|
||||
i -= 2;
|
||||
}
|
||||
else if (code.Calls(mtd_getvalue))
|
||||
{
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(AnimatorMeleeAttackState), "entity"),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(AnimatorMeleeAttackState), "actionIndex"),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.SetMinEventParamsActionData))
|
||||
});
|
||||
i += 5;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
//make sure it's set to current action after for loop
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.OnHoldingUpdate))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnHoldingUpdate_ItemClass(ItemInventoryData _data)
|
||||
{
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(_data.holdingEntity);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.StopHolding))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_StopHolding_ItemClass(ItemInventoryData _data)
|
||||
{
|
||||
if (_data.holdingEntity != null)
|
||||
{
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(_data.holdingEntity);
|
||||
MultiActionManager.SetMappingForEntity(_data.holdingEntity.entityId, null);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.StartHolding))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_StartHolding_ItemClass(ItemInventoryData _data)
|
||||
{
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(_data.holdingEntity);
|
||||
}
|
||||
|
||||
//should be fixed in Harmony 2.12.0.0
|
||||
//[HarmonyPatch(typeof(ItemClassesFromXml), nameof(ItemClassesFromXml.parseItem))]
|
||||
//[HarmonyPrefix]
|
||||
//private static bool Prefix_parseItem_ItemClassesFromXml(XElement _node)
|
||||
//{
|
||||
// DynamicProperties dynamicProperties = new DynamicProperties();
|
||||
// string attribute = _node.GetAttribute("name");
|
||||
// if (attribute.Length == 0)
|
||||
// {
|
||||
// throw new Exception("Attribute 'name' missing on item");
|
||||
// }
|
||||
// //here
|
||||
// List<IRequirement>[] array = new List<IRequirement>[ItemClass.cMaxActionNames];
|
||||
// for (int i = 0; i < array.Length; i++)
|
||||
// {
|
||||
// array[i] = new List<IRequirement>();
|
||||
// }
|
||||
|
||||
// foreach (XElement item in _node.Elements("property"))
|
||||
// {
|
||||
// dynamicProperties.Add(item);
|
||||
// string attribute2 = item.GetAttribute("class");
|
||||
// if (attribute2.StartsWith("Action"))
|
||||
// {
|
||||
// int num = attribute2[attribute2.Length - 1] - '0';
|
||||
// array[num].AddRange(RequirementBase.ParseRequirements(item));
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("Extends"))
|
||||
// {
|
||||
// string text = dynamicProperties.Values["Extends"];
|
||||
// ItemClass itemClass = ItemClass.GetItemClass(text);
|
||||
// if (itemClass == null)
|
||||
// {
|
||||
// throw new Exception($"Extends item {text} is not specified for item {attribute}'");
|
||||
// }
|
||||
|
||||
// HashSet<string> hashSet = new HashSet<string> { Block.PropCreativeMode };
|
||||
// if (dynamicProperties.Params1.ContainsKey("Extends"))
|
||||
// {
|
||||
// string[] array2 = dynamicProperties.Params1["Extends"].Split(new[] { ',' }, StringSplitOptions.None);
|
||||
// foreach (string text2 in array2)
|
||||
// {
|
||||
// hashSet.Add(text2.Trim());
|
||||
// }
|
||||
// }
|
||||
|
||||
// DynamicProperties dynamicProperties2 = new DynamicProperties();
|
||||
// dynamicProperties2.CopyFrom(itemClass.Properties, hashSet);
|
||||
// dynamicProperties2.CopyFrom(dynamicProperties);
|
||||
// dynamicProperties = dynamicProperties2;
|
||||
// }
|
||||
|
||||
// ItemClass itemClass2;
|
||||
// if (dynamicProperties.Values.ContainsKey("Class"))
|
||||
// {
|
||||
// string text3 = dynamicProperties.Values["Class"];
|
||||
// if (!text3.Contains(","))
|
||||
// {
|
||||
// text3 += ",Assembly-CSharp";
|
||||
// }
|
||||
// try
|
||||
// {
|
||||
// itemClass2 = (ItemClass)Activator.CreateInstance(Type.GetType(text3));
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
// throw new Exception("No item class '" + text3 + " found!");
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// itemClass2 = new ItemClass();
|
||||
// }
|
||||
|
||||
// itemClass2.Properties = dynamicProperties;
|
||||
// if (dynamicProperties.Params1.ContainsKey("Extends"))
|
||||
// {
|
||||
// string text4 = dynamicProperties.Values["Extends"];
|
||||
// if (ItemClass.GetItemClass(text4) == null)
|
||||
// {
|
||||
// throw new Exception($"Extends item {text4} is not specified for item {attribute}'");
|
||||
// }
|
||||
// }
|
||||
|
||||
// itemClass2.Effects = MinEffectController.ParseXml(_node, null, MinEffectController.SourceParentType.ItemClass, itemClass2.Id);
|
||||
// itemClass2.SetName(attribute);
|
||||
// itemClass2.setLocalizedItemName(Localization.Get(attribute));
|
||||
// if (dynamicProperties.Values.ContainsKey("Stacknumber"))
|
||||
// {
|
||||
// itemClass2.Stacknumber = new DataItem<int>(int.Parse(dynamicProperties.Values["Stacknumber"]));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// itemClass2.Stacknumber = new DataItem<int>(500);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("Canhold"))
|
||||
// {
|
||||
// itemClass2.SetCanHold(StringParsers.ParseBool(dynamicProperties.Values["Canhold"]));
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("Candrop"))
|
||||
// {
|
||||
// itemClass2.SetCanDrop(StringParsers.ParseBool(dynamicProperties.Values["Candrop"]));
|
||||
// }
|
||||
|
||||
// if (!dynamicProperties.Values.ContainsKey("Material"))
|
||||
// {
|
||||
// throw new Exception("Attribute 'material' missing on item '" + attribute + "'");
|
||||
// }
|
||||
|
||||
// itemClass2.MadeOfMaterial = MaterialBlock.fromString(dynamicProperties.Values["Material"]);
|
||||
// if (itemClass2.MadeOfMaterial == null)
|
||||
// {
|
||||
// throw new Exception("Attribute 'material' '" + dynamicProperties.Values["Material"] + "' refers to not existing material in item '" + attribute + "'");
|
||||
// }
|
||||
|
||||
// if (!dynamicProperties.Values.ContainsKey("Meshfile") && itemClass2.CanHold())
|
||||
// {
|
||||
// throw new Exception("Attribute 'Meshfile' missing on item '" + attribute + "'");
|
||||
// }
|
||||
|
||||
// itemClass2.MeshFile = dynamicProperties.Values["Meshfile"];
|
||||
// DataLoader.PreloadBundle(itemClass2.MeshFile);
|
||||
// StringParsers.TryParseFloat(dynamicProperties.Values["StickyOffset"], out itemClass2.StickyOffset);
|
||||
// StringParsers.TryParseFloat(dynamicProperties.Values["StickyColliderRadius"], out itemClass2.StickyColliderRadius);
|
||||
// StringParsers.TryParseSInt32(dynamicProperties.Values["StickyColliderUp"], out itemClass2.StickyColliderUp);
|
||||
// StringParsers.TryParseFloat(dynamicProperties.Values["StickyColliderLength"], out itemClass2.StickyColliderLength);
|
||||
// itemClass2.StickyMaterial = dynamicProperties.Values["StickyMaterial"];
|
||||
// if (dynamicProperties.Values.ContainsKey("ImageEffectOnActive"))
|
||||
// {
|
||||
// itemClass2.ImageEffectOnActive = new DataItem<string>(dynamicProperties.Values["ImageEffectOnActive"]);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("Active"))
|
||||
// {
|
||||
// itemClass2.Active = new DataItem<bool>(_startValue: false);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey(ItemClass.PropIsSticky))
|
||||
// {
|
||||
// itemClass2.IsSticky = StringParsers.ParseBool(dynamicProperties.Values[ItemClass.PropIsSticky]);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("DropMeshfile") && itemClass2.CanHold())
|
||||
// {
|
||||
// itemClass2.DropMeshFile = dynamicProperties.Values["DropMeshfile"];
|
||||
// DataLoader.PreloadBundle(itemClass2.DropMeshFile);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("HandMeshfile") && itemClass2.CanHold())
|
||||
// {
|
||||
// itemClass2.HandMeshFile = dynamicProperties.Values["HandMeshfile"];
|
||||
// DataLoader.PreloadBundle(itemClass2.HandMeshFile);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("HoldType"))
|
||||
// {
|
||||
// string s = dynamicProperties.Values["HoldType"];
|
||||
// int result = 0;
|
||||
// if (!int.TryParse(s, out result))
|
||||
// {
|
||||
// throw new Exception("Cannot parse attribute hold_type for item '" + attribute + "'");
|
||||
// }
|
||||
|
||||
// itemClass2.HoldType = new DataItem<int>(result);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("RepairTools"))
|
||||
// {
|
||||
// string[] array3 = dynamicProperties.Values["RepairTools"].Replace(" ", "").Split(new[] { ',' }, StringSplitOptions.None);
|
||||
// DataItem<string>[] array4 = new DataItem<string>[array3.Length];
|
||||
// for (int k = 0; k < array3.Length; k++)
|
||||
// {
|
||||
// array4[k] = new DataItem<string>(array3[k]);
|
||||
// }
|
||||
|
||||
// itemClass2.RepairTools = new ItemData.DataItemArrayRepairTools(array4);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("RepairAmount"))
|
||||
// {
|
||||
// int result2 = 0;
|
||||
// int.TryParse(dynamicProperties.Values["RepairAmount"], out result2);
|
||||
// itemClass2.RepairAmount = new DataItem<int>(result2);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("RepairTime"))
|
||||
// {
|
||||
// float _result = 0f;
|
||||
// StringParsers.TryParseFloat(dynamicProperties.Values["RepairTime"], out _result);
|
||||
// itemClass2.RepairTime = new DataItem<float>(_result);
|
||||
// }
|
||||
// else if (itemClass2.RepairAmount != null)
|
||||
// {
|
||||
// itemClass2.RepairTime = new DataItem<float>(1f);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("Degradation"))
|
||||
// {
|
||||
// itemClass2.MaxUseTimes = new DataItem<int>(int.Parse(dynamicProperties.Values["Degradation"]));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// itemClass2.MaxUseTimes = new DataItem<int>(0);
|
||||
// itemClass2.MaxUseTimesBreaksAfter = new DataItem<bool>(_startValue: false);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("DegradationBreaksAfter"))
|
||||
// {
|
||||
// itemClass2.MaxUseTimesBreaksAfter = new DataItem<bool>(StringParsers.ParseBool(dynamicProperties.Values["DegradationBreaksAfter"]));
|
||||
// }
|
||||
// else if (dynamicProperties.Values.ContainsKey("Degradation"))
|
||||
// {
|
||||
// itemClass2.MaxUseTimesBreaksAfter = new DataItem<bool>(_startValue: true);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Values.ContainsKey("EconomicValue"))
|
||||
// {
|
||||
// itemClass2.EconomicValue = StringParsers.ParseFloat(dynamicProperties.Values["EconomicValue"]);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties.Classes.ContainsKey("Preview"))
|
||||
// {
|
||||
// DynamicProperties dynamicProperties3 = dynamicProperties.Classes["Preview"];
|
||||
// itemClass2.Preview = new PreviewData();
|
||||
// if (dynamicProperties3.Values.ContainsKey("Zoom"))
|
||||
// {
|
||||
// itemClass2.Preview.Zoom = new DataItem<int>(int.Parse(dynamicProperties3.Values["Zoom"]));
|
||||
// }
|
||||
|
||||
// if (dynamicProperties3.Values.ContainsKey("Pos"))
|
||||
// {
|
||||
// itemClass2.Preview.Pos = new DataItem<Vector2>(StringParsers.ParseVector2(dynamicProperties3.Values["Pos"]));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// itemClass2.Preview.Pos = new DataItem<Vector2>(Vector2.zero);
|
||||
// }
|
||||
|
||||
// if (dynamicProperties3.Values.ContainsKey("Rot"))
|
||||
// {
|
||||
// itemClass2.Preview.Rot = new DataItem<Vector3>(StringParsers.ParseVector3(dynamicProperties3.Values["Rot"]));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// itemClass2.Preview.Rot = new DataItem<Vector3>(Vector3.zero);
|
||||
// }
|
||||
// }
|
||||
|
||||
// for (int l = 0; l < itemClass2.Actions.Length; l++)
|
||||
// {
|
||||
// string text5 = ItemClass.itemActionNames[l];
|
||||
// if (dynamicProperties.Classes.ContainsKey(text5))
|
||||
// {
|
||||
// if (!dynamicProperties.Values.ContainsKey(text5 + ".Class"))
|
||||
// {
|
||||
// throw new Exception("No class attribute found on " + text5 + " in item with '" + attribute + "'");
|
||||
// }
|
||||
|
||||
// string text6 = dynamicProperties.Values[text5 + ".Class"];
|
||||
// ItemAction itemAction;
|
||||
// try
|
||||
// {
|
||||
// itemAction = (ItemAction)Activator.CreateInstance(ReflectionHelpers.GetTypeWithPrefix("ItemAction", text6));
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
// throw new Exception("ItemAction class '" + text6 + " could not be instantiated");
|
||||
// }
|
||||
|
||||
// itemAction.item = itemClass2;
|
||||
// itemAction.ActionIndex = l;
|
||||
// itemAction.ReadFrom(dynamicProperties.Classes[text5]);
|
||||
// if (array[l].Count > 0)
|
||||
// {
|
||||
// itemAction.ExecutionRequirements = array[l];
|
||||
// }
|
||||
|
||||
// itemClass2.Actions[l] = itemAction;
|
||||
// }
|
||||
// }
|
||||
|
||||
// itemClass2.Init();
|
||||
// return false;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// fix requirement array count
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyPatch(typeof(ItemClassesFromXml), nameof(ItemClassesFromXml.parseItem))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_parseItem_ItemClassesFromXml(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
bool isLastInsThrow = false;
|
||||
foreach (var code in instructions)
|
||||
{
|
||||
if (isLastInsThrow)
|
||||
{
|
||||
isLastInsThrow = false;
|
||||
if (code.opcode == OpCodes.Ldc_I4_3)
|
||||
{
|
||||
code.opcode = OpCodes.Ldc_I4_5;
|
||||
}
|
||||
}
|
||||
if (code.opcode == OpCodes.Throw)
|
||||
{
|
||||
isLastInsThrow = true;
|
||||
}
|
||||
yield return code;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemModificationsFromXml), nameof(ItemModificationsFromXml.parseItem))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_parseItem_ItemModificationsFromXml(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
for (int i = 0; i < codes.Count - 1; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Ldc_I4_3 && codes[i + 1].opcode == OpCodes.Newarr)
|
||||
{
|
||||
codes[i].opcode = OpCodes.Ldc_I4_5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
/*
|
||||
[HarmonyPatch(typeof(ItemClassesFromXml), nameof(ItemClassesFromXml.parseItem))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_parseItem_ItemClassesFromXml(XElement _node)
|
||||
{
|
||||
//throw new Exception("Exception thrown from here!");
|
||||
DynamicProperties dynamicProperties = new DynamicProperties();
|
||||
string attribute = _node.GetAttribute("name");
|
||||
if (attribute.Length == 0)
|
||||
{
|
||||
throw new Exception("Attribute 'name' missing on item");
|
||||
}
|
||||
//Log.Out($"Parsing item {attribute}...");
|
||||
List<IRequirement>[] array = new List<IRequirement>[5];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = new List<IRequirement>();
|
||||
}
|
||||
|
||||
foreach (XElement item in _node.Elements("property"))
|
||||
{
|
||||
dynamicProperties.Add(item);
|
||||
string attribute2 = item.GetAttribute("class");
|
||||
if (attribute2.StartsWith("Action"))
|
||||
{
|
||||
int num = attribute2[attribute2.Length - 1] - 48;
|
||||
array[num].AddRange(RequirementBase.ParseRequirements(item));
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("Extends"))
|
||||
{
|
||||
string text = dynamicProperties.Values["Extends"];
|
||||
ItemClass itemClass = ItemClass.GetItemClass(text);
|
||||
if (itemClass == null)
|
||||
{
|
||||
throw new Exception($"Extends item {text} is not specified for item {attribute}'");
|
||||
}
|
||||
|
||||
HashSet<string> hashSet = new HashSet<string> { Block.PropCreativeMode };
|
||||
if (dynamicProperties.Params1.ContainsKey("Extends"))
|
||||
{
|
||||
string[] array2 = dynamicProperties.Params1["Extends"].Split(',');
|
||||
foreach (string text2 in array2)
|
||||
{
|
||||
hashSet.Add(text2.Trim());
|
||||
}
|
||||
}
|
||||
|
||||
DynamicProperties dynamicProperties2 = new DynamicProperties();
|
||||
dynamicProperties2.CopyFrom(itemClass.Properties, hashSet);
|
||||
dynamicProperties2.CopyFrom(dynamicProperties);
|
||||
dynamicProperties = dynamicProperties2;
|
||||
}
|
||||
|
||||
ItemClass itemClass2;
|
||||
if (dynamicProperties.Values.ContainsKey("Class"))
|
||||
{
|
||||
string text3 = dynamicProperties.Values["Class"];
|
||||
if (!text3.Contains(","))
|
||||
{
|
||||
text3 += ",Assembly-CSharp";
|
||||
}
|
||||
try
|
||||
{
|
||||
itemClass2 = (ItemClass)Activator.CreateInstance(Type.GetType(text3));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new Exception("No item class '" + text3 + "' found!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
itemClass2 = new ItemClass();
|
||||
}
|
||||
|
||||
itemClass2.Properties = dynamicProperties;
|
||||
if (dynamicProperties.Params1.ContainsKey("Extends"))
|
||||
{
|
||||
string text4 = dynamicProperties.Values["Extends"];
|
||||
if (ItemClass.GetItemClass(text4) == null)
|
||||
{
|
||||
throw new Exception($"Extends item {text4} is not specified for item {attribute}'");
|
||||
}
|
||||
}
|
||||
|
||||
itemClass2.Effects = MinEffectController.ParseXml(_node, null, MinEffectController.SourceParentType.ItemClass, itemClass2.Id);
|
||||
itemClass2.SetName(attribute);
|
||||
itemClass2.setLocalizedItemName(Localization.Get(attribute));
|
||||
if (dynamicProperties.Values.ContainsKey("Stacknumber"))
|
||||
{
|
||||
itemClass2.Stacknumber = new DataItem<int>(int.Parse(dynamicProperties.Values["Stacknumber"]));
|
||||
}
|
||||
else
|
||||
{
|
||||
itemClass2.Stacknumber = new DataItem<int>(500);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("Canhold"))
|
||||
{
|
||||
itemClass2.SetCanHold(StringParsers.ParseBool(dynamicProperties.Values["Canhold"]));
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("Candrop"))
|
||||
{
|
||||
itemClass2.SetCanDrop(StringParsers.ParseBool(dynamicProperties.Values["Candrop"]));
|
||||
}
|
||||
|
||||
if (!dynamicProperties.Values.ContainsKey("Material"))
|
||||
{
|
||||
throw new Exception("Attribute 'material' missing on item '" + attribute + "'");
|
||||
}
|
||||
|
||||
itemClass2.MadeOfMaterial = MaterialBlock.fromString(dynamicProperties.Values["Material"]);
|
||||
if (itemClass2.MadeOfMaterial == null)
|
||||
{
|
||||
throw new Exception("Attribute 'material' '" + dynamicProperties.Values["Material"] + "' refers to not existing material in item '" + attribute + "'");
|
||||
}
|
||||
|
||||
if (!dynamicProperties.Values.ContainsKey("Meshfile") && itemClass2.CanHold())
|
||||
{
|
||||
throw new Exception("Attribute 'Meshfile' missing on item '" + attribute + "'");
|
||||
}
|
||||
|
||||
itemClass2.MeshFile = dynamicProperties.Values["Meshfile"];
|
||||
DataLoader.PreloadBundle(itemClass2.MeshFile);
|
||||
StringParsers.TryParseFloat(dynamicProperties.Values["StickyOffset"], out itemClass2.StickyOffset);
|
||||
StringParsers.TryParseFloat(dynamicProperties.Values["StickyColliderRadius"], out itemClass2.StickyColliderRadius);
|
||||
StringParsers.TryParseSInt32(dynamicProperties.Values["StickyColliderUp"], out itemClass2.StickyColliderUp);
|
||||
StringParsers.TryParseFloat(dynamicProperties.Values["StickyColliderLength"], out itemClass2.StickyColliderLength);
|
||||
itemClass2.StickyMaterial = dynamicProperties.Values["StickyMaterial"];
|
||||
if (dynamicProperties.Values.ContainsKey("ImageEffectOnActive"))
|
||||
{
|
||||
itemClass2.ImageEffectOnActive = new DataItem<string>(dynamicProperties.Values["ImageEffectOnActive"]);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("Active"))
|
||||
{
|
||||
itemClass2.Active = new DataItem<bool>(_startValue: false);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey(ItemClass.PropIsSticky))
|
||||
{
|
||||
itemClass2.IsSticky = StringParsers.ParseBool(dynamicProperties.Values[ItemClass.PropIsSticky]);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("DropMeshfile") && itemClass2.CanHold())
|
||||
{
|
||||
itemClass2.DropMeshFile = dynamicProperties.Values["DropMeshfile"];
|
||||
DataLoader.PreloadBundle(itemClass2.DropMeshFile);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("HandMeshfile") && itemClass2.CanHold())
|
||||
{
|
||||
itemClass2.HandMeshFile = dynamicProperties.Values["HandMeshfile"];
|
||||
DataLoader.PreloadBundle(itemClass2.HandMeshFile);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("HoldType"))
|
||||
{
|
||||
string s = dynamicProperties.Values["HoldType"];
|
||||
int result = 0;
|
||||
if (!int.TryParse(s, out result))
|
||||
{
|
||||
throw new Exception("Cannot parse attribute hold_type for item '" + attribute + "'");
|
||||
}
|
||||
|
||||
itemClass2.HoldType = new DataItem<int>(result);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("RepairTools"))
|
||||
{
|
||||
string[] array3 = dynamicProperties.Values["RepairTools"].Replace(" ", "").Split(',');
|
||||
DataItem<string>[] array4 = new DataItem<string>[array3.Length];
|
||||
for (int k = 0; k < array3.Length; k++)
|
||||
{
|
||||
array4[k] = new DataItem<string>(array3[k]);
|
||||
}
|
||||
|
||||
itemClass2.RepairTools = new ItemData.DataItemArrayRepairTools(array4);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("RepairAmount"))
|
||||
{
|
||||
int result2 = 0;
|
||||
int.TryParse(dynamicProperties.Values["RepairAmount"], out result2);
|
||||
itemClass2.RepairAmount = new DataItem<int>(result2);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("RepairTime"))
|
||||
{
|
||||
float _result = 0f;
|
||||
StringParsers.TryParseFloat(dynamicProperties.Values["RepairTime"], out _result);
|
||||
itemClass2.RepairTime = new DataItem<float>(_result);
|
||||
}
|
||||
else if (itemClass2.RepairAmount != null)
|
||||
{
|
||||
itemClass2.RepairTime = new DataItem<float>(1f);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("Degradation"))
|
||||
{
|
||||
itemClass2.MaxUseTimes = new DataItem<int>(int.Parse(dynamicProperties.Values["Degradation"]));
|
||||
}
|
||||
else
|
||||
{
|
||||
itemClass2.MaxUseTimes = new DataItem<int>(0);
|
||||
itemClass2.MaxUseTimesBreaksAfter = new DataItem<bool>(_startValue: false);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("DegradationBreaksAfter"))
|
||||
{
|
||||
itemClass2.MaxUseTimesBreaksAfter = new DataItem<bool>(StringParsers.ParseBool(dynamicProperties.Values["DegradationBreaksAfter"]));
|
||||
}
|
||||
else if (dynamicProperties.Values.ContainsKey("Degradation"))
|
||||
{
|
||||
itemClass2.MaxUseTimesBreaksAfter = new DataItem<bool>(_startValue: true);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Values.ContainsKey("EconomicValue"))
|
||||
{
|
||||
itemClass2.EconomicValue = StringParsers.ParseFloat(dynamicProperties.Values["EconomicValue"]);
|
||||
}
|
||||
|
||||
if (dynamicProperties.Classes.ContainsKey("Preview"))
|
||||
{
|
||||
DynamicProperties dynamicProperties3 = dynamicProperties.Classes["Preview"];
|
||||
itemClass2.Preview = new PreviewData();
|
||||
if (dynamicProperties3.Values.ContainsKey("Zoom"))
|
||||
{
|
||||
itemClass2.Preview.Zoom = new DataItem<int>(int.Parse(dynamicProperties3.Values["Zoom"]));
|
||||
}
|
||||
|
||||
if (dynamicProperties3.Values.ContainsKey("Pos"))
|
||||
{
|
||||
itemClass2.Preview.Pos = new DataItem<Vector2>(StringParsers.ParseVector2(dynamicProperties3.Values["Pos"]));
|
||||
}
|
||||
else
|
||||
{
|
||||
itemClass2.Preview.Pos = new DataItem<Vector2>(Vector2.zero);
|
||||
}
|
||||
|
||||
if (dynamicProperties3.Values.ContainsKey("Rot"))
|
||||
{
|
||||
itemClass2.Preview.Rot = new DataItem<Vector3>(StringParsers.ParseVector3(dynamicProperties3.Values["Rot"]));
|
||||
}
|
||||
else
|
||||
{
|
||||
itemClass2.Preview.Rot = new DataItem<Vector3>(Vector3.zero);
|
||||
}
|
||||
}
|
||||
|
||||
for (int l = 0; l < itemClass2.Actions.Length; l++)
|
||||
{
|
||||
string text5 = ItemClass.itemActionNames[l];
|
||||
if (dynamicProperties.Classes.ContainsKey(text5))
|
||||
{
|
||||
if (!dynamicProperties.Values.ContainsKey(text5 + ".Class"))
|
||||
{
|
||||
throw new Exception("No class attribute found on " + text5 + " in item with '" + attribute + "'");
|
||||
}
|
||||
|
||||
string text6 = dynamicProperties.Values[text5 + ".Class"];
|
||||
ItemAction itemAction;
|
||||
try
|
||||
{
|
||||
itemAction = (ItemAction)Activator.CreateInstance(ReflectionHelpers.GetTypeWithPrefix("ItemAction", text6));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new Exception("ItemAction class '" + text6 + " could not be instantiated");
|
||||
}
|
||||
|
||||
itemAction.item = itemClass2;
|
||||
itemAction.ActionIndex = l;
|
||||
itemAction.ReadFrom(dynamicProperties.Classes[text5]);
|
||||
if (array[l].Count > 0)
|
||||
{
|
||||
itemAction.ExecutionRequirements = array[l];
|
||||
}
|
||||
|
||||
itemClass2.Actions[l] = itemAction;
|
||||
}
|
||||
}
|
||||
|
||||
itemClass2.Init();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.onInventoryChanged))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_onInventoryChanged_Inventory(Inventory __instance)
|
||||
{
|
||||
if (__instance.entity != null)
|
||||
MultiActionManager.UpdateLocalMetaSave(__instance.entity.entityId);
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region Action mode handling
|
||||
[HarmonyPatch(typeof(NetPackagePlayerStats), nameof(NetPackagePlayerStats.ProcessPackage))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ProcessPackage_NetPackagePlayerStats(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_entityid = AccessTools.Field(typeof(NetPackagePlayerStats), nameof(NetPackagePlayerStats.entityId));
|
||||
var fld_itemstack = AccessTools.Field(typeof(NetPackagePlayerStats), nameof(NetPackagePlayerStats.holdingItemStack));
|
||||
codes.InsertRange(codes.Count - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, fld_entityid),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, fld_itemstack),
|
||||
CodeInstruction.Call(typeof(MultiActionPatches), nameof(CheckItemValueMode))
|
||||
});
|
||||
|
||||
return codes;
|
||||
}
|
||||
[HarmonyPatch(typeof(NetPackageHoldingItem), nameof(NetPackageHoldingItem.ProcessPackage))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ProcessPackage_NetPackageHoldingItem(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_entityid = AccessTools.Field(typeof(NetPackagePlayerStats), nameof(NetPackageHoldingItem.entityId));
|
||||
var fld_itemstack = AccessTools.Field(typeof(NetPackagePlayerStats), nameof(NetPackageHoldingItem.holdingItemStack));
|
||||
codes.InsertRange(codes.Count - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, fld_entityid),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, fld_itemstack),
|
||||
CodeInstruction.Call(typeof(MultiActionPatches), nameof(CheckItemValueMode))
|
||||
});
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static void CheckItemValueMode(int entityId, ItemStack holdingItemStack)
|
||||
{
|
||||
ItemValue itemValue = holdingItemStack.itemValue;
|
||||
if (itemValue.HasMetadata(MultiActionMapping.STR_MULTI_ACTION_INDEX))
|
||||
{
|
||||
int mode = (int)itemValue.GetMetadata(MultiActionMapping.STR_MULTI_ACTION_INDEX);
|
||||
if (MultiActionManager.SetModeForEntity(entityId, mode) && ConnectionManager.Instance.IsServer)
|
||||
{
|
||||
ConnectionManager.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageEntityActionIndex>().Setup(entityId, mode), false, -1, entityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.UpdateTick))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_UpdateTick_GameManager(GameManager __instance)
|
||||
{
|
||||
if (MultiActionManager.LocalModeChanged && __instance.m_World != null)
|
||||
{
|
||||
MultiActionManager.LocalModeChanged = false;
|
||||
int playerID = __instance.m_World.GetPrimaryPlayerId();
|
||||
if (ConnectionManager.Instance.IsClient)
|
||||
{
|
||||
ConnectionManager.Instance.SendToServer(NetPackageManager.GetPackage<NetPackageEntityActionIndex>().Setup(playerID, MultiActionManager.GetModeForEntity(playerID)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ConnectionManager.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageEntityActionIndex>().Setup(playerID, MultiActionManager.GetModeForEntity(playerID)), false, -1, playerID);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Input Handling
|
||||
[HarmonyPatch(typeof(PlayerMoveController), nameof(PlayerMoveController.Update))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_Update_PlayerMoveController(PlayerMoveController __instance)
|
||||
{
|
||||
if (DroneManager.Debug_LocalControl || !__instance.gameManager.gameStateManager.IsGameStarted() || GameStats.GetInt(EnumGameStats.GameState) != 1)
|
||||
return true;
|
||||
|
||||
bool isUIOpen = __instance.windowManager.IsCursorWindowOpen() || __instance.windowManager.IsInputActive() || __instance.windowManager.IsModalWindowOpen();
|
||||
|
||||
MultiActionManager.UpdateLocalInput(__instance.entityPlayerLocal, __instance.playerInput, isUIOpen, Time.deltaTime);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HUD display
|
||||
/// <summary>
|
||||
/// redirect check to alternative action module
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyPatch(typeof(XUiC_HUDStatBar), nameof(XUiC_HUDStatBar.HasChanged))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_HasChanged_XUiC_HUDStatBar(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
MethodInfo mtd_edittool = AccessTools.Method(typeof(ItemAction), nameof(ItemAction.IsEditingTool));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.Calls(mtd_edittool))
|
||||
{
|
||||
codes.RemoveRange(i - 1, 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_HUDStatBar), nameof(XUiC_HUDStatBar.SetupActiveItemEntry))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetupActiveItemEntry_XUiC_HUDStatBar(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var lbd_index = generator.DeclareLocal(typeof(int));
|
||||
FieldInfo fld_action = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.Actions));
|
||||
FieldInfo fld_ammoindex = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.SelectedAmmoTypeIndex));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_action))
|
||||
{
|
||||
codes.RemoveAt(i + 1);
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_2),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetActionIndexByMetaData)),
|
||||
new CodeInstruction(OpCodes.Dup),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_index)
|
||||
});
|
||||
i += 3;
|
||||
}
|
||||
else if (codes[i].LoadsField(fld_ammoindex))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = AccessTools.Method(typeof(MultiActionUtils), nameof(MultiActionUtils.GetSelectedAmmoIndexByActionIndex));
|
||||
codes.Insert(i, new CodeInstruction(OpCodes.Ldloc_S, lbd_index));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_Radial), nameof(XUiC_Radial.handleActivatableItemCommand))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_handleActivatableItemCommand_XUiC_Radial(XUiC_Radial _sender)
|
||||
{
|
||||
EntityPlayerLocal entityPlayer = _sender.xui.playerUI.entityPlayer;
|
||||
MultiActionUtils.SetMinEventParamsByEntityInventory(entityPlayer);
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_ItemInfoWindow), nameof(XUiC_ItemInfoWindow.GetBindingValue))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_GetBindingValue_XUiC_ItemInfoWindow(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_actions = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.Actions));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_actions) && codes[i + 1].opcode == OpCodes.Ldc_I4_0)
|
||||
{
|
||||
codes.RemoveAt(i + 1);
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(XUiC_ItemInfoWindow), nameof(XUiC_ItemInfoWindow.itemStack)),
|
||||
CodeInstruction.LoadField(typeof(ItemStack), nameof(ItemStack.itemValue)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetActionIndexByMetaData))
|
||||
});
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Cancel reload on switching item
|
||||
//redirect these calls to action 0 and handle them in alternative module
|
||||
//may change in the future
|
||||
[HarmonyPatch(typeof(PlayerMoveController), nameof(PlayerMoveController.Update))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Update_PlayerMoveController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
MethodInfo mtd_getgun = AccessTools.Method(typeof(Inventory), nameof(Inventory.GetHoldingGun));
|
||||
MethodInfo mtd_getprimary = AccessTools.Method(typeof(Inventory), nameof(Inventory.GetHoldingPrimary));
|
||||
FieldInfo fld_reload = AccessTools.Field(typeof(PlayerActionsPermanent), nameof(PlayerActionsPermanent.Reload));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_getgun))
|
||||
{
|
||||
codes[i].operand = mtd_getprimary;
|
||||
//codes.RemoveAt(i - 2);
|
||||
//codes.InsertRange(i - 2, new[]
|
||||
//{
|
||||
// new CodeInstruction(OpCodes.Ldarg_0),
|
||||
// CodeInstruction.LoadField(typeof(PlayerMoveController), "entityPlayerLocal"),
|
||||
// CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.GetActionIndexForEntity))
|
||||
//});
|
||||
//i += 2;
|
||||
}
|
||||
else if (codes[i].LoadsField(fld_reload))
|
||||
{
|
||||
var label = codes[i + 6].operand;
|
||||
codes.InsertRange(i + 7, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(PlayerMoveController), nameof(PlayerMoveController.entityPlayerLocal)),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.inventory)),
|
||||
CodeInstruction.Call(typeof(Inventory), nameof(Inventory.GetIsFinishedSwitchingHeldItem)),
|
||||
new CodeInstruction(OpCodes.Brfalse, label)
|
||||
});
|
||||
i += 5;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Underwater check
|
||||
//skip underwater check if action is not current action
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.OnHoldingUpdate))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_OnHoldingUpdate_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_ammonames = AccessTools.Field(typeof(ItemActionAttack), nameof(ItemActionAttack.MagazineItemNames));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_ammonames) && (codes[i + 1].opcode == OpCodes.Brfalse_S || codes[i + 1].opcode == OpCodes.Brfalse))
|
||||
{
|
||||
var jumpto = codes[i + 1].operand;
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1).WithLabels(codes[i - 1].ExtractLabels()),
|
||||
CodeInstruction.LoadField(typeof(ItemActionData), nameof(ItemActionData.indexInEntityOfAction)),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(ItemActionData), nameof(ItemActionData.invData)),
|
||||
CodeInstruction.LoadField(typeof(ItemInventoryData), nameof(ItemInventoryData.holdingEntity)),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.GetActionIndexForEntity)),
|
||||
new CodeInstruction(OpCodes.Bne_Un_S, jumpto)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GameEvent
|
||||
[HarmonyPatch(typeof(ActionUnloadItems), nameof(ActionUnloadItems.HandleItemStackChange))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_HandleItemStackChange_ActionUnloadItems(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_actions = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.Actions));
|
||||
|
||||
for (var i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_actions))
|
||||
{
|
||||
var label = generator.DefineLabel();
|
||||
codes[i - 1].WithLabels(label);
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Ldind_Ref),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ActionUnloadItems), nameof(ActionUnloadItems.ItemStacks)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.MultiActionRemoveAmmoFromItemStack)),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region fast toolbelt item switching issue fix
|
||||
private static Coroutine switchHoldingItemCo;
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.ShowHeldItem))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_ShowHeldItem_Inventory(bool show, Inventory __instance)
|
||||
{
|
||||
//Log.Out($"ShowHeldItem {show} on entity {__instance.entity.entityName}\n{StackTraceUtility.ExtractStackTrace()}");
|
||||
if (show && __instance.entity is EntityPlayerLocal && switchHoldingItemCo != null)
|
||||
{
|
||||
GameManager.Instance.StopCoroutine(switchHoldingItemCo);
|
||||
switchHoldingItemCo = null;
|
||||
__instance.SetIsFinishedSwitchingHeldItem();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.ShowHeldItem))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ShowHeldItem_Inventory(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Pop)
|
||||
{
|
||||
var label = generator.DefineLabel();
|
||||
codes[i].WithLabels(label);
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(Inventory), nameof(Inventory.entity)),
|
||||
new CodeInstruction(OpCodes.Isinst, typeof(EntityPlayerLocal)),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label),
|
||||
CodeInstruction.StoreField(typeof(MultiActionPatches), nameof(switchHoldingItemCo)),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region item info display fix
|
||||
[HarmonyPatch(typeof(XUiM_ItemStack), nameof(XUiM_ItemStack.GetStatItemValueTextWithModInfo))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_GetStatItemValueTextWithModInfo_XUiM_ItemStack(ItemStack itemStack)
|
||||
{
|
||||
MultiActionUtils.SetCachedEventParamsDummyAction(itemStack);
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiM_ItemStack), nameof(XUiM_ItemStack.GetStatItemValueTextWithModColoring))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_GetStatItemValueTextWithModColoring_XUiM_ItemStack(ItemStack itemStack)
|
||||
{
|
||||
MultiActionUtils.SetCachedEventParamsDummyAction(itemStack);
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiM_ItemStack), nameof(XUiM_ItemStack.GetStatItemValueTextWithCompareInfo))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_GetStatItemValueTextWithCompareInfo_XUiM_ItemStack(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_getvalue = AccessTools.Method(typeof(EffectManager), nameof(EffectManager.GetValue));
|
||||
var fld_seed = AccessTools.Field(typeof(MinEventParams), nameof(MinEventParams.Seed));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_getvalue))
|
||||
{
|
||||
codes.InsertRange(i + 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.SetCachedEventParamsDummyAction)),
|
||||
});
|
||||
for (int j = i; j >= 0; j--)
|
||||
{
|
||||
if (codes[j].StoresField(fld_seed))
|
||||
{
|
||||
codes.InsertRange(j + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.SetCachedEventParamsDummyAction))
|
||||
});
|
||||
codes.RemoveRange(j - 8, 9);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes.Manipulator(static ins => ins.IsLdarg(2), static ins => ins.opcode = OpCodes.Ldnull);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_ItemStack), nameof(XUiC_ItemStack.GetBindingValue))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_GetBindingValue_XUiC_ItemStack(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var prop_perc = AccessTools.PropertyGetter(typeof(ItemValue), nameof(ItemValue.PercentUsesLeft));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(prop_perc))
|
||||
{
|
||||
codes.InsertRange(i - 3, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(XUiC_ItemStack), nameof(XUiC_ItemStack.itemStack)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.SetCachedEventParamsDummyAction))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ItemAction exclude tags
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.StartGame))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_StartGame_GameManager()
|
||||
{
|
||||
MultiActionManager.PreloadCleanup();
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.LateInit))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_LateInit_ItemClass(ItemClass __instance)
|
||||
{
|
||||
MultiActionManager.ParseItemActionExcludeTagsAndModifiers(__instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyPatch(typeof(EffectManager), nameof(EffectManager.GetValue))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_GetValue_EffectManager(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].IsStarg(5))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1).WithLabels(codes[i + 1].ExtractLabels()),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.CachedEventParam)),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.ItemActionData)),
|
||||
new CodeInstruction(OpCodes.Ldarga_S, 5),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.ModifyItemTags))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EffectManager), nameof(EffectManager.GetValuesAndSources))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_GetValuesAndSources_EffectManager(ItemValue _originalItemValue, EntityAlive _entity, ref FastTags<TagGroup.Global> tags)
|
||||
{
|
||||
MultiActionManager.ModifyItemTags(_originalItemValue, _entity?.MinEventContext?.ItemActionData, ref tags);
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ItemAction exclude modifiers
|
||||
//see Transpiler_ModifyValue_ItemValue
|
||||
//see Transpiler_GetModifiedValueData_ItemValue
|
||||
//see MultiActionProjectileRewrites.ProjectileValueModifyValue
|
||||
//see MultiActionUtils.GetPropertyOverrideForAction
|
||||
//see MultiActionManager.ParseItemActionExcludeTagsAndModifiers
|
||||
#endregion
|
||||
|
||||
#region requirement tags exclude
|
||||
//[HarmonyPatch(typeof(TriggerHasTags), nameof(TriggerHasTags.IsValid))]
|
||||
//[HarmonyTranspiler]
|
||||
//private static IEnumerable<CodeInstruction> Transpiler_IsValid_TriggerHasTags(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
//{
|
||||
// var codes = instructions.ToList();
|
||||
|
||||
// var lbd_tags = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
// FieldInfo fld_tags = AccessTools.Field(typeof(MinEventParams), nameof(MinEventParams.Tags));
|
||||
// bool firstRet = true;
|
||||
|
||||
// for (int i = 0; i < codes.Count; i++)
|
||||
// {
|
||||
// if (codes[i].opcode == OpCodes.Ret && firstRet)
|
||||
// {
|
||||
// firstRet = false;
|
||||
// codes.InsertRange(i + 1, new[]
|
||||
// {
|
||||
// new CodeInstruction(OpCodes.Ldarg_1),
|
||||
// new CodeInstruction(OpCodes.Ldfld, fld_tags),
|
||||
// new CodeInstruction(OpCodes.Stloc_S, lbd_tags),
|
||||
// new CodeInstruction(OpCodes.Ldarg_1),
|
||||
// CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.ItemValue)),
|
||||
// new CodeInstruction(OpCodes.Ldarg_1),
|
||||
// CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.ItemActionData)),
|
||||
// new CodeInstruction(OpCodes.Ldloca_S, lbd_tags),
|
||||
// CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.ModifyItemTags))
|
||||
// });
|
||||
// i += 9;
|
||||
// }
|
||||
// else if (codes[i].LoadsField(fld_tags))
|
||||
// {
|
||||
// codes[i].opcode = OpCodes.Ldloca_S;
|
||||
// codes[i].operand = lbd_tags;
|
||||
// codes[i].WithLabels(codes[i - 1].ExtractLabels());
|
||||
// codes.RemoveAt(i - 1);
|
||||
// i--;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return codes;
|
||||
//}
|
||||
|
||||
[HarmonyPatch(typeof(ItemHasTags), nameof(ItemHasTags.IsValid))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_IsValid_ItemHasTags(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var lbd_tags = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
FieldInfo fld_itemvalue = AccessTools.Field(typeof(MinEventParams), nameof(MinEventParams.ItemValue));
|
||||
FieldInfo fld_hasalltags = AccessTools.Field(typeof(ItemHasTags), nameof(ItemHasTags.hasAllTags));
|
||||
MethodInfo prop_itemclass = AccessTools.PropertyGetter(typeof(ItemValue), nameof(ItemValue.ItemClass));
|
||||
MethodInfo mtd_hasanytags = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.HasAnyTags));
|
||||
MethodInfo mtd_hasalltags = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.HasAllTags));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_hasalltags))
|
||||
{
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Ldfld, fld_itemvalue),
|
||||
new CodeInstruction(OpCodes.Callvirt, prop_itemclass),
|
||||
CodeInstruction.LoadField(typeof(ItemClass), nameof(ItemClass.ItemTags)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Ldfld, fld_itemvalue),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.ItemActionData)),
|
||||
new CodeInstruction(OpCodes.Ldloca_S, lbd_tags),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.ModifyItemTags))
|
||||
});
|
||||
i += 11;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_hasanytags))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AnySet));
|
||||
var labels = codes[i - 5].ExtractLabels();
|
||||
codes.RemoveRange(i - 5, 3);
|
||||
codes.Insert(i - 5, new CodeInstruction(OpCodes.Ldloca_S, lbd_tags).WithLabels(labels));
|
||||
i -= 2;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_hasalltags))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AllSet));
|
||||
var labels = codes[i - 5].ExtractLabels();
|
||||
codes.RemoveRange(i - 5, 3);
|
||||
codes.Insert(i - 5, new CodeInstruction(OpCodes.Ldloca_S, lbd_tags).WithLabels(labels));
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
|
||||
[HarmonyPatch(typeof(HoldingItemHasTags), nameof(ItemHasTags.IsValid))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_IsValid_HoldingItemHasTags(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var lbd_tags = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
FieldInfo fld_itemvalue = AccessTools.Field(typeof(MinEventParams), nameof(MinEventParams.ItemValue));
|
||||
FieldInfo fld_hasalltags = AccessTools.Field(typeof(HoldingItemHasTags), nameof(HoldingItemHasTags.hasAllTags));
|
||||
MethodInfo prop_itemclass = AccessTools.PropertyGetter(typeof(ItemValue), nameof(ItemValue.ItemClass));
|
||||
MethodInfo prop_itemvalue = AccessTools.PropertyGetter(typeof(Inventory), nameof(Inventory.holdingItemItemValue));
|
||||
MethodInfo mtd_hasanytags = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.HasAnyTags));
|
||||
MethodInfo mtd_hasalltags = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.HasAllTags));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_hasalltags))
|
||||
{
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(HoldingItemHasTags), nameof(HoldingItemHasTags.target)),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.inventory)),
|
||||
new CodeInstruction(OpCodes.Callvirt, prop_itemvalue),
|
||||
new CodeInstruction(OpCodes.Callvirt, prop_itemclass),
|
||||
CodeInstruction.LoadField(typeof(ItemClass), nameof(ItemClass.ItemTags)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(HoldingItemHasTags), nameof(HoldingItemHasTags.target)),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.inventory)),
|
||||
new CodeInstruction(OpCodes.Callvirt, prop_itemvalue),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(HoldingItemHasTags), nameof(HoldingItemHasTags.target)),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.MinEventContext)),
|
||||
CodeInstruction.LoadField(typeof(MinEventParams), nameof(MinEventParams.ItemActionData)),
|
||||
new CodeInstruction(OpCodes.Ldloca_S, lbd_tags),
|
||||
CodeInstruction.Call(typeof(MultiActionManager), nameof(MultiActionManager.ModifyItemTags))
|
||||
});
|
||||
i += 17;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_hasanytags))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AnySet));
|
||||
var labels = codes[i - 6].ExtractLabels();
|
||||
codes.RemoveRange(i - 6, 4);
|
||||
codes.Insert(i - 6, new CodeInstruction(OpCodes.Ldloca_S, lbd_tags).WithLabels(labels));
|
||||
i -= 3;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_hasalltags))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AllSet));
|
||||
var labels = codes[i - 6].ExtractLabels();
|
||||
codes.RemoveRange(i - 6, 4);
|
||||
codes.Insert(i - 6, new CodeInstruction(OpCodes.Ldloca_S, lbd_tags).WithLabels(labels));
|
||||
i -= 3;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Inventory make ItemValue valid on creating inventory data
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.SetItem), new[] { typeof(int), typeof(ItemValue), typeof(int), typeof(bool) })]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetItem_Inventory(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_clone = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.Clone));
|
||||
var mtd_create = AccessTools.Method(typeof(Inventory), nameof(Inventory.createHeldItem));
|
||||
var mtd_invdata = AccessTools.Method(typeof(Inventory), nameof(Inventory.createInventoryData));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
//if (codes[i].opcode == OpCodes.Ldarg_3 && (codes[i + 1].opcode == OpCodes.Brtrue_S || codes[i + 1].opcode == OpCodes.Brtrue))
|
||||
//{
|
||||
// var label = codes[i + 4].ExtractLabels();
|
||||
// codes.InsertRange(i + 4, new[]
|
||||
// {
|
||||
// new CodeInstruction(OpCodes.Ldarg_2).WithLabels(label),
|
||||
// new CodeInstruction(OpCodes.Callvirt, mtd_clone),
|
||||
// new CodeInstruction(OpCodes.Starg_S, 2)
|
||||
// });
|
||||
// i += 7;
|
||||
//}
|
||||
//else
|
||||
if (codes[i].Calls(mtd_create))
|
||||
{
|
||||
codes.InsertRange(i - 12, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_2),
|
||||
CodeInstruction.StoreField(typeof(ActionModuleAlternative), nameof(ActionModuleAlternative.InventorySetItemTemp))
|
||||
});
|
||||
i += 4;
|
||||
for (int j = i; j < codes.Count; j++)
|
||||
{
|
||||
if (codes[j].Calls(mtd_invdata))
|
||||
{
|
||||
codes.InsertRange(j + 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldnull),
|
||||
CodeInstruction.StoreField(typeof(ActionModuleAlternative), nameof(ActionModuleAlternative.InventorySetItemTemp))
|
||||
});
|
||||
i = j + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//else if (codes[i].Calls(mtd_clone))
|
||||
//{
|
||||
// codes.RemoveAt(i);
|
||||
// break;
|
||||
//}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.ForceHoldingItemUpdate))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ForceHoldingItemUpdate_Inventory(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_invdata = AccessTools.Method(typeof(Inventory), nameof(Inventory.createInventoryData));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_invdata))
|
||||
{
|
||||
codes.InsertRange(i + 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldnull),
|
||||
CodeInstruction.StoreField(typeof(ActionModuleAlternative), nameof(ActionModuleAlternative.InventorySetItemTemp))
|
||||
});
|
||||
codes.InsertRange(i - 8, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_0).WithLabels(codes[i - 8].ExtractLabels()),
|
||||
CodeInstruction.StoreField(typeof(ActionModuleAlternative), nameof(ActionModuleAlternative.InventorySetItemTemp))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Temporaty fix for hud ammo mismatch
|
||||
[HarmonyPatch(typeof(XUiC_HUDStatBar), nameof(XUiC_HUDStatBar.Update))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Update_XUiC_HUDStatBar(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
MethodInfo mtd_getfocus = AccessTools.Method(typeof(Inventory), nameof(Inventory.GetFocusedItemIdx));
|
||||
MethodInfo mtd_getholding = AccessTools.PropertyGetter(typeof(Inventory), nameof(Inventory.holdingItemIdx));
|
||||
|
||||
foreach (var ins in instructions)
|
||||
{
|
||||
if (ins.Calls(mtd_getfocus))
|
||||
{
|
||||
ins.operand = mtd_getholding;
|
||||
}
|
||||
yield return ins;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
//Moved to MultiActionFix
|
||||
//#region Ranged Reload
|
||||
//[HarmonyPatch]
|
||||
//public static class RangedReloadPatches
|
||||
//{
|
||||
// private static IEnumerable<MethodBase> TargetMethods()
|
||||
// {
|
||||
// return new MethodInfo[]
|
||||
// {
|
||||
// AccessTools.Method(typeof(ItemActionAttack), nameof(ItemActionAttack.ReloadGun)),
|
||||
// AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.ReloadGun)),
|
||||
// AccessTools.Method(typeof(ItemActionLauncher), nameof(ItemActionLauncher.ReloadGun))
|
||||
// };
|
||||
// }
|
||||
|
||||
// //Why? Ask TFP why they don't just call base.ReloadGun()
|
||||
// [HarmonyPrefix]
|
||||
// private static bool Prefix_ReloadGun(ItemActionData _actionData)
|
||||
// {
|
||||
// int reloadAnimationIndex = MultiActionManager.GetMetaIndexForActionIndex(_actionData.invData.holdingEntity.entityId, _actionData.indexInEntityOfAction);
|
||||
// _actionData.invData.holdingEntity.emodel?.avatarController?.UpdateInt(AvatarController.itemActionIndexHash, reloadAnimationIndex, false);
|
||||
// _actionData.invData.holdingEntity.MinEventContext.ItemActionData = _actionData;
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
//#endregion
|
||||
|
||||
//KEEP
|
||||
#region Melee action tags
|
||||
[HarmonyPatch]
|
||||
public static class ActionTagPatches1
|
||||
{
|
||||
private static IEnumerable<MethodBase> TargetMethods()
|
||||
{
|
||||
return new MethodInfo[]
|
||||
{
|
||||
AccessTools.Method(typeof(AnimatorMeleeAttackState), nameof(AnimatorMeleeAttackState.OnStateEnter), new[] {typeof(Animator), typeof(AnimatorStateInfo), typeof(int)}),
|
||||
AccessTools.Method(typeof(ItemActionAttack), nameof(ItemActionAttack.GetDamageBlock)),
|
||||
AccessTools.Method(typeof(ItemActionAttack), nameof(ItemActionAttack.GetDamageEntity)),
|
||||
AccessTools.Method(typeof(ItemActionDynamic), nameof(ItemActionDynamic.GetDamageBlock)),
|
||||
AccessTools.Method(typeof(ItemActionDynamic), nameof(ItemActionDynamic.GetDamageEntity)),
|
||||
AccessTools.Method(typeof(ItemActionThrownWeapon), nameof(ItemActionThrownWeapon.GetDamageBlock)),
|
||||
AccessTools.Method(typeof(ItemActionThrownWeapon), nameof(ItemActionThrownWeapon.GetDamageEntity))
|
||||
};
|
||||
}
|
||||
|
||||
//set correct tag for action index above 2
|
||||
//only action 1 uses secondary tag, others still use primary
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
FieldInfo fld_tag = AccessTools.Field(typeof(ItemActionAttack), nameof(ItemActionAttack.SecondaryTag));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.LoadsField(fld_tag))
|
||||
{
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Ceq)
|
||||
});
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
public static class ActionTagPatches2
|
||||
{
|
||||
private static IEnumerable<MethodBase> TargetMethods()
|
||||
{
|
||||
return new MethodInfo[]
|
||||
{
|
||||
AccessTools.Method(typeof(ItemActionDynamicMelee), nameof(ItemActionDynamicMelee.Raycast)),
|
||||
AccessTools.Method(typeof(ItemActionDynamic), nameof(ItemActionDynamic.GetExecuteActionGrazeTarget)),
|
||||
AccessTools.Method(typeof(ItemActionDynamic), nameof(ItemActionDynamic.hitTarget)),
|
||||
AccessTools.Method(typeof(ItemActionDynamicMelee), nameof(ItemActionDynamicMelee.canStartAttack)),
|
||||
AccessTools.Method(typeof(ItemActionDynamicMelee), nameof(ItemActionDynamicMelee.OnHoldingUpdate)),
|
||||
AccessTools.Method(typeof(ItemActionDynamicMelee), nameof(ItemActionDynamicMelee.SetAttackFinished)),
|
||||
AccessTools.Method(typeof(ItemActionMelee), nameof(ItemActionMelee.OnHoldingUpdate)),
|
||||
AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.ExecuteAction)),
|
||||
AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.fireShot)),
|
||||
AccessTools.Method(typeof(ItemActionThrownWeapon), nameof(ItemActionThrownWeapon.throwAway)),
|
||||
AccessTools.Method(typeof(ItemActionUseOther), nameof(ItemActionUseOther.ExecuteAction)),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
FieldInfo fld_index = AccessTools.Field(typeof(ItemActionData), nameof(ItemActionData.indexInEntityOfAction));
|
||||
for (int i = 0; i < codes.Count - 1; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.LoadsField(fld_index) && (codes[i + 1].opcode == OpCodes.Brfalse_S || codes[i + 1].opcode == OpCodes.Brfalse))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Ceq)
|
||||
});
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//KEEP
|
||||
#region 3
|
||||
[HarmonyPatch]
|
||||
public static class ThreePatches
|
||||
{
|
||||
private static IEnumerable<MethodBase> TargetMethods()
|
||||
{
|
||||
return new MethodInfo[]
|
||||
{
|
||||
AccessTools.Method(typeof(ItemClass), nameof(ItemClass.OnHoldingUpdate)),
|
||||
AccessTools.Method(typeof(ItemClass), nameof(ItemClass.CleanupHoldingActions)),
|
||||
AccessTools.Method(typeof(ItemClass), nameof(ItemClass.StartHolding)),
|
||||
AccessTools.Method(typeof(ItemClass), nameof(ItemClass.StopHolding)),
|
||||
AccessTools.Method(typeof(ItemClass), nameof(ItemClass.IsActionRunning))
|
||||
};
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Three(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
foreach (var instruction in instructions)
|
||||
{
|
||||
if (instruction.opcode == OpCodes.Ldc_I4_3)
|
||||
instruction.opcode = OpCodes.Ldc_I4_5;
|
||||
yield return instruction;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ItemAction property override
|
||||
[HarmonyPatch]
|
||||
public static class ItemActionPropertyOverridePatches
|
||||
{
|
||||
private static IEnumerable<MethodBase> TargetMethods()
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return a.GetTypes();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Type[0];
|
||||
}
|
||||
})
|
||||
.Where(t => t.IsSubclassOf(typeof(ItemAction)))
|
||||
.Select(t => AccessTools.Method(t, nameof(ItemAction.OnModificationsChanged)))
|
||||
.Where(m => m.IsDeclaredMember());
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
|
||||
{
|
||||
Log.Out($"Patching property override method {__originalMethod.DeclaringType.Name}.{__originalMethod.Name}");
|
||||
var codes = instructions.ToList();
|
||||
var mtd_override = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.GetPropertyOverride));
|
||||
var mtd_newoverride = AccessTools.Method(typeof(MultiActionUtils), nameof(MultiActionUtils.GetPropertyOverrideForAction));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_override))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = mtd_newoverride;
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(ItemAction), nameof(ItemAction.ActionIndex))
|
||||
});
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Remove ammo
|
||||
[HarmonyPatch]
|
||||
public static class RemoveAmmoPatches
|
||||
{
|
||||
private static IEnumerable<MethodBase> TargetMethods()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
AccessTools.Method(typeof(ItemActionEntryAssemble), nameof(ItemActionEntryAssemble.HandleRemoveAmmo)),
|
||||
AccessTools.Method(typeof(ItemActionEntryScrap), nameof(ItemActionEntryScrap.HandleRemoveAmmo)),
|
||||
AccessTools.Method(typeof(ItemActionEntrySell), nameof(ItemActionEntrySell.HandleRemoveAmmo)),
|
||||
};
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix(BaseItemActionEntry __instance, ItemStack stack, ref ItemStack __result)
|
||||
{
|
||||
List<ItemStack> list_ammo_stack = new List<ItemStack>();
|
||||
if (!MultiActionUtils.MultiActionRemoveAmmoFromItemStack(stack, list_ammo_stack))
|
||||
return true;
|
||||
|
||||
foreach (var ammoStack in list_ammo_stack)
|
||||
{
|
||||
if (!__instance.ItemController.xui.PlayerInventory.AddItem(ammoStack))
|
||||
{
|
||||
__instance.ItemController.xui.PlayerInventory.DropItem(ammoStack);
|
||||
}
|
||||
}
|
||||
__result = stack;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Generate initial meta
|
||||
[HarmonyPatch]
|
||||
public static class InitialMetaPatches
|
||||
{
|
||||
private static IEnumerable<MethodBase> TargetMethods()
|
||||
{
|
||||
return new MethodInfo[]
|
||||
{
|
||||
AccessTools.Method(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.SetupStartingItems)),
|
||||
AccessTools.Method(typeof(ItemClass), nameof(ItemClass.CreateItemStacks))
|
||||
};
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_initial = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.GetInitialMetadata));
|
||||
var mtd_initialnew = AccessTools.Method(typeof(MultiActionUtils), nameof(MultiActionUtils.GetMultiActionInitialMetaData));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_initial))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = mtd_initialnew;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Item Info DisplayType
|
||||
[HarmonyPatch]
|
||||
public static class DisplayTypePatches
|
||||
{
|
||||
[HarmonyPatch(typeof(XUiC_AssembleWindow), nameof(XUiC_AssembleWindow.ItemStack), MethodType.Setter)]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ItemStack_XUiC_AssembleWindow(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_displaytype = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.DisplayType));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_displaytype))
|
||||
{
|
||||
codes.RemoveRange(i - 1, 2);
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
CodeInstruction.LoadField(typeof(XUiC_AssembleWindow), nameof(XUiC_AssembleWindow.itemStack)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetDisplayTypeForAction), new []{ typeof(ItemStack) })
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_ItemInfoWindow), nameof(XUiC_ItemInfoWindow.SetInfo))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetInfo_XUiC_ItemInfoWindow(IEnumerable<CodeInstruction> instructions, MethodBase originalMethod)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_displaytype = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.DisplayType));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_displaytype))
|
||||
{
|
||||
codes.RemoveRange(i - 1, 2);
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
CodeInstruction.LoadField(typeof(XUiC_ItemInfoWindow), nameof(XUiC_ItemInfoWindow.itemStack)),
|
||||
CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetDisplayTypeForAction), new []{ typeof(ItemStack) })
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiM_ItemStack), nameof(XUiM_ItemStack.HasItemStats))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_HasItemStats_XUiM_ItemStack(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_displaytype = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.DisplayType));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_displaytype))
|
||||
{
|
||||
codes.RemoveRange(i - 1, 2);
|
||||
codes.Insert(i - 1, CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.GetDisplayTypeForAction), new []{ typeof(ItemValue) }));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_ItemInfoWindow), nameof(XUiC_ItemInfoWindow.HoverEntry), MethodType.Setter)]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_HoverEntry_XUiC_ItemInfoWindow(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_cancompare = AccessTools.Method(typeof(XUiM_ItemStack), nameof(XUiM_ItemStack.CanCompare));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_cancompare))
|
||||
{
|
||||
codes[i] = CodeInstruction.Call(typeof(MultiActionUtils), nameof(MultiActionUtils.CanCompare));
|
||||
codes[i - 1] = CodeInstruction.LoadField(typeof(XUiC_ItemInfoWindow), nameof(XUiC_ItemInfoWindow.itemStack));
|
||||
codes.Insert(i, CodeInstruction.LoadField(typeof(ItemStack), nameof(ItemStack.itemValue)));
|
||||
codes.RemoveAt(i - 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
68
Harmony/MultiActionReversePatches.cs
Normal file
68
Harmony/MultiActionReversePatches.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib.Scripts.Utilities;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using UnityEngine;
|
||||
|
||||
[HarmonyPatch]
|
||||
public static class MultiActionReversePatches
|
||||
{
|
||||
[HarmonyReversePatch(HarmonyReversePatchType.Snapshot)]
|
||||
[HarmonyPatch(typeof(EffectManager), nameof(EffectManager.GetValue))]
|
||||
public static float ProjectileGetValue(PassiveEffects _passiveEffect, ItemValue _originalItemValue = null, float _originalValue = 0f, EntityAlive _entity = null, Recipe _recipe = null, FastTags<TagGroup.Global> tags = default(FastTags<TagGroup.Global>), bool calcEquipment = true, bool calcHoldingItem = true, bool calcProgression = true, bool calcBuffs = true, bool calcChallenges = true, int craftingTier = 1, bool useMods = true, bool _useDurability = false)
|
||||
{
|
||||
IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
if (instructions == null)
|
||||
return null;
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_modify = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.ModifyValue));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
var code = codes[i];
|
||||
if (code.Calls(mtd_modify) && codes[i - 9].opcode == OpCodes.Ldarg_1)
|
||||
{
|
||||
code.operand = AccessTools.Method(typeof(MultiActionProjectileRewrites), nameof(MultiActionProjectileRewrites.ProjectileValueModifyValue));
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
_ = Transpiler(null);
|
||||
return _originalValue;
|
||||
}
|
||||
|
||||
[HarmonyReversePatch]
|
||||
[HarmonyPatch(typeof(ProjectileMoveScript), nameof(ProjectileMoveScript.Fire))]
|
||||
public static void ProjectileFire(this ProjectileMoveScript __instance, Vector3 _idealStartPosition, Vector3 _flyDirection, Entity _firingEntity, int _hmOverride = 0, float _radius = 0f)
|
||||
{
|
||||
IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
if (instructions == null)
|
||||
return null;
|
||||
|
||||
var codes = instructions.ToList();
|
||||
|
||||
FieldInfo fld_launcher = AccessTools.Field(typeof(ProjectileMoveScript), nameof(ProjectileMoveScript.itemValueLauncher));
|
||||
FieldInfo fld_projectile = AccessTools.Field(typeof(ProjectileMoveScript), nameof(ProjectileMoveScript.itemValueProjectile));
|
||||
MethodInfo mtd_getvalue = AccessTools.Method(typeof(EffectManager), nameof(EffectManager.GetValue));
|
||||
MethodInfo mtd_getvaluenew = AccessTools.Method(typeof(MultiActionReversePatches), nameof(ProjectileGetValue));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_launcher))
|
||||
{
|
||||
codes[i].operand = fld_projectile;
|
||||
}
|
||||
else if (codes[i].Calls(mtd_getvalue))
|
||||
{
|
||||
codes[i].operand = mtd_getvaluenew;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
_ = Transpiler(null);
|
||||
}
|
||||
}
|
||||
155
Harmony/MultiBarrelPatches.cs
Normal file
155
Harmony/MultiBarrelPatches.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public class MultiBarrelPatches
|
||||
{
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ExecuteAction))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ExecuteAction_ItemActionRanged(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_getmax = AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.GetMaxAmmoCount));
|
||||
var mtd_consume = AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.ConsumeAmmo));
|
||||
|
||||
Label loopStart = generator.DefineLabel();
|
||||
Label loopCondi = generator.DefineLabel();
|
||||
LocalBuilder lbd_data_module = generator.DeclareLocal(typeof(ActionModuleMultiBarrel.MultiBarrelData));
|
||||
LocalBuilder lbd_ismb = generator.DeclareLocal(typeof(bool));
|
||||
LocalBuilder lbd_i = generator.DeclareLocal(typeof(int));
|
||||
LocalBuilder lbd_rounds = generator.DeclareLocal(typeof(int));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
//prepare loop and store local variables
|
||||
if (codes[i].opcode == OpCodes.Stloc_S && ((LocalBuilder)codes[i].operand).LocalIndex == 6)
|
||||
{
|
||||
codes[i + 1].WithLabels(loopStart);
|
||||
Label lbl = generator.DefineLabel();
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldnull),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_data_module),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Ldloca_S, lbd_data_module),
|
||||
CodeInstruction.Call(typeof(MultiBarrelPatches), nameof(IsMultiBarrelData)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_ismb),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_i),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_ismb),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, lbl),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_data_module),
|
||||
CodeInstruction.LoadField(typeof(ActionModuleMultiBarrel.MultiBarrelData), nameof(ActionModuleMultiBarrel.MultiBarrelData.roundsPerShot)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_rounds),
|
||||
new CodeInstruction(OpCodes.Br_S, loopCondi),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1).WithLabels(lbl),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_rounds),
|
||||
new CodeInstruction(OpCodes.Br_S, loopCondi),
|
||||
});
|
||||
i += 16;
|
||||
}
|
||||
//one round multi shot check
|
||||
else if (codes[i].Calls(mtd_consume))
|
||||
{
|
||||
Label lbl = generator.DefineLabel();
|
||||
codes[i - 2].WithLabels(lbl);
|
||||
codes.InsertRange(i - 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_ismb),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, lbl),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_data_module),
|
||||
CodeInstruction.LoadField(typeof(ActionModuleMultiBarrel.MultiBarrelData), nameof(ActionModuleMultiBarrel.MultiBarrelData.oneRoundMultishot)),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, lbl),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_i),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Bgt_S, codes[i - 3].operand)
|
||||
});
|
||||
i += 8;
|
||||
}
|
||||
//loop conditions and cycle barrels
|
||||
else if (codes[i].Calls(mtd_getmax))
|
||||
{
|
||||
Label lbl_pre = generator.DefineLabel();
|
||||
Label lbl_post = generator.DefineLabel();
|
||||
CodeInstruction origin = codes[i - 2];
|
||||
codes.InsertRange(i - 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_ismb).WithLabels(origin.ExtractLabels()),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, lbl_pre),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_data_module),
|
||||
CodeInstruction.LoadField(typeof(ActionModuleMultiBarrel.MultiBarrelData), nameof(ActionModuleMultiBarrel.MultiBarrelData.muzzleIsPerRound)),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, lbl_pre),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_data_module),
|
||||
CodeInstruction.Call(typeof(ActionModuleMultiBarrel.MultiBarrelData), nameof(ActionModuleMultiBarrel.MultiBarrelData.CycleBarrels)),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_i).WithLabels(lbl_pre),
|
||||
//new CodeInstruction(OpCodes.Dup),
|
||||
//new CodeInstruction(OpCodes.Ldloc_S, lbd_rounds),
|
||||
//CodeInstruction.Call(typeof(MultiBarrelPatches), nameof(MultiBarrelPatches.LogInfo)),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||
new CodeInstruction(OpCodes.Add),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_i),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_i).WithLabels(loopCondi),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_rounds),
|
||||
new CodeInstruction(OpCodes.Blt_S, loopStart),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_ismb),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, lbl_post),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_data_module),
|
||||
CodeInstruction.LoadField(typeof(ActionModuleMultiBarrel.MultiBarrelData), nameof(ActionModuleMultiBarrel.MultiBarrelData.muzzleIsPerRound)),
|
||||
new CodeInstruction(OpCodes.Brtrue_S, lbl_post),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_data_module),
|
||||
CodeInstruction.Call(typeof(ActionModuleMultiBarrel.MultiBarrelData), nameof(ActionModuleMultiBarrel.MultiBarrelData.CycleBarrels))
|
||||
});
|
||||
origin.WithLabels(lbl_post);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AnimatorRangedReloadState), nameof(AnimatorRangedReloadState.OnStateEnter))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnStateEnter_AnimatorRangedReloadState(AnimatorRangedReloadState __instance)
|
||||
{
|
||||
ItemActionLauncher.ItemActionDataLauncher launcherData = __instance.actionData as ItemActionLauncher.ItemActionDataLauncher;
|
||||
if (launcherData != null && launcherData is IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData> dataModule && dataModule.Instance.oneRoundMultishot && dataModule.Instance.roundsPerShot > 1)
|
||||
{
|
||||
int count = launcherData.projectileInstance.Count;
|
||||
int times = dataModule.Instance.roundsPerShot - 1;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
for (int j = 0; j < times; j++)
|
||||
{
|
||||
launcherData.projectileJoint = dataModule.Instance.projectileJoints[j + 1];
|
||||
launcherData.projectileInstance.Insert(i * (times + 1) + j + 1,((ItemActionLauncher)__instance.actionRanged).instantiateProjectile(launcherData));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AnimatorRangedReloadState), nameof(AnimatorRangedReloadState.OnStateExit))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnStateExit_AnimatorRangedReloadState(AnimatorRangedReloadState __instance)
|
||||
{
|
||||
if (__instance.actionData is IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData> dataModule)
|
||||
{
|
||||
dataModule.Instance.SetCurrentBarrel(__instance.actionData.invData.itemValue.Meta);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsMultiBarrelData(ItemActionData data, out ActionModuleMultiBarrel.MultiBarrelData dataModule)
|
||||
{
|
||||
return (dataModule = (data as IModuleContainerFor<ActionModuleMultiBarrel.MultiBarrelData>)?.Instance) != null;
|
||||
}
|
||||
|
||||
private static void LogInfo(int cur, int max) => Log.Out($"max rounds {max}, cur {cur}");
|
||||
}
|
||||
}
|
||||
1325
Harmony/Patches.cs
Normal file
1325
Harmony/Patches.cs
Normal file
@@ -0,0 +1,1325 @@
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using KFCommonUtilityLib.Scripts.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniLinq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Xml.Linq;
|
||||
using UnityEngine;
|
||||
using KFCommonUtilityLib.Scripts.NetPackages;
|
||||
using KFCommonUtilityLib;
|
||||
|
||||
[HarmonyPatch]
|
||||
public static class CommonUtilityPatch
|
||||
{
|
||||
//fix reloading issue and onSelfRangedBurstShot timing
|
||||
public static void FakeReload(EntityAlive holdingEntity, ItemActionRanged.ItemActionDataRanged _actionData)
|
||||
{
|
||||
if (!holdingEntity)
|
||||
return;
|
||||
_actionData.isReloading = true;
|
||||
_actionData.isWeaponReloading = true;
|
||||
holdingEntity.MinEventContext.ItemActionData = _actionData;
|
||||
holdingEntity.FireEvent(MinEventTypes.onReloadStart, true);
|
||||
_actionData.isReloading = false;
|
||||
_actionData.isWeaponReloading = false;
|
||||
_actionData.isReloadCancelled = false;
|
||||
_actionData.isWeaponReloadCancelled = false;
|
||||
holdingEntity.FireEvent(MinEventTypes.onReloadStop);
|
||||
|
||||
AnimationAmmoUpdateState.SetAmmoCountForEntity(holdingEntity, holdingEntity.inventory.holdingItemIdx);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.SwapAmmoType))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SwapAmmoType_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = new List<CodeInstruction>(instructions);
|
||||
|
||||
for (int i = 0; i < codes.Count; ++i)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Ret)
|
||||
{
|
||||
codes.InsertRange(i, new CodeInstruction[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(CommonUtilityPatch), nameof(FakeReload))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ExecuteAction))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ExecuteAction_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = new List<CodeInstruction>(instructions);
|
||||
var mtd_fire_event = AccessTools.Method(typeof(EntityAlive), nameof(EntityAlive.FireEvent));
|
||||
var mtd_get_model_layer = AccessTools.Method(typeof(EntityAlive), nameof(EntityAlive.GetModelLayer));
|
||||
var mtd_get_perc_left = AccessTools.PropertyGetter(typeof(ItemValue), nameof(ItemValue.PercentUsesLeft));
|
||||
|
||||
int take = -1, insert = -1;
|
||||
for (int i = 0; i < codes.Count; ++i)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Ldc_I4_S && codes[i].OperandIs((int)MinEventTypes.onSelfRangedBurstShotEnd) && codes[i + 2].Calls(mtd_fire_event))
|
||||
take = i - 3;
|
||||
else if (codes[i].Calls(mtd_get_model_layer))
|
||||
insert = i + 2;
|
||||
}
|
||||
|
||||
if (take < insert)
|
||||
{
|
||||
var list = codes.GetRange(take, 6);
|
||||
codes.InsertRange(insert, list);
|
||||
codes.RemoveRange(take, 6);
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
//fix recoil animation does not match weapon RPM
|
||||
private static int weaponFireHash = Animator.StringToHash("WeaponFire");
|
||||
private static int aimHash = Animator.StringToHash("IsAiming");
|
||||
private static HashSet<int> hash_shot_state = new HashSet<int>();
|
||||
private static HashSet<int> hash_aimshot_state = new HashSet<int>();
|
||||
|
||||
public static void InitShotStates()
|
||||
{
|
||||
string[] weapons =
|
||||
{
|
||||
"fpvAK47",
|
||||
"fpvMagnum",
|
||||
"fpvRocketLauncher",
|
||||
"fpvSawedOffShotgun",
|
||||
"fpvBlunderbuss",
|
||||
"fpvCrossbow",
|
||||
"fpvPistol",
|
||||
"fpvHuntingRifle",
|
||||
"fpvSMG",
|
||||
"fpvSniperRifle",
|
||||
"M60",
|
||||
"fpvDoubleBarrelShotgun",
|
||||
//"fpvJunkTurret",
|
||||
"fpvTacticalAssaultRifle",
|
||||
"fpvDesertEagle",
|
||||
"fpvAutoShotgun",
|
||||
"fpvSharpShooterRifle",
|
||||
"fpvPipeMachineGun",
|
||||
"fpvPipeRifle",
|
||||
"fpvPipeRevolver",
|
||||
"fpvPipeShotgun",
|
||||
"fpvLeverActionRifle",
|
||||
};
|
||||
foreach (string weapon in weapons)
|
||||
{
|
||||
hash_shot_state.Add(Animator.StringToHash(weapon + "Fire"));
|
||||
hash_aimshot_state.Add(Animator.StringToHash(weapon + "AimFire"));
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.OnFired))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnFired_EntityPlayerLocal(EntityPlayerLocal __instance)
|
||||
{
|
||||
if (!__instance.bFirstPersonView)
|
||||
return;
|
||||
|
||||
ItemActionRanged.ItemActionDataRanged _rangedData;
|
||||
if ((_rangedData = __instance.inventory.holdingItemData.actionData[0] as ItemActionRanged.ItemActionDataRanged) == null && (_rangedData = __instance.inventory.holdingItemData.actionData[1] as ItemActionRanged.ItemActionDataRanged) == null)
|
||||
return;
|
||||
|
||||
if (_rangedData.invData.model.TryGetComponent<AnimationTargetsAbs>(out var targets) && targets.ItemFpv)
|
||||
return;
|
||||
|
||||
var anim = (__instance.emodel.avatarController as AvatarLocalPlayerController).FPSArms.Animator;
|
||||
if (anim.IsInTransition(0))
|
||||
return;
|
||||
|
||||
var curState = anim.GetCurrentAnimatorStateInfo(0);
|
||||
if (curState.length > _rangedData.Delay)
|
||||
{
|
||||
bool aimState = anim.GetBool(aimHash);
|
||||
short shotState = 0;
|
||||
if (hash_shot_state.Contains(curState.shortNameHash))
|
||||
shotState = 1;
|
||||
else if (hash_aimshot_state.Contains(curState.shortNameHash))
|
||||
shotState = 2;
|
||||
if (shotState == 0 || (shotState == 1 && aimState) || (shotState == 2 && !aimState))
|
||||
{
|
||||
if (shotState > 0)
|
||||
anim.ResetTrigger(weaponFireHash);
|
||||
return;
|
||||
}
|
||||
|
||||
//current state, layer 0, offset 0
|
||||
anim.PlayInFixedTime(0, 0, 0);
|
||||
anim.ResetTrigger(weaponFireHash);
|
||||
if (_rangedData.invData.itemValue.Meta == 0)
|
||||
{
|
||||
__instance.emodel.avatarController.CancelEvent(weaponFireHash);
|
||||
Log.Out("Cancel fire event because meta is 0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ItemActionEffects))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_ItemActionEffects_ItemActionRanged(ItemActionData _actionData, int _firingState)
|
||||
//{
|
||||
// if (_firingState == 0 && _actionData.invData.holdingEntity is EntityPlayerLocal && !(_actionData.invData.itemValue.ItemClass.Actions[0] is ItemActionCatapult))
|
||||
// {
|
||||
// _actionData.invData.holdingEntity?.emodel.avatarController.CancelEvent(weaponFireHash);
|
||||
// //Log.Out("Cancel fire event because firing state is 0\n" + StackTraceUtility.ExtractStackTrace());
|
||||
// }
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(GameManager), "gmUpdate")]
|
||||
//[HarmonyTranspiler]
|
||||
//private static IEnumerable<CodeInstruction> Transpiler_gmUpdate_GameManager(IEnumerable<CodeInstruction> instructions)
|
||||
//{
|
||||
// var codes = new List<CodeInstruction>(instructions);
|
||||
// var mtd_unload = AccessTools.Method(typeof(Resources), nameof(Resources.UnloadUnusedAssets));
|
||||
// var fld_duration = AccessTools.Field(typeof(GameManager), "unloadAssetsDuration");
|
||||
|
||||
// for (int i = 0; i < codes.Count; ++i)
|
||||
// {
|
||||
// if (codes[i].opcode == OpCodes.Call && codes[i].Calls(mtd_unload))
|
||||
// {
|
||||
// for (int j = i; j >= 0; --j)
|
||||
// {
|
||||
// if (codes[j].opcode == OpCodes.Ldfld && codes[j].LoadsField(fld_duration) && codes[j + 1].opcode == OpCodes.Ldc_R4)
|
||||
// codes[j + 1].operand = (float)codes[j + 1].operand / 2;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return codes;
|
||||
//}
|
||||
|
||||
//internal static void ForceUpdateGC()
|
||||
//{
|
||||
// if (GameManager.IsDedicatedServer)
|
||||
// return;
|
||||
// if (GameManager.frameCount % 18000 == 0)
|
||||
// {
|
||||
// long rss = GetRSS.GetCurrentRSS();
|
||||
// if (rss / 1024 / 1024 > 6144)
|
||||
// {
|
||||
// Log.Out("Memory usage exceeds threshold, now performing garbage collection...");
|
||||
// GC.Collect();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//altmode workarounds
|
||||
//deprecated by action module
|
||||
private static void ParseAltRequirements(XElement _node)
|
||||
{
|
||||
string itemName = _node.GetAttribute("name");
|
||||
if (string.IsNullOrEmpty(itemName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ItemClass item = ItemClass.GetItemClass(itemName);
|
||||
for (int i = 0; i < item.Actions.Length; i++)
|
||||
{
|
||||
if (item.Actions[i] is ItemActionAltMode _alt)
|
||||
_alt.ParseAltRequirements(_node, i);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClassesFromXml), nameof(ItemClassesFromXml.parseItem))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_parseItem_ItemClassesFromXml(XElement _node)
|
||||
{
|
||||
ParseAltRequirements(_node);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemClass), nameof(ItemClass.ExecuteAction))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_ExecuteAction_ItemClass(ItemClass __instance, int _actionIdx, ItemInventoryData _data, bool _bReleased)
|
||||
{
|
||||
if (!_bReleased && __instance.Actions[_actionIdx] is ItemActionAltMode _alt)
|
||||
_alt.SetAltRequirement(_data.actionData[_actionIdx]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(DynamicProperties), nameof(DynamicProperties.Parse))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_Parse_DynamicProperties(XElement elementProperty)
|
||||
{
|
||||
if (elementProperty.Name.LocalName != "property")
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//MinEventParams workarounds
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.fireShot))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_fireShot_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = new List<CodeInstruction>(instructions);
|
||||
|
||||
var fld_ranged_tag = AccessTools.Field(typeof(ItemActionAttack), nameof(ItemActionAttack.RangedTag));
|
||||
var fld_params = AccessTools.Field(typeof(EntityAlive), nameof(EntityAlive.MinEventContext));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_ranged_tag))
|
||||
{
|
||||
if (!codes[i + 3].LoadsField(fld_params))
|
||||
{
|
||||
codes.InsertRange(i + 2, new CodeInstruction[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_1),
|
||||
CodeInstruction.LoadField(typeof(EntityAlive), nameof(EntityAlive.MinEventContext)),
|
||||
new CodeInstruction(OpCodes.Dup),
|
||||
new CodeInstruction(OpCodes.Ldloc, 10),
|
||||
CodeInstruction.LoadField(typeof(WorldRayHitInfo), nameof(WorldRayHitInfo.hit)),
|
||||
CodeInstruction.LoadField(typeof(HitInfoDetails), nameof(HitInfoDetails.pos)),
|
||||
CodeInstruction.StoreField(typeof(MinEventParams), nameof(MinEventParams.Position)),
|
||||
new CodeInstruction(OpCodes.Ldloc_1),
|
||||
CodeInstruction.Call(typeof(EntityAlive), nameof(EntityAlive.GetPosition)),
|
||||
CodeInstruction.StoreField(typeof(MinEventParams), nameof(MinEventParams.StartPosition))
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.OnHoldingUpdate))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_OnHoldingUpdate_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var mtd_release = AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.triggerReleased));
|
||||
var codes = instructions.ToList();
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_release))
|
||||
{
|
||||
codes[i + 1].labels.Clear();
|
||||
codes[i + 1].MoveLabelsFrom(codes[i - 20]);
|
||||
codes.RemoveRange(i - 20, 21);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.triggerReleased))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_triggerReleased_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var mtd_effect = AccessTools.Method(typeof(IGameManager), nameof(IGameManager.ItemActionEffectsServer));
|
||||
var mtd_data = AccessTools.Method(typeof(ItemActionRanged), nameof(ItemActionRanged.getUserData));
|
||||
var codes = instructions.ToList();
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_effect))
|
||||
{
|
||||
codes.InsertRange(i, new CodeInstruction[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Callvirt, mtd_data)
|
||||
});
|
||||
codes.RemoveAt(i - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.StartGame))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_StartGame_GameManager()
|
||||
{
|
||||
CustomEffectEnumManager.InitFinal();
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PassiveEffect), nameof(PassiveEffect.ParsePassiveEffect))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ParsePassiveEffect_PassiveEffect(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
MethodInfo mtd_enum_parse = AccessTools.Method(typeof(EnumUtils), nameof(EnumUtils.Parse), new[] { typeof(string), typeof(bool) }, new[] { typeof(PassiveEffects) });
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_enum_parse))
|
||||
{
|
||||
codes.Insert(i + 1, CodeInstruction.Call(typeof(CustomEffectEnumManager), nameof(CustomEffectEnumManager.RegisterOrGetEnum), new[] { typeof(string), typeof(bool) }, new[] { typeof(PassiveEffects) }));
|
||||
codes.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(MinEventActionBase), nameof(MinEventActionBase.ParseXmlAttribute))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ParseXmlAttribute_MinEventActionBase(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
MethodInfo mtd_enum_parse = AccessTools.Method(typeof(EnumUtils), nameof(EnumUtils.Parse), new[] { typeof(string), typeof(bool) }, new[] { typeof(MinEventTypes) });
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_enum_parse))
|
||||
{
|
||||
codes.Insert(i + 1, CodeInstruction.Call(typeof(CustomEffectEnumManager), nameof(CustomEffectEnumManager.RegisterOrGetEnum), new[] { typeof(string), typeof(bool) }, new[] { typeof(MinEventTypes) }));
|
||||
codes.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionDynamicMelee), nameof(ItemActionDynamicMelee.OnHoldingUpdate))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_OnHoldingUpdate_ItemActionDynamicMelee(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Is(OpCodes.Ldc_R4, 0.1f))
|
||||
{
|
||||
codes.RemoveRange(i, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionDynamicMelee), nameof(ItemActionDynamicMelee.canStartAttack))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_canStartAttack_ItemActionDynamicMelee(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Is(OpCodes.Ldc_R4, 0.1f))
|
||||
{
|
||||
codes.RemoveRange(i, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// projectile direct hit damage percent
|
||||
/// removed due to new explosion damage passives
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <returns></returns>
|
||||
//[HarmonyPatch(typeof(ProjectileMoveScript), nameof(ProjectileMoveScript.checkCollision))]
|
||||
//[HarmonyTranspiler]
|
||||
//private static IEnumerable<CodeInstruction> Transpiler_checkCollision_ProjectileMoveScript(IEnumerable<CodeInstruction> instructions)
|
||||
//{
|
||||
// var codes = instructions.ToList();
|
||||
// var fld_strain = AccessTools.Field(typeof(ItemActionLauncher.ItemActionDataLauncher), nameof(ItemActionLauncher.ItemActionDataLauncher.strainPercent));
|
||||
// var mtd_block = AccessTools.Method(typeof(ItemActionAttack), nameof(ItemActionAttack.GetDamageBlock));
|
||||
|
||||
// for (int i = 0; i < codes.Count; i++)
|
||||
// {
|
||||
// if (codes[i].LoadsField(fld_strain))
|
||||
// {
|
||||
// codes.InsertRange(i + 1, new CodeInstruction[]
|
||||
// {
|
||||
// new CodeInstruction(OpCodes.Ldarg_0),
|
||||
// CodeInstruction.LoadField(typeof(ProjectileMoveScript), nameof(ProjectileMoveScript.itemValueProjectile)),
|
||||
// new CodeInstruction(OpCodes.Ldloc_S, 4),
|
||||
// CodeInstruction.Call(typeof(CommonUtilityPatch), codes[i - 3].Calls(mtd_block) ? nameof(GetProjectileBlockDamagePerc) : nameof(GetProjectileEntityDamagePerc)),
|
||||
// new CodeInstruction(OpCodes.Mul)
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// return codes;
|
||||
//}
|
||||
|
||||
//public static float GetProjectileBlockDamagePerc(ItemValue _itemValue, EntityAlive _holdingEntity)
|
||||
//{
|
||||
// return EffectManager.GetValue(CustomEnums.ProjectileImpactDamagePercentBlock, _itemValue, 1, _holdingEntity, null);
|
||||
//}
|
||||
|
||||
//public static float GetProjectileEntityDamagePerc(ItemValue _itemValue, EntityAlive _holdingEntity)
|
||||
//{
|
||||
// return EffectManager.GetValue(CustomEnums.ProjectileImpactDamagePercentEntity, _itemValue, 1, _holdingEntity, null);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// force tpv crosshair
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.guiDrawCrosshair))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_guiDrawCrosshair_EntityPlayerLocal(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
FieldInfo fld_debug = AccessTools.Field(typeof(ItemAction), nameof(ItemAction.ShowDistanceDebugInfo));
|
||||
|
||||
for ( int i = 0; i < codes.Count; i++ )
|
||||
{
|
||||
if (codes[i].LoadsField(fld_debug))
|
||||
{
|
||||
var label = codes[i - 1].operand;
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.bFirstPersonView)),
|
||||
new CodeInstruction(OpCodes.Brfalse_S, label)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// correctly apply muzzle flash silence with modifications
|
||||
/// </summary>
|
||||
/// <param name="_data"></param>
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.OnModificationsChanged))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_OnModificationsChanged_ItemActionRanged(ItemActionData _data)
|
||||
{
|
||||
ItemActionRanged.ItemActionDataRanged itemActionDataRanged = _data as ItemActionRanged.ItemActionDataRanged;
|
||||
if (itemActionDataRanged.SoundStart.Contains("silenced"))
|
||||
{
|
||||
itemActionDataRanged.IsFlashSuppressed = true;
|
||||
}
|
||||
|
||||
//should fix stuck on switching item?
|
||||
itemActionDataRanged.isReloadCancelled = false;
|
||||
itemActionDataRanged.isWeaponReloadCancelled = false;
|
||||
itemActionDataRanged.isReloading = false;
|
||||
itemActionDataRanged.isWeaponReloading = false;
|
||||
itemActionDataRanged.isChangingAmmoType = false;
|
||||
}
|
||||
|
||||
#region item tags modifier
|
||||
|
||||
/// <summary>
|
||||
/// should handle swapping mod
|
||||
/// first check if the mod to install can be installed after current mod is removed
|
||||
/// then check if any other mod requires or conflicts current mod
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <param name="generator"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyPatch(typeof(XUiC_ItemPartStack), nameof(XUiC_ItemPartStack.CanSwap))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_CanSwap_XUiC_ItemPartStack(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_tags_if_remove_prev = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
LocalBuilder lbd_tags_if_install_new = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
MethodInfo mtd_get_item_class = AccessTools.PropertyGetter(typeof(ItemValue), nameof(ItemValue.ItemClass));
|
||||
MethodInfo mtd_has_any_tags = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.HasAnyTags));
|
||||
MethodInfo mtd_test_any_set = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AnySet));
|
||||
FieldInfo fld_mod = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.Modifications));
|
||||
FieldInfo fld_installable_tags = AccessTools.Field(typeof(ItemClassModifier), nameof(ItemClassModifier.InstallableTags));
|
||||
|
||||
for (int i = 3; i < codes.Count; i++)
|
||||
{
|
||||
//get current tags
|
||||
if (codes[i].opcode == OpCodes.Stloc_2)
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_1),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(XUiC_ItemPartStack), "itemValue"),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.GetTagsAsIfNotInstalled)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags_if_remove_prev),
|
||||
new CodeInstruction(OpCodes.Ldloc_1),
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.GetTagsAsIfInstalled)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags_if_install_new)
|
||||
});
|
||||
i += 10;
|
||||
Log.Out("mod 1!!!");
|
||||
}
|
||||
//replace checking tags
|
||||
else if (codes[i].Calls(mtd_has_any_tags) && codes[i - 3].opcode == OpCodes.Ldloc_2)
|
||||
{
|
||||
if (codes[i - 1].LoadsField(fld_installable_tags) && (codes[i + 1].opcode == OpCodes.Brtrue || codes[i + 1].opcode == OpCodes.Brtrue_S))
|
||||
{
|
||||
var lbl_prev = codes[i + 4].ExtractLabels();
|
||||
var lbl_jump = generator.DefineLabel();
|
||||
codes[i + 4].WithLabels(lbl_jump);
|
||||
codes.InsertRange(i + 4, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_1).WithLabels(lbl_prev),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(XUiC_ItemPartStack), "itemValue"),
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.CanSwapMod)),
|
||||
new CodeInstruction(OpCodes.Brtrue, lbl_jump),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
});
|
||||
}
|
||||
codes[i - 3].opcode = OpCodes.Ldloca_S;
|
||||
codes[i - 3].operand = lbd_tags_if_remove_prev;
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = mtd_test_any_set;
|
||||
Log.Out("mod 2!!!");
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_ItemCosmeticStack), nameof(XUiC_ItemCosmeticStack.CanSwap))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_CanSwap_XUiC_ItemCosmeticStack(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_tags_if_remove_prev = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
LocalBuilder lbd_tags_if_install_new = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
LocalBuilder lbd_item_being_assembled = generator.DeclareLocal(typeof(ItemValue));
|
||||
MethodInfo mtd_get_item_class = AccessTools.PropertyGetter(typeof(ItemValue), nameof(ItemValue.ItemClass));
|
||||
MethodInfo mtd_has_any_tags = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.HasAnyTags));
|
||||
MethodInfo mtd_test_any_set = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AnySet));
|
||||
MethodInfo mtd_get_xui = AccessTools.PropertyGetter(typeof(XUiController), nameof(XUiController.xui));
|
||||
MethodInfo mtd_get_cur_item = AccessTools.PropertyGetter(typeof(XUiM_AssembleItem), nameof(XUiM_AssembleItem.CurrentItem));
|
||||
FieldInfo fld_cos = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.CosmeticMods));
|
||||
FieldInfo fld_installable_tags = AccessTools.Field(typeof(ItemClassModifier), nameof(ItemClassModifier.InstallableTags));
|
||||
|
||||
for (int i = 3; i < codes.Count; i++)
|
||||
{
|
||||
//get current tags
|
||||
if ((codes[i].opcode == OpCodes.Brtrue || codes[i].opcode == OpCodes.Brtrue_S) && codes[i - 1].opcode == OpCodes.Ldloc_0)
|
||||
{
|
||||
codes.InsertRange(i + 3, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(codes[i + 3]),
|
||||
new CodeInstruction(OpCodes.Call, mtd_get_xui),
|
||||
CodeInstruction.LoadField(typeof(XUi), nameof(XUi.AssembleItem)),
|
||||
new CodeInstruction(OpCodes.Callvirt, mtd_get_cur_item),
|
||||
CodeInstruction.LoadField(typeof(ItemStack), nameof(ItemStack.itemValue)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_item_being_assembled),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_item_being_assembled),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(XUiC_ItemCosmeticStack), "itemValue"),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.GetTagsAsIfNotInstalled)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags_if_remove_prev),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_item_being_assembled),
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.GetTagsAsIfInstalled)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags_if_install_new)
|
||||
});
|
||||
i += 18;
|
||||
Log.Out("cos 1!!!");
|
||||
}
|
||||
//replace checking tags
|
||||
else if (codes[i].Calls(mtd_has_any_tags) && codes[i - 3].Calls(mtd_get_item_class))
|
||||
{
|
||||
if (codes[i - 1].LoadsField(fld_installable_tags) && (codes[i + 1].opcode == OpCodes.Brtrue || codes[i + 1].opcode == OpCodes.Brtrue_S))
|
||||
{
|
||||
var lbl_prev = codes[i + 4].ExtractLabels();
|
||||
var lbl_jump = generator.DefineLabel();
|
||||
codes[i + 4].WithLabels(lbl_jump);
|
||||
codes.InsertRange(i + 4, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_item_being_assembled).WithLabels(lbl_prev),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.LoadField(typeof(XUiC_ItemPartStack), "itemValue"),
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.CanSwapMod)),
|
||||
new CodeInstruction(OpCodes.Brtrue, lbl_jump),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
});
|
||||
}
|
||||
codes[i - 8].MoveLabelsTo(codes[i - 3]);
|
||||
codes[i - 3].opcode = OpCodes.Ldloca_S;
|
||||
codes[i - 3].operand = lbd_tags_if_remove_prev;
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = mtd_test_any_set;
|
||||
codes.RemoveRange(i - 8, 5);
|
||||
i -= 5;
|
||||
Log.Out("cos 2!!!");
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// check if other mods relies on this one
|
||||
/// </summary>
|
||||
/// <param name="__result"></param>
|
||||
/// <param name="__instance"></param>
|
||||
/// <param name="___itemValue"></param>
|
||||
[HarmonyPatch(typeof(XUiC_ItemPartStack), "CanRemove")]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_CanRemove_XUiC_ItemPartStack(ref bool __result, XUiC_ItemPartStack __instance)
|
||||
{
|
||||
if (__result && __instance.xui?.AssembleItem?.CurrentItem?.itemValue is ItemValue itemValue)
|
||||
{
|
||||
ItemClass itemClass = itemValue.ItemClass;
|
||||
FastTags<TagGroup.Global> tagsAfterRemove = LocalItemTagsManager.GetTagsAsIfNotInstalled(itemValue, __instance.itemValue);
|
||||
if (tagsAfterRemove.IsEmpty)
|
||||
{
|
||||
__result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var mod in itemValue.Modifications)
|
||||
{
|
||||
if (mod.IsEmpty())
|
||||
continue;
|
||||
ItemClassModifier modClass = mod.ItemClass as ItemClassModifier;
|
||||
if (modClass == null || !tagsAfterRemove.Test_AnySet(modClass.InstallableTags) || tagsAfterRemove.Test_AnySet(modClass.DisallowedTags))
|
||||
{
|
||||
__result = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_ItemCosmeticStack), "CanRemove")]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_CanRemove_XUiC_ItemCosmeticStack(ref bool __result, XUiC_ItemCosmeticStack __instance)
|
||||
{
|
||||
if (__result && __instance.xui?.AssembleItem?.CurrentItem?.itemValue is ItemValue itemValue)
|
||||
{
|
||||
ItemClass itemClass = itemValue.ItemClass;
|
||||
FastTags<TagGroup.Global> tagsAfterRemove = LocalItemTagsManager.GetTagsAsIfNotInstalled(itemValue, __instance.itemValue);
|
||||
if (tagsAfterRemove.IsEmpty)
|
||||
{
|
||||
__result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var mod in itemValue.CosmeticMods)
|
||||
{
|
||||
if (mod.IsEmpty())
|
||||
continue;
|
||||
ItemClassModifier modClass = mod.ItemClass as ItemClassModifier;
|
||||
if (modClass == null || !tagsAfterRemove.Test_AnySet(modClass.InstallableTags) || tagsAfterRemove.Test_AnySet(modClass.DisallowedTags))
|
||||
{
|
||||
__result = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// should update the gear icon?
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <param name="generator"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyPatch(typeof(XUiC_ItemStack), nameof(XUiC_ItemStack.updateLockTypeIcon))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_updateLockTypeIcon_XUiC_ItemStack(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_tags = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
MethodInfo mtd_has_any_tags = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.HasAnyTags));
|
||||
MethodInfo mtd_test_any_set = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AnySet));
|
||||
MethodInfo mtd_get_item_class = AccessTools.PropertyGetter(typeof(ItemValue), nameof(ItemValue.ItemClass));
|
||||
MethodInfo mtd_get_cur_item = AccessTools.PropertyGetter(typeof(XUiM_AssembleItem), nameof(XUiM_AssembleItem.CurrentItem));
|
||||
MethodInfo mtd_get_xui = AccessTools.PropertyGetter(typeof(XUiController), nameof(XUiController.xui));
|
||||
|
||||
for (int i = 3; i < codes.Count; i++)
|
||||
{
|
||||
//get current tags
|
||||
if ((codes[i].opcode == OpCodes.Brfalse_S || codes[i].opcode == OpCodes.Brfalse) && codes[i - 1].Calls(mtd_get_cur_item))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Call, mtd_get_xui),
|
||||
CodeInstruction.LoadField(typeof(XUi), nameof(XUi.AssembleItem)),
|
||||
new CodeInstruction(OpCodes.Callvirt, mtd_get_cur_item),
|
||||
CodeInstruction.LoadField(typeof(ItemStack), nameof(ItemStack.itemValue)),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.GetTags)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags)
|
||||
});
|
||||
i += 7;
|
||||
}
|
||||
//do not touch check on the modification item
|
||||
else if (codes[i].Calls(mtd_has_any_tags) && codes[i - 3].Calls(mtd_get_item_class))
|
||||
{
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = mtd_test_any_set;
|
||||
var insert = new CodeInstruction(OpCodes.Ldloca_S, lbd_tags);
|
||||
codes[i - 8].MoveLabelsTo(insert);
|
||||
codes.RemoveRange(i - 8, 6);
|
||||
codes.Insert(i - 8, insert);
|
||||
i -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// when installing new mod, use modified tags to check for compatibility
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <param name="generator"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyPatch(typeof(XUiM_AssembleItem), nameof(XUiM_AssembleItem.AddPartToItem))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_AddPartToItem_XUiM_AssembleItem(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
LocalBuilder lbd_tags_cur = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
LocalBuilder lbd_tags_after_install = generator.DeclareLocal(typeof(FastTags<TagGroup.Global>));
|
||||
MethodInfo mtd_has_any_tags = AccessTools.Method(typeof(ItemClass), nameof(ItemClass.HasAnyTags));
|
||||
MethodInfo mtd_test_any_set = AccessTools.Method(typeof(FastTags<TagGroup.Global>), nameof(FastTags<TagGroup.Global>.Test_AnySet));
|
||||
MethodInfo mtd_get_item_class = AccessTools.PropertyGetter(typeof(ItemValue), nameof(ItemValue.ItemClass));
|
||||
MethodInfo mtd_get_cur_item = AccessTools.PropertyGetter(typeof(XUiM_AssembleItem), nameof(XUiM_AssembleItem.CurrentItem));
|
||||
MethodInfo mtd_is_empty = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.IsEmpty));
|
||||
FieldInfo fld_cos = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.CosmeticMods));
|
||||
FieldInfo fld_mod = AccessTools.Field(typeof(ItemValue), nameof(ItemValue.Modifications));
|
||||
FieldInfo fld_installable_tags = AccessTools.Field(typeof(ItemClassModifier), nameof(ItemClassModifier.InstallableTags));
|
||||
|
||||
for (int i = 3; i < codes.Count; i++)
|
||||
{
|
||||
//get current tags
|
||||
if (codes[i].opcode == OpCodes.Stloc_0)
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Call, mtd_get_cur_item),
|
||||
CodeInstruction.LoadField(typeof(ItemStack), nameof(ItemStack.itemValue)),
|
||||
new CodeInstruction(OpCodes.Dup),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.GetTags)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags_cur),
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.GetTagsAsIfInstalled)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_tags_after_install)
|
||||
});
|
||||
i += 9;
|
||||
}
|
||||
//do not touch check on the modification item, check if current mod can be installed
|
||||
else if (codes[i].Calls(mtd_has_any_tags) && codes[i - 3].Calls(mtd_get_item_class))
|
||||
{
|
||||
if (codes[i - 1].LoadsField(fld_installable_tags))
|
||||
{
|
||||
codes.InsertRange(i + 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Call, mtd_get_cur_item),
|
||||
CodeInstruction.LoadField(typeof(ItemStack), nameof(ItemStack.itemValue)),
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
CodeInstruction.Call(typeof(LocalItemTagsManager), nameof(LocalItemTagsManager.CanInstallMod)),
|
||||
new CodeInstruction(OpCodes.Brfalse, codes[i + 1].operand)
|
||||
});
|
||||
}
|
||||
codes[i].opcode = OpCodes.Call;
|
||||
codes[i].operand = mtd_test_any_set;
|
||||
var insert = new CodeInstruction(OpCodes.Ldloca_S, lbd_tags_cur);
|
||||
codes[i - 6].MoveLabelsTo(insert);
|
||||
codes.RemoveRange(i - 6, 4);
|
||||
codes.Insert(i - 6, insert);
|
||||
i -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
//change when aiming events are fired
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.SetMoveState))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetMoveState_EntityPlayerLocal(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
FieldInfo fld_msa = AccessTools.Field(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.moveStateAiming));
|
||||
|
||||
for (int i = 0; i < codes.Count - 2; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_msa) && codes[i + 2].opcode == OpCodes.Ldloc_1)
|
||||
{
|
||||
codes[i - 2].MoveLabelsTo(codes[i + 13]);
|
||||
codes.RemoveRange(i - 2, 15);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityAlive), nameof(EntityAlive.AimingGun), MethodType.Setter)]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_AimingGun_EntityAlive(bool value, EntityAlive __instance)
|
||||
{
|
||||
if (__instance is EntityPlayerLocal && __instance.inventory != null)
|
||||
{
|
||||
bool isAimingGun = __instance.AimingGun;
|
||||
if (value != isAimingGun)
|
||||
{
|
||||
__instance.FireEvent(value ? MinEventTypes.onSelfAimingGunStart : MinEventTypes.onSelfAimingGunStop, true);
|
||||
#if DEBUG
|
||||
Log.Out(value ? "START AIMING GUN FIRED" : "STOP AIMING GUN FIRED");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionAttack), nameof(ItemActionAttack.HasRadial))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_HasRadial_ItemActionAttack(ref bool __result)
|
||||
{
|
||||
EntityPlayerLocal player = GameManager.Instance.World?.GetPrimaryPlayer();
|
||||
int index = MultiActionManager.GetActionIndexForEntity(player);
|
||||
List<ItemActionData> actionDatas = player.inventory?.holdingItemData?.actionData;
|
||||
if (actionDatas != null && actionDatas.Count > index && actionDatas[index] is ItemActionRanged.ItemActionDataRanged rangedData && (rangedData.isReloading || rangedData.isWeaponReloading))
|
||||
{
|
||||
__result = false;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionAttack), nameof(ItemActionAttack.SetupRadial))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetupRadial_ItemActionAttack(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_usable = AccessTools.Field(typeof(ItemClass), nameof(ItemClass.UsableUnderwater));
|
||||
|
||||
var lbd_states = generator.DeclareLocal(typeof(bool[]));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Stloc_0)
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
new CodeInstruction(OpCodes.Ldarg_2),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_M1),
|
||||
CodeInstruction.Call(typeof(CommonUtilityPatch), nameof(CommonUtilityPatch.GetUnusableItemEntries)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, lbd_states)
|
||||
});
|
||||
i += 4;
|
||||
}
|
||||
else if (codes[i].LoadsField(fld_usable))
|
||||
{
|
||||
codes.InsertRange(i + 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, lbd_states).WithLabels(codes[i + 2].ExtractLabels()),
|
||||
new CodeInstruction(OpCodes.Ldloc_2),
|
||||
CodeInstruction.Call(typeof(CommonUtilityPatch), nameof(CommonUtilityPatch.IsAmmoDisabled)),
|
||||
new CodeInstruction(OpCodes.Brtrue_S, codes[i + 1].operand)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemAction), nameof(ItemAction.StartHolding))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_StartHolding_ItemAction(ItemActionData _data, ItemAction __instance)
|
||||
{
|
||||
if (__instance is ItemActionAttack itemActionAttack && _data.invData.holdingEntity is EntityPlayerLocal player)
|
||||
{
|
||||
var arr_disabled_ammo = GetUnusableItemEntries(itemActionAttack.MagazineItemNames, player, _data.indexInEntityOfAction);
|
||||
if (arr_disabled_ammo == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var itemValue = _data.invData.itemValue;
|
||||
int cur_index = itemValue.GetSelectedAmmoIndexByActionIndex(_data.indexInEntityOfAction);
|
||||
if (arr_disabled_ammo[cur_index])
|
||||
{
|
||||
int first_enabled_index = Mathf.Max(Array.IndexOf(arr_disabled_ammo, false), 0);
|
||||
|
||||
var mapping = MultiActionManager.GetMappingForEntity(player.entityId);
|
||||
if (mapping != null)
|
||||
{
|
||||
if (_data.indexInEntityOfAction == mapping.CurMetaIndex)
|
||||
{
|
||||
itemValue.SelectedAmmoTypeIndex = (byte)first_enabled_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemValue.SetMetadata(MultiActionUtils.ActionSelectedAmmoNames[mapping.indices.GetMetaIndexForActionIndex(_data.indexInEntityOfAction)], first_enabled_index, TypedMetadataValue.TypeTag.Integer);
|
||||
}
|
||||
_data.invData.holdingEntity.inventory.CallOnToolbeltChangedInternal();
|
||||
}
|
||||
else
|
||||
{
|
||||
itemValue.SelectedAmmoTypeIndex = (byte)(first_enabled_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool[] GetUnusableItemEntries(string[] ammoNames, EntityPlayerLocal player, int actionIndex = -1)
|
||||
{
|
||||
if (ammoNames == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (actionIndex < 0)
|
||||
{
|
||||
actionIndex = MultiActionManager.GetActionIndexForEntity(player);
|
||||
}
|
||||
string str_disabled_ammo_names = player.inventory.holdingItemItemValue.GetPropertyOverrideForAction("DisableAmmo", "", actionIndex);
|
||||
//Log.Out($"checking disabled ammo: {str_disabled_ammo_names}\n{StackTraceUtility.ExtractStackTrace()}");
|
||||
bool[] arr_disable_states = new bool[ammoNames.Length];
|
||||
if(!string.IsNullOrEmpty(str_disabled_ammo_names))
|
||||
{
|
||||
string[] arr_disabled_ammo_names = str_disabled_ammo_names.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var name in arr_disabled_ammo_names)
|
||||
{
|
||||
int index = Array.IndexOf(ammoNames, name.Trim());
|
||||
if (index >= 0)
|
||||
{
|
||||
arr_disable_states[index] = true;
|
||||
if (ConsoleCmdReloadLog.LogInfo)
|
||||
Log.Out($"ammo {ammoNames[index]} is disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr_disable_states;
|
||||
}
|
||||
|
||||
private static bool IsAmmoDisabled(bool[] ammoStates, int index)
|
||||
{
|
||||
if (ammoStates == null || ammoStates.Length <= index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ammoStates[index];
|
||||
}
|
||||
|
||||
//dont spread onSelfItemActivate/onSelfItemDeactivate to attachments
|
||||
//handle start holding
|
||||
[HarmonyPatch(typeof(Inventory), nameof(Inventory.syncHeldItem))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_syncHeldItem_Inventory(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var prop_itemvalue = AccessTools.PropertyGetter(typeof(Inventory), nameof(Inventory.holdingItemItemValue));
|
||||
var mtd_fireevent = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.FireEvent));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_fireevent) && codes[i - 5].Calls(prop_itemvalue))
|
||||
{
|
||||
codes[i] = CodeInstruction.Call(typeof(MinEffectController), nameof(MinEffectController.FireEvent));
|
||||
codes.InsertRange(i - 4, new[]
|
||||
{
|
||||
CodeInstruction.Call(typeof(ItemValue), "get_ItemClass"),
|
||||
CodeInstruction.LoadField(typeof(ItemClass), nameof(ItemClass.Effects))
|
||||
});
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
//handle radial activation
|
||||
[HarmonyPatch(typeof(XUiC_Radial), nameof(XUiC_Radial.handleActivatableItemCommand))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_handleActivatableItemCommand_XUiC_Radial(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_fireevent = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.FireEvent));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_fireevent))
|
||||
{
|
||||
codes[i] = CodeInstruction.Call(typeof(MinEffectController), nameof(MinEffectController.FireEvent));
|
||||
codes.InsertRange(i - 2, new[]
|
||||
{
|
||||
CodeInstruction.Call(typeof(ItemValue), "get_ItemClass"),
|
||||
CodeInstruction.LoadField(typeof(ItemClass), nameof(ItemClass.Effects))
|
||||
});
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
//handle equipments
|
||||
[HarmonyPatch(typeof(Equipment), nameof(Equipment.SetSlotItem))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_SetSlotItem_Equipment(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_fireevent = AccessTools.Method(typeof(ItemValue), nameof(ItemValue.FireEvent));
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_fireevent) && codes[i - 5].opcode == OpCodes.Ldloc_0 && codes[i - 4].OperandIs((int)MinEventTypes.onSelfItemDeactivate))
|
||||
{
|
||||
codes[i] = CodeInstruction.Call(typeof(MinEffectController), nameof(MinEffectController.FireEvent));
|
||||
codes.InsertRange(i - 4, new[]
|
||||
{
|
||||
CodeInstruction.Call(typeof(ItemValue), "get_ItemClass"),
|
||||
CodeInstruction.LoadField(typeof(ItemClass), nameof(ItemClass.Effects))
|
||||
});
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.DropContentOfLootContainerServer))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_DropContentOfLootContainerServer_GameManager(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var setter_localscale = AccessTools.PropertySetter(typeof(Transform), nameof(Transform.localScale));
|
||||
|
||||
for (var i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(setter_localscale))
|
||||
{
|
||||
codes.RemoveRange(i - 6, 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.onHoldingEntityFired))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_onHoldingEntityFired_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Ldc_R4 && codes[i].operand is 5f)
|
||||
{
|
||||
codes.RemoveAt(i);
|
||||
codes.InsertRange(i, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
CodeInstruction.Call(typeof(CommonUtilityPatch), nameof(CommonUtilityPatch.GetMaxSpread))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static float GetMaxSpread(ItemActionData _data)
|
||||
{
|
||||
return EffectManager.GetValue(CustomEnums.MaxWeaponSpread, _data.invData.itemValue, 5f, _data.invData.holdingEntity);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(NetEntityDistributionEntry), nameof(NetEntityDistributionEntry.getSpawnPacket))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_getSpawnPacket_NetEntityDistributionEntry(NetEntityDistributionEntry __instance, ref NetPackage __result)
|
||||
{
|
||||
if (__instance.trackedEntity is EntityAlive ea)
|
||||
{
|
||||
__result = NetPackageManager.GetPackage<NetPackageEntitySpawnWithCVar>().Setup(new EntityCreationData(__instance.trackedEntity, true), (EntityAlive)__instance.trackedEntity);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(World), nameof(World.SpawnEntityInWorld))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SpawnEntityInWorld_World(Entity _entity)
|
||||
{
|
||||
if (_entity is EntityAlive ea && !ea.isEntityRemote)
|
||||
{
|
||||
ea.FireEvent(CustomEnums.onSelfFirstCVarSync);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ItemActionRanged), nameof(ItemActionRanged.ItemActionEffects))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_ItemActionEffects_ItemActionRanged(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
for (int i = 0; i < codes.Count - 2; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Ldloc_S && ((LocalBuilder)codes[i].operand).LocalIndex == 9 && codes[i + 2].Branches(out _))
|
||||
{
|
||||
codes.InsertRange(i + 3, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, codes[i].operand).WithLabels(codes[i + 3].ExtractLabels()),
|
||||
CodeInstruction.Call(typeof(CommonUtilityPatch), nameof(AddTmpMuzzleFlash)),
|
||||
});
|
||||
i += 5;
|
||||
}
|
||||
else if (codes[i].opcode == OpCodes.Ldloc_S && ((LocalBuilder)codes[i].operand).LocalIndex == 12 && codes[i + 2].Branches(out _))
|
||||
{
|
||||
codes.InsertRange(i + 3, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_S, codes[i].operand).WithLabels(codes[i + 3].ExtractLabels()),
|
||||
CodeInstruction.Call(typeof(CommonUtilityPatch), nameof(AddTmpMuzzleFlash)),
|
||||
});
|
||||
i += 5;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static void AddTmpMuzzleFlash(Transform trans)
|
||||
{
|
||||
if (trans.TryGetComponent<TemporaryObject>(out var tmp))
|
||||
{
|
||||
tmp.StopAllCoroutines();
|
||||
Component.Destroy(tmp);
|
||||
}
|
||||
tmp = trans.AddMissingComponent<TemporaryMuzzleFlash>();
|
||||
tmp.life = 5f;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(vp_FPCamera), nameof(vp_FPCamera.UpdateShakes))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_UpdateShakes_vp_FPCamera(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var fld_shake = AccessTools.Field(typeof(vp_FPCamera), nameof(vp_FPCamera.m_Shake));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].StoresField(fld_shake))
|
||||
{
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
CodeInstruction.Call(typeof(CommonUtilityPatch), nameof(CheckShakeNaN))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static void CheckShakeNaN(vp_FPCamera fpcamera)
|
||||
{
|
||||
if (float.IsNaN(fpcamera.m_Shake.x) || float.IsNaN(fpcamera.m_Shake.y) || float.IsNaN(fpcamera.m_Shake.z))
|
||||
{
|
||||
Log.Warning("Shake1 NaN {0}, time {1}, speed {2}, amp {3}", new object[]
|
||||
{
|
||||
fpcamera.m_Shake,
|
||||
Time.time,
|
||||
fpcamera.ShakeSpeed,
|
||||
fpcamera.ShakeAmplitude
|
||||
});
|
||||
fpcamera.ShakeSpeed = 0f;
|
||||
fpcamera.m_Shake = Vector3.zero;
|
||||
fpcamera.m_Pitch += -1f;
|
||||
}
|
||||
}
|
||||
|
||||
//[HarmonyPatch(typeof(EntityBuffs), nameof(EntityBuffs.AddBuff), typeof(string), typeof(Vector3i), typeof(int), typeof(bool), typeof(bool), typeof(float))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_AddBuff_EntityBuffs(string _name, EntityBuffs __instance, EntityBuffs.BuffStatus __result, bool _netSync)
|
||||
//{
|
||||
// if (_name.StartsWith("eftZombieRandomArmor") || _name.StartsWith("eftZombieArmor"))
|
||||
// Log.Out($"AddBuff [{_name}] on entity {__instance.parent.GetDebugName()} should sync {_netSync} result {__result.ToStringCached()}\n{StackTraceUtility.ExtractStackTrace()}");
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(EntityBuffs), nameof(EntityBuffs.RemoveBuff))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_RemoveBuff_EntityBuffs(string _name, EntityBuffs __instance, bool _netSync)
|
||||
//{
|
||||
// if (_name.StartsWith("eftZombieRandomArmor") || _name.StartsWith("eftZombieArmor"))
|
||||
// Log.Out($"RemoveBuff [{_name}] on entity {__instance.parent.GetDebugName()} should sync {_netSync}\n{StackTraceUtility.ExtractStackTrace()}");
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(Inventory), nameof(Inventory.Execute))]
|
||||
//[HarmonyPrefix]
|
||||
//private static void Prefix_Execute_Inventory(Inventory __instance, int _actionIdx, bool _bReleased, PlayerActionsLocal _playerActions = null)
|
||||
//{
|
||||
// Log.Out($"Execute Inventory holding item {__instance.holdingItem.Name} slot {__instance.holdingItemIdx} action index {_actionIdx} released {_bReleased} is holster delay {__instance.IsHolsterDelayActive()} is unholster delay {__instance.IsUnholsterDelayActive()}");
|
||||
//}
|
||||
|
||||
//[HarmonyPatch(typeof(Inventory), nameof(Inventory.updateHoldingItem))]
|
||||
//[HarmonyTranspiler]
|
||||
//private static IEnumerable<CodeInstruction> Transpiler_updateHoldingItem_Inventory(IEnumerable<CodeInstruction> instructions)
|
||||
//{
|
||||
// var codes = instructions.ToList();
|
||||
|
||||
// var mtd_setholdingtrans = AccessTools.Method(typeof(Inventory), nameof(Inventory.setHoldingItemTransfrom));
|
||||
// var mtd_showrighthand = AccessTools.Method(typeof(Inventory), nameof(Inventory.ShowRightHand));
|
||||
// int insert = -1, take = -1;
|
||||
|
||||
// for (int i = 0; i < codes.Count; i++)
|
||||
// {
|
||||
// if (codes[i].Calls(mtd_showrighthand))
|
||||
// {
|
||||
// insert = i + 1;
|
||||
// }
|
||||
// else if (codes[i].Calls(mtd_setholdingtrans))
|
||||
// {
|
||||
// take = i - 6;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (take > insert)
|
||||
// {
|
||||
// var list_take = codes.GetRange(take, 7);
|
||||
// codes.RemoveRange(take, 7);
|
||||
// codes.InsertRange(insert, list_take);
|
||||
// }
|
||||
|
||||
// return codes;
|
||||
//}
|
||||
//private static bool exported = false;
|
||||
//[HarmonyPatch(typeof(EModelSDCS), nameof(EModelSDCS.createModel))]
|
||||
//[HarmonyPostfix]
|
||||
//private static void Postfix_test(EModelSDCS __instance)
|
||||
//{
|
||||
// if (!exported)
|
||||
// {
|
||||
// exported = true;
|
||||
// var objects = new[] { __instance.entity.RootTransform.gameObject.GetComponentsInChildren<Animator>()[1] };
|
||||
// Log.Out($"exporting objs: {objects.Length} avatar {objects[0].avatar.name} is human {objects[0].avatar.isHuman}");
|
||||
// FbxExporter07.OnExport(objects, @"E:\Unity Projects\AnimationPlayground\Assets\ExportedProject\example_skinned_mesh_with_bones.fbx");
|
||||
// Application.Quit();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
156
Harmony/RecoilPatch.cs
Normal file
156
Harmony/RecoilPatch.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using HarmonyLib;
|
||||
using KFCommonUtilityLib.Scripts.StaticManagers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using UnityEngine;
|
||||
using CameraShake;
|
||||
using System;
|
||||
|
||||
[HarmonyPatch]
|
||||
class RecoilPatch
|
||||
{
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), "Awake")]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_Awake_EntityPlayerLocal(EntityPlayerLocal __instance)
|
||||
{
|
||||
RecoilManager.InitPlayer(__instance);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(vp_FPCamera), nameof(vp_FPCamera.LateUpdate))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_LateUpdate_vp_FPCamera(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
var mtd_update = AccessTools.Method(typeof(vp_FPCamera), nameof(vp_FPCamera.Update3rdPerson));
|
||||
var prop_trans = AccessTools.PropertyGetter(typeof(vp_Component), nameof(vp_Component.transform));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].Calls(mtd_update))
|
||||
{
|
||||
codes.InsertRange(i - 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Call, prop_trans),
|
||||
CodeInstruction.Call(typeof(KFExtensions), nameof(KFExtensions.AddMissingComponent), new Type[]{ typeof(Transform) }, new Type[]{ typeof(CameraShaker) }),
|
||||
CodeInstruction.Call(typeof(CameraShaker), nameof(CameraShaker.UpdateShake))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameManager), nameof(GameManager.SaveAndCleanupWorld))]
|
||||
[HarmonyPostfix]
|
||||
private static void Postfix_SaveAndCleanupWorld_GameManager()
|
||||
{
|
||||
RecoilManager.Cleanup();
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.OnFired))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_OnFired_EntityPlayerLocal(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
FieldInfo fld_isfpv = AccessTools.Field(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.bFirstPersonView));
|
||||
ConstructorInfo mtd_ctor = AccessTools.Constructor(typeof(Vector2), new[] { typeof(float), typeof(float) });
|
||||
|
||||
for (int i = 0; i < codes.Count - 1; i++)
|
||||
{
|
||||
if (codes[i].Is(OpCodes.Call, mtd_ctor) && codes[i + 1].opcode == OpCodes.Ldloc_0)
|
||||
{
|
||||
for (int j = i + 1; j < codes.Count - 1; j++)
|
||||
{
|
||||
if (codes[j].opcode == OpCodes.Pop && codes[j + 1].opcode == OpCodes.Ldarg_0)
|
||||
{
|
||||
codes.RemoveRange(i + 1, j - i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
codes.InsertRange(i + 1, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldloca_S, 0),
|
||||
new CodeInstruction(OpCodes.Ldloca_S, 1),
|
||||
CodeInstruction.Call(typeof(RecoilPatch), nameof(RecoilPatch.ModifyRecoil))
|
||||
});
|
||||
i += 4;
|
||||
}
|
||||
else if (codes[i].LoadsField(fld_isfpv))
|
||||
{
|
||||
codes.RemoveRange(i + 2, codes.Count - i - 3);
|
||||
codes.InsertRange(i + 2, new[]
|
||||
{
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
new CodeInstruction(OpCodes.Ldloc_1),
|
||||
CodeInstruction.Call(typeof(RecoilManager), nameof(RecoilManager.AddRecoil))
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static void ModifyRecoil(EntityPlayerLocal player, ref Vector2 kickHor, ref Vector2 kickVer)
|
||||
{
|
||||
float multiplierHor = Mathf.Max(1 - EffectManager.GetValue(CustomEnums.KickDegreeHorizontalModifier, player.inventory.holdingItemItemValue, 0f, player), 0);
|
||||
float multiplierVer = Mathf.Max(1 - EffectManager.GetValue(CustomEnums.KickDegreeVerticalModifier, player.inventory.holdingItemItemValue, 0f, player), 0);
|
||||
kickHor *= multiplierHor;
|
||||
kickVer *= multiplierVer;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerMoveController), nameof(PlayerMoveController.Update))]
|
||||
[HarmonyTranspiler]
|
||||
private static IEnumerable<CodeInstruction> Transpiler_Update_PlayerMoveController(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var codes = instructions.ToList();
|
||||
|
||||
FieldInfo fld_rotation = AccessTools.Field(typeof(MovementInput), nameof(MovementInput.rotation));
|
||||
FieldInfo fld_rx = AccessTools.Field(typeof(Vector3), nameof(Vector3.x));
|
||||
FieldInfo fld_ry = AccessTools.Field(typeof(Vector3), nameof(Vector3.y));
|
||||
|
||||
for (int i = 0; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].LoadsField(fld_rotation, true))
|
||||
{
|
||||
if (codes[i + 1].LoadsField(fld_rx, true))
|
||||
{
|
||||
for (; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Stind_R4)
|
||||
{
|
||||
codes.Insert(i, CodeInstruction.Call(typeof(RecoilManager), nameof(RecoilManager.CompensateX)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (codes[i + 1].LoadsField(fld_ry, true))
|
||||
{
|
||||
for (; i < codes.Count; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Stind_R4)
|
||||
{
|
||||
codes.Insert(i, CodeInstruction.Call(typeof(RecoilManager), nameof(RecoilManager.CompensateY)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(EntityPlayerLocal), nameof(EntityPlayerLocal.MoveByInput))]
|
||||
[HarmonyPrefix]
|
||||
private static bool Prefix_MoveByInput_EntityPlayerLocal()
|
||||
{
|
||||
RecoilManager.ApplyRecoil();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
6
Harmony/SaveRescuePatches.cs
Normal file
6
Harmony/SaveRescuePatches.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace KFCommonUtilityLib.Harmony
|
||||
{
|
||||
public static class SaveRescuePatches
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user