### Critical Fixes
- Side/Field-Targeting Moves Scoring 0
Stealth Rock, Spikes, Reflect, Light Screen, Tailwind and all other moves with
num_targets == 0 were never scored because vanilla Essentials calls
pbGetMoveScore() without a target argument. The scorer's guard clause
(return 0 unless move && user && target) rejected them all.
- Core.rb: Added fallback target resolution — picks the first non-fainted
opponent when target is nil.
- 0_Move_Scorer.rb: Relaxed guard to return 0 unless move && user with
internal target resolution for nil targets.
- GrassyTerrain PBEffects Crash
PBEffects::GrassyTerrain does not exist; Grassy Terrain is a field terrain,
not a battle-side effect. Protect/Detect scoring crashed when evaluating
passive recovery.
- 0_Move_Scorer.rb line ~1680: Changed to
@battle.field.terrain == :Grassy && user.battler.affectedByTerrain?.
- Kernel#pp RGSS Safety
RGSS/mkxp lacks the pp standard library. Any call to pp (including AI
debug logging) caused a fatal NoMethodError.
- Core.rb: Defines Kernel#pp as a safe echoln-based fallback when the
native implementation is unavailable.
- SystemStackError Recursion Guard
Effectiveness.calculate and GameData::Type.calculate could infinitely
recurse in certain type-matchup edge cases.
- Hotfixes.rb: Added recursion depth guard (max 10) on both methods.