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 System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CommonAPI;
using HarmonyLib;
using MapStation.Common;
using MapStation.Common.Doctor;
using Microsoft.CodeAnalysis;
using ProtoBuf;
using Reptile;
using TombRush.Common;
using TombRush.Common.Dependencies;
using TombRush.Common.Runtime;
using TombRush.Plugin;
using TombRush.Plugin.Dependencies;
using TombRush2023;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("TombRush.Plugin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("BepInEx Plugin Assembly for TombRush.")]
[assembly: AssemblyFileVersion("0.0.0.0")]
[assembly: AssemblyInformationalVersion("0.0.0+f72d2f550b1df8b037608848a3cd4e74232208f5")]
[assembly: AssemblyProduct("TombRush.Plugin")]
[assembly: AssemblyTitle("TombRush.Plugin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 TombRush2023
{
public class CoroutineHelper : MonoBehaviour
{
public int currentZombieAmount;
public int totalSatelliteAmount;
public int currentSatelliteAmount;
public float timeOfFirstSatelliteDestruction;
public void LoadScene()
{
currentZombieAmount = 0;
currentSatelliteAmount = 13;
Log.Debug("Making scene adjustments...");
Transform[] componentsInChildren = Object.Instantiate<GameObject>(TombRushManager.Instance.currentStageAssets.ScriptableObject.satellites).GetComponentsInChildren<Transform>();
foreach (Transform val in componentsInChildren)
{
if (((Object)val).name.Contains("Satellite"))
{
((Component)val).gameObject.AddComponent<Satellite>();
}
}
try
{
Plugin2023.hitSoundObject = Object.Instantiate<GameObject>(Plugin2023.hitSoundPrefab, GameObject.Find("Player_HUMAN0").transform);
Plugin2023.hitSoundSource = Plugin2023.hitSoundObject.GetComponent<AudioSource>();
Plugin2023.hitSoundSource.outputAudioMixerGroup = Core.Instance.AudioManager.mixerGroups[3];
}
catch (Exception)
{
}
}
public void Test()
{
Plugin2023.isKing = true;
((MonoBehaviour)this).StartCoroutine(AddCrown());
}
public IEnumerator AddCrown()
{
yield return (object)new WaitForSeconds(3f);
try
{
if (!Plugin2023.isKing)
{
yield break;
}
bool flag = false;
Transform[] componentsInChildren = GameObject.Find("Player_HUMAN0").GetComponentsInChildren<Transform>();
foreach (Transform val in componentsInChildren)
{
if (!(((Object)val).name == "head"))
{
continue;
}
Transform[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Transform>();
for (int j = 0; j < componentsInChildren2.Length; j++)
{
if (((Object)componentsInChildren2[j]).name.Contains("CrownProp"))
{
flag = true;
}
}
if (!flag)
{
Object.Instantiate<GameObject>(Plugin2023.crown, val.position, GameObject.Find("Player_HUMAN0").transform.rotation, val);
}
}
}
catch (Exception)
{
}
}
public void DecreaseZombieCount(int amount)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
currentZombieAmount -= amount;
if (currentZombieAmount <= 20 && currentSatelliteAmount > 0)
{
TombRushStageScriptableObject scriptableObject = TombRushManager.Instance.currentStageAssets.ScriptableObject;
for (int i = 0; i < scriptableObject.zombieSpawnLocations.Count; i++)
{
Vector3 position = scriptableObject.zombieSpawnLocations[i];
int amount2 = scriptableObject.zombieQuantityPerSpawnLocation[i];
((MonoBehaviour)this).StartCoroutine(SpawnZombies(amount2, position, Plugin2023.characterShader));
}
}
else if (currentZombieAmount <= 0 && currentSatelliteAmount <= 0)
{
Debug.Log((object)"All satellites and zombies defeated! YOU DID ITTTTTT");
Plugin2023.isKing = true;
((MonoBehaviour)this).StartCoroutine(AddCrown());
}
else
{
Debug.Log((object)(currentZombieAmount + " zombies remaining..."));
}
}
public void DecreaseSatelliteCount(int amount)
{
if (currentSatelliteAmount == totalSatelliteAmount)
{
timeOfFirstSatelliteDestruction = Time.time;
}
currentSatelliteAmount -= amount;
StageRecords records = SaveManager.Instance.Stage.Records;
float newAttempt = Time.time - timeOfFirstSatelliteDestruction;
if (currentSatelliteAmount <= 0 && currentZombieAmount > 0)
{
Debug.Log((object)"ALL SATELLITES DESTROYED. Zombies can no longer respawn!");
records.TrySetNewRecordLowerIsBetter(ref records.FastestTimeToDestroyAllSatellites, newAttempt);
}
else if (currentSatelliteAmount <= 0 && currentZombieAmount <= 0)
{
Debug.Log((object)"All satellites and zombies defeated! YOU DID ITTTTTT");
Plugin2023.isKing = true;
SaveManager.Instance.Global.WonCrown = true;
records.TrySetNewRecordLowerIsBetter(ref records.FastestTimeToBeatSatelliteChallenge, newAttempt);
((MonoBehaviour)this).StartCoroutine(AddCrown());
}
else
{
Debug.Log((object)(currentSatelliteAmount + " satellites remaining..."));
}
}
public IEnumerator SpawnZombies(int amount, Vector3 position, Shader characterShader)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
GameObject parent = GameObjectUtility.FindIncludingInactive(TombRushManager.Instance.currentStageAssets.ScriptableObject.zombieSpawnParentPath);
int i = 0;
while (i < amount)
{
GameObject obj = Object.Instantiate<GameObject>(Plugin2023.zombie, position, Quaternion.identity, parent.transform);
ZombieConfig componentInChildren = obj.GetComponentInChildren<ZombieConfig>();
obj.AddComponent<Zombie>();
currentZombieAmount++;
List<SkinnedMeshRenderer> heads = componentInChildren.heads;
int num = Random.Range(0, heads.Count);
for (int j = 0; j < heads.Count; j++)
{
SkinnedMeshRenderer val = heads[j];
if (j != num)
{
Object.Destroy((Object)(object)val);
}
else
{
((Renderer)val).sharedMaterial.shader = characterShader;
}
}
List<SkinnedMeshRenderer> bodies = componentInChildren.bodies;
int num2 = Random.Range(0, bodies.Count);
for (int k = 0; k < bodies.Count; k++)
{
SkinnedMeshRenderer val2 = bodies[k];
if (k != num2)
{
Object.Destroy((Object)(object)val2);
}
else
{
((Renderer)val2).sharedMaterial.shader = characterShader;
}
}
yield return (object)new WaitForSeconds(0.5f);
int num3 = i + 1;
i = num3;
}
}
}
[HarmonyPatch(typeof(Player), "PlayAnim")]
public class DancePatch
{
public static AnimatorOverrideController thrillerOverride;
public static void Postfix(int newAnim, bool forceOverwrite, bool instant, float atTime, ref Player __instance)
{
}
}
public class DestroyOnTimer : MonoBehaviour
{
public float seconds = 5f;
private void Start()
{
Object.Destroy((Object)(object)((Component)this).gameObject, seconds);
}
}
internal class Plugin2023
{
public static Shader characterShader;
public static GameObject hitSoundObject;
public static AudioSource hitSoundSource;
public static bool isKing = false;
private static ManualLogSource Logger = Logger.CreateLogSource("TombRush2023");
public static GameObject zombie => Core.zombie;
public static GameObject explodeEffect => Core.explodeEffect;
public static GameObject crown => Core.crown;
public static GameObject hitSoundPrefab => Core.hitSoundPrefab;
public static List<AudioClip> zombieSounds => Core.zombieSounds;
public static AnimationClip thrillerDance => Core.thrillerDance;
public static TombRushCoreScriptableObject Core => TombRushAssets.Instance.CoreAssets;
public static AssetBundle bundle => TombRushAssets.Instance.CoreBundle;
}
public class Satellite : MonoBehaviour
{
private int health = 2;
private bool dead;
private void Awake()
{
AudioSource component = ((Component)this).GetComponent<AudioSource>();
if ((Object)(object)component != (Object)null)
{
component.outputAudioMixerGroup = Core.Instance.AudioManager.mixerGroups[3];
}
}
private void DoExplodeEffect()
{
//IL_000b: 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_0015: 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)
GameObject obj = Object.Instantiate<GameObject>(Plugin2023.explodeEffect, ((Component)this).transform.position + Vector3.up, ((Component)this).transform.rotation);
obj.AddComponent<DestroyOnTimer>();
AudioSource component = obj.GetComponent<AudioSource>();
component.volume = 1f;
component.outputAudioMixerGroup = Core.Instance.AudioManager.mixerGroups[3];
}
private void OnTriggerEnter(Collider other)
{
if (((Object)other).name == "autoAimCheck")
{
health--;
if (health <= 0 && !dead)
{
dead = true;
Object.FindObjectOfType<CoroutineHelper>().DecreaseSatelliteCount(1);
DoExplodeEffect();
Object.Destroy((Object)(object)((Component)this).gameObject);
}
else
{
DoExplodeEffect();
}
}
}
}
public class Zombie : MonoBehaviour
{
private enum States
{
Normal,
Hit,
Dead
}
private int health = TombRushAssets.Instance.CoreAssets.zombieHealth;
public float InvincibilityTime = TombRushAssets.Instance.CoreAssets.zombieInvincibilityTime;
public Transform targetedPlayer;
private Rigidbody rb;
private float speed;
private Vector3 lookPos;
private Animator animator;
private bool dead;
private bool stopped;
private AudioSource audio;
private States currentState;
private Collider collider;
private float timer;
private float targetTime;
private Vector3 velocityOnPause = Vector3.zero;
private float invincibilityTimer;
private void Start()
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Expected O, but got Unknown
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Expected O, but got Unknown
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Expected O, but got Unknown
ResetTargetTime();
collider = ((Component)this).GetComponent<Collider>();
audio = ((Component)this).GetComponent<AudioSource>();
audio.outputAudioMixerGroup = Core.Instance.AudioManager.mixerGroups[3];
audio.pitch = Random.Range(0.7f, 1.1f);
Core.OnUpdate += new OnUpdateHandler(OnUpdate);
Core.OnFixedUpdate += new OnFixedUpdateHandler(OnFixedUpdate);
Core.OnCoreUpdatePaused += new OnCoreUpdateHandler(OnPause);
Core.OnCoreUpdateUnPaused += new OnCoreUpdateUnpausedHandler(OnUnpause);
}
private void OnDestroy()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
Core.OnUpdate -= new OnUpdateHandler(OnUpdate);
Core.OnFixedUpdate -= new OnFixedUpdateHandler(OnFixedUpdate);
Core.OnCoreUpdatePaused -= new OnCoreUpdateHandler(OnPause);
Core.OnCoreUpdateUnPaused -= new OnCoreUpdateUnpausedHandler(OnUnpause);
}
private void OnEnable()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: 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)
rb = ((Component)this).GetComponent<Rigidbody>();
rb.velocity = Vector3.zero;
speed = Random.Range(0.3f, 1f);
animator = ((Component)this).GetComponent<Animator>();
animator.speed = speed * 2.5f;
lookPos = new Vector3(0f, ((Component)this).transform.position.y, 0f);
}
private void OnPause()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
velocityOnPause = rb.velocity;
rb.isKinematic = true;
animator.speed = 0f;
}
private void OnUnpause()
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
rb.isKinematic = false;
animator.speed = 1f;
rb.velocity = velocityOnPause;
}
private bool PlayerBusy()
{
Player currentPlayer = WorldHandler.instance.GetCurrentPlayer();
if (currentPlayer.IsBusyWithSequence())
{
return true;
}
if (currentPlayer.ability is CharacterSelectAbility)
{
return true;
}
return false;
}
private void OnUpdate()
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
if (PlayerBusy())
{
return;
}
invincibilityTimer -= Core.dt;
currentState = States.Normal;
if (dead)
{
currentState = States.Dead;
}
if (animator.GetCurrentStateName(0) == "Hit")
{
currentState = States.Hit;
}
UpdateTimer();
if ((Object)(object)targetedPlayer != (Object)null)
{
if (!dead && !stopped)
{
Vector3 val = default(Vector3);
((Vector3)(ref val))..ctor(targetedPlayer.position.x, ((Component)this).transform.position.y, targetedPlayer.position.z);
lookPos = Vector3.MoveTowards(lookPos, val, 10f);
((Component)this).transform.LookAt(lookPos);
}
}
else
{
targetedPlayer = ((Component)WorldHandler.instance.GetCurrentPlayer()).transform;
}
}
private void OnFixedUpdate()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: 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_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
if (!PlayerBusy() && !dead && !stopped)
{
Vector3 val = rb.position + ((Component)this).transform.forward * Time.deltaTime * speed;
rb.MovePosition(val);
if ((double)val.y < -200.0)
{
Object.FindObjectOfType<CoroutineHelper>().DecreaseZombieCount(1);
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
private void Die()
{
Physics.IgnoreCollision(collider, ((Component)WorldHandler.instance.GetCurrentPlayer()).GetComponent<Collider>());
animator.SetBool("Dead", true);
animator.Play("Death");
dead = true;
if (Random.Range(0, 10) > 7)
{
int index = Random.Range(0, Plugin2023.zombieSounds.Count);
audio.clip = Plugin2023.zombieSounds[index];
audio.Play();
}
timer = 0f;
}
private void OnCollisionEnter(Collision collision)
{
//IL_002c: 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_0058: 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)
if (collision.gameObject.layer != 21)
{
return;
}
Junk component = collision.gameObject.GetComponent<Junk>();
if (!((Object)(object)component == (Object)null))
{
Vector3 velocity = component.rigidBody.velocity;
if (((Vector3)(ref velocity)).magnitude >= 6f && !component.rigidBody.isKinematic)
{
Core.Instance.AudioManager.PlaySfxGameplay(component.audioClips, WorldHandler.instance.GetSpatialAudioSource(((Component)component).transform.position), 0f);
Die();
}
}
}
private void OnTriggerEnter(Collider other)
{
//IL_0088: 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_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
if (invincibilityTimer > 0f || currentState == States.Dead || ((Component)other).gameObject.layer != 18 || (Object)(object)((Component)other).GetComponentInParent<Player>() != (Object)(object)WorldHandler.instance.GetCurrentPlayer())
{
return;
}
if ((Object)(object)Plugin2023.hitSoundSource != (Object)null && !Plugin2023.hitSoundSource.isPlaying)
{
Plugin2023.hitSoundSource.pitch = Random.Range(0.7f, 1.2f);
Plugin2023.hitSoundSource.Play();
}
rb.AddForce((((Component)this).transform.up + -((Component)this).transform.forward) * 5f, (ForceMode)1);
health--;
if (health <= 0 && !dead)
{
Die();
}
else if (!dead)
{
invincibilityTimer = InvincibilityTime;
animator.Play("Hurt", 0, 0f);
if (Random.Range(0, 10) > 7)
{
int index = Random.Range(0, Plugin2023.zombieSounds.Count);
audio.clip = Plugin2023.zombieSounds[index];
audio.Play();
}
}
}
private void ResetTargetTime()
{
targetTime = Random.Range(3f, 10f);
}
private void UpdateTimer()
{
//IL_00f4: 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_01ac: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: 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)
if (currentState == States.Hit)
{
return;
}
timer += Core.dt;
if (currentState == States.Dead)
{
if (timer >= 3f)
{
Object.FindObjectOfType<CoroutineHelper>().DecreaseZombieCount(1);
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
else
{
if (!(timer >= targetTime))
{
return;
}
timer = 0f;
stopped = false;
ResetTargetTime();
if (Random.Range(0, 10) >= 7)
{
if (!dead)
{
if (Random.Range(0, 10) > 7)
{
int index = Random.Range(0, Plugin2023.zombieSounds.Count);
audio.clip = Plugin2023.zombieSounds[index];
audio.Play();
}
animator.Play("Idle");
stopped = true;
}
}
else
{
if (!((Object)(object)targetedPlayer != (Object)null))
{
return;
}
if ((double)Vector3.Distance(((Component)this).transform.position, ((Component)targetedPlayer).transform.position) <= 2.0)
{
if (!dead)
{
animator.Play("Hit");
((Component)targetedPlayer).GetComponent<Player>().GetHit(1, -((Component)this).transform.forward, (KnockbackType)3);
if (Random.Range(0, 10) > 5)
{
int index2 = Random.Range(0, Plugin2023.zombieSounds.Count);
audio.clip = Plugin2023.zombieSounds[index2];
audio.Play();
}
}
}
else if (Random.Range(0, 10) > 5)
{
rb.AddForce((((Component)this).transform.up + ((Component)this).transform.forward) * 5f, (ForceMode)1);
}
}
}
}
}
}
namespace TombRush.Plugin
{
public class LocalProgress
{
private const byte Version = 4;
private string savePath;
public LocalProgress()
{
InitializeNew();
}
public void InitializeNew()
{
savePath = Path.Combine(Paths.ConfigPath, "TombRush/localprogress.mwp");
}
public void Save()
{
using MemoryStream memoryStream = new MemoryStream();
using (BinaryWriter writer = new BinaryWriter(memoryStream))
{
Write(writer);
}
CustomStorage.Instance.WriteFile(memoryStream.ToArray(), savePath);
}
public void Load()
{
if (!File.Exists(savePath))
{
Debug.Log((object)"No TombRush save to load, starting a new game.");
return;
}
using FileStream input = File.Open(savePath, FileMode.Open);
using BinaryReader reader = new BinaryReader(input);
try
{
Read(reader);
}
catch (Exception arg)
{
Debug.LogError((object)$"Failed to load TombRush save!{Environment.NewLine}{arg}");
}
}
private void Write(BinaryWriter writer)
{
writer.Write((byte)4);
}
private void Read(BinaryReader reader)
{
byte b = reader.ReadByte();
if (b > 4)
{
Debug.LogError((object)$"Attemped to read a TombRush save that's too new (version {b}), current version is {(byte)4}.");
}
else
{
reader.ReadString();
}
}
}
[BepInPlugin("TombRush.Plugin", "TombRush.Plugin", "0.0.0")]
public class Plugin : BaseUnityPlugin
{
public delegate void UpdateDelegate();
public static Plugin Instance;
private static Type ForceLoadTombRushCommonAssembly = typeof(AssemblyDependencies);
private static Type ForceLoadTombRushPluginAssembly = typeof(AssemblyDependencies);
public bool ConflictingMovementModsInstalled;
public static UpdateDelegate UpdateEvent;
public static UpdateDelegate LateUpdateEvent;
public Plugin()
{
Log.Logger = ((BaseUnityPlugin)this).Logger;
}
private void Awake()
{
Instance = this;
try
{
Initialize();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin TombRush.Plugin 0.0.0 is loaded!");
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)string.Format("Plugin {0} {1} failed to load!{2}{3}", "TombRush.Plugin", "0.0.0", Environment.NewLine, ex));
}
}
private void Initialize()
{
//IL_0021: 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_009b: Expected O, but got Unknown
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Expected O, but got Unknown
new TombRushConfig(((BaseUnityPlugin)this).Config);
string? directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
new Harmony("TombRush.Plugin").PatchAll();
new TombRushAssets(directoryName);
new SaveManager();
bool conflictingMovementModsInstalled = Chainloader.PluginInfos.Keys.Any((string x) => x == "com.yuril.MovementPlus");
ConflictingMovementModsInstalled = conflictingMovementModsInstalled;
if (ConflictingMovementModsInstalled)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Disabled movement effects because conflicting movement mods are enabled.");
}
StageAPI.OnStagePreInitialization = (StageInitializationDelegate)Delegate.Combine((Delegate?)(object)StageAPI.OnStagePreInitialization, (Delegate?)new StageInitializationDelegate(StageAPI_OnStagePreInitialization));
}
private void StageAPI_OnStagePreInitialization(Stage newStage, Stage previousStage)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
TombRushManager.Create().SetupStage(newStage);
}
private void Update()
{
UpdateEvent?.Invoke();
}
private void LateUpdate()
{
LateUpdateEvent?.Invoke();
}
}
public class SaveManager
{
private readonly GlobalSaveFile globalSaveFile;
public static SaveManager Instance { get; private set; }
public GlobalSaveData Global => globalSaveFile.Data;
public StageSaveData Stage => GetStage(Utility.GetCurrentStage());
public StageSaveData GetStage(Stage stage)
{
//IL_0012: 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_002c: Unknown result type (might be due to invalid IL or missing references)
Dictionary<Stage, StageSaveData> stages = globalSaveFile.Data.Stages;
if (stages.TryGetValue(stage, out var value))
{
return value;
}
value = new StageSaveData();
value.Stage = stage;
stages.Add(stage, value);
return value;
}
public SaveManager()
{
if (Instance != null)
{
throw new InvalidOperationException("There is already an instance of SaveManager.");
}
Instance = this;
globalSaveFile = new GlobalSaveFile();
SaveAPI.RegisterCustomSaveData((CustomSaveData)(object)globalSaveFile);
}
}
public abstract class SaveData<T> : CustomSaveData
{
public T Data { get; protected set; }
protected SaveData(string filename)
: base("TombRush2024", filename)
{
}
public override void Read(BinaryReader reader)
{
try
{
Data = Serializer.Deserialize<T>(reader.BaseStream);
}
catch (Exception)
{
base.FailedToLoad = true;
}
}
public override void Write(BinaryWriter writer)
{
Serializer.Serialize<T>(writer.BaseStream, Data);
}
}
public class GlobalSaveFile : SaveData<GlobalSaveData>
{
public GlobalSaveFile()
: base("slot{0}_globalprogress.trp")
{
}
public override void Initialize()
{
base.Data = new GlobalSaveData();
}
}
[ProtoContract]
public class GlobalSaveData
{
[ProtoMember(1)]
public bool SugarRushExplained;
[ProtoMember(2)]
public bool ZombiesEnabled = true;
[ProtoMember(3)]
public bool WonCrown;
[ProtoMember(4)]
public GlobalRecords Records = new GlobalRecords();
[ProtoMember(5)]
public readonly Dictionary<Stage, StageSaveData> Stages = new Dictionary<Stage, StageSaveData>();
}
[ProtoContract]
public class GlobalRecords
{
[ProtoMember(1)]
public int TotalPedestriansScared;
[ProtoMember(2)]
public float TotalCandyCollected;
}
[ProtoContract]
public class StageSaveData
{
[ProtoMember(2)]
public Stage Stage;
[ProtoMember(1)]
public StageRecords Records = new StageRecords();
}
[ProtoContract]
public class StageRecords
{
[ProtoMember(1)]
public float FastestTimeTo50PedestriansInSingleCombo = -1f;
[ProtoMember(2)]
public float FastestTimeTo100PedestriansInSingleCombo = -1f;
[ProtoMember(3)]
public float FastestTimeTo200PedestriansInSingleCombo = -1f;
[ProtoMember(4)]
public int MaxPedestriansInSingleCombo = -1;
[ProtoMember(5)]
public float MaxTimeWith100PercentRush = -1f;
[ProtoMember(6)]
public float FastestTimeTo50TrickCombo = -1f;
[ProtoMember(7)]
public float FastestTimeTo100TrickCombo = -1f;
[ProtoMember(8)]
public float FastestTimeTo200TrickCombo = -1f;
[ProtoMember(9)]
public float FastestTimeToDestroyAllSatellites = -1f;
[ProtoMember(10)]
public float FastestTimeToBeatSatelliteChallenge = -1f;
[ProtoMember(11)]
public int TotalPedestriansScaredThisStage;
[ProtoMember(12)]
public float TotalCandyCollectedThisStage;
public bool TrySetNewRecordLowerIsBetter(ref float record, float newAttempt)
{
if (record < 0f)
{
record = newAttempt;
return true;
}
if (newAttempt < record)
{
record = newAttempt;
return true;
}
return false;
}
public bool TrySetNewRecordHigherIsBetter(ref int record, int newAttempt)
{
if (record < 0)
{
record = newAttempt;
return true;
}
if (newAttempt > record)
{
record = newAttempt;
return true;
}
return false;
}
public bool TrySetNewRecordHigherIsBetter(ref float record, float newAttempt)
{
if (record < 0f)
{
record = newAttempt;
return true;
}
if (newAttempt > record)
{
record = newAttempt;
return true;
}
return false;
}
}
public class SugarRushManager : MonoBehaviour
{
private TombRushPedestrian[] pedestrians;
private HashSet<TombRushPedestrian> pedestriansWithCandy = new HashSet<TombRushPedestrian>();
private List<TombRushPedestrian> pedestriansWithoutCandy = new List<TombRushPedestrian>();
private Coroutine sugarRushExplainerCoroutine;
private bool SugarExplaining;
public static SugarRushManager Instance { get; private set; }
public bool SugarExplained
{
get
{
return SaveManager.Instance.Global.SugarRushExplained;
}
set
{
SaveManager.Instance.Global.SugarRushExplained = value;
}
}
public void Awake()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Invalid comparison between Unknown and I4
//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)
Instance = this;
List<TombRushPedestrian> list = new List<TombRushPedestrian>();
if ((int)Utility.GetCurrentStage() == 4 || SugarExplained)
{
Scene activeScene = SceneManager.GetActiveScene();
GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
for (int i = 0; i < rootGameObjects.Length; i++)
{
Pedestrian[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Pedestrian>(true);
foreach (Pedestrian val in componentsInChildren)
{
list.Add(((Component)val).gameObject.AddComponent<TombRushPedestrian>());
}
}
}
pedestrians = list.ToArray();
foreach (TombRushPedestrian item in list)
{
pedestriansWithCandy.Add(item);
}
sugarRushExplainerCoroutine = ((MonoBehaviour)this).StartCoroutine(RespawnCandyCoroutine());
}
public void TombRushInitialize()
{
TombRushUI.Instance.SugarRushHUD.MeterVisible = SugarExplained;
}
public void OnDestroy()
{
if (sugarRushExplainerCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(sugarRushExplainerCoroutine);
}
}
public bool CanExplainSugarRush(TombRushPedestrian pedestrian)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Invalid comparison between Unknown and I4
if (!SugarExplaining)
{
return (int)Utility.GetCurrentStage() == 4;
}
return false;
}
public Coroutine ExplainSugarRush(TombRushPedestrian pedestrian)
{
return ((MonoBehaviour)this).StartCoroutine(ExplainSugarRushCoroutine(pedestrian));
}
private IEnumerator ExplainSugarRushCoroutine(TombRushPedestrian pedestrian)
{
SugarExplaining = true;
Debug.Log((object)"This where we trigger candy explainer cutscene");
yield return (object)new WaitForSeconds(0.2f);
SugarRushExplainerCutscene componentInSceneIncludingInactive = GameObjectUtility.GetComponentInSceneIncludingInactive<SugarRushExplainerCutscene>();
if ((Object)(object)componentInSceneIncludingInactive == (Object)null)
{
Debug.LogError((object)"No SugarRushExplainerCutscene found in scene. We should add it to SceneDeco");
}
else
{
((Component)componentInSceneIncludingInactive).gameObject.SetActive(true);
((Component)componentInSceneIncludingInactive).transform.position = ((Component)pedestrian).transform.position;
((Component)componentInSceneIncludingInactive).transform.rotation = ((Component)pedestrian).transform.rotation;
}
SugarExplained = true;
TombRushUI.Instance.SugarRushHUD.MeterVisible = true;
}
private IEnumerator RespawnCandyCoroutine()
{
while (true)
{
yield return (object)new WaitForSeconds(1f / TombRushAssets.Instance.CoreAssets.ThisManyPedestriansPerSecondRegainCandy);
Player currentPlayer = WorldHandler.instance.GetCurrentPlayer();
if ((Object)(object)currentPlayer == (Object)null || PlayerIsComboing())
{
continue;
}
foreach (TombRushPedestrian item in pedestriansWithoutCandy)
{
if (Vector3.Distance(((Component)currentPlayer).transform.position, ((Component)item).transform.position) > TombRushAssets.Instance.CoreAssets.PedestriansRegainCandyWhenThisFarFromPlayer)
{
item.ResetCandy();
break;
}
}
}
}
private bool PlayerIsComboing()
{
Player currentPlayer = WorldHandler.instance.GetCurrentPlayer();
if ((Object)(object)currentPlayer == (Object)null)
{
return false;
}
if (!currentPlayer.IsComboing())
{
return currentPlayer.ability is AirTrickAbility;
}
return true;
}
public void NotifyPedestrianHasCandy(TombRushPedestrian pedestrian, bool hasCandy)
{
if (hasCandy)
{
pedestriansWithCandy.Add(pedestrian);
pedestriansWithoutCandy.Remove(pedestrian);
}
else
{
pedestriansWithCandy.Remove(pedestrian);
pedestriansWithoutCandy.Add(pedestrian);
}
}
}
public class TombRushAssets
{
private readonly Dictionary<string, TombRushStageAssets> assetsByStageName;
public AssetBundle CoreBundle;
public TombRushCoreScriptableObject CoreAssets;
private string folder;
public static TombRushAssets Instance { get; private set; }
public TombRushAssets(string folder)
{
Instance = this;
assetsByStageName = new Dictionary<string, TombRushStageAssets>();
this.folder = folder;
LoadBundles();
}
private void LoadBundles()
{
string text = Path.Combine(folder, AssetConstants.CoreBundleFilename);
CoreBundle = AssetBundle.LoadFromFile(text);
CoreAssets = CoreBundle.LoadAsset<TombRushCoreScriptableObject>("Assets/core/TombRushCoreAssets.asset");
foreach (string stage in CoreAssets.stages)
{
AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(folder, AssetConstants.GetStageBundleFilename(stage)));
TombRushStageScriptableObject val2 = val.LoadAsset<TombRushStageScriptableObject>(AssetConstants.GetStageAssetsScriptableObjectPath(stage));
Debug.Log((object)$"Found bundle {val} for stage {stage}");
Debug.Log((object)("Found scriptable object " + (object)val2));
assetsByStageName[stage] = new TombRushStageAssets
{
Bundle = val,
ScriptableObject = val2
};
}
}
public TombRushStageAssets GetAssetsForStage(Stage stage)
{
string key = ((object)(Stage)(ref stage)).ToString().ToLowerInvariant();
assetsByStageName.TryGetValue(key, out var value);
return value;
}
public GameObject GetPrefabForStage(Stage stage)
{
string key = ((object)(Stage)(ref stage)).ToString().ToLowerInvariant();
if (!assetsByStageName.TryGetValue(key, out var value))
{
return null;
}
return value.ScriptableObject.stageAdditionsPrefab;
}
public void ReloadBundles()
{
UnloadBundles();
LoadBundles();
}
private void UnloadBundles()
{
AssetBundle coreBundle = CoreBundle;
if (coreBundle != null)
{
coreBundle.Unload(false);
}
CoreBundle = null;
foreach (KeyValuePair<string, TombRushStageAssets> item in assetsByStageName)
{
item.Value.Bundle.Unload(false);
}
assetsByStageName.Clear();
}
}
public class TombRushStageAssets
{
public AssetBundle Bundle;
public TombRushStageScriptableObject ScriptableObject;
}
public class TombRushConfig
{
public ConfigEntry<bool> ThisIsAConfigFlag;
public static TombRushConfig Instance { get; private set; }
public bool ThisIsAConfigFlagValue => ThisIsAConfigFlag.Value;
public TombRushConfig()
{
Instance = this;
}
public TombRushConfig(ConfigFile file)
: this()
{
string text = "General";
ThisIsAConfigFlag = file.Bind<bool>(text, "ThisIsAFlag", false, "Enable emotive Tryce mode.");
}
}
public class TombRushManager : MonoBehaviour
{
public GameObject stageAdditions;
public static TombRushManager Instance { get; private set; }
public Stage currentStage { get; private set; }
public TombRushStageAssets currentStageAssets => TombRushAssets.Instance.GetAssetsForStage(currentStage);
public static TombRushManager Create()
{
//IL_0005: 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)
GameObject val = new GameObject("TombRush Manager");
TombRushManager result = val.AddComponent<TombRushManager>();
val.AddComponent<SugarRushManager>();
return result;
}
public void SetupStage(Stage stage)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
currentStage = stage;
GameObject prefabForStage = TombRushAssets.Instance.GetPrefabForStage(stage);
if (!((Object)(object)prefabForStage == (Object)null))
{
stageAdditions = Object.Instantiate<GameObject>(prefabForStage);
SugarRushExplainerCutscene componentInChildren = stageAdditions.GetComponentInChildren<SugarRushExplainerCutscene>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
((Component)componentInChildren).gameObject.SetActive(true);
}
StageObject[] componentsInChildren = stageAdditions.GetComponentsInChildren<StageObject>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].PutInChunk();
}
}
}
private void SetupUI()
{
GameObject tombRushUIPrefab = TombRushAssets.Instance.CoreAssets.tombRushUIPrefab;
if (!((Object)(object)tombRushUIPrefab == (Object)null))
{
GameObject obj = Object.Instantiate<GameObject>(tombRushUIPrefab);
Transform val = ((Component)Core.Instance.UIManager).transform.Find("GamePlayUI(Clone)").Find("GameplayUI").Find("gameplayUIScreen");
obj.transform.SetParent(val, false);
}
}
private void Awake()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
Instance = this;
LightmapSettings.lightmaps = (LightmapData[])(object)new LightmapData[0];
QualitySettings.shadowDistance = 150f;
StageManager.OnStagePostInitialization += new OnStageInitializedDelegate(StageManager_OnStagePostInitialization);
}
private void OnDestroy()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
Instance = null;
StageManager.OnStagePostInitialization -= new OnStageInitializedDelegate(StageManager_OnStagePostInitialization);
}
private void StageManager_OnStagePostInitialization()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Invalid comparison between Unknown and I4
SetupUI();
if ((int)Utility.GetCurrentStage() == 4)
{
SetupTombRush();
}
SugarRushManager.Instance.TombRushInitialize();
}
private void SetupTombRush()
{
//IL_0005: 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)
//IL_008e: 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)
CoroutineHelper coroutineHelper = new GameObject("SceneController").AddComponent<CoroutineHelper>();
coroutineHelper.LoadScene();
Plugin2023.characterShader = ((Renderer)GameObject.Find("meshLank1").GetComponent<SkinnedMeshRenderer>()).sharedMaterial.shader;
Vector3 position = default(Vector3);
((Vector3)(ref position))..ctor(327.7377f, -1.6446f, -80.3011f);
Vector3 position2 = default(Vector3);
((Vector3)(ref position2))..ctor(280.0308f, -5.4126f, -2.5014f);
Vector3 position3 = default(Vector3);
((Vector3)(ref position3))..ctor(373.2899f, -8.8528f, -41.7996f);
((MonoBehaviour)coroutineHelper).StartCoroutine(coroutineHelper.SpawnZombies(20, position, Plugin2023.characterShader));
((MonoBehaviour)coroutineHelper).StartCoroutine(coroutineHelper.SpawnZombies(40, position2, Plugin2023.characterShader));
((MonoBehaviour)coroutineHelper).StartCoroutine(coroutineHelper.SpawnZombies(30, position3, Plugin2023.characterShader));
ChangeSkybox();
AddPrefabs();
((Component)((Component)Object.FindObjectOfType<AmbientManager>(true)).transform.Find("SunSprite")).gameObject.SetActive(false);
}
private void AddPrefabs()
{
Texture2D[] array = Plugin2023.bundle.LoadAllAssets<Texture2D>();
MeshRenderer[] componentsInChildren = GameObjectUtility.FindIncludingInactive("stageChunks/openHill").GetComponentsInChildren<MeshRenderer>(true);
int num = 0;
MeshRenderer[] array2 = componentsInChildren;
foreach (MeshRenderer val in array2)
{
if (!((Object)((Component)val).gameObject).name.Contains("CombinedMeshes"))
{
continue;
}
Texture mainTexture = ((Renderer)val).sharedMaterial.mainTexture;
Texture2D[] array3 = array;
foreach (Texture2D val2 in array3)
{
if (((Object)val2).name.Contains(((Object)mainTexture).name))
{
((Renderer)val).sharedMaterial.SetTexture("_MainTex", (Texture)(object)val2);
_ = ((Renderer)val).sharedMaterial.shader;
num++;
}
}
}
}
private void ChangeSkybox()
{
RenderSettings.skybox = TombRushAssets.Instance.CoreAssets.skybox;
}
}
public class TombRushPedestrian : MonoBehaviour
{
[SerializeField]
private GameObject candyBag;
[SerializeField]
private GameObject mask;
[SerializeField]
private GameObject particleEffectGo;
private ParticleSystem particleEffect;
private Pedestrian pedestrian;
private Transform head;
private Transform handl;
public bool HasCandy { get; private set; } = true;
private void Awake()
{
pedestrian = ((Component)this).GetComponent<Pedestrian>();
TombRushPedestrianAdditions pedestrianAdditions = TombRushAssets.Instance.CoreAssets.pedestrianAdditions;
string text = pedestrianAdditions.AttachMaskTo[Random.Range(0, pedestrianAdditions.AttachMaskTo.Length)];
string text2 = pedestrianAdditions.AttachCandyBagTo[Random.Range(0, pedestrianAdditions.AttachCandyBagTo.Length)];
head = ((Component)pedestrian).transform.Find(text);
if ((Object)(object)head == (Object)null)
{
Debug.LogError((object)"Pedestrian has no head!");
}
handl = ((Component)pedestrian).transform.Find(text2);
if ((Object)(object)handl == (Object)null)
{
Debug.LogError((object)"Pedestrian has no hand!");
}
mask = Object.Instantiate<GameObject>(RandomUtility.Choose<GameObject>(TombRushAssets.Instance.CoreAssets.pedestrianAdditions.Masks));
candyBag = Object.Instantiate<GameObject>(RandomUtility.Choose<GameObject>(TombRushAssets.Instance.CoreAssets.pedestrianAdditions.CandyBags));
mask.transform.SetParent(head, false);
candyBag.transform.SetParent(handl, false);
SpawnParticleEffect();
}
private void SpawnParticleEffect()
{
particleEffectGo = Object.Instantiate<GameObject>(RandomUtility.Choose<GameObject>(TombRushAssets.Instance.CoreAssets.pedestrianAdditions.ParticleEffects));
particleEffectGo.SetActive(false);
particleEffectGo.transform.SetParent(((Component)pedestrian).transform, false);
particleEffect = particleEffectGo.GetComponent<ParticleSystem>();
}
public void AnimateGiveCandy()
{
HasCandy = false;
candyBag.SetActive(false);
mask.SetActive(false);
particleEffectGo.SetActive(true);
((Component)particleEffect).GetComponent<ParticleSystem>().Play();
SugarRushManager.Instance.NotifyPedestrianHasCandy(this, hasCandy: false);
}
public void ResetCandy()
{
HasCandy = true;
candyBag.SetActive(true);
mask.SetActive(true);
SpawnParticleEffect();
SugarRushManager.Instance.NotifyPedestrianHasCandy(this, hasCandy: true);
}
}
public class TombRushPlayer : MonoBehaviour
{
[HarmonyPatch]
internal static class Patches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(Player), "Init")]
private static void Init_Postfix(Player __instance)
{
if (PlayerIsLocal(__instance))
{
((Component)__instance).gameObject.AddComponent<TombRushPlayer>().player = __instance;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(StreetLifeBehaviour), "Move")]
private static void Move_Prefix(StreetLifeBehaviour __instance, StreetLifeCluster cluster, StreetLife life, ref StreetLifeHot streetLifeHot, Transform otherTransform)
{
TombRushPlayer component = ((Component)otherTransform.parent.parent).GetComponent<TombRushPlayer>();
if ((Object)(object)component != (Object)null)
{
component.OnPedestrianDodge(life);
Log.Debug("Pedestrian dodged player: " + Doctor.GetGameObjectPath(((Component)life).gameObject));
}
}
}
public class TombRushPlayerDebugMenu : DebugMenu
{
private readonly TombRushPlayer player;
public override string Name => "TombRush Player";
public TombRushPlayerDebugMenu(TombRushPlayer player)
{
this.player = player;
}
public override void OnGUI()
{
GUILayout.Label("Status", Array.Empty<GUILayoutOption>());
GUILayout.Label($"Sugar Rush: {player.sugarRush:F2}", Array.Empty<GUILayoutOption>());
GUILayout.HorizontalSlider(player.sugarRush, 0f, player.s.MaxRushMeter, Array.Empty<GUILayoutOption>());
GUILayout.Label($"Sugar Rush Visual: {player.sugarRushVisual:F2}", Array.Empty<GUILayoutOption>());
GUILayout.HorizontalSlider(player.sugarRushVisual, 0f, player.s.MaxRushMeter, Array.Empty<GUILayoutOption>());
GUILayout.Label($"Sugar Rush Hold Time Remaining: {player.sugarRushHoldTimeRemaining:F2}", Array.Empty<GUILayoutOption>());
GUILayout.HorizontalSlider(player.sugarRushHoldTimeRemaining, 0f, player.s.RushHoldDuration, Array.Empty<GUILayoutOption>());
GUILayout.Space(15f);
player.useOverriddenFixedRush = GUILayout.Toggle(player.useOverriddenFixedRush, "Override with Locked Rush Amount", Array.Empty<GUILayoutOption>());
EditFloat("Locked Rush Amount", ref player.overriddenFixedSugarRush, player.s.MaxRushMeter);
GUILayout.Space(15f);
GUILayout.Label("Tweak", Array.Empty<GUILayoutOption>());
GUILayout.Label("Meter can exceed effect, but your animation boost is capped at 'effect' value", Array.Empty<GUILayoutOption>());
EditFloat("Max Rush Meter", ref player.s.MaxRushMeter, 5f);
EditFloat("Max Rush Effect", ref player.s.MaxRushEffect, 5f);
EditFloat("Rush Hold Duration (delay until decay starts)", ref player.s.RushHoldDuration, 5f);
EditFloat("Decay Rate", ref player.s.RushDecayRate, 5f);
EditFloat("Visual Change Rate", ref player.s.RushVisualChangeRate, 5f);
EditFloat("Pedestrian Grants", ref player.s.PedestrianGrantsRush, 5f);
EditFloat("CandyCorn Grants", ref player.s.CandycornGrantsRush, 5f);
EditFloat("Animation Speed Multiplier", ref player.s.AnimationSpeedMultiplier, 5f);
EditFloat("Movement Speed Multiplier", ref player.s.MovementSpeedMultiplier, 5f);
EditFloat("Max Base Run Speed Increase", ref player.s.MaxBaseRunSpeedIncrease, 5f);
static void EditFloat(string label, ref float value, float max)
{
GUILayout.Label($"{label}: {value:F2}", Array.Empty<GUILayoutOption>());
string text = GUILayout.TextField(value.ToString(), Array.Empty<GUILayoutOption>());
if (text != value.ToString() && float.TryParse(text, out var result))
{
value = result;
}
value = GUILayout.HorizontalSlider(value, 0f, max, Array.Empty<GUILayoutOption>());
}
}
}
[NonSerialized]
private Player player;
private Animator animator;
private float sugarRush;
private bool useOverriddenFixedRush;
private float overriddenFixedSugarRush = 1f;
private float sugarRushVisual;
private float sugarRushHoldTimeRemaining;
private bool isAt100PercentRush;
private float timeSpentAt100PercentRush;
private readonly SugarRushStats s = TombRushAssets.Instance.CoreAssets.SugarRushStats;
private TombRushPlayerDebugMenu debugMenu;
private bool gotBaseSpeeds;
private float baseGrindSpeed;
private float baseAirDashSpeed;
private float baseBoostSpeed;
private float baseWallRunMoveSpeed;
private float baseVertAbilitySpeed;
private float baseSlideAbilitySpeed;
private float baseRunSpeedModifier;
private float baseVertBottomExitSpeed;
private float baseVertMaxSpeed;
private float baseVertTopJumpSpeed;
private static bool gotStaticBaseSpeeds;
private static float bmxGrindSpeed;
private static float bmxRunSpeed;
private static float skateboardGrindSpeed;
private static float skateboardRunSpeed;
private static float inlineGrindSpeed;
private static float inlineRunSpeed;
public bool Local => PlayerIsLocal(player);
private float useThisSugarRush
{
get
{
if (!useOverriddenFixedRush)
{
return sugarRush;
}
return overriddenFixedSugarRush;
}
}
private float effectiveSugarRush
{
get
{
float num = useThisSugarRush;
if (!(num > 0.8f))
{
if (!(num > 0.6f))
{
if (!(num > 0.4f))
{
if (num > 0.2f)
{
return 0.25f;
}
return 0f;
}
return 0.5f;
}
return 0.75f;
}
return 1f;
}
}
private static bool PlayerIsLocal(Player player)
{
return (Object)(object)player == (Object)(object)WorldHandler.instance.GetCurrentPlayer();
}
public static TombRushPlayer Get(Player player)
{
return ((Component)player).GetComponent<TombRushPlayer>();
}
private void Awake()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
TryGrabAnimator();
Core.OnFixedUpdate += new OnFixedUpdateHandler(OnFixedUpdate);
Core.OnUpdate += new OnUpdateHandler(OnUpdate);
}
private void Start()
{
GetBaseAbilitySpeeds();
}
private void OnDestroy()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
Core.OnFixedUpdate -= new OnFixedUpdateHandler(OnFixedUpdate);
Core.OnUpdate -= new OnUpdateHandler(OnUpdate);
}
private void OnUpdate()
{
UpdateSugarMeter();
SetAnimatorSpeedBasedOnSugarLevels();
SetAbilitySpeedsBasedOnSugarLevels();
UpdateSugarHUD();
TrackSugarStats();
}
private void OnFixedUpdate()
{
}
private void UpdateSugarMeter()
{
if (sugarRush > 0f)
{
if (sugarRushHoldTimeRemaining > 0f)
{
sugarRushHoldTimeRemaining -= Time.deltaTime;
if (sugarRushHoldTimeRemaining < 0f)
{
sugarRushHoldTimeRemaining = 0f;
}
}
else
{
sugarRush -= s.RushDecayRate * Time.deltaTime;
if (sugarRush < 0f)
{
sugarRush = 0f;
}
}
}
if (sugarRushVisual < useThisSugarRush)
{
sugarRushVisual += s.RushVisualChangeRate * Time.deltaTime;
if (sugarRushVisual > useThisSugarRush)
{
sugarRushVisual = useThisSugarRush;
}
}
else if (sugarRushVisual > useThisSugarRush)
{
sugarRushVisual -= s.RushVisualChangeRate * Time.deltaTime;
if (sugarRushVisual < useThisSugarRush)
{
sugarRushVisual = useThisSugarRush;
}
}
}
private void TryGrabAnimator()
{
animator = ((Component)this).GetComponentInChildren<Animator>();
}
private void CollectRush(float amount)
{
sugarRush += amount;
SaveManager.Instance.Global.Records.TotalCandyCollected += amount;
SaveManager.Instance.Stage.Records.TotalCandyCollectedThisStage += amount;
if (sugarRush > s.MaxRushMeter)
{
sugarRush = s.MaxRushMeter;
}
sugarRushHoldTimeRemaining = s.RushHoldDuration;
}
private void OnPedestrianDodge(StreetLife pedestrian)
{
TombRushPedestrian component = ((Component)pedestrian).GetComponent<TombRushPedestrian>();
if ((Object)(object)component == (Object)null)
{
return;
}
bool flag = false;
if (component.HasCandy)
{
if (SugarRushManager.Instance.SugarExplained)
{
flag = true;
}
else if (SugarRushManager.Instance.CanExplainSugarRush(component))
{
SugarRushManager.Instance.ExplainSugarRush(component);
}
if (flag)
{
CollectRush(s.PedestrianGrantsRush);
component.AnimateGiveCandy();
SaveManager.Instance.Global.Records.TotalPedestriansScared++;
SaveManager.Instance.Stage.Records.TotalPedestriansScaredThisStage++;
}
}
}
private void GetBaseAbilitySpeeds()
{
baseAirDashSpeed = player.airDashAbility.airDashSpeed;
baseBoostSpeed = player.normalBoostSpeed;
baseWallRunMoveSpeed = player.wallrunAbility.wallRunMoveSpeed;
baseRunSpeedModifier = player.runSpeedModifier;
baseVertBottomExitSpeed = player.vertBottomExitSpeed;
baseVertMaxSpeed = player.vertMaxSpeed;
baseVertTopJumpSpeed = player.vertTopJumpSpeed;
if (!gotStaticBaseSpeeds)
{
bmxGrindSpeed = player.bmxMovementStats.grindSpeed;
bmxRunSpeed = player.bmxMovementStats.runSpeed;
inlineGrindSpeed = player.inlineMovementStats.grindSpeed;
inlineRunSpeed = player.inlineMovementStats.runSpeed;
skateboardGrindSpeed = player.skateboardMovementStats.grindSpeed;
skateboardRunSpeed = player.skateboardMovementStats.runSpeed;
gotStaticBaseSpeeds = true;
}
gotBaseSpeeds = true;
}
private void SetAbilitySpeedsBasedOnSugarLevels()
{
if (gotBaseSpeeds && !Plugin.Instance.ConflictingMovementModsInstalled)
{
float num = 1f + effectiveSugarRush * s.MovementSpeedMultiplier;
player.airDashAbility.airDashSpeed = baseAirDashSpeed * num;
player.normalBoostSpeed = baseBoostSpeed * num;
player.wallrunAbility.wallRunMoveSpeed = baseWallRunMoveSpeed * num;
player.runSpeedModifier = baseRunSpeedModifier + effectiveSugarRush * s.MaxBaseRunSpeedIncrease;
player.bmxMovementStats.grindSpeed = bmxGrindSpeed * num;
player.bmxMovementStats.runSpeed = bmxRunSpeed * num;
player.inlineMovementStats.grindSpeed = inlineGrindSpeed * num;
player.inlineMovementStats.runSpeed = inlineRunSpeed * num;
player.skateboardMovementStats.grindSpeed = skateboardGrindSpeed * num;
player.skateboardMovementStats.runSpeed = skateboardRunSpeed * num;
player.vertBottomExitSpeed = baseVertBottomExitSpeed * num;
player.vertMaxSpeed = baseVertMaxSpeed * num;
player.vertTopJumpSpeed = baseVertTopJumpSpeed * num;
}
}
private void SetAnimatorSpeedBasedOnSugarLevels()
{
if ((Object)(object)animator == (Object)null)
{
TryGrabAnimator();
}
if ((Object)(object)animator != (Object)null)
{
animator.speed = 1f + effectiveSugarRush * s.AnimationSpeedMultiplier;
}
}
private void UpdateSugarHUD()
{
if (!((Object)(object)TombRushUI.Instance == (Object)null))
{
TombRushUI.Instance.SugarRushHUD.SetMeterStyle((MeterStyle)(!(effectiveSugarRush > 0f)));
TombRushUI.Instance.SugarRushHUD.SetMeterValue(sugarRushVisual);
}
}
private void TrackSugarStats()
{
if (effectiveSugarRush >= 1f)
{
isAt100PercentRush = true;
timeSpentAt100PercentRush += Time.deltaTime;
return;
}
if (isAt100PercentRush)
{
StageRecords records = SaveManager.Instance.Stage.Records;
records.TrySetNewRecordHigherIsBetter(ref records.MaxTimeWith100PercentRush, timeSpentAt100PercentRush);
timeSpentAt100PercentRush = 0f;
}
isAt100PercentRush = false;
}
}
public static class PlayerExtensions
{
public static TombRushPlayer GetTombRushPlayer(this Player player)
{
return ((Component)player).GetComponent<TombRushPlayer>();
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "TombRush.Plugin";
public const string PLUGIN_NAME = "TombRush.Plugin";
public const string PLUGIN_VERSION = "0.0.0";
}
}
namespace TombRush.Plugin.Patches
{
[HarmonyPatch(typeof(AmbientManager))]
internal static class AmbientManagerPatch
{
[HarmonyPrefix]
[HarmonyPatch("Awake")]
private static void Awake_Prefix(AmbientManager __instance)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
Scene scene = ((Component)__instance).gameObject.scene;
if (!(((Scene)(ref scene)).name != "downhill"))
{
__instance.AmbientEnvLight = new Color(0.4f, 0.2f, 0.4f, 1f);
__instance.AmbientEnvShadow = new Color(0.1f, 0.15f, 0.2f, 1f);
}
}
}
}
namespace TombRush.Plugin.Dependencies
{
public class AssemblyDependencies
{
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}