From f7ca13d96e948a1e480f7ea1eebec17dd321154d Mon Sep 17 00:00:00 2001
From: Flashfyre <flashfireex@gmail.com>
Date: Tue, 6 Jun 2023 10:14:53 -0400
Subject: [PATCH] Fix crashing issues

---
 src/battle-phases.ts          | 15 +++++++++------
 src/battle-scene.ts           |  4 ++--
 src/modifier/modifier-type.ts |  1 +
 src/modifier/modifier.ts      |  3 ++-
 src/pokemon.ts                |  6 +++++-
 5 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/battle-phases.ts b/src/battle-phases.ts
index de480b5eafb..13cb3da59d8 100644
--- a/src/battle-phases.ts
+++ b/src/battle-phases.ts
@@ -222,7 +222,7 @@ export class EncounterPhase extends BattlePhase {
         this.scene.field.add(enemyPokemon);
         const playerPokemon = this.scene.getPlayerPokemon();
         if (playerPokemon.visible)
-          this.scene.field.moveBelow(enemyPokemon, playerPokemon);
+          this.scene.field.moveBelow(enemyPokemon as Pokemon, playerPokemon);
         enemyPokemon.tint(0, 0.5);
         if (battle.enemyField.length > 1)
           enemyPokemon.setFieldPosition(e ? FieldPosition.RIGHT : FieldPosition.LEFT);
@@ -2128,18 +2128,20 @@ export class PokemonHealPhase extends CommonAnimPhase {
   private message: string;
   private showFullHpMessage: boolean;
   private skipAnim: boolean;
+  private revive: boolean;
 
-  constructor(scene: BattleScene, battlerIndex: BattlerIndex, hpHealed: integer, message: string, showFullHpMessage: boolean, skipAnim?: boolean) {
+  constructor(scene: BattleScene, battlerIndex: BattlerIndex, hpHealed: integer, message: string, showFullHpMessage: boolean, skipAnim?: boolean, revive?: boolean) {
     super(scene, battlerIndex, undefined, CommonAnim.HEALTH_UP);
 
     this.hpHealed = hpHealed;
     this.message = message;
     this.showFullHpMessage = showFullHpMessage;
     this.skipAnim = !!skipAnim;
+    this.revive = !!revive;
   }
 
   start() {
-    if (!this.skipAnim && this.getPokemon().hp && this.getPokemon().getHpRatio() < 1)
+    if (!this.skipAnim && (this.revive || this.getPokemon().hp) && this.getPokemon().getHpRatio() < 1)
       super.start();
     else
       this.end();
@@ -2148,7 +2150,7 @@ export class PokemonHealPhase extends CommonAnimPhase {
   end() {
     const pokemon = this.getPokemon();
     
-    if (!this.getPokemon().isActive(true)) {
+    if (!pokemon.isOnField() || (!this.revive && !pokemon.isActive())) {
       super.end();
       return;
     }
@@ -2157,7 +2159,8 @@ export class PokemonHealPhase extends CommonAnimPhase {
 
     if (!fullHp) {
       const hpRestoreMultiplier = new Utils.IntegerHolder(1);
-      this.scene.applyModifiers(HealingBoosterModifier, this.player, hpRestoreMultiplier);
+      if (!this.revive)
+        this.scene.applyModifiers(HealingBoosterModifier, this.player, hpRestoreMultiplier);
       pokemon.hp = Math.min(pokemon.hp + this.hpHealed * hpRestoreMultiplier.value, pokemon.getMaxHp());
       pokemon.updateInfo().then(() => super.end());
     } else if (this.showFullHpMessage)
@@ -2212,7 +2215,7 @@ export class AttemptCapturePhase extends PokemonPhase {
 
     this.scene.sound.play('pb_throw');
     this.scene.time.delayedCall(300, () => {
-      this.scene.field.moveBelow(this.pokeball, pokemon);
+      this.scene.field.moveBelow(this.pokeball as Phaser.GameObjects.GameObject, pokemon);
     });
     this.scene.tweens.add({
       targets: this.pokeball,
diff --git a/src/battle-scene.ts b/src/battle-scene.ts
index 133360859f4..816b6936b95 100644
--- a/src/battle-scene.ts
+++ b/src/battle-scene.ts
@@ -668,13 +668,13 @@ export default class BattleScene extends Phaser.Scene {
 	}
 
 	playBgm(bgmName?: string, loopPoint?: number): void {
-		if (!bgmName && this.bgm) {
+		if (!bgmName && this.bgm && !this.bgm.pendingRemove) {
 			this.bgm.play({
 				volume: 1
 			});
 			return;
 		}
-		if (this.bgm && this.bgm.isPlaying)
+		if (this.bgm && !this.bgm.pendingRemove && this.bgm.isPlaying)
 			this.bgm.stop();
 		this.bgm = this.sound.add(bgmName, { loop: true });
 		this.bgm.play();
diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts
index ce70ace897d..0e065147c4c 100644
--- a/src/modifier/modifier-type.ts
+++ b/src/modifier/modifier-type.ts
@@ -760,6 +760,7 @@ const enemyModifierPool = {
     new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 1)
   ].map(m => { m.setTier(ModifierTier.GREAT); return m; }),
   [ModifierTier.ULTRA]: [
+    new WeightedModifierType(modifierTypes.REVIVER_SEED, 2),
     new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
     new WeightedModifierType(modifierTypes.FOCUS_BAND, 2),
     new WeightedModifierType(modifierTypes.LUCKY_EGG, 4),
diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts
index 27f77f3c742..980a401b305 100644
--- a/src/modifier/modifier.ts
+++ b/src/modifier/modifier.ts
@@ -682,7 +682,8 @@ export class PokemonInstantReviveModifier extends PokemonHeldItemModifier {
   apply(args: any[]): boolean {
     const pokemon = args[0] as Pokemon;
 
-    pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), Math.max(Math.floor(pokemon.getMaxHp() / 2)), getPokemonMessage(pokemon, ` was revived\nby its ${this.type.name}!`), false));
+    pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(),
+      Math.max(Math.floor(pokemon.getMaxHp() / 2), 1),getPokemonMessage(pokemon, ` was revived\nby its ${this.type.name}!`), false, false, true));
 
     return true;
   }
diff --git a/src/pokemon.ts b/src/pokemon.ts
index cace690733d..c42d6f2fafa 100644
--- a/src/pokemon.ts
+++ b/src/pokemon.ts
@@ -188,12 +188,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
     }
   }
 
+  isOnField(): boolean {
+    return this.scene.field.getIndex(this) > -1;
+  }
+
   isFainted(checkStatus?: boolean): boolean {
     return !this.hp && (!checkStatus || this.status?.effect === StatusEffect.FAINT);
   }
 
   isActive(onField?: boolean): boolean {
-    return !this.isFainted() && !!this.scene && (!onField || this.scene.field.getIndex(this) > -1);
+    return !this.isFainted() && !!this.scene && (!onField || this.isOnField());
   }
 
   abstract isPlayer(): boolean;