using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[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 REPOJP.EnemyOrbMerge
{
[BepInPlugin("REPOJP.EnemyOrbMerge", "EnemyOrbMerge", "1.0.0")]
public sealed class EnemyOrbMergePlugin : BaseUnityPlugin
{
private sealed class OrbEntry
{
public readonly EnemyValuable EnemyValuable;
public readonly ValuableObject ValuableObject;
public readonly PhysGrabObject PhysGrabObject;
public readonly PhysGrabObjectImpactDetector ImpactDetector;
public readonly PhotonView PhotonView;
public readonly GameObject GameObject;
public readonly int Id;
public readonly int SortToken;
public readonly float RegisteredTime;
public readonly List<Collider> Colliders = new List<Collider>();
public int MergeCount;
public float NextMergeAllowedTime;
public float InvincibilityEffectEndTime;
public float NextInvincibilityEffectRefreshTime;
private OrbEntry(EnemyValuable enemyValuable)
{
EnemyValuable = enemyValuable;
GameObject = ((Component)enemyValuable).gameObject;
ValuableObject = ((Component)enemyValuable).GetComponent<ValuableObject>();
PhysGrabObject = ((Component)enemyValuable).GetComponent<PhysGrabObject>();
ImpactDetector = ((Component)enemyValuable).GetComponent<PhysGrabObjectImpactDetector>();
PhotonView = ((Component)enemyValuable).GetComponent<PhotonView>();
Id = (((Object)(object)PhotonView != (Object)null && PhotonView.ViewID > 0) ? PhotonView.ViewID : ((Object)GameObject).GetInstanceID());
SortToken = Id;
RegisteredTime = Time.time;
MergeCount = 0;
NextMergeAllowedTime = 0f;
InvincibilityEffectEndTime = 0f;
NextInvincibilityEffectRefreshTime = 0f;
RefreshColliders();
}
public static OrbEntry Create(EnemyValuable enemyValuable)
{
if ((Object)(object)enemyValuable == (Object)null)
{
return null;
}
ValuableObject component = ((Component)enemyValuable).GetComponent<ValuableObject>();
PhysGrabObject component2 = ((Component)enemyValuable).GetComponent<PhysGrabObject>();
if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
{
return null;
}
return new OrbEntry(enemyValuable);
}
public void RefreshColliders()
{
Colliders.Clear();
if ((Object)(object)GameObject == (Object)null)
{
return;
}
Collider[] componentsInChildren = GameObject.GetComponentsInChildren<Collider>(true);
foreach (Collider val in componentsInChildren)
{
if (IsColliderUsable(val))
{
Colliders.Add(val);
}
}
}
public string Describe()
{
string text = (((Object)(object)GameObject != (Object)null) ? ((Object)GameObject).name : "null");
return text + "#" + Id + "(mergeCount=" + MergeCount + ")";
}
}
[HarmonyPatch(typeof(EnemyValuable), "Start")]
private static class EnemyValuableStartPatch
{
private static void Postfix(EnemyValuable __instance)
{
EnemyOrbMergePlugin instance = Instance;
if (!((Object)(object)instance == (Object)null))
{
instance.RegisterEnemyOrb(__instance);
}
}
}
[HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "OnCollisionStay")]
private static class PhysGrabObjectImpactDetectorOnCollisionStayPatch
{
private static bool Prefix(PhysGrabObjectImpactDetector __instance, Collision collision)
{
EnemyOrbMergePlugin instance = Instance;
if ((Object)(object)instance == (Object)null)
{
return true;
}
if (instance.ShouldIgnoreOrbToOrbBreak(__instance, collision))
{
instance.LogDebug("Ignored orb-to-orb destructive collision");
return false;
}
return true;
}
}
public const string PluginGuid = "REPOJP.EnemyOrbMerge";
public const string PluginName = "EnemyOrbMerge";
public const string PluginVersion = "1.0.0";
internal static EnemyOrbMergePlugin Instance;
private static readonly FieldInfo ValuableCurrentField = AccessTools.Field(typeof(ValuableObject), "dollarValueCurrent");
private static readonly FieldInfo ValuableOriginalField = AccessTools.Field(typeof(ValuableObject), "dollarValueOriginal");
private static readonly FieldInfo ValuableSetField = AccessTools.Field(typeof(ValuableObject), "dollarValueSet");
private static readonly FieldInfo EnemyValuableIndestructibleTimerField = AccessTools.Field(typeof(EnemyValuable), "indestructibleTimer");
private static readonly FieldInfo EnemyValuableIndestructibleLerpField = AccessTools.Field(typeof(EnemyValuable), "indestructibleLerp");
private static readonly FieldInfo EnemyValuableOuterMaterialField = AccessTools.Field(typeof(EnemyValuable), "outerMaterial");
private static readonly FieldInfo ImpactDetectorIndestructibleSpawnTimerField = AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "indestructibleSpawnTimer");
private Harmony harmony;
private ConfigEntry<float> mergeCheckInterval;
private ConfigEntry<float> mergeArmDelay;
private ConfigEntry<float> remergeCooldown;
private ConfigEntry<float> contactSkin;
private ConfigEntry<int> maxOrbValue;
private ConfigEntry<int> maxOrbMergeCount;
private ConfigEntry<bool> debugLog;
private ConfigEntry<bool> playNetworkMergeEffect;
private ConfigEntry<bool> playInvincibilityElectricityEffect;
private readonly Dictionary<int, OrbEntry> trackedOrbs = new Dictionary<int, OrbEntry>();
private readonly HashSet<int> busyOrbIds = new HashSet<int>();
private readonly List<int> removeBuffer = new List<int>();
private readonly List<OrbEntry> scanBuffer = new List<OrbEntry>();
private float mergeCheckTimer;
private float rescanTimer;
private void Awake()
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Expected O, but got Unknown
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Expected O, but got Unknown
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Expected O, but got Unknown
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Expected O, but got Unknown
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Expected O, but got Unknown
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0206: Expected O, but got Unknown
try
{
Instance = this;
((Component)this).transform.parent = null;
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
mergeCheckInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MergeCheckInterval", 0.05f, new ConfigDescription("Interval in seconds for orb merge checks.オーブ同士のマージ判定を行う秒間隔", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
mergeArmDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MergeArmDelay", 0.2f, new ConfigDescription("Delay in seconds after orb spawn before merge checks begin.オーブ生成後にマージ判定を開始するまでの待機秒数", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
remergeCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ReMergeCooldown", 0.05f, new ConfigDescription("Cooldown in seconds before a merged orb can merge again.マージ後のオーブが再度マージ可能になるまでの待機秒数", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
contactSkin = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ContactSkin", 0.02f, new ConfigDescription("Extra contact distance used when checking orb touch.オーブ接触判定時に追加する余裕距離", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 0.5f), Array.Empty<object>()));
maxOrbValue = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxOrbValue", 0, new ConfigDescription("Maximum merged orb value.0 = unlimited.マージ後オーブの金額上限 0 = 無制限", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000000), Array.Empty<object>()));
maxOrbMergeCount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxOrbMergeCount", 0, new ConfigDescription("Maximum number of successful merges allowed per orb lineage.0 = unlimited.オーブ系統ごとの成功マージ回数上限 0 = 無制限", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>()));
debugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLog", false, "Enable debug logging.デバッグログ出力");
playNetworkMergeEffect = ((BaseUnityPlugin)this).Config.Bind<bool>("Effect", "PlayNetworkMergeEffect", true, "Play a built-in network visible impact effect at merge position.マージ位置で既存のネットワーク可視衝突エフェクトを再生");
playInvincibilityElectricityEffect = ((BaseUnityPlugin)this).Config.Bind<bool>("Effect", "PlayInvincibilityElectricityEffect", true, "Play built-in death pit electricity visuals while merged orb invincibility is active.マージ後無敵中に既存の穴落下ビリビリ演出を再生");
harmony = new Harmony("REPOJP.EnemyOrbMerge");
harmony.PatchAll();
SceneManager.sceneLoaded += OnSceneLoaded;
ResetTrackingState();
LogInfo("Plugin loaded");
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Awake failed\n" + ex));
}
}
private void OnDestroy()
{
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
SceneManager.sceneLoaded -= OnSceneLoaded;
if (harmony != null)
{
harmony.UnpatchSelf();
harmony = null;
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
ResetTrackingState();
}
private void Update()
{
if (CanRunLogic())
{
UpdateInvincibilityElectricityEffects();
if (rescanTimer > 0f)
{
rescanTimer -= Time.deltaTime;
}
else
{
rescanTimer = 1f;
RescanSceneOrbs();
CleanupTrackedOrbs();
}
if (mergeCheckTimer > 0f)
{
mergeCheckTimer -= Time.deltaTime;
return;
}
mergeCheckTimer = Mathf.Max(0.01f, mergeCheckInterval.Value);
ProcessOrbMerges();
}
}
internal void RegisterEnemyOrb(EnemyValuable enemyValuable)
{
if (CanTrackEnemyOrb(enemyValuable))
{
OrbEntry orbEntry = OrbEntry.Create(enemyValuable);
if (orbEntry != null && !trackedOrbs.ContainsKey(orbEntry.Id))
{
trackedOrbs.Add(orbEntry.Id, orbEntry);
LogDebug("Tracked orb added: " + orbEntry.Describe());
}
}
}
internal bool ShouldIgnoreOrbToOrbBreak(PhysGrabObjectImpactDetector selfDetector, Collision collision)
{
if (!CanRunLogic())
{
return false;
}
EnemyValuable enemyValuableFromDetector = GetEnemyValuableFromDetector(selfDetector);
if ((Object)(object)enemyValuableFromDetector == (Object)null)
{
return false;
}
PhysGrabObjectImpactDetector impactDetectorFromCollision = GetImpactDetectorFromCollision(collision);
EnemyValuable enemyValuableFromDetector2 = GetEnemyValuableFromDetector(impactDetectorFromCollision);
if ((Object)(object)enemyValuableFromDetector2 == (Object)null)
{
return false;
}
if ((Object)(object)enemyValuableFromDetector == (Object)(object)enemyValuableFromDetector2)
{
return false;
}
if (!CanTrackEnemyOrb(enemyValuableFromDetector) || !CanTrackEnemyOrb(enemyValuableFromDetector2))
{
return false;
}
return true;
}
private bool CanRunLogic()
{
if ((Object)(object)GameManager.instance == (Object)null)
{
return false;
}
return SemiFunc.IsMasterClientOrSingleplayer();
}
private void ResetTrackingState()
{
trackedOrbs.Clear();
busyOrbIds.Clear();
removeBuffer.Clear();
scanBuffer.Clear();
mergeCheckTimer = 0f;
rescanTimer = 0f;
}
private void RescanSceneOrbs()
{
EnemyValuable[] array = Object.FindObjectsOfType<EnemyValuable>(true);
for (int i = 0; i < array.Length; i++)
{
RegisterEnemyOrb(array[i]);
}
}
private void CleanupTrackedOrbs()
{
removeBuffer.Clear();
foreach (KeyValuePair<int, OrbEntry> trackedOrb in trackedOrbs)
{
if (!IsEntryValid(trackedOrb.Value))
{
removeBuffer.Add(trackedOrb.Key);
}
}
for (int i = 0; i < removeBuffer.Count; i++)
{
int num = removeBuffer[i];
trackedOrbs.Remove(num);
busyOrbIds.Remove(num);
}
}
private void ProcessOrbMerges()
{
CleanupTrackedOrbs();
scanBuffer.Clear();
foreach (KeyValuePair<int, OrbEntry> trackedOrb in trackedOrbs)
{
if (IsEntryReady(trackedOrb.Value))
{
scanBuffer.Add(trackedOrb.Value);
}
}
for (int i = 0; i < scanBuffer.Count; i++)
{
OrbEntry orbEntry = scanBuffer[i];
if (!IsEntryReady(orbEntry))
{
continue;
}
for (int j = i + 1; j < scanBuffer.Count; j++)
{
OrbEntry orbEntry2 = scanBuffer[j];
if (IsEntryReady(orbEntry2) && AreOrbsTouching(orbEntry, orbEntry2) && TryMerge(orbEntry, orbEntry2))
{
break;
}
}
}
}
private bool TryMerge(OrbEntry first, OrbEntry second)
{
//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0217: Unknown result type (might be due to invalid IL or missing references)
if (!IsEntryValid(first) || !IsEntryValid(second))
{
return false;
}
if (busyOrbIds.Contains(first.Id) || busyOrbIds.Contains(second.Id))
{
return false;
}
int num = Mathf.Max(0, Mathf.FloorToInt(GetDollarValueCurrent(first.ValuableObject)));
int num2 = Mathf.Max(0, Mathf.FloorToInt(GetDollarValueCurrent(second.ValuableObject)));
int mergedValue = num + num2;
int num3 = Mathf.Max(first.MergeCount, second.MergeCount) + 1;
if (IsMergeBlockedByMaxValue(num, num2, mergedValue))
{
ApplyBlockedInvincibility(first, second);
LogDebug("Merge blocked by max value: first=" + first.Describe() + " second=" + second.Describe() + " mergedValue=" + mergedValue + " max=" + GetConfiguredMaxOrbValue());
return true;
}
if (IsMergeBlockedByMaxMergeCount(first.MergeCount, second.MergeCount, num3))
{
ApplyBlockedInvincibility(first, second);
LogDebug("Merge blocked by max merge count: first=" + first.Describe() + " second=" + second.Describe() + " mergedCount=" + num3 + " max=" + GetConfiguredMaxOrbMergeCount());
return true;
}
OrbEntry orbEntry = SelectWinner(first, second);
OrbEntry orbEntry2 = ((orbEntry.Id == first.Id) ? second : first);
busyOrbIds.Add(orbEntry.Id);
busyOrbIds.Add(orbEntry2.Id);
try
{
Vector3 mergeEffectPosition = GetMergeEffectPosition(orbEntry, orbEntry2);
ApplyMergedValue(orbEntry, mergedValue);
ReapplyVanillaEnemyOrbInvincibility(orbEntry, allowElectricityEffect: true);
PlayMergeEffects(orbEntry, mergeEffectPosition);
ZeroOutLocalValue(orbEntry2);
DestroyLoser(orbEntry2);
trackedOrbs.Remove(orbEntry2.Id);
orbEntry.MergeCount = num3;
orbEntry.NextMergeAllowedTime = Time.time + Mathf.Max(0f, remergeCooldown.Value);
LogDebug("Merged orbs: winner=" + orbEntry.Describe() + " loser=" + orbEntry2.Describe() + " mergedValue=" + mergedValue + " mergedCount=" + num3);
return true;
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Merge failed\n" + ex));
return false;
}
finally
{
busyOrbIds.Remove(orbEntry2.Id);
busyOrbIds.Remove(orbEntry.Id);
}
}
private void ApplyMergedValue(OrbEntry winner, int mergedValue)
{
float num = Mathf.Max(0, mergedValue);
SetDollarValuesLocal(winner.ValuableObject, num);
if (SemiFunc.IsMultiplayer())
{
PhotonView photonView = winner.PhotonView;
if ((Object)(object)photonView != (Object)null)
{
photonView.RPC("DollarValueSetRPC", (RpcTarget)3, new object[1] { num });
}
}
}
private void ReapplyVanillaEnemyOrbInvincibility(OrbEntry winner, bool allowElectricityEffect)
{
try
{
if (winner != null && !((Object)(object)winner.EnemyValuable == (Object)null) && !((Object)(object)winner.ImpactDetector == (Object)null))
{
EnemyValuable enemyValuable = winner.EnemyValuable;
PhysGrabObjectImpactDetector impactDetector = winner.ImpactDetector;
impactDetector.destroyDisable = true;
SetImpactDetectorIndestructibleSpawnTimer(impactDetector, 0.1f);
if ((Object)(object)winner.PhysGrabObject != (Object)null)
{
winner.PhysGrabObject.OverrideIndestructible(0.1f);
}
if (EnemyValuableIndestructibleTimerField != null)
{
EnemyValuableIndestructibleTimerField.SetValue(enemyValuable, 5f);
}
if (EnemyValuableIndestructibleLerpField != null)
{
EnemyValuableIndestructibleLerpField.SetValue(enemyValuable, 0f);
}
ApplyEnemyOrbIndestructibleVisuals(enemyValuable);
if (allowElectricityEffect)
{
BeginInvincibilityElectricityEffect(winner);
}
else if (winner != null)
{
winner.InvincibilityEffectEndTime = 0f;
winner.NextInvincibilityEffectRefreshTime = 0f;
}
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("ReapplyVanillaEnemyOrbInvincibility failed\n" + ex));
}
}
private void BeginInvincibilityElectricityEffect(OrbEntry winner)
{
if (!playInvincibilityElectricityEffect.Value)
{
if (winner != null)
{
winner.InvincibilityEffectEndTime = 0f;
winner.NextInvincibilityEffectRefreshTime = 0f;
}
}
else if (winner != null)
{
winner.InvincibilityEffectEndTime = Time.time + 5f;
winner.NextInvincibilityEffectRefreshTime = 0f;
RefreshInvincibilityElectricityEffect(winner);
}
}
private void UpdateInvincibilityElectricityEffects()
{
if (!playInvincibilityElectricityEffect.Value)
{
return;
}
foreach (OrbEntry value in trackedOrbs.Values)
{
if (value != null && !(value.InvincibilityEffectEndTime <= Time.time) && !(value.NextInvincibilityEffectRefreshTime > Time.time))
{
RefreshInvincibilityElectricityEffect(value);
}
}
}
private void RefreshInvincibilityElectricityEffect(OrbEntry entry)
{
try
{
if (IsEntryValid(entry) && !((Object)(object)entry.PhysGrabObject == (Object)null))
{
entry.PhysGrabObject.DeathPitEffectCreate();
entry.NextInvincibilityEffectRefreshTime = Time.time + 2.4f;
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("RefreshInvincibilityElectricityEffect failed" + ex));
}
}
private static void SetImpactDetectorIndestructibleSpawnTimer(PhysGrabObjectImpactDetector impactDetector, float seconds)
{
if (!((Object)(object)impactDetector == (Object)null) && !(ImpactDetectorIndestructibleSpawnTimerField == null))
{
ImpactDetectorIndestructibleSpawnTimerField.SetValue(impactDetector, Mathf.Max(0f, seconds));
}
}
private static void ApplyEnemyOrbIndestructibleVisuals(EnemyValuable enemyValuable)
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)enemyValuable == (Object)null))
{
Material enemyOrbOuterMaterial = GetEnemyOrbOuterMaterial(enemyValuable);
if (!((Object)(object)enemyOrbOuterMaterial == (Object)null))
{
int num = Shader.PropertyToID("_FresnelPower");
int num2 = Shader.PropertyToID("_FresnelColor");
enemyOrbOuterMaterial.SetFloat(num, enemyValuable.fresnelPowerIndestructible);
enemyOrbOuterMaterial.SetColor(num2, enemyValuable.fresnelColorIndestructible);
}
}
}
private static Material GetEnemyOrbOuterMaterial(EnemyValuable enemyValuable)
{
if ((Object)(object)enemyValuable == (Object)null)
{
return null;
}
if (EnemyValuableOuterMaterialField != null)
{
object? value = EnemyValuableOuterMaterialField.GetValue(enemyValuable);
Material val = (Material)((value is Material) ? value : null);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
if ((Object)(object)enemyValuable.outerMeshRenderer == (Object)null)
{
return null;
}
Material material = ((Renderer)enemyValuable.outerMeshRenderer).material;
if ((Object)(object)material != (Object)null && EnemyValuableOuterMaterialField != null)
{
EnemyValuableOuterMaterialField.SetValue(enemyValuable, material);
}
return material;
}
private void ZeroOutLocalValue(OrbEntry loser)
{
SetDollarValuesLocal(loser.ValuableObject, 0f);
}
private void DestroyLoser(OrbEntry loser)
{
if (SemiFunc.IsMultiplayer())
{
if ((Object)(object)loser.GameObject != (Object)null)
{
PhotonNetwork.Destroy(loser.GameObject);
}
}
else if ((Object)(object)loser.GameObject != (Object)null)
{
Object.Destroy((Object)(object)loser.GameObject);
}
}
private OrbEntry SelectWinner(OrbEntry first, OrbEntry second)
{
bool flag = IsHeldByAnyPlayer(first);
bool flag2 = IsHeldByAnyPlayer(second);
if (flag != flag2)
{
return flag ? first : second;
}
float dollarValueCurrent = GetDollarValueCurrent(first.ValuableObject);
float dollarValueCurrent2 = GetDollarValueCurrent(second.ValuableObject);
if (dollarValueCurrent > dollarValueCurrent2)
{
return first;
}
if (dollarValueCurrent2 > dollarValueCurrent)
{
return second;
}
return (first.SortToken <= second.SortToken) ? first : second;
}
private int GetConfiguredMaxOrbValue()
{
if (maxOrbValue == null)
{
return 0;
}
return Mathf.Max(0, maxOrbValue.Value);
}
private bool IsMergeBlockedByMaxValue(int firstValue, int secondValue, int mergedValue)
{
int configuredMaxOrbValue = GetConfiguredMaxOrbValue();
if (configuredMaxOrbValue <= 0)
{
return false;
}
if (firstValue >= configuredMaxOrbValue || secondValue >= configuredMaxOrbValue)
{
return true;
}
return mergedValue > configuredMaxOrbValue;
}
private int GetConfiguredMaxOrbMergeCount()
{
if (maxOrbMergeCount == null)
{
return 0;
}
return Mathf.Max(0, maxOrbMergeCount.Value);
}
private bool IsMergeBlockedByMaxMergeCount(int firstMergeCount, int secondMergeCount, int mergedCount)
{
int configuredMaxOrbMergeCount = GetConfiguredMaxOrbMergeCount();
if (configuredMaxOrbMergeCount <= 0)
{
return false;
}
if (firstMergeCount >= configuredMaxOrbMergeCount || secondMergeCount >= configuredMaxOrbMergeCount)
{
return true;
}
return mergedCount > configuredMaxOrbMergeCount;
}
private void ApplyBlockedInvincibility(OrbEntry first, OrbEntry second)
{
try
{
ReapplyVanillaEnemyOrbInvincibility(first, allowElectricityEffect: false);
ReapplyVanillaEnemyOrbInvincibility(second, allowElectricityEffect: false);
float nextMergeAllowedTime = Time.time + Mathf.Max(0f, remergeCooldown.Value);
if (first != null)
{
first.NextMergeAllowedTime = nextMergeAllowedTime;
}
if (second != null)
{
second.NextMergeAllowedTime = nextMergeAllowedTime;
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("ApplyBlockedInvincibility failed\n" + ex));
}
}
private static bool IsHeldByAnyPlayer(OrbEntry entry)
{
if (entry == null || (Object)(object)entry.PhysGrabObject == (Object)null)
{
return false;
}
PhysGrabObject physGrabObject = entry.PhysGrabObject;
if (physGrabObject.playerGrabbing != null && physGrabObject.playerGrabbing.Count > 0)
{
return true;
}
if (physGrabObject.grabbed || physGrabObject.grabbedLocal)
{
return true;
}
return false;
}
private bool AreOrbsTouching(OrbEntry first, OrbEntry second)
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: 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_0106: Unknown result type (might be due to invalid IL or missing references)
if (!TryGetCombinedBounds(first.Colliders, out var bounds) || !TryGetCombinedBounds(second.Colliders, out var bounds2))
{
return false;
}
float num = Mathf.Max(0.001f, contactSkin.Value);
((Bounds)(ref bounds)).Expand(num * 2f);
((Bounds)(ref bounds2)).Expand(num * 2f);
if (!((Bounds)(ref bounds)).Intersects(bounds2))
{
return false;
}
Vector3 val3 = default(Vector3);
float num2 = default(float);
for (int i = 0; i < first.Colliders.Count; i++)
{
Collider val = first.Colliders[i];
if (!IsColliderUsable(val))
{
continue;
}
for (int j = 0; j < second.Colliders.Count; j++)
{
Collider val2 = second.Colliders[j];
if (IsColliderUsable(val2))
{
if (Physics.ComputePenetration(val, ((Component)val).transform.position, ((Component)val).transform.rotation, val2, ((Component)val2).transform.position, ((Component)val2).transform.rotation, ref val3, ref num2))
{
return true;
}
if (AreCollidersCloseEnough(val, val2, num))
{
return true;
}
}
}
}
return false;
}
private bool IsEntryReady(OrbEntry entry)
{
if (!IsEntryValid(entry))
{
return false;
}
if (busyOrbIds.Contains(entry.Id))
{
return false;
}
if (Time.time < entry.RegisteredTime + Mathf.Max(0f, mergeArmDelay.Value))
{
return false;
}
if (Time.time < entry.NextMergeAllowedTime)
{
return false;
}
return true;
}
private bool IsEntryValid(OrbEntry entry)
{
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
if (entry == null)
{
return false;
}
if ((Object)(object)entry.EnemyValuable == (Object)null || (Object)(object)entry.GameObject == (Object)null || (Object)(object)entry.ValuableObject == (Object)null || (Object)(object)entry.PhysGrabObject == (Object)null)
{
return false;
}
Scene scene = entry.GameObject.scene;
if (!((Scene)(ref scene)).IsValid())
{
return false;
}
if (!entry.GameObject.activeInHierarchy)
{
return false;
}
if (entry.PhysGrabObject.dead)
{
return false;
}
if (entry.Colliders == null || entry.Colliders.Count == 0)
{
entry.RefreshColliders();
}
if (entry.Colliders == null || entry.Colliders.Count == 0)
{
return false;
}
return true;
}
private bool CanTrackEnemyOrb(EnemyValuable enemyValuable)
{
//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)
if ((Object)(object)enemyValuable == (Object)null)
{
return false;
}
if ((Object)(object)((Component)enemyValuable).gameObject == (Object)null)
{
return false;
}
Scene scene = ((Component)enemyValuable).gameObject.scene;
if (!((Scene)(ref scene)).IsValid())
{
return false;
}
if ((Object)(object)((Component)enemyValuable).GetComponent<ValuableObject>() == (Object)null)
{
return false;
}
if ((Object)(object)((Component)enemyValuable).GetComponent<PhysGrabObject>() == (Object)null)
{
return false;
}
return true;
}
private void PlayMergeEffects(OrbEntry winner, Vector3 mergeEffectPosition)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
if (playNetworkMergeEffect.Value)
{
PlayNetworkVisibleMergeEffect(winner, mergeEffectPosition);
}
}
private void PlayNetworkVisibleMergeEffect(OrbEntry winner, Vector3 mergeEffectPosition)
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
try
{
if (winner != null && !((Object)(object)winner.PhotonView == (Object)null) && !((Object)(object)winner.ImpactDetector == (Object)null))
{
if (SemiFunc.IsMultiplayer())
{
winner.PhotonView.RPC("ImpactEffectRPC", (RpcTarget)0, new object[1] { mergeEffectPosition });
}
else if ((Object)(object)AssetManager.instance != (Object)null)
{
AssetManager.instance.PhysImpactEffect(mergeEffectPosition);
}
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("PlayNetworkVisibleMergeEffect failed\n" + ex));
}
}
private Vector3 GetMergeEffectPosition(OrbEntry first, OrbEntry second)
{
//IL_0011: 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_0013: 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_0022: 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_0058: 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_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
if (TryGetClosestPointsBetweenEntries(first, second, out var firstPoint, out var secondPoint))
{
return (firstPoint + secondPoint) * 0.5f;
}
if (first != null && second != null && (Object)(object)first.PhysGrabObject != (Object)null && (Object)(object)second.PhysGrabObject != (Object)null)
{
return (first.PhysGrabObject.centerPoint + second.PhysGrabObject.centerPoint) * 0.5f;
}
if (first != null && second != null && (Object)(object)first.GameObject != (Object)null && (Object)(object)second.GameObject != (Object)null)
{
return (first.GameObject.transform.position + second.GameObject.transform.position) * 0.5f;
}
return Vector3.zero;
}
private static bool TryGetClosestPointsBetweenEntries(OrbEntry first, OrbEntry second, out Vector3 firstPoint, out Vector3 secondPoint)
{
//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_000d: 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_0092: 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_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_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_00b2: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: 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_00e4: 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)
firstPoint = Vector3.zero;
secondPoint = Vector3.zero;
if (first == null || second == null)
{
return false;
}
float num = float.MaxValue;
bool flag = false;
for (int i = 0; i < first.Colliders.Count; i++)
{
Collider val = first.Colliders[i];
if (!IsColliderUsable(val))
{
continue;
}
for (int j = 0; j < second.Colliders.Count; j++)
{
Collider val2 = second.Colliders[j];
if (IsColliderUsable(val2))
{
Bounds bounds = val2.bounds;
Vector3 val3 = val.ClosestPoint(((Bounds)(ref bounds)).center);
Vector3 val4 = val2.ClosestPoint(val3);
Vector3 val5 = val3 - val4;
float sqrMagnitude = ((Vector3)(ref val5)).sqrMagnitude;
if (!flag || sqrMagnitude < num)
{
num = sqrMagnitude;
firstPoint = val3;
secondPoint = val4;
flag = true;
}
}
}
}
return flag;
}
private void LogInfo(string message)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)message);
}
private void LogDebug(string message)
{
if (debugLog.Value)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)message);
}
}
private static PhysGrabObjectImpactDetector GetImpactDetectorFromCollision(Collision collision)
{
if (collision == null)
{
return null;
}
if ((Object)(object)collision.gameObject != (Object)null)
{
PhysGrabObjectImpactDetector component = collision.gameObject.GetComponent<PhysGrabObjectImpactDetector>();
if ((Object)(object)component != (Object)null)
{
return component;
}
}
if ((Object)(object)collision.transform != (Object)null)
{
PhysGrabObjectImpactDetector componentInParent = ((Component)collision.transform).GetComponentInParent<PhysGrabObjectImpactDetector>();
if ((Object)(object)componentInParent != (Object)null)
{
return componentInParent;
}
}
if ((Object)(object)collision.collider != (Object)null)
{
PhysGrabObjectImpactDetector componentInParent2 = ((Component)collision.collider).GetComponentInParent<PhysGrabObjectImpactDetector>();
if ((Object)(object)componentInParent2 != (Object)null)
{
return componentInParent2;
}
}
return null;
}
private static EnemyValuable GetEnemyValuableFromDetector(PhysGrabObjectImpactDetector detector)
{
if ((Object)(object)detector == (Object)null)
{
return null;
}
EnemyValuable component = ((Component)detector).GetComponent<EnemyValuable>();
if ((Object)(object)component != (Object)null)
{
return component;
}
return ((Component)detector).GetComponentInParent<EnemyValuable>();
}
private static bool AreCollidersCloseEnough(Collider firstCollider, Collider secondCollider, float skin)
{
//IL_0003: 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_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0019: 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_001f: 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_0021: 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_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_004e: 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_0058: 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_005b: 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_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: 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)
Bounds bounds = secondCollider.bounds;
Vector3 val = firstCollider.ClosestPoint(((Bounds)(ref bounds)).center);
Vector3 val2 = secondCollider.ClosestPoint(val);
Vector3 val3 = val - val2;
if (((Vector3)(ref val3)).sqrMagnitude <= skin * skin)
{
return true;
}
bounds = firstCollider.bounds;
Vector3 val4 = secondCollider.ClosestPoint(((Bounds)(ref bounds)).center);
Vector3 val5 = firstCollider.ClosestPoint(val4);
val3 = val5 - val4;
return ((Vector3)(ref val3)).sqrMagnitude <= skin * skin;
}
private static bool TryGetCombinedBounds(List<Collider> colliders, out Bounds bounds)
{
//IL_0002: 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_0034: 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)
bounds = default(Bounds);
bool flag = false;
for (int i = 0; i < colliders.Count; i++)
{
Collider val = colliders[i];
if (IsColliderUsable(val))
{
if (!flag)
{
bounds = val.bounds;
flag = true;
}
else
{
((Bounds)(ref bounds)).Encapsulate(val.bounds);
}
}
}
return flag;
}
private static bool IsColliderUsable(Collider collider)
{
return (Object)(object)collider != (Object)null && collider.enabled && !collider.isTrigger && ((Component)collider).gameObject.activeInHierarchy;
}
private static float GetDollarValueCurrent(ValuableObject valuableObject)
{
if ((Object)(object)valuableObject == (Object)null || ValuableCurrentField == null)
{
return 0f;
}
object value = ValuableCurrentField.GetValue(valuableObject);
if (value == null)
{
return 0f;
}
return Convert.ToSingle(value);
}
private static void SetDollarValuesLocal(ValuableObject valuableObject, float value)
{
if (!((Object)(object)valuableObject == (Object)null))
{
if (ValuableOriginalField != null)
{
ValuableOriginalField.SetValue(valuableObject, value);
}
if (ValuableCurrentField != null)
{
ValuableCurrentField.SetValue(valuableObject, value);
}
if (ValuableSetField != null)
{
ValuableSetField.SetValue(valuableObject, true);
}
}
}
}
}