using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Object;
using FishNet.Object;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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 FishmenInvasionMod
{
public enum FishmanKind
{
Fishman,
Brute,
Leaper,
Deepjaw,
BarnacleColossus,
Tidecaller,
PufferTitan
}
public static class Rules
{
public const int MinCatchGoal = 5;
public const int MaxCatchGoal = 20;
public const float MinionMinSize = 0.5f;
public const float MinionMaxSize = 1.5f;
public const float BossMinSize = 2.5f;
public const float BossMaxSize = 3f;
public static readonly byte[] ItemIds = new byte[7] { 244, 243, 242, 241, 240, 239, 238 };
public static readonly ushort[] PrefabCollections = new ushort[7] { 42426, 42427, 42428, 42429, 42430, 42431, 42432 };
public static bool EligibleIsland(byte current, byte maximum)
{
if (maximum >= 2 && current >= 2)
{
return current <= 5;
}
return false;
}
public static int CatchTarget(int baseGoal, float frequency)
{
return Math.Max(1, (int)Math.Ceiling((float)Math.Max(5, Math.Min(20, baseGoal)) / Math.Max(0.5f, Math.Min(3f, frequency))));
}
public static int Amount(int wave, float multiplier)
{
return Math.Max(1, Math.Min(40, (int)Math.Round((3.0 + Math.Floor((double)Math.Max(0, wave - 1) * 0.75)) * (double)Math.Max(0.5f, Math.Min(3f, multiplier)))));
}
public static int Rounds(int wave)
{
if (wave >= 3)
{
return Math.Min(4, 2 + (wave - 3) / 3);
}
return 1;
}
public static int Health(int wave, float multiplier, FishmanKind kind)
{
float num = ((kind == FishmanKind.Brute) ? 2.2f : ((kind == FishmanKind.Leaper) ? 0.78f : ((kind >= FishmanKind.Deepjaw) ? 8f : 1f)));
return Math.Max(1, Math.Min(50000, (int)Math.Round(35.0 * (1.0 + (double)Math.Max(0, wave - 1) * 0.12) * (double)Math.Max(0.5f, Math.Min(3f, multiplier)) * (double)num)));
}
public static int Attack(int wave, float multiplier, FishmanKind kind)
{
float num = ((kind == FishmanKind.Brute) ? 1.55f : ((kind == FishmanKind.Leaper) ? 0.82f : ((kind >= FishmanKind.Deepjaw) ? 2.4f : 1f)));
return Math.Max(1, Math.Min(1000, (int)Math.Round(8.0 * (1.0 + (double)Math.Max(0, wave - 1) * 0.01) * (double)Math.Max(0.25f, Math.Min(2f, multiplier)) * (double)num)));
}
public static int Worth(int wave, FishmanKind kind)
{
float num = ((kind == FishmanKind.Brute) ? 1.65f : ((kind == FishmanKind.Leaper) ? 1.25f : ((kind >= FishmanKind.Deepjaw) ? 10f : 1f)));
return Math.Max(250, Math.Min(250000, (int)Math.Round(750.0 * (1.0 + (double)Math.Max(0, wave - 1) * 0.08) * (double)num)));
}
public static float SpeedForSize(float size)
{
return Math.Max(0.58f, Math.Min(1.2f, 1.2f - (size - 0.5f) * 0.248f));
}
}
[Serializable]
public sealed class BossRecord
{
public string name;
public int kind;
public bool revengeDefeated;
}
[Serializable]
public sealed class WorldData
{
public string name;
public int completedWaves;
public int completedBosses;
public int catches;
public int nextBaseGoal;
public List<BossRecord> bosses = new List<BossRecord>();
}
[Serializable]
public sealed class SaveData
{
public int version = 2;
public List<WorldData> worlds = new List<WorldData>();
}
[Serializable]
public sealed class EventState
{
public int protocol = 2;
public int wave;
public int completed;
public int total;
public int alive;
public int normalAlive;
public int bruteAlive;
public int leaperAlive;
public int round = 1;
public int totalRounds = 1;
public int roundSignal;
public int thunderSignal;
public int bossHp;
public int bossMaxHp;
public int bossKind;
public int bossNumber;
public bool active;
public bool intro;
public bool boss;
public bool revenge;
public bool eventsEnabled = true;
public bool musicEnabled = true;
public bool lightningEnabled = true;
public float musicVolume = 0.7f;
public string bossName = "";
}
public struct StateMessage : IBroadcast
{
public string json;
}
public static class Codec
{
private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
TypeNameHandling = (TypeNameHandling)0,
MetadataPropertyHandling = (MetadataPropertyHandling)2
};
public static string ToJson<T>(T value)
{
return JsonConvert.SerializeObject((object)value, Settings);
}
public static T FromJson<T>(string value)
{
return JsonConvert.DeserializeObject<T>(value, Settings);
}
}
public static class Assets
{
public static readonly Dictionary<FishmanKind, Mesh> Meshes = new Dictionary<FishmanKind, Mesh>();
public static readonly Dictionary<FishmanKind, Texture2D> Textures = new Dictionary<FishmanKind, Texture2D>();
public static readonly Dictionary<FishmanKind, Texture2D> Icons = new Dictionary<FishmanKind, Texture2D>();
private static readonly string[] Keys = new string[7] { "fishman", "brute", "leaper", "deepjaw", "barnacle", "tidecaller", "puffertitan" };
private static byte[] Read(string name)
{
using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
if (stream == null)
{
throw new Exception("Missing embedded resource " + name);
}
byte[] array = new byte[stream.Length];
int num;
for (int i = 0; i < array.Length; i += num)
{
if ((num = stream.Read(array, i, array.Length - i)) <= 0)
{
break;
}
}
return array;
}
private static Mesh ReadMesh(byte[] data, string name)
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Expected O, but got Unknown
using MemoryStream input = new MemoryStream(data);
using BinaryReader binaryReader = new BinaryReader(input);
int num = binaryReader.ReadInt32();
int num2 = binaryReader.ReadInt32();
Vector3[] array = (Vector3[])(object)new Vector3[num];
Vector3[] array2 = (Vector3[])(object)new Vector3[num];
Vector2[] array3 = (Vector2[])(object)new Vector2[num];
int[] array4 = new int[num2];
for (int i = 0; i < num; i++)
{
array[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
}
for (int j = 0; j < num; j++)
{
array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
}
for (int k = 0; k < num; k++)
{
array3[k] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
}
for (int l = 0; l < num2; l++)
{
array4[l] = (int)binaryReader.ReadUInt32();
}
Mesh val = new Mesh
{
name = name,
indexFormat = (IndexFormat)1,
vertices = array,
normals = array2,
uv = array3,
triangles = array4
};
val.RecalculateBounds();
val.UploadMeshData(false);
return val;
}
public static void Load()
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Expected O, but got Unknown
if (Meshes.Count != 0)
{
return;
}
for (int i = 0; i < Keys.Length; i++)
{
FishmanKind key = (FishmanKind)i;
string text = Keys[i];
Meshes[key] = ReadMesh(Read("FishmenInvasion." + text + ".meshbin"), key.ToString() + " model");
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
{
name = key.ToString() + " texture",
wrapMode = (TextureWrapMode)0
};
if (!ImageConversion.LoadImage(val, Read("FishmenInvasion." + text + "-texture.jpg"), false))
{
throw new Exception(key.ToString() + " texture could not be decoded.");
}
Textures[key] = val;
Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, false)
{
name = key.ToString() + " HUD icon",
wrapMode = (TextureWrapMode)1
};
if (!ImageConversion.LoadImage(val2, Read("FishmenInvasion." + text + "-icon.png"), false))
{
throw new Exception(key.ToString() + " icon could not be decoded.");
}
Icons[key] = val2;
}
}
}
public static class FishmanItem
{
public static readonly Dictionary<FishmanKind, AttackingFish> Prefabs = new Dictionary<FishmanKind, AttackingFish>();
private static GameObject storage;
private static readonly string[] Names = new string[7] { "Fishman", "Fishman Brute", "Fishman Leaper", "Deepjaw", "Barnacle Colossus", "Tidecaller", "Puffer Titan" };
public static bool Ready => Prefabs.Count == 7;
public static bool Is(Item item)
{
if ((Object)(object)item != (Object)null && Array.IndexOf(Rules.ItemIds, item.ID) >= 0)
{
return (Object)(object)((Component)item).GetComponent<FishmanVisual>() != (Object)null;
}
return false;
}
public static FishmanKind Kind(Item item)
{
int num = (((Object)(object)item == (Object)null) ? (-1) : Array.IndexOf(Rules.ItemIds, item.ID));
if (num >= 0)
{
return (FishmanKind)num;
}
return FishmanKind.Fishman;
}
public static string Name(Item item)
{
return Names[(int)Kind(item)];
}
public static void Register()
{
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Expected O, but got Unknown
if (Ready || (Object)(object)InstanceFinder.NetworkManager == (Object)null)
{
return;
}
Dictionary<byte, Item> dictionary = (Dictionary<byte, Item>)AccessTools.Field(typeof(GameInfo), "_idToSpawnable").GetValue(null);
if (dictionary.Count == 0)
{
return;
}
Assets.Load();
for (int i = 0; i < Rules.ItemIds.Length; i++)
{
if (dictionary.ContainsKey(Rules.ItemIds[i]))
{
throw new Exception("Fishmen Invasion item ID " + Rules.ItemIds[i] + " is already in use.");
}
}
List<AttackingFish> source = (from x in dictionary.Values.OfType<AttackingFish>()
where (Object)(object)x != (Object)null && (Object)(object)((Component)x).GetComponent<NetworkObject>() != (Object)null
select x).Distinct().ToList();
AttackingFish val = ((IEnumerable<AttackingFish>)source).FirstOrDefault((Func<AttackingFish, bool>)((AttackingFish x) => (int)((Creature)x).BossType != 0 && (((Object)x).name ?? "").IndexOf("tuna", StringComparison.OrdinalIgnoreCase) >= 0)) ?? ((IEnumerable<AttackingFish>)source).FirstOrDefault((Func<AttackingFish, bool>)((AttackingFish x) => (((Object)x).name ?? "").IndexOf("tuna", StringComparison.OrdinalIgnoreCase) >= 0)) ?? ((IEnumerable<AttackingFish>)source).FirstOrDefault((Func<AttackingFish, bool>)((AttackingFish x) => (int)((Creature)x).BossType > 0)) ?? source.FirstOrDefault();
if ((Object)(object)val == (Object)null)
{
throw new Exception("No vanilla attacking-fish prefab was found.");
}
List<AttackingFish> list = source.Where((AttackingFish x) => (int)((Creature)x).BossType > 0).ToList();
if (list.Count == 0)
{
list.Add(val);
}
storage = new GameObject("Fishmen Invasion prefab storage");
storage.SetActive(false);
Object.DontDestroyOnLoad((Object)(object)storage);
for (int num = 0; num < 7; num++)
{
RegisterOne((FishmanKind)num, (num < 3) ? val : list[Random.Range(0, list.Count)], dictionary);
}
Plugin.Log("Registered seven Fishmen variants using Tuna/boss attacking-fish behavior.");
}
private static void RegisterOne(FishmanKind kind, AttackingFish source, Dictionary<byte, Item> ids)
{
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
//IL_041b: Unknown result type (might be due to invalid IL or missing references)
int num = (int)kind;
AttackingFish val = Object.Instantiate<AttackingFish>(source, storage.transform);
((Object)val).name = Names[num];
AccessTools.Field(typeof(Item), "_id").SetValue(val, Rules.ItemIds[num]);
AccessTools.Field(typeof(Item), "_cost").SetValue(val, 0);
AccessTools.Field(typeof(Item), "_worth").SetValue(val, Rules.Worth(1, kind));
AccessTools.Field(typeof(Item), "_ignoredBySeagulls").SetValue(val, false);
AccessTools.Field(typeof(Item), "_ignoredByMoneyNPC").SetValue(val, false);
AccessTools.Field(typeof(Item), "_heldPos").SetValue(val, (object)new Vector3(0.18f, -0.45f, 0.84f));
AccessTools.Field(typeof(Item), "_heldRot").SetValue(val, (object)new Vector3(-8f, 165f, 82f));
AccessTools.Field(typeof(Creature), "_maxHp").SetValue(val, Rules.Health(1, 1f, kind));
AccessTools.Field(typeof(Creature), "_excludeFromJournal").SetValue(val, true);
AccessTools.Field(typeof(Creature), "_skipRandomizedWeight").SetValue(val, true);
AccessTools.Field(typeof(Creature), "_ignoreDeathByWater").SetValue(val, true);
AccessTools.Field(typeof(Creature), "_bossType").SetValue(val, (object)(BossType)0);
AccessTools.Field(typeof(AttackingFish), "_onHitDamage").SetValue(val, Rules.Attack(1, 1f, kind));
AccessTools.Field(typeof(AttackingFish), "_setNewTargetDelay").SetValue(val, 0.35f);
AccessTools.Field(typeof(AttackingFish), "_attackInAir").SetValue(val, true);
AccessTools.Field(typeof(AttackingFish), "_towardsPlayerForce").SetValue(val, (kind == FishmanKind.Brute) ? 10f : 12f);
AccessTools.Field(typeof(AttackingFish), "_airTowardsPlayerForce").SetValue(val, (kind == FishmanKind.Leaper) ? 12f : 7f);
AccessTools.Field(typeof(Fish), "_jumpForce").SetValue(val, (kind == FishmanKind.Leaper) ? 14f : 8f);
AccessTools.Field(typeof(Fish), "_jumpOnWater").SetValue(val, true);
Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].enabled = false;
}
Collider[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Collider>(true);
for (int i = 0; i < componentsInChildren2.Length; i++)
{
componentsInChildren2[i].enabled = false;
}
FishmanVisual fishmanVisual = ((Component)val).gameObject.AddComponent<FishmanVisual>();
fishmanVisual.Build(kind);
((Component)val).gameObject.AddComponent<FishmanBrain>().kind = kind;
if (kind >= FishmanKind.Deepjaw)
{
((Component)val).gameObject.AddComponent<FishmanBossDeathEffect>();
}
AccessTools.Field(typeof(Item), "_mesh").SetValue(val, Assets.Meshes[kind]);
AccessTools.Field(typeof(Item), "_inventoryMeshScale").SetValue(val, 0.58f);
AccessTools.Field(typeof(Item), "_inventoryMeshPos").SetValue(val, (object)new Vector3(0f, -0.05f, 0f));
AccessTools.Field(typeof(Item), "_inventoryMeshRot").SetValue(val, (object)new Vector3(-8f, 155f, 0f));
AccessTools.Field(typeof(Item), "_renderers").SetValue(val, (from r in ((Component)fishmanVisual).GetComponentsInChildren<Renderer>(true)
where r.enabled
select r).ToList());
NetworkObject component = ((Component)val).GetComponent<NetworkObject>();
component.SetIsSpawnable(true);
PrefabObjects prefabObjects = InstanceFinder.NetworkManager.GetPrefabObjects<SinglePrefabObjects>(Rules.PrefabCollections[num], true);
if (prefabObjects.GetObjectCount() != 0)
{
throw new Exception("Fishmen network prefab collection " + Rules.PrefabCollections[num] + " is occupied.");
}
prefabObjects.AddObject(component, false, true);
ids.Add(Rules.ItemIds[num], (Item)(object)val);
((Dictionary<byte, Item>)AccessTools.Field(typeof(GameInfo), "_allItems").GetValue(null)).Add(Rules.ItemIds[num], (Item)(object)val);
((Dictionary<string, Item>)AccessTools.Field(typeof(GameInfo), "_nameToSpawnable").GetValue(null)).Add("fishmeninvasion_" + kind.ToString().ToLowerInvariant(), (Item)(object)val);
Prefabs[kind] = val;
}
public static AttackingFish Spawn(Vector3 position, int wave, float healthMulti, float attackMulti, FishmanKind kind, float size, bool revenge = false)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: 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)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0167: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
if (!Prefabs.TryGetValue(kind, out var value))
{
return null;
}
AttackingFish val = Object.Instantiate<AttackingFish>(value, position, Quaternion.identity, Server.Instance.DynamicObjectsHolder);
int num = Rules.Health(wave, healthMulti, kind);
if (revenge)
{
num = (int)((float)num * 1.65f);
}
AccessTools.Field(typeof(Creature), "_maxHp").SetValue(val, num);
((Creature)val)._hp.Value = num;
AccessTools.Field(typeof(AttackingFish), "_onHitDamage").SetValue(val, (int)((float)Rules.Attack(wave, attackMulti, kind) * (revenge ? 1.35f : 1f)));
AccessTools.Field(typeof(Item), "_worth").SetValue(val, Rules.Worth(wave, kind));
((Item)val)._syncedRandomWeight.Value = size;
FishmanBrain component = ((Component)val).GetComponent<FishmanBrain>();
if ((Object)(object)component != (Object)null)
{
component.Configure(kind, size, revenge, position);
}
InstanceFinder.ServerManager.Spawn(((Component)val).gameObject, (NetworkConnection)null, default(Scene));
((Item)val).RigidbodySync.ServerSetSyncedSimulator(((NetworkBehaviour)Server.Instance).Owner);
Vector3 val2 = Island.IslandPos - position;
val2.y = 0f;
if (((Vector3)(ref val2)).sqrMagnitude > 0.01f)
{
((Item)val).Rig.linearVelocity = ((Vector3)(ref val2)).normalized * 10f + Vector3.up * 7f;
}
return val;
}
}
public sealed class FishmanVisual : MonoBehaviour
{
private Transform model;
private Renderer modelRenderer;
private MaterialPropertyBlock block;
private Rigidbody rig;
private Creature creature;
private Vector3 facing = Vector3.forward;
private FishmanKind kind;
private float visualSpin;
public void Build(FishmanKind value)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
kind = value;
GameObject val = new GameObject("FishmanModel");
val.transform.SetParent(((Component)this).transform, false);
val.AddComponent<MeshFilter>().sharedMesh = Assets.Meshes[kind];
modelRenderer = (Renderer)(object)val.AddComponent<MeshRenderer>();
Material val2 = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"));
val2.mainTexture = (Texture)(object)Assets.Textures[kind];
if (val2.HasProperty("_BaseMap"))
{
val2.SetTexture("_BaseMap", (Texture)(object)Assets.Textures[kind]);
}
modelRenderer.sharedMaterial = val2;
BuildHitboxes(val, Assets.Meshes[kind]);
model = val.transform;
}
private static void BuildHitboxes(GameObject root, Mesh mesh)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: 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_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: 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)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_019f: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01a6: 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)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0206: Unknown result type (might be due to invalid IL or missing references)
Vector3[] vertices = mesh.vertices;
Bounds bounds = mesh.bounds;
List<Vector3>[] array = new List<Vector3>[24];
for (int i = 0; i < array.Length; i++)
{
array[i] = new List<Vector3>();
}
Vector3 min = ((Bounds)(ref bounds)).min;
Vector3 size = ((Bounds)(ref bounds)).size;
Vector3[] array2 = vertices;
foreach (Vector3 val in array2)
{
int num = Mathf.Clamp((int)((val.x - min.x) / Mathf.Max(0.001f, size.x) * 3f), 0, 2);
int num2 = Mathf.Clamp((int)((val.y - min.y) / Mathf.Max(0.001f, size.y) * 4f), 0, 3);
int num3 = Mathf.Clamp((int)((val.z - min.z) / Mathf.Max(0.001f, size.z) * 2f), 0, 1);
array[num + 3 * (num2 + 4 * num3)].Add(val);
}
List<Vector3>[] array3 = array;
Bounds val2 = default(Bounds);
foreach (List<Vector3> list in array3)
{
if (list.Count >= 8)
{
((Bounds)(ref val2))..ctor(list[0], Vector3.zero);
for (int k = 1; k < list.Count; k++)
{
((Bounds)(ref val2)).Encapsulate(list[k]);
}
Vector3 val3 = ((Bounds)(ref val2)).size * 0.01f;
Vector3 val4 = Vector3.Max(((Bounds)(ref bounds)).min, ((Bounds)(ref val2)).min - val3);
Vector3 val5 = Vector3.Min(((Bounds)(ref bounds)).max, ((Bounds)(ref val2)).max + val3);
Vector3 val6 = val5 - val4;
if (!(val6.x < 0.03f) && !(val6.y < 0.03f) && !(val6.z < 0.03f))
{
BoxCollider obj = root.AddComponent<BoxCollider>();
obj.center = (val4 + val5) * 0.5f;
obj.size = val6;
}
}
}
}
private void Awake()
{
rig = ((Component)this).GetComponent<Rigidbody>();
creature = ((Component)this).GetComponent<Creature>();
if ((Object)(object)model == (Object)null)
{
model = ((Component)this).transform.Find("FishmanModel");
if ((Object)(object)model != (Object)null)
{
modelRenderer = ((Component)model).GetComponent<Renderer>();
}
}
kind = FishmanItem.Kind((Item)(object)creature);
}
private void LateUpdate()
{
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_020b: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: 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_0289: Unknown result type (might be due to invalid IL or missing references)
//IL_029d: Unknown result type (might be due to invalid IL or missing references)
//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0271: Unknown result type (might be due to invalid IL or missing references)
//IL_0282: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: 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_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0167: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
//IL_02c1: Expected O, but got Unknown
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)model == (Object)null || (Object)(object)modelRenderer == (Object)null)
{
return;
}
if ((Object)(object)creature == (Object)null)
{
creature = ((Component)this).GetComponent<Creature>();
}
if ((Object)(object)rig == (Object)null)
{
rig = ((Component)this).GetComponent<Rigidbody>();
}
float num = 1.035f * Mathf.Clamp(((Object)(object)creature == (Object)null) ? 1f : ((Item)creature).RandomizedWeight, 0.5f, 3f);
model.localScale = Vector3.one * num;
if ((Object)(object)creature != (Object)null && !creature.IsDead && (Object)(object)((Item)creature).SyncedHolder == (Object)null)
{
Vector3 val = (((Object)(object)rig == (Object)null) ? Vector3.zero : rig.linearVelocity);
Vector3 val2 = val;
val2.y = 0f;
if (((Vector3)(ref val2)).sqrMagnitude > 0.2f)
{
facing = Vector3.Slerp(facing, ((Vector3)(ref val2)).normalized, Time.deltaTime * 9f);
}
model.position = ((Component)this).transform.position + Vector3.up * (0.78f * num);
Quaternion val3 = Quaternion.LookRotation(facing, Vector3.up);
if (((Vector3)(ref val)).sqrMagnitude > 3f)
{
if (kind == FishmanKind.Brute)
{
visualSpin += Time.deltaTime * 430f;
val3 *= Quaternion.AngleAxis(visualSpin, Vector3.forward);
}
else if (kind == FishmanKind.Fishman)
{
visualSpin += Time.deltaTime * 340f;
val3 *= Quaternion.AngleAxis(visualSpin, Vector3.up);
}
}
model.rotation = val3;
}
else
{
model.localPosition = Vector3.zero;
model.localRotation = Quaternion.identity;
}
float num2 = (((Object)(object)creature == (Object)null) ? 0f : ((Item)creature).Cookness);
Color val4 = ((num2 < 1f) ? Color.Lerp(Color.white, new Color(0.42f, 0.2f, 0.08f), Mathf.Clamp01(num2)) : Color.Lerp(new Color(0.42f, 0.2f, 0.08f), new Color(0.025f, 0.018f, 0.012f), Mathf.Clamp01(num2 - 1f)));
if (block == null)
{
block = new MaterialPropertyBlock();
}
modelRenderer.GetPropertyBlock(block);
block.SetColor("_BaseColor", val4);
block.SetColor("_Color", val4);
block.SetFloat("_Cookness", num2);
modelRenderer.SetPropertyBlock(block);
}
}
public sealed class FishmanBrain : MonoBehaviour
{
public FishmanKind kind;
public float size = 1f;
public bool revenge;
private AttackingFish creature;
private Rigidbody rig;
private Vector3 last;
private Vector3 spawnPoint;
private float nextAttack;
private float nextCheck;
private float stillFor;
private float noProgressFor;
private float lastTargetDistance = float.MaxValue;
private float deadSince = -1f;
private void Awake()
{
//IL_0020: 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_0026: 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)
//IL_002c: 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)
creature = ((Component)this).GetComponent<AttackingFish>();
rig = ((Component)this).GetComponent<Rigidbody>();
last = (spawnPoint = ((Component)this).transform.position);
if ((Object)(object)rig != (Object)null)
{
rig.maxAngularVelocity = 18f;
}
}
public void Configure(FishmanKind value, float scale, bool isRevenge, Vector3 spawn)
{
//IL_0016: 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_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
kind = value;
size = scale;
revenge = isRevenge;
spawnPoint = spawn;
last = spawn;
nextAttack = Time.time + 0.15f;
}
private void FixedUpdate()
{
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_038d: Unknown result type (might be due to invalid IL or missing references)
//IL_0393: Unknown result type (might be due to invalid IL or missing references)
//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_045d: Unknown result type (might be due to invalid IL or missing references)
//IL_047c: Unknown result type (might be due to invalid IL or missing references)
//IL_049c: Unknown result type (might be due to invalid IL or missing references)
//IL_027c: Unknown result type (might be due to invalid IL or missing references)
//IL_028e: Unknown result type (might be due to invalid IL or missing references)
//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
//IL_0334: Unknown result type (might be due to invalid IL or missing references)
//IL_034f: Unknown result type (might be due to invalid IL or missing references)
//IL_035c: Unknown result type (might be due to invalid IL or missing references)
//IL_0322: Unknown result type (might be due to invalid IL or missing references)
if (!InstanceFinder.IsServerStarted || (Object)(object)creature == (Object)null || (Object)(object)rig == (Object)null)
{
return;
}
if (((Creature)creature)._hp.Value <= 0)
{
if (deadSince < 0f)
{
deadSince = Time.time;
}
if (kind >= FishmanKind.Deepjaw && Time.time - deadSince > 1.15f)
{
if (!((NetworkBehaviour)creature).IsDeinitializing)
{
((Item)creature).DestroyItem((byte)0, byte.MaxValue);
}
return;
}
if (Time.time - deadSince > 4f && !((Item)creature).IsInInventory && !((Item)creature).HasPlayerHolder)
{
Vector3 linearVelocity = rig.linearVelocity;
if (((Vector3)(ref linearVelocity)).sqrMagnitude < 0.25f)
{
rig.Sleep();
}
}
if (Time.time - deadSince > 180f && !((Item)creature).IsInInventory && !((Item)creature).HasPlayerHolder)
{
((Item)creature).DestroyItem((byte)0, byte.MaxValue);
}
return;
}
Player nearestAlivePlayer = PlayerManager.GetNearestAlivePlayer(rig.worldCenterOfMass);
if (Time.time >= nextAttack && (Object)(object)nearestAlivePlayer != (Object)null)
{
float num = ((kind == FishmanKind.Leaper) ? Random.Range(0.28f, 0.48f) : ((kind == FishmanKind.Brute) ? Random.Range(0.4f, 0.65f) : Random.Range(0.42f, 0.68f)));
nextAttack = Time.time + num;
Vector3 val = nearestAlivePlayer.Transform.position - rig.worldCenterOfMass;
val.y = 0f;
if (((Vector3)(ref val)).sqrMagnitude > 0.1f)
{
((Vector3)(ref val)).Normalize();
float num2 = ((kind == FishmanKind.Brute) ? 0.82f : ((kind == FishmanKind.Leaper) ? 1.15f : 1f));
float num3 = Rules.SpeedForSize(size) * num2 * (revenge ? 1.2f : 1f);
float num4 = ((kind == FishmanKind.Brute) ? 11f : ((kind == FishmanKind.Leaper) ? 10.5f : 10f));
float num5 = ((kind == FishmanKind.Leaper) ? 14f : ((kind == FishmanKind.Brute) ? 4.5f : 8f));
rig.linearVelocity = new Vector3(val.x * num4 * num3, Mathf.Max(rig.linearVelocity.y, num5 * num3), val.z * num4 * num3);
if (kind == FishmanKind.Brute)
{
rig.angularVelocity = Vector3.Cross(Vector3.up, val) * 10f;
}
else if (kind == FishmanKind.Leaper)
{
rig.angularVelocity = new Vector3(Random.Range(-3f, 3f), Random.Range(-5f, 5f), Random.Range(-3f, 3f));
}
else
{
rig.angularVelocity = new Vector3(val.z * 7f, Random.Range(-8f, 8f), (0f - val.x) * 7f);
}
}
}
if (Time.time >= nextCheck)
{
nextCheck = Time.time + 1f;
float num6 = Vector3.Distance(((Component)this).transform.position, last);
stillFor = ((num6 < 0.3f) ? (stillFor + 1f) : 0f);
last = ((Component)this).transform.position;
float num7 = (((Object)(object)nearestAlivePlayer == (Object)null) ? 0f : Vector3.Distance(rig.worldCenterOfMass, nearestAlivePlayer.Transform.position));
if ((Object)(object)nearestAlivePlayer != (Object)null && num7 > 4f)
{
noProgressFor = ((num7 > lastTargetDistance - 0.45f) ? (noProgressFor + 1f) : 0f);
lastTargetDistance = num7;
}
else
{
noProgressFor = 0f;
lastTargetDistance = num7;
}
bool flag = ((Component)this).transform.position.y < WaterManager.WaterHeight - 7f;
bool flag2 = Physics.CheckSphere(rig.worldCenterOfMass, 0.18f * Mathf.Clamp(size, 0.5f, 1.5f), LayerMask.op_Implicit(GameInfo.LevelLayer), (QueryTriggerInteraction)1);
if (flag || flag2 || stillFor >= 4f || noProgressFor >= 6f)
{
Recover(flag ? "under map" : (flag2 ? "inside terrain" : "unable to reach a player"));
}
}
}
private void Recover(string reason)
{
//IL_001a: 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_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: 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_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: 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_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: 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_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: 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)
Vector3 val = (spawnPoint = (((Object)(object)Plugin.Instance == (Object)null) ? spawnPoint : Plugin.Instance.GetEnemySpawnPosition()));
((Component)this).transform.position = val;
rig.position = val;
Vector3 val2 = Island.IslandPos - val;
val2.y = 0f;
if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
{
val2 = Vector3.forward;
}
rig.linearVelocity = ((Vector3)(ref val2)).normalized * 10f + Vector3.up * 7f;
rig.angularVelocity = Vector3.zero;
stillFor = (noProgressFor = 0f);
lastTargetDistance = float.MaxValue;
last = val;
Plugin.Log("Recovered a stuck " + kind.ToString() + " (" + reason + ") at a clear waterline spawn.");
}
}
public sealed class FishmanBossDeathEffect : MonoBehaviour
{
private Creature creature;
private Rigidbody rig;
private bool played;
private void Awake()
{
creature = ((Component)this).GetComponent<Creature>();
rig = ((Component)this).GetComponent<Rigidbody>();
}
private void Update()
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
if (played || (Object)(object)creature == (Object)null || creature._hp.Value > 0)
{
return;
}
played = true;
BossManager.BossExplosion(((Object)(object)rig == (Object)null) ? ((Component)this).transform.position : rig.worldCenterOfMass, false);
Transform val = ((Component)this).transform.Find("FishmanModel");
if ((Object)(object)val != (Object)null)
{
Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].enabled = false;
}
Collider[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Collider>(true);
for (int i = 0; i < componentsInChildren2.Length; i++)
{
componentsInChildren2[i].enabled = false;
}
}
Plugin.Log("Played the vanilla BossDeath explosion for " + FishmanItem.Name((Item)(object)creature) + ".");
}
}
public static class EventAudio
{
private static AudioClip music;
private static AudioClip bossMusic;
private static AudioClip thunder;
private static AudioSource musicSource;
private static AudioSource fxSource;
private static bool loading;
private static bool eventActive;
private static bool bossActive;
private static bool pendingThunder;
public static IEnumerator Load()
{
if (!loading && !((Object)(object)music != (Object)null))
{
loading = true;
string folder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
yield return LoadOne(Find(folder, "fishmen-event-music.mp3", "FishmenInvasionEventMusic.mp3"), delegate(AudioClip c)
{
music = c;
});
yield return LoadOne(Find(folder, "fishmen-boss-music.mp3", "FishmanInvasionBossFightMusic.mp3"), delegate(AudioClip c)
{
bossMusic = c;
});
yield return LoadOne(Find(folder, "fishmen-event-start.mp3", "Thunderclapeventstartsound.mp3"), delegate(AudioClip c)
{
thunder = c;
});
loading = false;
}
}
private static string Find(string folder, string packaged, string original)
{
string text = Path.Combine(folder, packaged);
if (File.Exists(text))
{
return text;
}
return Path.Combine(folder, "assets", original);
}
private static IEnumerator LoadOne(string path, Action<AudioClip> assign)
{
if (!File.Exists(path))
{
Plugin.Log("Missing audio file: " + path);
yield break;
}
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, (AudioType)13);
try
{
yield return request.SendWebRequest();
if ((int)request.result != 1)
{
Plugin.Log("Audio load failed: " + request.error);
}
else
{
assign(DownloadHandlerAudioClip.GetContent(request));
}
}
finally
{
((IDisposable)request)?.Dispose();
}
}
private static void Ensure()
{
//IL_0013: 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_001e: Expected O, but got Unknown
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)musicSource != (Object)null))
{
GameObject val = new GameObject("Fishmen Invasion audio");
Object.DontDestroyOnLoad((Object)val);
musicSource = val.AddComponent<AudioSource>();
musicSource.loop = true;
musicSource.playOnAwake = false;
musicSource.spatialBlend = 0f;
fxSource = val.AddComponent<AudioSource>();
fxSource.playOnAwake = false;
fxSource.spatialBlend = 0f;
}
}
public static void Begin(bool boss, bool playThunder)
{
Ensure();
eventActive = true;
SetBoss(boss);
pendingThunder = playThunder && (Object)(object)thunder == (Object)null;
if (playThunder && (Object)(object)thunder != (Object)null)
{
fxSource.PlayOneShot(thunder, 0.58f);
}
PlayCorrectClip();
}
public static void SetBoss(bool boss)
{
if (bossActive != boss)
{
bossActive = boss;
if (eventActive)
{
PlayCorrectClip();
}
}
}
private static void PlayCorrectClip()
{
Ensure();
AudioClip val = ((bossActive && (Object)(object)bossMusic != (Object)null) ? bossMusic : music);
if ((Object)(object)val != (Object)null && (Object)(object)musicSource.clip != (Object)(object)val)
{
musicSource.Stop();
musicSource.clip = val;
musicSource.Play();
}
else if ((Object)(object)val != (Object)null && !musicSource.isPlaying)
{
musicSource.clip = val;
musicSource.Play();
}
}
public static void End()
{
eventActive = false;
}
public static void Tick(bool allowMusic, float volume)
{
Ensure();
if (pendingThunder && (Object)(object)thunder != (Object)null)
{
pendingThunder = false;
fxSource.PlayOneShot(thunder, 0.58f);
}
float num = ((eventActive && allowMusic) ? (0.42f * Mathf.Clamp01(volume)) : 0f);
musicSource.volume = Mathf.MoveTowards(musicSource.volume, num, Time.unscaledDeltaTime * ((num > musicSource.volume) ? 0.18f : 0.11f));
if (!eventActive && musicSource.volume <= 0.001f && musicSource.isPlaying)
{
musicSource.Stop();
}
else if (eventActive && allowMusic)
{
PlayCorrectClip();
}
}
public static void Destroy()
{
if ((Object)(object)musicSource != (Object)null)
{
Object.Destroy((Object)(object)((Component)musicSource).gameObject);
}
musicSource = null;
fxSource = null;
music = null;
bossMusic = null;
thunder = null;
}
}
[BepInPlugin("ponyfisher.howtofish.fishmeninvasion", "Fishmen Invasion Mod", "0.2.6")]
[DefaultExecutionOrder(29600)]
public sealed class Plugin : BaseUnityPlugin
{
public const string Guid = "ponyfisher.howtofish.fishmeninvasion";
public static Plugin Instance;
public EventState State = new EventState();
public string Status = "Fishmen invasions are waiting on internal Islands 2 through 5.";
private ConfigEntry<bool> eventsEnabled;
private ConfigEntry<bool> lightningEnabled;
private ConfigEntry<bool> musicEnabled;
private ConfigEntry<float> musicVolume;
private ConfigEntry<float> amountMultiplier;
private ConfigEntry<float> healthMultiplier;
private ConfigEntry<float> attackMultiplier;
private ConfigEntry<float> frequencyMultiplier;
private SaveData save = new SaveData();
private WorldData world;
private string savePath;
private NetworkManager manager;
private Harmony harmony;
private readonly List<AttackingFish> active = new List<AttackingFish>();
private readonly List<AttackingFish> spawned = new List<AttackingFish>();
private AttackingFish boss;
private float introEnds;
private float nextBroadcast;
private float nextSave;
private float flashStarted = -10f;
private float nextBossThunder;
private float nextMinionFill;
private float nextWaveSpawn;
private int pendingRoundEnemies;
private bool registrationFailed;
private bool wipeEnding;
private string activeBossBaseName = "";
private BossRecord activeBossRecord;
private static readonly string[] BossNames = new string[20]
{
"Captain Gillbeard", "Admiral Chum Bucket", "Baron von Bubbles", "Scurvy McScale", "Fin Diesel", "The Codfather", "Salmon Ella", "Long John Silverfish", "Davy Jones' Tuna", "Sir Bites-a-Lot",
"Mackerelmore", "Captain Flounderpants", "Blackbeard Bass", "Grouper Trooper", "Sushi Sam", "The Briny Bully", "Marlin Monroe", "Anchovy Annie", "Reef Richards", "Pike Tyson"
};
private FishmanKind activeBossKind = FishmanKind.Deepjaw;
private bool optionsOpen;
private bool draftsLoaded;
private float amountDraft = 1f;
private float healthDraft = 1f;
private float attackDraft = 1f;
private float frequencyDraft = 1f;
private float musicVolumeDraft = 0.7f;
private float nextGuiTimingLog;
private GUIStyle titleStyle;
private GUIStyle labelStyle;
private GUIStyle headerStyle;
private GUIStyle buttonStyle;
private GUIStyle barStyle;
private GUIStyle invasionButtonStyle;
private Rect optionsRect;
public bool EventsEnabled => eventsEnabled.Value;
public bool LightningEnabled => lightningEnabled.Value;
public bool MusicEnabled => musicEnabled.Value;
public float MusicVolume => musicVolume.Value;
public bool EffectiveMusicEnabled
{
get
{
if (!InstanceFinder.IsServerStarted)
{
return State.musicEnabled;
}
return MusicEnabled;
}
}
public bool EffectiveLightningEnabled
{
get
{
if (!InstanceFinder.IsServerStarted)
{
return State.lightningEnabled;
}
return LightningEnabled;
}
}
public float EffectiveMusicVolume
{
get
{
if (!InstanceFinder.IsServerStarted)
{
return State.musicVolume;
}
return MusicVolume;
}
}
public float AmountMultiplier => amountMultiplier.Value;
public float HealthMultiplier => healthMultiplier.Value;
public float AttackMultiplier => attackMultiplier.Value;
public float FrequencyMultiplier => frequencyMultiplier.Value;
public float FlashAge => Time.unscaledTime - flashStarted;
public bool OptionsOpen => optionsOpen;
public static void Log(string value)
{
if ((Object)(object)Instance != (Object)null)
{
((BaseUnityPlugin)Instance).Logger.LogInfo((object)value);
}
}
private void Awake()
{
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Expected O, but got Unknown
Instance = this;
((MonoBehaviour)this).useGUILayout = true;
eventsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Event", "Enabled", true, "Host: enable Fishmen invasions.");
lightningEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "LightningFlashes", true, "Host: show lightning flashes for the lobby.");
musicEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "EventMusic", true, "Host: play invasion music for the lobby.");
musicVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Effects", "EventMusicVolume", 0.7f, "Host event music volume (0-1). Default is 30% quieter.");
amountMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "FishmenAmountMultiplier", 1f, "Host event amount multiplier (0.5-3.0).");
healthMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "FishmenHealthMultiplier", 1f, "Host health multiplier (0.5-3.0).");
attackMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "FishmenAttackMultiplier", 1f, "Host attack multiplier (0.25-2.0).");
frequencyMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "InvasionFrequencyMultiplier", 1f, "Host frequency multiplier (0.5-3.0; higher triggers sooner).");
ClampConfig();
savePath = Path.Combine(Paths.ConfigPath, "FishmenInvasion-worlds.json");
LoadSave();
GenericWriter<StateMessage>.SetWrite((Action<Writer, StateMessage>)delegate(Writer w, StateMessage v)
{
w.WriteString(v.json);
});
GenericReader<StateMessage>.SetRead((Func<Reader, StateMessage>)((Reader r) => new StateMessage
{
json = r.ReadStringAllocated()
}));
harmony = new Harmony("ponyfisher.howtofish.fishmeninvasion");
harmony.PatchAll(typeof(Plugin).Assembly);
PatchDevIslandTrigger();
((MonoBehaviour)this).StartCoroutine(EventAudio.Load());
Log("Fishmen Invasion Mod 0.2.6 loaded. Eligible internal island indices: 2-5.");
}
private void LoadSave()
{
try
{
if (!File.Exists(savePath))
{
return;
}
save = Codec.FromJson<SaveData>(File.ReadAllText(savePath));
if (save == null || save.worlds == null)
{
throw new Exception("Unrecognized save format.");
}
save.version = 2;
foreach (WorldData world in save.worlds)
{
if (world.bosses == null)
{
world.bosses = new List<BossRecord>();
}
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)ex);
save = new SaveData();
Status = "The invasion save was unreadable; a fresh event record will be used.";
}
}
private void PatchDevIslandTrigger()
{
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
try
{
Type type = AccessTools.TypeByName("DevIslandUnlocked.Plugin");
MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "QueueDevIslandFromTrigger", new Type[2]
{
typeof(Collider),
typeof(string)
}, (Type[])null));
MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "AllowDevIslandTrigger", (Type[])null, (Type[])null);
if (methodInfo != null && methodInfo2 != null)
{
harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Log("Protected saved player spawns from the Dev Island travel trigger.");
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not install optional Dev Island spawn protection: " + ex.Message));
}
}
private static bool AllowDevIslandTrigger(Collider __0)
{
if ((Object)(object)__0 == (Object)null)
{
return true;
}
bool num = string.Equals(((Object)__0).name, "MenuBoat", StringComparison.OrdinalIgnoreCase) || (Object)(object)((Component)__0).GetComponentInParent<MainMenuManager>() != (Object)null;
Player componentInParent = ((Component)__0).GetComponentInParent<Player>();
if (!num && (Object)(object)componentInParent == (Object)null)
{
return true;
}
if ((Object)(object)Instance != (Object)null)
{
((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Ignored Dev Island startup trigger from " + ((Object)__0).name + " so the saved profile island remains authoritative."));
}
return false;
}
private void ClampConfig()
{
amountMultiplier.Value = Mathf.Clamp(amountMultiplier.Value, 0.5f, 3f);
healthMultiplier.Value = Mathf.Clamp(healthMultiplier.Value, 0.5f, 3f);
attackMultiplier.Value = Mathf.Clamp(attackMultiplier.Value, 0.25f, 2f);
frequencyMultiplier.Value = Mathf.Clamp(frequencyMultiplier.Value, 0.5f, 3f);
musicVolume.Value = Mathf.Clamp01(musicVolume.Value);
}
public void SaveOptions(float amount, float health, float attack, float frequency, float volume)
{
amountMultiplier.Value = Mathf.Clamp(amount, 0.5f, 3f);
healthMultiplier.Value = Mathf.Clamp(health, 0.5f, 3f);
attackMultiplier.Value = Mathf.Clamp(attack, 0.25f, 2f);
frequencyMultiplier.Value = Mathf.Clamp(frequency, 0.5f, 3f);
musicVolume.Value = Mathf.Clamp01(volume);
((BaseUnityPlugin)this).Config.Save();
Status = (InstanceFinder.IsServerStarted ? "Host invasion settings saved." : "Local preferences saved. Gameplay scaling is controlled by the host.");
}
public void SetToggle(string key, bool value)
{
switch (key)
{
case "events":
eventsEnabled.Value = value;
break;
case "lightning":
lightningEnabled.Value = value;
break;
case "music":
musicEnabled.Value = value;
break;
}
((BaseUnityPlugin)this).Config.Save();
if (key == "events" && !value && InstanceFinder.IsServerStarted && State.active)
{
CancelEvent(destroyBodies: false);
}
}
private void RegisterNetwork()
{
if (!((Object)(object)manager == (Object)(object)InstanceFinder.NetworkManager))
{
if ((Object)(object)manager != (Object)null)
{
manager.ClientManager.UnregisterBroadcast<StateMessage>((Action<StateMessage, Channel>)ReceiveState);
}
manager = InstanceFinder.NetworkManager;
if ((Object)(object)manager != (Object)null)
{
manager.ClientManager.RegisterBroadcast<StateMessage>((Action<StateMessage, Channel>)ReceiveState);
}
}
}
private void Update()
{
RegisterNetwork();
if (!registrationFailed && !FishmanItem.Ready)
{
try
{
FishmanItem.Register();
}
catch (Exception ex)
{
registrationFailed = true;
Status = "Fishman registration failed; check the BepInEx log.";
((BaseUnityPlugin)this).Logger.LogError((object)ex);
}
}
EventAudio.Tick(EffectiveMusicEnabled, EffectiveMusicVolume);
if (InstanceFinder.IsServerStarted && SaveManager.CurServerSave != null)
{
LoadWorld(SaveManager.CurServerSave.Name);
TickServer();
if (Time.unscaledTime >= nextBroadcast)
{
nextBroadcast = Time.unscaledTime + 0.2f;
Broadcast();
}
if (Time.unscaledTime >= nextSave)
{
nextSave = Time.unscaledTime + 8f;
Persist();
}
}
else if (!InstanceFinder.IsClientStarted)
{
world = null;
if (State.active)
{
ApplyState(new EventState());
}
}
}
private void LoadWorld(string name)
{
if (world == null || !(world.name == name))
{
if (State.active)
{
CancelEvent(destroyBodies: false);
}
world = save.worlds.FirstOrDefault((WorldData w) => w.name == name);
if (world == null)
{
world = new WorldData
{
name = name
};
save.worlds.Add(world);
}
if (world.bosses == null)
{
world.bosses = new List<BossRecord>();
}
world.catches = 0;
world.nextBaseGoal = Random.Range(5, 21);
State = new EventState
{
completed = world.completedWaves
};
active.Clear();
spawned.Clear();
boss = null;
Status = "Invasion watch reset: defeat " + Rules.CatchTarget(world.nextBaseGoal, FrequencyMultiplier) + " fish to draw the next wave.";
Persist();
Broadcast();
}
}
public void ServerCreatureKilled(Creature creature)
{
if (InstanceFinder.IsServerStarted && world != null && !State.active && EventsEnabled && !((Object)(object)creature == (Object)null) && !((Object)(object)((Item)creature).Fish == (Object)null) && !FishmanItem.Is((Item)(object)creature) && !((Object)(object)OnlineIslandManager.Instance == (Object)null) && Rules.EligibleIsland(OnlineIslandManager.CurIsland, OnlineIslandManager.MaxIslandUnlocked))
{
world.catches++;
int num = Rules.CatchTarget(world.nextBaseGoal, FrequencyMultiplier);
Status = "Invasion watch: " + world.catches + " / " + num + " fish defeated.";
if (world.catches >= num)
{
StartEvent();
}
}
}
private void StartEvent(bool forceBoss = false)
{
if (world != null && FishmanItem.Ready)
{
int num = world.completedWaves + 1;
world.catches = 0;
world.nextBaseGoal = Random.Range(5, 21);
active.Clear();
spawned.Clear();
boss = null;
activeBossRecord = null;
activeBossBaseName = "";
bool flag = forceBoss || num % 10 == 0;
EventState eventState = new EventState
{
active = true,
intro = true,
wave = num,
completed = world.completedWaves,
total = Rules.Amount(num, AmountMultiplier),
alive = Rules.Amount(num, AmountMultiplier),
round = 1,
totalRounds = (flag ? 1 : Rules.Rounds(num)),
roundSignal = State.roundSignal + 1,
thunderSignal = State.thunderSignal + 1,
boss = flag,
bossNumber = (flag ? (world.completedBosses + 1) : 0)
};
if (flag)
{
PrepareBoss(eventState);
}
introEnds = Time.time + 3.2f;
ApplyState(eventState);
Status = (flag ? (eventState.bossName + " has invaded the island!") : "The sky cracks open. Fishmen are invading!");
Broadcast();
}
}
private void PrepareBoss(EventState next)
{
FishmanKind fishmanKind = (FishmanKind)Random.Range(3, 7);
next.total = 10;
next.alive = 10;
float value = Random.value;
List<BossRecord> list = world.bosses.Where((BossRecord x) => !x.revengeDefeated).ToList();
if (value < 0.1f && list.Count > 0)
{
activeBossRecord = list[Random.Range(0, list.Count)];
fishmanKind = (FishmanKind)activeBossRecord.kind;
activeBossBaseName = activeBossRecord.name;
next.bossName = "Revenge of " + activeBossBaseName;
next.revenge = true;
}
else if (value < 0.19f && world.bosses.Count > 0)
{
BossRecord bossRecord = world.bosses[Random.Range(0, world.bosses.Count)];
activeBossBaseName = UnusedBossName();
next.bossName = "SPAWN OF " + bossRecord.name + ": " + activeBossBaseName;
}
else
{
activeBossBaseName = UnusedBossName();
next.bossName = activeBossBaseName;
}
next.bossMaxHp = Rules.Health(next.wave, HealthMultiplier, fishmanKind) * (next.revenge ? 165 : 100) / 100;
next.bossHp = next.bossMaxHp;
next.bossKind = (int)fishmanKind;
activeBossKind = fishmanKind;
}
private string UnusedBossName()
{
HashSet<string> used = new HashSet<string>(world.bosses.Select((BossRecord x) => x.name));
List<string> list = BossNames.Where((string x) => !used.Contains(x)).ToList();
if (list.Count <= 0)
{
return "Captain Scale-" + Random.Range(100, 999);
}
return list[Random.Range(0, list.Count)];
}
public void ForceStartEvent()
{
if (!InstanceFinder.IsServerStarted)
{
Status = "Only the host can force-start an invasion.";
}
else if (world == null || SaveManager.CurServerSave == null)
{
Status = "Load into a world before starting an invasion.";
}
else if (State.active)
{
Status = "A Fishmen invasion is already active.";
}
else if (!EventsEnabled)
{
Status = "Enable Fishmen invasions before force-starting a wave.";
}
else if ((Object)(object)OnlineIslandManager.Instance == (Object)null || !Rules.EligibleIsland(OnlineIslandManager.CurIsland, OnlineIslandManager.MaxIslandUnlocked))
{
Status = "Force Start Wave is available only on internal Islands 2 through 5 after Island 2 is unlocked.";
}
else
{
StartEvent();
}
}
public Vector3 GetEnemySpawnPosition()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: 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_0037: 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_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
float num = Mathf.Max(18f, Island.IslandSize * 0.95f + 10f);
Vector3 result = Island.IslandPos + Vector3.forward * (num + 12f);
result.y = WaterManager.WaterHeight + 0.6f;
Vector3 val = default(Vector3);
for (int i = 0; i < 28; i++)
{
float num2 = Random.value * (float)Math.PI * 2f;
float num3 = Random.Range(0f, 10f) + (float)(i / 8) * 4f;
((Vector3)(ref val))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2));
Vector3 val2 = Island.IslandPos + val * (num + num3);
val2.y = WaterManager.WaterHeight + 0.6f;
if (!Physics.CheckSphere(val2, 2.8f, LayerMask.op_Implicit(GameInfo.LevelLayer), (QueryTriggerInteraction)1))
{
return val2;
}
result = val2;
}
return result;
}
private FishmanKind RandomMinionKind()
{
if (State.wave < 3)
{
return FishmanKind.Fishman;
}
float value = Random.value;
float num = Mathf.Clamp01(0.18f + (float)(State.wave - 3) * 0.025f);
if (value > num)
{
return FishmanKind.Fishman;
}
if (!(Random.value < 0.52f))
{
return FishmanKind.Leaper;
}
return FishmanKind.Brute;
}
private AttackingFish SpawnEnemy(FishmanKind kind, bool isBoss = false)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
float size = (isBoss ? Random.Range(2.5f, 3f) : Random.Range(0.5f, 1.5f));
AttackingFish val = FishmanItem.Spawn(GetEnemySpawnPosition(), State.wave, HealthMultiplier, AttackMultiplier, kind, size, isBoss && State.revenge);
if ((Object)(object)val != (Object)null)
{
spawned.Add(val);
if (!isBoss)
{
active.Add(val);
}
}
return val;
}
public void ForceStartBossEvent()
{
if (!InstanceFinder.IsServerStarted)
{
Status = "Only the host can force-start a boss event.";
}
else if (world == null || SaveManager.CurServerSave == null)
{
Status = "Load into a world before starting a boss event.";
}
else if (State.active)
{
Status = "An invasion is already active.";
}
else if (!EventsEnabled)
{
Status = "Enable Fishmen invasions before force-starting a boss.";
}
else if ((Object)(object)OnlineIslandManager.Instance == (Object)null || !Rules.EligibleIsland(OnlineIslandManager.CurIsland, OnlineIslandManager.MaxIslandUnlocked))
{
Status = "Force Random Boss is available only on internal Islands 2 through 5 after Island 2 is unlocked.";
}
else
{
StartEvent(forceBoss: true);
}
}
private void SpawnCurrentRound()
{
if (State.active && State.intro)
{
active.Clear();
if (State.boss)
{
boss = SpawnEnemy(activeBossKind, isBoss: true);
FillBossMinions();
nextBossThunder = Time.time + Random.Range(4f, 8f);
}
else
{
pendingRoundEnemies = State.total;
nextWaveSpawn = Time.time;
}
State.intro = false;
UpdateVariantCounts();
Broadcast();
}
}
private void FillRoundQueue()
{
if (!State.boss && pendingRoundEnemies > 0 && active.Count < 10 && !(Time.time < nextWaveSpawn))
{
if ((Object)(object)SpawnEnemy(RandomMinionKind()) != (Object)null)
{
pendingRoundEnemies--;
}
nextWaveSpawn = Time.time + 0.5f;
}
}
private void FillBossMinions()
{
if (!State.boss || (Object)(object)boss == (Object)null || ((Creature)boss)._hp.Value <= 0)
{
return;
}
for (int num = active.Count - 1; num >= 0; num--)
{
if ((Object)(object)active[num] == (Object)null || ((NetworkBehaviour)active[num]).IsDeinitializing || ((Creature)active[num])._hp.Value <= 0)
{
active.RemoveAt(num);
}
}
while (active.Count < 10 && !((Object)(object)SpawnEnemy(RandomMinionKind()) == (Object)null))
{
}
State.total = 10;
UpdateVariantCounts();
}
private void TickServer()
{
if (State.active && (!EventsEnabled || (Object)(object)OnlineIslandManager.Instance == (Object)null || !Rules.EligibleIsland(OnlineIslandManager.CurIsland, OnlineIslandManager.MaxIslandUnlocked)))
{
CancelEvent(destroyBodies: false);
}
else
{
if (!State.active)
{
return;
}
if (PlayerManager.Players.Count > 0 && PlayerManager.AlivePlayers.Count == 0)
{
wipeEnding = true;
CancelEvent(destroyBodies: true);
return;
}
if (State.intro)
{
if (Time.time >= introEnds)
{
SpawnCurrentRound();
}
return;
}
for (int num = active.Count - 1; num >= 0; num--)
{
AttackingFish val = active[num];
if ((Object)(object)val == (Object)null || ((NetworkBehaviour)val).IsDeinitializing || ((Creature)val)._hp.Value <= 0)
{
active.RemoveAt(num);
}
}
if (State.boss)
{
if ((Object)(object)boss == (Object)null || ((NetworkBehaviour)boss).IsDeinitializing || ((Creature)boss)._hp.Value <= 0)
{
CompleteBoss();
return;
}
State.bossHp = ((Creature)boss)._hp.Value;
State.bossMaxHp = Mathf.Max(State.bossMaxHp, ((Creature)boss)._hp.Value);
if (Time.time >= nextMinionFill)
{
nextMinionFill = Time.time + 1f;
FillBossMinions();
}
if (Time.time >= nextBossThunder)
{
nextBossThunder = Time.time + Random.Range(4f, 8f);
State.thunderSignal++;
}
UpdateVariantCounts();
return;
}
FillRoundQueue();
UpdateVariantCounts();
if (active.Count == 0 && pendingRoundEnemies == 0)
{
if (State.round < State.totalRounds)
{
BeginNextRound();
}
else
{
CompleteEvent();
}
}
}
}
private void UpdateVariantCounts()
{
State.alive = active.Count + ((!State.boss) ? pendingRoundEnemies : 0);
State.normalAlive = active.Count((AttackingFish x) => (Object)(object)x != (Object)null && FishmanItem.Kind((Item)(object)x) == FishmanKind.Fishman);
State.bruteAlive = active.Count((AttackingFish x) => (Object)(object)x != (Object)null && FishmanItem.Kind((Item)(object)x) == FishmanKind.Brute);
State.leaperAlive = active.Count((AttackingFish x) => (Object)(object)x != (Object)null && FishmanItem.Kind((Item)(object)x) == FishmanKind.Leaper);
}
private void BeginNextRound()
{
State.round++;
State.roundSignal++;
State.thunderSignal++;
State.intro = true;
pendingRoundEnemies = 0;
State.alive = State.total;
introEnds = Time.time + 2.4f;
Status = "Wave " + State.wave + ", round " + State.round + " incoming!";
Broadcast();
}
private void CompleteBoss()
{
world.completedBosses++;
foreach (AttackingFish item in active)
{
if ((Object)(object)item != (Object)null && !((NetworkBehaviour)item).IsDeinitializing)
{
((Item)item).DestroyItem((byte)0, byte.MaxValue);
}
}
active.Clear();
if (State.revenge && activeBossRecord != null)
{
activeBossRecord.revengeDefeated = true;
}
else if (!string.IsNullOrEmpty(activeBossBaseName) && world.bosses.All((BossRecord x) => x.name != activeBossBaseName))
{
world.bosses.Add(new BossRecord
{
name = activeBossBaseName,
kind = (int)activeBossKind
});
}
CompleteEvent();
}
private void CompleteEvent()
{
if (State.active)
{
bool flag = State.boss;
int bossNumber = State.bossNumber;
world.completedWaves++;
Status = (flag ? ("Boss " + bossNumber + " defeated! Wave " + world.completedWaves + " complete.") : ("Fishmen invasion defeated! Wave " + world.completedWaves + " complete."));
ApplyState(new EventState
{
completed = world.completedWaves,
roundSignal = State.roundSignal,
thunderSignal = State.thunderSignal
});
active.Clear();
pendingRoundEnemies = 0;
boss = null;
Persist();
Broadcast();
}
}
private void CancelEvent(bool destroyBodies)
{
AttackingFish[] array = (destroyBodies ? spawned : active).ToArray();
foreach (AttackingFish val in array)
{
if ((Object)(object)val != (Object)null && !((NetworkBehaviour)val).IsDeinitializing)
{
((Item)val).DestroyItem((byte)0, byte.MaxValue);
}
}
active.Clear();
pendingRoundEnemies = 0;
if (destroyBodies)
{
spawned.Clear();
}
boss = null;
Status = (wipeEnding ? "The invasion ended when every player fell." : "Fishmen invasions disabled.");
wipeEnding = false;
ApplyState(new EventState
{
completed = ((world != null) ? world.completedWaves : 0),
roundSignal = State.roundSignal,
thunderSignal = State.thunderSignal
});
Persist();
Broadcast();
}
private void ApplyState(EventState next)
{
bool num = !State.active && next.active;
bool flag = State.active && !next.active;
bool flag2 = next.active && (next.thunderSignal != State.thunderSignal || next.roundSignal != State.roundSignal);
State = next;
if (num || flag2)
{
flashStarted = Time.unscaledTime;
EventAudio.Begin(next.boss, playThunder: true);
}
if (flag)
{
EventAudio.End();
}
else if (next.active)
{
EventAudio.SetBoss(next.boss);
}
}
private void ReceiveState(StateMessage message, Channel channel)
{
if (InstanceFinder.IsServerStarted || string.IsNullOrEmpty(message.json) || message.json.Length > 8192)
{
return;
}
try
{
EventState eventState = Codec.FromJson<EventState>(message.json);
if (eventState != null && eventState.protocol == 2)
{
ApplyState(eventState);
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected invasion state: " + ex.Message));
}
}
private void Broadcast()
{
if (InstanceFinder.IsServerStarted)
{
State.eventsEnabled = EventsEnabled;
State.musicEnabled = MusicEnabled;
State.lightningEnabled = LightningEnabled;
State.musicVolume = MusicVolume;
}
if ((Object)(object)manager != (Object)null && InstanceFinder.IsServerStarted)
{
manager.ServerManager.Broadcast<StateMessage>(new StateMessage
{
json = Codec.ToJson(State)
}, true, (Channel)0);
}
}
private void Persist()
{
if (world == null || !InstanceFinder.IsServerStarted)
{
return;
}
try
{
string text = savePath + ".tmp";
File.WriteAllText(text, Codec.ToJson(save));
if (File.Exists(savePath))
{
File.Replace(text, savePath, savePath + ".bak");
}
else
{
File.Move(text, savePath);
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Could not save invasion progress: " + ex.Message));
}
}
public void SaveNow()
{
Persist();
}
private void OnDestroy()
{
Persist();
EventAudio.Destroy();
if (harmony != null)
{
harmony.UnpatchSelf();
}
Instance = null;
}
private Texture2D Solid(Color color)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
Texture2D val = new Texture2D(1, 1);
val.SetPixel(0, 0, color);
val.Apply();
return val;
}
private void Styles()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Expected O, but got Unknown
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Expected O, but got Unknown
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Expected O, but got Unknown
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Expected O, but got Unknown
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: 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_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Expected O, but got Unknown
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
//IL_0201: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Unknown result type (might be due to invalid IL or missing references)
if (titleStyle == null)
{
titleStyle = new GUIStyle(GUI.skin.label)
{
fontSize = 26,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)4
};
titleStyle.normal.textColor = new Color(0.28f, 0.92f, 1f);
headerStyle = new GUIStyle(GUI.skin.label)
{
fontSize = 16,
fontStyle = (FontStyle)1
};
headerStyle.normal.textColor = new Color(1f, 0.68f, 0.18f);
labelStyle = new GUIStyle(GUI.skin.label)
{
fontSize = 14
};
labelStyle.normal.textColor = Color.white;
buttonStyle = new GUIStyle(GUI.skin.button)
{
fontSize = 14,
fontStyle = (FontStyle)1
};
barStyle = new GUIStyle(GUI.skin.label)
{
fontSize = 16,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)4
};
barStyle.normal.textColor = Color.white;
invasionButtonStyle = new GUIStyle(GUI.skin.button)
{
fontSize = 15,
fontStyle = (FontStyle)1
};
invasionButtonStyle.normal.background = Solid(new Color(0.02f, 0.48f, 0.5f, 0.98f));
invasionButtonStyle.hover.background = Solid(new Color(0.04f, 0.64f, 0.65f, 0.98f));
invasionButtonStyle.active.background = Solid(new Color(0.01f, 0.36f, 0.39f, 0.98f));
invasionButtonStyle.normal.textColor = new Color(1f, 0.86f, 0.12f);
invasionButtonStyle.hover.textColor = new Color(1f, 0.94f, 0.28f);
invasionButtonStyle.active.textColor = Color.yellow;
}
}
private void OnGUI()
{
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Expected O, but got Unknown
//IL_00af: 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)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
float realtimeSinceStartup = Time.realtimeSinceStartup;
Styles();
if (optionsOpen)
{
if (((Rect)(ref optionsRect)).width < 1f)
{
optionsRect = new Rect((float)(Screen.width - 720) / 2f, (float)(Screen.height - 705) / 2f, (float)Mathf.Min(720, Screen.width - 40), (float)Mathf.Min(705, Screen.height - 40));
}
GUI.depth = -30000;
optionsRect = GUI.ModalWindow(765421, optionsRect, new WindowFunction(DrawOptionsWindow), "", GUI.skin.window);
RecordGuiTiming(realtimeSinceStartup);
}
else
{
DrawAtmosphere();
DrawEventMeter();
DrawPauseButton();
}
}
private void RecordGuiTiming(float started)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
if ((int)Event.current.type == 7)
{
float num = (Time.realtimeSinceStartup - started) * 1000f;
if (num >= 8f && Time.unscaledTime >= nextGuiTimingLog)
{
nextGuiTimingLog = Time.unscaledTime + 10f;
((BaseUnityPlugin)this).Logger.LogWarning((object)("Fishmen options GUI repaint took " + num.ToString("0.0") + " ms. This diagnostic is throttled to once per 10 seconds."));
}
}
}
private void DrawAtmosphere()
{
//IL_000e: 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_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
if (!State.active)
{
return;
}
Color color = GUI.color;
GUI.depth = 900;
GUI.color = new Color(0.025f, 0.045f, 0.075f, 0.13f);
GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture);
if (EffectiveLightningEnabled)
{
float flashAge = FlashAge;
float num = 0f;
if (flashAge >= 0f && flashAge < 0.18f)
{
num = 0.78f * (1f - flashAge / 0.18f);
}
else if (flashAge > 0.38f && flashAge < 0.55f)
{
num = 0.48f * (1f - (flashAge - 0.38f) / 0.17f);
}
else if (flashAge > 0.78f && flashAge < 0.96f)
{
num = 0.3f * (1f - (flashAge - 0.78f) / 0.18f);
}
if (num > 0f)
{
GUI.color = new Color(0.82f, 0.92f, 1f, num);
GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture);
}
}
GUI.color = color;
GUI.depth = 0;
}
private void DrawEventMeter()
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
//IL_0245: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_01df: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0302: Unknown result type (might be due to invalid IL or missing references)
//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
//IL_031d: Unknown result type (might be due to invalid IL or missing references)
//IL_033b: Unknown result type (might be due to invalid IL or missing references)
//IL_0361: Unknown result type (might be due to invalid IL or missing references)
//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
//IL_040f: Unknown result type (might be due to invalid IL or missing references)
//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
if (!State.active)
{
return;
}
float num = Mathf.Min(720f, (float)Screen.width - 80f);
float num2 = ((float)Screen.width - num) / 2f;
float num3 = 24f;
GUI.Box(new Rect(num2 - 8f, num3 - 6f, num + 16f, (float)(State.boss ? 150 : 106)), GUIContent.none);
GUI.Label(new Rect(num2, num3, num, 24f), "FISHMEN INVASION • WAVE " + State.wave + " • ROUND " + State.round + " / " + State.totalRounds + " • " + State.completed + " COMPLETED", barStyle);
DrawRoster(num2 + num / 2f - 145f, num3 + 25f, FishmanKind.Fishman, State.normalAlive);
DrawRoster(num2 + num / 2f - 35f, num3 + 25f, FishmanKind.Brute, State.bruteAlive);
DrawRoster(num2 + num / 2f + 75f, num3 + 25f, FishmanKind.Leaper, State.leaperAlive);
int num4 = Mathf.Max(1, State.total);
int num5 = Mathf.Clamp(State.alive, 0, num4);
float num6 = 3f;
float num7 = (num - num6 * (float)(num4 - 1)) / (float)num4;
for (int i = 0; i < num4; i++)
{
Color color = GUI.color;
GUI.color = ((i < num5) ? new Color(0.08f, 0.78f, 0.87f) : new Color(0.16f, 0.19f, 0.22f));
GUI.DrawTexture(new Rect(num2 + (float)i * (num7 + num6), num3 + 66f, num7, 20f), (Texture)(object)Texture2D.whiteTexture);
GUI.color = color;
}
GUI.Label(new Rect(num2, num3 + 64f, num, 24f), State.intro ? "INCOMING..." : (num5 + " / " + num4 + " FISHMEN REMAINING"), barStyle);
if (State.boss)
{
float num8 = ((State.bossMaxHp <= 0) ? 0f : Mathf.Clamp01((float)State.bossHp / (float)State.bossMaxHp));
Color color2 = GUI.color;
GUI.color = (State.revenge ? new Color(0.95f, 0.05f, 0.04f) : new Color(0.78f, 0.18f, 0.62f));
GUI.DrawTexture(new Rect(num2, num3 + 108f, num * num8, 24f), (Texture)(object)Texture2D.whiteTexture);
GUI.color = new Color(0.12f, 0.08f, 0.13f);
GUI.DrawTexture(new Rect(num2 + num * num8, num3 + 108f, num * (1f - num8), 24f), (Texture)(object)Texture2D.whiteTexture);
GUI.color = color2;
FishmanKind key = (FishmanKind)Mathf.Clamp(State.bossKind, 3, 6);
if (Assets.Icons.TryGetValue(key, out var value))
{
GUI.DrawTexture(new Rect(num2 + 92f, num3 + 104f, 34f, 34f), (Texture)(object)value, (ScaleMode)2, true);
}
GUI.Label(new Rect(num2 + 8f, num3 + 107f, 82f, 26f), "BOSS " + State.bossNumber, barStyle);
GUI.Label(new Rect(num2, num3 + 107f, num, 26f), State.bossName + " • " + State.bossHp + " / " + State.bossMaxHp, barStyle);
}
}
private void DrawRoster(float x, float y, FishmanKind kind, int count)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
if (Assets.Icons.TryGetValue(kind, out var value))
{
GUI.DrawTexture(new Rect(x, y, 28f, 28f), (Texture)(object)value, (ScaleMode)2, true);
}
GUI.Label(new Rect(x + 30f, y + 2f, 72f, 24f), "x" + count, barStyle);
}
private void DrawPauseButton()
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
if (PauseManager.IsPaused && !optionsOpen)
{
float num = 330f;
GUI.depth = -20000;
if (GUI.Button(new Rect(((float)Screen.width - num) / 2f, 72f, num, 42f), "FISHMEN INVASION OPTIONS", invasionButtonStyle))
{
OpenOptions();
}
}
}
private void OpenOptions()
{
optionsOpen = true;
LoadDrafts();
SetVanillaPauseVisible(visible: false);
}
private void SetVanillaPauseVisible(bool visible)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
try
{
PauseManager val = Object.FindAnyObjectByType<PauseManager>();
if (!((Object)(object)val == (Object)null))
{
GameObject val2 = (GameObject)AccessTools.Field(typeof(PauseManager), "_mainScreen").GetValue(val);
GameObject val3 = (GameObject)AccessTools.Field(typeof(PauseManager), "_optionsScreen").GetValue(val);
if ((Object)(object)val2 != (Object)null)
{
val2.SetActive(visible && !MainMenuManager.IsInMenu);
}
if ((Object)(object)val3 != (Object)null)
{
val3.SetActive(visible && MainMenuManager.IsInMenu);
}
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not toggle the background pause menu: " + ex.Message));
}
}
private void LoadDrafts()
{
amountDraft = AmountMultiplier;
healthDraft = HealthMultiplier;
attackDraft = AttackMultiplier;
frequencyDraft = FrequencyMultiplier;
musicVolumeDraft = MusicVolume;
draftsLoaded = true;
}
private float SliderRow(float x, float y, float width, string name, float value, float min, float max)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: 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)
GUI.Label(new Rect(x, y, 245f, 24f), name + ": " + value.ToString("0.00") + "x", labelStyle);
value = GUI.HorizontalSlider(new Rect(x + 235f, y + 6f, width - 355f, 20f), value, min, max);
if (GUI.Button(new Rect(x + width - 108f, y - 4f, 108f, 30f), "DEFAULT", buttonStyle))
{
value = 1f;
}
return value;
}
private float VolumeRow(float x, float y, float width, float value)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: 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)
GUI.Label(new Rect(x, y, 245f, 24f), "Event music volume: " + Mathf.RoundToInt(value * 100f) + "%", labelStyle);
value = GUI.HorizontalSlider(new Rect(x + 235f, y + 6f, width - 355f, 20f), value, 0f, 1f);
if (GUI.Button(new Rect(x + width - 108f, y - 4f, 108f, 30f), "DEFAULT", buttonStyle))
{
value = 0.7f;
}
return value;
}
private void DrawOptionsWindow(int id)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_033e: Unknown result type (might be due to invalid IL or missing references)
//IL_039b: Unknown result type (might be due to invalid IL or missing references)
//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
//IL_044c: Unknown result type (might be due to invalid IL or missing references)
//IL_0482: Unknown result type (might be due to invalid IL or missing references)
if (!draftsLoaded)
{
LoadDrafts();
}
float width = ((Rect)(ref optionsRect)).width;
Color color = GUI.color;
GUI.color = new Color(0.025f, 0.075f, 0.1f, 0.985f);
GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref optionsRect)).width, ((Rect)(ref optionsRect)).height), (Texture)(object)Texture2D.whiteTexture);
GUI.color = color;
GUI.Label(new Rect(20f, 18f, width - 40f, 38f), "FISHMEN INVASION OPTIONS", titleStyle);
if (GUI.Button(new Rect(width - 48f, 14f, 34f, 30f), "X", buttonStyle))
{
CloseOptions();
return;
}
GUI.Label(new Rect(28f, 62f, width - 56f, 44f), "Only the host can change invasion gameplay, lightning, music, and volume settings for the lobby.", labelStyle);
bool isServerStarted = InstanceFinder.IsServerStarted;
bool enabled = GUI.enabled;
GUI.enabled = isServerStarted;
bool flag = (isServerStarted ? EventsEnabled : State.eventsEnabled);
bool flag2 = GUI.Toggle(new Rect(35f, 118f, 310f, 28f), flag, " Enable Fishmen invasions");
if (isServerStarted && flag2 != EventsEnabled)
{
SetToggle("events", flag2);
}
bool flag3 = (isServerStarted ? LightningEnabled : State.lightningEnabled);
bool flag4 = GUI.Toggle(new Rect(365f, 118f, 160f, 28f), flag3, " Lightning flashes");
if (isServerStarted && flag4 != LightningEnabled)
{
SetToggle("lightning", flag4);
}
bool flag5 = (isServerStarted ? MusicEnabled : State.musicEnabled);
bool flag6 = GUI.Toggle(new Rect(535f, 118f, 145f, 28f), flag5, " Event music");
if (isServerStarted && flag6 != MusicEnabled)
{
SetToggle("music", flag6);
}
GUI.Label(new Rect(30f, 158f, width - 60f, 28f), "HOST INVASION SETTINGS", headerStyle);
amountDraft = SliderRow(35f, 195f, width - 70f, "Fishmen amount per round", amountDraft, 0.5f, 3f);
healthDraft = SliderRow(35f, 245f, width - 70f, "Fishmen health", healthDraft, 0.5f, 3f);
attackDraft = SliderRow(35f, 295f, width - 70f, "Fishmen attack", attackDraft, 0.25f, 2f);
frequencyDraft = SliderRow(35f, 345f, width - 70f, "Invasion frequency", frequencyDraft, 0.5f, 3f);
musicVolumeDraft = VolumeRow(35f, 395f, width - 70f, musicVolumeDraft);
if (GUI.Button(new Rect(35f, 445f, width - 70f, 42f), isServerStarted ? "APPLY AND SAVE HOST SETTINGS" : "HOST CONTROLS ALL EVENT SETTINGS", buttonStyle) && isServerStarted)
{
SaveOptions(amountDraft, healthDraft, attackDraft, frequencyDraft, musicVolumeDraft);
}
if (GUI.Button(new Rect(35f, 497f, width - 70f, 42f), State.active ? "INVASION ALREADY ACTIVE" : "FORCE START WAVE", buttonStyle) && isServerStarted && !State.active)
{
ForceStartEvent();
}
if (GUI.Button(new Rect(35f, 549f, width - 70f, 42f), State.active ? "INVASION ALREADY ACTIVE" : "FORCE RANDOM BOSS EVENT", buttonStyle) && isServerStarted && !State.active)
{
ForceStartBossEvent();
}
GUI.enabled = enabled;
GUI.Label(new Rect(35f, 604f, width - 70f, 64f), isServerStarted ? Status : "These values are controlled by the host and synchronized to every player.", labelStyle);
GUI.DragWindow(new Rect(0f, 0f, width - 55f, 58f));
}
public void CloseOptions()
{
optionsOpen = false;
SetVanillaPauseVisible(visible: true);
}
}
[HarmonyPatch(typeof(GameInfo), "Awake")]
internal static class RegisterFishman
{
private static void Postfix()
{
try
{
FishmanItem.Register();
}
catch (Exception ex)
{
Plugin.Log("Fishman registration deferred: " + ex.Message);
}
}
}
[HarmonyPatch(typeof(Creature), "ServerChangeHp")]
internal static class CountFishDefeated
{
private static void Prefix(Creature __instance, out int __state)
{
__state = ((!((Object)(object)__instance == (Object)null)) ? __instance._hp.Value : 0);
}
private static void Postfix(Creature __instance, int __state)
{
if ((Object)(object)__instance != (Object)null && __state > 0 && __instance._hp.Value <= 0 && (Object)(object)Plugin.Instance != (Object)null)
{
Plugin.Instance.ServerCreatureKilled(__instance);
}
}
}
[HarmonyPatch(typeof(Item), "GetName")]
internal static class FishmanName
{
private static bool Prefix(Item __instance, ref string __result)
{
if (!FishmanItem.Is(__instance))
{
return true;
}
__result = FishmanItem.Name(__instance);
return false;
}
}
[HarmonyPatch(typeof(SaveManager), "SaveServer")]
internal static class SaveInvasion
{
private static void Postfix()
{
if ((Object)(object)Plugin.Instance != (Object)null)
{
Plugin.Instance.SaveNow();
}
}
}
[HarmonyPatch(typeof(PauseManager), "PauseInput")]
internal static class CloseInvasionOptions
{
private static bool Prefix(CallbackContext context)
{
if ((Object)(object)Plugin.Instance == (Object)null || !Plugin.Instance.OptionsOpen)
{
return true;
}
if (((CallbackContext)(ref context)).performed)
{
Plugin.Instance.CloseOptions();
}
return false;
}
}
}