################################################################################
#
# GameData::Species changes.
#
################################################################################
module GameData
class Species
#---------------------------------------------------------------------------
# Aliased so that moves can be set as learnable at Lvl -1.
# This is used for Move Reminder-exclusive moves.
#---------------------------------------------------------------------------
Species.singleton_class.alias_method :paldea_schema, :schema
def self.schema(compiling_forms = false)
ret = self.paldea_schema(compiling_forms)
ret["Moves"] = [:moves, "*ie", nil, :Move]
return ret
end
#---------------------------------------------------------------------------
# Aliased so that Incense is no longer required for hatching baby Pokemon.
#---------------------------------------------------------------------------
alias paldea_get_baby_species get_baby_species
def get_baby_species(*args)
if Settings::MECHANICS_GENERATION >= 9
return paldea_get_baby_species(false, nil, nil)
end
return paldea_get_baby_species(*args)
end
end
end
################################################################################
#
# Pokemon class additions.
#
################################################################################
class Pokemon
alias paldea_initialize initialize
def initialize(species, level, owner = $player, withMoves = true, recheck_form = true)
paldea_initialize(species, level, owner, withMoves, recheck_form)
@evo_move_count = {}
@evo_crest_count = {}
@evo_recoil_count = 0
@evo_step_count = 0
if @species == :BASCULEGION && recheck_form
f = MultipleForms.call("getFormOnCreation", self)
if f
self.form = f
reset_moves if withMoves
end
end
end
#-----------------------------------------------------------------------------
# Move count evolution utilities.
#-----------------------------------------------------------------------------
def init_evo_move_count(move)
@evo_move_count = Hash.new if !@evo_move_count
@evo_move_count[move] = 0 if !@evo_move_count[move]
end
def move_count_evolution(move, qty = 1)
species_data.get_evolutions.each do |evo|
if evo[1] == :LevelUseMoveCount && evo[2] == move
init_evo_move_count(move)
@evo_move_count[move] += qty
break
end
end
end
def evo_move_count(move)
init_evo_move_count(move)
return @evo_move_count[move]
end
def set_evo_move_count(move, value)
init_evo_move_count(move)
@evo_move_count[move] = value
end
#-----------------------------------------------------------------------------
# Leader's crest evolution utilities.
#-----------------------------------------------------------------------------
def init_evo_crest_count(item)
@evo_crest_count = Hash.new if !@evo_crest_count
@evo_crest_count[item] = 0 if !@evo_crest_count[item]
end
def leaders_crest_evolution(item, qty = 1)
species_data.get_evolutions.each do |evo|
if evo[1] == :LevelDefeatItsKindWithItem && evo[2] == item
init_evo_crest_count(item)
@evo_crest_count[item] += qty
break
end
end
end
def evo_crest_count(item)
init_evo_crest_count(item)
return @evo_crest_count[item]
end
def set_evo_crest_count(item, value)
init_evo_crest_count(item)
@evo_crest_count[item] = value
end
#-----------------------------------------------------------------------------
# Recoil damage evolution utilities.
#-----------------------------------------------------------------------------
def recoil_evolution(qty = 1)
species_data.get_evolutions.each do |evo|
if evo[1] == :LevelRecoilDamage
@evo_recoil_count = 0 if !@evo_recoil_count
@evo_recoil_count += qty
break
end
end
end
def evo_recoil_count
return @evo_recoil_count || 0
end
def evo_recoil_count=(value)
@evo_recoil_count = value
end
#-----------------------------------------------------------------------------
# Walking evolution utilities.
#-----------------------------------------------------------------------------
def walking_evolution(qty = 1)
species_data.get_evolutions.each do |evo|
if evo[1] == :LevelWalk
@evo_step_count = 0 if !@evo_step_count
@evo_step_count += qty
break
end
end
end
def evo_step_count
return @evo_step_count || 0
end
def evo_step_count=(value)
@evo_step_count = value
end
#-----------------------------------------------------------------------------
# Edited for Move Relearner-exclusive moves.
#-----------------------------------------------------------------------------
def reset_moves
this_level = self.level
moveset = self.getMoveList
knowable_moves = []
moveset.each { |m| knowable_moves.push(m[1]) if (0..this_level).include?(m[0]) }
knowable_moves = knowable_moves.reverse
knowable_moves |= []
knowable_moves = knowable_moves.reverse
@moves.clear
first_move_index = knowable_moves.length - MAX_MOVES
first_move_index = 0 if first_move_index < 0
(first_move_index...knowable_moves.length).each do |i|
@moves.push(Pokemon::Move.new(knowable_moves[i]))
end
end
end
################################################################################
#
# New evolution methods.
#
################################################################################
GameData::Evolution.register({
:id => :CollectItems,
:parameter => :Item,
:any_level_up => true, # Needs any level up
:level_up_proc => proc { |pkmn, parameter|
next $bag.quantity(parameter) >= 999
},
:after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species|
next false if evo_species != new_species || $bag.quantity(parameter) < 999
$bag.remove(parameter, 999)
next true
}
})
GameData::Evolution.register({
:id => :LevelWithPartner,
:parameter => Integer,
:level_up_proc => proc { |pkmn, parameter|
next pkmn.level >= parameter && $PokemonGlobal.partner
}
})
GameData::Evolution.register({
:id => :LevelUseMoveCount,
:parameter => :Move,
:any_level_up => true, # Needs any level up
:level_up_proc => proc { |pkmn, parameter|
next pkmn.evo_move_count(parameter) >= 20
},
:after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species|
next false if evo_species != new_species || pkmn.evo_move_count(parameter) < 20
pkmn.set_evo_move_count(parameter, 0)
next true
}
})
GameData::Evolution.register({
:id => :LevelDefeatItsKindWithItem,
:parameter => :Item,
:any_level_up => true, # Needs any level up
:level_up_proc => proc { |pkmn, parameter|
next pkmn.evo_crest_count(parameter) >= 3
},
:after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species|
next false if evo_species != new_species || pkmn.evo_crest_count(parameter) < 3
pkmn.set_evo_crest_count(parameter,0)
next true
}
})
GameData::Evolution.register({
:id => :LevelRecoilDamage,
:parameter => Integer,
:any_level_up => true, # Needs any level up
:level_up_proc => proc { |pkmn, parameter|
next pkmn.evo_recoil_count >= parameter
},
:after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species|
next false if evo_species != new_species || pkmn.evo_recoil_count < parameter
pkmn.evo_recoil_count = 0
next true
}
})
GameData::Evolution.register({
:id => :LevelWalk,
:parameter => Integer,
:any_level_up => true, # Needs any level up
:level_up_proc => proc { |pkmn, parameter|
next pkmn.evo_step_count >= parameter
},
:after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species|
next false if evo_species != new_species || pkmn.evo_step_count < parameter
pkmn.evo_step_count = 0
next true
}
})
################################################################################
#
# Step-based event handlers.
#
################################################################################
#-------------------------------------------------------------------------------
# Tracks steps taken to trigger walking evolutions for the lead Pokemon.
#-------------------------------------------------------------------------------
EventHandlers.add(:on_player_step_taken, :evolution_steps, proc {
$player.first_able_pokemon.walking_evolution if $player.party.length > 0 && $player.first_able_pokemon
})
#-------------------------------------------------------------------------------
# Initializes Mirror Herb step counter.
#-------------------------------------------------------------------------------
class PokemonGlobalMetadata
attr_accessor :mirrorherb_steps
alias paldea_initialize initialize
def initialize
@mirrorherb_steps = 0
paldea_initialize
end
end
#-------------------------------------------------------------------------------
# Tracks steps taken while Pokemon in the party are holding a Mirror Herb.
# Every 256 steps, inherits Egg moves from other party members if possible.
#-------------------------------------------------------------------------------
EventHandlers.add(:on_player_step_taken, :mirrorherb_step, proc {
if $player.able_party.any? { |p| p&.hasItem?(:MIRRORHERB) }
$PokemonGlobal.mirrorherb_steps = 0 if !$PokemonGlobal.mirrorherb_steps
$PokemonGlobal.mirrorherb_steps += 1
if $PokemonGlobal.mirrorherb_steps > 255
found_eggMove = false
$player.able_party.each_with_index do |pkmn, i|
next if pkmn.item != :MIRRORHERB
next if pkmn.numMoves == Pokemon::MAX_MOVES
baby_species = pkmn.species_data.get_baby_species
eggmoves = GameData::Species.get(baby_species).egg_moves.clone
eggmoves.shuffle.each do |move|
next if pkmn.hasMove?(move)
next if !$player.get_pokemon_with_move(move)
pkmn.learn_move(move)
found_eggMove = true
break
end
break if found_eggMove
end
$PokemonGlobal.mirrorherb_steps = 0
end
else
$PokemonGlobal.mirrorherb_steps = 0
end
})
################################################################################
#
# Edits to Egg generation for Tauros regional form inheritence.
#
################################################################################
class DayCare
module EggGenerator
module_function
def generate(mother, father)
if mother.male? || father.female? || mother.genderless?
mother, father = father, mother
end
mother_data = [mother, mother.species_data.egg_groups.include?(:Ditto)]
father_data = [father, father.species_data.egg_groups.include?(:Ditto)]
species_parent = (mother_data[1]) ? father : mother
baby_species = determine_egg_species(species_parent.species, mother, father)
mother_data.push(mother.species_data.breeding_can_produce?(baby_species))
father_data.push(father.species_data.breeding_can_produce?(baby_species))
egg = generate_basic_egg(baby_species, species_parent)
inherit_form(egg, species_parent, mother_data, father_data)
inherit_nature(egg, mother, father)
inherit_ability(egg, mother_data, father_data)
inherit_moves(egg, mother_data, father_data)
inherit_IVs(egg, mother, father)
inherit_poke_ball(egg, mother_data, father_data)
set_shininess(egg, mother, father)
set_pokerus(egg)
egg.calc_stats
return egg
end
def generate_basic_egg(species, species_parent)
egg = Pokemon.new(species, Settings::EGG_LEVEL)
egg.name = _INTL("Egg")
egg.steps_to_hatch = egg.species_data.hatch_steps
egg.obtain_text = _INTL("Day-Care Couple")
egg.happiness = 120
egg.form = 0 if species == :SINISTEA
new_form = MultipleForms.call("getFormOnEggCreation", egg, species_parent)
egg.form = new_form if new_form
return egg
end
end
end
################################################################################
#
# Form handlers.
#
################################################################################
#-------------------------------------------------------------------------------
# Regional forms upon creating an egg.
#-------------------------------------------------------------------------------
MultipleForms.register(:RATTATA, {
"getFormOnEggCreation" => proc { |pkmn, parent|
if $game_map
map_pos = $game_map.metadata&.town_map_position
if map_pos
form = 0
case map_pos[0]
#-----------------------------------------------------------------------
when 1 # Alola region
case pkmn.species
when :RATTATA, :SANDSHREW, :VULPIX, :DIGLETT, :MEOWTH, :GEODUDE, :GRIMER
form = 1
end
#-----------------------------------------------------------------------
when 2 # Galar region
case pkmn.species
when :PONYTA, :SLOWPOKE, :FARFETCHD, :ARTICUNO, :ZAPDOS, :MOLTRES, :CORSOLA, :ZIGZAGOON, :YAMASK, :STUNFISK
form = 1
when :MEOWTH, :DARUMAKA
form = 2
end
#-----------------------------------------------------------------------
when 3 # Hisui region
case pkmn.species
when :GROWLITHE, :VOLTORB, :QWILFISH, :SNEASEL, :ZORUA
form = 1
end
#-----------------------------------------------------------------------
when 4 # Paldea region
case pkmn.species
when :WOOPER
form = 1
when :TAUROS
form = (parent.form == 0) ? 1 : parent.form
end
end
next form if form > 0 && GameData::Species.get_species_form(pkmn.species, form).form == form
end
end
next 0
}
})
MultipleForms.copy(:RATTATA, :SANDSHREW, :VULPIX, :DIGLETT, :MEOWTH, :GEODUDE, :GRIMER, # Alolan
:PONYTA, :FARFETCHD, :CORSOLA, :ZIGZAGOON, :YAMASK, :STUNFISK, # Galarian
:SLOWPOKE, :ARTICUNO, :ZAPDOS, :MOLTRES, # Galarian (DLC)
:GROWLITHE, :VOLTORB, :QWILFISH, :SNEASEL, :ZORUA, # Hisuian
:TAUROS, :WOOPER # Paldean
)
#-------------------------------------------------------------------------------
# Species with regional evolutions (Hisuian forms).
#-------------------------------------------------------------------------------
MultipleForms.register(:QUILAVA, {
"getForm" => proc { |pkmn|
next if pkmn.form_simple >= 2
if $game_map
map_pos = $game_map.metadata&.town_map_position
next 1 if map_pos && map_pos[0] == 3 # Hisui region
end
next 0
}
})
MultipleForms.copy(:QUILAVA, :DEWOTT, :DARTRIX, :PETILIL, :RUFFLET, :GOOMY, :BERGMITE)
#-------------------------------------------------------------------------------
# Dundunsparce - Segment sizes.
#-------------------------------------------------------------------------------
MultipleForms.register(:DUNSPARCE, {
"getFormOnCreation" => proc { |pkmn|
next (pkmn.personalID % 100 == 0) ? 1 : 0
}
})
MultipleForms.copy(:DUNSPARCE, :DUDUNSPARCE)
#-------------------------------------------------------------------------------
# Dialga - Origin Forme.
#-------------------------------------------------------------------------------
MultipleForms.register(:DIALGA, {
"getForm" => proc { |pkmn|
next 1 if pkmn.hasItem?(:ADAMANTCRYSTAL)
next 0
}
})
#-------------------------------------------------------------------------------
# Palkia - Origin Forme.
#-------------------------------------------------------------------------------
MultipleForms.register(:PALKIA, {
"getForm" => proc { |pkmn|
next 1 if pkmn.hasItem?(:LUSTROUSGLOBE)
next 0
}
})
#-------------------------------------------------------------------------------
# Giratina - Origin Forme.
#-------------------------------------------------------------------------------
MultipleForms.register(:GIRATINA, {
"getForm" => proc { |pkmn|
next 1 if pkmn.hasItem?(:GRISEOUSCORE)
next 1 if Settings::MECHANICS_GENERATION < 9 && pkmn.hasItem?(:GRISEOUSORB)
if $game_map &&
GameData::MapMetadata.try_get($game_map.map_id)&.has_flag?("DistortionWorld")
next 1
end
next 0
}
})
#-------------------------------------------------------------------------------
# Shaymin - Sky Forme.
#-------------------------------------------------------------------------------
MultipleForms.register(:SHAYMIN, {
"getForm" => proc { |pkmn|
next 0 if pkmn.fainted? || [:FROZEN, :FROSTBITE].include?(pkmn.status) || PBDayNight.isNight?
}
})
#-------------------------------------------------------------------------------
# Hoopa - Unbound form.
#-------------------------------------------------------------------------------
MultipleForms.register(:HOOPA, {
"getForm" => proc { |pkmn|
if Settings::MECHANICS_GENERATION < 9 && (!pkmn.time_form_set ||
pbGetTimeNow.to_i > pkmn.time_form_set.to_i + (60 * 60 * 24 * 3)) # 3 days
next 0
end
},
"onSetForm" => proc { |pkmn, form, oldForm|
pkmn.time_form_set = (form > 0) ? pbGetTimeNow.to_i : nil if Settings::MECHANICS_GENERATION < 9
# Move Change
form_moves = [
:HYPERSPACEHOLE, # Confined form
:HYPERSPACEFURY, # Unbound form
]
# Find a known move that should be forgotten
old_move_index = -1
pkmn.moves.each_with_index do |move, i|
next if !form_moves.include?(move.id)
old_move_index = i
break
end
# Determine which new move to learn (if any)
new_move_id = form_moves[form]
new_move_id = nil if !GameData::Move.exists?(new_move_id)
new_move_id = nil if pkmn.hasMove?(new_move_id)
# Forget a known move (if relevant) and learn a new move (if relevant)
if old_move_index >= 0
old_move_name = pkmn.moves[old_move_index].name
if new_move_id.nil?
# Just forget the old move
pkmn.forget_move_at_index(old_move_index)
else
# Replace the old move with the new move (keeps the same index)
pkmn.moves[old_move_index].id = new_move_id
new_move_name = pkmn.moves[old_move_index].name
pbMessage("\\se[]" + _INTL("{1} learned {2}!", pkmn.name, new_move_name) + "\\se[Pkmn move learnt]")
end
end
}
})
#-------------------------------------------------------------------------------
# Basculin
#-------------------------------------------------------------------------------
MultipleForms.register(:BASCULIN, {
"getForm" => proc { |pkmn|
if pkmn.form_simple >= 2
next (pkmn.female?) ? 3 : 2
end
next pkmn.form_simple
}
})
#-------------------------------------------------------------------------------
# Basculegion - Gender forms.
#-------------------------------------------------------------------------------
MultipleForms.register(:BASCULEGION, {
"getForm" => proc { |pkmn|
next (pkmn.female?) ? 3 : 2
},
"getFormOnCreation" => proc { |pkmn|
next (pkmn.female?) ? 3 : 2
}
})
#-------------------------------------------------------------------------------
# Oinkologne - Gender forms.
#-------------------------------------------------------------------------------
MultipleForms.register(:LECHONK, {
"getForm" => proc { |pkmn|
next pkmn.gender
},
"getFormOnCreation" => proc { |pkmn|
next pkmn.gender
}
})
MultipleForms.copy(:LECHONK, :OINKOLOGNE)
#-------------------------------------------------------------------------------
# Maushold - Family sizes.
#-------------------------------------------------------------------------------
MultipleForms.register(:TANDEMAUS, {
"getFormOnCreation" => proc { |pkmn|
next (pkmn.personalID % 100 == 0) ? 1 : 0
}
})
MultipleForms.copy(:TANDEMAUS, :MAUSHOLD)
#-------------------------------------------------------------------------------
# Squawkabilly - Plumage colors.
#-------------------------------------------------------------------------------
MultipleForms.register(:SQUAWKABILLY, {
"getFormOnCreation" => proc { |pkmn|
next rand(4)
}
})
#-------------------------------------------------------------------------------
# Palafin - Zero Form.
#-------------------------------------------------------------------------------
MultipleForms.register(:PALAFIN, {
"getFormOnLeavingBattle" => proc { |pkmn, battle, usedInBattle, endBattle|
next 0 if endBattle
}
})
#-------------------------------------------------------------------------------
# Tatsugiri - Multiple Forms.
#-------------------------------------------------------------------------------
MultipleForms.register(:TATSUGIRI, {
"getFormOnCreation" => proc { |pkmn|
next rand(3)
}
})
#-------------------------------------------------------------------------------
# Poltchageist/Sinistcha - Unremarkable/Masterpiece forms.
#-------------------------------------------------------------------------------
MultipleForms.copy(:SINISTEA, :POLTEAGEIST, :POLTCHAGEIST, :SINISTCHA)
#-------------------------------------------------------------------------------
# Ogerpon - Masked forms.
#-------------------------------------------------------------------------------
MultipleForms.register(:OGERPON, {
"getForm" => proc { |pkmn|
next 1 if pkmn.hasItem?(:WELLSPRINGMASK)
next 2 if pkmn.hasItem?(:HEARTHFLAMEMASK)
next 3 if pkmn.hasItem?(:CORNERSTONEMASK)
next 0
},
"getFormOnStartingBattle" => proc { |pkmn, wild|
next 5 if pkmn.hasItem?(:WELLSPRINGMASK)
next 6 if pkmn.hasItem?(:HEARTHFLAMEMASK)
next 7 if pkmn.hasItem?(:CORNERSTONEMASK)
next 4
},
"getFormOnLeavingBattle" => proc { |pkmn, battle, usedInBattle, endBattle|
next pkmn.form - 4 if pkmn.form > 3 && endBattle
},
"getTerastalForm" => proc { |pkmn|
next pkmn.form + 4
},
"getUnTerastalForm" => proc { |pkmn|
next pkmn.form - 4
},
# Compability for Pokedex Data Page plugin
"getDataPageInfo" => proc { |pkmn|
next if pkmn.form < 8
mask = nil
case pkmn.form
when 9 then mask = :WELLSPRINGMASK
when 10 then mask = :HEARTHFLAMEMASK
when 11 then mask = :CORNERSTONEMASK
end
next [pkmn.form, pkmn.form - 4, mask]
}
})
#-------------------------------------------------------------------------------
# Terapagos - Terastal and Stellar form.
#-------------------------------------------------------------------------------
MultipleForms.register(:TERAPAGOS, {
"getFormOnLeavingBattle" => proc { |pkmn, battle, usedInBattle, endBattle|
next 0 if pkmn.form > 0 && endBattle
},
"getTerastalForm" => proc { |pkmn|
next 2
},
"getUnTerastalForm" => proc { |pkmn|
next 1
},
"getDataPageInfo" => proc { |pkmn|
next if pkmn.form < 2
next [pkmn.form, 1]
}
})
#-------------------------------------------------------------------------------
# Zygarde - Mega Zygarde form.
#-------------------------------------------------------------------------------
MultipleForms.register(:ZYGARDE, {
"changePokemonOnMegaEvolve" => proc { |battler, battle|
if GameData::Move.exists?(:NIHILLIGHT)
if [4, 5].include?(battler.form)
battler.eachMoveWithIndex do |m, i|
next if m.id != :COREENFORCER
pokemon_move = battler.pokemon.moves[i]
pokemon_move.id = :NIHILLIGHT
battler_move = Battle::Move.from_pokemon_move(battle, pokemon_move)
battler.moves[i] = battler_move
if battle.choices[battler.index][1] == i
battle.choices[battler.index][2] = battler_move
battle.pbDisplay(_INTL("{1}'s {2} transform into {3}!", battler.pbThis,
GameData::Move.get(:COREENFORCER).name,
GameData::Move.get(:NIHILLIGHT).name
))
break
end
end
end
end
},
"getMegaMoves" => proc { |pkmn|
next { :COREENFORCER => :NIHILLIGHT }
},
"changePokemonOnLeavingBattle" => proc { |pkmn, battle, usedInBattle, endBattle|
if GameData::Move.exists?(:COREENFORCER) && endBattle
pkmn.moves.each { |move| move.id = :COREENFORCER if move.id == :NIHILLIGHT }
end
},
"getFormOnLeavingBattle" => proc { |pkmn, battle, usedInBattle, endBattle|
pkmn.makeUnmega if pkmn.mega? && endBattle
next pkmn.form - 2 if [2, 3].include?(pkmn.form) && (pkmn.fainted? || endBattle)
}
})