using System.Collections.Generic; namespace Harmony.SleeperVolumePatches { [HarmonyPatch(typeof(SleeperVolume))] [HarmonyPatch("CheckTrigger")] public class CheckTriggerPatch { public static bool Prefix(SleeperVolume __instance, ref bool __result, World _world, Vector3 playerPos) { if (RebirthVariables.customScenario == "purge") { if (__instance.wasCleared) { return false; } } return true; } } [HarmonyPatch(typeof(SleeperVolume))] [HarmonyPatch("Touch")] public class TouchPatch { public static bool Prefix(SleeperVolume __instance, World _world, EntityPlayer _player, bool setActive, SleeperVolume.ETriggerType trigger) { /*Log.Out("SleeperVolumePatches-Touch START"); if (__instance.prefabInstance != null) { Log.Out("SleeperVolumePatches-Touch __instance.prefabInstance.name: " + __instance.prefabInstance.name); Log.Out("SleeperVolumePatches-Touch __instance.prefabInstance.name: " + __instance.prefabInstance.name); }*/ /*if (RebirthVariables.customScenario == "purge") { //Log.Out("SleeperVolumePatches-Touch setActive: " + setActive); if (setActive) { //Log.Out("SleeperVolumePatches-Touch SET ACTIVE"); bool flag = (trigger == SleeperVolume.ETriggerType.Attack || trigger == SleeperVolume.ETriggerType.Trigger) && (bool)(UnityEngine.Object)_player; foreach (KeyValuePair respawn in __instance.respawnMap) { int key = respawn.Key; //Log.Out("SleeperVolumePatches-Touch __instance.PrefabInstance.name: " + __instance.PrefabInstance.name); //Log.Out("SleeperVolumePatches-Touch key: " + key); EntityAlive entity = (EntityAlive)_world.GetEntity(key); if ((bool)(UnityEngine.Object)entity) { Log.Out("SleeperVolumePatches-Touch WAKE UP entity: " + entity.EntityName); entity.Buffs.SetCustomVar("$IsAIOff", 0f); if (flag && _player.Stealth.CanSleeperAttackDetect(entity)) { Log.Out("SleeperVolumePatches-Touch 1"); entity.ConditionalTriggerSleeperWakeUp(); entity.SetAttackTarget((EntityAlive)_player, 400); } else if (trigger == SleeperVolume.ETriggerType.Wander) { Log.Out("SleeperVolumePatches-Touch 2"); entity.ConditionalTriggerSleeperWakeUp(); } else if (--SleeperVolume.wanderingCountdown <= 0) { Log.Out("SleeperVolumePatches-Touch 3"); SleeperVolume.wanderingCountdown = 10; entity.ConditionalTriggerSleeperWakeUp(); } else { Log.Out("SleeperVolumePatches-Touch 4"); entity.SetSleeperActive(); } } } __instance.hasPassives = false; __instance.triggerState = trigger; } else { __instance.playerTouchedToUpdate = _player; __instance.ticksUntilDespawn = 900; //Log.Out("SleeperVolumePatches-Touch __instance.hasPassives: " + __instance.hasPassives); if (__instance.hasPassives) { __instance.ticksUntilDespawn = 200; } if (!__instance.wasCleared || _world.worldTime >= __instance.respawnTime) { //Log.Out("SleeperVolumePatches-Touch 5"); return false; } __instance.respawnTime = Math.Max(__instance.respawnTime, _world.worldTime + 1000UL); } return false; }*/ return true; } } /*[HarmonyPatch(typeof(SleeperVolume))] [HarmonyPatch("Spawn")] public class SpawnPatch { public static void Postfix(SleeperVolume __instance, ref EntityAlive __result, World _world, int entityClass, int spawnIndex, BlockSleeper block) { if (RebirthVariables.customScenario == "purge") { Log.Out("SleeperVolumePatches-Spawn entity: " + __result.EntityName); __result.Buffs.SetCustomVar("$IsAIOff", 1f); } } }*/ [HarmonyPatch(typeof(SleeperVolume))] [HarmonyPatch("UpdatePlayerTouched")] public class UpdatePlayerTouchedPatch { public static bool Prefix(SleeperVolume __instance, World _world, EntityPlayer _playerTouched, int ___gameStage ) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched START"); if (__instance.isSpawned || _world.worldTime < __instance.respawnTime && __instance.wasCleared) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched IS SPAWNED"); return false; } if (_world.worldTime >= __instance.respawnTime) { // NEW - Prevent respawns in Purge if (RebirthVariables.customScenario != "purge") { __instance.Reset(); } } __instance.isSpawning = true; __instance.isSpawned = true; bool flag = false; float _countScale = 1f; if (__instance.prefabInstance != null) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched __instance.prefabInstance.name: " + __instance.prefabInstance.name); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched __instance.prefabInstance.prefab.PrefabName: " + __instance.prefabInstance.prefab.PrefabName); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched __instance.prefabInstance.sleeperVolumes.Count: " + __instance.prefabInstance.sleeperVolumes.Count); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched __instance.prefabInstance.prefab.SleeperVolumes.Count: " + __instance.prefabInstance.prefab.SleeperVolumes.Count); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched __instance.prefabInstance.boundingBoxPosition: " + __instance.prefabInstance.boundingBoxPosition); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched _playerTouched.position: " + _playerTouched.position); /*PrefabInstance poiatPosition = RebirthUtilities.GetPrefabAtPosition(_playerTouched.position); // _playerTouched.world.GetPOIAtPosition(_playerTouched.position, false); if (poiatPosition != null) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched poiatPosition.name: " + poiatPosition.name); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched poiatPosition.prefab.PrefabName: " + poiatPosition.prefab.PrefabName); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched poiatPosition.prefab.SleeperVolumes.Count: " + poiatPosition.prefab.SleeperVolumes.Count); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched poiatPosition.boundingBoxPosition: " + poiatPosition.boundingBoxPosition); }*/ if (__instance.prefabInstance.LastRefreshType.Test_AnySet(QuestEventManager.infestedTag)) flag = true; float num = __instance.prefabInstance.LastQuestClass == null ? 1f : __instance.prefabInstance.LastQuestClass.SpawnMultiplier; byte difficultyTier = __instance.prefabInstance.prefab.DifficultyTier; _countScale = num * ((int)difficultyTier < SleeperVolume.difficultyTierScale.Length ? SleeperVolume.difficultyTierScale[(int)difficultyTier] : SleeperVolume.difficultyTierScale[SleeperVolume.difficultyTierScale.Length - 1]); if (__instance.prefabInstance.LastRefreshType.Test_AnySet(QuestEventManager.banditTag)) _countScale = 0.2f; /*// NEW - Double spawns if (RebirthVariables.customScenario == "purge") { flag = true; }*/ if (RebirthVariables.customScenario == "purge" && !RebirthVariables.activatingSleeperVolumes) { if (_playerTouched.AttachedToEntity == null && !_playerTouched.IsFlyMode.Value) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched activateSleeperVolumes"); GameManager.Instance.StartCoroutine(RebirthUtilities.activateSleeperVolumes(__instance.prefabInstance.sleeperVolumes, _playerTouched, __instance.prefabInstance.prefab.PrefabName, new Vector3(__instance.prefabInstance.boundingBoxPosition.x, __instance.prefabInstance.boundingBoxPosition.y, __instance.prefabInstance.boundingBoxPosition.z), __instance.prefabInstance.prefab.DifficultyTier)); } } } if (__instance.spawnPointList.Count > 0) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched 1"); if (__instance.respawnMap.Count > 0) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched 2, __instance.respawnMap.Count: " + __instance.respawnMap.Count); __instance.respawnList = new List(__instance.respawnMap.Count); foreach (KeyValuePair respawn in __instance.respawnMap) __instance.respawnList.Add(respawn.Key); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched 3, __instance.respawnList.Count: " + __instance.respawnList.Count); } int num = 0; __instance.gameStage = Mathf.Max(0, __instance.GetGameStageAround(_playerTouched) + num); __instance.spawnsAvailable = new List(__instance.spawnPointList.Count); for (int index = 0; index < __instance.spawnPointList.Count; ++index) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched 4, index: " + index); if (flag || __instance.spawnPointList[index].GetBlock().spawnMode != BlockSleeper.eMode.Infested) __instance.spawnsAvailable.Add(index); } //Log.Out("SleeperVolumePatches-UpdatePlayerTouched 5, __instance.spawnsAvailable.Count: " + __instance.spawnsAvailable.Count); if (__instance.groupCountList != null) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched 6"); __instance.groupCountList.Clear(); } if (__instance.spawnCountMin < (short)0 || __instance.spawnCountMax < (short)0) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched 7"); __instance.spawnCountMin = (short)5; __instance.spawnCountMax = (short)6; } __instance.AddSpawnCount(__instance.groupName, (float)__instance.spawnCountMin * _countScale, (float)__instance.spawnCountMax * _countScale); __instance.spawnDelay = 0; } // NEW - START - Gamestage calculation string biomeName = RebirthUtilities.GetBiomeName(_playerTouched); if (__instance.prefabInstance != null) { int tier = __instance.prefabInstance.prefab.DifficultyTier; if (RebirthUtilities.ScenarioSkip()) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched A START: " + _playerTouched.biomeStandingOn.m_sBiomeName + $" ({_playerTouched.position})"); RebirthUtilities.SetHiveSpawnGroup(biomeName); } int biomeID = RebirthUtilities.GetCurrentBiomeID(biomeName); int adjustGamestage = RebirthUtilities.AdjustGamestage(_playerTouched.gameStage, tier, biomeID); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched CURRENT GAMESTAGE: " + _playerTouched.gameStage); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched GAMESTAGE ADJUSTMENT: " + adjustGamestage); RebirthVariables.gameStage = _playerTouched.gameStage + adjustGamestage; //Log.Out("SleeperVolumePatches-UpdatePlayerTouched AJUSTED GAMESTAGE: " + RebirthVariables.gameStage); } else { RebirthVariables.gameStage = _playerTouched.gameStage; if (RebirthUtilities.ScenarioSkip()) { //Log.Out("SleeperVolumePatches-UpdatePlayerTouched B START: " + _playerTouched.biomeStandingOn.m_sBiomeName + $" ({_playerTouched.position})"); RebirthUtilities.SetHiveSpawnGroup(biomeName); } } // NEW - END if (__instance.minScript == null) return false; __instance.minScript.Run(__instance, _playerTouched, _countScale); return false; } /*public static void Postfix(SleeperVolume __instance, World _world, EntityPlayer _playerTouched, int ___gameStage ) { PrefabInstance poiatPosition = RebirthUtilities.GetPrefabAtPosition(_playerTouched.position); // _playerTouched.world.GetPOIAtPosition(_playerTouched.position, false); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched ___gameStage: " + ___gameStage); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched _playerTouched.gameStage: " + _playerTouched.gameStage); if (poiatPosition != null) { int tier = poiatPosition.prefab.DifficultyTier; int adjustGamestage = RebirthUtilities.AdjustGamestage(_playerTouched.gameStage, tier); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched CURRENT GAMESTAGE: " + _playerTouched.gameStage); //Log.Out("SleeperVolumePatches-UpdatePlayerTouched GAMESTAGE ADJUSTMENT: " + adjustGamestage); RebirthVariables.gameStage = _playerTouched.gameStage + adjustGamestage; //Log.Out("SleeperVolumePatches-UpdatePlayerTouched AJUSTED GAMESTAGE: " + RebirthVariables.gameStage); } else { RebirthVariables.gameStage = _playerTouched.gameStage; } //Log.Out("SleeperVolumePatches-UpdatePlayerTouched START, RebirthVariables.gameStage: " + RebirthVariables.gameStage); }*/ } [HarmonyPatch(typeof(SleeperVolume))] [HarmonyPatch("CheckTouching")] public class CheckTouchingPatch { public static MethodInfo TouchGroup = AccessTools.Method(typeof(SleeperVolume), "TouchGroup", new Type[] { typeof(World), typeof(EntityPlayer), typeof(bool) }); public static MethodInfo CheckTrigger = AccessTools.Method(typeof(SleeperVolume), "CheckTrigger", new Type[] { typeof(World), typeof(Vector3) }); public struct RespawnData { public string className; public int spawnPointIndex; } public static void Postfix(SleeperVolume __instance, World _world, EntityPlayer _player, int ___flags, List ___TriggeredByIndices, Dictionary ___respawnMap, bool ___hasPassives, EntityPlayer ___playerTouchedToUpdate, SleeperVolume.ETriggerType ___triggerState, short ___groupId, PrefabInstance ___prefabInstance ) { //Log.Out("SleeperVolumePatches-CheckTouching START"); if ((___TriggeredByIndices.Count > 0 && ___respawnMap.Count == 0) || _player.IsSpectator) { //Log.Out("SleeperVolumePatches-CheckTouching RETURN"); return; } for (int j = 0; j < _player.Companions.Count; j++) { EntityNPCRebirth companion = _player.Companions[j] as EntityNPCRebirth; if (companion != null) { //Log.Out("SleeperVolumePatches-CheckTouching companion: " + companion.EntityClass.entityClassName); Vector3 position = companion.position; position.y += 0.8f; SleeperVolume.ETriggerType etriggerType = (SleeperVolume.ETriggerType)(___flags & 7); if (___hasPassives) { if (position.x >= (float)__instance.BoxMin.x - -0.3f && position.x < (float)__instance.BoxMax.x + -0.3f && position.y >= (float)__instance.BoxMin.y && position.y < (float)__instance.BoxMax.y && position.z >= (float)__instance.BoxMin.z - -0.3f && position.z < (float)__instance.BoxMax.z + -0.3f && etriggerType != SleeperVolume.ETriggerType.Passive) { //Log.Out("SleeperVolumePatches-CheckTouching 1"); TouchGroup.Invoke(__instance, new object[] { _world, _player, true }); } } else if ((etriggerType == SleeperVolume.ETriggerType.Attack || etriggerType == SleeperVolume.ETriggerType.Trigger) && ___triggerState != etriggerType && position.x >= (float)__instance.BoxMin.x - -0.1f && position.x < (float)__instance.BoxMax.x + -0.1f && position.y >= (float)__instance.BoxMin.y && position.y < (float)__instance.BoxMax.y && position.z >= (float)__instance.BoxMin.z - -0.1f && position.z < (float)__instance.BoxMax.z + -0.1f) { //Log.Out("SleeperVolumePatches-CheckTouching 2"); TouchGroup.Invoke(__instance, new object[] { _world, _player, true }); } object[] pCheckTrigger = new object[] { _world, position }; bool triggerChecked = (bool)CheckTrigger.Invoke(__instance, new object[] { _world, position }); if (___playerTouchedToUpdate == null && triggerChecked) { //Log.Out("SleeperVolumePatches-CheckTouching 3"); TouchGroup.Invoke(__instance, new object[] { _world, _player, false }); } } } } } [HarmonyPatch(typeof(SleeperVolume))] [HarmonyPatch("UpdateSpawn")] public class UpdateSpawnPatch { public static bool Prefix(SleeperVolume __instance, World _world, PrefabInstance ___prefabInstance ) { //Log.Out("SleeperVolumePatches-UpdateSpawn START"); if (___prefabInstance != null && ___prefabInstance.prefab != null) { RebirthVariables.prefabDifficulty = ___prefabInstance.prefab.DifficultyTier; if (RebirthUtilities.ScenarioSkip()) { string biomeName = RebirthUtilities.GetBiomeName(___prefabInstance.boundingBoxPosition); if (biomeName != "") { //Log.Out("SleeperVolumePatches-UpdateSpawn START: " + biomeAt.m_sBiomeName + $" ({___prefabInstance.boundingBoxPosition})"); RebirthUtilities.SetHiveSpawnGroup(biomeName); } } } //EXISTING CODE /*if (--__instance.spawnDelay > 0) { Log.Out("SleeperVolumePatches-UpdateSpawn 1"); return false; } __instance.spawnDelay = 2; bool flag1 = AIDirector.CanSpawn(2.1f); int num1 = GameStats.GetInt(EnumGameStats.EnemyCount); bool flag2 = false; if (__instance.minScript != null && __instance.minScript.IsRunning()) { Log.Out("SleeperVolumePatches-UpdateSpawn 2"); flag2 = true; } if (__instance.spawnsAvailable != null && __instance.spawnsAvailable.Count > 0) { Log.Out("SleeperVolumePatches-UpdateSpawn 3"); string cultureInvariantString = Time.time.ToCultureInvariantString(); if (__instance.respawnList != null && __instance.respawnList.Count > 0) { Log.Out("SleeperVolumePatches-UpdateSpawn 4"); int respawn = __instance.respawnList[__instance.respawnList.Count - 1]; __instance.respawnList.RemoveAt(__instance.respawnList.Count - 1); Entity entity = _world.GetEntity(respawn); if ((bool)(UnityEngine.Object)entity) { Log.Out("SleeperVolumePatches-UpdateSpawn 5"); __instance.hasPassives = true; flag2 = true; Log.Out("{0} SleeperVolume {1}: Still alive '{2}'", (object)cultureInvariantString, (object)__instance.BoxMin, (object)entity.name); } else { Log.Out("SleeperVolumePatches-UpdateSpawn 6"); int num2 = __instance.respawnMap[respawn].spawnPointIndex; if (num2 >= 0) { Log.Out("SleeperVolumePatches-UpdateSpawn 7"); __instance.RemoveSpawnAvailable(num2); } else { Log.Out("SleeperVolumePatches-UpdateSpawn 8"); num2 = __instance.FindSpawnIndex(_world); } if (num2 >= 0) { Log.Out("SleeperVolumePatches-UpdateSpawn 9"); SleeperVolume.SpawnPoint spawnPoint = __instance.spawnPointList[num2]; if (!__instance.CheckSpawnPos(_world, spawnPoint.pos)) { Log.Out("SleeperVolumePatches-UpdateSpawn 10"); __instance.respawnList.Add(respawn); __instance.spawnsAvailable.Add(num2); return false; } string className = __instance.respawnMap[respawn].className; Log.Out("{0} SleeperVolume {1}: Restoring {2} ({3}) '{4}', count {5}", (object)cultureInvariantString, (object)__instance.BoxMin, (object)spawnPoint.pos, (object)World.toChunkXZ(spawnPoint.pos), (object)className, (object)num1); int entityClass = EntityClass.FromString(className); BlockSleeper block = spawnPoint.GetBlock(); if ((bool)(UnityEngine.Object)__instance.Spawn(_world, entityClass, num2, block)) { Log.Out("SleeperVolumePatches-UpdateSpawn 11"); __instance.respawnMap.Remove(respawn); } flag2 = true; } } } else if (flag1) { Log.Out("SleeperVolumePatches-UpdateSpawn 12"); GameStageDefinition gameStageDefinition = (GameStageDefinition)null; if (__instance.groupCountList != null) { Log.Out("SleeperVolumePatches-UpdateSpawn 13"); int num3 = 0; for (int index = 0; index < __instance.groupCountList.Count; ++index) { Log.Out("SleeperVolumePatches-UpdateSpawn 14, index: " + index); num3 += __instance.groupCountList[index].count; if (num3 > __instance.numSpawned) { Log.Out("SleeperVolumePatches-UpdateSpawn 15"); GameStageGroup gameStageGroup = GameStageGroup.TryGet(__instance.groupCountList[index].groupName); if (gameStageGroup != null) { Log.Out("SleeperVolumePatches-UpdateSpawn 16"); gameStageDefinition = gameStageGroup.spawner; break; } } } } if (gameStageDefinition != null) { Log.Out("SleeperVolumePatches-UpdateSpawn 17"); GameStageDefinition.Stage stage = gameStageDefinition.GetStage(__instance.gameStage); if (stage != null) { Log.Out("SleeperVolumePatches-UpdateSpawn 18"); int spawnIndex = __instance.FindSpawnIndex(_world); if (spawnIndex >= 0) { Log.Out("SleeperVolumePatches-UpdateSpawn 19"); SleeperVolume.SpawnPoint spawnPoint = __instance.spawnPointList[spawnIndex]; if (!__instance.CheckSpawnPos(_world, spawnPoint.pos)) { Log.Out("SleeperVolumePatches-UpdateSpawn 20"); __instance.spawnsAvailable.Add(spawnIndex); return false; } BlockSleeper block = spawnPoint.GetBlock(); if (block == null) { Log.Out("SleeperVolumePatches-UpdateSpawn 21"); Log.Error("{0} BlockSleeper {1} null, type {2}", (object)cultureInvariantString, (object)spawnPoint.pos, (object)spawnPoint.blockType); } else { Log.Out("SleeperVolumePatches-UpdateSpawn 22"); string _sEntityGroupName = block.spawnGroup; if (string.IsNullOrEmpty(_sEntityGroupName)) { _sEntityGroupName = stage.GetSpawnGroup(0).groupName; Log.Out("SleeperVolumePatches-UpdateSpawn 23"); } int randomFromGroup = EntityGroups.GetRandomFromGroup(_sEntityGroupName, ref __instance.lastClassId, SleeperVolume.sleeperRandom); EntityClass entityClass; EntityClass.list.TryGetValue(randomFromGroup, out entityClass); Log.Out("{0} SleeperVolume {1}: Spawning {2} ({3}), group '{4}', class {5}, count {6}", (object)cultureInvariantString, (object)__instance.BoxMin, (object)spawnPoint.pos, (object)World.toChunkXZ(spawnPoint.pos), (object)_sEntityGroupName, entityClass != null ? (object)entityClass.entityClassName : (object)"?", (object)num1); if ((bool)(UnityEngine.Object)__instance.Spawn(_world, randomFromGroup, spawnIndex, block)) { Log.Out("SleeperVolumePatches-UpdateSpawn 24"); ++__instance.numSpawned; } flag2 = true; } } } } } } if (flag2) { Log.Out("SleeperVolumePatches-UpdateSpawn 25"); return false; } __instance.isSpawning = false; __instance.respawnList = (List)null; if (__instance.numSpawned != 0) { Log.Out("SleeperVolumePatches-UpdateSpawn 26"); return false; } if (__instance.respawnMap.Count == 0) { Log.Out("SleeperVolumePatches-UpdateSpawn 27"); __instance.wasCleared = true; } Log.Out("{0} SleeperVolume {1}: None spawned, canSpawn {2}, respawnCnt {3}", (object)Time.time.ToCultureInvariantString(), (object)__instance.BoxMin, (object)flag1, (object)__instance.respawnMap.Count); return false;*/ return true; } } }