diff --git a/HKMP/Animation/Effects/HazardDeath.cs b/HKMP/Animation/Effects/HazardDeath.cs index 1040ba16..6fb90e61 100644 --- a/HKMP/Animation/Effects/HazardDeath.cs +++ b/HKMP/Animation/Effects/HazardDeath.cs @@ -54,24 +54,36 @@ public override void Play(GameObject playerObject, bool[] effectInfo) { // Destroy it after some time Object.Destroy(spikeDeath, FadeOutDuration); } else if (hazardWasAcid) { - // Spawn the acid death object relative to the player object var acidDeathPrefab = HeroController.instance.acidDeathPrefab; - var acidDeath = acidDeathPrefab.Spawn(playerObject.transform.position); - - var acidDeathFsm = acidDeath.LocateMyFSM("Knight Acid Death"); - - // Get the audio play action and change the spawn point of the audio to be the player object - var damagePlayAction = acidDeathFsm.GetAction("Effects", 2); - damagePlayAction.spawnPoint.Value = playerObject; - // There is another one that plays the splash sound, also change the spawn point - var splashPlayAction = acidDeathFsm.GetAction("Effects", 3); - // Also change the audio player, otherwise the sound will play at the local player - splashPlayAction.audioPlayer = damagePlayAction.audioPlayer; - splashPlayAction.spawnPoint.Value = playerObject; - - // Remove the screen shake effect - acidDeathFsm.GetAction("Effects", 5).sendEvent.Value = ""; + // Spawn the acid death object relative to the player object + var acidDeath = Object.Instantiate( + acidDeathPrefab, + playerObject.transform.position, + Quaternion.identity + ); + var fsm = acidDeath.GetComponent(); + + // Obtain the audio actions for the hero damage and acid splash sounds + var heroDmgAudioAction = fsm.GetAction("Effects", 2); + var heroDmgClip = heroDmgAudioAction.audioClips[0]; + var acidSplashAudioAction = fsm.GetAction("Effects", 3); + var acidSplashClip = acidSplashAudioAction.audioClips[0]; + + // Get an audio source to play the sounds at the location of the remote player + var audioObj = AudioUtil.GetAudioSourceObject(playerObject); + var audioSource = audioObj.GetComponent(); + audioSource.PlayOneShot(heroDmgClip); + audioSource.PlayOneShot(acidSplashClip); + + Object.Destroy(audioObj, acidSplashClip.length); + + // Remove the actions with indices 1 through 5 + // Each removal shuffles the actions down an index so we call the remove method with 1 each time + for (var i = 0; i < 5; i++) { + fsm.RemoveAction("Effects", 1); + } + // Start a coroutine to fade out the spike death object MonoBehaviourUtil.Instance.StartCoroutine(FadeObjectOut( acidDeath.GetComponent(), @@ -104,7 +116,11 @@ private IEnumerator FadeObjectOut(Renderer renderer, float duration) { for (var t = 0f; t < duration; t += Time.deltaTime) { var normalizedTime = t / duration; var alpha = 1f - normalizedTime; - + + if (renderer == null || renderer.material == null) { + yield break; + } + var material = renderer.material; var color = material.color; material.color = new Color(color.r, color.g, color.b, alpha); diff --git a/HKMP/Fsm/FsmPatcher.cs b/HKMP/Fsm/FsmPatcher.cs index a74be040..fc6f819b 100644 --- a/HKMP/Fsm/FsmPatcher.cs +++ b/HKMP/Fsm/FsmPatcher.cs @@ -36,50 +36,5 @@ private void OnFsmEnable(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self) triggerAction.collideTag.Value = "Player"; triggerAction.collideTag.UseVariable = false; } - - // Insert an action that specifically re-scales the fireball to be in line with the player's scale - // For some reason players dying in acid might mess up the future scale of fireballs - // This is the case for the "top" and "spiral" objects of the fireball - - // TODO: figure out the root cause of the issue that this band-aid solution fixes. It has something to do - // with the HazardDeath animation effect playing that messes up future fireballs in the same scene. - // Although the issue already exists as soon as I try to find the FSM for the acid death object. - // Something with FSM initialization gets messed up at that point, but I'm confused why this doesn't happen - // with spike deaths or anywhere else for that matter. - if ((self.name.Contains("Fireball Top") || self.name.Contains("Fireball2 Top")) && self.Fsm.Name.Equals("Fireball Cast")) { - self.InsertMethod("L or R", 3, () => { - var hero = HeroController.instance.gameObject; - if (hero == null) { - return; - } - - var heroScaleX = hero.transform.localScale.x; - - var scaleFsmVar = self.Fsm.GetFsmFloat("Hero Scale"); - if (scaleFsmVar == null) { - return; - } - - scaleFsmVar.Value = heroScaleX; - }); - } - - if (self.name.Contains("Fireball2 Spiral") && self.Fsm.Name.Equals("Fireball Control")) { - self.InsertMethod("Init", 3, () => { - var hero = HeroController.instance.gameObject; - if (hero == null) { - return; - } - - var heroScaleX = hero.transform.localScale.x; - - var scaleFsmVar = self.Fsm.GetFsmFloat("X Scale"); - if (scaleFsmVar == null) { - return; - } - - scaleFsmVar.Value = heroScaleX; - }); - } } } diff --git a/HKMP/Util/FsmUtilExt.cs b/HKMP/Util/FsmUtilExt.cs index d678a99b..d0ea16b6 100644 --- a/HKMP/Util/FsmUtilExt.cs +++ b/HKMP/Util/FsmUtilExt.cs @@ -97,6 +97,28 @@ public static void InsertAction(PlayMakerFSM fsm, string stateName, FsmStateActi public static void InsertMethod(this PlayMakerFSM fsm, string stateName, int index, Action method) { InsertAction(fsm, stateName, new InvokeMethod(method), index); } + + /// + /// Removes an action from a specific state in a FSM. + /// + /// The FSM. + /// The name of the state with the action to remove. + /// The index of the action within the state. + public static void RemoveAction(this PlayMakerFSM fsm, string stateName, int index) { + var state = fsm.GetState(stateName); + + var origActions = state.Actions; + var actions = new FsmStateAction[origActions.Length - 1]; + for (var i = 0; i < index; i++) { + actions[i] = origActions[i]; + } + + for (var i = index; i < actions.Length; i++) { + actions[i] = origActions[i + 1]; + } + + state.Actions = actions; + } } ///