using System.Collections; using System.Reflection; using CLre.API.Engines; using Game.Building; using Game.Character; using Game.Utilities; using HarmonyLib; using Svelto.ECS; using Svelto.Tasks; using UnityEngine; using voxelfarm.VFCol; namespace CLre.Fixes { [Bugfix(name = "UnderStructureCollider", description = "Prevent passing through structures from below a bit better", more = "https://trello.com/c/nfuaZWQZ/10-passing-through-structures", component = BugfixType.Initialiser, id = 7)] public static class UnderStructureCollider { public static void Init() { #if DEBUG MainLevel_BuildDeprecatedEngines_Patch.afterBuildEngines.Add(new CharacterGroundedCheckEngine()); #endif MainLevel_BuildDeprecatedEngines_Patch.afterBuildEngines.Add(new CharacterUnderStructureRaycastEngine()); } } [Bugfix(name = "UnderStructureCollider", description = "Prevent passing through structures from below a bit better", more = "https://trello.com/c/nfuaZWQZ/10-passing-through-structures", component = BugfixType.HarmonyPatch, id = 7)] [HarmonyPatch(typeof(VFColUtility), "Move")] class VFCOlUtility_Move_Patch { internal static bool Override = false; [HarmonyPostfix] public static void AfterMethodCall(ref Vector3 __result) { #if DEBUG API.Utility.Logging.MetaLog("Intercepting CharacterMovementEngine.ApplyForces(...)"); #endif if (Override) { if (__result.y > 0) { __result = Vector3.zero; } } } } #if DEBUG [Bugfix(name = "UnderStructureCollider", description = "Prevent passing through structures from below a bit better", more = "https://trello.com/c/nfuaZWQZ/10-passing-through-structures", component = BugfixType.Debug, id = 7)] public class CharacterGroundedCheckEngine : SingleEntityViewEngine, ICLreEngine { private CharacterOnStructureNode _characterOnStructureNode; public void Ready() {} public IEntitiesDB entitiesDB { get; set; } public IEntityFactory entityFactory { get; set; } protected override void Add(CharacterOnStructureNode entityView) { _characterOnStructureNode = entityView; CheckNode().Run(); } protected override void Remove(CharacterOnStructureNode entityView) { _characterOnStructureNode = null; } public IEnumerator CheckNode() { while (_characterOnStructureNode != null) { if (_characterOnStructureNode.characterGroundedRaycastComponent.didHit) { if (_characterOnStructureNode.characterGroundedRaycastComponent.hitResult.transform != null) { API.Utility.Logging.MetaLog($"HIT: {_characterOnStructureNode.characterGroundedRaycastComponent.hitResult.transform.tag} (audio: '{_characterOnStructureNode.characterOnStructureComponent.characterPositionStructureAudioSwitch.value}')"); RaycastHit raycastHitInfo = _characterOnStructureNode.characterGroundedRaycastComponent.hitResult; if (raycastHitInfo.transform.tag == GameTags.STRUCTURE_TAG) { int instanceID = raycastHitInfo.transform.GetComponentInParent().gameObject.GetInstanceID(); if (entitiesDB.TryQueryEntityView(instanceID, DEPRECATED_SveltoExtensions.DEPRECATED_GROUP, out PlacedStructureNode entityView)) { API.Utility.Logging.MetaLog($"Structure: {entityView.structureNameComponent.resourceName}"); } } } else { API.Utility.Logging.MetaLog("No transform (not on a structure?)"); } } else { API.Utility.Logging.MetaLog("No hit"); } yield return null; } } } #endif [Bugfix(name = "UnderStructureCollider", description = "Prevent passing through structures from below a bit better", more = "https://trello.com/c/nfuaZWQZ/10-passing-through-structures", component = BugfixType.Miscellaneous, id = 7)] public class CharacterUnderStructureRaycastEngine : SingleEntityViewEngine, ICLreEngine { private bool _playerExists = false; private int _layer = GameLayers.CARD_INTERACTABLE; public void Ready() { } public IEntitiesDB entitiesDB { get; set; } public IEntityFactory entityFactory { get; set; } protected override void Add(CharacterMovementNode entityView) { _playerExists = true; RaycastStructureCheck(entityView.ID.entityID).RunOnScheduler(StandardSchedulers.physicScheduler); } protected override void Remove(CharacterMovementNode entityView) { _playerExists = false; } public IEnumerator RaycastStructureCheck(int playerId) { while (_playerExists) { CharacterMovementNode cmn; while (entitiesDB.TryQueryEntityView(playerId, DEPRECATED_SveltoExtensions.DEPRECATED_GROUP, out cmn)) { Vector3 position = cmn.characterMovementComponent.characterController.transform.position; CharacterController cc = cmn.characterMovementComponent.characterController; RaycastHit rayInfo; bool didHit = Physics.SphereCast( position, //+ Vector3.up * (cc.height * 0.5f), // center of player cc.radius, Vector3.up, out rayInfo, cc.height, //* 0.5f - cc.radius * 0.05f, _layer); if (didHit && rayInfo.transform != null) { if (rayInfo.transform.CompareTag(GameTags.STRUCTURE_TAG)) { #if DEBUG API.Utility.Logging.MetaLog("Structure is above me!"); #endif VFCOlUtility_Move_Patch.Override = true; } } else { #if DEBUG API.Utility.Logging.MetaLog("No structure above :("); #endif VFCOlUtility_Move_Patch.Override = false; } yield return null; } yield return null; } } } }