Decompiled source of FistAttackMod v1.0.0

plugins/FistAttackPlugin.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("FistAttackPlugin")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FistAttackPlugin")]
[assembly: AssemblyTitle("FistAttackPlugin")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FistAttackPlugin;

internal static class FistWeaponFilter
{
	internal static bool Matches(ItemData weapon)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Invalid comparison between Unknown and I4
		if (weapon?.m_shared == null)
		{
			return false;
		}
		if ((int)weapon.m_shared.m_skillType == 11)
		{
			return true;
		}
		GameObject dropPrefab = weapon.m_dropPrefab;
		string text = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? string.Empty;
		return text.IndexOf("Fist", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Claw", StringComparison.OrdinalIgnoreCase) >= 0;
	}
}
internal static class FistBaselineKick
{
	private static Attack _cached;

	internal static Attack Get(Humanoid humanoid)
	{
		if (_cached != null)
		{
			return _cached;
		}
		Attack val = humanoid?.m_unarmedWeapon?.m_itemData?.m_shared?.m_secondaryAttack;
		if (val == null)
		{
			Plugin.Log.LogWarning((object)"[FistChain] Humanoid.m_unarmedWeapon에서 발차기(2차 공격)를 찾지 못했습니다. 3타 체인이 비활성화됩니다.");
			return null;
		}
		_cached = val;
		return _cached;
	}
}
internal static class FistChainSystem
{
	private sealed class ChainState
	{
		public int Level;
	}

	private static readonly ConditionalWeakTable<Character, ChainState> _states = new ConditionalWeakTable<Character, ChainState>();

	private static readonly HashSet<Character> _pendingPrimary = new HashSet<Character>();

	private const float ChainMaxTime = 0.2f;

	internal static void OnPrimaryStartAttempt(Humanoid humanoid)
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		if (!Plugin.FcEnable.Value)
		{
			return;
		}
		ItemData currentWeapon = humanoid.GetCurrentWeapon();
		if (!FistWeaponFilter.Matches(currentWeapon) || FistBaselineKick.Get(humanoid) == null)
		{
			return;
		}
		if (Plugin.FcMinSkillLevel.Value > 0f)
		{
			Player val = (Player)(object)((humanoid is Player) ? humanoid : null);
			if (val != null && ((Character)val).GetSkillLevel((SkillType)11) < Plugin.FcMinSkillLevel.Value)
			{
				return;
			}
		}
		_pendingPrimary.Add((Character)humanoid);
	}

	internal static void ClearPendingIfLeftover(Character ch)
	{
		_pendingPrimary.Remove(ch);
	}

	internal static bool TryConsumePending(Character ch)
	{
		return _pendingPrimary.Remove(ch);
	}

	internal static int GetLevel(Character ch, float timeSinceLastAttack)
	{
		ChainState value = _states.GetValue(ch, (Character _) => new ChainState());
		if (timeSinceLastAttack > 0.2f)
		{
			value.Level = 0;
		}
		return value.Level;
	}

	internal static void SetLevel(Character ch, int level)
	{
		ChainState value = _states.GetValue(ch, (Character _) => new ChainState());
		value.Level = level;
	}
}
[HarmonyPatch(typeof(Humanoid), "StartAttack")]
internal static class HumanoidStartAttack_FistChain_Patch
{
	private static void Prefix(Humanoid __instance, bool secondaryAttack)
	{
		if (!secondaryAttack)
		{
			FistChainSystem.OnPrimaryStartAttempt(__instance);
		}
	}

	private static void Postfix(Humanoid __instance)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		FistChainSystem.ClearPendingIfLeftover((Character)__instance);
	}
}
[HarmonyPatch(typeof(Attack), "Start")]
internal static class AttackStart_FistChain_Patch
{
	private static void Prefix(Attack __instance, Humanoid character, ItemData weapon, float timeSinceLastAttack)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		Character ch = (Character)character;
		if (!FistChainSystem.TryConsumePending(ch) || !FistWeaponFilter.Matches(weapon))
		{
			return;
		}
		Attack val = FistBaselineKick.Get(character);
		if (val != null)
		{
			int level = FistChainSystem.GetLevel(ch, timeSinceLastAttack);
			if (level < 2)
			{
				FistChainSystem.SetLevel(ch, level + 1);
				return;
			}
			__instance.m_attackAnimation = val.m_attackAnimation;
			__instance.m_attackChainLevels = 0;
			__instance.m_attackRandomAnimations = 0;
			__instance.m_attackType = val.m_attackType;
			__instance.m_attackRange = val.m_attackRange;
			__instance.m_attackHeight = val.m_attackHeight;
			__instance.m_attackOffset = val.m_attackOffset;
			__instance.m_attackAngle = val.m_attackAngle;
			__instance.m_attackRayWidth = val.m_attackRayWidth;
			__instance.m_maxYAngle = val.m_maxYAngle;
			__instance.m_forceMultiplier = val.m_forceMultiplier;
			__instance.m_damageMultiplier = val.m_damageMultiplier * Mathf.Max(0f, Plugin.FcKickDamageMult.Value);
			__instance.m_staggerMultiplier = val.m_staggerMultiplier;
			__instance.m_attackStamina = val.m_attackStamina;
			__instance.m_attackEitr = val.m_attackEitr;
			__instance.m_attackHealth = val.m_attackHealth;
			__instance.m_attackHealthPercentage = val.m_attackHealthPercentage;
			__instance.m_attackHealthReturnHit = val.m_attackHealthReturnHit;
			__instance.m_attackHealthLowBlockUse = val.m_attackHealthLowBlockUse;
			__instance.m_attackStartNoise = val.m_attackStartNoise;
			__instance.m_attackHitNoise = val.m_attackHitNoise;
			__instance.m_hitTerrain = val.m_hitTerrain;
			__instance.m_hitFriendly = val.m_hitFriendly;
			__instance.m_hitThroughWalls = val.m_hitThroughWalls;
			__instance.m_multiHit = val.m_multiHit;
			__instance.m_lowerDamagePerHit = val.m_lowerDamagePerHit;
			__instance.m_hitPointtype = val.m_hitPointtype;
			__instance.m_recoilPushback = val.m_recoilPushback;
			FistChainSystem.SetLevel(ch, 0);
		}
	}
}
[BepInPlugin("com.fistattack.plugin", "FistAttackMod", "1.0.0")]
[BepInProcess("valheim.exe")]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "com.fistattack.plugin";

	public const string NAME = "FistAttackMod";

	public const string VERSION = "1.0.0";

	private readonly Harmony _harmony = new Harmony("com.fistattack.plugin");

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> FcEnable;

	internal static ConfigEntry<float> FcKickDamageMult;

	internal static ConfigEntry<float> FcMinSkillLevel;

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		FcEnable = ((BaseUnityPlugin)this).Config.Bind<bool>("FistChain", "Enable", true, "Fist(주먹/클로/Warfare 등) 계열 무기 — 좌클릭 3연타: 펀치 + 펀치 + 킥(바닐라 Fists 발차기 고정 사용). 무기 고유의 2차 공격(우클릭 특수기)은 그대로 유지되며 3타 체인과 무관함.");
		FcKickDamageMult = ((BaseUnityPlugin)this).Config.Bind<float>("FistChain", "KickDamageMult", 2f, "3타(킥) 데미지 배율 — 바닐라 Fists 발차기 데미지에 곱함 (1.0 = 원래 발차기 데미지 그대로)");
		FcMinSkillLevel = ((BaseUnityPlugin)this).Config.Bind<float>("FistChain", "MinSkillLevel", 0f, "스킬 발동 최소 레벨 — Unarmed (0~100, 0 = 제한 없음)");
		_harmony.PatchAll();
		Log.LogInfo((object)"FistAttackMod 1.0.0 로드 완료");
	}

	private void OnDestroy()
	{
		_harmony.UnpatchSelf();
	}
}