using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using OpJosModREPO.IAmDucky.Patches;
using OpJosModREPO.Util;
using Photon.Pun;
using REPOMods;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("REPOMods")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("REPOMods")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ae067094-69b3-4aaf-9688-38ff78ee3b28")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace OpJosModREPO.Util
{
public class ReflectionUtils
{
public static void InvokeMethod(object obj, string methodName, object[] parameters)
{
Type type = obj.GetType();
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
method.Invoke(obj, parameters);
}
public static void InvokeMethod(object obj, Type forceType, string methodName, object[] parameters)
{
MethodInfo method = forceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
method.Invoke(obj, parameters);
}
public static void SetPropertyValue(object obj, string propertyName, object value)
{
Type type = obj.GetType();
PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
property.SetValue(obj, value);
}
public static T InvokeMethod<T>(object obj, string methodName, object[] parameters)
{
Type type = obj.GetType();
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return (T)method.Invoke(obj, parameters);
}
public static T GetFieldValue<T>(object obj, string fieldName)
{
Type type = obj.GetType();
FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return (T)field.GetValue(obj);
}
public static void SetFieldValue(object obj, string fieldName, object value)
{
Type type = obj.GetType();
FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
field.SetValue(obj, value);
}
}
}
namespace OpJosModREPO.IAmDucky
{
public class DuckPlayerController : MonoBehaviour
{
private static ManualLogSource mls;
private EnemyRigidbody erb;
private Rigidbody rb;
private Vector3 moveDirection;
public float moveSpeed = 3f;
public float turnSpeed = 3f;
public float jumpForce = 0.5f;
public Transform cameraTransform;
public float mouseSensitivity = 0.25f;
private float cameraPitch = 0f;
public Vector3 cameraOffset = new Vector3(0f, 1.75f, -1.75f);
public float cameraSmoothSpeed = 15f;
public EnemyDuck thisDuck = null;
public int controlActorNumber;
private float attackCooldown;
private bool isYourDuck = false;
private bool isHost = false;
private float syncTimer = 0f;
private float syncInterval = 0.375f;
private Vector3 targetLookDirection;
private bool shouldJump = false;
private bool slowFall = false;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
public void Setup(int actorNumber, EnemyDuck duck)
{
//IL_00c7: 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)
controlActorNumber = actorNumber;
thisDuck = duck;
isHost = PhotonNetwork.IsMasterClient;
erb = ReflectionUtils.GetFieldValue<EnemyRigidbody>(thisDuck.enemy, "Rigidbody");
rb = ReflectionUtils.GetFieldValue<Rigidbody>(erb, "rb");
rb.drag = 5000f;
rb.constraints = (RigidbodyConstraints)80;
rb.useGravity = true;
if (PhotonNetwork.LocalPlayer.ActorNumber == controlActorNumber)
{
isYourDuck = true;
((Behaviour)PlayerController.instance).enabled = false;
((Component)Camera.main).transform.SetParent(((Component)duck).gameObject.transform);
((Component)Camera.main).transform.localPosition = cameraOffset;
((Component)Camera.main).transform.localRotation = Quaternion.identity;
Cursor.lockState = (CursorLockMode)1;
Cursor.visible = false;
}
cameraTransform = ((Component)Camera.main).transform;
}
public void UpdateMovementAndRotation(Vector3 movement, Vector3 camForward, bool jump)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: 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)
moveDirection = movement;
targetLookDirection = camForward;
if (jump)
{
TriggerJump();
}
}
private void Start()
{
}
private void Update()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: 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_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_009c: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
if (isYourDuck)
{
Vector2 val = (Vector2)((Keyboard.current != null) ? new Vector2((float)(((ButtonControl)Keyboard.current.aKey).isPressed ? (-1) : (((ButtonControl)Keyboard.current.dKey).isPressed ? 1 : 0)), (float)(((ButtonControl)Keyboard.current.sKey).isPressed ? (-1) : (((ButtonControl)Keyboard.current.wKey).isPressed ? 1 : 0))) : Vector2.zero);
Transform transform = ((Component)this).transform;
Vector3 val2 = new Vector3(val.x, 0f, val.y);
moveDirection = transform.TransformDirection(((Vector3)(ref val2)).normalized);
float num = ((InputControl<float>)(object)((Vector2Control)((Pointer)Mouse.current).delta).x).ReadValue() * mouseSensitivity;
float num2 = ((InputControl<float>)(object)((Vector2Control)((Pointer)Mouse.current).delta).y).ReadValue() * mouseSensitivity;
cameraPitch -= num2;
cameraPitch = Mathf.Clamp(cameraPitch, -60f, 60f);
((Component)this).transform.Rotate(Vector3.up * num);
cameraTransform.localRotation = Quaternion.Euler(cameraPitch, 0f, 0f);
handleInput();
}
}
private void FixedUpdate()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: 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_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
//IL_01d4: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
if ((isYourDuck || isHost) && targetLookDirection != Vector3.zero)
{
Quaternion val = Quaternion.LookRotation(targetLookDirection);
((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, val, Time.deltaTime * 10f);
}
if (isHost)
{
erb.DisableFollowPosition(0.5f, 50f);
rb.AddForce(new Vector3(moveDirection.x * moveSpeed, 0f, moveDirection.z * moveSpeed), (ForceMode)5);
if (moveDirection.x == 0f && moveDirection.z == 0f)
{
Vector3 velocity = rb.velocity;
Vector3 val2 = default(Vector3);
((Vector3)(ref val2))..ctor(velocity.x, 0f, velocity.z);
val2 = Vector3.Lerp(val2, Vector3.zero, Time.fixedDeltaTime * 5f);
rb.velocity = new Vector3(val2.x, velocity.y, val2.z);
}
((Component)thisDuck).gameObject.transform.position = ((Component)rb).transform.position;
}
if (isYourDuck)
{
cameraTransform.position = new Vector3(cameraTransform.position.x, ((Component)rb).transform.position.y + cameraOffset.y, cameraTransform.position.z);
if (attackCooldown > 0f)
{
attackCooldown -= Time.fixedDeltaTime;
}
if (attackCooldown <= 0f)
{
attackNearbyEnemies();
attackCooldown = 0.75f;
}
}
}
private void handleInput()
{
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Invalid comparison between Unknown and I4
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
if (controlActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)
{
return;
}
if (((ButtonControl)Keyboard.current.spaceKey).wasPressedThisFrame && PhotonNetwork.IsMasterClient)
{
TriggerJump();
}
if (((ButtonControl)Keyboard.current.cKey).wasPressedThisFrame)
{
mls.LogInfo((object)"Reseting control of duck");
if (PhotonNetwork.IsMasterClient)
{
GeneralUtil.ControlClosestDuck(cameraTransform.position, 1);
}
}
if (((ButtonControl)Keyboard.current.eKey).wasPressedThisFrame)
{
if ((int)thisDuck.currentState == 11)
{
mls.LogInfo((object)"Stopping duck attack mode");
ReflectionUtils.InvokeMethod(thisDuck, "UpdateState", new object[1] { (object)(State)1 });
}
else
{
mls.LogInfo((object)"Starting duck attack mode");
ReflectionUtils.InvokeMethod(thisDuck, "UpdateState", new object[1] { (object)(State)11 });
}
}
if (((ButtonControl)Keyboard.current.kKey).wasPressedThisFrame)
{
EnemyHealth fieldValue = ReflectionUtils.GetFieldValue<EnemyHealth>(thisDuck.enemy, "Health");
ReflectionUtils.InvokeMethod(fieldValue, "Death", new object[1] { Vector3.zero });
mls.LogMessage((object)"Killed controlled duck");
}
}
private void attackNearbyEnemies()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Invalid comparison between Unknown and I4
//IL_0023: 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_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: 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_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
if ((int)thisDuck.currentState != 11)
{
return;
}
List<Enemy> list = GeneralUtil.FindCloseEnemies(((Component)thisDuck).transform.position, 2.25f);
foreach (Enemy item in list)
{
if (!((Object)(object)item != (Object)null) || ((Object)item).GetInstanceID() == ((Object)thisDuck.enemy).GetInstanceID())
{
continue;
}
Vector3 val = ((Component)item).transform.position - ((Component)thisDuck).transform.position;
Vector3 normalized = ((Vector3)(ref val)).normalized;
float num = Vector3.Angle(((Component)thisDuck).transform.forward, normalized);
if (num < 50f)
{
EnemyHealth fieldValue = ReflectionUtils.GetFieldValue<EnemyHealth>(item, "Health");
if ((Object)(object)fieldValue != (Object)null)
{
val = ((Component)item).transform.position - ((Component)thisDuck).transform.position;
Vector3 normalized2 = ((Vector3)(ref val)).normalized;
fieldValue.Hurt(25, normalized2);
}
else
{
mls.LogError((object)("Health component not found for enemy: " + ((Object)item).name));
}
}
}
}
private void TriggerJump()
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: 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)
if ((Object)(object)thisDuck == (Object)null)
{
return;
}
Enemy enemy = thisDuck.enemy;
if (!((Object)(object)enemy == (Object)null))
{
object fieldValue = ReflectionUtils.GetFieldValue<object>(enemy, "Jump");
if (fieldValue != null)
{
ReflectionUtils.InvokeMethod(fieldValue, "StuckTrigger", new object[1] { Vector3.up });
rb.AddForce(Vector3.up * jumpForce, (ForceMode)1);
}
}
}
}
public static class GeneralUtil
{
private static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
public static EnemyDuck FindClosestDuck(Vector3 pos)
{
//IL_0026: 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)
EnemyDuck result = null;
float num = float.MaxValue;
EnemyDuck[] array = Object.FindObjectsOfType<EnemyDuck>();
foreach (EnemyDuck val in array)
{
float num2 = Vector3.Distance(((Component)val).gameObject.transform.position, pos);
if (num2 < num)
{
result = val;
num = num2;
}
}
return result;
}
public static EnemyDuck FindClosestDuckWithoutController(Vector3 pos)
{
//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)
EnemyDuck result = null;
float num = float.MaxValue;
EnemyDuck[] array = Object.FindObjectsOfType<EnemyDuck>();
foreach (EnemyDuck val in array)
{
if (!((Object)(object)FindDuckController(val) != (Object)null))
{
float num2 = Vector3.Distance(((Component)val).gameObject.transform.position, pos);
if (num2 < num)
{
result = val;
num = num2;
}
}
}
return result;
}
public static DuckPlayerController FindDuckController(EnemyDuck duck)
{
DuckPlayerController[] array = Object.FindObjectsOfType<DuckPlayerController>();
foreach (DuckPlayerController duckPlayerController in array)
{
if (((Object)duckPlayerController.thisDuck).GetInstanceID() == ((Object)duck).GetInstanceID())
{
return duckPlayerController;
}
}
return null;
}
public static DuckPlayerController FindDuckController(int? actorNumber)
{
DuckPlayerController[] array = Object.FindObjectsOfType<DuckPlayerController>();
foreach (DuckPlayerController duckPlayerController in array)
{
if (duckPlayerController.controlActorNumber == actorNumber)
{
return duckPlayerController;
}
}
return null;
}
public static List<Enemy> FindCloseEnemies(Vector3 pos, float range)
{
//IL_0022: 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)
List<Enemy> list = new List<Enemy>();
Enemy[] array = Object.FindObjectsOfType<Enemy>();
foreach (Enemy val in array)
{
float num = Vector3.Distance(((Component)val).gameObject.transform.position, pos);
if (num <= range)
{
list.Add(val);
}
}
return list;
}
public static void MoveDuckToPos(Vector3 pos)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
EnemyDuck obj = FindClosestDuckWithoutController(pos);
GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
if ((Object)(object)val == (Object)null)
{
mls.LogError((object)"No duck found without a controller to teleport.");
return;
}
mls.LogMessage((object)$"Found closest duck at {val.transform.position}, moving it to player.");
EnemyDuck component = val.GetComponent<EnemyDuck>();
if ((Object)(object)component != (Object)null)
{
((Behaviour)component).enabled = false;
component.currentState = (State)1;
}
EnemyRigidbody component2 = val.GetComponent<EnemyRigidbody>();
if ((Object)(object)component2 != (Object)null)
{
((Behaviour)component2).enabled = false;
}
NavMeshAgent component3 = val.GetComponent<NavMeshAgent>();
if ((Object)(object)component3 != (Object)null)
{
component3.Warp(pos);
}
mls.LogMessage((object)$"Duck moving towards {val.transform.position}");
}
public static void ControlClosestDuck(Vector3 pos, int actorNumber)
{
//IL_0001: 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)
EnemyDuck val = FindClosestDuck(pos);
if ((Object)(object)val != (Object)null)
{
mls.LogInfo((object)$"Found closest duck at {((Component)val).gameObject.transform.position}, transferring control to player.");
DuckPlayerController duckPlayerController = ((Component)val).gameObject.GetComponent<DuckPlayerController>();
if ((Object)(object)duckPlayerController == (Object)null)
{
duckPlayerController = ((Component)val).gameObject.AddComponent<DuckPlayerController>();
}
duckPlayerController.Setup(actorNumber, val);
NavMeshAgent component = ((Component)val).gameObject.GetComponent<NavMeshAgent>();
if ((Object)(object)component != (Object)null)
{
component.isStopped = true;
((Behaviour)component).enabled = false;
}
mls.LogInfo((object)"Control transferred to the duck.");
}
else
{
mls.LogInfo((object)"No duck found to transfer control.");
}
}
public static void RemoveSpawnedControllableDuck(DuckPlayerController duckController)
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)duckController == (Object)null)
{
mls.LogWarning((object)"Duck controller is null, cannot destroy.");
return;
}
Object.Destroy((Object)(object)duckController);
mls.LogInfo((object)"Duck controller destroyed.");
if (PhotonNetwork.IsMasterClient)
{
PlayerController instance = PlayerController.instance;
if ((Object)(object)duckController.thisDuck != (Object)null)
{
EnemyHealth fieldValue = ReflectionUtils.GetFieldValue<EnemyHealth>(duckController.thisDuck.enemy, "Health");
ReflectionUtils.InvokeMethod(fieldValue, "Death", new object[1] { Vector3.zero });
mls.LogMessage((object)"Killed controlled duck");
}
}
}
public static void ReattatchCameraToPlayer()
{
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
PlayerController pc = PlayerController.instance;
Camera val = Camera.main ?? Object.FindObjectOfType<Camera>();
if ((Object)(object)val != (Object)null)
{
((Component)val).tag = "MainCamera";
((Behaviour)val).enabled = true;
((Component)val).gameObject.SetActive(true);
if ((Object)(object)pc.cameraGameObject != (Object)null)
{
((Component)val).transform.SetParent(pc.cameraGameObject.transform);
((Component)val).transform.localPosition = Vector3.zero;
((Component)val).transform.localRotation = Quaternion.identity;
((Component)val).transform.localScale = Vector3.one;
}
mls.LogInfo((object)"Camera moved back to player.");
}
else
{
mls.LogWarning((object)"No main camera found when trying to move back to player.");
}
((Behaviour)pc).enabled = true;
if ((Object)(object)pc.cameraGameObject != (Object)null)
{
pc.cameraGameObject.SetActive(true);
}
if ((Object)(object)pc.cameraGameObjectLocal != (Object)null)
{
pc.cameraGameObjectLocal.SetActive(true);
}
DelayUtility.RunAfterDelay(0.25f, delegate
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
CameraAim instance = CameraAim.Instance;
if (instance != null)
{
instance.CameraAimSpawn(((Component)pc).transform.eulerAngles.y);
}
});
}
public static void ReleaseDuckControlToSpectate()
{
if (PublicVars.DuckCleanupInProgress)
{
mls.LogInfo((object)"Duck cleanup already in progress — skipping duplicate call of ReleaseDuckControlToSpectate");
return;
}
PublicVars.DuckCleanupInProgress = true;
ReattatchCameraToPlayer();
DuckPlayerController duckPlayerController = Object.FindObjectOfType<DuckPlayerController>();
if ((Object)(object)duckPlayerController != (Object)null)
{
Object.Destroy((Object)(object)duckPlayerController);
mls.LogInfo((object)"Duck controller destroyed.");
}
if ((Object)(object)PlayerAvatar.instance != (Object)null && ReflectionUtils.GetFieldValue<bool>(PlayerAvatar.instance, "deadSet"))
{
mls.LogInfo((object)"Calling SetSpectate to enter true spectator mode...");
PlayerAvatar.instance.SetSpectate();
DelayUtility.RunAfterDelay(0.25f, delegate
{
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
SpectateCamera instance = SpectateCamera.instance;
if ((Object)(object)instance != (Object)null)
{
bool flag = ReflectionUtils.InvokeMethod<bool>(instance, "CheckState", new object[1] { Enum.Parse(typeof(State), "Normal") });
Transform val = PlayerAvatar.instance?.spectatePoint;
if ((Object)(object)val != (Object)null)
{
if (!flag)
{
ReflectionUtils.InvokeMethod(instance, "UpdateState", new object[1] { Enum.Parse(typeof(State), "Normal") });
mls.LogWarning((object)"SpectateCamera was not in Normal state — forcing it.");
}
Camera fieldValue = ReflectionUtils.GetFieldValue<Camera>(instance, "MainCamera");
Transform normalTransformDistance = instance.normalTransformDistance;
if ((Object)(object)fieldValue != (Object)null && (Object)(object)normalTransformDistance != (Object)null)
{
((Component)fieldValue).transform.SetParent(normalTransformDistance);
((Component)fieldValue).transform.localPosition = Vector3.zero;
((Component)fieldValue).transform.localRotation = Quaternion.identity;
((Component)fieldValue).tag = "MainCamera";
((Behaviour)fieldValue).enabled = true;
((Component)fieldValue).gameObject.SetActive(true);
fieldValue.clearFlags = (CameraClearFlags)1;
fieldValue.backgroundColor = Color.black;
}
else
{
mls.LogWarning((object)"Missing MainCamera or follow transform during spectate setup.");
}
}
}
else
{
mls.LogWarning((object)"SpectateCamera.instance was null.");
}
PublicVars.DuckCleanupInProgress = false;
});
}
else
{
mls.LogWarning((object)"PlayerAvatar.instance was null when trying to spectate.");
PublicVars.DuckCleanupInProgress = false;
}
}
public static void SpawnDuckAt(Vector3 spawnPos, int actorNumber)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: 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)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
mls.LogMessage((object)$"Spawning duck at {spawnPos}");
string text = "Enemies/Enemy - Duck";
GameObject val = Resources.Load<GameObject>(text);
if ((Object)(object)val == (Object)null)
{
mls.LogError((object)("Duck prefab not found at path: " + text));
return;
}
EnemySetup val2 = ScriptableObject.CreateInstance<EnemySetup>();
val2.spawnObjects = new List<GameObject> { val };
ReflectionUtils.InvokeMethod(LevelGenerator.Instance, "EnemySpawn", new object[2] { val2, spawnPos });
mls.LogInfo((object)"Duck spawned successfully.");
DelayUtility.RunAfterDelay(10f, delegate
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
MoveDuckToPos(spawnPos);
});
DelayUtility.RunAfterDelay(25f, delegate
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
ControlClosestDuck(spawnPos, actorNumber);
});
}
}
[BepInPlugin("OpJosModREPO.IAmDucky", "IAmDucky", "1.2.1")]
public class OpJosModBase : BaseUnityPlugin
{
private const string modGUID = "OpJosModREPO.IAmDucky";
private const string modName = "IAmDucky";
private const string modVersion = "1.2.1";
private readonly Harmony harmoy = new Harmony("OpJosModREPO.IAmDucky");
private static OpJosModBase Instance;
internal ManualLogSource mls;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
mls = Logger.CreateLogSource("OpJosModREPO.IAmDucky");
mls.LogInfo((object)"IAmDucky has started!");
PlayerAvatarPatch.SetLogSource(mls);
EnemyHealthPatch.SetLogSource(mls);
DuckPlayerController.SetLogSource(mls);
GeneralUtil.SetLogSource(mls);
harmoy.PatchAll();
}
}
}
namespace OpJosModREPO.IAmDucky.Patches
{
[HarmonyPatch(typeof(EnemyHealth))]
internal class EnemyHealthPatch
{
private static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
[HarmonyPatch("DeathRPC")]
[HarmonyPrefix]
private static void DeathRPCPatch(EnemyHealth __instance)
{
if (!PhotonNetwork.IsMasterClient)
{
return;
}
Enemy fieldValue = ReflectionUtils.GetFieldValue<Enemy>(__instance, "enemy");
EnemyDuck component = ((Component)fieldValue).GetComponent<EnemyDuck>();
if ((Object)(object)component == (Object)null)
{
return;
}
if (PublicVars.DuckCleanupInProgress)
{
mls.LogInfo((object)"Duck cleanup already in progress — skipping DeathRPC patch.");
return;
}
DuckPlayerController duckPlayerController = GeneralUtil.FindDuckController(component);
if (PhotonNetwork.LocalPlayer.ActorNumber == duckPlayerController.controlActorNumber && ReflectionUtils.GetFieldValue<bool>(PlayerAvatar.instance, "deadSet"))
{
mls.LogInfo((object)"Duck dying is duck being controlled, release control of duck");
PublicVars.DuckDied = true;
GeneralUtil.ReleaseDuckControlToSpectate();
}
else if (PhotonNetwork.IsMasterClient)
{
Object.Destroy((Object)(object)duckPlayerController);
mls.LogInfo((object)$"Player{duckPlayerController.controlActorNumber}'s Duck controller destroyed.");
}
}
}
[HarmonyPatch(typeof(PlayerAvatar))]
internal class PlayerAvatarPatch
{
private static ManualLogSource mls;
public static void SetLogSource(ManualLogSource logSource)
{
mls = logSource;
}
[HarmonyPatch("PlayerDeath")]
[HarmonyPostfix]
private static void PlayerDeathPatch(PlayerAvatar __instance)
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
if (!PhotonNetwork.IsMasterClient)
{
return;
}
if (!PublicVars.CanSpawnDuck)
{
mls.LogInfo((object)"Can't spawn duck again, set to spectate");
GeneralUtil.ReleaseDuckControlToSpectate();
return;
}
PublicVars.CanSpawnDuck = false;
if (PhotonNetwork.IsMasterClient)
{
mls.LogMessage((object)"Player is dead, spawning duck as host");
GeneralUtil.SpawnDuckAt(((Component)__instance).transform.position, 1);
}
}
[HarmonyPatch("ReviveRPC")]
[HarmonyPostfix]
private static void ReviveRPCPatch(PlayerAvatar __instance)
{
if (!PhotonNetwork.IsMasterClient)
{
return;
}
int ownerActorNr = __instance.photonView.OwnerActorNr;
if (ownerActorNr == PhotonNetwork.LocalPlayer.ActorNumber)
{
mls.LogInfo((object)$"Handling local player respawn: {ownerActorNr}");
DuckPlayerController duckController = GeneralUtil.FindDuckController((int?)ownerActorNr);
if (!PublicVars.CanSpawnDuck && !PublicVars.DuckDied)
{
mls.LogMessage((object)"Player revived while duck is spawned and alive");
GeneralUtil.ReattatchCameraToPlayer();
GeneralUtil.RemoveSpawnedControllableDuck(duckController);
PublicVars.DuckDied = true;
}
else if (!PublicVars.CanSpawnDuck && PublicVars.DuckDied)
{
mls.LogMessage((object)"Player revived while duck was spawned and died");
GeneralUtil.ReattatchCameraToPlayer();
}
PublicVars.DuckCleanupInProgress = false;
}
else if (PhotonNetwork.IsMasterClient)
{
mls.LogInfo((object)$"[HOST] Cleaning up duck for revived player: {ownerActorNr}");
DuckPlayerController duckController2 = GeneralUtil.FindDuckController((int?)ownerActorNr);
GeneralUtil.RemoveSpawnedControllableDuck(duckController2);
}
}
[HarmonyPatch("LoadingLevelAnimationCompleted")]
[HarmonyPostfix]
private static void LoadingLevelAnimationCompletedPatch(PlayerAvatar __instance)
{
if (PhotonNetwork.IsMasterClient && ((Object)__instance).GetInstanceID() == ((Object)PlayerAvatar.instance).GetInstanceID())
{
mls.LogMessage((object)"New Level, allow being duck again");
PublicVars.CanSpawnDuck = true;
PublicVars.DuckDied = false;
PublicVars.DuckCleanupInProgress = false;
}
}
}
}
namespace REPOMods
{
public class DelayUtility : MonoBehaviour
{
private static DelayUtility _instance;
public static DelayUtility Instance
{
get
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
if ((Object)(object)_instance == (Object)null)
{
GameObject val = new GameObject("DelayUtility");
_instance = val.AddComponent<DelayUtility>();
Object.DontDestroyOnLoad((Object)(object)val);
}
return _instance;
}
}
private void Awake()
{
if ((Object)(object)_instance == (Object)null)
{
_instance = this;
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
}
else if ((Object)(object)_instance != (Object)(object)this)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
public static void RunAfterDelay(float seconds, Action action)
{
((MonoBehaviour)Instance).StartCoroutine(Instance.DelayCoroutine(seconds, action));
}
private IEnumerator DelayCoroutine(float seconds, Action action)
{
yield return (object)new WaitForSeconds(seconds);
action?.Invoke();
}
}
public static class PublicVars
{
public static bool CanSpawnDuck = true;
public static bool DuckDied = false;
public static bool DuckCleanupInProgress = false;
}
}