using System.Collections.Generic; using RoR2; using RoR2.HudOverlay; using RoR2.UI; using UnityEngine; using UnityEngine.UI; namespace EntityStates.Seeker; public class MeditationUI : BaseSkillState { [SerializeField] [Header("UI")] public GameObject scopeOverlayPrefab; [SerializeField] public float duration = 5f; [SerializeField] public float timePenalty = 1f; [SerializeField] public float failureCooldownPenalty = 5f; [SerializeField] public float animDuration; [SerializeField] public float smallHopVelocity; [SerializeField] public Sprite primaryIcon; [SerializeField] public Sprite secondaryIcon; [SerializeField] public Sprite utilityIcon; [SerializeField] public Sprite specialIcon; [SerializeField] public SeekerController seekerController; [SerializeField] public GameObject lotusPrefab; [SerializeField] public float wrapUpDuration; [SerializeField] public GameObject successEffectPrefab; [SerializeField] public GameObject crosshairOverridePrefab; [SerializeField] public string startSoundString; [SerializeField] public string stopSoundString; [SerializeField] public string timeoutSoundString; [SerializeField] public string successSoundString; [SerializeField] public string inputCorrectSoundString; [SerializeField] public string inputFailSoundString; [SerializeField] [Header("Healing Explosion")] public float healingExplosionAmount = 10f; [SerializeField] public float healingOverShield = 5f; [SerializeField] public float blastRadius = 5f; [SerializeField] public float damageCoefficient = 5f; [SerializeField] public float blastForce = 5f; [SerializeField] public Vector3 blastBonusForce; [SerializeField] public float blastProcCoefficient = 5f; [SerializeField] public float percentPerGate = 0.75f; [SerializeField] public float overShieldPercent = 0.25f; [SerializeField] public float startingOverShieldPercentage = 0.33f; private CrosshairUtils.OverrideRequest crosshairOverrideRequest; private GameObject lotus; private OverlayController overlayController; private bool meditationSuccess; private ICharacterGravityParameterProvider characterGravityParameterProvider; private ChildLocator overlayInstanceChildLocator; private ChildLocator lotusChildLocator; private List fillUiList = new List(); private CameraTargetParams.AimRequest aimRequest; private bool spawnedLotus; private bool failed; private bool meditationWrapUp; private bool wrapUpAnimationPlayed; private float wrapUpTimer; private float startingYaw; private EntityStateMachine bodyStateMachine; private float explosionHealingMod; private bool upReady = true; private bool downReady = true; private bool rightReady = true; private bool leftReady = true; private static string[] c = new string[5] { "ArrowInput1", "ArrowInput2", "ArrowInput3", "ArrowInput4", "ArrowInput5" }; public override void OnEnter() { base.OnEnter(); EntityStateMachine[] components = base.characterBody.gameObject.GetComponents(); foreach (EntityStateMachine entityStateMachine in components) { if (entityStateMachine.customName == "Body") { bodyStateMachine = entityStateMachine; } } bodyStateMachine.SetNextState(new Idle()); explosionHealingMod = base.characterBody.maxHealth; if (explosionHealingMod < base.characterBody.baseMaxHealth) { explosionHealingMod = base.characterBody.baseMaxHealth; } base.healthComponent.AddBarrierAuthority(explosionHealingMod * startingOverShieldPercentage); seekerController = base.characterBody.transform.GetComponent(); if (base.isAuthority) { seekerController.RandomizeMeditationInputs(); } SmallHop(base.characterMotor, smallHopVelocity); if ((bool)base.characterMotor) { base.characterMotor.walkSpeedPenaltyCoefficient = 0f; } if ((bool)base.characterBody) { base.characterBody.isSprinting = false; } if ((bool)base.characterDirection) { base.characterDirection.moveVector = base.characterDirection.forward; } if ((bool)base.rigidbodyMotor) { base.rigidbodyMotor.moveVector = Vector3.zero; } PlayAnimation("FullBody, Override", "MeditationStart", "Meditation.playbackRate", animDuration); characterGravityParameterProvider = base.gameObject.GetComponent(); if (characterGravityParameterProvider != null) { CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; gravityParameters.channeledAntiGravityGranterCount++; characterGravityParameterProvider.gravityParameters = gravityParameters; } overlayController = HudOverlayManager.AddOverlay(base.gameObject, new OverlayCreationParams { prefab = scopeOverlayPrefab, childLocatorEntry = "CrosshairExtras" }); overlayController.onInstanceAdded += OnOverlayInstanceAdded; overlayController.onInstanceRemove += OnOverlayInstanceRemoved; crosshairOverrideRequest = CrosshairUtils.RequestOverrideForBody(base.characterBody, crosshairOverridePrefab, CrosshairUtils.OverridePriority.Skill); CameraTargetParams component = base.gameObject.GetComponent(); if ((bool)component) { aimRequest = component.RequestAimType(CameraTargetParams.AimType.ZoomedOut); } startingYaw = base.characterDirection.yaw; Util.PlaySound(startSoundString, base.gameObject); } public override void Update() { if (seekerController.meditationUIDirty) { seekerController.meditationUIDirty = false; UpdateUIInputSequence(); } base.characterDirection.yaw = startingYaw; base.characterDirection.moveVector = base.characterDirection.forward; base.Update(); if (meditationWrapUp) { wrapUpTimer += Time.deltaTime; if (wrapUpTimer > wrapUpDuration) { outer.SetNextStateToMain(); } if (!wrapUpAnimationPlayed) { wrapUpAnimationPlayed = true; if (meditationSuccess) { PlayAnimation("FullBody, Override", "MeditationSuccess", "Meditation.playbackRate", animDuration); Util.PlaySound(successSoundString, base.gameObject); lotus.GetComponentInChildren().Play("MeditationSuccess"); EffectManager.SpawnEffect(successEffectPrefab, new EffectData { origin = base.characterBody.corePosition }, transmit: true); if (base.isAuthority) { float num = 0f; float num2 = 0f; seekerController.IncrementChakraGate(); if (base.characterBody.HasBuff(DLC2Content.Buffs.ChakraBuff)) { num2 = base.characterBody.GetBuffCount(DLC2Content.Buffs.ChakraBuff); num = num2 * percentPerGate; } seekerController.CallCmdTriggerHealPulse((healingExplosionAmount * num2 + 0.04f) * explosionHealingMod, base.characterBody.corePosition, blastRadius); BlastAttack blastAttack = new BlastAttack(); blastAttack.attacker = base.characterBody.gameObject; blastAttack.baseDamage = (damageCoefficient + num) * base.characterBody.damage; blastAttack.baseForce = blastForce; blastAttack.bonusForce = blastBonusForce; blastAttack.attackerFiltering = AttackerFiltering.NeverHitSelf; blastAttack.crit = base.characterBody.RollCrit(); blastAttack.damageColorIndex = DamageColorIndex.Item; blastAttack.inflictor = base.gameObject; blastAttack.position = base.characterBody.corePosition; blastAttack.procChainMask = default(ProcChainMask); blastAttack.procCoefficient = blastProcCoefficient; blastAttack.radius = blastRadius; blastAttack.falloffModel = BlastAttack.FalloffModel.None; blastAttack.teamIndex = base.teamComponent.teamIndex; blastAttack.Fire(); } } else { PlayAnimation("FullBody, Override", "MeditationFail", "Meditation.playbackRate", animDuration); Util.PlaySound(timeoutSoundString, base.gameObject); lotus.GetComponentInChildren().Play("MeditationFail"); outer.SetNextStateToMain(); } } } int num3 = -1; if (base.inputBank.rawMoveUp.justPressed) { num3 = 0; } if (base.inputBank.rawMoveDown.justPressed) { num3 = 1; } if (base.inputBank.rawMoveRight.justPressed) { num3 = 2; } if (base.inputBank.rawMoveLeft.justPressed) { num3 = 3; } if (seekerController.meditationInputStep > 4) { meditationSuccess = true; meditationWrapUp = true; } if (num3 == seekerController.GetNextMeditationStep()) { if (!wrapUpAnimationPlayed && seekerController.meditationInputStep < 5) { Util.PlaySound(inputCorrectSoundString, base.gameObject); seekerController.meditationInputStep++; } } else if (num3 != -1) { Util.PlaySound(inputFailSoundString, base.gameObject); base.fixedAge += timePenalty; } if (base.fixedAge > 0.4f) { base.characterMotor.velocity = new Vector3(0f, 0f, 0f); if (base.inputBank.skill4.justPressed) { meditationWrapUp = true; } Transform modelTransform = GetModelTransform(); if ((bool)modelTransform && !spawnedLotus) { spawnedLotus = true; lotusChildLocator = modelTransform.GetComponent(); lotus = Object.Instantiate(lotusPrefab, lotusChildLocator.FindChild("Lotus"), worldPositionStays: false); } } if (base.fixedAge > duration) { failed = true; meditationWrapUp = true; } else { UpdateUI(); } } private void SetupInputUIIcons() { for (int i = 0; i < 5; i++) { switch (seekerController.meditationStepAndSequence[i + 1]) { case 0: overlayInstanceChildLocator.FindChild(c[i]).GetComponent().rotation = Quaternion.Euler(0f, 0f, 0f); break; case 1: overlayInstanceChildLocator.FindChild(c[i]).GetComponent().rotation = Quaternion.Euler(0f, 0f, -180f); break; case 2: overlayInstanceChildLocator.FindChild(c[i]).GetComponent().rotation = Quaternion.Euler(0f, 0f, -90f); break; case 3: overlayInstanceChildLocator.FindChild(c[i]).GetComponent().rotation = Quaternion.Euler(0f, 0f, -270f); break; } } UpdateUIInputSequence(); } private void UpdateUIInputSequence() { if (base.isAuthority) { Color32 color = new Color32(byte.MaxValue, 233, 124, byte.MaxValue); for (int i = 0; i < seekerController.meditationInputStep; i++) { overlayInstanceChildLocator.FindChild(c[i]).GetComponent().color = color; } } } private void UpdateUI() { foreach (ImageFillController fillUi in fillUiList) { fillUi.SetTValue(base.fixedAge / duration); } } public override void OnExit() { PlayAnimation("FullBody, Override", "Empty"); Util.PlaySound(stopSoundString, base.gameObject); if (overlayController != null) { HudOverlayManager.RemoveOverlay(overlayController); overlayController = null; } aimRequest?.Dispose(); crosshairOverrideRequest?.Dispose(); if (characterGravityParameterProvider != null) { CharacterGravityParameters gravityParameters = characterGravityParameterProvider.gravityParameters; gravityParameters.channeledAntiGravityGranterCount--; characterGravityParameterProvider.gravityParameters = gravityParameters; } if ((bool)base.characterMotor) { base.characterMotor.walkSpeedPenaltyCoefficient = 1f; } if ((bool)lotus) { lotus.GetComponent().duration = 0.01f; } if (failed) { base.skillLocator.special.temporaryCooldownPenalty += failureCooldownPenalty; } bodyStateMachine.SetNextStateToMain(); base.OnExit(); } private void OnOverlayInstanceAdded(OverlayController controller, GameObject instance) { fillUiList.Add(instance.GetComponent()); overlayInstanceChildLocator = instance.GetComponent(); SetupInputUIIcons(); } private void OnOverlayInstanceRemoved(OverlayController controller, GameObject instance) { fillUiList.Remove(instance.GetComponent()); } public override InterruptPriority GetMinimumInterruptPriority() { return InterruptPriority.PrioritySkill; } }