using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Object;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using NativeStatusUI;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ArceDev.FishEffects")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.3.0")]
[assembly: AssemblyInformationalVersion("0.5.3")]
[assembly: AssemblyProduct("ArceDev.FishEffects")]
[assembly: AssemblyTitle("FishEffects")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.5.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
[Embedded]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
[Embedded]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace Microsoft.CodeAnalysis
{
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace FishEffects
{
internal readonly record struct StatusBroadcast(byte Effect, float Duration) : IBroadcast;
internal static class EffectNetwork
{
private readonly record struct StatusStyle(string Name, string Resource, Color Color);
private static readonly Action<StatusBroadcast, Channel> Handler = OnStatus;
private static readonly Dictionary<TimedEffect, StatusStyle> Styles = new Dictionary<TimedEffect, StatusStyle>
{
[TimedEffect.Regeneration] = new StatusStyle("Regeneration", "regeneration.png", new Color(0.28f, 0.95f, 0.42f)),
[TimedEffect.Agility] = new StatusStyle("Agility", "agility.png", new Color(1f, 0.82f, 0.2f)),
[TimedEffect.FastBite] = new StatusStyle("FastBite", "fast-bite.png", new Color(0.2f, 0.9f, 1f)),
[TimedEffect.Resistance] = new StatusStyle("Resistance", "resistance.png", new Color(0.3f, 0.58f, 1f)),
[TimedEffect.Slowness] = new StatusStyle("Slowness", "slowness.png", new Color(0.68f, 0.45f, 0.85f)),
[TimedEffect.Luck] = new StatusStyle("Luck", "clover.png", new Color(0.35f, 0.9f, 0.4f))
};
private static bool _clientRegistered;
internal static void Initialize()
{
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
GenericWriter<StatusBroadcast>.SetWrite((Action<Writer, StatusBroadcast>)delegate(Writer writer, StatusBroadcast message)
{
writer.WriteUInt8Unpacked(message.Effect);
writer.WriteSingle(message.Duration);
});
GenericReader<StatusBroadcast>.SetRead((Func<Reader, StatusBroadcast>)((Reader reader) => new StatusBroadcast(reader.ReadUInt8Unpacked(), reader.ReadSingle())));
foreach (var (effect, statusStyle2) in Styles)
{
NativeStatus.Register(StatusId(effect), LoadPng(statusStyle2.Resource), statusStyle2.Color);
}
}
internal static void RegisterClient()
{
if (!_clientRegistered && Object.op_Implicit((Object)(object)InstanceFinder.ClientManager))
{
InstanceFinder.ClientManager.RegisterBroadcast<StatusBroadcast>(Handler);
_clientRegistered = true;
}
}
internal static void Send(Player player, TimedEffect effect, float duration)
{
NetworkConnection owner = ((NetworkBehaviour)player).Owner;
if (owner != null && owner.IsValid && Object.op_Implicit((Object)(object)InstanceFinder.ServerManager))
{
InstanceFinder.ServerManager.Broadcast<StatusBroadcast>(owner, new StatusBroadcast((byte)effect, duration), true, (Channel)0);
}
}
internal static string ColorHex(TimedEffect effect)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
return ColorUtility.ToHtmlStringRGB(Styles[effect].Color);
}
private static byte[] LoadPng(string resource)
{
using Stream stream = typeof(EffectNetwork).Assembly.GetManifestResourceStream("FishEffects." + resource) ?? throw new InvalidOperationException("Embedded status icon '" + resource + "' was not found.");
using MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
private static void OnStatus(StatusBroadcast message, Channel channel)
{
TimedEffect effect = (TimedEffect)message.Effect;
if (Styles.ContainsKey(effect) && !(message.Duration <= 0f))
{
NativeStatus.Activate(StatusId(effect), message.Duration);
TimedEffects.ActivateLocal(effect, message.Duration);
}
}
private static string StatusId(TimedEffect effect)
{
return "ArceDev.FishEffects." + Styles[effect].Name;
}
}
internal static class LuckEffect
{
internal const float DurationSeconds = 60f;
private const int RerollSeedOffset = 104729;
private static readonly Dictionary<ulong, float> ExpiresAt = new Dictionary<ulong, float>();
internal static void Activate(Player player)
{
ExpiresAt[player.SteamID] = Time.time + 60f;
EffectNetwork.Send(player, TimedEffect.Luck, 60f);
Plugin.Log.LogInfo((object)$"Luck activated for {player.SteamName} for {60f:0} seconds.");
}
internal static void ApplyLuckyWeight(Bait bait)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
Item serverItemOnBait = bait.ServerItemOnBait;
Creature val = ((serverItemOnBait != null) ? serverItemOnBait.Creature : null);
FishingRod fishingRod = bait.FishingRod;
Player val2 = ((fishingRod != null) ? ((Item)fishingRod).Holder : null);
if (Object.op_Implicit((Object)(object)val) && (int)val.BossType == 0 && !val._skipRandomizedWeight && IsActive(val2))
{
float value = ((Item)val)._syncedRandomWeight.Value;
int num = ((NetworkBehaviour)val).ObjectId + 104729;
float weightWithStandardDeviation = CreatureUtils.GetWeightWithStandardDeviation(num);
((Item)val)._syncedRandomWeight.Value = BetterWeight(value, weightWithStandardDeviation);
Plugin.Log.LogDebug((object)$"Luck weight roll for {val2.SteamName}: {value:0.###} vs {weightWithStandardDeviation:0.###}.");
}
}
internal static void Validate()
{
if (BetterWeight(3f, 2f) != 3f || BetterWeight(3f, 4f) != 4f)
{
throw new InvalidOperationException("FishEffects Luck weight validation failed.");
}
}
private static float BetterWeight(float currentWeight, float rerolledWeight)
{
return Mathf.Max(currentWeight, rerolledWeight);
}
private static bool IsActive(Player? player)
{
if (!Object.op_Implicit((Object)(object)player) || !ExpiresAt.TryGetValue(player.SteamID, out var value))
{
return false;
}
if (Time.time < value)
{
return true;
}
ExpiresAt.Remove(player.SteamID);
return false;
}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("ArceDev.FishEffects", "FishEffects", "0.5.3")]
public class Plugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(Server), "RpcLogic___FinishEatingCreature___1039939981")]
private static class FinishEatingCreaturePatch
{
private static void Prefix(Creature __0, out ConsumedFood __state)
{
__state = ((Object.op_Implicit((Object)(object)__0) && !((NetworkBehaviour)__0).IsDeinitializing) ? new ConsumedFood(FoodEffectRules.Resolve(__0), __0.IsDrip) : default(ConsumedFood));
}
private static void Postfix(Player __1, ConsumedFood __state)
{
ConsumedFood consumedFood = __state;
if (Object.op_Implicit((Object)(object)__1) && !((NetworkBehaviour)__1).IsDeinitializing)
{
if (consumedFood.Effect.HasEffect)
{
consumedFood.Effect.Apply(__1);
Log.LogDebug((object)$"Applied {consumedFood.Effect} to {__1.SteamName}.");
}
if (consumedFood.GrantsLuck)
{
LuckEffect.Activate(__1);
}
}
}
}
[HarmonyPatch(typeof(CreatureManager), "HookItem")]
private static class HookItemPatch
{
private static void Postfix(Bait __1)
{
LuckEffect.ApplyLuckyWeight(__1);
}
}
[HarmonyPatch(typeof(Bait), "IncreaseUnderwaterTime")]
private static class IncreaseUnderwaterTimePatch
{
private static void Prefix(Bait __instance, out float __state)
{
__state = __instance.TimeUnderWater;
}
private static void Postfix(Bait __instance, float __state)
{
TimedEffects.ApplyFastBite(__instance, __instance.TimeUnderWater - __state);
}
}
[HarmonyPatch(typeof(PlayerVitals), "TakeDamage")]
private static class TakeDamagePatch
{
private static void Prefix(Player ____player, ref int amount)
{
amount = TimedEffects.ApplyResistance(____player, amount);
}
}
[HarmonyPatch(typeof(PlayerMovement), "UpdateMoveSpeed")]
private static class UpdateMoveSpeedPatch
{
private readonly record struct Speeds(float Walk, float Sprint);
private static void Prefix(Player ____player, ref float ____walkSpeed, ref float ____sprintSpeed, out Speeds __state)
{
__state = new Speeds(____walkSpeed, ____sprintSpeed);
float localMovementMultiplier = TimedEffects.GetLocalMovementMultiplier(____player);
____walkSpeed *= localMovementMultiplier;
____sprintSpeed *= localMovementMultiplier;
}
private static void Postfix(ref float ____walkSpeed, ref float ____sprintSpeed, Speeds __state)
{
Speeds speeds = __state;
____walkSpeed = speeds.Walk;
____sprintSpeed = speeds.Sprint;
}
}
[HarmonyPatch(typeof(WeaponUI), "UpdateInspectedItemText")]
private static class UpdateInspectedItemTextPatch
{
private static void Prefix(Item ____inspectedItem, ref string ____extraDescription)
{
Creature val = (Creature)(object)((____inspectedItem is Creature) ? ____inspectedItem : null);
if (val != null)
{
____extraDescription = InspectionText.WithEffect(____extraDescription, FoodEffectRules.Resolve(val), val.IsDrip);
}
}
}
[HarmonyPatch(typeof(VitalsUI), "Awake")]
private static class VitalsUiPatch
{
private static void Postfix()
{
EffectNetwork.RegisterClient();
}
}
public const string Id = "ArceDev.FishEffects";
internal static ManualLogSource Log { get; private set; }
public static string Name => "FishEffects";
public static string Version => "0.5.3";
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
FoodEffectRules.Validate();
InspectionText.Validate();
LuckEffect.Validate();
EffectNetwork.Initialize();
Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "ArceDev.FishEffects");
Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
}
private void Update()
{
TimedEffects.UpdateServer();
}
}
internal enum TimedEffect : byte
{
None,
Regeneration,
Agility,
FastBite,
Resistance,
Slowness,
Luck
}
internal enum CookState
{
Raw,
Cooked,
Burnt
}
internal readonly record struct FoodEffect(TimedEffect Timed = TimedEffect.None, float Duration = 0f, bool Poison = false, bool Fire = false)
{
internal bool HasEffect
{
get
{
if (Timed == TimedEffect.None && !Poison)
{
return Fire;
}
return true;
}
}
internal void Apply(Player player)
{
if (Poison)
{
player.Vitals.ApplyNewPoison();
}
if (Fire)
{
player.Vitals.ApplyNewFire();
}
if (Timed != TimedEffect.None)
{
TimedEffects.Activate(player, Timed, Duration);
}
}
public override string ToString()
{
if (Poison)
{
return "Poison";
}
if (Fire)
{
return "Fire";
}
return $"{TimedEffects.DisplayName(Timed)} ({Duration:0}s)";
}
[CompilerGenerated]
private bool PrintMembers(StringBuilder builder)
{
builder.Append("Timed = ");
builder.Append(Timed.ToString());
builder.Append(", Duration = ");
builder.Append(Duration.ToString());
builder.Append(", Poison = ");
builder.Append(Poison.ToString());
builder.Append(", Fire = ");
builder.Append(Fire.ToString());
return true;
}
}
internal readonly record struct ConsumedFood(FoodEffect Effect, bool GrantsLuck);
internal static class InspectionText
{
private const string Marker = "\n\nFish Effects: ";
internal static string WithEffect(string description, FoodEffect effect, bool grantsLuck = false)
{
string text = "\n\nFish Effects: " + FormatEffect(effect);
if (grantsLuck)
{
text += string.Format("\nSpecial Effect: {0} ({1:0}s)", Colorize("Luck", EffectNetwork.ColorHex(TimedEffect.Luck)), 60f);
}
if (description.EndsWith(text, StringComparison.Ordinal))
{
return description;
}
int num = description.IndexOf("\n\nFish Effects: ", StringComparison.Ordinal);
string text2 = ((num >= 0) ? description.Substring(0, num) : description);
return text2 + text;
}
private static string FormatEffect(FoodEffect effect)
{
if (effect.Poison)
{
return Colorize("Poison", "8F35BE");
}
if (effect.Fire)
{
return Colorize("Fire", "FF6A2A");
}
string text = TimedEffects.DisplayName(effect.Timed);
return $"{Colorize(text, EffectNetwork.ColorHex(effect.Timed))} ({effect.Duration:0}s)";
}
private static string Colorize(string text, string hex)
{
return "<color=#" + hex + ">" + text + "</color>";
}
internal static void Validate()
{
string text = "Weight: 1\nKillscore: 1x";
string text2 = WithEffect(text, new FoodEffect(TimedEffect.Regeneration, 40f), grantsLuck: true);
string text3 = WithEffect(text2, new FoodEffect(TimedEffect.None, 0f, Poison: false, Fire: true));
string text4 = WithEffect(text3, new FoodEffect(TimedEffect.None, 0f, Poison: true));
if (text2 != text + "\n\nFish Effects: <color=#47F26B>Regeneration</color> (40s)\nSpecial Effect: <color=#59E666>Luck</color> (60s)" || text3 != text + "\n\nFish Effects: <color=#FF6A2A>Fire</color>" || text4 != text + "\n\nFish Effects: <color=#8F35BE>Poison</color>" || WithEffect(text3, new FoodEffect(TimedEffect.None, 0f, Poison: false, Fire: true)) != text3)
{
throw new InvalidOperationException("FishEffects inspection text validation failed.");
}
}
}
internal static class FoodEffectRules
{
private const float CookedAt = 0.75f;
private const float BurntAt = 1.25f;
private static readonly HashSet<string> Toxic = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Pufferfish", "SeaUrchin", "Stonefish", "YellowBoxFish" };
private static readonly HashSet<string> Indigestible = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Blobfish", "Bowlfish", "Dripper", "RottenShrimp", "Voxelfish" };
private static readonly Dictionary<string, TimedEffect> SpeciesEffects = new Dictionary<string, TimedEffect>(StringComparer.OrdinalIgnoreCase)
{
["AngelFish"] = TimedEffect.Regeneration,
["Bluegill"] = TimedEffect.Regeneration,
["Clownfish"] = TimedEffect.Regeneration,
["Goldfish"] = TimedEffect.Regeneration,
["Parrotfish"] = TimedEffect.Regeneration,
["Seahorse"] = TimedEffect.Regeneration,
["SuperdwarfFish"] = TimedEffect.Regeneration,
["FlyingFish"] = TimedEffect.Agility,
["Needlefish"] = TimedEffect.Agility,
["Piranha"] = TimedEffect.Agility,
["Tigerfish"] = TimedEffect.Agility,
["Tuna"] = TimedEffect.Agility,
["YellowBoxFish"] = TimedEffect.Agility,
["Anglerfish"] = TimedEffect.FastBite,
["BingBong"] = TimedEffect.FastBite,
["Eel"] = TimedEffect.FastBite,
["Gammelgäddan"] = TimedEffect.FastBite,
["Goby"] = TimedEffect.FastBite,
["RedSnapper"] = TimedEffect.FastBite,
["Stonefish"] = TimedEffect.FastBite,
["Bass"] = TimedEffect.Resistance,
["Belodontichthys Truncatus"] = TimedEffect.Resistance,
["BlueShark"] = TimedEffect.Resistance,
["BowheadWhale"] = TimedEffect.Resistance,
["Catfish"] = TimedEffect.Resistance,
["GiantPiranha"] = TimedEffect.Resistance,
["GoblinShark"] = TimedEffect.Resistance,
["Halibut"] = TimedEffect.Resistance,
["Lobster"] = TimedEffect.Resistance,
["Oarfish"] = TimedEffect.Resistance,
["Pufferfish"] = TimedEffect.Resistance,
["RockCrab"] = TimedEffect.Resistance,
["SeaUrchin"] = TimedEffect.Resistance,
["Spidercrab"] = TimedEffect.Resistance,
["Sunfish"] = TimedEffect.Resistance
};
internal static FoodEffect Resolve(Creature creature)
{
return Resolve(((Object)creature).name.Replace("(Clone)", string.Empty).Trim(), ((Item)creature).Cookness);
}
internal static void Validate()
{
FoodEffect[] array = new FoodEffect[7]
{
Resolve("Pufferfish", 0.749f),
Resolve("Pufferfish", 0.75f),
Resolve("AngelFish", 0.75f),
Resolve("Blobfish", 0.75f),
Resolve("Anglerfish", 1.25f),
Resolve("Anglerfish", 1.251f),
Resolve("ModdedFish", 0.75f)
};
FoodEffect[] array2 = new FoodEffect[7]
{
new FoodEffect(TimedEffect.None, 0f, Poison: true),
new FoodEffect(TimedEffect.Resistance, 50f),
new FoodEffect(TimedEffect.Regeneration, 40f),
new FoodEffect(TimedEffect.Slowness, 30f),
new FoodEffect(TimedEffect.FastBite, 60f),
new FoodEffect(TimedEffect.None, 0f, Poison: false, Fire: true),
new FoodEffect(TimedEffect.FastBite, 60f)
};
if (!((ReadOnlySpan<FoodEffect>)array).SequenceEqual((ReadOnlySpan<FoodEffect>)array2))
{
throw new InvalidOperationException("FishEffects rule validation failed.");
}
}
private static FoodEffect Resolve(string species, float cookness)
{
CookState cookState = GetCookState(cookness);
if (cookState == CookState.Burnt)
{
return new FoodEffect(TimedEffect.None, 0f, Poison: false, Fire: true);
}
if (TryResolveHazard(species, cookState, out var effect))
{
return effect;
}
TimedEffect value;
TimedEffect timedEffect = (SpeciesEffects.TryGetValue(species, out value) ? value : TimedEffect.FastBite);
return new FoodEffect(timedEffect, Duration(timedEffect, cookState));
}
private static bool TryResolveHazard(string species, CookState state, out FoodEffect effect)
{
if (Indigestible.Contains(species))
{
effect = ((state == CookState.Raw) ? new FoodEffect(TimedEffect.None, 0f, Poison: true) : new FoodEffect(TimedEffect.Slowness, 30f));
return true;
}
if (state == CookState.Raw && Toxic.Contains(species))
{
effect = new FoodEffect(TimedEffect.None, 0f, Poison: true);
return true;
}
effect = default(FoodEffect);
return false;
}
private static CookState GetCookState(float cookness)
{
if (!(cookness > 1.25f))
{
if (!(cookness >= 0.75f))
{
return CookState.Raw;
}
return CookState.Cooked;
}
return CookState.Burnt;
}
private static float Duration(TimedEffect effect, CookState state)
{
switch (effect)
{
case TimedEffect.Regeneration:
return (state == CookState.Raw) ? 20f : 40f;
case TimedEffect.Resistance:
return (state == CookState.Raw) ? 25f : 50f;
case TimedEffect.Agility:
case TimedEffect.FastBite:
return (state == CookState.Raw) ? 30f : 60f;
default:
throw new ArgumentOutOfRangeException("effect");
}
}
}
internal static class TimedEffects
{
private readonly record struct EffectKey(ulong PlayerId, TimedEffect Effect);
private readonly record struct ActiveEffect(float ExpiresAt, float NextTick);
private const float RegenerationInterval = 2f;
private const int RegenerationAmount = 2;
private const float AgilityMultiplier = 1.15f;
private const float SlownessMultiplier = 0.8f;
private const float FastBiteBonus = 0.25f;
private const float ResistanceMultiplier = 0.8f;
private static readonly Dictionary<EffectKey, ActiveEffect> ServerEffects = new Dictionary<EffectKey, ActiveEffect>();
private static readonly Dictionary<TimedEffect, float> LocalExpiresAt = new Dictionary<TimedEffect, float>();
internal static void Activate(Player player, TimedEffect effect, float duration)
{
float time = Time.time;
ServerEffects[new EffectKey(player.SteamID, effect)] = new ActiveEffect(time + duration, (effect == TimedEffect.Regeneration) ? (time + 2f) : 0f);
EffectNetwork.Send(player, effect, duration);
}
internal static void ActivateLocal(TimedEffect effect, float duration)
{
LocalExpiresAt[effect] = Time.time + duration;
}
internal static void UpdateServer()
{
if (InstanceFinder.IsServerStarted && ServerEffects.Count != 0)
{
float time = Time.time;
EffectKey[] array = ServerEffects.Keys.ToArray();
foreach (EffectKey key in array)
{
UpdateEffect(key, time);
}
}
}
internal static int ApplyResistance(Player player, int amount)
{
if (amount <= 0 || !IsServerActive(player, TimedEffect.Resistance))
{
return amount;
}
return Mathf.Max(1, Mathf.RoundToInt((float)amount * 0.8f));
}
internal static void ApplyFastBite(Bait bait, float actualIncrement)
{
if (!(actualIncrement <= 0f) && InstanceFinder.IsServerStarted)
{
FishingRod fishingRod = bait.FishingRod;
if (IsServerActive((fishingRod != null) ? ((Item)fishingRod).Holder : null, TimedEffect.FastBite))
{
bait.TimeUnderWater += actualIncrement * 0.25f;
}
}
}
internal static float GetLocalMovementMultiplier(Player player)
{
if (!Object.op_Implicit((Object)(object)player) || !((NetworkBehaviour)player).IsOwner)
{
return 1f;
}
float num = 1f;
if (IsLocalActive(TimedEffect.Agility))
{
num *= 1.15f;
}
if (IsLocalActive(TimedEffect.Slowness))
{
num *= 0.8f;
}
return num;
}
internal static string DisplayName(TimedEffect effect)
{
return effect switch
{
TimedEffect.Regeneration => "Regeneration",
TimedEffect.Agility => "Agility",
TimedEffect.FastBite => "Fast Bite",
TimedEffect.Resistance => "Resistance",
TimedEffect.Slowness => "Slowness",
TimedEffect.Luck => "Luck",
_ => "None",
};
}
private static bool IsServerActive(Player? player, TimedEffect effect)
{
if (!Object.op_Implicit((Object)(object)player) || !ServerEffects.TryGetValue(new EffectKey(player.SteamID, effect), out var value))
{
return false;
}
if (Time.time < value.ExpiresAt)
{
return true;
}
ServerEffects.Remove(new EffectKey(player.SteamID, effect));
return false;
}
private static void UpdateEffect(EffectKey key, float now)
{
ActiveEffect active = ServerEffects[key];
Player player = FindPlayer(key.PlayerId);
if (ShouldRemove(player, active, now))
{
ServerEffects.Remove(key);
}
else if (key.Effect == TimedEffect.Regeneration && now >= active.NextTick)
{
TickRegeneration(key, player, active, now);
}
}
private static bool ShouldRemove(Player? player, ActiveEffect active, float now)
{
if (Object.op_Implicit((Object)(object)player) && !((NetworkBehaviour)player).IsDeinitializing)
{
return now >= active.ExpiresAt;
}
return true;
}
private static void TickRegeneration(EffectKey key, Player player, ActiveEffect active, float now)
{
if (!player.Dying.IsDead)
{
player.Vitals.Heal(2);
}
ServerEffects[key] = active with
{
NextTick = now + 2f
};
}
private static bool IsLocalActive(TimedEffect effect)
{
if (!LocalExpiresAt.TryGetValue(effect, out var value))
{
return false;
}
if (Time.time < value)
{
return true;
}
LocalExpiresAt.Remove(effect);
return false;
}
private static Player? FindPlayer(ulong playerId)
{
return ((IEnumerable<Player>)PlayerManager.Players).FirstOrDefault((Func<Player, bool>)((Player player) => Object.op_Implicit((Object)(object)player) && player.SteamID == playerId));
}
}
}
namespace System.Diagnostics.CodeAnalysis
{
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class ConstantExpectedAttribute : Attribute
{
public object? Min { get; set; }
public object? Max { get; set; }
}
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class ExperimentalAttribute : Attribute
{
public string DiagnosticId { get; }
public string? UrlFormat { get; set; }
public ExperimentalAttribute(string diagnosticId)
{
DiagnosticId = diagnosticId;
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
[ExcludeFromCodeCoverage]
internal sealed class MemberNotNullAttribute : Attribute
{
public string[] Members { get; }
public MemberNotNullAttribute(string member)
{
Members = new string[1] { member };
}
public MemberNotNullAttribute(params string[] members)
{
Members = members;
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
[ExcludeFromCodeCoverage]
internal sealed class MemberNotNullWhenAttribute : Attribute
{
public bool ReturnValue { get; }
public string[] Members { get; }
public MemberNotNullWhenAttribute(bool returnValue, string member)
{
ReturnValue = returnValue;
Members = new string[1] { member };
}
public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
{
ReturnValue = returnValue;
Members = members;
}
}
[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class SetsRequiredMembersAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class StringSyntaxAttribute : Attribute
{
public const string CompositeFormat = "CompositeFormat";
public const string DateOnlyFormat = "DateOnlyFormat";
public const string DateTimeFormat = "DateTimeFormat";
public const string EnumFormat = "EnumFormat";
public const string GuidFormat = "GuidFormat";
public const string Json = "Json";
public const string NumericFormat = "NumericFormat";
public const string Regex = "Regex";
public const string TimeOnlyFormat = "TimeOnlyFormat";
public const string TimeSpanFormat = "TimeSpanFormat";
public const string Uri = "Uri";
public const string Xml = "Xml";
public string Syntax { get; }
public object?[] Arguments { get; }
public StringSyntaxAttribute(string syntax)
{
Syntax = syntax;
Arguments = new object[0];
}
public StringSyntaxAttribute(string syntax, params object?[] arguments)
{
Syntax = syntax;
Arguments = arguments;
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class UnscopedRefAttribute : Attribute
{
}
}
namespace System.Runtime.Versioning
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class RequiresPreviewFeaturesAttribute : Attribute
{
public string? Message { get; }
public string? Url { get; set; }
public RequiresPreviewFeaturesAttribute()
{
}
public RequiresPreviewFeaturesAttribute(string? message)
{
Message = message;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class CallerArgumentExpressionAttribute : Attribute
{
public string ParameterName { get; }
public CallerArgumentExpressionAttribute(string parameterName)
{
ParameterName = parameterName;
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class CollectionBuilderAttribute : Attribute
{
public Type BuilderType { get; }
public string MethodName { get; }
public CollectionBuilderAttribute(Type builderType, string methodName)
{
BuilderType = builderType;
MethodName = methodName;
}
}
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class CompilerFeatureRequiredAttribute : Attribute
{
public const string RefStructs = "RefStructs";
public const string RequiredMembers = "RequiredMembers";
public string FeatureName { get; }
public bool IsOptional { get; set; }
public CompilerFeatureRequiredAttribute(string featureName)
{
FeatureName = featureName;
}
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
{
public string[] Arguments { get; }
public InterpolatedStringHandlerArgumentAttribute(string argument)
{
Arguments = new string[1] { argument };
}
public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
{
Arguments = arguments;
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class InterpolatedStringHandlerAttribute : Attribute
{
}
[EditorBrowsable(EditorBrowsableState.Never)]
[ExcludeFromCodeCoverage]
internal static class IsExternalInit
{
}
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class ModuleInitializerAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class OverloadResolutionPriorityAttribute : Attribute
{
public int Priority { get; }
public OverloadResolutionPriorityAttribute(int priority)
{
Priority = priority;
}
}
[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
[ExcludeFromCodeCoverage]
internal sealed class ParamCollectionAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class RequiredMemberAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[ExcludeFromCodeCoverage]
internal sealed class RequiresLocationAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
[ExcludeFromCodeCoverage]
internal sealed class SkipLocalsInitAttribute : Attribute
{
}
}