Decompiled source of SalskeriSoulAxe v1.0.0

plugins\SalskeriSoulAxe.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SalskeriSoulAxe")]
[assembly: AssemblyDescription("Salskeri Soul Axe custom Valheim weapon mod.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SalskeriSoulAxe")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("842c8317-74f1-4a7a-b31d-d25793cbaf1f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SalskeriSoulAxe;

[BepInPlugin("samuel.valheim.salskerisoulaxe", "SalskeriSoulAxe", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class SalskeriSoulAxe : BaseUnityPlugin
{
	public const string PluginGuid = "samuel.valheim.salskerisoulaxe";

	public const string PluginName = "SalskeriSoulAxe";

	public const string PluginVersion = "1.0.0";

	private const string WeaponIconFileName = "SalskeriSprite.png";

	private static string PluginFolder;

	private static ConfigEntry<string> WeaponSourcePrefab;

	private static ConfigEntry<string> WeaponDisplayName;

	private static ConfigEntry<string> WeaponDescription;

	private static ConfigEntry<string> WeaponCraftingStation;

	private static ConfigEntry<int> WeaponMinStationLevel;

	private static ConfigEntry<string> RecipeRequirementOneItem;

	private static ConfigEntry<int> RecipeRequirementOneAmount;

	private static ConfigEntry<string> RecipeRequirementTwoItem;

	private static ConfigEntry<int> RecipeRequirementTwoAmount;

	private static ConfigEntry<string> RecipeRequirementThreeItem;

	private static ConfigEntry<int> RecipeRequirementThreeAmount;

	private static ConfigEntry<float> SlashDamage;

	private static ConfigEntry<float> SpiritDamage;

	private static ConfigEntry<float> MaxDurability;

	private static ConfigEntry<float> BlockPower;

	private static ConfigEntry<float> BlockForce;

	private static ConfigEntry<float> ParryBonus;

	private static ConfigEntry<float> Knockback;

	private static ConfigEntry<float> MovementModifier;

	private static ConfigEntry<float> PrimaryAttackStamina;

	private static ConfigEntry<float> SecondaryAttackRange;

	private static ConfigEntry<float> SecondaryAttackAngle;

	private static ConfigEntry<float> SecondaryAttackRayWidth;

	private static ConfigEntry<bool> SecondaryUseHitboxPrefab;

	private static ConfigEntry<string> SecondaryHitboxPrefab;

	private static ConfigEntry<bool> SecondaryCopyHitboxAttackType;

	private static ConfigEntry<bool> SecondaryHitMultipleTargets;

	private static ConfigEntry<bool> SecondaryLowerDamagePerHit;

	private static ConfigEntry<float> SecondaryAttackStamina;

	private static ConfigEntry<float> SecondaryDamageMultiplier;

	private static ConfigEntry<float> AimBlinkMaxDistance;

	private static ConfigEntry<float> DodgeBlinkDistance;

	private static ConfigEntry<string> AimBlinkStartSfx;

	private static ConfigEntry<string> BlinkDodgeVfx;

	private static ConfigEntry<string> BlinkDodgeFallbackVfx;

	private static ConfigEntry<string> BlinkDodgeSfx;

	internal static ConfigEntry<bool> GreenFlameEnabled;

	internal static ConfigEntry<string> GreenFlamePrefab;

	internal static ConfigEntry<float> GreenFlamePositionX;

	internal static ConfigEntry<float> GreenFlamePositionY;

	internal static ConfigEntry<float> GreenFlamePositionZ;

	internal static ConfigEntry<float> GreenFlameRotationX;

	internal static ConfigEntry<float> GreenFlameRotationY;

	internal static ConfigEntry<float> GreenFlameRotationZ;

	internal static ConfigEntry<float> GreenFlameScaleX;

	internal static ConfigEntry<float> GreenFlameScaleY;

	internal static ConfigEntry<float> GreenFlameScaleZ;

	internal static ConfigEntry<string> GreenFlameColorHex;

	internal static ConfigEntry<float> GreenFlameAlpha;

	internal static ConfigEntry<float> GreenFlameBrightness;

	internal static ConfigEntry<float> GreenFlameVolume;

	internal static ConfigEntry<bool> GreenFlameOnBack;

	internal static ConfigEntry<bool> GreenFlameOnItemStands;

	internal static ConfigEntry<bool> GreenFlameComfortEnabled;

	internal static ConfigEntry<int> GreenFlameComfort;

	private float nextVisualCheck;

	private static bool loggedBlinkDodgeEffectPrefab;

	internal static ManualLogSource Log { get; private set; }

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		PluginFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		BindConfig();
		PrefabManager.OnVanillaPrefabsAvailable += AddCustomItems;
	}

	private void BindConfig()
	{
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Expected O, but got Unknown
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		//IL_035c: Expected O, but got Unknown
		//IL_047b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0485: Expected O, but got Unknown
		//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c2: Expected O, but got Unknown
		//IL_05c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d3: Expected O, but got Unknown
		//IL_0606: Unknown result type (might be due to invalid IL or missing references)
		//IL_0610: Expected O, but got Unknown
		//IL_0643: Unknown result type (might be due to invalid IL or missing references)
		//IL_064d: Expected O, but got Unknown
		//IL_0680: Unknown result type (might be due to invalid IL or missing references)
		//IL_068a: Expected O, but got Unknown
		//IL_06bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c7: Expected O, but got Unknown
		//IL_06fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0704: Expected O, but got Unknown
		//IL_0737: Unknown result type (might be due to invalid IL or missing references)
		//IL_0741: Expected O, but got Unknown
		//IL_0774: Unknown result type (might be due to invalid IL or missing references)
		//IL_077e: Expected O, but got Unknown
		//IL_07b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_07bb: Expected O, but got Unknown
		//IL_0812: Unknown result type (might be due to invalid IL or missing references)
		//IL_081c: Expected O, but got Unknown
		//IL_084f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0859: Expected O, but got Unknown
		//IL_088c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0896: Expected O, but got Unknown
		//IL_091e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0928: Expected O, but got Unknown
		WeaponSourcePrefab = ((BaseUnityPlugin)this).Config.Bind<string>("Weapon", "Source Prefab", "AxeJotunBane", "Valheim prefab copied to create this weapon. Requires game restart after changing.");
		WeaponDisplayName = ((BaseUnityPlugin)this).Config.Bind<string>("Weapon", "Display Name", "Sálskeri", "Name shown in-game. Requires game restart after changing.");
		WeaponDescription = ((BaseUnityPlugin)this).Config.Bind<string>("Weapon", "Description", "A spirit axe made from remnants of a lower realm.", "Description shown in-game. Requires game restart after changing.");
		WeaponCraftingStation = ((BaseUnityPlugin)this).Config.Bind<string>("Weapon", "Crafting Station", "piece_magetable", "Crafting station prefab name. Requires game restart after changing.");
		WeaponMinStationLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Weapon", "Minimum Station Level", 1, "Required crafting station level. Requires game restart after changing.");
		RecipeRequirementOneItem = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "Requirement 1 Item", "Blackwood", "First recipe item prefab name. Ashwood uses the prefab ID Blackwood. Requires game restart after changing.");
		RecipeRequirementOneAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "Requirement 1 Amount", 10, "First recipe item amount. Requires game restart after changing.");
		RecipeRequirementTwoItem = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "Requirement 2 Item", "FlametalNew", "Second recipe item prefab name. Flametal bars use the prefab ID FlametalNew. Requires game restart after changing.");
		RecipeRequirementTwoAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "Requirement 2 Amount", 10, "Second recipe item amount. Requires game restart after changing.");
		RecipeRequirementThreeItem = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "Requirement 3 Item", "Ectoplasm", "Third recipe item prefab name. Requires game restart after changing.");
		RecipeRequirementThreeAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "Requirement 3 Amount", 30, "Third recipe item amount. Requires game restart after changing.");
		SlashDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Slash Damage", 80f, "Weapon slash damage. Requires game restart after changing.");
		SpiritDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Spirit Damage", 100f, "Weapon spirit damage. Requires game restart after changing.");
		MaxDurability = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Max Durability", 300f, "Weapon durability. Requires game restart after changing.");
		BlockPower = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Block Armor", 90f, "Weapon block armor. Requires game restart after changing.");
		BlockForce = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Block Force", 90f, "Weapon block force. Requires game restart after changing.");
		ParryBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Parry Bonus", 4f, "Timed block/parry bonus. Requires game restart after changing.");
		Knockback = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Knockback", 90f, "Weapon attack force/knockback. Requires game restart after changing.");
		MovementModifier = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "Movement Modifier", 0.05f, new ConfigDescription("Movement modifier while equipped. 0.05 means +5%. Requires game restart after changing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>()));
		PrimaryAttackStamina = ((BaseUnityPlugin)this).Config.Bind<float>("Attacks", "Primary Stamina", 5f, "Primary attack stamina cost. Requires game restart after changing.");
		SecondaryAttackRange = ((BaseUnityPlugin)this).Config.Bind<float>("Attacks", "Secondary Range", 4f, "Secondary attack range. Requires game restart after changing.");
		SecondaryAttackAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Attacks", "Secondary Angle", 180f, "Secondary attack angle. Requires game restart after changing.");
		SecondaryAttackRayWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Attacks", "Secondary AoE Radius", 5.352113f, new ConfigDescription("Secondary attack sweep/AoE radius. Requires game restart after changing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
		SecondaryUseHitboxPrefab = ((BaseUnityPlugin)this).Config.Bind<bool>("Attacks", "Secondary Use Hitbox Prefab", true, "When enabled, secondary attack range/angle/radius are copied from the configured hitbox prefab. Requires game restart after changing.");
		SecondaryHitboxPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("Attacks", "Secondary Hitbox Prefab", "SledgeIron", "Weapon prefab whose primary attack hitbox shape is copied for this weapon's secondary attack. Requires game restart after changing.");
		SecondaryCopyHitboxAttackType = ((BaseUnityPlugin)this).Config.Bind<bool>("Attacks", "Secondary Copy Hitbox Attack Type", true, "When enabled, the secondary attack also copies the hitbox prefab's attack type, which is needed for true sledge-style area hits. Requires game restart after changing.");
		SecondaryHitMultipleTargets = ((BaseUnityPlugin)this).Config.Bind<bool>("Attacks", "Secondary Hit Multiple Targets", true, "When enabled, the secondary attack can damage every valid target it hits instead of stopping at one target. Requires game restart after changing.");
		SecondaryLowerDamagePerHit = ((BaseUnityPlugin)this).Config.Bind<bool>("Attacks", "Secondary Lower Damage Per Hit", false, "When enabled, Valheim may reduce damage across multiple hits. Requires game restart after changing.");
		SecondaryAttackStamina = ((BaseUnityPlugin)this).Config.Bind<float>("Attacks", "Secondary Stamina", 5f, "Secondary attack stamina cost. Requires game restart after changing.");
		SecondaryDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Attacks", "Secondary Damage Multiplier", 1.25f, "Secondary attack damage multiplier. Requires game restart after changing.");
		AimBlinkMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Blink", "Aim Blink Max Distance", 100f, new ConfigDescription("Shift + middle mouse aim blink max distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
		DodgeBlinkDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Blink", "Dodge Blink Distance", 8f, new ConfigDescription("Shift + right click + space blink distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
		AimBlinkStartSfx = ((BaseUnityPlugin)this).Config.Bind<string>("Blink", "Aim Blink Start SFX", "sfx_dverger_ice_projectile_start", "Sound effect prefab for the long aim blink.");
		BlinkDodgeVfx = ((BaseUnityPlugin)this).Config.Bind<string>("Blink", "Dodge Blink VFX", "fx_Fader_Roar", "Visual effect prefab for the dodge blink.");
		BlinkDodgeFallbackVfx = ((BaseUnityPlugin)this).Config.Bind<string>("Blink", "Dodge Blink Fallback VFX", "fx_Fader_Roar_Projectile_Hit", "Fallback visual effect prefab if the main dodge blink VFX is missing.");
		BlinkDodgeSfx = ((BaseUnityPlugin)this).Config.Bind<string>("Blink", "Dodge Blink SFX", "sfx_Potion_frostresist_Start", "Sound effect prefab for the dodge blink.");
		GreenFlameEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Green Flame", "Enabled", true, "Show the attached weapon flame.");
		GreenFlamePrefab = ((BaseUnityPlugin)this).Config.Bind<string>("Green Flame", "Prefab", "vfx_UndeadBurn", "Visual effect prefab attached to the equipped weapon.");
		GreenFlamePositionX = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Position X", 0f, new ConfigDescription("Local X offset from the weapon visual.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-10f, 10f), Array.Empty<object>()));
		GreenFlamePositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Position Y", 0f, new ConfigDescription("Local Y offset from the weapon visual.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-10f, 10f), Array.Empty<object>()));
		GreenFlamePositionZ = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Position Z", -0.2859152f, new ConfigDescription("Local Z offset from the weapon visual.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-10f, 10f), Array.Empty<object>()));
		GreenFlameRotationX = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Rotation X", 90f, new ConfigDescription("Local X rotation in degrees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-360f, 360f), Array.Empty<object>()));
		GreenFlameRotationY = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Rotation Y", 0f, new ConfigDescription("Local Y rotation in degrees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-360f, 360f), Array.Empty<object>()));
		GreenFlameRotationZ = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Rotation Z", 0f, new ConfigDescription("Local Z rotation in degrees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-360f, 360f), Array.Empty<object>()));
		GreenFlameScaleX = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Scale X", 0.3f, new ConfigDescription("Local X size of the flame.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
		GreenFlameScaleY = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Scale Y", 0.7f, new ConfigDescription("Local Y size of the flame.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
		GreenFlameScaleZ = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Scale Z", 0.3f, new ConfigDescription("Local Z size of the flame.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
		GreenFlameColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Green Flame", "Color Hex", "#FFFFFF", "Particle color tint as #RRGGBB.");
		GreenFlameAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Alpha", 0.2629108f, new ConfigDescription("Particle opacity from 0 to 1.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		GreenFlameBrightness = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Brightness", 1.971831f, new ConfigDescription("Particle color/emission multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
		GreenFlameVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Green Flame", "Sound Volume", 0f, new ConfigDescription("Volume for looping sounds inside the attached green flame effect. 0 is silent, 1 is full prefab volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		GreenFlameOnBack = ((BaseUnityPlugin)this).Config.Bind<bool>("Green Flame", "Show On Back", true, "Disabled in the current recovery build while troubleshooting world loading.");
		GreenFlameOnItemStands = ((BaseUnityPlugin)this).Config.Bind<bool>("Green Flame", "Show On Item Stands", true, "Show the flame effect when the weapon is displayed on an item stand. Scans only after the player has loaded.");
		GreenFlameComfortEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Green Flame", "Counts As Fire Comfort", true, "Reserved for a safer comfort implementation. Runtime weapon visuals cannot safely use Valheim's Piece comfort component.");
		GreenFlameComfort = ((BaseUnityPlugin)this).Config.Bind<int>("Green Flame", "Comfort Amount", 1, new ConfigDescription("Comfort provided by the green flame fire source.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>()));
	}

	private void Update()
	{
		HandleDirectionalBlinkDodge();
		HandleBlinkTeleport();
		if (!(Time.time < nextVisualCheck))
		{
			nextVisualCheck = Time.time + 1f;
			SalskeriSoulAxeGreenFlame.TryAttachToVisibleSalskeriSoulAxes();
		}
	}

	private void AddCustomItems()
	{
		AddSalskeriSoulAxe();
		PrefabManager.OnVanillaPrefabsAvailable -= AddCustomItems;
	}

	internal static bool IsSalskeriSoulAxe(ItemData itemData)
	{
		if (itemData == null)
		{
			return false;
		}
		if ((Object)(object)itemData.m_dropPrefab != (Object)null && ((Object)itemData.m_dropPrefab).name.IndexOf("SalskeriSoulAxe", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (itemData.m_shared != null && itemData.m_shared.m_name != null)
		{
			if (itemData.m_shared.m_name.IndexOf("SalskeriSoulAxe", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return itemData.m_shared.m_name.IndexOf("Sálskeri", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}
		return false;
	}

	private unsafe static void HandleDirectionalBlinkDodge()
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if (!((Object)(object)localPlayer == (Object)null) && IsSalskeriSoulAxe(((Humanoid)localPlayer).GetCurrentWeapon()))
		{
			bool num = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			bool mouseButton = Input.GetMouseButton(1);
			if (num && mouseButton && Input.GetKeyDown((KeyCode)32))
			{
				Vector3 directionalInput = GetDirectionalInput(localPlayer);
				CreateBlinkDodgeEffect(((Component)localPlayer).transform.position, ((Component)localPlayer).transform.rotation);
				InstantBlinkMove(localPlayer, ((Component)localPlayer).transform.position + directionalInput * DodgeBlinkDistance.Value);
				TryStartValheimDodge(localPlayer, directionalInput);
				ManualLogSource log = Log;
				string[] obj = new string[5]
				{
					WeaponDisplayName.Value,
					" blink dodge moved ",
					DodgeBlinkDistance.Value.ToString(),
					"m toward ",
					null
				};
				Vector3 val = directionalInput;
				obj[4] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString();
				log.LogInfo((object)string.Concat(obj));
			}
		}
	}

	private unsafe static void HandleBlinkTeleport()
	{
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || !IsSalskeriSoulAxe(((Humanoid)localPlayer).GetCurrentWeapon()) || (!Input.GetKey((KeyCode)304) && !Input.GetKey((KeyCode)303)) || !Input.GetMouseButtonDown(2))
		{
			return;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			Log.LogWarning((object)"Cannot blink: Camera.main is null.");
			return;
		}
		Ray val = default(Ray);
		((Ray)(ref val))..ctor(((Component)main).transform.position, ((Component)main).transform.forward);
		Vector3 val2 = ((Ray)(ref val)).origin + ((Ray)(ref val)).direction * AimBlinkMaxDistance.Value;
		RaycastHit val3 = default(RaycastHit);
		if (Physics.Raycast(val, ref val3, AimBlinkMaxDistance.Value, -5, (QueryTriggerInteraction)1))
		{
			val2 = ((RaycastHit)(ref val3)).point;
		}
		CreateBlinkStartEffects().Create(((Component)localPlayer).transform.position, ((Component)localPlayer).transform.rotation, (Transform)null, 1f, -1);
		InstantBlinkMove(localPlayer, val2);
		ManualLogSource log = Log;
		Vector3 val4 = val2;
		log.LogInfo((object)("Salskeri instant blink moved to " + ((object)(*(Vector3*)(&val4))/*cast due to .constrained prefix*/).ToString()));
	}

	private static Vector3 GetDirectionalInput(Player player)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		Vector3 forward = ((Component)player).transform.forward;
		Vector3 right = ((Component)player).transform.right;
		Camera main = Camera.main;
		if ((Object)(object)main != (Object)null)
		{
			forward = ((Component)main).transform.forward;
			right = ((Component)main).transform.right;
		}
		forward.y = 0f;
		right.y = 0f;
		((Vector3)(ref forward)).Normalize();
		((Vector3)(ref right)).Normalize();
		Vector3 val = Vector3.zero;
		if (Input.GetKey((KeyCode)119))
		{
			val += forward;
		}
		if (Input.GetKey((KeyCode)115))
		{
			val -= forward;
		}
		if (Input.GetKey((KeyCode)100))
		{
			val += right;
		}
		if (Input.GetKey((KeyCode)97))
		{
			val -= right;
		}
		if (((Vector3)(ref val)).sqrMagnitude <= 0.001f)
		{
			val = forward;
		}
		return ((Vector3)(ref val)).normalized;
	}

	private static void TryStartValheimDodge(Player player, Vector3 direction)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		MethodInfo method = typeof(Player).GetMethod("Dodge", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Vector3) }, null);
		if (method == null)
		{
			Log.LogWarning((object)"Could not find Player.Dodge(Vector3); Salskeri blink still moved the player.");
			return;
		}
		try
		{
			method.Invoke(player, new object[1] { direction });
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Could not invoke Player.Dodge(Vector3): " + ex.Message));
		}
	}

	private static void InstantBlinkMove(Player player, Vector3 target)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		Rigidbody component = ((Component)player).GetComponent<Rigidbody>();
		if ((Object)(object)component != (Object)null)
		{
			component.velocity = Vector3.zero;
			component.angularVelocity = Vector3.zero;
			component.position = target;
			component.WakeUp();
		}
		((Component)player).transform.position = target;
	}

	private static void AddSalskeriSoulAxe()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Expected O, but got Unknown
		ItemConfig val = new ItemConfig
		{
			Name = WeaponDisplayName.Value,
			Description = WeaponDescription.Value,
			CraftingStation = WeaponCraftingStation.Value,
			MinStationLevel = WeaponMinStationLevel.Value
		};
		AddRequirementIfConfigured(val, RecipeRequirementOneItem.Value, RecipeRequirementOneAmount.Value);
		AddRequirementIfConfigured(val, RecipeRequirementTwoItem.Value, RecipeRequirementTwoAmount.Value);
		AddRequirementIfConfigured(val, RecipeRequirementThreeItem.Value, RecipeRequirementThreeAmount.Value);
		CustomItem val2 = new CustomItem("SalskeriSoulAxe", WeaponSourcePrefab.Value, val);
		SharedData shared = val2.ItemDrop.m_itemData.m_shared;
		Sprite val3 = LoadIconSprite("SalskeriSprite.png");
		if ((Object)(object)val3 != (Object)null)
		{
			shared.m_icons = (Sprite[])(object)new Sprite[1] { val3 };
		}
		shared.m_damages.m_slash = SlashDamage.Value;
		shared.m_damages.m_spirit = SpiritDamage.Value;
		shared.m_maxDurability = MaxDurability.Value;
		shared.m_blockPower = BlockPower.Value;
		shared.m_deflectionForce = BlockForce.Value;
		shared.m_timedBlockBonus = ParryBonus.Value;
		shared.m_attackForce = Knockback.Value;
		shared.m_movementModifier = MovementModifier.Value;
		ConfigurePrimaryAttack(shared);
		ConfigureSecondaryAttack(shared);
		ItemManager.Instance.AddItem(val2);
		Log.LogInfo((object)"Registered SalskeriSoulAxe.");
	}

	private static Sprite LoadIconSprite(string fileName)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(PluginFolder))
		{
			Log.LogWarning((object)"Could not load weapon icon because the plugin folder is unknown.");
			return null;
		}
		string text = Path.Combine(PluginFolder, fileName);
		if (!File.Exists(text))
		{
			Log.LogWarning((object)("Weapon icon file not found: " + text));
			return null;
		}
		byte[] data = File.ReadAllBytes(text);
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
		if (!TryLoadImage(val, data))
		{
			Log.LogWarning((object)("Could not load weapon icon image: " + text));
			return null;
		}
		((Object)val).name = Path.GetFileNameWithoutExtension(fileName);
		((Texture)val).filterMode = (FilterMode)1;
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
	}

	private static bool TryLoadImage(Texture2D texture, byte[] data)
	{
		Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
		if (type == null)
		{
			Log.LogWarning((object)"Could not find UnityEngine.ImageConversion while loading the weapon icon.");
			return false;
		}
		MethodInfo method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
		{
			typeof(Texture2D),
			typeof(byte[])
		}, null);
		if (method == null)
		{
			Log.LogWarning((object)"Could not find UnityEngine.ImageConversion.LoadImage(Texture2D, byte[]).");
			return false;
		}
		return (bool)method.Invoke(null, new object[2] { texture, data });
	}

	private static void AddRequirementIfConfigured(ItemConfig config, string itemName, int amount)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		if (!string.IsNullOrEmpty(itemName) && amount > 0)
		{
			config.AddRequirement(new RequirementConfig(itemName, amount, 0, true));
		}
	}

	private static void ConfigurePrimaryAttack(SharedData shared)
	{
		shared.m_attack = CloneAttack(shared.m_attack);
		shared.m_attack.m_attackStamina = PrimaryAttackStamina.Value;
		shared.m_attack.m_hitEffect = CreatePrimaryImpactEffects();
	}

	private static void ConfigureSecondaryAttack(SharedData shared)
	{
		Attack val = ((shared.m_secondaryAttack != null) ? CloneAttack(shared.m_secondaryAttack) : CloneAttack(shared.m_attack));
		if (!TryApplySecondaryHitboxPrefab(val))
		{
			val.m_attackRange = SecondaryAttackRange.Value;
			val.m_attackAngle = SecondaryAttackAngle.Value;
			val.m_attackRayWidth = SecondaryAttackRayWidth.Value;
		}
		val.m_attackStamina = SecondaryAttackStamina.Value;
		val.m_damageMultiplier = SecondaryDamageMultiplier.Value;
		val.m_hitTerrain = true;
		val.m_multiHit = SecondaryHitMultipleTargets.Value;
		val.m_lowerDamagePerHit = SecondaryLowerDamagePerHit.Value;
		val.m_hitEffect = CreateSecondaryImpactEffects();
		val.m_hitTerrainEffect = CreateSecondaryImpactEffects();
		shared.m_secondaryAttack = val;
	}

	private static bool TryApplySecondaryHitboxPrefab(Attack secondary)
	{
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		if (!SecondaryUseHitboxPrefab.Value)
		{
			return false;
		}
		string value = SecondaryHitboxPrefab.Value;
		if (string.IsNullOrEmpty(value))
		{
			Log.LogWarning((object)"Secondary hitbox prefab is blank; using manual secondary attack shape config.");
			return false;
		}
		GameObject prefab = PrefabManager.Instance.GetPrefab(value);
		if ((Object)(object)prefab == (Object)null)
		{
			Log.LogWarning((object)("Could not find secondary hitbox prefab '" + value + "'; using manual secondary attack shape config."));
			return false;
		}
		ItemDrop component = prefab.GetComponent<ItemDrop>();
		if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
		{
			Log.LogWarning((object)("Secondary hitbox prefab '" + value + "' is not an item prefab; using manual secondary attack shape config."));
			return false;
		}
		Attack attack = component.m_itemData.m_shared.m_attack;
		if (attack == null)
		{
			Log.LogWarning((object)("Secondary hitbox prefab '" + value + "' does not have a primary attack; using manual secondary attack shape config."));
			return false;
		}
		AttackType attackType = secondary.m_attackType;
		string attackAnimation = secondary.m_attackAnimation;
		secondary.m_attackRange = attack.m_attackRange;
		secondary.m_attackHeight = attack.m_attackHeight;
		secondary.m_attackHeightChar1 = attack.m_attackHeightChar1;
		secondary.m_attackHeightChar2 = attack.m_attackHeightChar2;
		secondary.m_attackOffset = attack.m_attackOffset;
		secondary.m_attackAngle = attack.m_attackAngle;
		secondary.m_attackRayWidth = attack.m_attackRayWidth;
		secondary.m_attackRayWidthCharExtra = attack.m_attackRayWidthCharExtra;
		secondary.m_hitPointtype = attack.m_hitPointtype;
		secondary.m_hitThroughWalls = attack.m_hitThroughWalls;
		if (SecondaryCopyHitboxAttackType.Value)
		{
			secondary.m_attackType = attack.m_attackType;
			secondary.m_attackAnimation = attackAnimation;
		}
		else
		{
			secondary.m_attackType = attackType;
		}
		Log.LogInfo((object)("Copied secondary attack hitbox shape from " + value + ". AttackType=" + ((object)Unsafe.As<AttackType, AttackType>(ref secondary.m_attackType)/*cast due to .constrained prefix*/).ToString() + " primary attack. Range=" + secondary.m_attackRange + ", Angle=" + secondary.m_attackAngle + ", RayWidth=" + secondary.m_attackRayWidth));
		return true;
	}

	private static Attack CloneAttack(Attack source)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Expected O, but got Unknown
		if (source != null)
		{
			return (Attack)typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(source, null);
		}
		return new Attack();
	}

	private static EffectList CreateSecondaryImpactEffects()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		EffectList val = new EffectList();
		val.m_effectPrefabs = (EffectData[])(object)new EffectData[2]
		{
			CreateEffectData("fx_Fader_Roar_Projectile_Hit"),
			CreateEffectData("sfx_charred_melee_attack__swing")
		};
		return val;
	}

	private static EffectList CreatePrimaryImpactEffects()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		EffectList val = new EffectList();
		val.m_effectPrefabs = (EffectData[])(object)new EffectData[2]
		{
			CreateEffectData("vfx_WishbonePing"),
			CreateEffectData("sfx_ghosts_melee_attack_impact")
		};
		return val;
	}

	private static EffectList CreateBlinkStartEffects()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		EffectList val = new EffectList();
		val.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { CreateEffectData(AimBlinkStartSfx.Value) };
		return val;
	}

	private static void CreateBlinkDodgeEffect(Vector3 position, Quaternion rotation)
	{
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Expected O, but got Unknown
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Expected O, but got Unknown
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Expected O, but got Unknown
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		GameObject prefab = PrefabManager.Instance.GetPrefab(BlinkDodgeVfx.Value);
		GameObject prefab2 = PrefabManager.Instance.GetPrefab(BlinkDodgeSfx.Value);
		if ((Object)(object)prefab == (Object)null)
		{
			prefab = PrefabManager.Instance.GetPrefab(BlinkDodgeFallbackVfx.Value);
			if (!loggedBlinkDodgeEffectPrefab)
			{
				Log.LogWarning((object)("Could not resolve " + BlinkDodgeVfx.Value + ". Falling back to " + BlinkDodgeFallbackVfx.Value + "."));
				loggedBlinkDodgeEffectPrefab = true;
			}
		}
		if ((Object)(object)prefab == (Object)null)
		{
			if (!loggedBlinkDodgeEffectPrefab)
			{
				Log.LogWarning((object)("Could not resolve any " + WeaponDisplayName.Value + " blink dodge effect prefab."));
				loggedBlinkDodgeEffectPrefab = true;
			}
			return;
		}
		if (!loggedBlinkDodgeEffectPrefab)
		{
			Log.LogInfo((object)("Resolved " + WeaponDisplayName.Value + " blink dodge effect prefab: " + ((Object)prefab).name));
			loggedBlinkDodgeEffectPrefab = true;
		}
		EffectList val = new EffectList();
		val.m_effectPrefabs = (EffectData[])(object)new EffectData[2]
		{
			new EffectData
			{
				m_prefab = prefab,
				m_enabled = true
			},
			new EffectData
			{
				m_prefab = prefab2,
				m_enabled = ((Object)(object)prefab2 != (Object)null)
			}
		};
		val.Create(position, rotation, (Transform)null, 1f, -1);
	}

	private static EffectData CreateEffectData(string prefabName)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		return new EffectData
		{
			m_prefab = PrefabManager.Instance.GetPrefab(prefabName),
			m_enabled = true
		};
	}
}
public sealed class SalskeriSoulAxeGreenFlame : MonoBehaviour
{
	private const string EffectPrefabName = "vfx_UndeadBurn";

	private const string ItemPrefabName = "SalskeriSoulAxe";

	private const string FlameInstanceName = "SalskeriSoulAxe_GreenFlame";

	private GameObject effectInstance;

	private static readonly HashSet<int> LoggedMissingPrefabHosts = new HashSet<int>();

	private static bool loggedEquippedSearch;

	private static float nextItemStandScan;

	private void OnEnable()
	{
		EnsureEffect();
	}

	private void Start()
	{
		EnsureEffect();
	}

	private void EnsureEffect()
	{
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		if (!SalskeriSoulAxe.GreenFlameEnabled.Value)
		{
			Object.Destroy((Object)(object)this);
		}
		else if (!ShouldKeepEffect())
		{
			Object.Destroy((Object)(object)this);
		}
		else if (!((Object)(object)effectInstance != (Object)null))
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(SalskeriSoulAxe.GreenFlamePrefab.Value);
			if ((Object)(object)prefab == (Object)null)
			{
				LogOnceMissingPrefab();
				return;
			}
			effectInstance = Object.Instantiate<GameObject>(prefab, ((Component)this).transform);
			((Object)effectInstance).name = "SalskeriSoulAxe_GreenFlame";
			effectInstance.transform.localPosition = new Vector3(SalskeriSoulAxe.GreenFlamePositionX.Value, SalskeriSoulAxe.GreenFlamePositionY.Value, SalskeriSoulAxe.GreenFlamePositionZ.Value);
			effectInstance.transform.localRotation = Quaternion.Euler(SalskeriSoulAxe.GreenFlameRotationX.Value, SalskeriSoulAxe.GreenFlameRotationY.Value, SalskeriSoulAxe.GreenFlameRotationZ.Value);
			effectInstance.transform.localScale = new Vector3(SalskeriSoulAxe.GreenFlameScaleX.Value, SalskeriSoulAxe.GreenFlameScaleY.Value, SalskeriSoulAxe.GreenFlameScaleZ.Value);
			StripWorldOnlyComponents(effectInstance);
			int num = ApplyAudioVolume(effectInstance);
			int num2 = RestartParticles(effectInstance);
			SalskeriSoulAxe.Log.LogInfo((object)("Attached vfx_UndeadBurn to " + GetPath(((Component)this).transform) + " with " + num2 + " particle system(s) and " + num + " audio source(s)."));
		}
	}

	private void Update()
	{
		if (ShouldKeepEffect())
		{
			if ((Object)(object)effectInstance != (Object)null)
			{
				ApplyAudioVolume(effectInstance);
			}
			return;
		}
		if ((Object)(object)effectInstance != (Object)null)
		{
			Object.Destroy((Object)(object)effectInstance);
		}
		Object.Destroy((Object)(object)this);
	}

	public static void TryAttachToVisibleSalskeriSoulAxes()
	{
		TryAttachToPlayerVisibleAxe();
		if (SalskeriSoulAxe.GreenFlameOnItemStands.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && !(Time.time < nextItemStandScan))
		{
			nextItemStandScan = Time.time + 5f;
			TryAttachToItemStands();
		}
	}

	private static void TryAttachToPlayerVisibleAxe()
	{
		Player localPlayer = Player.m_localPlayer;
		if (!((Object)(object)localPlayer == (Object)null))
		{
			ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon();
			Transform val = null;
			if (IsSalskeriSoulAxe(currentWeapon))
			{
				val = FindEquippedAxeVisual(((Component)localPlayer).transform);
			}
			if (!((Object)(object)val == (Object)null) && (Object)(object)((Component)val).GetComponent<SalskeriSoulAxeGreenFlame>() == (Object)null)
			{
				((Component)val).gameObject.AddComponent<SalskeriSoulAxeGreenFlame>();
				SalskeriSoulAxe.Log.LogInfo((object)("Added green flame component to equipped axe visual: " + GetPath(val)));
			}
		}
	}

	private static void TryAttachToItemStands()
	{
		ItemStand[] array = Object.FindObjectsOfType<ItemStand>();
		foreach (ItemStand val in array)
		{
			if (!((Object)(object)val == (Object)null) && IsSalskeriSoulAxeItemStand(val))
			{
				Transform val2 = FindItemStandVisual(val);
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).GetComponent<SalskeriSoulAxeGreenFlame>() != (Object)null))
				{
					((Component)val2).gameObject.AddComponent<SalskeriSoulAxeGreenFlame>();
					SalskeriSoulAxe.Log.LogInfo((object)("Added green flame component to item stand visual: " + GetPath(val2)));
				}
			}
		}
	}

	private static bool IsSalskeriSoulAxe(ItemData itemData)
	{
		return SalskeriSoulAxe.IsSalskeriSoulAxe(itemData);
	}

	private static Transform FindEquippedAxeVisual(Transform playerRoot)
	{
		Transform[] componentsInChildren = ((Component)playerRoot).GetComponentsInChildren<Transform>(true);
		Transform[] array = componentsInChildren;
		foreach (Transform val in array)
		{
			if (((Object)val).name.IndexOf("SalskeriSoulAxe", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return val;
			}
		}
		Transform val2 = FindEquippedAxeModelFallback(componentsInChildren);
		if ((Object)(object)val2 != (Object)null)
		{
			SalskeriSoulAxe.Log.LogInfo((object)("Using equipped axe model fallback for SalskeriSoulAxe visual: " + GetPath(val2)));
			return val2;
		}
		Transform val3 = FindRightHandAttachFallback(componentsInChildren);
		if ((Object)(object)val3 != (Object)null)
		{
			SalskeriSoulAxe.Log.LogInfo((object)("Using right-hand attachment fallback for SalskeriSoulAxe visual: " + GetPath(val3)));
			return val3;
		}
		if (!loggedEquippedSearch)
		{
			loggedEquippedSearch = true;
			SalskeriSoulAxe.Log.LogInfo((object)("Could not find equipped SalskeriSoulAxe visual yet. Axe-like transforms under player: " + BuildTransformSummary(componentsInChildren)));
		}
		return null;
	}

	private static Transform FindNamedSalskeriSoulAxeVisual(Transform root)
	{
		Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
		foreach (Transform val in componentsInChildren)
		{
			if (!IsFlameTransform(val) && ((Object)val).name.IndexOf("SalskeriSoulAxe", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return val;
			}
		}
		return null;
	}

	private static Transform FindItemStandVisual(ItemStand itemStand)
	{
		Transform val = FindNamedSalskeriSoulAxeVisual(((Component)itemStand).transform);
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		return FindBestRenderedChild(((Component)itemStand).transform);
	}

	private static bool IsSalskeriSoulAxeItemStand(ItemStand itemStand)
	{
		string attachedItem = itemStand.GetAttachedItem();
		if (!string.IsNullOrEmpty(attachedItem))
		{
			return attachedItem.IndexOf("SalskeriSoulAxe", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return false;
	}

	private static Transform FindRightHandAttachFallback(Transform[] transforms)
	{
		foreach (Transform val in transforms)
		{
			if (((Object)val).name.IndexOf("RightHand_Attach", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				Transform val2 = FindBestRenderedChild(val);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
		}
		return null;
	}

	private static Transform FindBestRenderedChild(Transform root)
	{
		Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null) && GetPath(((Component)val).transform).IndexOf("SalskeriSoulAxe_GreenFlame", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return ((Component)val).transform;
			}
		}
		return null;
	}

	private static Transform FindEquippedAxeModelFallback(Transform[] transforms)
	{
		foreach (Transform val in transforms)
		{
			string name = ((Object)val).name;
			if (name.IndexOf("pickaxe", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("axe", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return val;
			}
		}
		return null;
	}

	private bool ShouldKeepEffect()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)null && IsChildOf(((Component)this).transform, ((Component)localPlayer).transform))
		{
			return IsSalskeriSoulAxe(((Humanoid)localPlayer).GetCurrentWeapon());
		}
		if (SalskeriSoulAxe.GreenFlameOnItemStands.Value)
		{
			ItemStand componentInParent = ((Component)this).GetComponentInParent<ItemStand>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return IsSalskeriSoulAxeItemStand(componentInParent);
			}
			return false;
		}
		return false;
	}

	private static bool HostLooksLikeSalskeriSoulAxe(Transform host)
	{
		if ((Object)(object)host != (Object)null)
		{
			return GetPath(host).IndexOf("SalskeriSoulAxe", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return false;
	}

	private static bool IsChildOf(Transform child, Transform parent)
	{
		while ((Object)(object)child != (Object)null)
		{
			if ((Object)(object)child == (Object)(object)parent)
			{
				return true;
			}
			child = child.parent;
		}
		return false;
	}

	private static bool IsFlameTransform(Transform transform)
	{
		if ((Object)(object)transform != (Object)null)
		{
			return GetPath(transform).IndexOf("SalskeriSoulAxe_GreenFlame", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return false;
	}

	private static string BuildTransformSummary(Transform[] transforms)
	{
		List<string> list = new List<string>();
		foreach (Transform val in transforms)
		{
			if (((Object)val).name.IndexOf("axe", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)val).name.IndexOf("weapon", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)val).name.IndexOf("hand", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				list.Add(((Object)val).name);
			}
			if (list.Count >= 20)
			{
				break;
			}
		}
		if (list.Count != 0)
		{
			return string.Join(", ", list.ToArray());
		}
		return "(none)";
	}

	private void LogOnceMissingPrefab()
	{
		int instanceID = ((Object)((Component)this).gameObject).GetInstanceID();
		if (LoggedMissingPrefabHosts.Add(instanceID))
		{
			SalskeriSoulAxe.Log.LogWarning((object)("Could not find prefab " + SalskeriSoulAxe.GreenFlamePrefab.Value + " while attaching to " + GetPath(((Component)this).transform)));
		}
	}

	private static void StripWorldOnlyComponents(GameObject effect)
	{
		Component[] componentsInChildren = effect.GetComponentsInChildren<Component>(true);
		foreach (Component val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null))
			{
				switch (((object)val).GetType().Name)
				{
				case "ZNetView":
				case "ZSyncTransform":
				case "TimedDestruction":
					Object.Destroy((Object)(object)val);
					break;
				}
			}
		}
	}

	private static int RestartParticles(GameObject effect)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		Color val = ParseConfiguredColor();
		ParticleSystem[] componentsInChildren = effect.GetComponentsInChildren<ParticleSystem>(true);
		ParticleSystem[] array = componentsInChildren;
		foreach (ParticleSystem obj in array)
		{
			MainModule main = obj.main;
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).stopAction = (ParticleSystemStopAction)0;
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(val);
			((Component)obj).gameObject.SetActive(true);
			obj.Clear(true);
			obj.Play(true);
		}
		ParticleSystemRenderer[] componentsInChildren2 = effect.GetComponentsInChildren<ParticleSystemRenderer>(true);
		foreach (ParticleSystemRenderer val2 in componentsInChildren2)
		{
			if ((Object)(object)((Renderer)val2).material != (Object)null)
			{
				((Renderer)val2).material.color = val;
				if (((Renderer)val2).material.HasProperty("_EmissionColor"))
				{
					((Renderer)val2).material.SetColor("_EmissionColor", val * SalskeriSoulAxe.GreenFlameBrightness.Value);
				}
			}
		}
		return componentsInChildren.Length;
	}

	private static int ApplyAudioVolume(GameObject effect)
	{
		float volume = Mathf.Clamp01(SalskeriSoulAxe.GreenFlameVolume.Value);
		AudioSource[] componentsInChildren = effect.GetComponentsInChildren<AudioSource>(true);
		AudioSource[] array = componentsInChildren;
		for (int i = 0; i < array.Length; i++)
		{
			array[i].volume = volume;
		}
		return componentsInChildren.Length;
	}

	private static Color ParseConfiguredColor()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		Color white = Color.white;
		if (!ColorUtility.TryParseHtmlString(SalskeriSoulAxe.GreenFlameColorHex.Value, ref white))
		{
			SalskeriSoulAxe.Log.LogWarning((object)("Invalid green flame color hex: " + SalskeriSoulAxe.GreenFlameColorHex.Value));
			white = Color.white;
		}
		float num = Mathf.Max(0f, SalskeriSoulAxe.GreenFlameBrightness.Value);
		white.r *= num;
		white.g *= num;
		white.b *= num;
		white.a = Mathf.Clamp01(SalskeriSoulAxe.GreenFlameAlpha.Value);
		return white;
	}

	private static string GetPath(Transform transform)
	{
		List<string> list = new List<string>();
		while ((Object)(object)transform != (Object)null)
		{
			list.Add(((Object)transform).name);
			transform = transform.parent;
		}
		list.Reverse();
		return string.Join("/", list.ToArray());
	}
}