From 29087710b7e180efe31594c5d178ec9770a3c2ad Mon Sep 17 00:00:00 2001
From: "Amani H." <109637146+xsn34kzx@users.noreply.github.com>
Date: Fri, 10 Jan 2025 19:34:16 -0500
Subject: [PATCH] [Balance] Adjust Orb & Light Ball Weight Functions (#5070)

* [Balance] Adjust Orb & Light Ball Weight Functions

* Apply Kev's Suggestions

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: damocleas <damocleas25@gmail.com>
---
 src/modifier/modifier-type.ts | 74 +++++++++++++++++++++--------------
 1 file changed, 44 insertions(+), 30 deletions(-)

diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts
index e1c8cb04405..b6cf78fb414 100644
--- a/src/modifier/modifier-type.ts
+++ b/src/modifier/modifier-type.ts
@@ -1040,7 +1040,8 @@ class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
       for (const p of party) {
         const speciesId = p.getSpeciesForm(true).speciesId;
         const fusionSpeciesId = p.isFusion() ? p.getFusionSpeciesForm(true).speciesId : null;
-        const hasFling = p.getMoveset(true).some(m => m?.moveId === Moves.FLING);
+        // TODO: Use commented boolean when Fling is implemented
+        const hasFling = false; /* p.getMoveset(true).some(m => m?.moveId === Moves.FLING) */
 
         for (const i in values) {
           const checkedSpecies = values[i].species;
@@ -1755,56 +1756,69 @@ const modifierPool: ModifierPool = {
     }, 12),
     new WeightedModifierType(modifierTypes.TOXIC_ORB, (party: Pokemon[]) => {
       return party.some(p => {
-        const moveset = p.getMoveset(true).filter(m => !isNullOrUndefined(m)).map(m => m.moveId);
-
-        const canSetStatus = p.canSetStatus(StatusEffect.TOXIC, true, true, null, true);
         const isHoldingOrb = p.getHeldItems().some(i => i.type.id === "FLAME_ORB" || i.type.id === "TOXIC_ORB");
 
-        // Moves that take advantage of obtaining the actual status effect
-        const hasStatusMoves = [ Moves.FACADE, Moves.PSYCHO_SHIFT ]
-          .some(m => moveset.includes(m));
-        // Moves that take advantage of being able to give the target a status orb
-        // TODO: Take moves from comment they are implemented
-        const hasItemMoves = [ /* Moves.TRICK, Moves.FLING, Moves.SWITCHEROO */ ]
-          .some(m => moveset.includes(m));
-        // Abilities that take advantage of obtaining the actual status effect
-        const hasRelevantAbilities = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.TOXIC_BOOST, Abilities.POISON_HEAL, Abilities.MAGIC_GUARD ]
-          .some(a => p.hasAbility(a, false, true));
-
         if (!isHoldingOrb) {
+          const moveset = p.getMoveset(true).filter(m => !isNullOrUndefined(m)).map(m => m.moveId);
+          const canSetStatus = p.canSetStatus(StatusEffect.TOXIC, true, true, null, true);
+
+          // Moves that take advantage of obtaining the actual status effect
+          const hasStatusMoves = [ Moves.FACADE, Moves.PSYCHO_SHIFT ]
+            .some(m => moveset.includes(m));
+          // Moves that take advantage of being able to give the target a status orb
+          // TODO: Take moves (Trick, Fling, Switcheroo) from comment when they are implemented
+          const hasItemMoves = [ /* Moves.TRICK, Moves.FLING, Moves.SWITCHEROO */ ]
+            .some(m => moveset.includes(m));
+
           if (canSetStatus) {
-            return hasRelevantAbilities || hasStatusMoves;
+            // Abilities that take advantage of obtaining the actual status effect, separated based on specificity to the orb
+            const hasGeneralAbility = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.MAGIC_GUARD ]
+              .some(a => p.hasAbility(a, false, true));
+            const hasSpecificAbility = [ Abilities.TOXIC_BOOST, Abilities.POISON_HEAL ]
+              .some(a => p.hasAbility(a, false, true));
+            const hasOppositeAbility = [ Abilities.FLARE_BOOST ]
+              .some(a => p.hasAbility(a, false, true));
+
+            return hasSpecificAbility || (hasGeneralAbility && !hasOppositeAbility) || hasStatusMoves;
           } else {
             return hasItemMoves;
           }
         }
+
         return false;
       }) ? 10 : 0;
     }, 10),
     new WeightedModifierType(modifierTypes.FLAME_ORB, (party: Pokemon[]) => {
       return party.some(p => {
-        const moveset = p.getMoveset(true).filter(m => !isNullOrUndefined(m)).map(m => m.moveId);
-        const canSetStatus = p.canSetStatus(StatusEffect.BURN, true, true, null, true);
         const isHoldingOrb = p.getHeldItems().some(i => i.type.id === "FLAME_ORB" || i.type.id === "TOXIC_ORB");
 
-        // Moves that take advantage of obtaining the actual status effect
-        const hasStatusMoves = [ Moves.FACADE, Moves.PSYCHO_SHIFT ]
-          .some(m => moveset.includes(m));
-        // Moves that take advantage of being able to give the target a status orb
-        // TODO: Take moves from comment they are implemented
-        const hasItemMoves = [ /* Moves.TRICK, Moves.FLING, Moves.SWITCHEROO */ ]
-          .some(m => moveset.includes(m));
-        // Abilities that take advantage of obtaining the actual status effect
-        const hasRelevantAbilities = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.FLARE_BOOST, Abilities.MAGIC_GUARD ]
-          .some(a => p.hasAbility(a, false, true));
-
         if (!isHoldingOrb) {
+          const moveset = p.getMoveset(true).filter(m => !isNullOrUndefined(m)).map(m => m.moveId);
+          const canSetStatus = p.canSetStatus(StatusEffect.TOXIC, true, true, null, true);
+
+          // Moves that take advantage of obtaining the actual status effect
+          const hasStatusMoves = [ Moves.FACADE, Moves.PSYCHO_SHIFT ]
+            .some(m => moveset.includes(m));
+          // Moves that take advantage of being able to give the target a status orb
+          // TODO: Take moves (Trick, Fling, Switcheroo) from comment when they are implemented
+          const hasItemMoves = [ /* Moves.TRICK, Moves.FLING, Moves.SWITCHEROO */ ]
+            .some(m => moveset.includes(m));
+
           if (canSetStatus) {
-            return hasRelevantAbilities || hasStatusMoves;
+            // Abilities that take advantage of obtaining the actual status effect, separated based on specificity to the orb
+            const hasGeneralAbility = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.MAGIC_GUARD ]
+              .some(a => p.hasAbility(a, false, true));
+            const hasSpecificAbility = [ Abilities.FLARE_BOOST ]
+              .some(a => p.hasAbility(a, false, true));
+            const hasOppositeAbility = [ Abilities.TOXIC_BOOST, Abilities.POISON_HEAL ]
+              .some(a => p.hasAbility(a, false, true));
+
+            return hasSpecificAbility || (hasGeneralAbility && !hasOppositeAbility) || hasStatusMoves;
           } else {
             return hasItemMoves;
           }
         }
+
         return false;
       }) ? 10 : 0;
     }, 10),