using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RaiderClans")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Hostile Player-Model Raiders & Infused Loot Mod for Valheim")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RaiderClans")] [assembly: AssemblyTitle("RaiderClans")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 RaiderClans { public interface IRaiderBehaviorFactory { void Attach(GameObject raiderObject); } public interface IStructureAttackAugment { bool CanApply(HitData hitData, Piece targetPiece); void Apply(HitData hitData, Piece targetPiece); } public sealed class TorchFireAugment : IStructureAttackAugment { public bool CanApply(HitData hitData, Piece targetPiece) { return false; } public void Apply(HitData hitData, Piece targetPiece) { RaiderClansPlugin.LogDebug("[TorchFireAugment] Would ignite " + (((targetPiece != null) ? ((Object)targetPiece).name : null) ?? "") + " once fire system is ready."); } } public sealed class PillagerBehaviorFactory : IRaiderBehaviorFactory { private static readonly StructurePriority[] DefaultPriorities = new StructurePriority[17] { new StructurePriority("guard_stone", null, 0), new StructurePriority("portal_wood", null, 1), new StructurePriority("piece_workbench", null, 2), new StructurePriority("piece_stonecutter", null, 3), new StructurePriority("forge", null, 4), new StructurePriority("blackforge", null, 5), new StructurePriority("mage_table", null, 6), new StructurePriority("artisan_table", null, 7), new StructurePriority(null, (PieceCategory)1, 8), new StructurePriority("piece_chest_blackmetal", null, 9), new StructurePriority("piece_chest_private", null, 10), new StructurePriority("piece_chest_wood", null, 11), new StructurePriority("piece_door_iron", null, 12), new StructurePriority("piece_door_secret", null, 13), new StructurePriority("piece_door", null, 14), new StructurePriority(null, (PieceCategory)3, 15), new StructurePriority(null, (PieceCategory)2, 16) }; private readonly IReadOnlyList _priorities; private readonly float _searchRadius; private readonly float _scanInterval; private readonly List _augments; private PillagerBehaviorFactory(IReadOnlyList priorities, float searchRadius, float scanInterval, IEnumerable augments) { _priorities = priorities; _searchRadius = searchRadius; _scanInterval = scanInterval; _augments = new List(augments ?? Array.Empty()); } public static PillagerBehaviorFactory CreateDefault() { return new PillagerBehaviorFactory(DefaultPriorities, 45f, 5f, new TorchFireAugment[1] { new TorchFireAugment() }); } public void Attach(GameObject raiderObject) { if (!((Object)(object)raiderObject == (Object)null)) { PillagerBehavior pillagerBehavior = raiderObject.GetComponent(); if ((Object)(object)pillagerBehavior == (Object)null) { pillagerBehavior = raiderObject.AddComponent(); } pillagerBehavior.Configure(_priorities, _searchRadius, _scanInterval, _augments); MonsterAI component = raiderObject.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_enableHuntPlayer = false; ((BaseAI)component).SetHuntPlayer(false); } } } } public class PillagerBehavior : MonoBehaviour { private enum PillagerState { Searching, StructureCommitted, AggroPlayer, NoStructures } private const float AggroMemorySeconds = 10f; private const float BlockCheckInterval = 0.5f; private const float BlockingDetectionRadius = 2.5f; private const float StructureProgressSampleInterval = 2f; private const float StructureProgressThreshold = 1.5f; private const float StructureStuckTimeout = 6f; private static readonly FieldRef TargetStaticField = AccessTools.FieldRefAccess("m_targetStatic"); private static readonly FieldRef TargetCreatureField = AccessTools.FieldRefAccess("m_targetCreature"); private MonsterAI _monsterAI; private BaseAI _baseAI; private Character _character; private ZNetView _nview; private readonly List _structureBuffer = new List(64); private readonly List _augments = new List(); private IReadOnlyList _priorities = Array.Empty(); private float _searchRadius = 40f; private float _scanInterval = 5f; private float _nextScanTime; private float _nextBlockCheck; private Piece _currentStructureTarget; private Character _currentAggressor; private float _aggroExpiry; private float _structureProgressSampleTime; private float _previousStructureDistance; private float _structureStuckTimer; private PillagerState _state = PillagerState.Searching; public void Configure(IReadOnlyList priorities, float searchRadius, float scanInterval, IEnumerable augments) { _priorities = priorities ?? Array.Empty(); _searchRadius = Mathf.Max(5f, searchRadius); _scanInterval = Mathf.Max(1f, scanInterval); _augments.Clear(); if (augments != null) { _augments.AddRange(augments); } } private void Awake() { _monsterAI = ((Component)this).GetComponent(); _baseAI = (BaseAI)(object)_monsterAI; _character = ((Component)this).GetComponent(); _nview = ((Component)this).GetComponent(); if ((Object)(object)_character != (Object)null) { Character character = _character; character.m_onDamaged = (Action)Delegate.Combine(character.m_onDamaged, new Action(OnDamaged)); } } private void OnDestroy() { if ((Object)(object)_character != (Object)null) { Character character = _character; character.m_onDamaged = (Action)Delegate.Remove(character.m_onDamaged, new Action(OnDamaged)); } } private void Update() { if (!ShouldRun()) { return; } float deltaTime = Time.deltaTime; if (UpdateAggroState()) { MaintainAggressorTarget(); return; } MaintainStructureTarget(deltaTime); ScanForStructureTargets(); if ((Object)(object)_currentStructureTarget != (Object)null) { CheckBlockingPlayer(); } } internal static void TryHandleStructureHit(Character attacker, Piece targetPiece, HitData hitData) { if (!((Object)(object)attacker == (Object)null) && !((Object)(object)targetPiece == (Object)null) && hitData != null) { ((Component)attacker).GetComponent()?.ApplyAugments(targetPiece, hitData); } } private bool ShouldRun() { if ((Object)(object)_monsterAI == (Object)null || (Object)(object)_baseAI == (Object)null || (Object)(object)_character == (Object)null || (Object)(object)_nview == (Object)null) { return false; } if (!_nview.IsValid() || !_nview.IsOwner()) { return false; } return true; } private void OnDamaged(float damage, Character attacker) { if (!((Object)(object)attacker == (Object)null) && !attacker.IsDead() && attacker.IsPlayer()) { AdoptAggressor(attacker); } } private bool UpdateAggroState() { //IL_0042: 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 ((Object)(object)_currentAggressor == (Object)null) { return false; } _state = PillagerState.AggroPlayer; if (_currentAggressor.IsDead() || Time.time > _aggroExpiry || Vector3.Distance(((Component)_currentAggressor).transform.position, ((Component)this).transform.position) > _searchRadius * 1.5f) { ClearAggressor(); } return (Object)(object)_currentAggressor != (Object)null; } private void MaintainAggressorTarget() { if (!((Object)(object)_monsterAI == (Object)null) && !((Object)(object)_currentAggressor == (Object)null)) { TargetStaticField.Invoke(_monsterAI) = null; Character val = TargetCreatureField.Invoke(_monsterAI); if ((Object)(object)val != (Object)(object)_currentAggressor) { TargetCreatureField.Invoke(_monsterAI) = _currentAggressor; } ((BaseAI)_monsterAI).Alert(); } } private void ClearAggressor() { _currentAggressor = null; _aggroExpiry = 0f; if ((Object)(object)_monsterAI != (Object)null) { TargetCreatureField.Invoke(_monsterAI) = null; if (((BaseAI)_monsterAI).HuntPlayer()) { ((BaseAI)_monsterAI).SetHuntPlayer(false); } } _state = (((Object)(object)_currentStructureTarget != (Object)null) ? PillagerState.StructureCommitted : PillagerState.Searching); } private void AdoptAggressor(Character aggressor) { if (!((Object)(object)aggressor == (Object)null)) { _currentAggressor = aggressor; _aggroExpiry = Time.time + 10f; BaseAI baseAI = _baseAI; if (baseAI != null) { baseAI.SetAggravated(true, (AggravatedReason)0); } if ((Object)(object)_monsterAI != (Object)null && !((BaseAI)_monsterAI).HuntPlayer()) { ((BaseAI)_monsterAI).SetHuntPlayer(true); } } } private void ScanForStructureTargets() { //IL_003a: 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) if (Time.time < _nextScanTime) { return; } _nextScanTime = Time.time + _scanInterval; if (!HasValidStructureTarget()) { RaiderTargetingService.FindPlayerStructures(((Component)this).transform.position, _searchRadius, _structureBuffer); Piece val = RaiderTargetingService.SelectHighestPriorityStructure(_structureBuffer, _priorities, ((Component)this).transform.position); if ((Object)(object)val == (Object)null) { HandleNoStructuresFound(); } else { AssignStructureTarget(val); } } } private void MaintainStructureTarget(float dt) { if (HasValidStructureTarget()) { StaticTarget val = TargetStaticField.Invoke(_monsterAI); if ((Object)(object)val != (Object)(object)_currentStructureTarget) { TargetStaticField.Invoke(_monsterAI) = (StaticTarget)(object)_currentStructureTarget; TargetCreatureField.Invoke(_monsterAI) = null; } UpdateStructureProgress(dt); } } internal bool ShouldPreferStructureTarget() { return (Object)(object)_currentStructureTarget != (Object)null && (Object)(object)_currentAggressor == (Object)null; } private void AssignStructureTarget(Piece piece) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) _currentStructureTarget = piece; if (!((Object)(object)_monsterAI == (Object)null)) { TargetCreatureField.Invoke(_monsterAI) = null; TargetStaticField.Invoke(_monsterAI) = (StaticTarget)(object)piece; BaseAI baseAI = _baseAI; if (baseAI != null) { baseAI.SetAggravated(true, (AggravatedReason)0); } ((BaseAI)_monsterAI).Alert(); _state = PillagerState.StructureCommitted; _structureStuckTimer = 0f; _previousStructureDistance = Vector3.Distance(((Component)this).transform.position, ((Component)piece).transform.position); _structureProgressSampleTime = Time.time + 2f; } } private void ClearStructureTarget() { _currentStructureTarget = null; if ((Object)(object)_monsterAI != (Object)null) { TargetStaticField.Invoke(_monsterAI) = null; } _state = PillagerState.Searching; _structureStuckTimer = 0f; } private void CheckBlockingPlayer() { //IL_003f: 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) if ((Object)(object)_currentStructureTarget == (Object)null || Time.time < _nextBlockCheck) { return; } _nextBlockCheck = Time.time + 0.5f; Character val = RaiderTargetingService.FindBlockingPlayer(((Component)this).transform.position, ((Component)_currentStructureTarget).transform.position, 2.5f); if ((Object)(object)val != (Object)null && val.IsPlayer()) { MonsterAI monsterAI = _monsterAI; if (monsterAI != null) { ((BaseAI)monsterAI).Alert(); } } } private void ApplyAugments(Piece targetPiece, HitData hitData) { if ((Object)(object)targetPiece == (Object)null || hitData == null || _augments.Count == 0) { return; } foreach (IStructureAttackAugment augment in _augments) { if (augment != null && augment.CanApply(hitData, targetPiece)) { augment.Apply(hitData, targetPiece); } } } private bool HasValidStructureTarget() { if ((Object)(object)_currentStructureTarget == (Object)null) { return false; } if ((Object)(object)((Component)_currentStructureTarget).gameObject == (Object)null || !((Component)_currentStructureTarget).gameObject.activeInHierarchy || !_currentStructureTarget.IsPlacedByPlayer()) { ClearStructureTarget(); return false; } return true; } private void UpdateStructureProgress(float dt) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_currentStructureTarget == (Object)null) { return; } float num = Vector3.Distance(((Component)this).transform.position, ((Component)_currentStructureTarget).transform.position); if (num <= 2.5f) { _structureStuckTimer = 0f; } else { if (Time.time < _structureProgressSampleTime) { return; } float num2 = _previousStructureDistance - num; if (num2 < 1.5f) { _structureStuckTimer += 2f; if (_structureStuckTimer >= 6f) { RaiderClansPlugin.LogDebug("[PillagerBehavior] Structure target unreachable, searching for a new one."); ClearStructureTarget(); return; } } else { _structureStuckTimer = 0f; } _previousStructureDistance = num; _structureProgressSampleTime = Time.time + 2f; } } private void HandleNoStructuresFound() { _state = PillagerState.NoStructures; TargetStaticField.Invoke(_monsterAI) = null; } } [HarmonyPatch(typeof(WearNTear), "RPC_Damage")] internal static class PillagerStructureHitPatch { private static void Prefix(WearNTear __instance, HitData hit) { if ((Object)(object)__instance == (Object)null || hit == null) { return; } Character attacker = hit.GetAttacker(); if (!((Object)(object)attacker == (Object)null)) { Piece component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { PillagerBehavior.TryHandleStructureHit(attacker, component, hit); } } } } public class RaiderAI { public readonly struct RaiderSpawnRequest { public Vector3 Position { get; } public Biome Biome { get; } public RaiderRole Role { get; } public RaiderSpawnRequest(Vector3 position, Biome biome, RaiderRole role) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Position = position; Biome = biome; Role = role; } } public const string RaiderCustomDataKey = "RaiderClans_IsRaider"; private const string ChieftainCustomDataKey = "RaiderClans_IsChieftain"; private const string BiomeCustomDataKey = "RaiderClans_Biome"; private const string RoleCustomDataKey = "RaiderClans_Role"; private const string MinimalPrefabName = "RaiderClan_Minimal"; private static bool s_minimalPrefabRegistered; private static readonly Dictionary s_damageEffects = new Dictionary(); public static void Initialize() { RaiderRoleRegistry.Initialize(); PrefabManager.OnVanillaPrefabsAvailable += RegisterMinimalRaiderPrefab; } private static void RegisterMinimalRaiderPrefab() { if (!s_minimalPrefabRegistered) { RaiderClansPlugin.LogDebug("Registering minimal raider NPC prefab via Jotunn"); GameObject val = CreateMinimalRaiderPrefab("RaiderClan_Minimal"); if ((Object)(object)val != (Object)null) { PrefabManager.Instance.AddPrefab(val); s_minimalPrefabRegistered = true; RaiderClansPlugin.Logger.LogInfo((object)"Minimal raider prefab registered successfully via Jotunn"); } else { RaiderClansPlugin.Logger.LogError((object)"Failed to register minimal raider prefab"); } } } private static GameObject CreateMinimalRaiderPrefab(string prefabName) { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) RaiderClansPlugin.LogDebug("Creating " + prefabName + " prefab (minimal Player clone)"); GameObject val = PrefabManager.Instance.CreateClonedPrefab(prefabName, "Player"); if ((Object)(object)val == (Object)null) { RaiderClansPlugin.Logger.LogError((object)"Failed to clone Player prefab"); return null; } PlayerController component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } AudioListener[] componentsInChildren = val.GetComponentsInChildren(true); foreach (AudioListener val2 in componentsInChildren) { Object.DestroyImmediate((Object)(object)val2); } GuidePoint[] componentsInChildren2 = val.GetComponentsInChildren(true); foreach (GuidePoint val3 in componentsInChildren2) { Object.DestroyImmediate((Object)(object)val3); } Player component2 = val.GetComponent(); if ((Object)(object)component2 == (Object)null) { RaiderClansPlugin.Logger.LogError((object)"Player clone missing Player component!"); return null; } ItemDrop unarmedWeapon = ((Humanoid)component2).m_unarmedWeapon; EffectList consumeItemEffects = ((Humanoid)component2).m_consumeItemEffects; EffectList equipEffects = ((Humanoid)component2).m_equipEffects; Object.DestroyImmediate((Object)(object)component2); Humanoid val4 = val.AddComponent(); val4.m_unarmedWeapon = unarmedWeapon; val4.m_consumeItemEffects = consumeItemEffects; val4.m_equipEffects = equipEffects; Character val5 = (Character)(object)val4; if ((Object)(object)val5 != (Object)null) { val5.m_name = "Clan Raider"; val5.m_group = "Raiders"; val5.m_faction = (Faction)3; val5.m_walkSpeed = 2f; val5.m_runSpeed = 4f; val5.m_health = 100f; val5.m_staggerWhenBlocked = true; val5.m_staggerDamageFactor = 0.2f; Transform val6 = Utils.FindChild(val.transform, "EyePos", (IterativeSearchType)0); if ((Object)(object)val6 == (Object)null) { GameObject val7 = new GameObject("EyePos"); val7.transform.SetParent(val.transform); val7.transform.localPosition = new Vector3(0f, 1.6f, 0f); val6 = val7.transform; } val5.m_eye = val6; CharacterDrop val8 = val.GetComponent(); if ((Object)(object)val8 == (Object)null) { val8 = val.AddComponent(); } val8.m_dropsEnabled = true; } MonsterAI val9 = val.AddComponent(); ((BaseAI)val9).m_viewRange = 60f; ((BaseAI)val9).m_viewAngle = 90f; ((BaseAI)val9).m_hearRange = 30f; ((BaseAI)val9).m_aggravatable = true; val9.m_attackPlayerObjects = true; val9.m_enableHuntPlayer = true; val9.m_minAttackInterval = 2f; val9.m_circleTargetInterval = 0f; ((BaseAI)val9).m_randomMoveInterval = 1f; ((BaseAI)val9).m_randomMoveRange = 5f; RaiderClansPlugin.LogDebug(prefabName + " prefab created successfully"); return val; } public static Humanoid SpawnRaider(Vector3 position, Biome biome, bool isChieftain = false, bool isRanged = false) { //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) RaiderRole role = (isChieftain ? RaiderRole.Chieftain : RaiderRole.Warrior); if (isRanged) { RaiderClansPlugin.LogDebug("Ranged raiders not yet implemented; defaulting to melee role behavior."); } return SpawnRaider(new RaiderSpawnRequest(position, biome, role)); } public static Humanoid SpawnRaider(RaiderSpawnRequest request) { //IL_0014: 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_0073: 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_007b: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected I4, but got Unknown //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) RaiderClansPlugin.LogDebug($"Attempting to spawn raider role {request.Role} at {request.Position}"); GameObject prefab = ZNetScene.instance.GetPrefab("RaiderClan_Minimal"); if ((Object)(object)prefab == (Object)null) { RaiderClansPlugin.Logger.LogError((object)"Could not find RaiderClan_Minimal template in ZNetScene"); return null; } RaiderRoleConfig config = RaiderRoleRegistry.GetConfig(request.Role); Vector3 position = request.Position; Biome biome = request.Biome; GameObject val = Object.Instantiate(prefab, position, Quaternion.identity); if ((Object)(object)val == (Object)null) { RaiderClansPlugin.Logger.LogError((object)"Failed to instantiate raider"); return null; } RaiderClansPlugin.LogDebug("Spawned minimal raider instance: " + ((Object)val).name); Humanoid component = val.GetComponent(); if ((Object)(object)component == (Object)null) { RaiderClansPlugin.Logger.LogError((object)"Failed to get Humanoid component from spawned raider"); ZNetScene.instance.Destroy(val); return null; } Character component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 == (Object)null) { RaiderClansPlugin.Logger.LogError((object)"Spawned raider missing Character component"); ZNetScene.instance.Destroy(val); return null; } component2.m_faction = (Faction)3; component2.m_name = "Clan Raider"; ZNetView val2 = ((Character)component).m_nview ?? val.GetComponent(); ZDO val3 = ((val2 != null) ? val2.GetZDO() : null); if (val3 != null) { val3.Set("RaiderClans_IsRaider", true); val3.Set("RaiderClans_IsChieftain", request.Role == RaiderRole.Chieftain); val3.Set("RaiderClans_Biome", (int)biome); val3.Set("RaiderClans_Role", (int)request.Role); } else { RaiderClansPlugin.Logger.LogWarning((object)"Spawned raider without valid ZDO; custom metadata unavailable"); } float baseHealthForBiome = RaiderRoleRegistry.GetBaseHealthForBiome(biome); float num = Mathf.Max(50f, baseHealthForBiome * config.HealthMultiplier); component2.SetMaxHealth(num); component2.SetHealth(num); CharacterDrop component3 = val.GetComponent(); RaiderLoot.ConfigureCharacterDrop(component3, biome); ApplyRoleConfiguration(component, val, config, biome); RaiderClansPlugin.LogDebug("Successfully spawned minimal raider"); return component; } private static void ApplyRoleConfiguration(Humanoid raider, GameObject raiderObj, RaiderRoleConfig config, Biome biome) { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)raider == (Object)null || config == null) { return; } Character component = ((Component)raider).GetComponent(); if ((Object)(object)component != (Object)null) { component.m_name = "Clan " + config.DisplayName; component.m_walkSpeed *= config.MoveSpeedMultiplier; component.m_runSpeed *= config.MoveSpeedMultiplier; if (Mathf.Abs(config.ModelScale - 1f) > 0.01f) { raiderObj.transform.localScale = Vector3.Scale(raiderObj.transform.localScale, new Vector3(config.ModelScale, config.ModelScale, config.ModelScale)); } } MonsterAI component2 = ((Component)raider).GetComponent(); if ((Object)(object)component2 != (Object)null) { ((BaseAI)component2).m_pathAgentType = (AgentType)10; if (config.Role == RaiderRole.Pillager) { component2.m_enableHuntPlayer = false; ((BaseAI)component2).SetHuntPlayer(false); } } ApplyDefaultItems(raider, config.ResolveDefaultItems(biome)); config.BehaviorFactory?.Attach(raiderObj); ApplyDamageMultiplier(component, config); } private static void ApplyDefaultItems(Humanoid humanoid, IReadOnlyList prefabNames) { if ((Object)(object)humanoid == (Object)null || prefabNames == null || prefabNames.Count == 0) { return; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { RaiderClansPlugin.Logger.LogWarning((object)"ObjectDB not ready; cannot equip raider role items."); return; } List list = new List(); foreach (string prefabName in prefabNames) { if (!string.IsNullOrWhiteSpace(prefabName)) { GameObject itemPrefab = instance.GetItemPrefab(prefabName); if ((Object)(object)itemPrefab != (Object)null) { list.Add(itemPrefab); } else { RaiderClansPlugin.Logger.LogWarning((object)("Missing item prefab '" + prefabName + "' for raider role " + ((Object)humanoid).name)); } } } if (list.Count != 0) { humanoid.m_defaultItems = list.ToArray(); GameObject[] defaultItems = humanoid.m_defaultItems; foreach (GameObject val in defaultItems) { humanoid.GiveDefaultItem(val); } } } private static void ApplyDamageMultiplier(Character character, RaiderRoleConfig config) { if ((Object)(object)character == (Object)null || config == null || Mathf.Approximately(config.DamageMultiplier, 1f)) { return; } SEMan sEMan = character.GetSEMan(); if (sEMan != null) { StatusEffect damageEffectTemplate = GetDamageEffectTemplate(config); if ((Object)(object)damageEffectTemplate != (Object)null) { sEMan.AddStatusEffect(damageEffectTemplate, true, 0, 0f); } } } private static StatusEffect GetDamageEffectTemplate(RaiderRoleConfig config) { //IL_005f: 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_0081: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown if (s_damageEffects.TryGetValue(config.Role, out var value)) { return value; } SE_Stats val = ScriptableObject.CreateInstance(); ((Object)val).name = $"SE_Raider_{config.Role}_Damage"; ((StatusEffect)val).m_name = ((Object)val).name; val.m_damageModifier = config.DamageMultiplier; val.m_modifyAttackSkill = (SkillType)999; ((StatusEffect)val).m_icon = null; ((StatusEffect)val).m_tooltip = string.Empty; ((StatusEffect)val).m_startEffects = new EffectList(); ((StatusEffect)val).m_stopEffects = new EffectList(); ((StatusEffect)val).m_ttl = 0f; ((StatusEffect)val).m_cooldown = 0f; s_damageEffects[config.Role] = (StatusEffect)(object)val; return (StatusEffect)(object)val; } public static bool IsRaider(Character character) { if (character?.m_nview?.m_zdo == null) { return false; } return character.m_nview.m_zdo.GetBool("RaiderClans_IsRaider", false); } public static RaiderRole? GetRole(Character character) { if (character?.m_nview?.m_zdo == null) { return null; } int num = character.m_nview.m_zdo.GetInt("RaiderClans_Role", -1); if (num == -1) { return null; } return (RaiderRole)num; } public static bool IsChieftain(Character character) { if (character?.m_nview?.m_zdo == null) { return false; } return character.m_nview.m_zdo.GetBool("RaiderClans_IsChieftain", false); } } [HarmonyPatch] internal class RaiderClansDevCommands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; public static ConsoleOptionsFetcher <>9__0_1; public static ConsoleEvent <>9__0_2; public static ConsoleOptionsFetcher <>9__0_3; public static ConsoleOptionsFetcher <>9__0_4; public static ConsoleEvent <>9__0_5; public static ConsoleEvent <>9__0_6; public static ConsoleEvent <>9__0_7; public static ConsoleEvent <>9__0_8; public static ConsoleOptionsFetcher <>9__0_9; public static ConsoleEvent <>9__0_10; public static ConsoleOptionsFetcher <>9__0_11; public static ConsoleEvent <>9__0_12; public static ConsoleEvent <>9__0_13; internal void b__0_0(ConsoleEventArgs args) { //IL_002c: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_0133: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); return; } Biome val = (Biome)1; if (args.Length >= 2) { if (Enum.TryParse(args[1], ignoreCase: true, out Biome result)) { val = result; } else { args.Context.AddString("Invalid biome: " + args[1] + ". Using Meadows."); } } bool result2 = false; if (args.Length >= 3) { bool.TryParse(args[2], out result2); } Vector3 val2 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 3f; Humanoid val3 = RaiderAI.SpawnRaider(val2, val, result2); if ((Object)(object)val3 != (Object)null) { args.Context.AddString(string.Format("Spawned {0} for biome {1} at {2}", result2 ? "Chieftain" : "Raider", val, val2)); RaiderClansPlugin.Logger.LogInfo((object)$"Dev command spawned raider: Biome={val}, Chieftain={result2}, Pos={val2}"); } else { args.Context.AddString("Failed to spawn raider - check logs"); } } internal List b__0_1() { return new List { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" }; } internal void b__0_2(ConsoleEventArgs args) { //IL_004e: 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_007b: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); } else if (args.Length >= 2) { if (Enum.TryParse(args[1], ignoreCase: true, out Biome result)) { RaiderEvents.StartRaidManually(result); args.Context.AddString($"Raider clan raid event started for {result}!"); RaiderClansPlugin.Logger.LogInfo((object)$"Dev command started raid event for biome {result}"); } else { args.Context.AddString("Invalid biome '" + args[1] + "'."); } } else { RaiderEvents.StartRaidManually(); args.Context.AddString("Raider clan raid event started!"); RaiderClansPlugin.Logger.LogInfo((object)"Dev command started raid event"); } } internal List b__0_3() { return new List { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" }; } internal List b__0_4() { return new List { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" }; } internal void b__0_5(ConsoleEventArgs args) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0072: 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) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); return; } Vector2i zone = ZoneSystem.GetZone(((Component)Player.m_localPlayer).transform.position); args.Context.AddString($"Processing zone {zone}..."); RaiderClansPlugin.Logger.LogInfo((object)$"Dev command processing zone: {zone}"); int num = RaiderTowerOverwrites.ProcessZoneLocations(zone); args.Context.AddString($"Processed {num} locations in zone {zone}"); } internal void b__0_6(ConsoleEventArgs args) { if (args.Length >= 2) { if (args[1].ToLower() == "on") { RaiderClansPlugin.EnableDebugLogging.Value = true; args.Context.AddString("Debug logging enabled"); } else if (args[1].ToLower() == "off") { RaiderClansPlugin.EnableDebugLogging.Value = false; args.Context.AddString("Debug logging disabled"); } } else { args.Context.AddString("Debug logging is currently " + (RaiderClansPlugin.EnableDebugLogging.Value ? "enabled" : "disabled")); } } internal void b__0_7(ConsoleEventArgs args) { HashSet processedLocations = RaiderTowerOverwrites.GetProcessedLocations(); args.Context.AddString($"Processed {processedLocations.Count} locations:"); foreach (string item in processedLocations) { args.Context.AddString(" - " + item); } } internal void b__0_8(ConsoleEventArgs args) { //IL_0067: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00bc: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); return; } if (args.Length < 2 || !Enum.TryParse(args[1], ignoreCase: true, out var result)) { args.Context.AddString("Usage: raiderclan_spawnrole [Biome]"); return; } Biome val = (Biome)1; if (args.Length >= 3 && Enum.TryParse(args[2], ignoreCase: true, out Biome result2)) { val = result2; } Vector3 val2 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 3f; Humanoid val3 = RaiderAI.SpawnRaider(new RaiderAI.RaiderSpawnRequest(val2, val, result)); args.Context.AddString(((Object)(object)val3 != (Object)null) ? $"Spawned {result} with {val} loadout at {val2}" : "Failed to spawn raider"); } internal List b__0_9() { return new List { "Warrior", "Pillager", "Chieftain" }; } internal void b__0_10(ConsoleEventArgs args) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00b2: 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_012f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); return; } if (args.Length < 2) { args.Context.AddString("Usage: raiderclan_spawngarrison [radius]"); return; } string text = args[1].ToLowerInvariant(); float num = 20f; if (args.Length >= 3 && float.TryParse(args[2], out var result)) { num = Mathf.Clamp(result, 5f, 50f); } GameObject val = new GameObject("RaiderClans_GarrisonRoot"); val.transform.position = ((Component)Player.m_localPlayer).transform.position; if (text == "tower") { RaiderTowerOverwrites.SpawnTowerRaiders(val); args.Context.AddString($"Spawned tower garrison at {val.transform.position} (radius {num})"); } else if (text == "village") { RaiderTowerOverwrites.SpawnVillageRaiders(val); args.Context.AddString($"Spawned village garrison at {val.transform.position} (radius {num})"); } else { args.Context.AddString("Invalid garrison type. Use 'tower' or 'village'."); } Object.Destroy((Object)(object)val); } internal List b__0_11() { return new List { "tower", "village" }; } internal void b__0_12(ConsoleEventArgs args) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); return; } if (args.Length < 2 || !int.TryParse(args[1], out var result)) { args.Context.AddString("Usage: raiderclan_wave "); return; } if (!RaiderEvents.IsRaidActive()) { RaiderEvents.StartRaidManually(); } MethodInfo methodInfo = AccessTools.Method(typeof(RaiderEvents), "SpawnWave", (Type[])null, (Type[])null); for (int i = 0; i < result; i++) { methodInfo.Invoke(null, null); } args.Context.AddString($"Spawned raid wave {result}"); } internal void b__0_13(ConsoleEventArgs args) { //IL_002a: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0086: 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_009e: 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_0054: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); return; } Biome val = (Biome)1; if (args.Length >= 2 && Enum.TryParse(args[1], ignoreCase: true, out Biome result)) { val = result; } Vector3 val2 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 2f; RaiderLoot.DropRegularLoot(val2, val); args.Context.AddString($"Spawned regular loot for {val} biome at {val2}"); } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] [HarmonyPostfix] private static void AddCustomCommands() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0051: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_006b: 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_0076: Expected O, but got Unknown //IL_00a9: 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_00a6: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_0151: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown //IL_0203: 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_020e: Expected O, but got Unknown //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Expected O, but got Unknown //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { //IL_002c: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_0133: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); } else { Biome val16 = (Biome)1; if (args.Length >= 2) { if (Enum.TryParse(args[1], ignoreCase: true, out Biome result)) { val16 = result; } else { args.Context.AddString("Invalid biome: " + args[1] + ". Using Meadows."); } } bool result2 = false; if (args.Length >= 3) { bool.TryParse(args[2], out result2); } Vector3 val17 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 3f; Humanoid val18 = RaiderAI.SpawnRaider(val17, val16, result2); if ((Object)(object)val18 != (Object)null) { args.Context.AddString(string.Format("Spawned {0} for biome {1} at {2}", result2 ? "Chieftain" : "Raider", val16, val17)); RaiderClansPlugin.Logger.LogInfo((object)$"Dev command spawned raider: Biome={val16}, Chieftain={result2}, Pos={val17}"); } else { args.Context.AddString("Failed to spawn raider - check logs"); } } }; <>c.<>9__0_0 = val; obj = (object)val; } object obj2 = <>c.<>9__0_1; if (obj2 == null) { ConsoleOptionsFetcher val2 = () => new List { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" }; <>c.<>9__0_1 = val2; obj2 = (object)val2; } new ConsoleCommand("raiderclan_spawn", "[biome] [isChieftain] - Spawn a test raider", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false); object obj3 = <>c.<>9__0_2; if (obj3 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { //IL_004e: 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_007b: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); } else if (args.Length >= 2) { if (Enum.TryParse(args[1], ignoreCase: true, out Biome result)) { RaiderEvents.StartRaidManually(result); args.Context.AddString($"Raider clan raid event started for {result}!"); RaiderClansPlugin.Logger.LogInfo((object)$"Dev command started raid event for biome {result}"); } else { args.Context.AddString("Invalid biome '" + args[1] + "'."); } } else { RaiderEvents.StartRaidManually(); args.Context.AddString("Raider clan raid event started!"); RaiderClansPlugin.Logger.LogInfo((object)"Dev command started raid event"); } }; <>c.<>9__0_2 = val3; obj3 = (object)val3; } ConsoleEvent val4 = (ConsoleEvent)obj3; object obj4 = <>c.<>9__0_3; if (obj4 == null) { ConsoleOptionsFetcher val5 = () => new List { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" }; <>c.<>9__0_3 = val5; obj4 = (object)val5; } new ConsoleCommand("raiderclan_startraid", "[biome] - Start a raider clan raid event (optional biome override)", val4, true, false, false, false, false, (ConsoleOptionsFetcher)obj4, false, false, false); object obj5 = <>c.<>9__0_4; if (obj5 == null) { ConsoleOptionsFetcher val6 = () => new List { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" }; <>c.<>9__0_4 = val6; obj5 = (object)val6; } new ConsoleCommand("raidclan_startraid", "[biome] - Alias for raiderclan_startraid", val4, true, false, false, false, false, (ConsoleOptionsFetcher)obj5, false, false, false); object obj6 = <>c.<>9__0_5; if (obj6 == null) { ConsoleEvent val7 = delegate(ConsoleEventArgs args) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0072: 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) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); } else { Vector2i zone = ZoneSystem.GetZone(((Component)Player.m_localPlayer).transform.position); args.Context.AddString($"Processing zone {zone}..."); RaiderClansPlugin.Logger.LogInfo((object)$"Dev command processing zone: {zone}"); int num = RaiderTowerOverwrites.ProcessZoneLocations(zone); args.Context.AddString($"Processed {num} locations in zone {zone}"); } }; <>c.<>9__0_5 = val7; obj6 = (object)val7; } new ConsoleCommand("raiderclan_processzone", "- Force process locations in current zone", (ConsoleEvent)obj6, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj7 = <>c.<>9__0_6; if (obj7 == null) { ConsoleEvent val8 = delegate(ConsoleEventArgs args) { if (args.Length >= 2) { if (args[1].ToLower() == "on") { RaiderClansPlugin.EnableDebugLogging.Value = true; args.Context.AddString("Debug logging enabled"); } else if (args[1].ToLower() == "off") { RaiderClansPlugin.EnableDebugLogging.Value = false; args.Context.AddString("Debug logging disabled"); } } else { args.Context.AddString("Debug logging is currently " + (RaiderClansPlugin.EnableDebugLogging.Value ? "enabled" : "disabled")); } }; <>c.<>9__0_6 = val8; obj7 = (object)val8; } new ConsoleCommand("raiderclan_debug", "[on/off] - Toggle debug logging", (ConsoleEvent)obj7, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj8 = <>c.<>9__0_7; if (obj8 == null) { ConsoleEvent val9 = delegate(ConsoleEventArgs args) { HashSet processedLocations = RaiderTowerOverwrites.GetProcessedLocations(); args.Context.AddString($"Processed {processedLocations.Count} locations:"); foreach (string item in processedLocations) { args.Context.AddString(" - " + item); } }; <>c.<>9__0_7 = val9; obj8 = (object)val9; } new ConsoleCommand("raiderclan_listlocations", "- List all processed locations", (ConsoleEvent)obj8, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj9 = <>c.<>9__0_8; if (obj9 == null) { ConsoleEvent val10 = delegate(ConsoleEventArgs args) { //IL_0067: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00bc: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) RaiderRole result; if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); } else if (args.Length < 2 || !Enum.TryParse(args[1], ignoreCase: true, out result)) { args.Context.AddString("Usage: raiderclan_spawnrole [Biome]"); } else { Biome val16 = (Biome)1; if (args.Length >= 3 && Enum.TryParse(args[2], ignoreCase: true, out Biome result2)) { val16 = result2; } Vector3 val17 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 3f; Humanoid val18 = RaiderAI.SpawnRaider(new RaiderAI.RaiderSpawnRequest(val17, val16, result)); args.Context.AddString(((Object)(object)val18 != (Object)null) ? $"Spawned {result} with {val16} loadout at {val17}" : "Failed to spawn raider"); } }; <>c.<>9__0_8 = val10; obj9 = (object)val10; } object obj10 = <>c.<>9__0_9; if (obj10 == null) { ConsoleOptionsFetcher val11 = () => new List { "Warrior", "Pillager", "Chieftain" }; <>c.<>9__0_9 = val11; obj10 = (object)val11; } new ConsoleCommand("raiderclan_spawnrole", " [biome] - Spawn a specific raider role with biome gear", (ConsoleEvent)obj9, true, false, false, false, false, (ConsoleOptionsFetcher)obj10, false, false, false); object obj11 = <>c.<>9__0_10; if (obj11 == null) { ConsoleEvent val12 = delegate(ConsoleEventArgs args) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00b2: 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_012f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); } else if (args.Length < 2) { args.Context.AddString("Usage: raiderclan_spawngarrison [radius]"); } else { string text = args[1].ToLowerInvariant(); float num = 20f; if (args.Length >= 3 && float.TryParse(args[2], out var result)) { num = Mathf.Clamp(result, 5f, 50f); } GameObject val16 = new GameObject("RaiderClans_GarrisonRoot"); val16.transform.position = ((Component)Player.m_localPlayer).transform.position; if (text == "tower") { RaiderTowerOverwrites.SpawnTowerRaiders(val16); args.Context.AddString($"Spawned tower garrison at {val16.transform.position} (radius {num})"); } else if (text == "village") { RaiderTowerOverwrites.SpawnVillageRaiders(val16); args.Context.AddString($"Spawned village garrison at {val16.transform.position} (radius {num})"); } else { args.Context.AddString("Invalid garrison type. Use 'tower' or 'village'."); } Object.Destroy((Object)(object)val16); } }; <>c.<>9__0_10 = val12; obj11 = (object)val12; } object obj12 = <>c.<>9__0_11; if (obj12 == null) { ConsoleOptionsFetcher val13 = () => new List { "tower", "village" }; <>c.<>9__0_11 = val13; obj12 = (object)val13; } new ConsoleCommand("raiderclan_spawngarrison", " [radius] - Spawn a raider garrison using tower/village rules", (ConsoleEvent)obj11, true, false, false, false, false, (ConsoleOptionsFetcher)obj12, false, false, false); object obj13 = <>c.<>9__0_12; if (obj13 == null) { ConsoleEvent val14 = delegate(ConsoleEventArgs args) { int result; if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); } else if (args.Length < 2 || !int.TryParse(args[1], out result)) { args.Context.AddString("Usage: raiderclan_wave "); } else { if (!RaiderEvents.IsRaidActive()) { RaiderEvents.StartRaidManually(); } MethodInfo methodInfo = AccessTools.Method(typeof(RaiderEvents), "SpawnWave", (Type[])null, (Type[])null); for (int i = 0; i < result; i++) { methodInfo.Invoke(null, null); } args.Context.AddString($"Spawned raid wave {result}"); } }; <>c.<>9__0_12 = val14; obj13 = (object)val14; } new ConsoleCommand("raiderclan_wave", " - Force-spawn a raid wave", (ConsoleEvent)obj13, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj14 = <>c.<>9__0_13; if (obj14 == null) { ConsoleEvent val15 = delegate(ConsoleEventArgs args) { //IL_002a: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0086: 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_009e: 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_0054: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { args.Context.AddString("No local player found"); } else { Biome val16 = (Biome)1; if (args.Length >= 2 && Enum.TryParse(args[1], ignoreCase: true, out Biome result)) { val16 = result; } Vector3 val17 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 2f; RaiderLoot.DropRegularLoot(val17, val16); args.Context.AddString($"Spawned regular loot for {val16} biome at {val17}"); } }; <>c.<>9__0_13 = val15; obj14 = (object)val15; } new ConsoleCommand("raiderclan_spawnloot", "[biome] - Spawn infused loot item", (ConsoleEvent)obj14, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); RaiderClansPlugin.Logger.LogInfo((object)"RaiderClans dev commands registered"); } } [HarmonyPatch(typeof(Game), "FixedUpdate")] internal class GameFixedUpdatePatch { private static void Postfix(Game __instance) { RaiderEvents.Update(Time.fixedDeltaTime); } } [HarmonyPatch(typeof(Character), "OnDeath")] internal class CharacterOnDeathPatch { private static void Postfix(Character __instance) { bool flag = RaiderAI.IsRaider(__instance); if (!flag) { string text = __instance.m_name ?? string.Empty; flag = text.StartsWith("Clan ", StringComparison.OrdinalIgnoreCase) || ((Object)__instance).name.Contains("RaiderClan_Melee") || ((Object)__instance).name.Contains("RaiderClan_Ranged"); } bool flag2 = RaiderAI.IsChieftain(__instance) || __instance.m_name == "Clan Chieftain"; RaiderClansPlugin.LogDebug($"Character died: {((Object)__instance).name}, isRaider={flag}, isChieftain={flag2}"); if (flag) { RaiderEvents.OnRaiderKilled(__instance, identityConfirmed: true, flag2); } } } [HarmonyPatch(typeof(ItemData), "GetDamage", new Type[] { typeof(int), typeof(float) })] internal class ItemDataGetDamagePatch { private static void Postfix(ItemData __instance, ref DamageTypes __result) { float infusedDamageBonus = RaiderLoot.GetInfusedDamageBonus(__instance); if (infusedDamageBonus > 1f) { ((DamageTypes)(ref __result)).Modify(infusedDamageBonus); } } } [HarmonyPatch(typeof(ItemData), "GetArmor", new Type[] { typeof(int), typeof(float) })] internal class ItemDataGetArmorPatch { private static void Postfix(ItemData __instance, ref float __result) { float infusedArmorBonus = RaiderLoot.GetInfusedArmorBonus(__instance); if (infusedArmorBonus > 1f) { __result *= infusedArmorBonus; } } } [HarmonyPatch(typeof(Humanoid), "EquipItem", new Type[] { typeof(ItemData), typeof(bool) })] internal class HumanoidEquipItemPatch { private static void Postfix(Humanoid __instance, ItemData item, bool triggerEquipEffects) { if (!triggerEquipEffects || item == null) { return; } float infusedDamageBonus = RaiderLoot.GetInfusedDamageBonus(item); float infusedArmorBonus = RaiderLoot.GetInfusedArmorBonus(item); if (!(infusedDamageBonus > 1f) && !(infusedArmorBonus > 1f)) { return; } SEMan sEMan = ((Character)__instance).GetSEMan(); if (sEMan != null) { StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Potion_hasty")); if ((Object)(object)statusEffect != (Object)null) { sEMan.AddStatusEffect(statusEffect, false, 0, 0f); } } } } [HarmonyPatch(typeof(Humanoid), "UnequipItem", new Type[] { typeof(ItemData), typeof(bool) })] internal class HumanoidUnequipItemPatch { private static void Postfix(Humanoid __instance, ItemData item, bool triggerEquipEffects) { if (!triggerEquipEffects || item == null) { return; } float infusedDamageBonus = RaiderLoot.GetInfusedDamageBonus(item); float infusedArmorBonus = RaiderLoot.GetInfusedArmorBonus(item); if (!(infusedDamageBonus > 1f) && !(infusedArmorBonus > 1f)) { return; } SEMan sEMan = ((Character)__instance).GetSEMan(); if (sEMan != null) { StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Potion_hasty")); if ((Object)(object)statusEffect != (Object)null) { sEMan.RemoveStatusEffect(statusEffect, false); } } } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] internal class ItemDataGetTooltipPatch { private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, ref string __result) { if (item != null && (RaiderLoot.GetInfusedDamageBonus(item) > 1f || RaiderLoot.GetInfusedArmorBonus(item) > 1f)) { float infusedDamageBonus = RaiderLoot.GetInfusedDamageBonus(item); float infusedArmorBonus = RaiderLoot.GetInfusedArmorBonus(item); __result += "\nInfused"; if (infusedDamageBonus > 1f) { int num = Mathf.RoundToInt((infusedDamageBonus - 1f) * 100f); __result += $"\n+{num}% Damage"; } if (infusedArmorBonus > 1f) { int num2 = Mathf.RoundToInt((infusedArmorBonus - 1f) * 100f); __result += $"\n+{num2}% Armor"; } __result += "\n+25% Movement Speed"; } } } [HarmonyPatch(typeof(Character), "HaveEitr")] internal class CharacterHaveEitrPatch { private static bool Prefix(Character __instance, ref bool __result) { if (RaiderAI.IsRaider(__instance)) { __result = true; return false; } return true; } } [HarmonyPatch(typeof(Character), "UseEitr")] internal class CharacterUseEitrPatch { private static bool Prefix(Character __instance) { if (RaiderAI.IsRaider(__instance)) { return false; } return true; } } [HarmonyPatch(typeof(Projectile), "FixedUpdate")] internal static class ProjectileFixedUpdatePatch { private static readonly FieldRef NviewRef = AccessTools.FieldRefAccess("m_nview"); private static readonly FieldRef OwnerRef = AccessTools.FieldRefAccess("m_owner"); private static readonly HashSet LoggedProjectiles = new HashSet(); private static void Prefix(Projectile __instance) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) ZNetView val = NviewRef.Invoke(__instance); if ((Object)(object)val == (Object)null || !val.IsValid()) { return; } Character val2 = OwnerRef.Invoke(__instance); if (!((Object)(object)val2 == (Object)null) && RaiderAI.IsRaider(val2) && !val.IsOwner()) { int instanceID = ((Object)__instance).GetInstanceID(); if (LoggedProjectiles.Add(instanceID)) { ZDO zDO = val.GetZDO(); long num = ((zDO != null) ? zDO.GetOwner() : 0); long num2 = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.GetUID() : 0); RaiderClansPlugin.LogDebug($"[ProjectileDebug] Raider projectile not owned locally. owner={val2.m_name} projOwnerPeer={num} localPeer={num2} pos={((Component)__instance).transform.position}"); } } } } [HarmonyPatch(typeof(Projectile), "OnHit")] internal static class ProjectileOnHitPatch { private static readonly FieldRef OwnerRef = AccessTools.FieldRefAccess("m_owner"); private static readonly FieldRef OriginalHitDataRef = AccessTools.FieldRefAccess("m_originalHitData"); private static readonly FieldRef DamageRef = AccessTools.FieldRefAccess("m_damage"); private static void Prefix(Projectile __instance, Collider collider, Vector3 hitPoint, bool water, Vector3 normal) { //IL_0050: 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_00a4: Unknown result type (might be due to invalid IL or missing references) Character val = OwnerRef.Invoke(__instance); if (!((Object)(object)val == (Object)null) && RaiderAI.IsRaider(val)) { string text = (Object.op_Implicit((Object)(object)collider) ? ((Object)collider).name : ""); DamageTypes val2 = DamageRef.Invoke(__instance); float totalDamage = ((DamageTypes)(ref val2)).GetTotalDamage(); HitData obj = OriginalHitDataRef.Invoke(__instance); float num = ((obj != null) ? ((DamageTypes)(ref obj.m_damage)).GetTotalDamage() : 0f); RaiderClansPlugin.LogDebug($"[ProjectileDebug] OnHit owner={val.m_name} targetCollider={text} water={water} pos={hitPoint} projDamage={totalDamage:F2} originalDamage={num:F2}"); } } } [BepInPlugin("com.ruijven.raiderclans", "RaiderClans", "1.0.0")] internal class RaiderClansPlugin : BaseUnityPlugin { public const string PluginGUID = "com.ruijven.raiderclans"; public const string PluginName = "RaiderClans"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Logger; public static ConfigEntry DailyRaidChance; public static ConfigEntry RaidCheckTimeOfDay; public static ConfigEntry EnableTowerOverwrites; public static ConfigEntry EnableRaidEvents; public static ConfigEntry EnableDebugLogging; public static ConfigEntry Wave1Composition; public static ConfigEntry Wave2Composition; public static ConfigEntry Wave3Composition; public static ConfigEntry Wave4Composition; public static ConfigEntry EnableRegularLoot; public static ConfigEntry ChieftainDropInfusedItem; public static ConfigEntry InfusedDamageBonus; public static ConfigEntry InfusedArmorBonus; internal static RaiderClansPlugin Instance { get; private set; } private void Awake() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; InitializeConfig(); Harmony val = new Harmony("com.ruijven.raiderclans"); val.PatchAll(Assembly.GetExecutingAssembly()); RaiderAI.Initialize(); RaiderTowerOverwrites.Initialize(); ((MonoBehaviour)this).StartCoroutine(DelayedInitialization()); Logger.LogInfo((object)"RaiderClans v1.0.0 loaded successfully!"); } private void OnDestroy() { RaiderTowerOverwrites.SaveProcessedLocations(); } private void InitializeConfig() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Expected O, but got Unknown //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Expected O, but got Unknown //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Expected O, but got Unknown DailyRaidChance = ((BaseUnityPlugin)this).Config.Bind("Raid Events", "DailyRaidChance", 0.15f, new ConfigDescription("Chance for a raid to trigger each day at the specified time (0.0 - 1.0, e.g., 0.15 = 15%)", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); RaidCheckTimeOfDay = ((BaseUnityPlugin)this).Config.Bind("Raid Events", "RaidCheckTimeOfDay", 0.6f, new ConfigDescription("Time of day to check for raid trigger (0.0 - 1.0, e.g., 0.6 = just after noon)", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); EnableTowerOverwrites = ((BaseUnityPlugin)this).Config.Bind("Tower Overwrites", "EnableTowerOverwrites", true, new ConfigDescription("Enable Mistlands Dvergr tower overwrites with raiders", (AcceptableValueBase)null, Array.Empty())); EnableRaidEvents = ((BaseUnityPlugin)this).Config.Bind("Raid Events", "EnableRaidEvents", true, new ConfigDescription("Enable custom raid event system", (AcceptableValueBase)null, Array.Empty())); EnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind("Debug", "EnableDebugLogging", false, new ConfigDescription("Enable verbose debug logging for troubleshooting", (AcceptableValueBase)null, Array.Empty())); Wave1Composition = ((BaseUnityPlugin)this).Config.Bind("Raid Waves", "Wave1", "Warrior:2", "Comma-separated Role:Count entries (e.g., Warrior:3,Pillager:1) for wave 1"); Wave2Composition = ((BaseUnityPlugin)this).Config.Bind("Raid Waves", "Wave2", "Warrior:3,Pillager:1", "Comma-separated Role:Count entries (e.g., Warrior:3,Pillager:1) for wave 2"); Wave3Composition = ((BaseUnityPlugin)this).Config.Bind("Raid Waves", "Wave3", "Warrior:4,Pillager:2", "Comma-separated Role:Count entries (e.g., Warrior:4,Pillager:2) for wave 3"); Wave4Composition = ((BaseUnityPlugin)this).Config.Bind("Raid Waves", "Wave4", "Warrior:5,Pillager:3,Chieftain:1", "Comma-separated Role:Count entries (e.g., Warrior:5,Pillager:3,Chieftain:1) for wave 4"); Wave1Composition.SettingChanged += OnWaveConfigChanged; Wave2Composition.SettingChanged += OnWaveConfigChanged; Wave3Composition.SettingChanged += OnWaveConfigChanged; Wave4Composition.SettingChanged += OnWaveConfigChanged; ReloadWaveConfigFromSettings(); EnableRegularLoot = ((BaseUnityPlugin)this).Config.Bind("Loot - Regular Raiders", "EnableLoot", true, new ConfigDescription("Enable loot drops for regular raiders", (AcceptableValueBase)null, Array.Empty())); ChieftainDropInfusedItem = ((BaseUnityPlugin)this).Config.Bind("Loot - Chieftains", "DropInfusedItem", true, new ConfigDescription("Whether chieftains drop infused items", (AcceptableValueBase)null, Array.Empty())); InfusedDamageBonus = ((BaseUnityPlugin)this).Config.Bind("Loot - Chieftains", "InfusedDamageBonus", 1.2f, new ConfigDescription("Damage bonus multiplier for infused items (e.g., 1.2 = +20% damage)", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 3f), Array.Empty())); InfusedArmorBonus = ((BaseUnityPlugin)this).Config.Bind("Loot - Chieftains", "InfusedArmorBonus", 1.2f, new ConfigDescription("Armor bonus multiplier for infused items (e.g., 1.2 = +20% armor)", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 3f), Array.Empty())); void OnWaveConfigChanged(object _, EventArgs __) { ReloadWaveConfigFromSettings(); } } private IEnumerator DelayedInitialization() { while ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_items.Count == 0) { yield return null; } RaiderLoot.Initialize(); Logger.LogInfo((object)"RaiderClans systems initialized successfully."); Logger.LogInfo((object)"Raider prefab will be created when ZNetScene loads."); } public static void LogDebug(string message) { if (EnableDebugLogging.Value) { Logger.LogInfo((object)("[DEBUG] " + message)); } } private void ReloadWaveConfigFromSettings() { RaiderEvents.ConfigureWaves(Wave1Composition?.Value, Wave2Composition?.Value, Wave3Composition?.Value, Wave4Composition?.Value); } } public class RaiderEvents { private sealed class RaidWaveDefinition { public int WaveNumber { get; } public Dictionary RoleCounts { get; } public RaidWaveDefinition(int waveNumber, Dictionary roleCounts) { WaveNumber = waveNumber; RoleCounts = roleCounts ?? new Dictionary(); } } private static bool raidActive = false; private static Vector3 raidPosition; private static Biome raidBiome; private static int currentWave = 0; private static int raidersKilled = 0; private static bool chieftainSpawned = false; private static List activeRaiders = new List(); private static float lastRaidCheckTime = -1f; private static float nextWaveTime = 0f; private const float WAVE_INTERVAL = 30f; private static RaidWaveDefinition[] s_waveDefinitions = DefaultWaves; private static readonly RaidWaveDefinition[] DefaultWaves = new RaidWaveDefinition[4] { new RaidWaveDefinition(1, new Dictionary { { RaiderRole.Warrior, 2 } }), new RaidWaveDefinition(2, new Dictionary { { RaiderRole.Warrior, 3 }, { RaiderRole.Pillager, 1 } }), new RaidWaveDefinition(3, new Dictionary { { RaiderRole.Warrior, 4 }, { RaiderRole.Pillager, 2 } }), new RaidWaveDefinition(4, new Dictionary { { RaiderRole.Warrior, 5 }, { RaiderRole.Pillager, 3 }, { RaiderRole.Chieftain, 1 } }) }; public static void StartRaidManually() { //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_0007: Unknown result type (might be due to invalid IL or missing references) Biome highestUnlockedBiome = GetHighestUnlockedBiome(); StartRaidManually(highestUnlockedBiome); } public static void StartRaidManually(Biome biome) { //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_005b: 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_0072: 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) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { RaiderClansPlugin.Logger.LogWarning((object)"No local player found for manual raid start"); return; } if (raidActive) { RaiderClansPlugin.Logger.LogWarning((object)"Raid already active"); return; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; RaiderClansPlugin.Logger.LogInfo((object)$"Manually starting raid at {position}, biome: {biome}"); StartRaid(position, biome); } public static void Update(float dt) { if (RaiderClansPlugin.EnableRaidEvents.Value && ZNet.instance.IsServer()) { CheckDailyRaidTrigger(); UpdateRaidState(dt); } } private static void CheckDailyRaidTrigger() { float dayFraction = EnvMan.instance.GetDayFraction(); float value = RaiderClansPlugin.RaidCheckTimeOfDay.Value; if (lastRaidCheckTime < 0f || dayFraction < lastRaidCheckTime) { lastRaidCheckTime = dayFraction; } else if (dayFraction >= value && lastRaidCheckTime < value) { lastRaidCheckTime = dayFraction; if (Random.value <= RaiderClansPlugin.DailyRaidChance.Value) { StartRaid(); } } } private static void StartRaid() { //IL_004d: 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_0058: 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_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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) if (raidActive) { RaiderClansPlugin.LogDebug("Raid already active, skipping StartRaid"); return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { RaiderClansPlugin.Logger.LogWarning((object)"No local player found for raid start"); return; } Biome biome = WorldGenerator.instance.GetBiome(((Component)localPlayer).transform.position); raidBiome = GetHighestUnlockedBiome(); raidPosition = ((Component)localPlayer).transform.position; raidActive = true; currentWave = 0; raidersKilled = 0; chieftainSpawned = false; activeRaiders.Clear(); nextWaveTime = Time.time; RaiderClansPlugin.Logger.LogInfo((object)$"Starting raid in biome: {raidBiome} at position {raidPosition}"); RaiderClansPlugin.LogDebug($"Player biome: {biome}, Raid biome: {raidBiome}"); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "Raiders are attacking!", 0, (Sprite)null); } } private static void StartRaid(Vector3 position, Biome biome) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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) if (raidActive) { RaiderClansPlugin.LogDebug("Raid already active, skipping StartRaid"); return; } raidBiome = biome; raidPosition = position; raidActive = true; currentWave = 0; raidersKilled = 0; chieftainSpawned = false; activeRaiders.Clear(); nextWaveTime = Time.time; RaiderClansPlugin.Logger.LogInfo((object)$"Starting raid in biome: {raidBiome} at position {raidPosition}"); } private static Biome GetHighestUnlockedBiome() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_005d: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return (Biome)1; } if (instance.GetGlobalKey("defeated_queen")) { return (Biome)32; } if (instance.GetGlobalKey("defeated_bonemass")) { return (Biome)512; } if (instance.GetGlobalKey("defeated_goblinking")) { return (Biome)16; } if (instance.GetGlobalKey("defeated_dragon")) { return (Biome)4; } if (instance.GetGlobalKey("defeated_greydwarf")) { return (Biome)2; } if (instance.GetGlobalKey("defeated_eikthyr")) { return (Biome)8; } return (Biome)1; } private static void SpawnWave() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) RaidWaveDefinition[] waveDefinitions = GetWaveDefinitions(); int num = currentWave; if (num >= waveDefinitions.Length) { RaiderClansPlugin.LogDebug("No additional wave definitions available."); return; } RaidWaveDefinition raidWaveDefinition = waveDefinitions[num]; currentWave++; int num2 = 0; foreach (KeyValuePair roleCount in raidWaveDefinition.RoleCounts) { RaiderRole key = roleCount.Key; int num3 = Mathf.Max(0, roleCount.Value); for (int i = 0; i < num3; i++) { Vector3 distributedSpawnPosition = GetDistributedSpawnPosition(); Humanoid val = RaiderAI.SpawnRaider(new RaiderAI.RaiderSpawnRequest(distributedSpawnPosition, raidBiome, key)); if ((Object)(object)val == (Object)null) { continue; } Character component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { activeRaiders.Add(component); } if (key == RaiderRole.Chieftain && !chieftainSpawned) { chieftainSpawned = true; if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, "The Clan Chieftain has entered the fray!", 0, (Sprite)null); } RaiderClansPlugin.Logger.LogInfo((object)"Chieftain spawned with wave"); } num2++; } } RaiderClansPlugin.Logger.LogInfo((object)$"Wave {raidWaveDefinition.WaveNumber}: Spawned {num2} raiders"); } private static Vector3 GetDistributedSpawnPosition() { //IL_003d: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) float num = Random.Range(18f, 32f); float num2 = Random.Range(0f, MathF.PI * 2f); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Cos(num2) * num, 0f, Mathf.Sin(num2) * num); return raidPosition + val; } private static void UpdateRaidState(float dt) { if (!raidActive) { return; } activeRaiders.RemoveAll((Character r) => (Object)(object)r == (Object)null || r.IsDead()); RaidWaveDefinition[] waveDefinitions = GetWaveDefinitions(); if (currentWave < waveDefinitions.Length && Time.time >= nextWaveTime) { SpawnWave(); if (currentWave < waveDefinitions.Length) { nextWaveTime = Time.time + 30f; } } if (chieftainSpawned) { Character val = activeRaiders.Find((Character r) => RaiderAI.IsChieftain(r)); if ((Object)(object)val == (Object)null || val.IsDead()) { MakeRaidersFlee(); EndRaid(); } } else if (currentWave >= waveDefinitions.Length && activeRaiders.Count == 0) { EndRaid(); } } public static void ConfigureWaves(params string[] waveDefinitions) { if (waveDefinitions == null || waveDefinitions.Length == 0) { s_waveDefinitions = DefaultWaves; RaiderClansPlugin.Logger.LogInfo((object)"Using default raid wave definitions."); return; } List list = new List(); for (int i = 0; i < waveDefinitions.Length; i++) { Dictionary roleCounts = ParseWaveDefinition(waveDefinitions[i], i); list.Add(new RaidWaveDefinition(i + 1, roleCounts)); } s_waveDefinitions = list.ToArray(); RaiderClansPlugin.Logger.LogInfo((object)"Raid wave definitions reloaded from configuration."); } private static RaidWaveDefinition[] GetWaveDefinitions() { return s_waveDefinitions ?? DefaultWaves; } private static Dictionary ParseWaveDefinition(string config, int fallbackIndex) { Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(config)) { string[] array = config.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (text2.Length == 0) { continue; } string[] array3 = text2.Split(new char[2] { ':', '=' }, StringSplitOptions.RemoveEmptyEntries); if (array3.Length == 2) { int result2; if (!Enum.TryParse(array3[0].Trim(), ignoreCase: true, out var result)) { RaiderClansPlugin.Logger.LogWarning((object)("Unknown raider role '" + array3[0] + "' in wave config '" + config + "'")); } else if (!int.TryParse(array3[1].Trim(), out result2) || result2 <= 0) { RaiderClansPlugin.Logger.LogWarning((object)$"Invalid count '{array3[1]}' for role '{result}' in wave config '{config}'"); } else if (dictionary.ContainsKey(result)) { dictionary[result] += result2; } else { dictionary[result] = result2; } } } } if (dictionary.Count == 0) { return CloneRoleCounts(DefaultWaves[Mathf.Clamp(fallbackIndex, 0, DefaultWaves.Length - 1)]); } return dictionary; } private static Dictionary CloneRoleCounts(RaidWaveDefinition definition) { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair roleCount in definition.RoleCounts) { dictionary[roleCount.Key] = roleCount.Value; } return dictionary; } private static void MakeRaidersFlee() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) foreach (Character activeRaider in activeRaiders) { if ((Object)(object)activeRaider != (Object)null && !activeRaider.IsDead() && !RaiderAI.IsChieftain(activeRaider)) { BaseAI component = ((Component)activeRaider).GetComponent(); if ((Object)(object)component != (Object)null) { component.Flee(0f, Vector3.zero); } } } } private static void EndRaid() { raidActive = false; currentWave = 0; raidersKilled = 0; chieftainSpawned = false; activeRaiders.Clear(); RaiderClansPlugin.Logger.LogInfo((object)"Raid ended"); } public static void OnRaiderKilled(Character raider, bool identityConfirmed = false, bool chieftainConfirmed = false) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)raider == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } bool flag = identityConfirmed || RaiderAI.IsRaider(raider); if (!flag) { string text = raider.m_name ?? string.Empty; flag = text.StartsWith("Clan ", StringComparison.OrdinalIgnoreCase); } if (flag) { raidersKilled++; RaiderClansPlugin.Logger.LogInfo((object)$"Raider killed. Total: {raidersKilled}"); if (chieftainConfirmed || RaiderAI.IsChieftain(raider)) { RaiderLoot.DropInfusedItem(((Component)raider).transform.position, raidBiome); MakeRaidersFlee(); EndRaid(); } } } public static bool IsRaidActive() { return raidActive; } } [HarmonyPatch] internal class RaiderHarmonyPatches { private static bool IsRaider(Character character) { if ((Object)(object)character == (Object)null) { return false; } string name = ((Object)character).name; return name.Contains("RaiderClan_Melee") || name.Contains("RaiderClan_Ranged"); } [HarmonyPatch(typeof(Attack), "UseAmmo")] [HarmonyPrefix] private static bool UseAmmo_Prefix(Attack __instance, ref bool __result) { if ((Object)(object)__instance?.m_character != (Object)null && IsRaider((Character)(object)__instance.m_character)) { __result = true; return false; } return true; } [HarmonyPatch(typeof(Character), "Awake")] [HarmonyPostfix] private static void IdentityInjection_Postfix(Character __instance) { //IL_005c: 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_0085: Unknown result type (might be due to invalid IL or missing references) if (!IsRaider(__instance)) { return; } ZNetView nview = __instance.m_nview; if (nview != null) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("RaiderClans_IsRaider", true); } } ZNetView nview2 = __instance.m_nview; ZDO val = ((nview2 != null) ? nview2.GetZDO() : null); if (val != null) { int num = val.GetInt("RaiderClans_Biome", 1); Biome val2 = (Biome)num; RaiderClansPlugin.LogDebug($"[AWAKE] Retrieved biome from ZDO: {val2} (int: {num})"); CharacterDrop component = ((Component)__instance).GetComponent(); RaiderLoot.ConfigureCharacterDrop(component, val2); } } [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] [HarmonyPostfix] private static void PathfindingFallback_Postfix(MonsterAI __instance, float dt) { //IL_0035: 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_005a: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0088: 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_008c: Unknown result type (might be due to invalid IL or missing references) Character component = ((Component)__instance).GetComponent(); if (IsRaider(component) && (Object)(object)__instance.m_targetCreature != (Object)null && !((BaseAI)__instance).HavePath(((Component)__instance.m_targetCreature).transform.position)) { Vector3 position = ((Component)__instance.m_targetCreature).transform.position; Vector3 position2 = ((Component)__instance).transform.position; Vector3 val = position - position2; val.y = 0f; ((Vector3)(ref val)).Normalize(); ((BaseAI)__instance).MoveTo(dt, position2 + val, 5f, ((BaseAI)__instance).IsAlerted()); } } [HarmonyPatch(typeof(Character), "OnRagdollCreated")] [HarmonyPrefix] private static bool SkipRagdoll_Prefix(Character __instance, Ragdoll ragdoll) { if (IsRaider(__instance)) { return false; } return true; } [HarmonyPatch(typeof(Humanoid), "EquipBestWeapon")] [HarmonyPrefix] private static bool PreventWeaponSwitching_Prefix(Humanoid __instance) { if ((Object)(object)__instance != (Object)null && IsRaider((Character)(object)__instance)) { return false; } return true; } [HarmonyPatch(typeof(Character), "SetVisible")] [HarmonyPrefix] private static void SetVisibleLogging_Prefix(Character __instance, bool visible) { if ((Object)(object)__instance != (Object)null && IsRaider(__instance)) { ZNetView nview = __instance.m_nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); RaiderClansPlugin.LogDebug($"[VISIBILITY] {((Object)__instance).name} SetVisible({visible}) HasOwner={((val != null) ? new bool?(val.HasOwner()) : ((bool?)null))} Owner={((val != null) ? new long?(val.GetOwner()) : ((long?)null))} IsOwner={((val != null) ? new bool?(val.IsOwner()) : ((bool?)null))} IsValid={((val != null) ? new bool?(val.IsValid()) : ((bool?)null))}"); } } [HarmonyPatch(typeof(BaseAI), "FindEnemy")] [HarmonyPrefix] private static bool EnforceStructurePriority_Prefix(BaseAI __instance, ref Character __result) { MonsterAI val = (MonsterAI)(object)((__instance is MonsterAI) ? __instance : null); if (val != null) { PillagerBehavior component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && component.ShouldPreferStructureTarget()) { __result = null; return false; } } return true; } } public class RaiderLoot { private const string InfusedDamageKey = "RaiderClans_InfusedDamage"; private const string InfusedArmorKey = "RaiderClans_InfusedArmor"; private static Dictionary> biomeMaterialDrops; private static Dictionary biomeRareCores; public static void ConfigureCharacterDrop(CharacterDrop charDrop, Biome biome) { //IL_0029: 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_00ee: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00c5: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown if ((Object)(object)charDrop == (Object)null || !RaiderClansPlugin.EnableRegularLoot.Value || !biomeMaterialDrops.ContainsKey(biome)) { return; } List list = biomeMaterialDrops[biome]; charDrop.m_drops = new List(); int num = Random.Range(1, 3); for (int i = 0; i < num && i < list.Count; i++) { string text = list[Random.Range(0, list.Count)]; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); if ((Object)(object)itemPrefab != (Object)null) { charDrop.m_drops.Add(new Drop { m_prefab = itemPrefab, m_chance = 0.3f, m_amountMin = 1, m_amountMax = 2, m_levelMultiplier = false }); } } if (biomeRareCores.ContainsKey(biome)) { string text2 = biomeRareCores[biome]; if (!string.IsNullOrEmpty(text2)) { GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(text2); if ((Object)(object)itemPrefab2 != (Object)null) { charDrop.m_drops.Add(new Drop { m_prefab = itemPrefab2, m_chance = 0.1f, m_amountMin = 1, m_amountMax = 1, m_levelMultiplier = false }); } } } RaiderClansPlugin.LogDebug($"Configured CharacterDrop with {charDrop.m_drops.Count} drops for raid biome {biome}"); } public static void Initialize() { BuildMaterialDropPools(); BuildRareCoreMapping(); } private static void BuildMaterialDropPools() { biomeMaterialDrops = new Dictionary>(); biomeMaterialDrops[(Biome)1] = new List { "Wood", "Flint", "DeerHide", "LeatherScraps", "Feathers" }; biomeMaterialDrops[(Biome)8] = new List { "RoundLog", "CarrotSeeds", "CopperOre", "TinOre", "FineWood" }; biomeMaterialDrops[(Biome)2] = new List { "Chain", "IronOre", "ElderBark", "Guck", "TurnipSeeds" }; biomeMaterialDrops[(Biome)4] = new List { "Obsidian", "SilverOre", "Crystal", "WolfPelt", "OnionSeeds" }; biomeMaterialDrops[(Biome)16] = new List { "Tar", "Iron", "Barley", "Flax", "BjornHide" }; biomeMaterialDrops[(Biome)512] = new List { "JuteBlue", "YggdrasilWood", "DvergrNeedle", "Carapace", "Mandible" }; biomeMaterialDrops[(Biome)32] = new List { "Blackwood", "MorgenSinew", "GemstoneBlue", "GemstoneRed", "GemstoneGreen" }; RaiderClansPlugin.Logger.LogInfo((object)$"Built material drop pools for {biomeMaterialDrops.Count} biomes"); } private static void BuildRareCoreMapping() { biomeRareCores = new Dictionary(); biomeRareCores[(Biome)1] = ""; biomeRareCores[(Biome)8] = "SurtlingCore"; biomeRareCores[(Biome)2] = "Chitin"; biomeRareCores[(Biome)4] = "DragonEgg"; biomeRareCores[(Biome)16] = "GoblinTotem"; biomeRareCores[(Biome)512] = "BlackCore"; biomeRareCores[(Biome)32] = "MoltenCore"; RaiderClansPlugin.Logger.LogInfo((object)"Built rare core mapping"); } public static void DropRegularLoot(Vector3 position, Biome biome) { //IL_0006: 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_002c: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0112: 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_015c: Unknown result type (might be due to invalid IL or missing references) RaiderClansPlugin.LogDebug($"DropRegularLoot called: biome={biome}, hasBiome={biomeMaterialDrops.ContainsKey(biome)}"); if (!biomeMaterialDrops.ContainsKey(biome)) { RaiderClansPlugin.LogDebug($"No materials for biome {biome}"); return; } List list = biomeMaterialDrops[biome]; RaiderClansPlugin.LogDebug($"Found {list.Count} materials for biome {biome}"); int num = Random.Range(1, 3); RaiderClansPlugin.LogDebug($"Dropping {num} material types"); for (int i = 0; i < num && i < list.Count; i++) { string text = list[Random.Range(0, list.Count)]; int num2 = Random.Range(1, 3); RaiderClansPlugin.LogDebug($"Attempting to spawn {num2}x {text}"); SpawnItemDrop(position, text, num2); } if (Random.value <= 0.1f && biomeRareCores.ContainsKey(biome)) { string text2 = biomeRareCores[biome]; if (!string.IsNullOrEmpty(text2)) { int num3 = 1; RaiderClansPlugin.LogDebug($"Attempting to spawn {num3}x {text2} (rare core)"); SpawnItemDrop(position, text2, num3); } } } public static ItemData DropInfusedItem(Vector3 position, Biome biome) { //IL_001d: 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) if (!RaiderClansPlugin.ChieftainDropInfusedItem.Value) { return null; } string randomInfusedItem = GetRandomInfusedItem(biome); if (string.IsNullOrEmpty(randomInfusedItem)) { return null; } GameObject val = SpawnItemDrop(position, randomInfusedItem, 1); if ((Object)(object)val == (Object)null) { return null; } ItemDrop component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return null; } ItemData itemData = component.m_itemData; itemData.m_customData["RaiderClans_InfusedDamage"] = RaiderClansPlugin.InfusedDamageBonus.Value.ToString("F2", CultureInfo.InvariantCulture); itemData.m_customData["RaiderClans_InfusedArmor"] = RaiderClansPlugin.InfusedArmorBonus.Value.ToString("F2", CultureInfo.InvariantCulture); return itemData; } private static string GetRandomInfusedItem(Biome biome) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_000f: 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_0027: Expected I4, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 List list = new List(); if ((int)biome <= 8) { switch (biome - 1) { default: if ((int)biome == 8) { list.AddRange(new string[5] { "ArmorBronzeChest", "ArmorBronzeLegs", "SwordBronze", "AxeBronze", "HelmetBerserkerHood" }); } break; case 0: list.AddRange(new string[3] { "ArmorLeatherChest", "ArmorLeatherLegs", "Early_Axes" }); break; case 1: list.AddRange(new string[5] { "ArmorIronChest", "ArmorIronLegs", "SwordIron", "KnifeChitin", "ArmorRootChest" }); break; case 3: list.AddRange(new string[5] { "ArmorWolfChest", "ArmorWolfLegs", "SwordSilver", "MaceSilver", "ArmorFenringChest" }); break; case 2: break; } } else if ((int)biome != 16) { if ((int)biome != 32) { if ((int)biome == 512) { list.AddRange(new string[6] { "ArmorCarapaceChest", "ArmorCarapaceLegs", "AxeJotunBane", "THSwordKrom", "ArmorMageChest", "CapeFeather" }); } } else { list.AddRange(new string[6] { "HelmetAshlandsMediumHood", "ArmorFlametalChest", "ArmorFlametalLegs", "SwordNiedhogg", "AxeBerzerkr", "ArmorMageLegs_Ashlands" }); } } else { list.AddRange(new string[5] { "ArmorPaddedCuirass", "ArmorPaddedGreaves", "SwordBlackmetal", "BattleaxeBlackmetal", "HelmetBerserkerUndead" }); } if (list.Count == 0) { return null; } return list[Random.Range(0, list.Count)]; } private static GameObject SpawnItemDrop(Vector3 position, string itemName, int stackSize) { //IL_000d: 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_0053: Unknown result type (might be due to invalid IL or missing references) RaiderClansPlugin.LogDebug($"SpawnItemDrop: {itemName} x{stackSize} at {position}"); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName); if ((Object)(object)itemPrefab == (Object)null) { RaiderClansPlugin.Logger.LogWarning((object)("Could not find item prefab: " + itemName)); return null; } GameObject val = Object.Instantiate(itemPrefab, position, Quaternion.identity); RaiderClansPlugin.LogDebug("Instantiated item: " + ((Object)val).name); ItemDrop component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_itemData.m_stack = stackSize; RaiderClansPlugin.LogDebug($"Set stack size to {stackSize}"); } else { RaiderClansPlugin.Logger.LogWarning((object)("No ItemDrop component on " + ((Object)val).name)); } return val; } public static float GetInfusedDamageBonus(ItemData item) { if (!item.m_customData.TryGetValue("RaiderClans_InfusedDamage", out var value)) { return 1f; } if (!float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) { return 1f; } return result; } public static float GetInfusedArmorBonus(ItemData item) { if (!item.m_customData.TryGetValue("RaiderClans_InfusedArmor", out var value)) { return 1f; } if (!float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) { return 1f; } return result; } } public enum RaiderRole { Warrior, Pillager, Chieftain } public sealed class RaiderRoleConfig { private readonly Func> _defaultItemSelector; public RaiderRole Role { get; } public string DisplayName { get; } public float HealthMultiplier { get; } public float DamageMultiplier { get; } public IReadOnlyList DefaultItemPrefabs { get; } public IRaiderBehaviorFactory BehaviorFactory { get; } public float ModelScale { get; } public float MoveSpeedMultiplier { get; } public RaiderRoleConfig(RaiderRole role, string displayName, float healthMultiplier, float damageMultiplier, IReadOnlyList defaultItemPrefabs, IRaiderBehaviorFactory behaviorFactory = null, float modelScale = 1f, float moveSpeedMultiplier = 1f, Func> defaultItemSelector = null) { Role = role; DisplayName = displayName; HealthMultiplier = healthMultiplier; DamageMultiplier = damageMultiplier; DefaultItemPrefabs = defaultItemPrefabs ?? Array.Empty(); BehaviorFactory = behaviorFactory; ModelScale = modelScale; MoveSpeedMultiplier = moveSpeedMultiplier; _defaultItemSelector = defaultItemSelector; } public IReadOnlyList ResolveDefaultItems(Biome biome) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList readOnlyList = _defaultItemSelector?.Invoke(biome); if (readOnlyList == null || readOnlyList.Count == 0) { return DefaultItemPrefabs; } return readOnlyList; } } public static class RaiderRoleRegistry { private sealed class BiomeLoadoutDefinition { public IReadOnlyList Armor { get; } public string WarriorOneHand { get; } public string WarriorShield { get; } public string WarriorTwoHand { get; } public string ChieftainOneHand { get; } public string ChieftainShield { get; } public string ChieftainTwoHand { get; } public BiomeLoadoutDefinition(IReadOnlyList armor, string warriorOneHand, string warriorShield, string warriorTwoHand, string chieftainOneHand, string chieftainShield, string chieftainTwoHand) { Armor = armor ?? Array.Empty(); WarriorOneHand = warriorOneHand; WarriorShield = warriorShield; WarriorTwoHand = warriorTwoHand; ChieftainOneHand = chieftainOneHand ?? warriorOneHand; ChieftainShield = chieftainShield ?? warriorShield; ChieftainTwoHand = chieftainTwoHand ?? warriorTwoHand; } } private static readonly Dictionary RoleConfigs = new Dictionary(); private static readonly Dictionary BiomeLoadouts = new Dictionary(); private static readonly Dictionary BiomeBaseHealth = new Dictionary(); private static bool s_initialized; public static void Initialize() { if (!s_initialized) { RoleConfigs.Clear(); BiomeLoadouts.Clear(); BiomeBaseHealth.Clear(); InitializeBiomeLoadouts(); InitializeBiomeHealth(); RoleConfigs[RaiderRole.Warrior] = new RaiderRoleConfig(RaiderRole.Warrior, "Warrior", 1f, 1f, Array.Empty(), new WarriorBehaviorFactory(), 1f, 1f, ResolveWarriorLoadout); RoleConfigs[RaiderRole.Pillager] = new RaiderRoleConfig(RaiderRole.Pillager, "Pillager", 1.1f, 1f, Array.Empty(), PillagerBehaviorFactory.CreateDefault(), 1f, 1f, ResolvePillagerLoadout); RoleConfigs[RaiderRole.Chieftain] = new RaiderRoleConfig(RaiderRole.Chieftain, "Chieftain", 1.6f, 1.35f, Array.Empty(), new ChieftainBehaviorFactory(), 1.1f, 1.1f, ResolveChieftainLoadout); s_initialized = true; } } public static RaiderRoleConfig GetConfig(RaiderRole role) { if (!s_initialized) { Initialize(); } if (RoleConfigs.TryGetValue(role, out var value)) { return value; } throw new KeyNotFoundException($"No RaiderRoleConfig registered for {role}."); } public static IReadOnlyCollection GetAllConfigs() { if (!s_initialized) { Initialize(); } return RoleConfigs.Values; } private static IReadOnlyList ResolveArmorSet(Biome biome) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (BiomeLoadouts.TryGetValue(biome, out var value)) { return value.Armor; } return Array.Empty(); } private static IReadOnlyList ResolveWarriorLoadout(Biome biome) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) List list = new List(); AppendLoadoutBasics(list, biome); if (BiomeLoadouts.TryGetValue(biome, out var value)) { AddUnique(list, value.WarriorOneHand); AddUnique(list, value.WarriorShield); AddUnique(list, value.WarriorTwoHand); } return list; } private static IReadOnlyList ResolvePillagerLoadout(Biome biome) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) List list = new List(); AppendLoadoutBasics(list, biome); string pillagerSledge = GetPillagerSledge(biome); AddUnique(list, pillagerSledge); return list; } private static IReadOnlyList ResolveChieftainLoadout(Biome biome) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) List list = new List(); AppendLoadoutBasics(list, biome); if (BiomeLoadouts.TryGetValue(biome, out var value)) { AddUnique(list, value.ChieftainOneHand); AddUnique(list, value.ChieftainShield); AddUnique(list, value.ChieftainTwoHand); } return list; } private static void AppendLoadoutBasics(List loadout, Biome biome) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList readOnlyList = ResolveArmorSet(biome); foreach (string item in readOnlyList) { AddUnique(loadout, item); } } private static void AddUnique(List loadout, string prefab) { if (!string.IsNullOrWhiteSpace(prefab) && !loadout.Exists((string existing) => string.Equals(existing, prefab, StringComparison.OrdinalIgnoreCase))) { loadout.Add(prefab); } } private static string GetPillagerSledge(Biome biome) { //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) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_0007: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_0009: 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_0021: Expected I4, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 if ((int)biome <= 8) { switch (biome - 1) { default: if ((int)biome == 8) { goto case 0; } goto IL_0059; case 0: return "SledgeStagbreaker"; case 1: case 3: break; case 2: goto IL_0059; } } else if ((int)biome != 16) { if ((int)biome != 32 && (int)biome != 512) { goto IL_0059; } return "SledgeDemolisher"; } return "SledgeIron"; IL_0059: return null; } private static void InitializeBiomeLoadouts() { BiomeLoadouts[(Biome)1] = new BiomeLoadoutDefinition(new string[3] { "ArmorLeatherChest", "ArmorLeatherLegs", "HelmetLeather" }, "Club", "ShieldWood", null, "AxeFlint", "ShieldWoodTower", null); BiomeLoadouts[(Biome)8] = new BiomeLoadoutDefinition(new string[3] { "ArmorBronzeChest", "ArmorBronzeLegs", "HelmetBronze" }, "AxeBronze", "ShieldBronzeBuckler", null, "SwordBronze", "ShieldBanded", null); BiomeLoadouts[(Biome)2] = new BiomeLoadoutDefinition(new string[3] { "ArmorIronChest", "ArmorIronLegs", "HelmetIron" }, "SwordIron", "ShieldIronBuckler", null, null, null, "Battleaxe"); BiomeLoadouts[(Biome)4] = new BiomeLoadoutDefinition(new string[3] { "ArmorWolfChest", "ArmorWolfLegs", "HelmetDrake" }, "SwordSilver", "ShieldSilver", null, null, null, "BattleaxeCrystal"); BiomeLoadouts[(Biome)16] = new BiomeLoadoutDefinition(new string[3] { "ArmorPaddedCuirass", "ArmorPaddedGreaves", "HelmetPadded" }, "AxeBlackMetal", "ShieldBlackmetal", null, null, null, "AtgeirBlackmetal"); BiomeLoadouts[(Biome)512] = new BiomeLoadoutDefinition(new string[3] { "ArmorCarapaceChest", "ArmorCarapaceLegs", "HelmetCarapace" }, "AxeJotunBane", "ShieldCarapaceBuckler", null, null, null, "AtgeirHimminAfl"); BiomeLoadouts[(Biome)32] = new BiomeLoadoutDefinition(new string[3] { "ArmorFlametalChest", "ArmorFlametalLegs", "HelmetFlametal" }, null, null, "AxeBerzerkr", null, null, "BattleaxeSkullSplittur"); } private static void InitializeBiomeHealth() { BiomeBaseHealth[(Biome)1] = 200f; BiomeBaseHealth[(Biome)8] = 325f; BiomeBaseHealth[(Biome)2] = 475f; BiomeBaseHealth[(Biome)4] = 650f; BiomeBaseHealth[(Biome)16] = 825f; BiomeBaseHealth[(Biome)512] = 950f; BiomeBaseHealth[(Biome)32] = 1000f; } public static float GetBaseHealthForBiome(Biome biome) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!s_initialized) { Initialize(); } if (BiomeBaseHealth.TryGetValue(biome, out var value)) { return value; } return BiomeBaseHealth[(Biome)1]; } } public readonly struct StructurePriority { public string PrefabName { get; } public PieceCategory? Category { get; } public int Priority { get; } public StructurePriority(string prefabName, PieceCategory? category, int priority) { PrefabName = prefabName ?? string.Empty; Category = category; Priority = priority; } public bool Matches(Piece piece) { //IL_005b: 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) if ((Object)(object)piece == (Object)null) { return false; } if (!string.IsNullOrEmpty(PrefabName)) { string prefabName = Utils.GetPrefabName(((Component)piece).gameObject); if (string.Equals(prefabName, PrefabName, StringComparison.OrdinalIgnoreCase)) { return true; } } if (Category.HasValue && piece.m_category == Category.Value) { return true; } return false; } } public static class RaiderTargetingService { public static List FindPlayerStructures(Vector3 origin, float radius, List buffer) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (buffer == null) { buffer = new List(); } buffer.Clear(); Piece.GetAllPiecesInRadius(origin, radius, buffer); for (int num = buffer.Count - 1; num >= 0; num--) { Piece val = buffer[num]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null || !((Component)val).gameObject.activeInHierarchy) { buffer.RemoveAt(num); } else if (!val.IsPlacedByPlayer()) { buffer.RemoveAt(num); } } return buffer; } public static Piece SelectHighestPriorityStructure(IList candidates, IReadOnlyList priorities, Vector3 origin) { //IL_0062: 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) if (candidates == null || candidates.Count == 0) { return null; } Piece val = null; int num = int.MaxValue; float num2 = float.MaxValue; Piece val2 = null; float num3 = float.MaxValue; foreach (Piece candidate in candidates) { if ((Object)(object)candidate == (Object)null) { continue; } float num4 = Vector3.Distance(origin, ((Component)candidate).transform.position); bool flag = false; if (priorities != null) { foreach (StructurePriority priority in priorities) { if (priority.Matches(candidate)) { flag = true; if (priority.Priority < num || (priority.Priority == num && num4 < num2)) { val = candidate; num = priority.Priority; num2 = num4; } break; } } } if (!flag && num4 < num3) { val2 = candidate; num3 = num4; } } return val ?? val2; } public static Character FindBlockingPlayer(Vector3 origin, Vector3 destination, float horizontalRadius) { //IL_0065: 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_006e: 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) //IL_007a: 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) List allPlayers = Player.GetAllPlayers(); if (allPlayers == null || allPlayers.Count == 0) { return null; } foreach (Player item in allPlayers) { if (!((Object)(object)item == (Object)null) && !((Character)item).IsDead() && !((Character)item).InGhostMode() && !item.InDebugFlyMode()) { Vector3 val = ClosestPointOnSegmentXZ(origin, destination, ((Component)item).transform.position); float num = Utils.DistanceXZ(val, ((Component)item).transform.position); if (num <= horizontalRadius) { return (Character)(object)item; } } } return null; } public static Character FindClosestPlayer(Vector3 origin, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Player closestPlayer = Player.GetClosestPlayer(origin, radius); return (Character)(object)(((Object)(object)closestPlayer != (Object)null && !((Character)closestPlayer).IsDead()) ? closestPlayer : null); } private static Vector3 ClosestPointOnSegmentXZ(Vector3 a, Vector3 b, Vector3 point) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0026: 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_003e: 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_004a: Unknown result type (might be due to invalid IL or missing references) //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_006f: 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_0071: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_00b7: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(a.x, 0f, a.z); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(b.x, 0f, b.z); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(point.x, 0f, point.z); Vector3 val4 = val2 - val; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (sqrMagnitude < Mathf.Epsilon) { return val; } float num = Vector3.Dot(val3 - val, val4) / sqrMagnitude; num = Mathf.Clamp01(num); Vector3 val5 = val + val4 * num; return new Vector3(val5.x, point.y, val5.z); } } public class RaiderTowerOverwrites { private static readonly string[] MistlandsTowerPrefabs = new string[3] { "Mistlands_GuardTower1_new", "Mistlands_GuardTower2_new", "Mistlands_GuardTower3_new" }; private static readonly string[] MountainTowerPrefabs = new string[2] { "MountainGrave01", "WoodCabin02" }; private static readonly string[] MeadowsVillagePrefabs = new string[1] { "WoodVillage1" }; private static readonly string ProcessedLocationsFile = Path.Combine(Paths.ConfigPath, "RaiderClans_processedLocations.txt"); internal static readonly HashSet processedLocations = new HashSet(); public static void Initialize() { LoadProcessedLocations(); } public static void SaveProcessedLocations() { try { File.WriteAllLines(ProcessedLocationsFile, processedLocations); } catch (Exception arg) { RaiderClansPlugin.Logger.LogError((object)$"Failed to persist processed locations: {arg}"); } } private static void LoadProcessedLocations() { processedLocations.Clear(); if (!File.Exists(ProcessedLocationsFile)) { return; } try { string[] array = File.ReadAllLines(ProcessedLocationsFile); for (int i = 0; i < array.Length; i++) { string text = array[i]?.Trim(); if (!string.IsNullOrEmpty(text)) { processedLocations.Add(text); } } } catch (Exception arg) { RaiderClansPlugin.Logger.LogError((object)$"Failed to load processed locations: {arg}"); } } public static HashSet GetProcessedLocations() { return new HashSet(processedLocations); } public static int ProcessZoneLocations(Vector2i zoneID) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) RaiderClansPlugin.LogDebug($"Manually triggering zone processing for {zoneID}"); RaiderClansPlugin.Logger.LogInfo((object)"Zone processing is automatic - locations will be processed when zone loads"); RaiderClansPlugin.Logger.LogInfo((object)$"Current processed locations: {processedLocations.Count}"); return processedLocations.Count; } public static bool IsMistlandsTower(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } string[] mistlandsTowerPrefabs = MistlandsTowerPrefabs; foreach (string value in mistlandsTowerPrefabs) { if (prefabName.Equals(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static bool IsMountainTower(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } string[] mountainTowerPrefabs = MountainTowerPrefabs; foreach (string value in mountainTowerPrefabs) { if (prefabName.Equals(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static bool IsMeadowsVillage(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } string[] meadowsVillagePrefabs = MeadowsVillagePrefabs; foreach (string value in meadowsVillagePrefabs) { if (prefabName.Equals(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static bool ShouldInjectPlainsVillage(Biome biome, string prefabName) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 if ((int)biome != 16) { return false; } return IsMeadowsVillage(prefabName); } public static void OverwriteLocationSpawners(GameObject locationRoot, string prefabName) { if ((Object)(object)locationRoot == (Object)null) { return; } CreatureSpawner[] componentsInChildren = locationRoot.GetComponentsInChildren(true); CreatureSpawner[] array = componentsInChildren; foreach (CreatureSpawner val in array) { if (!((Object)(object)val == (Object)null)) { GameObject creaturePrefab = val.m_creaturePrefab; string text = ((creaturePrefab != null) ? ((Object)creaturePrefab).name : null) ?? ""; if (IsMistlandsTower(prefabName) && IsDvergrSpawner(text)) { Object.Destroy((Object)(object)val); RaiderClansPlugin.Logger.LogInfo((object)("Destroyed Dvergr spawner: " + text)); } else if (IsMeadowsVillage(prefabName) && IsDraugrSpawner(text)) { Object.Destroy((Object)(object)val); RaiderClansPlugin.Logger.LogInfo((object)("Destroyed draugr spawner: " + text)); } } } RepairLocationPieces(locationRoot); if (IsMistlandsTower(prefabName) || IsMountainTower(prefabName)) { SpawnTowerRaiders(locationRoot); } else if (IsMeadowsVillage(prefabName)) { SpawnVillageRaiders(locationRoot); } } private static void RepairLocationPieces(GameObject locationRoot) { if ((Object)(object)locationRoot == (Object)null) { return; } WearNTear[] componentsInChildren = locationRoot.GetComponentsInChildren(true); WearNTear[] array = componentsInChildren; foreach (WearNTear val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val.m_nview != (Object)null) { val.m_nview.m_zdo.Set("health", val.m_health); val.m_nview.m_zdo.Set("float_health", val.m_health); } } } private static bool IsDvergrSpawner(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } return prefabName.Contains("Dvergr", StringComparison.OrdinalIgnoreCase) || prefabName.Contains("dvergr", StringComparison.OrdinalIgnoreCase); } private static bool IsDraugrSpawner(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } return prefabName.Contains("Draugr", StringComparison.OrdinalIgnoreCase) || prefabName.Contains("draugr", StringComparison.OrdinalIgnoreCase); } public static void SpawnTowerRaiders(GameObject towerRoot) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)towerRoot == (Object)null) { return; } Vector3 position = towerRoot.transform.position; Biome biome = WorldGenerator.instance.GetBiome(position); int num = Random.Range(3, 6); for (int i = 0; i < num; i++) { Vector3 randomTowerPosition = GetRandomTowerPosition(position, 10f, 25f); Humanoid val = RaiderAI.SpawnRaider(randomTowerPosition, biome); if ((Object)(object)val != (Object)null) { RaiderClansPlugin.Logger.LogInfo((object)$"Spawned tower raider at: {randomTowerPosition}"); } } Vector3 randomTowerPosition2 = GetRandomTowerPosition(position, 0f, 5f); randomTowerPosition2.y += 10f; Humanoid val2 = RaiderAI.SpawnRaider(randomTowerPosition2, biome, isChieftain: true); if ((Object)(object)val2 != (Object)null) { Character component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null) { component.m_name = "Tower Commander"; } RaiderClansPlugin.Logger.LogInfo((object)$"Spawned Tower Commander at: {randomTowerPosition2}"); } } public static void SpawnVillageRaiders(GameObject villageRoot) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_004f: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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) if ((Object)(object)villageRoot == (Object)null) { return; } Vector3 position = villageRoot.transform.position; Biome biome = WorldGenerator.instance.GetBiome(position); int num = Random.Range(5, 11); for (int i = 0; i < num; i++) { Vector3 randomTowerPosition = GetRandomTowerPosition(position, 5f, 30f); Humanoid val = RaiderAI.SpawnRaider(randomTowerPosition, biome); if ((Object)(object)val != (Object)null) { RaiderClansPlugin.Logger.LogInfo((object)$"Spawned village raider at: {randomTowerPosition}"); } } Vector3 randomTowerPosition2 = GetRandomTowerPosition(position, 0f, 10f); Humanoid val2 = RaiderAI.SpawnRaider(randomTowerPosition2, biome, isChieftain: true); if ((Object)(object)val2 != (Object)null) { Character component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null) { component.m_name = "Village Chieftain"; } RaiderClansPlugin.Logger.LogInfo((object)$"Spawned Village Chieftain at: {randomTowerPosition2}"); } } private static Vector3 GetRandomTowerPosition(Vector3 center, float minRadius, float maxRadius) { //IL_003b: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) float num = Random.Range(0f, 360f) * (MathF.PI / 180f); float num2 = Random.Range(minRadius, maxRadius); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Sin(num) * num2, 0f, Mathf.Cos(num) * num2); return center + val; } } [HarmonyPatch(typeof(ZoneSystem), "PlaceLocations")] internal class ZoneSystemPlaceLocationsPatch { private static void Postfix(ZoneSystem __instance, Vector2i zoneID, Vector3 zoneCenterPos, Transform parent, Heightmap hmap, List clearAreas, SpawnMode mode, List spawnedObjects) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Invalid comparison between Unknown and I4 //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0185: 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_0207: 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_0249: Unknown result type (might be due to invalid IL or missing references) if (!RaiderClansPlugin.EnableTowerOverwrites.Value || (int)mode > 0) { return; } foreach (GameObject spawnedObject in spawnedObjects) { if ((Object)(object)spawnedObject == (Object)null) { continue; } Location component = spawnedObject.GetComponent(); if ((Object)(object)component == (Object)null) { continue; } string text = ""; if ((Object)(object)spawnedObject.GetComponent() != (Object)null && spawnedObject.GetComponent().m_zdo != null) { text = spawnedObject.GetComponent().m_zdo.GetString(ZDOVars.s_location, ""); } Biome biome = WorldGenerator.instance.GetBiome(spawnedObject.transform.position); if (RaiderTowerOverwrites.IsMistlandsTower(text) || RaiderTowerOverwrites.IsMountainTower(text)) { string item = $"{zoneID.x}_{zoneID.y}_{text}"; if (!RaiderTowerOverwrites.processedLocations.Contains(item)) { RaiderTowerOverwrites.processedLocations.Add(item); RaiderClansPlugin.Logger.LogInfo((object)$"Processing tower: {text} at zone {zoneID}"); RaiderTowerOverwrites.OverwriteLocationSpawners(spawnedObject, text); } } else if (RaiderTowerOverwrites.IsMeadowsVillage(text) && (int)biome == 1) { string item2 = $"{zoneID.x}_{zoneID.y}_{text}"; if (!RaiderTowerOverwrites.processedLocations.Contains(item2)) { RaiderTowerOverwrites.processedLocations.Add(item2); RaiderClansPlugin.Logger.LogInfo((object)$"Processing Meadows village: {text} at zone {zoneID}"); RaiderTowerOverwrites.OverwriteLocationSpawners(spawnedObject, text); } } else if (RaiderTowerOverwrites.ShouldInjectPlainsVillage(biome, text)) { string item3 = $"{zoneID.x}_{zoneID.y}_{text}"; if (!RaiderTowerOverwrites.processedLocations.Contains(item3)) { RaiderTowerOverwrites.processedLocations.Add(item3); RaiderClansPlugin.Logger.LogInfo((object)$"Processing Plains village injection: {text} at zone {zoneID}"); RaiderTowerOverwrites.OverwriteLocationSpawners(spawnedObject, text); } } } } } public sealed class WarriorBehaviorFactory : IRaiderBehaviorFactory { private readonly float _minAttackInterval; private readonly float _viewRangeMultiplier; public WarriorBehaviorFactory(float minAttackInterval = 1.5f, float viewRangeMultiplier = 1.1f) { _minAttackInterval = Mathf.Max(0.5f, minAttackInterval); _viewRangeMultiplier = Mathf.Max(0.5f, viewRangeMultiplier); } public void Attach(GameObject raiderObject) { if (!((Object)(object)raiderObject == (Object)null)) { WarriorBehavior warriorBehavior = raiderObject.GetComponent(); if ((Object)(object)warriorBehavior == (Object)null) { warriorBehavior = raiderObject.AddComponent(); } warriorBehavior.Configure(_minAttackInterval, _viewRangeMultiplier); } } } public sealed class ChieftainBehaviorFactory : IRaiderBehaviorFactory { private readonly float _minAttackInterval; private readonly float _viewRangeMultiplier; private readonly float _roarInterval; public ChieftainBehaviorFactory(float minAttackInterval = 1.25f, float viewRangeMultiplier = 1.2f, float roarInterval = 30f) { _minAttackInterval = Mathf.Max(0.3f, minAttackInterval); _viewRangeMultiplier = Mathf.Max(0.5f, viewRangeMultiplier); _roarInterval = Mathf.Max(5f, roarInterval); } public void Attach(GameObject raiderObject) { if (!((Object)(object)raiderObject == (Object)null)) { ChieftainBehavior chieftainBehavior = raiderObject.GetComponent(); if ((Object)(object)chieftainBehavior == (Object)null) { chieftainBehavior = raiderObject.AddComponent(); } chieftainBehavior.Configure(_minAttackInterval, _viewRangeMultiplier, _roarInterval); } } } public class WarriorBehavior : MonoBehaviour { protected MonsterAI MonsterAI; protected Character Character; private ZNetView _nview; private float _minAttackInterval = 1.5f; private float _viewRangeMultiplier = 1f; private bool _configured; public void Configure(float minAttackInterval, float viewRangeMultiplier) { _minAttackInterval = Mathf.Max(0.3f, minAttackInterval); _viewRangeMultiplier = Mathf.Max(0.5f, viewRangeMultiplier); _configured = true; ApplyTuning(); } protected virtual void Awake() { MonsterAI = ((Component)this).GetComponent(); Character = ((Component)this).GetComponent(); _nview = ((Component)this).GetComponent(); } protected virtual void Start() { if (!_configured) { Configure(_minAttackInterval, _viewRangeMultiplier); } } protected virtual void Update() { if (!((Object)(object)_nview == (Object)null) && _nview.IsOwner() && !((Object)(object)MonsterAI == (Object)null) && !((BaseAI)MonsterAI).IsAlerted()) { ((BaseAI)MonsterAI).Alert(); } } private void ApplyTuning() { if (!((Object)(object)MonsterAI == (Object)null)) { MonsterAI.m_minAttackInterval = Mathf.Min(MonsterAI.m_minAttackInterval, _minAttackInterval); MonsterAI monsterAI = MonsterAI; ((BaseAI)monsterAI).m_viewRange = ((BaseAI)monsterAI).m_viewRange * _viewRangeMultiplier; MonsterAI.m_enableHuntPlayer = true; } } } public sealed class ChieftainBehavior : WarriorBehavior { private float _roarInterval = 30f; private float _nextRoarTime; public void Configure(float minAttackInterval, float viewRangeMultiplier, float roarInterval) { Configure(minAttackInterval, viewRangeMultiplier); _roarInterval = Mathf.Max(5f, roarInterval); _nextRoarTime = Time.time + _roarInterval; } protected override void Update() { base.Update(); if (Time.time >= _nextRoarTime) { EmitLeadershipRoar(); _nextRoarTime = Time.time + _roarInterval; } } private void EmitLeadershipRoar() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Character == (Object)null)) { RaiderClansPlugin.LogDebug($"[ChieftainBehavior] Leadership roar placeholder at {((Component)Character).transform.position}"); } } } }