using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Companions;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace WanderingCompanions
{
public static class BiomeGearTable
{
public struct BiomeGear
{
public string[] Items;
public float BaseHealth;
}
private static readonly Dictionary<Biome, BiomeGear> _table = new Dictionary<Biome, BiomeGear>
{
[(Biome)1] = new BiomeGear
{
BaseHealth = 150f,
Items = new string[8] { "AxeBronze", "ShieldBronze", "BowFineWood", "ArrowBronze", "HelmetBronze", "ArmorBronzeChest", "ArmorBronzeLegs", "CapeTrollHide" }
},
[(Biome)8] = new BiomeGear
{
BaseHealth = 300f,
Items = new string[8] { "MaceBronze", "ShieldBanded", "BowHuntsman", "ArrowIron", "HelmetIron", "ArmorIronChest", "ArmorIronLegs", "CapeTrollHide" }
},
[(Biome)2] = new BiomeGear
{
BaseHealth = 500f,
Items = new string[8] { "SwordIron", "ShieldIron", "BowHuntsman", "ArrowObsidian", "HelmetIron", "ArmorIronChest", "ArmorIronLegs", "CapeLox" }
},
[(Biome)4] = new BiomeGear
{
BaseHealth = 800f,
Items = new string[8] { "SwordSilver", "ShieldSilver", "BowDraugrFang", "ArrowObsidian", "HelmetDrake", "ArmorWolfChest", "ArmorWolfLegs", "CapeWolf" }
},
[(Biome)16] = new BiomeGear
{
BaseHealth = 1200f,
Items = new string[8] { "AtgeirBlackmetal", "ShieldBlackmetal", "BowDraugrFang", "ArrowNeedle", "HelmetPadded", "ArmorPaddedCuirass", "ArmorPaddedGreaves", "CapeLinen" }
},
[(Biome)512] = new BiomeGear
{
BaseHealth = 1800f,
Items = new string[8] { "SwordMistwalker", "ShieldCarapace", "BowSpineSnap", "ArrowCarapace", "HelmetCarapace", "ArmorCarapaceChest", "ArmorCarapaceLegs", "CapeFeather" }
},
[(Biome)32] = new BiomeGear
{
BaseHealth = 2500f,
Items = new string[8] { "SwordFlametal", "ShieldFlametal", "BowSpineSnap", "ArrowCarapace", "HelmetFlametal", "ArmorFlametalChest", "ArmorFlametalLegs", "CapeLox" }
}
};
public static IEnumerable<Biome> SpawnBiomes => _table.Keys;
public static BiomeGear GetGear(Biome biome)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
if (_table.TryGetValue(biome, out var value))
{
return value;
}
return _table[(Biome)1];
}
public static Biome GetNextBiome(Biome current)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Invalid comparison between Unknown and I4
//IL_0004: 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_001c: Expected I4, but got Unknown
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Invalid comparison between Unknown and I4
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Invalid comparison between Unknown and I4
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Invalid comparison between Unknown and I4
if ((int)current <= 8)
{
switch (current - 1)
{
default:
if ((int)current != 8)
{
break;
}
return (Biome)2;
case 0:
return (Biome)8;
case 1:
return (Biome)4;
case 3:
return (Biome)16;
case 2:
break;
}
}
else
{
if ((int)current == 16)
{
return (Biome)512;
}
if ((int)current == 32)
{
return (Biome)32;
}
if ((int)current == 512)
{
return (Biome)32;
}
}
return (Biome)8;
}
}
[BepInPlugin("com.wandering.companions", "Wandering Companions", "1.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class WanderingPlugin : BaseUnityPlugin
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static ConsoleEvent <>9__4_0;
internal void <Awake>b__4_0(ConsoleEventArgs args)
{
//IL_0059: 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_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: 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_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_0234: 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)
if ((Object)(object)Player.m_localPlayer == (Object)null)
{
args.Context.AddString("No local player found.");
return;
}
ZNetScene instance = ZNetScene.instance;
GameObject val = ((instance != null) ? instance.GetPrefab("WC_Wanderer") : null);
if ((Object)(object)val == (Object)null)
{
args.Context.AddString("WC_Wanderer prefab not found.");
return;
}
Vector3 position = ((Component)Player.m_localPlayer).transform.position;
Vector3 forward = ((Component)Player.m_localPlayer).transform.forward;
Vector3 val2 = position + forward * 10f + Vector3.up * 1f;
GameObject val3 = Object.Instantiate<GameObject>(val, val2, Quaternion.identity);
if (args.Length >= 2)
{
WanderingCompanion component = val3.GetComponent<WanderingCompanion>();
if ((Object)(object)component != (Object)null)
{
string text = args[1].ToLowerInvariant();
Biome? val4 = null;
switch (text)
{
case "meadows":
val4 = (Biome)1;
break;
case "blackforest":
val4 = (Biome)8;
break;
case "swamp":
val4 = (Biome)2;
break;
case "mountain":
val4 = (Biome)4;
break;
case "plains":
val4 = (Biome)16;
break;
case "mistlands":
val4 = (Biome)512;
break;
case "ashlands":
val4 = (Biome)32;
break;
}
if (val4.HasValue)
{
component.OverrideBiome = val4.Value;
}
else
{
args.Context.AddString("Unknown biome '" + text + "', using position-based biome.");
}
}
}
args.Context.AddString($"Spawned wandering companion at {val2}");
}
}
public const string PluginGuid = "com.wandering.companions";
public const string PluginName = "Wandering Companions";
public const string PluginVersion = "1.1.1";
internal static ManualLogSource Log;
private void Awake()
{
//IL_001b: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
WanderingConfig.Init(((BaseUnityPlugin)this).Config);
new Harmony("com.wandering.companions").PatchAll(typeof(WanderingPlugin).Assembly);
object obj = <>c.<>9__4_0;
if (obj == null)
{
ConsoleEvent val = delegate(ConsoleEventArgs args)
{
//IL_0059: 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_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: 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_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_0234: 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)
if ((Object)(object)Player.m_localPlayer == (Object)null)
{
args.Context.AddString("No local player found.");
}
else
{
ZNetScene instance = ZNetScene.instance;
GameObject val2 = ((instance != null) ? instance.GetPrefab("WC_Wanderer") : null);
if ((Object)(object)val2 == (Object)null)
{
args.Context.AddString("WC_Wanderer prefab not found.");
}
else
{
Vector3 position = ((Component)Player.m_localPlayer).transform.position;
Vector3 forward = ((Component)Player.m_localPlayer).transform.forward;
Vector3 val3 = position + forward * 10f + Vector3.up * 1f;
GameObject val4 = Object.Instantiate<GameObject>(val2, val3, Quaternion.identity);
if (args.Length >= 2)
{
WanderingCompanion component = val4.GetComponent<WanderingCompanion>();
if ((Object)(object)component != (Object)null)
{
string text = args[1].ToLowerInvariant();
Biome? val5 = null;
switch (text)
{
case "meadows":
val5 = (Biome)1;
break;
case "blackforest":
val5 = (Biome)8;
break;
case "swamp":
val5 = (Biome)2;
break;
case "mountain":
val5 = (Biome)4;
break;
case "plains":
val5 = (Biome)16;
break;
case "mistlands":
val5 = (Biome)512;
break;
case "ashlands":
val5 = (Biome)32;
break;
}
if (val5.HasValue)
{
component.OverrideBiome = val5.Value;
}
else
{
args.Context.AddString("Unknown biome '" + text + "', using position-based biome.");
}
}
}
args.Context.AddString($"Spawned wandering companion at {val3}");
}
}
};
<>c.<>9__4_0 = val;
obj = (object)val;
}
new ConsoleCommand("spawnwanderer", "Spawns a hostile wandering companion nearby. Optional biome: meadows/blackforest/swamp/mountain/plains/mistlands/ashlands", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
Log.LogInfo((object)"Wandering Companions v1.1.1 loaded.");
}
}
public class WanderingCombatAI : MonoBehaviour
{
public const int StanceBalanced = 0;
public const int StanceMelee = 1;
public const int StanceRanged = 2;
private const float InterceptTimeMin = 0f;
private const float InterceptTimeMax = 4f;
private const float CircleTargetInterval = 3f;
private const float CircleTargetDuration = 1f;
private const float CircleTargetDistance = 4f;
private const float UpdateWeaponInterval = 1f;
private const float GiveUpTime = 30f;
private const float UpdateTargetIntervalNear = 2f;
private const float UpdateTargetIntervalFar = 6f;
private const float UnableToAttackDuration = 15f;
private const float WeaponSwitchCooldown = 4f;
private const float BowCooldown = 3f;
private MonsterAI _monsterAI;
private Character _character;
private Humanoid _humanoid;
private Character _targetCreature;
private Vector3 _lastKnownTargetPos;
private bool _beenAtLastPos;
private float _timeSinceAttacking;
private float _timeSinceSensedTarget;
private float _updateTargetTimer;
private float _updateWeaponTimer;
private float _interceptTime;
private float _pauseTimer;
private float _unableToAttackTargetTimer;
private float _weaponSwitchCooldown;
private float _bowCooldownTimer;
private int _stance;
private bool _engaged;
private float _blockHoldTimer;
private float _enemySwingTimer;
private const float ParryDelay = 0.2f;
private int _parryAttackCount;
private float _parryGraceTimer;
internal bool IsEngaged => _engaged;
internal void SetStance(int stance)
{
_stance = stance;
}
private void Awake()
{
_monsterAI = ((Component)this).GetComponent<MonsterAI>();
_character = ((Component)this).GetComponent<Character>();
_humanoid = ((Component)this).GetComponent<Humanoid>();
}
internal void Engage(Character target)
{
//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)
if (!((Object)(object)target == (Object)null) && !(target.GetHealth() <= 0f))
{
_targetCreature = target;
_lastKnownTargetPos = ((Component)target).transform.position;
_beenAtLastPos = false;
_timeSinceAttacking = 0f;
_timeSinceSensedTarget = 0f;
_updateTargetTimer = 0f;
_updateWeaponTimer = 0f;
_weaponSwitchCooldown = 0f;
_pauseTimer = Random.Range(0f, 3f);
_interceptTime = Random.Range(0f, 4f);
_unableToAttackTargetTimer = 0f;
_parryAttackCount = 0;
_engaged = true;
WanderingReflection.SetAlerted((BaseAI)(object)_monsterAI, alert: true);
}
}
internal void Disengage()
{
if (_engaged)
{
_targetCreature = null;
_engaged = false;
WanderingReflection.SetTargetCreature(_monsterAI, null);
WanderingReflection.SetAlerted((BaseAI)(object)_monsterAI, alert: false);
((BaseAI)_monsterAI).StopMoving();
((BaseAI)_monsterAI).ChargeStop();
ClearBlock();
_parryAttackCount = 0;
}
}
internal bool UpdateCombat(float dt)
{
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Invalid comparison between Unknown and I4
//IL_00e3: 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_0233: Invalid comparison between Unknown and I4
//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
//IL_0277: Unknown result type (might be due to invalid IL or missing references)
//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0309: Unknown result type (might be due to invalid IL or missing references)
//IL_04df: Unknown result type (might be due to invalid IL or missing references)
//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
//IL_038c: Unknown result type (might be due to invalid IL or missing references)
//IL_0391: Unknown result type (might be due to invalid IL or missing references)
//IL_0393: Unknown result type (might be due to invalid IL or missing references)
//IL_039b: Unknown result type (might be due to invalid IL or missing references)
//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
//IL_0434: Unknown result type (might be due to invalid IL or missing references)
//IL_044c: Unknown result type (might be due to invalid IL or missing references)
if (!_engaged)
{
return false;
}
if ((Object)(object)_humanoid == (Object)null)
{
return false;
}
if (_bowCooldownTimer > 0f)
{
_bowCooldownTimer -= dt;
}
UpdateTarget(dt, out var canHearTarget, out var canSeeTarget);
if ((Object)(object)_targetCreature == (Object)null)
{
Disengage();
return false;
}
WanderingReflection.SetTargetCreature(_monsterAI, _targetCreature);
UpdateBlocking(dt);
bool blocking = WanderingReflection.GetBlocking(_character);
if ((Object)(object)_targetCreature != (Object)null && !blocking && _parryAttackCount <= 0)
{
_pauseTimer += dt;
if (_pauseTimer > 3f)
{
if (_pauseTimer > 4f)
{
_pauseTimer = Random.Range(0f, 0.3f);
}
WanderingReflection.RandomMovementAroundPoint((BaseAI)(object)_monsterAI, dt, ((Component)_targetCreature).transform.position, 4f, ((BaseAI)_monsterAI).IsAlerted());
return true;
}
}
ItemData val = SelectBestAttack(dt);
float num = ((val != null && (int)val.m_shared.m_itemType == 4) ? 0.5f : 0f);
bool flag = val != null && Time.time - val.m_lastAttackTime > val.m_shared.m_aiAttackInterval + num;
bool flag2 = _character.GetTimeSinceLastAttack() >= 0.5f;
bool flag3 = _parryAttackCount > 0;
bool flag4 = val != null && !WanderingReflection.IsTakingOff((BaseAI)(object)_monsterAI) && (flag3 || (flag && flag2));
if (!((BaseAI)_monsterAI).IsCharging() && (Object)(object)_targetCreature != (Object)null && val != null && flag4 && !_character.InAttack() && val.m_shared.m_attack != null && !val.m_shared.m_attack.IsDone() && !string.IsNullOrEmpty(val.m_shared.m_attack.m_chargeAnimationBool))
{
((BaseAI)_monsterAI).ChargeStart(val.m_shared.m_attack.m_chargeAnimationBool);
}
bool flag5 = val != null && (val.m_shared.m_aiAttackRange > 10f || (int)val.m_shared.m_itemType == 4);
if ((Object)(object)_targetCreature != (Object)null && val != null && !flag4 && !_character.InAttack() && !flag5)
{
WanderingReflection.RandomMovementAroundPoint((BaseAI)(object)_monsterAI, dt, ((Component)_targetCreature).transform.position, 5f, ((BaseAI)_monsterAI).IsAlerted());
return true;
}
if ((Object)(object)_targetCreature == (Object)null || val == null)
{
((BaseAI)_monsterAI).ChargeStop();
Disengage();
return false;
}
if ((int)val.m_shared.m_aiTargetType == 0 && (Object)(object)_targetCreature != (Object)null)
{
if (canHearTarget || canSeeTarget)
{
_beenAtLastPos = false;
_lastKnownTargetPos = ((Component)_targetCreature).transform.position;
float num2 = Vector3.Distance(_lastKnownTargetPos, ((Component)this).transform.position) - _targetCreature.GetRadius();
float num3 = 9999f * _targetCreature.GetStealthFactor();
if (canSeeTarget && num2 < num3)
{
WanderingReflection.SetAlerted((BaseAI)(object)_monsterAI, alert: true);
}
float aiAttackRange = val.m_shared.m_aiAttackRange;
bool num4 = num2 < aiAttackRange;
if (!num4 || !canSeeTarget || !((BaseAI)_monsterAI).IsAlerted() || val.m_shared.m_aiAttackRangeMin < 0f)
{
Vector3 velocity = _targetCreature.GetVelocity();
Vector3 val2 = velocity * _interceptTime;
Vector3 val3 = _lastKnownTargetPos;
if (num2 > ((Vector3)(ref val2)).magnitude / 4f)
{
val3 += velocity * _interceptTime;
}
WanderingReflection.MoveTo((BaseAI)(object)_monsterAI, dt, val3, 0f, run: true);
if (_timeSinceAttacking > 15f)
{
_unableToAttackTargetTimer = 15f;
}
}
else
{
((BaseAI)_monsterAI).StopMoving();
}
if (num4 && canSeeTarget && ((BaseAI)_monsterAI).IsAlerted() && !blocking)
{
WanderingReflection.LookAt((BaseAI)(object)_monsterAI, _targetCreature.GetTopPoint());
if (flag4 && WanderingReflection.IsLookingAt((BaseAI)(object)_monsterAI, _lastKnownTargetPos, val.m_shared.m_aiAttackMaxAngle, val.m_shared.m_aiInvertAngleCheck) && DoAttack(_targetCreature) && _parryAttackCount > 0)
{
_parryAttackCount--;
}
}
}
else
{
((BaseAI)_monsterAI).ChargeStop();
if (_beenAtLastPos)
{
WanderingReflection.RandomMovement((BaseAI)(object)_monsterAI, dt, _lastKnownTargetPos);
if (_timeSinceAttacking > 15f)
{
_unableToAttackTargetTimer = 15f;
}
}
else if (WanderingReflection.MoveTo((BaseAI)(object)_monsterAI, dt, _lastKnownTargetPos, 0f, run: true))
{
_beenAtLastPos = true;
}
}
}
return true;
}
private void UpdateTarget(float dt, out bool canHearTarget, out bool canSeeTarget)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
_unableToAttackTargetTimer -= dt;
_updateTargetTimer -= dt;
if (_updateTargetTimer <= 0f && !_character.InAttack())
{
bool flag = Player.IsPlayerInRange(((Component)this).transform.position, 50f);
_updateTargetTimer = (flag ? 2f : 6f);
Character val = WanderingReflection.FindEnemy((BaseAI)(object)_monsterAI);
if ((Object)(object)val != (Object)null)
{
_targetCreature = val;
}
}
if ((Object)(object)_targetCreature != (Object)null)
{
ZNetView component = ((Component)_targetCreature).GetComponent<ZNetView>();
if ((Object)(object)component != (Object)null && !component.IsValid())
{
_targetCreature = null;
}
else if (_targetCreature.GetHealth() <= 0f)
{
_targetCreature = null;
}
else if (!((BaseAI)_monsterAI).IsEnemy(_targetCreature))
{
_targetCreature = null;
}
}
canHearTarget = false;
canSeeTarget = false;
if ((Object)(object)_targetCreature != (Object)null)
{
canHearTarget = ((BaseAI)_monsterAI).CanHearTarget(_targetCreature);
canSeeTarget = ((BaseAI)_monsterAI).CanSeeTarget(_targetCreature);
if (canSeeTarget | canHearTarget)
{
_timeSinceSensedTarget = 0f;
}
}
_timeSinceSensedTarget += dt;
if (((BaseAI)_monsterAI).IsAlerted() || (Object)(object)_targetCreature != (Object)null)
{
_timeSinceAttacking += dt;
if (_timeSinceSensedTarget > 30f || _timeSinceAttacking > 60f)
{
WanderingReflection.SetAlerted((BaseAI)(object)_monsterAI, alert: false);
_targetCreature = null;
_timeSinceAttacking = 0f;
_updateTargetTimer = 5f;
}
}
}
private ItemData SelectBestAttack(float dt)
{
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Invalid comparison between Unknown and I4
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Invalid comparison between Unknown and I4
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Invalid comparison between Unknown and I4
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Invalid comparison between Unknown and I4
if ((Object)(object)_targetCreature != (Object)null)
{
_updateWeaponTimer -= dt;
if (_weaponSwitchCooldown > 0f)
{
_weaponSwitchCooldown -= dt;
}
if (_updateWeaponTimer <= 0f && !_character.InAttack() && _weaponSwitchCooldown <= 0f)
{
_updateWeaponTimer = 1f;
string text = _humanoid.GetCurrentWeapon()?.m_shared?.m_name;
bool flag = false;
ItemData currentWeapon = _humanoid.GetCurrentWeapon();
if (_stance == 2)
{
if (currentWeapon == null || (int)currentWeapon.m_shared.m_itemType != 4)
{
WanderingReflection.HaveFriendsInRange((BaseAI)(object)_monsterAI, ((BaseAI)_monsterAI).m_viewRange, out var hurtFriend, out var friend);
_humanoid.EquipBestWeapon(_targetCreature, (StaticTarget)null, hurtFriend, friend);
TryForceRangedWeapon();
flag = true;
}
}
else if (_stance == 1)
{
if (currentWeapon == null || ((int)currentWeapon.m_shared.m_itemType != 3 && (int)currentWeapon.m_shared.m_itemType != 14 && (int)currentWeapon.m_shared.m_itemType != 22))
{
WanderingReflection.HaveFriendsInRange((BaseAI)(object)_monsterAI, ((BaseAI)_monsterAI).m_viewRange, out var hurtFriend2, out var friend2);
_humanoid.EquipBestWeapon(_targetCreature, (StaticTarget)null, hurtFriend2, friend2);
TryForceMeleeWeapon();
flag = true;
}
}
else
{
WanderingReflection.HaveFriendsInRange((BaseAI)(object)_monsterAI, ((BaseAI)_monsterAI).m_viewRange, out var hurtFriend3, out var friend3);
_humanoid.EquipBestWeapon(_targetCreature, (StaticTarget)null, hurtFriend3, friend3);
}
TryEquipShield();
if (_humanoid.GetCurrentWeapon()?.m_shared?.m_name != text || flag)
{
_weaponSwitchCooldown = 4f;
}
}
}
return _humanoid.GetCurrentWeapon();
}
private bool DoAttack(Character target)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Invalid comparison between Unknown and I4
ItemData currentWeapon = _humanoid.GetCurrentWeapon();
if (currentWeapon == null)
{
return false;
}
if (!((BaseAI)_monsterAI).CanUseAttack(currentWeapon))
{
return false;
}
bool flag = (int)currentWeapon.m_shared.m_itemType == 4;
if (flag && _bowCooldownTimer > 0f)
{
return false;
}
Attack val = currentWeapon.m_shared?.m_attack;
bool flag2 = false;
if (val != null && val.m_bowDraw)
{
flag2 = true;
val.m_bowDraw = false;
}
bool num = _character.StartAttack(target, false);
if (flag2 && val != null)
{
val.m_bowDraw = true;
}
if (num)
{
_timeSinceAttacking = 0f;
if (flag)
{
_bowCooldownTimer = 3f;
}
}
return num;
}
private void UpdateBlocking(float dt)
{
//IL_003e: 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_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_targetCreature == (Object)null || _character.InAttack() || _character.IsStaggering() || _parryAttackCount > 0)
{
ClearBlock();
return;
}
float num = Vector3.Distance(((Component)this).transform.position, ((Component)_targetCreature).transform.position);
if (_targetCreature.InAttack() && num < 8f)
{
_enemySwingTimer += dt;
WanderingReflection.LookAt((BaseAI)(object)_monsterAI, _targetCreature.GetTopPoint());
if (_enemySwingTimer >= 0.2f)
{
WanderingReflection.TrySetBlocking(_character, value: true);
WanderingReflection.TrySetBlockTimer(_humanoid, 0f);
_blockHoldTimer = 0.2f;
}
return;
}
if (_blockHoldTimer > 0f)
{
_blockHoldTimer -= dt;
WanderingReflection.TrySetBlocking(_character, value: true);
WanderingReflection.LookAt((BaseAI)(object)_monsterAI, _targetCreature.GetTopPoint());
_enemySwingTimer = 0f;
return;
}
if (_blockHoldTimer < 0f)
{
_parryGraceTimer = 0.15f;
}
if (_parryGraceTimer > 0f)
{
_parryGraceTimer -= dt;
if ((Object)(object)_targetCreature != (Object)null && _targetCreature.IsStaggering())
{
_parryAttackCount = 2;
_parryGraceTimer = 0f;
}
}
ClearBlock();
}
private void ClearBlock()
{
_enemySwingTimer = 0f;
if (WanderingReflection.GetBlocking(_character))
{
WanderingReflection.TrySetBlocking(_character, value: false);
}
_blockHoldTimer = 0f;
}
private bool TryEquipShield()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Invalid comparison between Unknown and I4
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Invalid comparison between Unknown and I4
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Invalid comparison between Unknown and I4
ItemData currentWeapon = _humanoid.GetCurrentWeapon();
if (currentWeapon == null)
{
return false;
}
if ((int)currentWeapon.m_shared.m_itemType != 3)
{
return false;
}
ItemData leftItem = _humanoid.LeftItem;
if (leftItem != null && (int)leftItem.m_shared.m_itemType == 5)
{
return false;
}
Inventory inventory = _humanoid.GetInventory();
if (inventory == null)
{
return false;
}
ItemData val = null;
float num = -1f;
foreach (ItemData allItem in inventory.GetAllItems())
{
if (allItem.IsEquipable() && (int)allItem.m_shared.m_itemType == 5 && allItem.m_shared.m_blockPower > num)
{
num = allItem.m_shared.m_blockPower;
val = allItem;
}
}
if (val == null)
{
return false;
}
_humanoid.EquipItem(val, true);
return true;
}
private bool TryForceRangedWeapon()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Invalid comparison between Unknown and I4
Inventory inventory = _humanoid.GetInventory();
if (inventory == null)
{
return false;
}
foreach (ItemData allItem in inventory.GetAllItems())
{
if (allItem.IsEquipable() && (int)allItem.m_shared.m_itemType == 4)
{
_humanoid.EquipItem(allItem, true);
return true;
}
}
return false;
}
private bool TryForceMeleeWeapon()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Invalid comparison between Unknown and I4
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Invalid comparison between Unknown and I4
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Invalid comparison between Unknown and I4
Inventory inventory = _humanoid.GetInventory();
if (inventory == null)
{
return false;
}
foreach (ItemData allItem in inventory.GetAllItems())
{
if (allItem.IsEquipable() && ((int)allItem.m_shared.m_itemType == 3 || (int)allItem.m_shared.m_itemType == 14 || (int)allItem.m_shared.m_itemType == 22))
{
_humanoid.EquipItem(allItem, true);
return true;
}
}
return false;
}
}
public class WanderingCompanion : MonoBehaviour
{
private static readonly int OwnerHash = StringExtensionMethods.GetStableHashCode("HC_Owner");
private static readonly int AppearanceHash = StringExtensionMethods.GetStableHashCode("HC_Appearance");
private static readonly int NameHash = StringExtensionMethods.GetStableHashCode("HC_Name");
private static readonly int FollowHash = StringExtensionMethods.GetStableHashCode("HC_Follow");
private static readonly string[] HairStyles = new string[14]
{
"Hair1", "Hair2", "Hair3", "Hair4", "Hair5", "Hair6", "Hair7", "Hair8", "Hair9", "Hair10",
"Hair11", "Hair12", "Hair13", "Hair14"
};
private static readonly string[] BeardStyles = new string[11]
{
"", "Beard1", "Beard2", "Beard3", "Beard4", "Beard5", "Beard6", "Beard7", "Beard8", "Beard9",
"Beard10"
};
private Humanoid _humanoid;
private ZNetView _nview;
private VisEquipment _visEquip;
private Character _character;
private int _modelIndex;
private string _hairItem;
private string _beardItem;
private Vector3 _skinColor;
private Vector3 _hairColor;
private ZDOID _lastAttackerZDOID;
private float _biomeHealth;
private bool _initialized;
internal Biome? OverrideBiome;
private bool _aggro;
private static readonly Vector3[] SkinTones = (Vector3[])(object)new Vector3[7]
{
new Vector3(1f, 0.93f, 0.86f),
new Vector3(0.96f, 0.87f, 0.78f),
new Vector3(0.88f, 0.75f, 0.63f),
new Vector3(0.76f, 0.6f, 0.46f),
new Vector3(0.62f, 0.45f, 0.33f),
new Vector3(0.48f, 0.33f, 0.22f),
new Vector3(0.35f, 0.22f, 0.14f)
};
private static readonly Vector3[] HairColors = (Vector3[])(object)new Vector3[9]
{
new Vector3(0.1f, 0.08f, 0.06f),
new Vector3(0.25f, 0.15f, 0.08f),
new Vector3(0.45f, 0.3f, 0.15f),
new Vector3(0.6f, 0.4f, 0.2f),
new Vector3(0.75f, 0.55f, 0.25f),
new Vector3(0.9f, 0.75f, 0.45f),
new Vector3(0.55f, 0.2f, 0.1f),
new Vector3(0.7f, 0.68f, 0.65f),
new Vector3(0.9f, 0.88f, 0.85f)
};
private void Awake()
{
_humanoid = ((Component)this).GetComponent<Humanoid>();
_nview = ((Component)this).GetComponent<ZNetView>();
_visEquip = ((Component)this).GetComponent<VisEquipment>();
_character = ((Component)this).GetComponent<Character>();
if ((Object)(object)_humanoid != (Object)null)
{
((Character)_humanoid).m_onDeath = (Action)Delegate.Combine(((Character)_humanoid).m_onDeath, new Action(OnDeath));
}
if ((Object)(object)_character != (Object)null)
{
_character.m_onDamaged = (Action<float, Character>)Delegate.Combine(_character.m_onDamaged, new Action<float, Character>(OnDamaged));
}
}
private void Start()
{
//IL_0037: 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_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: 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_0044: 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_0161: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Invalid comparison between Unknown and I4
if ((Object)(object)_nview == (Object)null || !_nview.IsOwner())
{
return;
}
Biome val = (Biome)(((??)OverrideBiome) ?? GetBiomeAtPosition());
Biome nextBiome = BiomeGearTable.GetNextBiome(val);
BiomeGearTable.BiomeGear gear = BiomeGearTable.GetGear(nextBiome);
_biomeHealth = gear.BaseHealth * WanderingConfig.HealthMultiplier.Value * 1.5f;
List<GameObject> list = ResolveGearPrefabs(gear.Items);
if (list.Count > 0)
{
_humanoid.m_defaultItems = list.ToArray();
_humanoid.GiveDefaultItems();
Inventory inventory = _humanoid.GetInventory();
if (inventory != null)
{
foreach (ItemData allItem in inventory.GetAllItems())
{
if ((int)allItem.m_shared.m_itemType == 9)
{
allItem.m_stack = allItem.m_shared.m_maxStackSize;
}
}
}
}
((Character)_humanoid).SetMaxHealth(_biomeHealth);
((Character)_humanoid).SetHealth(_biomeHealth);
WanderingCombatAI component = ((Component)this).GetComponent<WanderingCombatAI>();
if ((Object)(object)component != (Object)null)
{
int stance = Random.Range(0, 3);
component.SetStance(stance);
}
float value = WanderingConfig.SizeScale.Value;
((Component)this).transform.localScale = Vector3.one * value;
RandomizeAppearance();
ApplyAppearance();
_initialized = true;
WanderingPlugin.Log.LogInfo((object)($"[WanderingCompanion] Spawned in {val} (gear={nextBiome}) with {list.Count} items, " + $"health={_biomeHealth}, scale={WanderingConfig.SizeScale.Value}"));
}
private void Update()
{
if (_initialized && (Object)(object)_nview != (Object)null && _nview.IsOwner() && _biomeHealth > 0f && (Object)(object)_humanoid != (Object)null && ((Character)_humanoid).GetMaxHealth() != _biomeHealth)
{
((Character)_humanoid).SetMaxHealth(_biomeHealth);
}
}
private void OnDamaged(float damage, Character attacker)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)attacker != (Object)null))
{
return;
}
ZNetView component = ((Component)attacker).GetComponent<ZNetView>();
if ((Object)(object)component != (Object)null)
{
_lastAttackerZDOID = component.GetZDO()?.m_uid ?? ZDOID.None;
}
if (!_aggro)
{
_aggro = true;
MonsterAI component2 = ((Component)this).GetComponent<MonsterAI>();
if ((Object)(object)component2 != (Object)null)
{
component2.m_enableHuntPlayer = true;
component2.m_alertRange = 9999f;
WanderingReflection.SetTargetCreature(component2, attacker);
WanderingReflection.SetAlerted((BaseAI)(object)component2, alert: true);
((BaseAI)component2).Alert();
}
WanderingCombatAI component3 = ((Component)this).GetComponent<WanderingCombatAI>();
if ((Object)(object)component3 != (Object)null)
{
component3.Engage(attacker);
}
}
}
private void OnDeath()
{
if (!((Object)(object)_nview == (Object)null) && _nview.IsOwner() && WanderingConfig.ConvertOnDeath.Value)
{
Player val = FindKillerPlayer();
if ((Object)(object)val == (Object)null)
{
val = Player.m_localPlayer;
}
if ((Object)(object)val == (Object)null)
{
WanderingPlugin.Log.LogWarning((object)"[WanderingCompanion] No killer found, skipping friendly spawn.");
}
else
{
SpawnFriendlyCompanion(val);
}
}
}
private void SpawnFriendlyCompanion(Player killer)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_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_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_0059: 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_005f: 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_006b: 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_019b: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: 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_01a6: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
ZNetScene instance = ZNetScene.instance;
GameObject val = ((instance != null) ? instance.GetPrefab("HC_Companion") : null);
if ((Object)(object)val == (Object)null)
{
WanderingPlugin.Log.LogError((object)"[WanderingCompanion] HC_Companion prefab not found! Is HaldorCompanions installed?");
return;
}
Vector3 position = ((Component)this).transform.position;
Quaternion rotation = ((Component)this).transform.rotation;
SpawnVFX("fx_eikthyr_forwardshockwave", position, rotation);
SpawnVFX("vfx_offering", position + Vector3.up, rotation);
GameObject val2 = Object.Instantiate<GameObject>(val, position, rotation);
ZNetView component = val2.GetComponent<ZNetView>();
if ((Object)(object)component == (Object)null)
{
return;
}
component.ClaimOwnership();
ZDO zDO = component.GetZDO();
if (zDO != null)
{
long playerID = killer.GetPlayerID();
zDO.Set(OwnerHash, playerID.ToString());
zDO.Set(NameHash, "Companion");
string text = SerializeAppearance();
zDO.Set(AppearanceHash, text);
zDO.Set(FollowHash, true);
zDO.Persistent = true;
VisEquipment component2 = val2.GetComponent<VisEquipment>();
if ((Object)(object)component2 != (Object)null)
{
component2.SetModel(_modelIndex);
component2.SetHairItem(_hairItem ?? "");
component2.SetBeardItem(_beardItem ?? "");
component2.SetSkinColor(_skinColor);
component2.SetHairColor(_hairColor);
}
Humanoid component3 = val2.GetComponent<Humanoid>();
if ((Object)(object)component3 != (Object)null)
{
((Character)component3).SetHealth(((Character)component3).GetMaxHealth());
}
CompanionAI component4 = val2.GetComponent<CompanionAI>();
if ((Object)(object)component4 != (Object)null)
{
component4.SetFollowTarget(((Component)killer).gameObject);
}
SpawnVFX("vfx_GoblinShaman_protect", position + Vector3.up, rotation);
WanderingPlugin.Log.LogInfo((object)("[WanderingCompanion] Spawned friendly companion for player " + killer.GetPlayerName() + " " + $"at {position}"));
}
}
private static void SpawnVFX(string prefabName, Vector3 pos, Quaternion rot)
{
//IL_001d: 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)
ZNetScene instance = ZNetScene.instance;
GameObject val = ((instance != null) ? instance.GetPrefab(prefabName) : null);
if ((Object)(object)val != (Object)null)
{
Object.Instantiate<GameObject>(val, pos, rot);
}
}
private Player FindKillerPlayer()
{
//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_0047: 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)
if (_lastAttackerZDOID == ZDOID.None)
{
return null;
}
foreach (Player allPlayer in Player.GetAllPlayers())
{
ZNetView component = ((Component)allPlayer).GetComponent<ZNetView>();
if ((Object)(object)component != (Object)null && component.GetZDO() != null && component.GetZDO().m_uid == _lastAttackerZDOID)
{
return allPlayer;
}
}
return null;
}
private void RandomizeAppearance()
{
//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_007e: 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)
_modelIndex = Random.Range(0, 2);
_hairItem = HairStyles[Random.Range(0, HairStyles.Length)];
_beardItem = ((_modelIndex == 0) ? BeardStyles[Random.Range(0, BeardStyles.Length)] : "");
_skinColor = SkinTones[Random.Range(0, SkinTones.Length)];
_hairColor = HairColors[Random.Range(0, HairColors.Length)];
}
private void ApplyAppearance()
{
//IL_005b: 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 (!((Object)(object)_visEquip == (Object)null))
{
_visEquip.SetModel(_modelIndex);
_visEquip.SetHairItem(_hairItem ?? "");
_visEquip.SetBeardItem(_beardItem ?? "");
_visEquip.SetSkinColor(_skinColor);
_visEquip.SetHairColor(_hairColor);
}
}
private string SerializeAppearance()
{
CultureInfo invariantCulture = CultureInfo.InvariantCulture;
return string.Join(";", _modelIndex.ToString(invariantCulture), _hairItem ?? "", _beardItem ?? "", _skinColor.x.ToString("F3", invariantCulture), _skinColor.y.ToString("F3", invariantCulture), _skinColor.z.ToString("F3", invariantCulture), _hairColor.x.ToString("F3", invariantCulture), _hairColor.y.ToString("F3", invariantCulture), _hairColor.z.ToString("F3", invariantCulture));
}
private Biome GetBiomeAtPosition()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
if (WorldGenerator.instance != null)
{
return WorldGenerator.instance.GetBiome(((Component)this).transform.position);
}
return (Biome)1;
}
private static List<GameObject> ResolveGearPrefabs(string[] itemNames)
{
List<GameObject> list = new List<GameObject>();
if ((Object)(object)ObjectDB.instance == (Object)null)
{
return list;
}
foreach (string text in itemNames)
{
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
if ((Object)(object)itemPrefab != (Object)null)
{
list.Add(itemPrefab);
}
else
{
WanderingPlugin.Log.LogWarning((object)("[WanderingCompanion] Item prefab '" + text + "' not found in ObjectDB — skipping."));
}
}
return list;
}
}
public static class WanderingConfig
{
public static ConfigEntry<bool> Enabled;
public static ConfigEntry<float> SpawnInterval;
public static ConfigEntry<float> SpawnChance;
public static ConfigEntry<float> HealthMultiplier;
public static ConfigEntry<float> SizeScale;
public static ConfigEntry<bool> ConvertOnDeath;
public static void Init(ConfigFile cfg)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Expected O, but got Unknown
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Expected O, but got Unknown
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Expected O, but got Unknown
Enabled = cfg.Bind<bool>("General", "Enabled", true, "Master toggle for wandering companion spawns.");
SpawnInterval = cfg.Bind<float>("Spawning", "SpawnInterval", 3000f, new ConfigDescription("Seconds between spawn attempts per biome (default 50 min).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 7200f), Array.Empty<object>()));
SpawnChance = cfg.Bind<float>("Spawning", "SpawnChance", 15f, new ConfigDescription("Percent chance a spawn attempt succeeds (0-100).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
HealthMultiplier = cfg.Bind<float>("General", "HealthMultiplier", 1f, new ConfigDescription("Multiplier applied to wandering companion base health per biome.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
SizeScale = cfg.Bind<float>("General", "SizeScale", 1.5f, new ConfigDescription("Scale of wandering companions relative to the player (1.0 = same size).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
ConvertOnDeath = cfg.Bind<bool>("General", "ConvertOnDeath", true, "When true, defeated wanderers convert into a friendly companion. When false, they just die.");
}
}
public static class WanderingPrefabs
{
public const string PrefabName = "WC_Wanderer";
private static GameObject _container;
private static readonly FieldInfo _namedPrefabsField = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");
public static void Init(ZNetScene zNetScene)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
if (!((Object)(object)zNetScene.GetPrefab("WC_Wanderer") != (Object)null))
{
if ((Object)(object)_container == (Object)null)
{
_container = new GameObject("WC_PrefabContainer");
Object.DontDestroyOnLoad((Object)(object)_container);
_container.SetActive(false);
}
CreateWandererPrefab(zNetScene);
}
}
private static void CreateWandererPrefab(ZNetScene zNetScene)
{
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
GameObject prefab = zNetScene.GetPrefab("Player");
if ((Object)(object)prefab == (Object)null)
{
WanderingPlugin.Log.LogError((object)"[WanderingPrefabs] Player prefab not found!");
return;
}
GameObject obj = Object.Instantiate<GameObject>(prefab, _container.transform, false);
((Object)obj).name = "WC_Wanderer";
DestroyComponent<PlayerController>(obj);
DestroyComponent<Player>(obj);
DestroyComponent<Talker>(obj);
DestroyComponent<Skills>(obj);
Humanoid component = prefab.GetComponent<Humanoid>();
Humanoid val = obj.AddComponent<Humanoid>();
if ((Object)(object)component != (Object)null)
{
val.m_unarmedWeapon = component.m_unarmedWeapon;
val.m_consumeItemEffects = component.m_consumeItemEffects;
val.m_equipEffects = component.m_equipEffects;
}
SetupHumanoid(val, zNetScene);
CharacterAnimEvent componentInChildren = obj.GetComponentInChildren<CharacterAnimEvent>();
if ((Object)(object)componentInChildren != (Object)null)
{
AccessTools.Field(typeof(CharacterAnimEvent), "m_character")?.SetValue(componentInChildren, val);
}
SetupMonsterAI(obj.AddComponent<MonsterAI>());
obj.AddComponent<WanderingCombatAI>();
obj.AddComponent<WanderingCompanion>();
obj.AddComponent<WanderingTalk>();
ZNetView component2 = obj.GetComponent<ZNetView>();
component2.m_persistent = false;
component2.m_distant = false;
component2.m_type = (ObjectType)0;
component2.m_syncInitialScale = false;
ZSyncTransform component3 = obj.GetComponent<ZSyncTransform>();
if ((Object)(object)component3 != (Object)null)
{
component3.m_syncPosition = true;
component3.m_syncRotation = true;
component3.m_syncScale = false;
component3.m_syncBodyVelocity = false;
}
ZSyncAnimation component4 = obj.GetComponent<ZSyncAnimation>();
if ((Object)(object)component4 != (Object)null)
{
component4.m_smoothCharacterSpeeds = true;
}
Rigidbody component5 = obj.GetComponent<Rigidbody>();
if ((Object)(object)component5 != (Object)null)
{
component5.mass = 50f;
}
DestroyComponent<CharacterDrop>(obj);
RegisterPrefab(obj, zNetScene);
WanderingPlugin.Log.LogInfo((object)"[WanderingPrefabs] Created and registered WC_Wanderer");
}
private static void SetupHumanoid(Humanoid h, ZNetScene scene)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_018b: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
((Character)h).m_name = "Wanderer";
((Character)h).m_group = "";
((Character)h).m_faction = (Faction)2;
((Character)h).m_boss = false;
((Character)h).m_health = 100f;
((Character)h).m_walkSpeed = 2f;
((Character)h).m_runSpeed = 7f;
((Character)h).m_speed = 5f;
((Character)h).m_crouchSpeed = 2f;
((Character)h).m_turnSpeed = 300f;
((Character)h).m_runTurnSpeed = 300f;
((Character)h).m_acceleration = 1f;
((Character)h).m_jumpForce = 8f;
((Character)h).m_jumpForceForward = 2f;
((Character)h).m_canSwim = true;
((Character)h).m_swimDepth = 2f;
((Character)h).m_swimSpeed = 2f;
((Character)h).m_swimTurnSpeed = 100f;
((Character)h).m_swimAcceleration = 0.05f;
((Character)h).m_tolerateWater = true;
((Character)h).m_staggerWhenBlocked = true;
((Character)h).m_staggerDamageFactor = 0f;
((Character)h).m_eye = Utils.FindChild(((Component)h).gameObject.transform, "EyePos", (IterativeSearchType)0);
((Character)h).m_hitEffects.m_effectPrefabs = BuildEffects(scene, "vfx_player_hit", "sfx_hit");
((Character)h).m_critHitEffects.m_effectPrefabs = BuildEffects(scene, "fx_crit");
((Character)h).m_backstabHitEffects.m_effectPrefabs = BuildEffects(scene, "fx_backstab");
((Character)h).m_deathEffects.m_effectPrefabs = BuildEffects(scene, "vfx_ghost_death", "sfx_ghost_death");
((Character)h).m_damageModifiers = new DamageModifiers
{
m_chop = (DamageModifier)3,
m_pickaxe = (DamageModifier)3,
m_spirit = (DamageModifier)3
};
h.m_defaultItems = Array.Empty<GameObject>();
h.m_randomWeapon = Array.Empty<GameObject>();
h.m_randomArmor = Array.Empty<GameObject>();
h.m_randomShield = Array.Empty<GameObject>();
h.m_randomSets = Array.Empty<ItemSet>();
}
private static void SetupMonsterAI(MonsterAI ai)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
((BaseAI)ai).m_viewRange = 30f;
((BaseAI)ai).m_viewAngle = 120f;
((BaseAI)ai).m_hearRange = 30f;
((BaseAI)ai).m_mistVision = true;
((BaseAI)ai).m_alertedEffects = new EffectList();
((BaseAI)ai).m_idleSound = new EffectList();
ai.m_wakeupEffects = new EffectList();
ai.m_sleepEffects = new EffectList();
((BaseAI)ai).m_pathAgentType = (AgentType)1;
((BaseAI)ai).m_moveMinAngle = 90f;
((BaseAI)ai).m_smoothMovement = true;
((BaseAI)ai).m_serpentMovement = false;
((BaseAI)ai).m_randomMoveInterval = 10f;
((BaseAI)ai).m_randomMoveRange = 15f;
ai.m_circulateWhileCharging = true;
ai.m_enableHuntPlayer = false;
ai.m_attackPlayerObjects = false;
ai.m_alertRange = 0f;
ai.m_interceptTimeMin = 0f;
ai.m_interceptTimeMax = 4f;
ai.m_circleTargetInterval = 3f;
ai.m_circleTargetDuration = 1f;
ai.m_circleTargetDistance = 4f;
ai.m_maxChaseDistance = 0f;
ai.m_fleeIfHurtWhenTargetCantBeReached = false;
ai.m_fleeIfNotAlerted = false;
ai.m_fleeIfLowHealth = 0f;
ai.m_sleeping = false;
ai.m_consumeItems = null;
((BaseAI)ai).m_avoidFire = false;
((BaseAI)ai).m_afraidOfFire = false;
((BaseAI)ai).m_avoidWater = false;
ai.m_avoidLand = false;
}
private static void RegisterPrefab(GameObject go, ZNetScene zNetScene)
{
int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)go).name);
zNetScene.m_prefabs.Add(go);
if (_namedPrefabsField?.GetValue(zNetScene) is Dictionary<int, GameObject> dictionary)
{
dictionary[stableHashCode] = go;
}
}
private static EffectData[] BuildEffects(ZNetScene scene, params string[] names)
{
//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)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
List<EffectData> list = new List<EffectData>();
foreach (string text in names)
{
GameObject prefab = scene.GetPrefab(text);
if ((Object)(object)prefab != (Object)null)
{
list.Add(new EffectData
{
m_prefab = prefab,
m_enabled = true,
m_variant = -1
});
}
}
return list.ToArray();
}
private static void DestroyComponent<T>(GameObject go) where T : Component
{
T component = go.GetComponent<T>();
if ((Object)(object)component != (Object)null)
{
Object.DestroyImmediate((Object)(object)component);
}
}
}
internal static class WanderingReflection
{
private static readonly MethodInfo _moveTo = AccessTools.Method(typeof(BaseAI), "MoveTo", new Type[4]
{
typeof(float),
typeof(Vector3),
typeof(float),
typeof(bool)
}, (Type[])null);
private static readonly MethodInfo _lookAt = AccessTools.Method(typeof(BaseAI), "LookAt", new Type[1] { typeof(Vector3) }, (Type[])null);
private static readonly MethodInfo _isLookingAt = AccessTools.Method(typeof(BaseAI), "IsLookingAt", new Type[3]
{
typeof(Vector3),
typeof(float),
typeof(bool)
}, (Type[])null);
private static readonly MethodInfo _setAlerted = AccessTools.Method(typeof(BaseAI), "SetAlerted", new Type[1] { typeof(bool) }, (Type[])null);
private static readonly MethodInfo _findEnemy = AccessTools.Method(typeof(BaseAI), "FindEnemy", (Type[])null, (Type[])null);
private static readonly MethodInfo _randomMovement = AccessTools.Method(typeof(BaseAI), "RandomMovement", new Type[3]
{
typeof(float),
typeof(Vector3),
typeof(bool)
}, (Type[])null);
private static readonly MethodInfo _randomMovementAroundPoint = AccessTools.Method(typeof(BaseAI), "RandomMovementArroundPoint", new Type[4]
{
typeof(float),
typeof(Vector3),
typeof(float),
typeof(bool)
}, (Type[])null);
private static readonly MethodInfo _isTakingOff = AccessTools.Method(typeof(BaseAI), "IsTakingOff", (Type[])null, (Type[])null);
private static readonly MethodInfo _haveFriendsInRange = AccessTools.Method(typeof(BaseAI), "HaveFriendsInRange", (Type[])null, (Type[])null);
private static readonly MethodInfo _haveFriendInRange = AccessTools.Method(typeof(BaseAI), "HaveFriendInRange", new Type[1] { typeof(float) }, (Type[])null);
private static readonly MethodInfo _haveHurtFriendInRange = AccessTools.Method(typeof(BaseAI), "HaveHurtFriendInRange", new Type[1] { typeof(float) }, (Type[])null);
internal static readonly FieldInfo TargetCreatureField = AccessTools.Field(typeof(MonsterAI), "m_targetCreature");
internal static readonly FieldInfo TargetStaticField = AccessTools.Field(typeof(MonsterAI), "m_targetStatic");
private static readonly FieldInfo _blockingField = AccessTools.Field(typeof(Character), "m_blocking");
private static readonly FieldInfo _blockTimerField = AccessTools.Field(typeof(Humanoid), "m_blockTimer");
internal static bool MoveTo(BaseAI ai, float dt, Vector3 point, float dist, bool run)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (_moveTo == null)
{
return false;
}
try
{
return (bool)_moveTo.Invoke(ai, new object[4] { dt, point, dist, run });
}
catch
{
return false;
}
}
internal static void LookAt(BaseAI ai, Vector3 point)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (_lookAt == null)
{
return;
}
try
{
_lookAt.Invoke(ai, new object[1] { point });
}
catch
{
}
}
internal static bool IsLookingAt(BaseAI ai, Vector3 point, float angle, bool inverted = false)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
if (_isLookingAt == null)
{
return false;
}
try
{
return (bool)_isLookingAt.Invoke(ai, new object[3] { point, angle, inverted });
}
catch
{
return false;
}
}
internal static void SetAlerted(BaseAI ai, bool alert)
{
if (_setAlerted == null)
{
return;
}
try
{
_setAlerted.Invoke(ai, new object[1] { alert });
}
catch
{
}
}
internal static Character FindEnemy(BaseAI ai)
{
if (_findEnemy == null)
{
return null;
}
try
{
object? obj = _findEnemy.Invoke(ai, null);
return (Character)((obj is Character) ? obj : null);
}
catch
{
return null;
}
}
internal static void RandomMovement(BaseAI ai, float dt, Vector3 center)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
if (_randomMovement == null)
{
return;
}
try
{
_randomMovement.Invoke(ai, new object[3] { dt, center, false });
}
catch
{
}
}
internal static void RandomMovementAroundPoint(BaseAI ai, float dt, Vector3 point, float distance, bool run)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
if (_randomMovementAroundPoint == null)
{
return;
}
try
{
_randomMovementAroundPoint.Invoke(ai, new object[4] { dt, point, distance, run });
}
catch
{
}
}
internal static bool IsTakingOff(BaseAI ai)
{
if (_isTakingOff == null)
{
return false;
}
try
{
return (bool)_isTakingOff.Invoke(ai, null);
}
catch
{
return false;
}
}
internal static void HaveFriendsInRange(BaseAI ai, float range, out Character hurtFriend, out Character friend)
{
hurtFriend = null;
friend = null;
if (_haveFriendsInRange == null)
{
return;
}
try
{
object[] array = new object[3] { range, null, null };
_haveFriendsInRange.Invoke(ai, array);
object obj = array[1];
hurtFriend = (Character)((obj is Character) ? obj : null);
object obj2 = array[2];
friend = (Character)((obj2 is Character) ? obj2 : null);
}
catch
{
}
}
internal static Character HaveHurtFriendInRange(BaseAI ai, float range)
{
if (_haveHurtFriendInRange == null)
{
return null;
}
try
{
object? obj = _haveHurtFriendInRange.Invoke(ai, new object[1] { range });
return (Character)((obj is Character) ? obj : null);
}
catch
{
return null;
}
}
internal static Character HaveFriendInRange(BaseAI ai, float range)
{
if (_haveFriendInRange == null)
{
return null;
}
try
{
object? obj = _haveFriendInRange.Invoke(ai, new object[1] { range });
return (Character)((obj is Character) ? obj : null);
}
catch
{
return null;
}
}
internal static Character GetTargetCreature(MonsterAI ai)
{
if ((Object)(object)ai == (Object)null || TargetCreatureField == null)
{
return null;
}
try
{
object? value = TargetCreatureField.GetValue(ai);
return (Character)((value is Character) ? value : null);
}
catch
{
return null;
}
}
internal static void SetTargetCreature(MonsterAI ai, Character target)
{
if ((Object)(object)ai == (Object)null || TargetCreatureField == null)
{
return;
}
try
{
TargetCreatureField.SetValue(ai, target);
}
catch
{
}
}
internal static bool TrySetBlocking(Character c, bool value)
{
if ((Object)(object)c == (Object)null || _blockingField == null)
{
return false;
}
try
{
_blockingField.SetValue(c, value);
return true;
}
catch
{
return false;
}
}
internal static bool GetBlocking(Character c)
{
if ((Object)(object)c == (Object)null || _blockingField == null)
{
return false;
}
try
{
return (bool)_blockingField.GetValue(c);
}
catch
{
return false;
}
}
internal static bool TrySetBlockTimer(Humanoid h, float value)
{
if ((Object)(object)h == (Object)null || _blockTimerField == null)
{
return false;
}
try
{
_blockTimerField.SetValue(h, value);
return true;
}
catch
{
return false;
}
}
}
public class WanderingTalk : MonoBehaviour
{
private ZNetView _nview;
private Character _character;
private float _talkTimer;
private const float MinInterval = 20f;
private const float MaxInterval = 45f;
private const float SpeechOffset = 1.8f;
private const float CullDistance = 30f;
private const float SpeechTTL = 4f;
private static readonly string[] IdleLines = new string[10] { "Who dares trespass here?", "I hear something...", "These lands are mine.", "Another day, another fool.", "Stay sharp.", "Something stirs...", "The wilds are not kind to strangers.", "I'll claim what I can.", "No rest for the weary.", "This place suits me just fine." };
private static readonly string[] CombatLines = new string[10] { "You picked the wrong fight!", "Stand and face me!", "Your gear will be mine!", "Is that all you've got?", "I've slain bigger than you!", "Come closer, coward!", "You'll regret this!", "For glory!", "To the death!", "You won't leave here alive!" };
private static readonly string[] SpotLines = new string[5] { "There you are!", "Fresh prey!", "You shouldn't have come here.", "Finally, a challenge!", "An intruder!" };
private bool _spottedPlayer;
private WanderingCombatAI _combatAI;
private void Awake()
{
_nview = ((Component)this).GetComponent<ZNetView>();
_character = ((Component)this).GetComponent<Character>();
_combatAI = ((Component)this).GetComponent<WanderingCombatAI>();
ResetTimer();
_talkTimer += Random.Range(0f, 22.5f);
}
private void Update()
{
if ((Object)(object)_nview == (Object)null || !_nview.IsOwner() || (Object)(object)_character == (Object)null || _character.GetHealth() <= 0f || (Object)(object)Chat.instance == (Object)null)
{
return;
}
bool flag = (Object)(object)_combatAI != (Object)null && _combatAI.IsEngaged;
if (flag && !_spottedPlayer)
{
_spottedPlayer = true;
Say(SpotLines[Random.Range(0, SpotLines.Length)]);
ResetTimer();
return;
}
_talkTimer -= Time.deltaTime;
if (!(_talkTimer > 0f))
{
ResetTimer();
if (flag)
{
Say(CombatLines[Random.Range(0, CombatLines.Length)]);
}
else
{
Say(IdleLines[Random.Range(0, IdleLines.Length)]);
}
}
}
private void Say(string text)
{
//IL_0021: 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)
if (!string.IsNullOrEmpty(text) && !((Object)(object)Chat.instance == (Object)null))
{
Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * 1.8f, 30f, 4f, "", text, false);
}
}
private void ResetTimer()
{
_talkTimer = Random.Range(20f, 45f);
}
}
}
namespace WanderingCompanions.Patches
{
[HarmonyPatch]
public static class CombatPatches
{
[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
[HarmonyPrefix]
private static bool MonsterAI_UpdateAI_Prefix(MonsterAI __instance, float dt, ref bool __result)
{
WanderingCombatAI component = ((Component)__instance).GetComponent<WanderingCombatAI>();
if ((Object)(object)component == (Object)null)
{
return true;
}
if (!component.IsEngaged)
{
Character targetCreature = WanderingReflection.GetTargetCreature(__instance);
if ((Object)(object)targetCreature != (Object)null && targetCreature.GetHealth() > 0f)
{
component.Engage(targetCreature);
}
}
if (component.IsEngaged)
{
__result = component.UpdateCombat(dt);
return false;
}
return true;
}
}
[HarmonyPatch]
public static class SpawnPatches
{
private static bool _entriesAdded;
[HarmonyPatch(typeof(ZNetScene), "Awake")]
[HarmonyPostfix]
private static void ZNetScene_Awake_Postfix(ZNetScene __instance)
{
_entriesAdded = false;
WanderingPrefabs.Init(__instance);
}
[HarmonyPatch(typeof(SpawnSystem), "Awake")]
[HarmonyPostfix]
private static void SpawnSystem_Awake_Postfix(SpawnSystem __instance)
{
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
if (_entriesAdded || !WanderingConfig.Enabled.Value)
{
return;
}
ZNetScene instance = ZNetScene.instance;
GameObject val = ((instance != null) ? instance.GetPrefab("WC_Wanderer") : null);
if ((Object)(object)val == (Object)null)
{
WanderingPlugin.Log.LogWarning((object)"[SpawnPatches] WC_Wanderer prefab not found — spawn entries not added.");
return;
}
if (__instance.m_spawnLists == null || __instance.m_spawnLists.Count == 0)
{
WanderingPlugin.Log.LogWarning((object)"[SpawnPatches] No spawn lists found on SpawnSystem.");
return;
}
List<SpawnData> spawners = __instance.m_spawnLists[0].m_spawners;
int num = 0;
foreach (Biome spawnBiome in BiomeGearTable.SpawnBiomes)
{
spawners.Add(CreateSpawnEntry(val, spawnBiome));
num++;
}
_entriesAdded = true;
WanderingPlugin.Log.LogInfo((object)$"[SpawnPatches] Added {num} wandering companion spawn entries.");
}
private static SpawnData CreateSpawnEntry(GameObject prefab, Biome biome)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: 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_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: 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_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: 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_005e: 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_006c: 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_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: 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_0127: 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_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: 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_015f: Expected O, but got Unknown
return new SpawnData
{
m_name = $"WC_Wanderer_{biome}",
m_prefab = prefab,
m_enabled = true,
m_biome = biome,
m_biomeArea = (BiomeArea)3,
m_maxSpawned = 1,
m_spawnInterval = WanderingConfig.SpawnInterval.Value,
m_spawnChance = WanderingConfig.SpawnChance.Value,
m_groupSizeMin = 1,
m_groupSizeMax = 1,
m_groupRadius = 0f,
m_huntPlayer = false,
m_spawnAtDay = true,
m_spawnAtNight = true,
m_minAltitude = 1f,
m_maxAltitude = 1000f,
m_minTilt = 0f,
m_maxTilt = 35f,
m_spawnRadiusMin = 50f,
m_spawnRadiusMax = 100f,
m_insidePlayerBase = false,
m_canSpawnCloseToPlayer = false,
m_inForest = true,
m_outsideForest = true,
m_inLava = false,
m_outsideLava = true,
m_minLevel = 1,
m_maxLevel = 1,
m_groundOffset = 0.5f,
m_requiredGlobalKey = "",
m_requiredEnvironments = new List<string>(),
m_spawnDistance = 10f,
m_minDistanceFromCenter = 0f,
m_maxDistanceFromCenter = 0f,
m_minOceanDepth = 0f,
m_maxOceanDepth = 0f
};
}
}
}