using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Mirage; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NuclearOption.MissionEditorScripts; using NuclearOption.Networking; using NuclearOption.SavedMission; using NuclearOption.SavedMission.Objectives; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [CompilerGenerated] [EditorBrowsable(EditorBrowsableState.Never)] [GeneratedCode("Unity.MonoScriptGenerator.MonoScriptInfoGenerator", null)] internal class UnitySourceGeneratedAssemblyMonoScriptTypes_v1 { private struct MonoScriptData { public byte[] FilePathsData; public byte[] TypesData; public int TotalTypes; public int TotalFiles; public bool IsEditorOnly; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static MonoScriptData Get() { return new MonoScriptData { FilePathsData = new byte[657] { 0, 0, 0, 1, 0, 0, 0, 33, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 65, 115, 115, 101, 116, 115, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 31, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 66, 111, 100, 121, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 32, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 66, 114, 97, 105, 110, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 33, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 67, 111, 110, 102, 105, 103, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 38, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 36, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 72, 101, 97, 108, 116, 104, 66, 97, 114, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 31, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 72, 111, 115, 116, 46, 99, 115, 0, 0, 0, 2, 0, 0, 0, 47, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 77, 105, 115, 115, 105, 111, 110, 83, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 38, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 80, 108, 117, 103, 105, 110, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 44, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 79, 98, 106, 101, 99, 116, 105, 118, 101, 80, 114, 111, 103, 114, 101, 115, 115, 46, 99, 115, 0, 0, 0, 2, 0, 0, 0, 33, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 80, 97, 114, 97, 109, 115, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 35, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 82, 101, 103, 105, 115, 116, 114, 121, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 34, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 83, 112, 97, 119, 110, 101, 114, 46, 99, 115, 0, 0, 0, 1, 0, 0, 0, 32, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 83, 119, 105, 112, 101, 46, 99, 115, 0, 0, 0, 3, 0, 0, 0, 40, 92, 65, 115, 115, 101, 116, 115, 92, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 92, 75, 97, 105, 106, 117, 85, 110, 105, 116, 80, 97, 110, 101, 108, 73, 110, 102, 111, 46, 99, 115 }, TypesData = new byte[595] { 0, 0, 0, 0, 22, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 65, 115, 115, 101, 116, 115, 0, 0, 0, 0, 20, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 66, 111, 100, 121, 0, 0, 0, 0, 21, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 66, 114, 97, 105, 110, 0, 0, 0, 0, 22, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 67, 111, 110, 102, 105, 103, 0, 0, 0, 0, 27, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 0, 0, 0, 0, 25, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 72, 101, 97, 108, 116, 104, 66, 97, 114, 0, 0, 0, 0, 20, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 72, 111, 115, 116, 0, 0, 0, 0, 34, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 67, 111, 110, 116, 97, 105, 110, 101, 114, 67, 111, 110, 118, 101, 114, 116, 101, 114, 0, 0, 0, 0, 36, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 77, 105, 115, 115, 105, 111, 110, 83, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 0, 0, 0, 0, 27, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 80, 108, 117, 103, 105, 110, 0, 0, 0, 0, 33, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 79, 98, 106, 101, 99, 116, 105, 118, 101, 80, 114, 111, 103, 114, 101, 115, 115, 0, 0, 0, 0, 22, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 80, 97, 114, 97, 109, 115, 0, 0, 0, 0, 26, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 80, 97, 114, 97, 109, 83, 116, 111, 114, 101, 0, 0, 0, 0, 24, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 82, 101, 103, 105, 115, 116, 114, 121, 0, 0, 0, 0, 23, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 83, 112, 97, 119, 110, 101, 114, 0, 0, 0, 0, 21, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 83, 119, 105, 112, 101, 0, 0, 0, 0, 29, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 124, 75, 97, 105, 106, 117, 85, 110, 105, 116, 80, 97, 110, 101, 108, 73, 110, 102, 111, 0, 0, 0, 0, 33, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 46, 75, 97, 105, 106, 117, 85, 110, 105, 116, 80, 97, 110, 101, 108, 73, 110, 102, 111, 124, 82, 111, 119, 0, 0, 0, 0, 35, 75, 97, 105, 106, 117, 78, 117, 107, 101, 109, 46, 75, 97, 105, 106, 117, 85, 110, 105, 116, 80, 97, 110, 101, 108, 73, 110, 102, 111, 124, 66, 108, 111, 99, 107 }, TotalFiles = 15, TotalTypes = 19, IsEditorOnly = false }; } } namespace KaijuNukem; public static class KaijuAssets { private const string BundleName = "kaiju"; private const string KaijuPrefabName = "KaijuCharacter"; private static AssetBundle _bundle; private const string KaijuDefinitionName = "KaijuDefinition"; public static bool Loaded => (Object)(object)_bundle != (Object)null; public static GameObject KaijuPrefab { get; private set; } public static UnitDefinition KaijuDefinition { get; private set; } public static bool Load(ManualLogSource log) { if ((Object)(object)_bundle != (Object)null) { return true; } string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { log.LogError((object)"[assets] could not resolve the plugin directory"); return false; } string text = Path.Combine(directoryName, "kaiju"); if (!File.Exists(text)) { log.LogError((object)("[assets] bundle missing at " + text + " — run the ThunderKit Deploy pipeline")); return false; } _bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)_bundle == (Object)null) { log.LogError((object)("[assets] AssetBundle.LoadFromFile returned null for " + text)); return false; } KaijuPrefab = _bundle.LoadAsset("KaijuCharacter"); if ((Object)(object)KaijuPrefab == (Object)null) { log.LogError((object)("[assets] 'KaijuCharacter' not found in bundle. Contents: " + string.Join(", ", _bundle.GetAllAssetNames()))); return false; } KaijuDefinition = _bundle.LoadAsset("KaijuDefinition"); if ((Object)(object)KaijuDefinition == (Object)null) { log.LogWarning((object)"[assets] 'KaijuDefinition' not in bundle — Mission Editor registration will be skipped"); } log.LogInfo((object)($"[assets] bundle loaded, {_bundle.GetAllAssetNames().Length} assets, " + $"prefab '{((Object)KaijuPrefab).name}' animator={(Object)(object)KaijuPrefab.GetComponentInChildren() != (Object)null}, " + "definition=" + (((Object)(object)KaijuDefinition != (Object)null) ? KaijuDefinition.jsonKey : "MISSING"))); return true; } } [DisallowMultipleComponent] public class KaijuBody : MonoBehaviour, IDamageable { private Unit _unit; private Rigidbody _rb; private ArmorProperties _armor; private byte _damageableId; private bool _damageableRegistered; private readonly Dictionary _unpaidDamage = new Dictionary(); private float _hitPoints; private float _maxHitPoints; private bool _dead; public static readonly List Live = new List(); public string DisplayName { get { if (!((Object)(object)_unit != (Object)null) || string.IsNullOrEmpty(_unit.unitName)) { return "Kaiju"; } return _unit.unitName; } } public float HitPoints => _hitPoints; public float HealthFraction { get { EnsureHealthInitialised(); if (!(_maxHitPoints > 0f)) { return 0f; } return Mathf.Clamp01(_hitPoints / _maxHitPoints); } } public bool IsDead => _dead; public event Action OnKaijuKilled; private void OnEnable() { if (!Live.Contains(this)) { Live.Add(this); } } private void OnDisable() { Live.Remove(this); } private void EnsureHealthInitialised() { if (!(_maxHitPoints > 0f)) { _maxHitPoints = (_hitPoints = KaijuParamStore.ForUnit(_unit).Health); if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)$"[body] health initialised to {_maxHitPoints:F0}"); } } } private void Awake() { //IL_006d: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown if ((Object)(object)_unit == (Object)null) { _unit = ((Component)this).GetComponent(); } if ((Object)(object)_rb == (Object)null) { _rb = ((Component)this).GetComponent(); } if ((Object)(object)_unit != (Object)null && string.IsNullOrEmpty(_unit.unitName)) { _unit.unitName = "Kaiju"; } if (_armor == null) { _armor = new ArmorProperties { pierceArmor = 20f, blastArmor = 50f, fireArmor = 10f, overpressureLimit = 1000f }; } } public void Initialize(Unit unit, float hitPoints, ArmorProperties armor) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) _unit = (((Object)(object)unit != (Object)null) ? unit : ((Component)this).GetComponent()); _rb = (((Object)(object)_unit != (Object)null) ? ((Component)_unit).GetComponent() : ((Component)this).GetComponent()); _maxHitPoints = (_hitPoints = hitPoints); _armor = (ArmorProperties)(((object)armor) ?? ((object)new ArmorProperties())); } private void Start() { if ((Object)(object)_unit == (Object)null) { _unit = ((Component)this).GetComponent(); } if (!((Object)(object)_unit == (Object)null)) { EnsureHealthInitialised(); _damageableId = _unit.RegisterDamageable((IDamageable)(object)this); _damageableRegistered = true; } } public void TakeDamage(float pierceDamage, float blastDamage, float amountAffected, float fireDamage, float ImpactDamage, PersistentID dealerID) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (_dead || (Object)(object)_unit == (Object)null || !((NetworkBehaviour)_unit).IsServer) { return; } float num = NetDamage(pierceDamage, blastDamage, amountAffected, fireDamage, ImpactDamage); if (!(num <= 0f)) { if (_damageableRegistered) { _unit.Damage(_damageableId, new DamageInfo(pierceDamage, blastDamage, fireDamage, ImpactDamage)); } ReduceHealth(num, dealerID); } } private float NetDamage(float pierceDamage, float blastDamage, float amountAffected, float fireDamage, float impactDamage) { KaijuParams kaijuParams = KaijuParamStore.ForUnit(_unit); float num = Mathf.Max(pierceDamage - _armor.pierceArmor, 0f) / _armor.pierceTolerance * Mathf.Max(kaijuParams.RoundDamageScale, 0f); float num2 = Mathf.Max(blastDamage - _armor.blastArmor, 0f) * amountAffected / _armor.blastTolerance * Mathf.Max(kaijuParams.BlastDamageScale, 0f); float num3 = Mathf.Max(fireDamage - _armor.fireArmor, 0f) / _armor.fireTolerance; return num + num2 + num3 + impactDamage; } public void ApplyDamage(float pierceDamage, float blastDamage, float fireDamage, float impactDamage) { if (!((Object)(object)_unit != (Object)null) || !((NetworkBehaviour)_unit).IsServer) { _hitPoints = Mathf.Max(0f, _hitPoints - NetDamage(pierceDamage, blastDamage, 1f, fireDamage, impactDamage)); } } private void ReduceHealth(float amount, PersistentID dealerID) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) EnsureHealthInitialised(); _hitPoints -= amount; PayForDamage(amount, dealerID); if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)$"[body] -{amount:F0} hp, {_hitPoints:F0}/{_maxHitPoints:F0} remaining"); } if (!(_hitPoints > 0f)) { _dead = true; _hitPoints = 0f; KaijuNukemPlugin.Log.LogInfo((object)"[body] Kaiju killed"); _unit.Networkdisabled = true; _unit.ReportKilled(); this.OnKaijuKilled?.Invoke(); } } private void PayForDamage(float amount, PersistentID dealerID) { //IL_0029: 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_0061: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0f) { return; } float moneyPer1000Damage = KaijuParamStore.ForUnit(_unit).MoneyPer1000Damage; if (moneyPer1000Damage <= 0f) { return; } _unpaidDamage.TryGetValue(dealerID, out var value); value += amount; float num = Mathf.Floor(value / 1000f); _unpaidDamage[dealerID] = value - num * 1000f; PersistentUnit val = default(PersistentUnit); if (num <= 0f || !UnitRegistry.TryGetPersistentUnit(dealerID, ref val)) { return; } Player val2 = val?.player; if ((Object)(object)val2 == (Object)null) { return; } FactionHQ hQ = val2.HQ; if (!((Object)(object)hQ == (Object)null)) { float num2 = num * moneyPer1000Damage; hQ.RewardPlayer(val2, _unit, num2, num2, (RewardType)0); if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)$"[body] paid ${num2:F0} for {num * 1000f:F0} damage"); } } } public void TakeShockwave(Vector3 origin, float overpressure, float blastPower) { } public void Detach(Vector3 velocity, Vector3 relativePos) { } public ArmorProperties GetArmorProperties() { return _armor; } public Unit GetUnit() { return _unit; } public float GetMass() { if (!((Object)(object)_rb != (Object)null)) { return 1000f; } return _rb.mass; } public Transform GetTransform() { return ((Component)this).transform; } } [DisallowMultipleComponent] public class KaijuBrain : MonoBehaviour { private static readonly int IsWalkingParam = Animator.StringToHash("IsWalking"); private static readonly int AttackParam = Animator.StringToHash("Attack"); private static readonly int RoarParam = Animator.StringToHash("Roar"); private static readonly int AttackStateHash = Animator.StringToHash("Attack"); private const float SwipeWindowStart = 0.35f; private const float SwipeWindowEnd = 0.55f; private Unit _unit; private Rigidbody _rb; private bool _scaleApplied; private bool _bodyMeasured; private float _soleOffsetLocal; private float _bodyHeightLocal; private float _soleOffsetFromCollider; private Renderer[] _renderers; private float _soleSettleAt; private bool _soleLogged; private static bool _loggedKinematicFix; private Animator _animator; private KaijuSwipe _swipe; private KaijuBody _body; private GlobalPosition _destination; private bool _hasDestination; private float _nextTargetRefresh; private const float TargetRefreshSeconds = 2f; private float _nextSwipeTime; private bool _swipeFiredThisAttack; private bool _roared; private bool _destinationSearched; private static readonly Collider[] ProbeBuffer = (Collider[])(object)new Collider[64]; private KaijuParams Tuning => KaijuParamStore.ForUnit(((Object)(object)_unit != (Object)null) ? _unit : (_unit = ((Component)this).GetComponent())); private void EnsureBodyMetrics() { //IL_0032: 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_00c0: 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) if (_bodyMeasured) { return; } _bodyMeasured = true; BoxCollider component = ((Component)this).GetComponent(); if ((Object)(object)component == (Object)null) { KaijuNukemPlugin.Log.LogWarning((object)"[brain] no BoxCollider on the Kaiju root — cannot place its feet on the ground."); return; } _bodyHeightLocal = Mathf.Abs(component.size.y); _soleOffsetLocal = (_soleOffsetFromCollider = _bodyHeightLocal * 0.5f - component.center.y); _renderers = ((Component)this).GetComponentsInChildren(true); SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].updateWhenOffscreen = true; } _soleSettleAt = Time.time + 3f; KaijuNukemPlugin.Log.LogInfo((object)($"[brain] body measured from its collider: {_bodyHeightLocal * ((Component)this).transform.localScale.y:F0} m tall, " + $"pivot {_soleOffsetLocal * ((Component)this).transform.localScale.y:F0} m above the soles.")); } private void RefineSoleOffsetFromPose() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0093: 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_006c: Unknown result type (might be due to invalid IL or missing references) if (_renderers == null || _renderers.Length == 0) { return; } float scale = Tuning.Scale; if (scale <= 0f) { return; } float num = float.MaxValue; Renderer[] renderers = _renderers; foreach (Renderer val in renderers) { if (!((Object)(object)val == (Object)null)) { Bounds bounds = val.bounds; if (((Bounds)(ref bounds)).min.y < num) { bounds = val.bounds; num = ((Bounds)(ref bounds)).min.y; } } } if (num == float.MaxValue) { return; } float num2 = (((Component)this).transform.position.y - num) / scale; if (!(num2 <= 0f) && !(num2 > _bodyHeightLocal)) { _soleOffsetLocal = Mathf.Lerp(_soleOffsetLocal, num2, 0.1f); if (!_soleLogged && !(Time.time < _soleSettleAt)) { _soleLogged = true; KaijuNukemPlugin.Log.LogInfo((object)($"[brain] sole line from the animated pose: pivot {_soleOffsetLocal * scale:F0} m above the " + $"soles (the collider alone said {_soleOffsetFromCollider * scale:F0} m, so the feet were " + $"{(_soleOffsetFromCollider - _soleOffsetLocal) * scale:F0} m off the ground).")); } } } private void HoldGround() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) SetWalking(walking: false); if (!((Object)(object)_rb == (Object)null)) { Vector3 position = ((Component)this).transform.position; position.y = GroundHeight(position); _rb.MovePosition(position); } } private void EnforceKinematicBody() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 if ((Object)(object)_rb == (Object)null) { return; } if (!_rb.isKinematic) { _rb.isKinematic = true; if (!_loggedKinematicFix) { _loggedKinematicFix = true; KaijuNukemPlugin.Log.LogInfo((object)"[brain] Container turned the Kaiju's rigidbody dynamic; forcing it kinematic so terrain depenetration and buoyancy cannot launch it."); } } if ((int)_rb.interpolation != 1) { _rb.interpolation = (RigidbodyInterpolation)1; } if (_rb.useGravity) { _rb.useGravity = false; } } private void ApplyPlacementScaleOnce() { //IL_002b: 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_004a: Unknown result type (might be due to invalid IL or missing references) if (_scaleApplied) { return; } _scaleApplied = true; float scale = Tuning.Scale; if (!(scale <= 0f) && !Mathf.Approximately(((Component)this).transform.localScale.x, scale)) { ((Component)this).transform.localScale = Vector3.one * scale; if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)$"[brain] applied placement scale {scale:F1}x"); } } } private void Awake() { if ((Object)(object)_unit == (Object)null) { _unit = ((Component)this).GetComponent(); } if ((Object)(object)_rb == (Object)null) { _rb = ((Component)this).GetComponent(); } if ((Object)(object)_animator == (Object)null) { _animator = ((Component)this).GetComponentInChildren(); } if ((Object)(object)_swipe == (Object)null) { _swipe = ((Component)this).GetComponent(); } if ((Object)(object)_body == (Object)null) { _body = ((Component)this).GetComponent(); } ConfigureAnimator(); } public void Initialize(Unit unit, Animator animator, KaijuSwipe swipe, KaijuBody body) { _unit = (((Object)(object)unit != (Object)null) ? unit : ((Component)this).GetComponent()); _rb = (((Object)(object)_unit != (Object)null) ? ((Component)_unit).GetComponent() : ((Component)this).GetComponent()); _animator = (((Object)(object)animator != (Object)null) ? animator : ((Component)this).GetComponentInChildren()); _swipe = (((Object)(object)swipe != (Object)null) ? swipe : ((Component)this).GetComponent()); _body = (((Object)(object)body != (Object)null) ? body : ((Component)this).GetComponent()); ConfigureAnimator(); } private void ConfigureAnimator() { if (!((Object)(object)_animator == (Object)null)) { _animator.applyRootMotion = false; _animator.cullingMode = (AnimatorCullingMode)0; } } private void AcquireDestinationIfNeeded() { //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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_007c: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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) if (TryAcquireMissionTarget() || _hasDestination || _destinationSearched) { return; } _destinationSearched = true; MapBuildingSet[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return; } Vector3 position = ((Component)this).transform.position; float num = float.MaxValue; Vector3 val = default(Vector3); bool flag = false; MapBuildingSet[] array2 = array; foreach (MapBuildingSet val2 in array2) { if ((Object)(object)val2 == (Object)null) { continue; } MapBuilding[] componentsInChildren = ((Component)val2).GetComponentsInChildren(false); if (componentsInChildren.Length != 0) { Vector3 val3 = Vector3.zero; MapBuilding[] array3 = componentsInChildren; foreach (MapBuilding val4 in array3) { val3 += ((Component)val4).transform.position; } Vector3 val5 = val3 / (float)componentsInChildren.Length; Vector3 val6 = val5 - position; float sqrMagnitude = ((Vector3)(ref val6)).sqrMagnitude; if (!(sqrMagnitude >= num)) { num = sqrMagnitude; val = val5; flag = true; } } } if (flag) { SetDestination(GlobalPositionExtensions.ToGlobalPosition(val)); KaijuNukemPlugin.Log.LogInfo((object)$"[brain] marching on the nearest settlement, {Mathf.Sqrt(num) / 1000f:F1} km away"); } } private bool TryAcquireMissionTarget() { //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) string targetUnitName = Tuning.TargetUnitName; if (string.IsNullOrEmpty(targetUnitName)) { return false; } if (Time.time < _nextTargetRefresh && _hasDestination) { return true; } _nextTargetRefresh = Time.time + 2f; if (!UnitRegistry.customIDLookup.TryGetValue(targetUnitName, out var value) || (Object)(object)value == (Object)null) { if (!_hasDestination && KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)("[brain] target '" + targetUnitName + "' not in the unit registry yet")); } return _hasDestination; } SetDestination(GlobalPositionExtensions.ToGlobalPosition(((Component)value).transform.position)); return true; } public void SetDestination(GlobalPosition destination) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) _destination = destination; _hasDestination = true; } private void FixedUpdate() { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0111: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_unit == (Object)null || (Object)(object)_body == (Object)null || _body.IsDead) { SetWalking(walking: false); return; } EnforceKinematicBody(); if (!_unit.LocalSim) { return; } ApplyPlacementScaleOnce(); EnsureBodyMetrics(); RefineSoleOffsetFromPose(); KaijuDiagnostics.DumpUnitOnce(_unit, ((Component)this).transform); if (!_roared && (Object)(object)_animator != (Object)null) { _animator.SetTrigger(RoarParam); _roared = true; } TryStrike(); AcquireDestinationIfNeeded(); if (!_hasDestination) { HoldGround(); return; } Vector3 val = GlobalPositionExtensions.ToLocalPosition(_destination); Vector3 position = ((Component)this).transform.position; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(val.x - position.x, 0f, val.z - position.z); float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < Tuning.SwipeRange * 0.5f) { HoldGround(); return; } Vector3 val3 = val2 / magnitude; Quaternion val4 = Quaternion.LookRotation(val3, Vector3.up); Quaternion val5 = Quaternion.RotateTowards(((Component)this).transform.rotation, val4, Tuning.TurnRateDegPerSec * Time.fixedDeltaTime); float num = ((Vector3.Angle(((Component)this).transform.forward, val3) < 45f) ? (Tuning.WalkSpeed * Time.fixedDeltaTime) : 0f); Vector3 val6 = position + ((Component)this).transform.forward * num; val6.y = GroundHeight(val6); _rb.MoveRotation(val5); _rb.MovePosition(val6); SetWalking(num > 0f); } private float GroundHeight(Vector3 at) { //IL_0006: 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_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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_005d: 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) float localSeaY = Datum.LocalSeaY; Vector3 val = at + Vector3.up * 6000f; Vector3 val2 = at - Vector3.up * 6000f; float num = KaijuConfig.WadeDepthFraction.Value * _bodyHeightLocal * Tuning.Scale; float value = KaijuConfig.GroundOffset.Value; RaycastHit val3 = default(RaycastHit); float num2 = (Physics.Linecast(val, val2, ref val3, LayerMask.op_Implicit(PhysicsLayers.StaticsMask)) ? Mathf.Max(((RaycastHit)(ref val3)).point.y, localSeaY - num) : (localSeaY - num)); float num3 = num2 + value + _soleOffsetLocal * Tuning.Scale; if (KaijuConfig.VerboseLogging.Value && Time.frameCount % 120 == 0) { KaijuNukemPlugin.Log.LogInfo((object)$"[brain] soles y={num2:F1} seaY={localSeaY:F1} wade={num:F1} offset={value:F1} -> pivot y={num3:F1}"); } return num3; } private void SetWalking(bool walking) { if ((Object)(object)_animator != (Object)null) { _animator.SetBool(IsWalkingParam, walking); } } private void TryStrike() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_animator == (Object)null || (Object)(object)_swipe == (Object)null) { return; } AnimatorStateInfo currentAnimatorStateInfo = _animator.GetCurrentAnimatorStateInfo(0); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash == AttackStateHash) { float num = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime % 1f; if (!_swipeFiredThisAttack && num >= 0.35f && num <= 0.55f) { _swipeFiredThisAttack = true; _swipe.Strike(); } } else { _swipeFiredThisAttack = false; if (!(Time.time < _nextSwipeTime) && AnythingWorthHitting()) { _nextSwipeTime = Time.time + Tuning.SwipeCooldown; _animator.SetTrigger(AttackParam); } } } private bool AnythingWorthHitting() { //IL_0012: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) float swipeRange = Tuning.SwipeRange; int num = Physics.OverlapSphereNonAlloc(((Component)this).transform.position + ((Component)this).transform.forward * (swipeRange * 0.5f), swipeRange, ProbeBuffer, ~LayerMask.op_Implicit(PhysicsLayers.ExclusionZonesMask)); IDamageable val2 = default(IDamageable); for (int i = 0; i < num; i++) { Collider val = ProbeBuffer[i]; if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.TryGetComponent(ref val2) && val2.GetUnit() != _unit) { return true; } } return false; } } public static class KaijuConfig { public static ConfigEntry Enabled; public static ConfigEntry AutoSpawn; public static ConfigEntry WadeDepthFraction; public static ConfigEntry GroundOffset; public static ConfigEntry SpawnDistanceFromPlayer; public static ConfigEntry SpawnDistanceFromShore; public static ConfigEntry KaijuScale; public static ConfigEntry WalkSpeed; public static ConfigEntry TurnRateDegPerSec; public static ConfigEntry Health; public static ConfigEntry SwipeRange; public static ConfigEntry SwipeArcDegrees; public static ConfigEntry SwipeDamage; public static ConfigEntry SwipeCooldown; public static ConfigEntry RoundDamageScale; public static ConfigEntry BlastDamageScale; public static ConfigEntry MoneyPer1000Damage; public static ConfigEntry VerboseLogging; public static void Bind(ConfigFile cfg) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Expected O, but got Unknown //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Expected O, but got Unknown //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Expected O, but got Unknown //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Expected O, but got Unknown //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Expected O, but got Unknown Enabled = cfg.Bind("Master", "Enabled", true, "Master switch. When false the mod does nothing at all."); AutoSpawn = cfg.Bind("Master", "AutoSpawn", false, "Spawn a Kaiju automatically on any mission. Off by design — the Kaiju is meant to be placed deliberately in the Mission Editor, not to gatecrash every flight. Turn it on only to test the creature without authoring a mission. A Kaiju spawned this way is not registered under a UniqueName, so mission objectives cannot target it — testing objective wiring needs an editor-placed Kaiju."); GroundOffset = cfg.Bind("Placement", "GroundOffset", 0f, new ConfigDescription("Vertical correction in metres, applied on land AND water. Leave this at 0: the Kaiju's feet are now placed from its own collider, which the prefab authors to enclose the model exactly, so the geometry is already right. It stays here only to nudge art that sits slightly off its own bounds. Negative sinks it, positive raises it.", (AcceptableValueBase)(object)new AcceptableValueRange(-500f, 500f), Array.Empty())); WadeDepthFraction = cfg.Bind("Placement", "WadeDepthFraction", 0.22f, new ConfigDescription("How deep the Kaiju sinks when standing in water, as a fraction of its full height. 0 walks on the surface; 0.22 is roughly thigh-deep. It still stands properly on land, and never sinks below the actual seabed in shallow water. Keep it well under 1.0 — the game discards weapon hits below sea level as splashes, so a submerged Kaiju is progressively harder to shoot.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.9f), Array.Empty())); SpawnDistanceFromPlayer = cfg.Bind("Scenario", "SpawnDistanceFromPlayer", 8000f, new ConfigDescription("Metres from your own airbase that the Kaiju surfaces. Kept short on purpose so it is a quick flight away rather than somewhere unfindable on the map.", (AcceptableValueBase)(object)new AcceptableValueRange(500f, 60000f), Array.Empty())); SpawnDistanceFromShore = cfg.Bind("Scenario", "SpawnDistanceFromShore", 3000f, new ConfigDescription("Metres out to sea the Kaiju surfaces, measured from its target on land.", (AcceptableValueBase)(object)new AcceptableValueRange(200f, 20000f), Array.Empty())); KaijuScale = cfg.Bind("Scenario", "KaijuScale", 300f, new ConfigDescription("Uniform scale applied to the Synty prefab, which is authored at roughly 2.5 m. 300 gives a creature about 755 m tall — properly kaiju-sized against aircraft. Collider and wade depth scale with it; the movement and swipe defaults below are tuned for this value, so raise them together if you go much larger.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 1000f), Array.Empty())); WalkSpeed = cfg.Bind("Movement", "WalkSpeed", 120f, new ConfigDescription("Ground speed in metres per second while advancing on the target.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 500f), Array.Empty())); TurnRateDegPerSec = cfg.Bind("Movement", "TurnRateDegPerSec", 10f, new ConfigDescription("How fast the Kaiju can yaw toward its target. Low values read as heavy.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 180f), Array.Empty())); Health = cfg.Bind("Combat", "Health", 20000f, new ConfigDescription("Total damage the Kaiju absorbs before it dies. Whether that kill ends the mission is decided by the mission's own objectives, not by this mod.", (AcceptableValueBase)(object)new AcceptableValueRange(100f, 1000000f), Array.Empty())); SwipeRange = cfg.Bind("Combat", "SwipeRange", 700f, new ConfigDescription("Reach of the left-hand swipe, in metres from the Kaiju's centre.", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 5000f), Array.Empty())); SwipeArcDegrees = cfg.Bind("Combat", "SwipeArcDegrees", 120f, new ConfigDescription("Total width of the swipe arc. Anything destructible inside the arc and within range is hit.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 360f), Array.Empty())); SwipeDamage = cfg.Bind("Combat", "SwipeDamage", 5000f, new ConfigDescription("Damage applied to each entity caught in the swipe.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100000f), Array.Empty())); SwipeCooldown = cfg.Bind("Combat", "SwipeCooldown", 6f, new ConfigDescription("Seconds between swipes.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 60f), Array.Empty())); RoundDamageScale = cfg.Bind("Combat", "RoundDamageScale", 0.5f, new ConfigDescription("How much damage GUN ROUNDS do to the Kaiju, as a multiplier. 1 is vanilla, 0.5 halves it, 0 makes it immune to guns. Rounds are the one weapon the game does not scale by target size, so against a creature this large they are worth far more per second than anything else a pilot can carry — this is the dial that puts cannon back in proportion with ordnance.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 2f), Array.Empty())); BlastDamageScale = cfg.Bind("Combat", "BlastDamageScale", 25f, new ConfigDescription("How much damage BLAST does to the Kaiju — bombs, rockets and missile warheads — as a multiplier. Far above 1 on purpose, and it is a correction rather than a buff: the game scales blast by how much of the target the explosion engulfs, so a creature with a ~261 m mean extent absorbs roughly a fiftieth of what a tank would take, purely for being big. At 1 a direct bomb hit is worth about four cannon rounds. Raise it if bombing still feels pointless.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 200f), Array.Empty())); MoneyPer1000Damage = cfg.Bind("Rewards", "MoneyPer1000Damage", 100f, new ConfigDescription("Default payout, in dollars, per 1000 points of damage a pilot deals to a Kaiju. This is only the starting value for a NEW placement — each Kaiju placed in the Mission Editor owns its own rate, so changing this does not alter existing missions.", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 1000f), Array.Empty())); VerboseLogging = cfg.Bind("Diagnostics", "VerboseLogging", false, "Log per-step scenario state. Noisy; for diagnosing a Kaiju that will not spawn or move."); } } internal static class KaijuDiagnostics { private static bool _dumpedUnit; private static bool _dumpedObjective; private static bool _dumpedPercent; public static void DumpUnitOnce(Unit unit, Transform root) { //IL_0039: 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_0065: 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_00ba: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) if (_dumpedUnit || (Object)(object)unit == (Object)null || (Object)(object)root == (Object)null) { return; } _dumpedUnit = true; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("[diag] ===== KAIJU UNIT ====="); stringBuilder.AppendLine($"[diag] transform.position = {root.position} (y={root.position.y:F1})"); stringBuilder.AppendLine($"[diag] localScale = {root.localScale}"); stringBuilder.AppendLine($"[diag] seaY = {Datum.LocalSeaY:F1}"); BoxCollider component = ((Component)root).GetComponent(); Bounds bounds; if ((Object)(object)component != (Object)null) { stringBuilder.AppendLine($"[diag] box.center(local) = {component.center} size={component.size}"); bounds = ((Collider)component).bounds; object arg = ((Bounds)(ref bounds)).min.y; bounds = ((Collider)component).bounds; object arg2 = ((Bounds)(ref bounds)).center.y; bounds = ((Collider)component).bounds; stringBuilder.AppendLine($"[diag] box.bounds(world) = min.y {arg:F1} / centre.y {arg2:F1} / max.y {((Bounds)(ref bounds)).max.y:F1}"); } else { stringBuilder.AppendLine("[diag] NO BoxCollider on the root"); } Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); if (componentsInChildren.Length != 0) { Bounds bounds2 = componentsInChildren[0].bounds; Renderer[] array = componentsInChildren; foreach (Renderer val in array) { ((Bounds)(ref bounds2)).Encapsulate(val.bounds); } stringBuilder.AppendLine($"[diag] model bounds(world) = min.y {((Bounds)(ref bounds2)).min.y:F1} / max.y {((Bounds)(ref bounds2)).max.y:F1} (height {((Bounds)(ref bounds2)).size.y:F0} m, {componentsInChildren.Length} renderers)"); if ((Object)(object)component != (Object)null) { float y = ((Bounds)(ref bounds2)).min.y; bounds = ((Collider)component).bounds; float num = y - ((Bounds)(ref bounds)).min.y; bounds = ((Collider)component).bounds; float num2 = ((Bounds)(ref bounds)).max.y - ((Bounds)(ref bounds2)).max.y; stringBuilder.AppendLine($"[diag] model vs collider = feet {num:F1} m, head {num2:F1} m " + "(both near 0 = collider wraps the creature; large = something is misaligned)"); } Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(((Bounds)(ref bounds2)).center.x, ((Bounds)(ref bounds2)).min.y + 10f, ((Bounds)(ref bounds2)).center.z); RaycastHit val3 = default(RaycastHit); stringBuilder.AppendLine(Physics.Linecast(val2, val2 - Vector3.up * 12000f, ref val3, LayerMask.op_Implicit(PhysicsLayers.StaticsMask)) ? $"[diag] feet above ground = {((Bounds)(ref bounds2)).min.y - ((RaycastHit)(ref val3)).point.y:F1} m (ground '{((Object)((RaycastHit)(ref val3)).collider).name}' y={((RaycastHit)(ref val3)).point.y:F1})" : $"[diag] feet above ground = no terrain below; sea is at y={Datum.LocalSeaY:F1}"); } else { stringBuilder.AppendLine("[diag] NO Renderers under the root"); } UnitDefinition definition = unit.definition; if ((Object)(object)definition != (Object)null) { stringBuilder.AppendLine($"[diag] definition dims = L {definition.length:F0} W {definition.width:F0} H {definition.height:F0}"); stringBuilder.AppendLine($"[diag] definition.jsonKey = {definition.jsonKey} iconSize={definition.iconSize}"); } else { stringBuilder.AppendLine("[diag] unit.definition IS NULL <-- maxRadius would stay 0"); } stringBuilder.AppendLine($"[diag] unit.maxRadius = {unit.maxRadius:F1} (missiles aim at transform.position when < 20)"); stringBuilder.AppendLine("[diag] unit.SavedUnit = " + ((unit.SavedUnit != null) ? ("'" + unit.SavedUnit.UniqueName + "' type=" + unit.SavedUnit.type) : "NULL <-- per-placement values cannot resolve")); bool flag = unit.SavedUnit != null && UnitRegistry.customIDLookup.ContainsKey(unit.SavedUnit.UniqueName); stringBuilder.AppendLine($"[diag] in customIDLookup = {flag} (objectives resolve targets through this)"); KaijuBody component2 = ((Component)root).GetComponent(); stringBuilder.AppendLine(((Object)(object)component2 != (Object)null) ? $"[diag] KaijuBody hp = {component2.HitPoints:F0} fraction={component2.HealthFraction:F3}" : "[diag] NO KaijuBody on the root"); stringBuilder.Append("[diag] ======================"); KaijuNukemPlugin.Log.LogInfo((object)stringBuilder.ToString()); } public static void DumpObjectiveOnce(string objectiveName, List items) { if (_dumpedObjective) { return; } _dumpedObjective = true; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("[diag] ===== DESTROY OBJECTIVE ====="); stringBuilder.AppendLine($"[diag] objective '{objectiveName}' targets={items?.Count ?? (-1)}"); if (items != null) { foreach (SavedUnit item in items) { if (item == null) { stringBuilder.AppendLine("[diag] "); continue; } Unit value; bool flag = UnitRegistry.customIDLookup.TryGetValue(item.UniqueName, out value); KaijuBody kaijuBody = ((flag && (Object)(object)value != (Object)null) ? ((Component)value).GetComponent() : null); stringBuilder.AppendLine($"[diag] '{item.UniqueName}' type={item.type} isKaiju={KaijuParamStore.IsKaiju(item)} " + $"inRegistry={flag} live={(Object)(object)value != (Object)null} body={(Object)(object)kaijuBody != (Object)null} " + "frac=" + (((Object)(object)kaijuBody != (Object)null) ? kaijuBody.HealthFraction.ToString("F3") : "-")); } } stringBuilder.Append("[diag] ============================="); KaijuNukemPlugin.Log.LogInfo((object)stringBuilder.ToString()); } public static void DumpPercentOnce(float ours, float vanilla) { if (!_dumpedPercent) { _dumpedPercent = true; KaijuNukemPlugin.Log.LogInfo((object)$"[diag] percentage hook REACHED: vanilla={vanilla:F3} ours={ours:F3}"); } } } internal class KaijuHealthBar : MonoBehaviour { private const float BarWidth = 900f; private const float BarHeight = 26f; private const float TopMargin = 90f; private const int SortingOrder = 5000; private Canvas _canvas; private CanvasGroup _group; private RectTransform _fill; private Image _fillImage; private TextMeshProUGUI _label; private static readonly Color BackColor = new Color(0f, 0f, 0f, 0.55f); private static readonly Color HealthyColor = new Color(0.85f, 0.25f, 0.18f, 0.95f); private static readonly Color HurtColor = new Color(0.95f, 0.65f, 0.1f, 0.95f); public static KaijuHealthBar Install(GameObject host) { return host.AddComponent(); } private void Awake() { BuildUi(); SetVisible(visible: false); } private void BuildUi() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_005d: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_0186: 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_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("KaijuNukem.HealthBar"); val.transform.SetParent(((Component)this).transform, false); _canvas = val.AddComponent(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 5000; CanvasScaler obj = val.AddComponent(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); obj.matchWidthOrHeight = 0.5f; _group = val.AddComponent(); _group.interactable = false; _group.blocksRaycasts = false; RectTransform val2 = NewRect("Root", val.transform); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 1f); val2.anchorMax = val3; val2.anchorMin = val3; val2.pivot = new Vector2(0.5f, 1f); val2.anchoredPosition = new Vector2(0f, -90f); val2.sizeDelta = new Vector2(900f, 26f); ((Graphic)((Component)val2).gameObject.AddComponent()).color = BackColor; RectTransform val4 = NewRect("Fill", (Transform)(object)val2); val4.anchorMin = new Vector2(0f, 0f); val4.anchorMax = new Vector2(1f, 1f); val4.pivot = new Vector2(0f, 0.5f); val4.offsetMin = new Vector2(2f, 2f); val4.offsetMax = new Vector2(-2f, -2f); _fill = val4; _fillImage = ((Component)val4).gameObject.AddComponent(); ((Graphic)_fillImage).color = HealthyColor; RectTransform val5 = NewRect("Label", (Transform)(object)val2); val5.anchorMin = new Vector2(0f, 0f); val5.anchorMax = new Vector2(1f, 1f); val5.offsetMin = Vector2.zero; val5.offsetMax = Vector2.zero; _label = ((Component)val5).gameObject.AddComponent(); ((TMP_Text)_label).alignment = (TextAlignmentOptions)514; ((TMP_Text)_label).fontSize = 17f; ((Graphic)_label).color = Color.white; ((Graphic)_label).raycastTarget = false; ((TMP_Text)_label).text = ""; } private static RectTransform NewRect(string name, Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); return (RectTransform)val.transform; } private void Update() { //IL_003b: 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_0053: Unknown result type (might be due to invalid IL or missing references) KaijuBody kaijuBody = PickTarget(); if ((Object)(object)kaijuBody == (Object)null) { SetVisible(visible: false); return; } SetVisible(visible: true); float num = Mathf.Clamp01(kaijuBody.HealthFraction); ((Transform)_fill).localScale = new Vector3(num, 1f, 1f); ((Graphic)_fillImage).color = ((num > 0.35f) ? HealthyColor : HurtColor); ((TMP_Text)_label).text = $"{kaijuBody.DisplayName} {100f * num:F0}% ({kaijuBody.HitPoints:N0} HP)"; } private static KaijuBody PickTarget() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (KaijuBody.Live.Count == 0) { return null; } Aircraft val = default(Aircraft); if (!GameManager.GetLocalAircraft(ref val) || (Object)(object)val == (Object)null) { return null; } WeaponManager weaponManager = val.weaponManager; if ((Object)(object)weaponManager == (Object)null) { return null; } KaijuBody result = null; float num = float.MaxValue; Vector3 position = ((Component)val).transform.position; for (int i = 0; i < KaijuBody.Live.Count; i++) { KaijuBody kaijuBody = KaijuBody.Live[i]; if ((Object)(object)kaijuBody == (Object)null || kaijuBody.IsDead) { continue; } Unit unit = kaijuBody.GetUnit(); if (!((Object)(object)unit == (Object)null) && weaponManager.CheckIsTarget(unit)) { Vector3 val2 = ((Component)kaijuBody).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude >= num)) { num = sqrMagnitude; result = kaijuBody; } } } return result; } private void SetVisible(bool visible) { if ((Object)(object)_group != (Object)null) { _group.alpha = (visible ? 1f : 0f); } } } public class KaijuHost : MonoBehaviour { private bool _spawned; public static KaijuHost Install() { //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) //IL_0010: Expected O, but got Unknown //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown GameObject val = new GameObject("KaijuNukem.Host"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; KaijuHealthBar.Install(val); return val.AddComponent(); } private void Start() { ((MonoBehaviour)this).StartCoroutine(KaijuRegistry.RegisterWhenReady()); ((MonoBehaviour)this).StartCoroutine(RunTestSpawnerWhenReady()); } private IEnumerator RunTestSpawnerWhenReady() { FactionHQ val = default(FactionHQ); while (!_spawned) { yield return (object)new WaitForSeconds(2f); if (!KaijuConfig.Enabled.Value || !KaijuConfig.AutoSpawn.Value) { continue; } NetworkManagerNuclearOption i = NetworkManagerNuclearOption.i; if ((Object)(object)i == (Object)null || !((NetworkManager)i).Server.Active || (Object)(object)Datum.origin == (Object)null || (Object)(object)NetworkSceneSingleton.i == (Object)null) { continue; } if (!GameManager.GetLocalHQ(ref val) || (Object)(object)val == (Object)null) { if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)"[testspawn] waiting for the player to join a faction"); } } else { TryTestSpawn(); } } } private void TryTestSpawn() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_009e: 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) if (!TryFindCity(out var city)) { if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)"[testspawn] no building cluster found yet, waiting"); } return; } GlobalPosition anchor; GlobalPosition val = (TryFindPlayerAnchor(out anchor) ? anchor : city); if (!TryFindSeaSpawn(val, out var sea)) { KaijuNukemPlugin.Log.LogWarning((object)"[testspawn] could not find open water near the spawn anchor"); } else if (!((Object)(object)KaijuSpawner.Spawn(sea, city) == (Object)null)) { _spawned = true; Vector3 val2 = GlobalPositionExtensions.ToLocalPosition(val); Vector3 val3 = GlobalPositionExtensions.ToLocalPosition(sea); Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(val3.x - val2.x, 0f, val3.z - val2.z); float num = Mathf.Repeat(Mathf.Atan2(val4.x, val4.z) * 57.29578f, 360f); KaijuNukemPlugin.Log.LogInfo((object)($"[testspawn] test Kaiju — bearing {num:F0}° at {((Vector3)(ref val4)).magnitude / 1000f:F1} km " + "from you, heading for the city.")); } } private static bool TryFindPlayerAnchor(out GlobalPosition anchor) { //IL_008a: 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_0023: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) Aircraft val = default(Aircraft); if (GameManager.GetLocalAircraft(ref val) && (Object)(object)val != (Object)null) { anchor = GlobalPositionExtensions.ToGlobalPosition(((Component)val).transform.position); return true; } FactionHQ val2 = default(FactionHQ); if (GameManager.GetLocalHQ(ref val2) && (Object)(object)val2 != (Object)null) { foreach (Airbase airbasis in val2.GetAirbases()) { if (!((Object)(object)airbasis == (Object)null)) { anchor = GlobalPositionExtensions.ToGlobalPosition(((Component)airbasis).transform.position); return true; } } } anchor = default(GlobalPosition); return false; } private static bool TryFindCity(out GlobalPosition city) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) city = default(GlobalPosition); MapBuildingSet[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return false; } MapBuildingSet val = null; int num = 0; MapBuildingSet[] array2 = array; foreach (MapBuildingSet val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { int num2 = ((Component)val2).GetComponentsInChildren(false).Length; if (num2 > num) { num = num2; val = val2; } } } if ((Object)(object)val == (Object)null || num == 0) { return false; } Vector3 val3 = Vector3.zero; int num3 = 0; MapBuilding[] componentsInChildren = ((Component)val).GetComponentsInChildren(false); foreach (MapBuilding val4 in componentsInChildren) { if (!((Object)(object)val4 == (Object)null)) { val3 += ((Component)val4).transform.position; num3++; } } if (num3 == 0) { return false; } city = GlobalPositionExtensions.ToGlobalPosition(val3 / (float)num3); if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)$"[testspawn] target city: {((Object)val).name}, {num} buildings"); } return true; } private static bool TryFindSeaSpawn(GlobalPosition anchor, out GlobalPosition sea) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) Vector3 val = GlobalPositionExtensions.ToLocalPosition(anchor); float value = KaijuConfig.SpawnDistanceFromPlayer.Value; for (int i = 0; i < 3; i++) { float num = value * (1f - (float)i * 0.25f); for (int j = 0; j < 360; j += 15) { float num2 = (float)j * (MathF.PI / 180f); Vector3 val2 = val + new Vector3(Mathf.Sin(num2) * num, 0f, Mathf.Cos(num2) * num); val2.y = Datum.LocalSeaY; if (IsOpenWater(val2)) { sea = GlobalPositionExtensions.ToGlobalPosition(val2); return true; } } } sea = default(GlobalPosition); return false; } private static bool IsOpenWater(Vector3 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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_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_0016: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Vector3 val = p + Vector3.up * 1000f; Vector3 val2 = p - Vector3.up * 1000f; RaycastHit val3 = default(RaycastHit); if (!Physics.Linecast(val, val2, ref val3, LayerMask.op_Implicit(PhysicsLayers.StaticsMask))) { return true; } return ((RaycastHit)(ref val3)).point.y < Datum.LocalSeaY; } } internal class KaijuContainerConverter : JsonConverter { private const string PropertyName = "kaijuParams"; [ThreadStatic] private static bool _isWriting; public override bool CanWrite => !_isWriting; public override void WriteJson(JsonWriter writer, SavedContainer value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } _isWriting = true; try { JObject val = JObject.FromObject((object)value, serializer); if (KaijuParamStore.IsKaiju((SavedUnit)(object)value) && KaijuParamStore.TryGet((SavedUnit)(object)value, out var parameters) && parameters != null) { val["kaijuParams"] = (JToken)(object)JObject.FromObject((object)parameters, serializer); } ((JToken)val).WriteTo(writer, Array.Empty()); } finally { _isWriting = false; } } public override SavedContainer ReadJson(JsonReader reader, Type objectType, SavedContainer existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if ((int)reader.TokenType == 11) { return null; } JObject val = JObject.Load(reader); JToken val2 = val["kaijuParams"]; if (val2 != null) { val.Remove("kaijuParams"); } SavedContainer val3 = (SavedContainer)((hasExistingValue && existingValue != null) ? ((object)existingValue) : ((object)new SavedContainer())); JsonReader val4 = ((JToken)val).CreateReader(); try { serializer.Populate(val4, (object)val3); } finally { ((IDisposable)val4)?.Dispose(); } if (val2 != null) { try { KaijuParams kaijuParams = val2.ToObject(serializer); if (kaijuParams != null) { KaijuParamStore.Set((SavedUnit)(object)val3, kaijuParams); } } catch (Exception ex) { KaijuNukemPlugin.Log.LogWarning((object)("[mission] ignoring unreadable kaijuParams on container '" + ((SavedUnit)val3).UniqueName + "': " + ex.GetType().Name + ": " + ex.Message)); } } return val3; } } public static class KaijuMissionSerialization { private static bool _installed; public static void Install() { if (_installed) { return; } try { JsonSerializerSettings val = NewtonsoftHelper.Default; if (((val != null) ? val.Converters : null) == null) { KaijuNukemPlugin.Log.LogError((object)"[mission] NewtonsoftHelper.Default has no converter list — per-placement Kaiju values will not be saved into missions."); _installed = true; return; } foreach (JsonConverter converter in val.Converters) { if (converter is KaijuContainerConverter) { _installed = true; return; } } val.Converters.Add((JsonConverter)(object)new KaijuContainerConverter()); _installed = true; KaijuNukemPlugin.Log.LogInfo((object)"[mission] per-placement Kaiju parameters will be saved into mission.json."); } catch (Exception ex) { _installed = true; KaijuNukemPlugin.Log.LogError((object)("[mission] could not install the mission converter (" + ex.GetType().Name + ": " + ex.Message + ") — Kaiju parameters will be editable but will not persist.")); } } } [BepInPlugin("hendev.kaijunukem", "KaijuNukem", "1.0.0")] public class KaijuNukemPlugin : BaseUnityPlugin { public const string Guid = "hendev.kaijunukem"; public const string Name = "KaijuNukem"; public const string Version = "1.0.0"; public static KaijuNukemPlugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; KaijuConfig.Bind(((BaseUnityPlugin)this).Config); if (!KaijuConfig.Enabled.Value) { Log.LogInfo((object)"KaijuNukem 1.0.0 loaded but disabled by config."); return; } if (!KaijuAssets.Load(Log)) { Log.LogError((object)"KaijuNukem 1.0.0 could not load its assets — the Kaiju will not run."); return; } KaijuHost.Install(); KaijuMissionSerialization.Install(); KaijuUnitPanelInfo.Apply(); KaijuObjectiveProgress.Apply(); Log.LogInfo((object)"KaijuNukem 1.0.0 loaded."); } } internal static class KaijuObjectiveProgress { private const string PatchId = "hendev.kaijunukem.objectiveprogress"; private static bool _patched; private static bool _loggedFailure; private static FieldInfo _allItemsField; public static void Apply() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown if (_patched) { return; } try { MethodInfo methodInfo = AccessTools.Method(typeof(ObjectiveInfoList_ObjEntry), "Refresh", (Type[])null, (Type[])null); if (methodInfo == null) { KaijuNukemPlugin.Log.LogWarning((object)"[objective] ObjectiveInfoList_ObjEntry.Refresh not found — the Kaiju damage percentage is disabled. The objective itself still works normally."); _patched = true; return; } _allItemsField = AccessTools.Field(typeof(DestroyUnitObjective), "allItems"); new Harmony("hendev.kaijunukem.objectiveprogress").Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(KaijuObjectiveProgress), "RefreshPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _patched = true; KaijuNukemPlugin.Log.LogInfo((object)"[objective] Kaiju destroy-objectives will show live damage progress."); } catch (Exception ex) { _patched = true; KaijuNukemPlugin.Log.LogError((object)("[objective] could not patch the objective HUD (" + ex.GetType().Name + ": " + ex.Message + ") — continuing without the damage percentage.")); } } private static void RefreshPostfix(ObjectiveInfoList_ObjEntry __instance, Objective obj) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 try { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.OBJ_Complete == (Object)null) { return; } DestroyUnitObjective val = (DestroyUnitObjective)(object)((obj is DestroyUnitObjective) ? obj : null); if (val != null) { if (_allItemsField != null && _allItemsField.GetValue(val) is List items) { KaijuDiagnostics.DumpObjectiveOnce(((Objective)val).SavedObjective?.DisplayName ?? "?", items); } if ((int)obj.Status != 2 && TryDamagePercent(val, out var percent)) { KaijuDiagnostics.DumpPercentOnce(percent, obj.CompletePercent); ((TMP_Text)__instance.OBJ_Complete).text = $"{100f * percent:F0}%"; } } } catch (Exception ex) { if (!_loggedFailure) { _loggedFailure = true; KaijuNukemPlugin.Log.LogError((object)("[objective] damage percentage failed and is now inert (" + ex.GetType().Name + ": " + ex.Message + "). The objective HUD is otherwise unaffected.")); } } } private static bool TryDamagePercent(DestroyUnitObjective destroy, out float percent) { percent = 0f; if (destroy == null || _allItemsField == null) { return false; } if (!(_allItemsField.GetValue(destroy) is List { Count: not 0 } list)) { return false; } float num = 0f; int num2 = 0; bool flag = false; foreach (SavedUnit item in list) { if (item != null) { if (KaijuParamStore.IsKaiju(item)) { flag = true; num += DamageFraction(item); } else { num += (IsDead(item) ? 1f : 0f); } num2++; } } if (!flag || num2 == 0) { return false; } percent = Mathf.Clamp01(num / (float)num2); return true; } private static float DamageFraction(SavedUnit saved) { if (IsDead(saved)) { return 1f; } if (!UnitRegistry.customIDLookup.TryGetValue(saved.UniqueName, out var value) || (Object)(object)value == (Object)null) { return 0f; } KaijuBody component = ((Component)value).GetComponent(); if ((Object)(object)component == (Object)null) { return 0f; } return Mathf.Clamp01(1f - component.HealthFraction); } private static bool IsDead(SavedUnit saved) { if (UnitRegistry.customIDLookup.TryGetValue(saved.UniqueName, out var value)) { if (!((Object)(object)value == (Object)null)) { return value.disabled; } return true; } return false; } } public class KaijuParams { public float Health; public float Scale; public float WalkSpeed; public float TurnRateDegPerSec; public float SwipeRange; public float SwipeArcDegrees; public float SwipeDamage; public float SwipeCooldown; public string TargetUnitName = ""; public float MoneyPer1000Damage = 100f; public float RoundDamageScale = 0.5f; public float BlastDamageScale = 25f; public static KaijuParams Defaults() { return new KaijuParams { Health = Cfg(KaijuConfig.Health, 20000f), Scale = Cfg(KaijuConfig.KaijuScale, 300f), WalkSpeed = Cfg(KaijuConfig.WalkSpeed, 120f), TurnRateDegPerSec = Cfg(KaijuConfig.TurnRateDegPerSec, 10f), SwipeRange = Cfg(KaijuConfig.SwipeRange, 700f), SwipeArcDegrees = Cfg(KaijuConfig.SwipeArcDegrees, 120f), SwipeDamage = Cfg(KaijuConfig.SwipeDamage, 5000f), SwipeCooldown = Cfg(KaijuConfig.SwipeCooldown, 6f), TargetUnitName = "", MoneyPer1000Damage = Cfg(KaijuConfig.MoneyPer1000Damage, 100f), RoundDamageScale = Cfg(KaijuConfig.RoundDamageScale, 0.5f), BlastDamageScale = Cfg(KaijuConfig.BlastDamageScale, 25f) }; } private static float Cfg(ConfigEntry entry, float fallback) { return entry?.Value ?? fallback; } public KaijuParams Clone() { return (KaijuParams)MemberwiseClone(); } } public static class KaijuParamStore { private static readonly ConditionalWeakTable _byUnit = new ConditionalWeakTable(); public static bool IsKaiju(SavedUnit saved) { if (saved != null) { return saved.type == "kaiju_nukem"; } return false; } public static KaijuParams Get(SavedUnit saved) { if (saved == null) { return KaijuParams.Defaults(); } return _byUnit.GetValue(saved, (SavedUnit _) => KaijuParams.Defaults()); } public static bool TryGet(SavedUnit saved, out KaijuParams parameters) { parameters = null; if (saved != null) { return _byUnit.TryGetValue(saved, out parameters); } return false; } public static void Set(SavedUnit saved, KaijuParams parameters) { if (saved != null && parameters != null) { _byUnit.Remove(saved); _byUnit.Add(saved, parameters); } } public static KaijuParams ForUnit(Unit unit) { if ((Object)(object)unit == (Object)null) { return KaijuParams.Defaults(); } SavedUnit savedUnit = unit.SavedUnit; if (savedUnit == null) { return KaijuParams.Defaults(); } return Get(savedUnit); } } public static class KaijuRegistry { private const int KaijuPrefabHash = 1262569802; public const string JsonKey = "kaiju_nukem"; public static bool Registered { get; private set; } public static IEnumerator RegisterWhenReady() { while (!Registered) { yield return (object)new WaitForSeconds(1f); if (!((Object)(object)Encyclopedia.i == (Object)null) && Encyclopedia.Lookup != null) { TryRegister(); } } } private static void TryRegister() { UnitDefinition kaijuDefinition = KaijuAssets.KaijuDefinition; if ((Object)(object)kaijuDefinition == (Object)null) { KaijuNukemPlugin.Log.LogError((object)"[registry] no KaijuDefinition in the bundle — not registering"); Registered = true; return; } if (Encyclopedia.Lookup.ContainsKey("kaiju_nukem")) { Registered = true; return; } if ((Object)(object)kaijuDefinition.unitPrefab == (Object)null) { Abort("definition has no unitPrefab"); return; } NetworkIdentity component = kaijuDefinition.unitPrefab.GetComponent(); if ((Object)(object)component == (Object)null) { Abort("prefab has no NetworkIdentity — refusing to inject"); return; } if ((Object)(object)kaijuDefinition.unitPrefab.GetComponent() == (Object)null) { Abort("prefab has no Unit component (expected Container) — refusing to inject"); return; } if (HashCollides(1262569802)) { Abort($"prefab hash 0x{1262569802:X} already used by a vanilla prefab"); return; } try { component.PrefabHash = 1262569802; kaijuDefinition.jsonKey = "kaiju_nukem"; if (kaijuDefinition.mass <= 0f) { kaijuDefinition.mass = 500000f; } EnsureDimensions(kaijuDefinition); BorrowIcons(kaijuDefinition); Encyclopedia.i.otherUnits.Add(kaijuDefinition); Encyclopedia.Lookup.Add("kaiju_nukem", kaijuDefinition); ((INetworkDefinition)kaijuDefinition).LookupIndex = Encyclopedia.i.IndexLookup.Count; Encyclopedia.i.IndexLookup.Add((INetworkDefinition)(object)kaijuDefinition); Registered = true; KaijuNukemPlugin.Log.LogInfo((object)(string.Format("[registry] Kaiju registered as '{0}' (index {1}) ", "kaiju_nukem", ((INetworkDefinition)kaijuDefinition).LookupIndex) + "— it should now appear in the Mission Editor under Other Units.")); } catch (Exception ex) { Encyclopedia.i.otherUnits.Remove(kaijuDefinition); Encyclopedia.Lookup.Remove("kaiju_nukem"); Encyclopedia.i.IndexLookup.Remove((INetworkDefinition)(object)kaijuDefinition); Abort("injection threw and was rolled back: " + ex.GetType().Name + ": " + ex.Message); } } private static void Abort(string reason) { Registered = true; KaijuNukemPlugin.Log.LogError((object)("[registry] NOT registering the Kaiju: " + reason + ". The Mission Editor will not list it; enable Master/AutoSpawn to test the creature via the legacy spawner instead.")); } private static void EnsureDimensions(UnitDefinition def) { //IL_0041: 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_0049: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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) BoxCollider component = def.unitPrefab.GetComponent(); if ((Object)(object)component == (Object)null) { def.length = (def.width = 300f); def.height = 570f; } else { Vector3 localScale = def.unitPrefab.transform.localScale; def.width = Mathf.Abs(component.size.x * localScale.x); def.height = Mathf.Abs(component.size.y * localScale.y); def.length = Mathf.Abs(component.size.z * localScale.z); } KaijuNukemPlugin.Log.LogInfo((object)($"[registry] dimensions set to {def.width:F0} x {def.length:F0} x {def.height:F0} m " + $"(maxRadius {Mathf.Max(Mathf.Max(def.length, def.width), def.height) * 0.5f:F0} m) — " + "missiles will aim at the body instead of the pivot between its feet.")); } private static bool HashCollides(int hash) { foreach (INetworkDefinition item in Encyclopedia.i.IndexLookup) { UnitDefinition val = (UnitDefinition)(object)((item is UnitDefinition) ? item : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.unitPrefab == (Object)null)) { NetworkIdentity component = val.unitPrefab.GetComponent(); if ((Object)(object)component != (Object)null && component.PrefabHash == hash) { return true; } } } return false; } private static void BorrowIcons(UnitDefinition def) { if ((Object)(object)def.mapIcon != (Object)null) { return; } Encyclopedia i = Encyclopedia.i; if (i?.vehicles != null && i.vehicles.Count != 0) { VehicleDefinition val = i.vehicles[0]; if (!((Object)(object)val == (Object)null)) { def.mapIcon = ((UnitDefinition)val).mapIcon; def.friendlyIcon = ((UnitDefinition)val).friendlyIcon; def.hostileIcon = ((UnitDefinition)val).hostileIcon; def.mapOrient = ((UnitDefinition)val).mapOrient; } } } } public static class KaijuSpawner { private const int KaijuPrefabHash = 1262569802; public static GameObject Spawn(GlobalPosition where, GlobalPosition walkTarget) { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020c: 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) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Expected O, but got Unknown //IL_028a: 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) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) NetworkManagerNuclearOption i = NetworkManagerNuclearOption.i; if ((Object)(object)i == (Object)null || !((NetworkManager)i).Server.Active) { KaijuNukemPlugin.Log.LogWarning((object)"[spawn] not the server/host — Kaiju spawn skipped"); return null; } if ((Object)(object)KaijuAssets.KaijuPrefab == (Object)null) { KaijuNukemPlugin.Log.LogError((object)"[spawn] no prefab loaded"); return null; } GameObject val = Object.Instantiate(KaijuAssets.KaijuPrefab); val.SetActive(false); Transform[] componentsInChildren = val.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren.Length; j++) { ((Component)componentsInChildren[j]).gameObject.layer = PhysicsLayers.Default; } val.transform.SetParent((Transform)null, true); Scene val2; if ((Object)(object)Datum.origin != (Object)null) { val2 = ((Component)Datum.origin).gameObject.scene; if (((Scene)(ref val2)).IsValid()) { SceneManager.MoveGameObjectToScene(val, ((Component)Datum.origin).gameObject.scene); } } ((Object)val).name = "Kaiju"; val.transform.localScale = Vector3.one * KaijuConfig.KaijuScale.Value; Rigidbody val3 = val.AddComponent(); val3.isKinematic = true; val3.useGravity = false; val3.mass = 500000f; val3.interpolation = (RigidbodyInterpolation)1; CapsuleCollider obj = val.AddComponent(); obj.direction = 1; obj.radius = 0.45f; obj.height = 1.9f; obj.center = new Vector3(0f, 0.95f, 0f); NetworkIdentity val4 = val.AddComponent(); Unit unit = val.AddComponent(); KaijuBody kaijuBody = val.AddComponent(); KaijuSwipe kaijuSwipe = val.AddComponent(); KaijuBrain kaijuBrain = val.AddComponent(); unit.definition = BuildDefinition(val); unit.MapUniqueName = string.Empty; unit.unitName = "Kaiju"; val.transform.position = GlobalPositionExtensions.ToLocalPosition(where); val.transform.rotation = Quaternion.identity; Animator componentInChildren = val.GetComponentInChildren(); Transform val5 = FindHandBone(componentInChildren, val.transform); kaijuBody.Initialize(armor: new ArmorProperties { pierceArmor = 20f, blastArmor = 50f, fireArmor = 10f, pierceTolerance = 1f, blastTolerance = 1f, fireTolerance = 1f, overpressureLimit = 1000f }, unit: unit, hitPoints: KaijuConfig.Health.Value); kaijuSwipe.Initialize(unit, val5); kaijuBrain.Initialize(unit, componentInChildren, kaijuSwipe, kaijuBody); kaijuBrain.SetDestination(walkTarget); SkinnedMeshRenderer[] componentsInChildren2 = val.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { componentsInChildren2[j].updateWhenOffscreen = true; } val.SetActive(true); val3.ResetCenterOfMass(); val3.ResetInertiaTensor(); val4.PrefabHash = 1262569802; AssignHostileFaction(unit); val4.OnStartClient.AddListener((Action)delegate { OnKaijuStartClient(unit); }); ((NetworkManager)i).ServerObjectManager.Spawn(val4); ManualLogSource log = KaijuNukemPlugin.Log; string[] obj2 = new string[6] { $"[spawn] Kaiju spawned at {val.transform.position} scale={KaijuConfig.KaijuScale.Value} ", string.Format("hp={0} hand={1} ", KaijuConfig.Health.Value, ((Object)(object)val5 != (Object)null) ? ((Object)val5).name : "NONE"), "scene=", null, null, null }; val2 = val.scene; obj2[3] = ((Scene)(ref val2)).name; obj2[4] = " active="; val2 = SceneManager.GetActiveScene(); obj2[5] = ((Scene)(ref val2)).name; log.LogInfo((object)string.Concat(obj2)); return val; } private static void AssignHostileFaction(Unit unit) { FactionHQ val = default(FactionHQ); if (!GameManager.GetLocalHQ(ref val) || (Object)(object)val == (Object)null) { KaijuNukemPlugin.Log.LogWarning((object)"[spawn] player has no faction yet — leaving the Kaiju factionless"); return; } FactionHQ val2 = null; foreach (FactionHQ allHQ in FactionRegistry.GetAllHQs()) { if (!((Object)(object)allHQ == (Object)null) && !((Object)(object)allHQ == (Object)(object)val)) { val2 = allHQ; break; } } if ((Object)(object)val2 == (Object)null) { KaijuNukemPlugin.Log.LogWarning((object)("[spawn] '" + ((Object)val).name + "' is the only faction — Kaiju left factionless")); return; } unit.NetworkHQ = val2; KaijuNukemPlugin.Log.LogInfo((object)("[spawn] you are '" + ((Object)val).name + "'; Kaiju assigned to hostile faction '" + ((Object)val2).name + "'")); } private static void OnKaijuStartClient(Unit unit) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) NetworkManagerNuclearOption i = NetworkManagerNuclearOption.i; unit.SetLocalSim((Object)(object)i != (Object)null && ((NetworkManager)i).Server.Active); unit.RegisterUnit((float?)4f); unit.InitializeUnit(); DynamicMap i2 = SceneSingleton.i; if ((Object)(object)i2 != (Object)null) { i2.GetOrAddIcon(unit); KaijuNukemPlugin.Log.LogInfo((object)"[spawn] map icon requested for the Kaiju"); } else { KaijuNukemPlugin.Log.LogWarning((object)"[spawn] DynamicMap not available — no map pin"); } if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)$"[spawn] OnStartClient localSim={unit.LocalSim} id={unit.persistentID}"); } } private static UnitDefinition BuildDefinition(GameObject go) { float value = KaijuConfig.KaijuScale.Value; UnitDefinition obj = ScriptableObject.CreateInstance(); ((Object)obj).name = "KaijuDefinition"; obj.unitName = "Kaiju"; obj.bogeyName = "Kaiju"; obj.description = "Something very large has come ashore."; obj.jsonKey = "kaijunukem_kaiju"; obj.unitPrefab = go; obj.length = 1.2f * value; obj.width = 1.2f * value; obj.height = 1.9f * value; obj.mass = 500000f; obj.value = 1000f; obj.visibleRange = 40000f; obj.iconRange = 40000f; obj.radarSize = 200f; obj.armorTier = 2f; obj.damageTolerance = 1f; obj.IsObstacle = false; obj.dontAutomaticallyAddToEncyclopedia = true; BorrowIcons(obj); return obj; } private static void BorrowIcons(UnitDefinition def) { Encyclopedia i = Encyclopedia.i; if (!((Object)(object)i == (Object)null) && i.vehicles != null && i.vehicles.Count != 0) { VehicleDefinition val = i.vehicles[0]; if (!((Object)(object)val == (Object)null)) { def.mapIcon = ((UnitDefinition)val).mapIcon; def.friendlyIcon = ((UnitDefinition)val).friendlyIcon; def.hostileIcon = ((UnitDefinition)val).hostileIcon; def.iconSize = ((UnitDefinition)val).iconSize; def.mapIconSize = ((UnitDefinition)val).mapIconSize * 2f; def.mapOrient = ((UnitDefinition)val).mapOrient; } } } private static Transform FindHandBone(Animator animator, Transform root) { if ((Object)(object)animator != (Object)null && animator.isHuman) { Transform boneTransform = animator.GetBoneTransform((HumanBodyBones)17); if ((Object)(object)boneTransform != (Object)null) { return boneTransform; } } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == "Hand_L") { return val; } } KaijuNukemPlugin.Log.LogWarning((object)"[spawn] left-hand bone not found; swipe will originate from the root"); return null; } } public class KaijuSwipe : MonoBehaviour { private static readonly Collider[] Buffer = (Collider[])(object)new Collider[512]; private Unit _unit; private Transform _handBone; private void Awake() { if ((Object)(object)_unit == (Object)null) { _unit = ((Component)this).GetComponent(); } if ((Object)(object)_handBone == (Object)null) { _handBone = FindHandBone(); } } public void Initialize(Unit unit, Transform handBone) { _unit = (((Object)(object)unit != (Object)null) ? unit : ((Component)this).GetComponent()); _handBone = (((Object)(object)handBone != (Object)null) ? handBone : FindHandBone()); } private Transform FindHandBone() { Animator componentInChildren = ((Component)this).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.isHuman) { Transform boneTransform = componentInChildren.GetBoneTransform((HumanBodyBones)17); if ((Object)(object)boneTransform != (Object)null) { return boneTransform; } } Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == "Hand_L") { return val; } } return null; } public void Strike() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_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_0087: 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_01c3: 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) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManagerNuclearOption.i == (Object)null || !((NetworkManager)NetworkManagerNuclearOption.i).Server.Active || (Object)(object)_unit == (Object)null) { return; } Vector3 val = (((Object)(object)_handBone != (Object)null) ? _handBone.position : ((Component)this).transform.position); Vector3 forward = ((Component)this).transform.forward; KaijuParams kaijuParams = KaijuParamStore.ForUnit(_unit); float swipeRange = kaijuParams.SwipeRange; float num = kaijuParams.SwipeArcDegrees * 0.5f; float swipeDamage = kaijuParams.SwipeDamage; int num2 = Physics.OverlapSphereNonAlloc(val, swipeRange, Buffer, ~LayerMask.op_Implicit(PhysicsLayers.ExclusionZonesMask)); if (num2 >= Buffer.Length) { KaijuNukemPlugin.Log.LogWarning((object)$"[swipe] overlap buffer saturated at {Buffer.Length}; some targets ignored"); } int num3 = 0; IDamageable val3 = default(IDamageable); Vector3 val5 = default(Vector3); for (int i = 0; i < num2; i++) { Collider val2 = Buffer[i]; if ((Object)(object)val2 == (Object)null || !((Component)val2).gameObject.TryGetComponent(ref val3) || val3.GetUnit() == _unit) { continue; } Vector3 val4 = ((Component)val2).transform.position - val; if (!(((Vector3)(ref val4)).sqrMagnitude > swipeRange * swipeRange)) { ((Vector3)(ref val5))..ctor(val4.x, 0f, val4.z); if (!(((Vector3)(ref val5)).sqrMagnitude < 0.001f) && !(Vector3.Angle(forward, val5) > num)) { val3.TakeDamage(0f, swipeDamage, 1f, 0f, swipeDamage * 0.25f, _unit.persistentID); num3++; } } } if (KaijuConfig.VerboseLogging.Value) { KaijuNukemPlugin.Log.LogInfo((object)$"[swipe] origin={val} reach={swipeRange} arc={num * 2f} candidates={num2} hits={num3}"); } } } internal static class KaijuUnitPanelInfo { private class Row { public readonly string Label; public readonly float Min; public readonly float Max; public readonly string Format; public readonly Func Read; public readonly Action Write; public Row(string label, float min, float max, string format, Func read, Action write) { Label = label; Min = min; Max = max; Format = format; Read = read; Write = write; } } private class Block { public GameObject Root; public FloatDataField[] Fields; public ReferenceDataField Target; } private const string BlockName = "KaijuParams"; private const string PatchId = "hendev.kaijunukem.unitpanel"; private static bool _patched; private static bool _loggedInstall; private static bool _loggedFailure; private static FieldInfo _targetsField; private static FieldInfo _captureFieldTemplate; private static FieldInfo _referenceFieldTemplate; private static readonly ConditionalWeakTable _blocks = new ConditionalWeakTable(); private static readonly Row[] Rows = new Row[11] { new Row("Health", 1f, 5000000f, "0", (KaijuParams p) => p.Health, delegate(KaijuParams p, float v) { p.Health = v; }), new Row("Scale", 1f, 1000f, "0.0", (KaijuParams p) => p.Scale, delegate(KaijuParams p, float v) { p.Scale = v; }), new Row("Walk Speed", 1f, 500f, "0", (KaijuParams p) => p.WalkSpeed, delegate(KaijuParams p, float v) { p.WalkSpeed = v; }), new Row("Turn Rate", 1f, 180f, "0.0", (KaijuParams p) => p.TurnRateDegPerSec, delegate(KaijuParams p, float v) { p.TurnRateDegPerSec = v; }), new Row("Swipe Range", 10f, 5000f, "0", (KaijuParams p) => p.SwipeRange, delegate(KaijuParams p, float v) { p.SwipeRange = v; }), new Row("Swipe Arc", 5f, 360f, "0", (KaijuParams p) => p.SwipeArcDegrees, delegate(KaijuParams p, float v) { p.SwipeArcDegrees = v; }), new Row("Swipe Damage", 1f, 100000f, "0", (KaijuParams p) => p.SwipeDamage, delegate(KaijuParams p, float v) { p.SwipeDamage = v; }), new Row("Swipe Cooldown", 0.5f, 60f, "0.0", (KaijuParams p) => p.SwipeCooldown, delegate(KaijuParams p, float v) { p.SwipeCooldown = v; }), new Row("$ / 1000 dmg", 10f, 1000f, "0", (KaijuParams p) => p.MoneyPer1000Damage, delegate(KaijuParams p, float v) { p.MoneyPer1000Damage = v; }), new Row("Round Damage x", 0f, 2f, "0.00", (KaijuParams p) => p.RoundDamageScale, delegate(KaijuParams p, float v) { p.RoundDamageScale = v; }), new Row("Blast Damage x", 1f, 200f, "0", (KaijuParams p) => p.BlastDamageScale, delegate(KaijuParams p, float v) { p.BlastDamageScale = v; }) }; public static void Apply() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown if (_patched) { return; } try { MethodInfo methodInfo = AccessTools.Method(typeof(UnitPanel), "OnTargetsChanged", (Type[])null, (Type[])null); if (methodInfo == null) { KaijuNukemPlugin.Log.LogWarning((object)"[panel] UnitPanel.OnTargetsChanged not found — the Mission Editor parameter fields are disabled. The Kaiju still places and fights; only per-placement editing is missing."); _patched = true; return; } _targetsField = AccessTools.Field(typeof(UnitPanel), "targets"); _captureFieldTemplate = AccessTools.Field(typeof(UnitPanel), "captureStrengthField"); _referenceFieldTemplate = AccessTools.Field(typeof(UnitPanel), "airbaseReference"); new Harmony("hendev.kaijunukem.unitpanel").Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(KaijuUnitPanelInfo), "OnTargetsChangedPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _patched = true; KaijuNukemPlugin.Log.LogInfo((object)"[panel] Mission Editor unit panel patched — a selected Kaiju gets editable parameters."); } catch (Exception ex) { _patched = true; KaijuNukemPlugin.Log.LogError((object)("[panel] could not patch UnitPanel (" + ex.GetType().Name + ": " + ex.Message + ") — continuing without the parameter fields.")); } } private static void OnTargetsChangedPostfix(UnitPanel __instance) { try { Refresh(__instance); } catch (Exception ex) { if (!_loggedFailure) { _loggedFailure = true; KaijuNukemPlugin.Log.LogError((object)("[panel] parameter fields failed and are now inert (" + ex.GetType().Name + ": " + ex.Message + "). The editor itself is unaffected.")); } } } private static void Refresh(UnitPanel panel) { //IL_010d: 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_014f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)panel == (Object)null || _targetsField == null) { return; } bool anyNonKaiju; List list = CollectKaijuTargets(panel, out anyNonKaiju); if (list.Count == 0 || anyNonKaiju) { if (_blocks.TryGetValue(panel, out var value) && (Object)(object)value?.Root != (Object)null) { value.Root.SetActive(false); } return; } Block orCreateBlock = GetOrCreateBlock(panel); if ((Object)(object)orCreateBlock?.Root == (Object)null) { return; } orCreateBlock.Root.SetActive(true); for (int i = 0; i < Rows.Length && i < orCreateBlock.Fields.Length; i++) { FloatDataField val = orCreateBlock.Fields[i]; if ((Object)(object)val == (Object)null) { continue; } Row row = Rows[i]; List targets = list; ValueWrapperFloat val2 = ValueWrapper.FromCallback((object)panel, row.Read(KaijuParamStore.Get(targets[0])), (Action)delegate(float v) { foreach (SavedUnit item in targets) { row.Write(KaijuParamStore.Get(item), v); } }); val.Setup(row.Label, (IValueWrapper)(object)val2, (FloatSettings?)new FloatSettings { Slider = new FloatSlider(row.Min, row.Max), TextFormat = row.Format }); } RefreshTargetPicker(orCreateBlock, list); FixLayout.RebuildRoot(((Component)panel).gameObject); } private static void RefreshTargetPicker(Block block, List selected) { if ((Object)(object)block?.Target == (Object)null || selected.Count == 0) { return; } List list = new List(); MissionManager.GetAllSavedUnitsNonAlloc(list, true); list.RemoveAll(KaijuParamStore.IsKaiju); string currentName = KaijuParamStore.Get(selected[0]).TargetUnitName; SavedUnit val = null; if (!string.IsNullOrEmpty(currentName)) { val = list.Find((SavedUnit u) => u != null && u.UniqueName == currentName); } List targets = selected; block.Target.Setup("Target", list, val, (Action)delegate(SavedUnit picked) { foreach (SavedUnit item in targets) { KaijuParamStore.Get(item).TargetUnitName = ((picked != null) ? picked.UniqueName : ""); } }); } private static List CollectKaijuTargets(UnitPanel panel, out bool anyNonKaiju) { anyNonKaiju = false; List list = new List(); object value = _targetsField.GetValue(panel); if (value == null) { return list; } if (value.GetType().GetProperty("Targets")?.GetValue(value) is IEnumerable enumerable) { foreach (object item in enumerable) { SavedUnit val = (SavedUnit)((item is SavedUnit) ? item : null); if (val != null) { if (KaijuParamStore.IsKaiju(val)) { list.Add(val); } else { anyNonKaiju = true; } } } } return list; } private static Block GetOrCreateBlock(UnitPanel panel) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown if (_blocks.TryGetValue(panel, out var value) && (Object)(object)value?.Root != (Object)null) { return value; } _blocks.Remove(panel); object? obj = _captureFieldTemplate?.GetValue(panel); FloatDataField val = (FloatDataField)((obj is FloatDataField) ? obj : null); if ((Object)(object)val == (Object)null) { if (!_loggedFailure) { _loggedFailure = true; KaijuNukemPlugin.Log.LogWarning((object)"[panel] UnitPanel.captureStrengthField not found — cannot build the Kaiju parameter fields without a field to clone."); } return null; } GameObject val2 = new GameObject("KaijuParams", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(((Component)panel).transform, false); VerticalLayoutGroup obj2 = val2.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ContentSizeFitter obj3 = val2.AddComponent(); obj3.verticalFit = (FitMode)2; obj3.horizontalFit = (FitMode)0; FloatDataField[] array = (FloatDataField[])(object)new FloatDataField[Rows.Length]; for (int i = 0; i < Rows.Length; i++) { FloatDataField val3 = Object.Instantiate(val, val2.transform); ((Object)((Component)val3).gameObject).name = "KaijuParams." + Rows[i].Label; ((Component)val3).gameObject.SetActive(true); array[i] = val3; } ReferenceDataField val4 = null; object? obj4 = _referenceFieldTemplate?.GetValue(panel); ReferenceDataField val5 = (ReferenceDataField)((obj4 is ReferenceDataField) ? obj4 : null); if ((Object)(object)val5 != (Object)null) { val4 = Object.Instantiate(val5, val2.transform); ((Object)((Component)val4).gameObject).name = "KaijuParams.Target"; ((Component)val4).gameObject.SetActive(true); ((Component)val4).transform.SetAsFirstSibling(); } else if (!_loggedFailure) { _loggedFailure = true; KaijuNukemPlugin.Log.LogWarning((object)"[panel] UnitPanel.airbaseReference not found — the Kaiju Target picker is unavailable; it will fall back to marching on the nearest building cluster."); } Block block = new Block { Root = val2, Fields = array, Target = val4 }; _blocks.Add(panel, block); if (!_loggedInstall) { _loggedInstall = true; KaijuNukemPlugin.Log.LogInfo((object)$"[panel] built {array.Length} editable Kaiju parameter fields in the unit panel."); } return block; } }