Rearranged some script files

This commit is contained in:
Maruno17
2020-09-05 22:34:32 +01:00
parent 5d3189174c
commit 5073f86190
188 changed files with 250 additions and 239 deletions

View File

@@ -0,0 +1,937 @@
# This class stores data on each Pokémon. Refer to $Trainer.party for an array
# of each Pokémon in the Trainer's current party.
class PokeBattle_Pokemon
attr_accessor :name # Nickname
attr_reader :species # Species (National Pokedex number)
attr_reader :exp # Current experience points
attr_reader :hp # Current HP
attr_reader :totalhp # Current Total HP
attr_reader :attack # Current Attack stat
attr_reader :defense # Current Defense stat
attr_reader :speed # Current Speed stat
attr_reader :spatk # Current Special Attack stat
attr_reader :spdef # Current Special Defense stat
attr_accessor :status # Status problem (PBStatuses)
attr_accessor :statusCount # Sleep count/Toxic flag
attr_accessor :abilityflag # Forces the first/second/hidden (0/1/2) ability
attr_accessor :genderflag # Forces male (0) or female (1)
attr_accessor :natureflag # Forces a particular nature
attr_accessor :natureOverride # Overrides nature's stat-changing effects
attr_accessor :shinyflag # Forces the shininess (true/false)
attr_accessor :moves # Moves (PBMove)
attr_accessor :firstmoves # The moves known when this Pokémon was obtained
attr_accessor :item # Held item
attr_accessor :mail # Mail
attr_accessor :fused # The Pokémon fused into this one
attr_accessor :iv # Array of 6 Individual Values for HP, Atk, Def,
# Speed, Sp Atk, and Sp Def
attr_accessor :ivMaxed # Array of booleans that max each IV value
attr_accessor :ev # Effort Values
attr_accessor :happiness # Current happiness
attr_accessor :ballused # Ball used
attr_accessor :eggsteps # Steps to hatch egg, 0 if Pokémon is not an egg
attr_accessor :markings # Markings
attr_accessor :ribbons # Array of ribbons
attr_accessor :pokerus # Pokérus strain and infection time
attr_accessor :personalID # Personal ID
attr_accessor :trainerID # 32-bit Trainer ID (the secret ID is in the upper
# 16 bits)
attr_accessor :obtainMode # Manner obtained:
# 0 - met, 1 - as egg, 2 - traded,
# 4 - fateful encounter
attr_accessor :obtainMap # Map where obtained
attr_accessor :obtainText # Replaces the obtain map's name if not nil
attr_accessor :obtainLevel # Level obtained
attr_accessor :hatchedMap # Map where an egg was hatched
attr_accessor :language # Language
attr_accessor :ot # Original Trainer's name
attr_accessor :otgender # Original Trainer's gender:
# 0 - male, 1 - female, 2 - mixed, 3 - unknown
# For information only, not used to verify
# ownership of the Pokémon
attr_accessor :cool,:beauty,:cute,:smart,:tough,:sheen # Contest stats
IV_STAT_LIMIT = 31 # Max total IVs
EV_LIMIT = 510 # Max total EVs
EV_STAT_LIMIT = 252 # Max EVs that a single stat can have
MAX_POKEMON_NAME_SIZE = 10 # Maximum length a Pokémon's nickname can be
#=============================================================================
# Ownership, obtained information
#=============================================================================
# Returns the public portion of the original trainer's ID.
def publicID
return @trainerID&0xFFFF
end
# Returns whether the specified Trainer is NOT this Pokémon's original trainer.
def foreign?(trainer)
return @trainerID!=trainer.id || @ot!=trainer.name
end
alias isForeign? foreign?
# Returns the gender of this Pokémon's original trainer (2=unknown).
def otgender
return @otgender || 2
end
# Returns this Pokémon's level when this Pokémon was obtained.
def obtainLevel
return @obtainLevel || 0
end
# Returns the time when this Pokémon was obtained.
def timeReceived
return @timeReceived ? Time.at(@timeReceived) : Time.gm(2000)
end
# Sets the time when this Pokémon was obtained (in seconds since Unix epoch).
def timeReceived=(value)
@timeReceived = value.to_i
end
# Returns the time when this Pokémon hatched.
def timeEggHatched
if obtainMode==1
return @timeEggHatched ? Time.at(@timeEggHatched) : Time.gm(2000)
else
return Time.gm(2000)
end
end
# Sets the time when this Pokémon hatched (in seconds since Unix epoch).
def timeEggHatched=(value)
@timeEggHatched = value.to_i
end
#=============================================================================
# Level
#=============================================================================
# Returns this Pokémon's level.
def level
@level = PBExperience.pbGetLevelFromExperience(@exp,self.growthrate) if !@level
return @level
end
# Sets this Pokémon's level.
def level=(value)
if value<1 || value>PBExperience.maxLevel
raise ArgumentError.new(_INTL("The level number ({1}) is invalid.",value))
end
@level = value
self.exp = PBExperience.pbGetStartExperience(value,self.growthrate)
end
# Sets this Pokémon's Exp. Points.
def exp=(value)
@exp = value
@level = nil
end
# Returns whether this Pokémon is an egg.
def egg?
return @eggsteps>0
end
alias isEgg? egg?
# Returns this Pokémon's growth rate.
def growthrate
return pbGetSpeciesData(@species,formSimple,SpeciesGrowthRate)
end
# Returns this Pokémon's base Experience value.
def baseExp
return pbGetSpeciesData(@species,formSimple,SpeciesBaseExp)
end
# Returns a number between 0 and 1 indicating how much of the current level's
# Exp this Pokémon has.
def expFraction
l = self.level
return 0.0 if l>=PBExperience.maxLevel
gr = self.growthrate
startexp = PBExperience.pbGetStartExperience(l,gr)
endexp = PBExperience.pbGetStartExperience(l+1,gr)
return 1.0*(@exp-startexp)/(endexp-startexp)
end
#=============================================================================
# Gender
#=============================================================================
# Returns this Pokémon's gender. 0=male, 1=female, 2=genderless
def gender
# Return sole gender option for all male/all female/genderless species
genderRate = pbGetSpeciesData(@species,formSimple,SpeciesGenderRate)
case genderRate
when PBGenderRates::AlwaysMale; return 0
when PBGenderRates::AlwaysFemale; return 1
when PBGenderRates::Genderless; return 2
end
# Return gender for species that can be male or female
return @genderflag if @genderflag && (@genderflag==0 || @genderflag==1)
return ((@personalID&0xFF)<PBGenderRates.genderByte(genderRate)) ? 1 : 0
end
# Returns whether this Pokémon species is restricted to only ever being one
# gender (or genderless).
def singleGendered?
genderRate = pbGetSpeciesData(@species,formSimple,SpeciesGenderRate)
return genderRate==PBGenderRates::AlwaysMale ||
genderRate==PBGenderRates::AlwaysFemale ||
genderRate==PBGenderRates::Genderless
end
alias isSingleGendered? singleGendered?
# Returns whether this Pokémon is male.
def male?
return self.gender==0
end
alias isMale? male?
# Returns whether this Pokémon is female.
def female?
return self.gender==1
end
alias isFemale? female?
# Returns whether this Pokémon is genderless.
def genderless?
return self.gender==2
end
alias isGenderless? genderless?
# Sets this Pokémon's gender to a particular gender (if possible).
def setGender(value)
@genderflag = value if !singleGendered?
end
def makeMale; setGender(0); end
def makeFemale; setGender(1); end
#=============================================================================
# Ability
#=============================================================================
# Returns the index of this Pokémon's ability.
def abilityIndex
return @abilityflag || (@personalID&1)
end
# Returns the ID of this Pokémon's ability.
def ability
abilIndex = abilityIndex
# Hidden ability
if abilIndex>=2
hiddenAbil = pbGetSpeciesData(@species,formSimple,SpeciesHiddenAbility)
if hiddenAbil.is_a?(Array)
ret = hiddenAbil[abilIndex-2]
return ret if ret && ret>0
else
return hiddenAbil if abilIndex==2 && hiddenAbil>0
end
abilIndex = (@personalID&1)
end
# Natural ability
abilities = pbGetSpeciesData(@species,formSimple,SpeciesAbilities)
if abilities.is_a?(Array)
ret = abilities[abilIndex]
ret = abilities[(abilIndex+1)%2] if !ret || ret==0
return ret || 0
end
return abilities || 0
end
# Returns whether this Pokémon has a particular ability.
def hasAbility?(value=0)
abil = self.ability
return abil>0 if value==0
return abil==getID(PBAbilities,value)
end
# Sets this Pokémon's ability to a particular ability (if possible).
def setAbility(value)
@abilityflag = value
end
def hasHiddenAbility?
abil = abilityIndex
return abil!=nil && abil>=2
end
# Returns the list of abilities this Pokémon can have.
def getAbilityList
ret = []
abilities = pbGetSpeciesData(@species,formSimple,SpeciesAbilities)
if abilities.is_a?(Array)
abilities.each_with_index { |a,i| ret.push([a,i]) if a && a>0 }
else
ret.push([abilities,0]) if abilities>0
end
hiddenAbil = pbGetSpeciesData(@species,formSimple,SpeciesHiddenAbility)
if hiddenAbil.is_a?(Array)
hiddenAbil.each_with_index { |a,i| ret.push([a,i+2]) if a && a>0 }
else
ret.push([hiddenAbil,2]) if hiddenAbil>0
end
return ret
end
#=============================================================================
# Nature
#=============================================================================
# Returns the ID of this Pokémon's nature.
def nature
return @natureflag || (@personalID%25)
end
# Returns the calculated nature, taking into account things that change its
# stat-altering effect (i.e. Gen 8 mints). Only used for calculating stats.
def calcNature
return @natureOverride if @natureOverride
return self.nature
end
# Returns whether this Pokémon has a particular nature.
def hasNature?(value=-1)
nat = self.nature
return nat>=0 if value<0
return nat==getID(PBNatures,value)
end
# Sets this Pokémon's nature to a particular nature.
def setNature(value)
@natureflag = getID(PBNatures,value)
self.calcStats
end
#=============================================================================
# Shininess
#=============================================================================
# Returns whether this Pokémon is shiny (differently colored).
def shiny?
return @shinyflag if @shinyflag!=nil
a = @personalID^@trainerID
b = a&0xFFFF
c = (a>>16)&0xFFFF
d = b^c
return d<SHINY_POKEMON_CHANCE
end
alias isShiny? shiny?
# Makes this Pokémon shiny.
def makeShiny
@shinyflag = true
end
# Makes this Pokémon not shiny.
def makeNotShiny
@shinyflag = false
end
#=============================================================================
# Pokérus
#=============================================================================
# Returns the Pokérus infection stage for this Pokémon.
def pokerusStrain
return @pokerus/16
end
# Returns the Pokérus infection stage for this Pokémon.
def pokerusStage
return 0 if !@pokerus || @pokerus==0 # Not infected
return 2 if @pokerus>0 && (@pokerus%16)==0 # Cured
return 1 # Infected
end
# Gives this Pokémon Pokérus (either the specified strain or a random one).
def givePokerus(strain=0)
return if self.pokerusStage==2 # Can't re-infect a cured Pokémon
strain = 1+rand(15) if strain<=0 || strain>=16
time = 1+(strain%4)
@pokerus = time
@pokerus |= strain<<4
end
# Resets the infection time for this Pokémon's Pokérus (even if cured).
def resetPokerusTime
return if @pokerus==0
strain = @pokerus%16
time = 1+(strain%4)
@pokerus = time
@pokerus |= strain<<4
end
# Reduces the time remaining for this Pokémon's Pokérus (if infected).
def lowerPokerusCount
return if self.pokerusStage!=1
@pokerus -= 1
end
#=============================================================================
# Types
#=============================================================================
# Returns this Pokémon's first type.
def type1
return pbGetSpeciesData(@species,formSimple,SpeciesType1)
end
# Returns this Pokémon's second type.
def type2
ret = pbGetSpeciesData(@species,formSimple,SpeciesType2)
ret = pbGetSpeciesData(@species,formSimple,SpeciesType1) if !ret
return ret
end
def types
ret1 = pbGetSpeciesData(@species,formSimple,SpeciesType1)
ret2 = pbGetSpeciesData(@species,formSimple,SpeciesType2)
ret = [ret1]
ret.push(ret2) if ret2 && ret2!=ret1
return ret
end
# Returns whether this Pokémon has the specified type.
def hasType?(type)
t = self.types
if !type.is_a?(Integer)
return t.any? { |tp| isConst?(tp,PBTypes,type) }
end
return t.any? { |tp| tp==type }
end
#=============================================================================
# Moves
#=============================================================================
# Returns the number of moves known by the Pokémon.
def numMoves
ret = 0
@moves.each { |m| ret += 1 if m && m.id!=0 }
return ret
end
# Returns true if the Pokémon knows the given move.
def hasMove?(move)
move = getID(PBMoves,move)
return false if !move || move<=0
@moves.each { |m| return true if m && m.id==move }
return false
end
alias knowsMove? hasMove?
# Returns the list of moves this Pokémon can learn by levelling up.
def getMoveList
return pbGetSpeciesMoveset(@species,formSimple)
end
# Sets this Pokémon's movelist to the default movelist it originally had.
def resetMoves
lvl = self.level
fullMoveList = self.getMoveList
moveList = []
fullMoveList.each { |m| moveList.push(m[1]) if m[0]<=lvl }
moveList = moveList.reverse
moveList |= [] # Remove duplicates
moveList = moveList.reverse
listend = moveList.length-4
listend = 0 if listend<0
j = 0
for i in listend...listend+4
moveid = (i>=moveList.length) ? 0 : moveList[i]
@moves[j] = PBMove.new(moveid)
j += 1
end
end
# Silently learns the given move. Will erase the first known move if it has to.
def pbLearnMove(move)
move = getID(PBMoves,move)
return if move<=0
for i in 0...4 # Already knows move, relocate it to the end of the list
next if @moves[i].id!=move
j = i+1; while j<4
break if @moves[j].id==0
tmp = @moves[j]
@moves[j] = @moves[j-1]
@moves[j-1] = tmp
j += 1
end
return
end
for i in 0...4 # Has empty move slot, put move in there
next if @moves[i].id!=0
@moves[i] = PBMove.new(move)
return
end
# Already knows 4 moves, forget the first move and learn the new move
@moves[0] = @moves[1]
@moves[1] = @moves[2]
@moves[2] = @moves[3]
@moves[3] = PBMove.new(move)
end
# Deletes the given move from the Pokémon.
def pbDeleteMove(move)
move = getID(PBMoves,move)
return if !move || move<=0
newMoves = []
@moves.each { |m| newMoves.push(m) if m && m.id!=move }
newMoves.push(PBMove.new(0))
for i in 0...4
@moves[i] = newMoves[i]
end
end
# Deletes the move at the given index from the Pokémon.
def pbDeleteMoveAtIndex(index)
newMoves = []
@moves.each_with_index { |m,i| newMoves.push(m) if m && i!=index }
newMoves.push(PBMove.new(0))
for i in 0...4
@moves[i] = newMoves[i]
end
end
# Deletes all moves from the Pokémon.
def pbDeleteAllMoves
for i in 0...4
@moves[i] = PBMove.new(0)
end
end
# Copies currently known moves into a separate array, for Move Relearner.
def pbRecordFirstMoves
@firstmoves = []
@moves.each { |m| @firstmoves.push(m.id) if m && m.id>0 }
end
def pbAddFirstMove(move)
move = getID(PBMoves,move)
@firstmoves.push(move) if move>0 && !@firstmoves.include?(move)
end
def pbRemoveFirstMove(move)
move = getID(PBMoves,move)
@firstmoves.delete(move) if move>0
end
def pbClearFirstMoves
@firstmoves = []
end
def compatibleWithMove?(move)
return pbSpeciesCompatible?(self.fSpecies,move)
end
#=============================================================================
# Contest attributes, ribbons
#=============================================================================
def cool; return @cool ? @cool : 0; end
def beauty; return @beauty ? @beauty : 0; end
def cute; return @cute ? @cute : 0; end
def smart; return @smart ? @smart : 0; end
def tough; return @tough ? @tough : 0; end
def sheen; return @sheen ? @sheen : 0; end
# Returns the number of ribbons this Pokémon has.
def ribbonCount
return (@ribbons) ? @ribbons.length : 0
end
# Returns whether this Pokémon has the specified ribbon.
def hasRibbon?(ribbon)
return false if !@ribbons
ribbon = getID(PBRibbons,ribbon)
return false if ribbon==0
return @ribbons.include?(ribbon)
end
# Gives this Pokémon the specified ribbon.
def giveRibbon(ribbon)
@ribbons = [] if !@ribbons
ribbon = getID(PBRibbons,ribbon)
return if ribbon==0
@ribbons.push(ribbon) if !@ribbons.include?(ribbon)
end
# Replaces one ribbon with the next one along, if possible.
def upgradeRibbon(*arg)
@ribbons = [] if !@ribbons
for i in 0...arg.length-1
for j in 0...@ribbons.length
thisribbon = (arg[i].is_a?(Integer)) ? arg[i] : getID(PBRibbons,arg[i])
if @ribbons[j]==thisribbon
nextribbon = (arg[i+1].is_a?(Integer)) ? arg[i+1] : getID(PBRibbons,arg[i+1])
@ribbons[j] = nextribbon
return nextribbon
end
end
end
if !hasRibbon?(arg[arg.length-1])
firstribbon = (arg[0].is_a?(Integer)) ? arg[0] : getID(PBRibbons,arg[0])
giveRibbon(firstribbon)
return firstribbon
end
return 0
end
# Removes the specified ribbon from this Pokémon.
def takeRibbon(ribbon)
return if !@ribbons
ribbon = getID(PBRibbons,ribbon)
return if ribbon==0
for i in 0...@ribbons.length
next if @ribbons[i]!=ribbon
@ribbons[i] = nil
break
end
@ribbons.compact!
end
# Removes all ribbons from this Pokémon.
def clearAllRibbons
@ribbons = []
end
#=============================================================================
# Items
#=============================================================================
# Returns whether this Pokémon has a hold item.
def hasItem?(value=0)
itm = self.item
return itm>0 if value==0
return itm==getID(PBItems,value)
end
# Sets this Pokémon's item. Accepts symbols.
def setItem(value)
self.item = getID(PBItems,value)
end
# Returns the items this species can be found holding in the wild.
def wildHoldItems
ret = []
ret.push(pbGetSpeciesData(@species,formSimple,SpeciesWildItemCommon))
ret.push(pbGetSpeciesData(@species,formSimple,SpeciesWildItemUncommon))
ret.push(pbGetSpeciesData(@species,formSimple,SpeciesWildItemRare))
return ret
end
# Returns this Pokémon's mail.
def mail
return nil if !@mail
@mail = nil if @mail.item==0 || !hasItem?(@mail.item)
return @mail
end
#=============================================================================
# Other
#=============================================================================
def species=(value)
resetName = nicknamed?
@species = value
@name = PBSpecies.getName(@species) if !resetName
@level = nil # In case growth rate is different for the new species
@forcedForm = nil
self.form = 0 # Also recalculates stats
end
def isSpecies?(s)
s = getID(PBSpecies,s)
return s && @species==s
end
# Returns the species name of this Pokémon.
def speciesName
return PBSpecies.getName(@species)
end
def nicknamed?
return @name==self.speciesName
end
# Returns this Pokémon's language.
def language; return @language || 0; end
# Returns the markings this Pokémon has.
def markings; return @markings || 0; end
# Returns a string stating the Unown form of this Pokémon.
def unownShape
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ?!"[@form,1]
end
# Returns the height of this Pokémon.
def height
return pbGetSpeciesData(@species,formSimple,SpeciesHeight)
end
# Returns the weight of this Pokémon.
def weight
return pbGetSpeciesData(@species,formSimple,SpeciesWeight)
end
# Returns an array of booleans indicating whether a stat is made to have
# maximum IVs (for Hyper Training). Set like @ivMaxed[PBStats::ATTACK] = true
def ivMaxed
@ivMaxed = [] if !@ivMaxed
return @ivMaxed
end
# Returns this Pokémon's effective IVs, taking into account Hyper Training.
# Only used for calculating stats.
def calcIV
ret = self.iv.clone
if @ivMaxed
PBStats.eachStat { |s| ret[s] = IV_STAT_LIMIT if @ivMaxed[s] }
end
return ret
end
# Returns the EV yield of this Pokémon.
def evYield
ret = pbGetSpeciesData(@species,formSimple,SpeciesEffortPoints)
return ret.clone
end
# Sets this Pokémon's HP.
def hp=(value)
value = 0 if value<0
@hp = value
if @hp==0
@status = PBStatuses::NONE
@statusCount = 0
end
end
def able?
return !egg? && @hp>0
end
alias isAble? able?
def fainted?
return !egg? && @hp<=0
end
alias isFainted? fainted?
# Heals all HP of this Pokémon.
def healHP
return if egg?
@hp = @totalhp
end
# Heals the status problem of this Pokémon.
def healStatus
return if egg?
@status = PBStatuses::NONE
@statusCount = 0
end
# Heals all PP of this Pokémon.
def healPP(index=-1)
return if egg?
if index>=0
@moves[index].pp = @moves[index].totalpp
else
@moves.each { |m| m.pp = m.totalpp }
end
end
# Heals all HP, PP, and status problems of this Pokémon.
def heal
return if egg?
healHP
healStatus
healPP
end
# Changes the happiness of this Pokémon depending on what happened to change it.
def changeHappiness(method)
gain = 0
case method
when "walking"
gain = 1
gain = 2 if @happiness<200
when "levelup"
gain = 3
gain = 4 if @happiness<200
gain = 5 if @happiness<100
when "groom"
gain = 4
gain = 10 if @happiness<200
when "evberry"
gain = 2
gain = 5 if @happiness<200
gain = 10 if @happiness<100
when "vitamin"
gain = 2
gain = 3 if @happiness<200
gain = 5 if @happiness<100
when "wing"
gain = 1
gain = 2 if @happiness<200
gain = 3 if @happiness<100
when "machine"
gain = 0
gain = 1 if @happiness<200
when "battleitem"
gain = 0
gain = 1 if @happiness<200
when "faint"
gain = -1
when "faintbad" # Fainted against an opponent that is 30+ levels higher
gain = -10
gain = -5 if @happiness<200
when "powder"
gain = -10
gain = -5 if @happiness<200
when "energyroot"
gain = -15
gain = -10 if @happiness<200
when "revivalherb"
gain = -20
gain = -15 if @happiness<200
else
raise _INTL("Unknown happiness-changing method: {1}",method.to_s)
end
if gain>0
gain += 1 if @obtainMap==$game_map.map_id
gain += 1 if self.ballused==pbGetBallType(:LUXURYBALL)
gain = (gain*1.5).floor if isConst?(self.item,PBItems,:SOOTHEBELL)
end
@happiness += gain
@happiness = [[255,@happiness].min,0].max
end
#=============================================================================
# Stat calculations, Pokémon creation
#=============================================================================
# Returns this Pokémon's base stats. An array of six values.
def baseStats
ret = pbGetSpeciesData(@species,formSimple,SpeciesBaseStats)
return ret.clone
end
# Returns the maximum HP of this Pokémon.
def calcHP(base,level,iv,ev)
return 1 if base==1 # For Shedinja
return ((base*2+iv+(ev>>2))*level/100).floor+level+10
end
# Returns the specified stat of this Pokémon (not used for total HP).
def calcStat(base,level,iv,ev,pv)
return ((((base*2+iv+(ev>>2))*level/100).floor+5)*pv/100).floor
end
# Recalculates this Pokémon's stats.
def calcStats
bs = self.baseStats
usedLevel = self.level
usedIV = self.calcIV
pValues = PBNatures.getStatChanges(self.calcNature)
stats = []
PBStats.eachStat do |s|
if s==PBStats::HP
stats[s] = calcHP(bs[s],usedLevel,usedIV[s],@ev[s])
else
stats[s] = calcStat(bs[s],usedLevel,usedIV[s],@ev[s],pValues[s])
end
end
hpDiff = @totalhp-@hp
@totalhp = stats[PBStats::HP]
@hp = @totalhp-hpDiff
@hp = 0 if @hp<0
@hp = @totalhp if @hp>@totalhp
@attack = stats[PBStats::ATTACK]
@defense = stats[PBStats::DEFENSE]
@spatk = stats[PBStats::SPATK]
@spdef = stats[PBStats::SPDEF]
@speed = stats[PBStats::SPEED]
end
def clone
ret = super
ret.iv = @iv.clone
ret.ivMaxed = @ivMaxed.clone
ret.ev = @ev.clone
ret.moves = []
@moves.each_with_index { |m,i| ret.moves[i] = m.clone }
ret.ribbons = @ribbons.clone if @ribbons
return ret
end
# Creates a new Pokémon object.
# species - Pokémon species.
# level - Pokémon level.
# player - PokeBattle_Trainer object for the original trainer.
# withMoves - If false, this Pokémon has no moves.
def initialize(species,level,player=nil,withMoves=true)
ospecies = species.to_s
species = getID(PBSpecies,species)
cname = getConstantName(PBSpecies,species) rescue nil
realSpecies = pbGetSpeciesFromFSpecies(species)[0] if species && species>0
if !species || species<=0 || realSpecies>PBSpecies.maxValue || !cname
raise ArgumentError.new(_INTL("The species given ({1}) is invalid.",ospecies))
return nil
end
@species = realSpecies
@name = PBSpecies.getName(@species)
@personalID = rand(256)
@personalID |= rand(256)<<8
@personalID |= rand(256)<<16
@personalID |= rand(256)<<24
@hp = 1
@totalhp = 1
@iv = []
@ivMaxed = []
@ev = []
PBStats.eachStat do |s|
@iv[s] = rand(IV_STAT_LIMIT+1)
@ev[s] = 0
end
@moves = []
@status = PBStatuses::NONE
@statusCount = 0
@item = 0
@mail = nil
@fused = nil
@ribbons = []
@ballused = 0
@eggsteps = 0
if player
@trainerID = player.id
@ot = player.name
@otgender = player.gender
@language = player.language
else
@trainerID = 0
@ot = ""
@otgender = 2
end
@obtainMap = ($game_map) ? $game_map.map_id : 0
@obtainText = nil
@obtainLevel = level
@obtainMode = 0 # Met
@obtainMode = 4 if $game_switches && $game_switches[FATEFUL_ENCOUNTER_SWITCH]
@hatchedMap = 0
@timeReceived = pbGetTimeNow.to_i
self.level = level
calcStats
@hp = @totalhp
@happiness = pbGetSpeciesData(@species,formSimple,SpeciesHappiness)
if withMoves
self.resetMoves
else
for i in 0...4
@moves[i] = PBMove.new(0)
end
end
end
end
def pbNewPkmn(species,level,owner=nil,withMoves=true)
owner = $Trainer if !owner
return PokeBattle_Pokemon.new(species,level,owner,withMoves)
end
alias pbGenPkmn pbNewPkmn
alias pbGenPoke pbNewPkmn

View File

@@ -0,0 +1,690 @@
class PokeBattle_Pokemon
attr_accessor :formTime # Time when Furfrou's/Hoopa's form was set
attr_accessor :forcedForm
def form
return @forcedForm if @forcedForm!=nil
return (@form || 0) if $game_temp.in_battle
v = MultipleForms.call("getForm",self)
self.form = v if v!=nil && (!@form || v!=@form)
return @form || 0
end
def form=(value)
setForm(value)
end
def setForm(value)
oldForm = @form
@form = value
yield if block_given?
MultipleForms.call("onSetForm",self,value,oldForm)
self.calcStats
pbSeenForm(self)
end
def formSimple
return @forcedForm if @forcedForm!=nil
return @form || 0
end
def formSimple=(value)
@form = value
self.calcStats
end
def fSpecies
return pbGetFSpeciesFromForm(@species,formSimple)
end
alias __mf_compatibleWithMove? compatibleWithMove? # Deprecated
def compatibleWithMove?(move)
v = MultipleForms.call("getMoveCompatibility",self)
if v!=nil
return v.any? { |j| j==move }
end
return __mf_compatibleWithMove?(move)
end
alias __mf_initialize initialize
def initialize(*args)
@form = (pbGetSpeciesFromFSpecies(args[0])[1] rescue 0)
__mf_initialize(*args)
if @form==0
f = MultipleForms.call("getFormOnCreation",self)
if f
self.form = f
self.resetMoves
end
end
end
end
class PokeBattle_RealBattlePeer
def pbOnEnteringBattle(battle,pkmn,wild=false)
f = MultipleForms.call("getFormOnEnteringBattle",pkmn,wild)
pkmn.form = f if f
end
# For switching out, including due to fainting, and for the end of battle
def pbOnLeavingBattle(battle,pkmn,usedInBattle,endBattle=false)
f = MultipleForms.call("getFormOnLeavingBattle",pkmn,battle,usedInBattle,endBattle)
pkmn.form = f if f && pkmn.form!=f
pkmn.hp = pkmn.totalhp if pkmn.hp>pkmn.totalhp
end
end
module MultipleForms
@@formSpecies = SpeciesHandlerHash.new
def self.copy(sym,*syms)
@@formSpecies.copy(sym,*syms)
end
def self.register(sym,hash)
@@formSpecies.add(sym,hash)
end
def self.registerIf(cond,hash)
@@formSpecies.addIf(cond,hash)
end
def self.hasFunction?(pkmn,func)
spec = (pkmn.is_a?(Numeric)) ? pkmn : pkmn.species
sp = @@formSpecies[spec]
return sp && sp[func]
end
def self.getFunction(pkmn,func)
spec = (pkmn.is_a?(Numeric)) ? pkmn : pkmn.species
sp = @@formSpecies[spec]
return (sp && sp[func]) ? sp[func] : nil
end
def self.call(func,pkmn,*args)
sp = @@formSpecies[pkmn.species]
return nil if !sp || !sp[func]
return sp[func].call(pkmn,*args)
end
end
def drawSpot(bitmap,spotpattern,x,y,red,green,blue)
height = spotpattern.length
width = spotpattern[0].length
for yy in 0...height
spot = spotpattern[yy]
for xx in 0...width
if spot[xx]==1
xOrg = (x+xx)<<1
yOrg = (y+yy)<<1
color = bitmap.get_pixel(xOrg,yOrg)
r = color.red+red
g = color.green+green
b = color.blue+blue
color.red = [[r,0].max,255].min
color.green = [[g,0].max,255].min
color.blue = [[b,0].max,255].min
bitmap.set_pixel(xOrg,yOrg,color)
bitmap.set_pixel(xOrg+1,yOrg,color)
bitmap.set_pixel(xOrg,yOrg+1,color)
bitmap.set_pixel(xOrg+1,yOrg+1,color)
end
end
end
end
def pbSpindaSpots(pkmn,bitmap)
spot1 = [
[0,0,1,1,1,1,0,0],
[0,1,1,1,1,1,1,0],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[0,1,1,1,1,1,1,0],
[0,0,1,1,1,1,0,0]
]
spot2 = [
[0,0,1,1,1,0,0],
[0,1,1,1,1,1,0],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[0,1,1,1,1,1,0],
[0,0,1,1,1,0,0]
]
spot3 = [
[0,0,0,0,0,1,1,1,1,0,0,0,0],
[0,0,0,1,1,1,1,1,1,1,0,0,0],
[0,0,1,1,1,1,1,1,1,1,1,0,0],
[0,1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,1,0],
[1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1],
[0,1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,1,1,1,1,1,1,1,0,0],
[0,0,0,1,1,1,1,1,1,1,0,0,0],
[0,0,0,0,0,1,1,1,0,0,0,0,0]
]
spot4 = [
[0,0,0,0,1,1,1,0,0,0,0,0],
[0,0,1,1,1,1,1,1,1,0,0,0],
[0,1,1,1,1,1,1,1,1,1,0,0],
[0,1,1,1,1,1,1,1,1,1,1,0],
[1,1,1,1,1,1,1,1,1,1,1,0],
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,1,1,1,0],
[0,0,1,1,1,1,1,1,1,1,0,0],
[0,0,0,0,1,1,1,1,1,0,0,0]
]
id = pkmn.personalID
h = (id>>28)&15
g = (id>>24)&15
f = (id>>20)&15
e = (id>>16)&15
d = (id>>12)&15
c = (id>>8)&15
b = (id>>4)&15
a = (id)&15
if pkmn.shiny?
drawSpot(bitmap,spot1,b+33,a+25,-75,-10,-150)
drawSpot(bitmap,spot2,d+21,c+24,-75,-10,-150)
drawSpot(bitmap,spot3,f+39,e+7,-75,-10,-150)
drawSpot(bitmap,spot4,h+15,g+6,-75,-10,-150)
else
drawSpot(bitmap,spot1,b+33,a+25,0,-115,-75)
drawSpot(bitmap,spot2,d+21,c+24,0,-115,-75)
drawSpot(bitmap,spot3,f+39,e+7,0,-115,-75)
drawSpot(bitmap,spot4,h+15,g+6,0,-115,-75)
end
end
#===============================================================================
# Regular form differences
#===============================================================================
MultipleForms.register(:UNOWN,{
"getFormOnCreation" => proc { |pkmn|
next rand(28)
}
})
MultipleForms.register(:SPINDA,{
"alterBitmap" => proc { |pkmn,bitmap|
pbSpindaSpots(pkmn,bitmap)
}
})
MultipleForms.register(:CASTFORM,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0
}
})
MultipleForms.register(:BURMY,{
"getFormOnCreation" => proc { |pkmn|
case pbGetEnvironment
when PBEnvironment::Rock, PBEnvironment::Sand, PBEnvironment::Cave
next 1 # Sandy Cloak
when PBEnvironment::None
next 2 # Trash Cloak
else
next 0 # Plant Cloak
end
},
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next if !endBattle || !usedInBattle
env = battle.environment
case battle.environment
when PBEnvironment::Rock, PBEnvironment::Sand, PBEnvironment::Cave
next 1 # Sandy Cloak
when PBEnvironment::None
next 2 # Trash Cloak
else
next 0 # Plant Cloak
end
}
})
MultipleForms.register(:WORMADAM,{
"getFormOnCreation" => proc { |pkmn|
case pbGetEnvironment
when PBEnvironment::Rock, PBEnvironment::Sand, PBEnvironment::Cave
next 1 # Sandy Cloak
when PBEnvironment::None
next 2 # Trash Cloak
else
next 0 # Plant Cloak
end
}
})
MultipleForms.register(:CHERRIM,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0
}
})
MultipleForms.register(:ROTOM,{
"onSetForm" => proc { |pkmn,form,oldForm|
formMoves = [
:OVERHEAT, # Heat, Microwave
:HYDROPUMP, # Wash, Washing Machine
:BLIZZARD, # Frost, Refrigerator
:AIRSLASH, # Fan
:LEAFSTORM # Mow, Lawnmower
]
idxMoveToReplace = -1
pkmn.moves.each_with_index do |move,i|
next if !move
formMoves.each do |newMove|
next if !isConst?(move.id,PBMoves,newMove)
idxMoveToReplace = i
break
end
break if idxMoveToReplace>=0
end
if form==0
if idxMoveToReplace>=0
moveName = PBMoves.getName(pkmn.moves[idxMoveToReplace].id)
pkmn.pbDeleteMoveAtIndex(idxMoveToReplace)
pbMessage(_INTL("{1} forgot {2}...",pkmn.name,moveName))
pkmn.pbLearnMove(:THUNDERSHOCK) if pkmn.numMoves==0
end
else
newMove = getConst(PBMoves,formMoves[form-1])
if idxMoveToReplace>=0
oldMoveName = PBMoves.getName(pkmn.moves[idxMoveToReplace].id)
if newMove && newMove>0
newMoveName = PBMoves.getName(newMove)
pkmn.moves[idxMoveToReplace].id = newMove
pbMessage(_INTL("1,\\wt[16] 2, and\\wt[16]...\\wt[16] ...\\wt[16] ... Ta-da!\\se[Battle ball drop]\1"))
pbMessage(_INTL("{1} forgot how to use {2}.\\nAnd...\1",pkmn.name,oldMoveName))
pbMessage(_INTL("\\se[]{1} learned {2}!\\se[Pkmn move learnt]",pkmn.name,newMoveName))
else
pkmn.pbDeleteMoveAtIndex(idxMoveToReplace)
pbMessage(_INTL("{1} forgot {2}...",pkmn.name,oldMoveName))
pkmn.pbLearnMove(:THUNDERSHOCK) if pkmn.numMoves==0
end
elsif newMove && newMove>0
pbLearnMove(pkmn,newMove,true)
end
end
}
})
MultipleForms.register(:GIRATINA,{
"getForm" => proc { |pkmn|
maps = [49,50,51,72,73] # Map IDs for Origin Forme
if isConst?(pkmn.item,PBItems,:GRISEOUSORB) ||
maps.include?($game_map.map_id)
next 1
end
next 0
}
})
MultipleForms.register(:SHAYMIN,{
"getForm" => proc { |pkmn|
next 0 if pkmn.fainted? || pkmn.status==PBStatuses::FROZEN ||
PBDayNight.isNight?
}
})
MultipleForms.register(:ARCEUS,{
"getForm" => proc { |pkmn|
next nil if !isConst?(pkmn.ability,PBAbilities,:MULTITYPE)
typeArray = {
1 => [:FISTPLATE,:FIGHTINIUMZ],
2 => [:SKYPLATE,:FLYINIUMZ],
3 => [:TOXICPLATE,:POISONIUMZ],
4 => [:EARTHPLATE,:GROUNDIUMZ],
5 => [:STONEPLATE,:ROCKIUMZ],
6 => [:INSECTPLATE,:BUGINIUMZ],
7 => [:SPOOKYPLATE,:GHOSTIUMZ],
8 => [:IRONPLATE,:STEELIUMZ],
10 => [:FLAMEPLATE,:FIRIUMZ],
11 => [:SPLASHPLATE,:WATERIUMZ],
12 => [:MEADOWPLATE,:GRASSIUMZ],
13 => [:ZAPPLATE,:ELECTRIUMZ],
14 => [:MINDPLATE,:PSYCHIUMZ],
15 => [:ICICLEPLATE,:ICIUMZ],
16 => [:DRACOPLATE,:DRAGONIUMZ],
17 => [:DREADPLATE,:DARKINIUMZ],
18 => [:PIXIEPLATE,:FAIRIUMZ]
}
ret = 0
typeArray.each do |f, items|
for i in items
next if !isConst?(pkmn.item,PBItems,i)
ret = f
break
end
break if ret>0
end
next ret
}
})
MultipleForms.register(:BASCULIN,{
"getFormOnCreation" => proc { |pkmn|
next rand(2)
}
})
MultipleForms.register(:DARMANITAN,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0
}
})
MultipleForms.register(:DEERLING,{
"getForm" => proc { |pkmn|
next pbGetSeason
}
})
MultipleForms.copy(:DEERLING,:SAWSBUCK)
MultipleForms.register(:KYUREM,{
"getFormOnEnteringBattle" => proc { |pkmn,wild|
next pkmn.form+2 if pkmn.form==1 || pkmn.form==2
},
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next pkmn.form-2 if pkmn.form>=3 # Fused forms stop glowing
},
"onSetForm" => proc { |pkmn,form,oldForm|
case form
when 0 # Normal
pkmn.moves.each do |move|
next if !move
if (isConst?(move.id,PBMoves,:ICEBURN) ||
isConst?(move.id,PBMoves,:FREEZESHOCK)) && hasConst?(PBMoves,:GLACIATE)
move.id = getConst(PBMoves,:GLACIATE)
end
if (isConst?(move.id,PBMoves,:FUSIONFLARE) ||
isConst?(move.id,PBMoves,:FUSIONBOLT)) && hasConst?(PBMoves,:SCARYFACE)
move.id = getConst(PBMoves,:SCARYFACE)
end
end
when 1 # White
pkmn.moves.each do |move|
next if !move
if isConst?(move.id,PBMoves,:GLACIATE) && hasConst?(PBMoves,:ICEBURN)
move.id = getConst(PBMoves,:ICEBURN)
end
if isConst?(move.id,PBMoves,:SCARYFACE) && hasConst?(PBMoves,:FUSIONFLARE)
move.id = getConst(PBMoves,:FUSIONFLARE)
end
end
when 2 # Black
pkmn.moves.each do |move|
next if !move
if isConst?(move.id,PBMoves,:GLACIATE) && hasConst?(PBMoves,:FREEZESHOCK)
move.id = getConst(PBMoves,:FREEZESHOCK)
end
if isConst?(move.id,PBMoves,:SCARYFACE) && hasConst?(PBMoves,:FUSIONBOLT)
move.id = getConst(PBMoves,:FUSIONBOLT)
end
end
end
}
})
MultipleForms.register(:KELDEO,{
"getForm" => proc { |pkmn|
next 1 if pkmn.hasMove?(:SECRETSWORD) # Resolute Form
next 0 # Ordinary Form
}
})
MultipleForms.register(:MELOETTA,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0
}
})
MultipleForms.register(:GENESECT,{
"getForm" => proc { |pkmn|
next 1 if isConst?(pkmn.item,PBItems,:SHOCKDRIVE)
next 2 if isConst?(pkmn.item,PBItems,:BURNDRIVE)
next 3 if isConst?(pkmn.item,PBItems,:CHILLDRIVE)
next 4 if isConst?(pkmn.item,PBItems,:DOUSEDRIVE)
next 0
}
})
MultipleForms.register(:GRENINJA,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0 if pkmn.fainted? || endBattle
}
})
MultipleForms.register(:SCATTERBUG,{
"getFormOnCreation" => proc { |pkmn|
next $Trainer.secretID%18
}
})
MultipleForms.copy(:SCATTERBUG,:SPEWPA,:VIVILLON)
MultipleForms.register(:FLABEBE,{
"getFormOnCreation" => proc { |pkmn|
next rand(5)
}
})
MultipleForms.copy(:FLABEBE,:FLOETTE,:FLORGES)
MultipleForms.register(:FURFROU,{
"getForm" => proc { |pkmn|
if !pkmn.formTime || pbGetTimeNow.to_i>pkmn.formTime.to_i+60*60*24*5 # 5 days
next 0
end
},
"onSetForm" => proc { |pkmn,form,oldForm|
pkmn.formTime = (form>0) ? pbGetTimeNow.to_i : nil
}
})
MultipleForms.register(:ESPURR,{
"getForm" => proc { |pkmn|
next pkmn.gender
}
})
MultipleForms.copy(:ESPURR,:MEOWSTIC)
MultipleForms.register(:AEGISLASH,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0
}
})
MultipleForms.register(:PUMPKABOO,{
"getFormOnCreation" => proc { |pkmn|
r = rand(100)
if r<5; next 3 # Super Size (5%)
elsif r<20; next 2 # Large (15%)
elsif r<65; next 1 # Average (45%)
end
next 0 # Small (35%)
}
})
MultipleForms.copy(:PUMPKABOO,:GOURGEIST)
MultipleForms.register(:XERNEAS,{
"getFormOnEnteringBattle" => proc { |pkmn,wild|
next 1
},
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0
}
})
MultipleForms.register(:ZYGARDE,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next pkmn.form-2 if pkmn.form>=2 && (pkmn.fainted? || endBattle)
}
})
MultipleForms.register(:HOOPA,{
"getForm" => proc { |pkmn|
if !pkmn.formTime || pbGetTimeNow.to_i>pkmn.formTime.to_i+60*60*24*3 # 3 days
next 0
end
},
"onSetForm" => proc { |pkmn,form,oldForm|
pkmn.formTime = (form>0) ? pbGetTimeNow.to_i : nil
}
})
MultipleForms.register(:ORICORIO,{
"getFormOnCreation" => proc { |pkmn|
next rand(4) # 0=red, 1=yellow, 2=pink, 3=purple
},
})
MultipleForms.register(:ROCKRUFF,{
"getForm" => proc { |pkmn|
next if pkmn.formSimple>=2 # Own Tempo Rockruff cannot become another form
next 1 if PBDayNight.isNight?
next 0
}
})
MultipleForms.register(:LYCANROC,{
"getFormOnCreation" => proc { |pkmn|
next 2 if PBDayNight.isEvening? # Dusk
next 1 if PBDayNight.isNight? # Midnight
next 0 # Midday
},
})
MultipleForms.register(:WISHIWASHI,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0
}
})
MultipleForms.register(:SILVALLY,{
"getForm" => proc { |pkmn|
next nil if !isConst?(pkmn.ability,PBAbilities,:RKSSYSTEM)
typeArray = {
1 => [:FIGHTINGMEMORY],
2 => [:FLYINGMEMORY],
3 => [:POISONMEMORY],
4 => [:GROUNDMEMORY],
5 => [:ROCKMEMORY],
6 => [:BUGMEMORY],
7 => [:GHOSTMEMORY],
8 => [:STEELMEMORY],
10 => [:FIREMEMORY],
11 => [:WATERMEMORY],
12 => [:GRASSMEMORY],
13 => [:ELECTRICMEMORY],
14 => [:PSYCHICMEMORY],
15 => [:ICEMEMORY],
16 => [:DRAGONMEMORY],
17 => [:DARKMEMORY],
18 => [:FAIRYMEMORY]
}
ret = 0
typeArray.each do |f, items|
for i in items
next if !isConst?(pkmn.item,PBItems,i)
ret = f
break
end
break if ret>0
end
next ret
}
})
MultipleForms.register(:MINIOR,{
"getFormOnCreation" => proc { |pkmn|
next 7+rand(7) # Meteor forms are 0-6, Core forms are 7-13
},
"getFormOnEnteringBattle" => proc { |pkmn,wild|
next pkmn.form-7 if pkmn.form>=7 && wild # Wild Minior always appear in Meteor form
},
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next pkmn.form+7 if pkmn.form<7
}
})
MultipleForms.register(:MIMIKYU,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
next 0 if pkmn.fainted? || endBattle
}
})
MultipleForms.register(:NECROZMA,{
"getFormOnLeavingBattle" => proc { |pkmn,battle,usedInBattle,endBattle|
# Fused forms are 1 and 2, Ultra form is 3 or 4 depending on which fusion
next pkmn.form-2 if pkmn.form>=3 && (pkmn.fainted? || endBattle)
},
"onSetForm" => proc { |pkmn,form,oldForm|
next if form>2 || oldForm>2 # Ultra form changes don't affect moveset
formMoves = [
:SUNSTEELSTRIKE, # Dusk Mane (with Solgaleo) (form 1)
:MOONGEISTBEAM # Dawn Wings (with Lunala) (form 2)
]
if form==0
idxMoveToReplace = -1
pkmn.moves.each_with_index do |move,i|
next if !move
formMoves.each do |newMove|
next if !isConst?(move.id,PBMoves,newMove)
idxMoveToReplace = i
break
end
break if idxMoveToReplace>=0
end
if idxMoveToReplace>=0
moveName = PBMoves.getName(pkmn.moves[idxMoveToReplace].id)
pkmn.pbDeleteMoveAtIndex(idxMoveToReplace)
pbMessage(_INTL("{1} forgot {2}...",pkmn.name,moveName))
pkmn.pbLearnMove(:CONFUSION) if pkmn.numMoves==0
end
else
newMove = getConst(PBMoves,formMoves[form-1])
if newMove && newMove>0
pbLearnMove(pkmn,newMove,true)
end
end
}
})
#===============================================================================
# Alolan forms
#===============================================================================
# These species don't have visually different Alolan forms, but they need to
# evolve into different forms depending on the location where they evolved.
MultipleForms.register(:PIKACHU,{
"getForm" => proc { |pkmn|
next if pkmn.formSimple>=2
mapPos = pbGetMetadata($game_map.map_id,MetadataMapPosition)
next 1 if mapPos && mapPos[0]==1 # Tiall region
next 0
}
})
MultipleForms.copy(:PIKACHU,:EXEGGCUTE,:CUBONE)

View File

@@ -0,0 +1,110 @@
#===============================================================================
# Mega Evolution
# NOTE: These are treated as form changes in Essentials.
#===============================================================================
class PokeBattle_Pokemon
def getMegaForm(checkItemOnly=false)
formData = pbLoadFormToSpecies
return 0 if !formData[@species] || formData[@species].length==0
ret = 0
speciesData = pbLoadSpeciesData
for i in 0...formData[@species].length
fSpec = formData[@species][i]
next if !fSpec || fSpec<=0
megaStone = speciesData[fSpec][SpeciesMegaStone] || 0
if megaStone>0 && self.hasItem?(megaStone)
ret = i; break
end
if !checkItemOnly
megaMove = speciesData[fSpec][SpeciesMegaMove] || 0
if megaMove>0 && self.hasMove?(megaMove)
ret = i; break
end
end
end
return ret # form number, or 0 if no accessible Mega form
end
def getUnmegaForm
return -1 if !mega?
unmegaForm = pbGetSpeciesData(@species,formSimple,SpeciesUnmegaForm)
return unmegaForm # form number
end
def hasMegaForm?
megaForm = self.getMegaForm
return megaForm>0 && megaForm!=self.formSimple
end
def mega?
megaForm = self.getMegaForm
return megaForm>0 && megaForm==self.formSimple
end
alias isMega? mega?
def makeMega
megaForm = self.getMegaForm
self.form = megaForm if megaForm>0
end
def makeUnmega
unmegaForm = self.getUnmegaForm
self.form = unmegaForm if unmegaForm>=0
end
def megaName
formName = pbGetMessage(MessageTypes::FormNames,self.fSpecies)
return (formName && formName!="") ? formName : _INTL("Mega {1}",PBSpecies.getName(@species))
end
def megaMessage # 0=default message, 1=Rayquaza message
return pbGetSpeciesData(@species,getMegaForm,SpeciesMegaMessage)
end
end
#===============================================================================
# Primal Reversion
# NOTE: These are treated as form changes in Essentials.
#===============================================================================
class PokeBattle_Pokemon
def hasPrimalForm?
v = MultipleForms.call("getPrimalForm",self)
return v!=nil
end
def primal?
v = MultipleForms.call("getPrimalForm",self)
return v!=nil && v==@form
end
alias isPrimal? primal?
def makePrimal
v = MultipleForms.call("getPrimalForm",self)
self.form = v if v!=nil
end
def makeUnprimal
v = MultipleForms.call("getUnprimalForm",self)
if v!=nil; self.form = v
elsif primal?; self.form = 0
end
end
end
MultipleForms.register(:GROUDON,{
"getPrimalForm" => proc { |pkmn|
next 1 if isConst?(pkmn.item,PBItems,:REDORB)
next
}
})
MultipleForms.register(:KYOGRE,{
"getPrimalForm" => proc { |pkmn|
next 1 if isConst?(pkmn.item,PBItems,:BLUEORB)
next
}
})

View File

@@ -0,0 +1,708 @@
=begin
All types except Shadow have Shadow as a weakness.
Shadow has Shadow as a resistance.
On a side note, the Shadow moves in Colosseum will not be affected by Weaknesses
or Resistances, while in XD the Shadow-type is Super-Effective against all other
types.
2/5 - display nature
XD - Shadow Rush -- 55, 100 - Deals damage.
Colosseum - Shadow Rush -- 90, 100
If this attack is successful, user loses half of HP lost by opponent due to this
attack (recoil). If user is in Hyper Mode, this attack has a good chance for a
critical hit.
=end
#===============================================================================
# Purify a Shadow Pokémon.
#===============================================================================
def pbPurify(pokemon,scene)
return if pokemon.heartgauge!=0 || !pokemon.shadow
return if !pokemon.savedev && !pokemon.savedexp
pokemon.shadow = false
pokemon.giveRibbon(PBRibbons::NATIONAL)
scene.pbDisplay(_INTL("{1} opened the door to its heart!",pokemon.name))
oldmoves = []
for i in 0...4; oldmoves.push(pokemon.moves[i].id); end
pokemon.pbUpdateShadowMoves
for i in 0...4
next if pokemon.moves[i].id<=0 || pokemon.moves[i].id==oldmoves[i]
scene.pbDisplay(_INTL("{1} regained the move \n{2}!",
pokemon.name,PBMoves.getName(pokemon.moves[i].id)))
end
pokemon.pbRecordFirstMoves
if pokemon.savedev
for i in 0...6
pbApplyEVGain(pokemon,i,pokemon.savedev[i])
end
pokemon.savedev = nil
end
newexp = PBExperience.pbAddExperience(pokemon.exp,pokemon.savedexp||0,pokemon.growthrate)
pokemon.savedexp = nil
newlevel = PBExperience.pbGetLevelFromExperience(newexp,pokemon.growthrate)
curlevel = pokemon.level
if newexp!=pokemon.exp
scene.pbDisplay(_INTL("{1} regained {2} Exp. Points!",pokemon.name,newexp-pokemon.exp))
end
if newlevel==curlevel
pokemon.exp = newexp
pokemon.calcStats
else
pbChangeLevel(pokemon,newlevel,scene) # for convenience
pokemon.exp = newexp
end
speciesname = PBSpecies.getName(pokemon.species)
if scene.pbConfirm(_INTL("Would you like to give a nickname to {1}?",speciesname))
newname = pbEnterPokemonName(_INTL("{1}'s nickname?",speciesname),
0,PokeBattle_Pokemon::MAX_POKEMON_NAME_SIZE,"",pokemon)
pokemon.name = newname if newname!=""
end
end
def pbApplyEVGain(pokemon,ev,evgain)
totalev = 0
for i in 0...6
totalev += pokemon.ev[i]
end
if totalev+evgain>PokeBattle_Pokemon::EV_LIMIT # Can't exceed overall limit
evgain -= totalev+evgain-PokeBattle_Pokemon::EV_LIMIT
end
if pokemon.ev[ev]+evgain>PokeBattle_Pokemon::EV_STAT_LIMIT
evgain -= totalev+evgain-PokeBattle_Pokemon::EV_STAT_LIMIT
end
if evgain>0
pokemon.ev[ev] += evgain
end
end
def pbReplaceMoves(pokemon,move1,move2=0,move3=0,move4=0)
return if !pokemon
[move1,move2,move3,move4].each { |move|
moveIndex = -1
if move!=0
# Look for given move
for i in 0...4
moveIndex = i if pokemon.moves[i].id==move
end
end
if moveIndex==-1
# Look for slot to replace move
for i in 0...4
if (pokemon.moves[i].id==0 && move!=0) || (
pokemon.moves[i].id!=move1 &&
pokemon.moves[i].id!=move2 &&
pokemon.moves[i].id!=move3 &&
pokemon.moves[i].id!=move4)
# Replace move
pokemon.moves[i] = PBMove.new(move)
break
end
end
end
}
end
#===============================================================================
# Relic Stone scene.
#===============================================================================
class RelicStoneScene
def pbPurify
end
def pbUpdate
pbUpdateSpriteHash(@sprites)
end
def pbEndScene
pbFadeOutAndHide(@sprites) { pbUpdate }
pbDisposeSpriteHash(@sprites)
@viewport.dispose
end
def pbDisplay(msg,brief=false)
UIHelper.pbDisplay(@sprites["msgwindow"],msg,brief) { pbUpdate }
end
def pbConfirm(msg)
UIHelper.pbConfirm(@sprites["msgwindow"],msg) { pbUpdate }
end
def pbStartScene(pokemon)
@sprites = {}
@viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
@viewport.z = 99999
@pokemon = pokemon
addBackgroundPlane(@sprites,"bg","relicstonebg",@viewport)
@sprites["msgwindow"] = Window_AdvancedTextPokemon.new("")
@sprites["msgwindow"].viewport = @viewport
@sprites["msgwindow"].x = 0
@sprites["msgwindow"].y = Graphics.height-96
@sprites["msgwindow"].width = Graphics.width
@sprites["msgwindow"].height = 96
@sprites["msgwindow"].text = ""
@sprites["msgwindow"].visible = true
pbDeactivateWindows(@sprites)
pbFadeInAndShow(@sprites) { pbUpdate }
end
end
class RelicStoneScreen
def initialize(scene)
@scene = scene
end
def pbDisplay(x)
@scene.pbDisplay(x)
end
def pbConfirm(x)
@scene.pbConfirm(x)
end
def pbRefresh
end
def pbStartScreen(pokemon)
@scene.pbStartScene(pokemon)
@scene.pbPurify
pbPurify(pokemon,self)
@scene.pbEndScene
end
end
def pbRelicStoneScreen(pkmn)
retval = true
pbFadeOutIn {
scene = RelicStoneScene.new
screen = RelicStoneScreen.new(scene)
retval = screen.pbStartScreen(pkmn)
}
return retval
end
#===============================================================================
#
#===============================================================================
def pbIsPurifiable?(pkmn)
return false if !pkmn
return false if isConst?(pkmn.species,PBSpecies,:LUGIA)
return false if !pkmn.shadowPokemon? || pkmn.heartgauge>0
return true
end
def pbHasPurifiableInParty?
return $Trainer.party.any? { |pkmn| pbIsPurifiable?(pkmn) }
end
def pbRelicStone
if !pbHasPurifiableInParty?
pbMessage(_INTL("You have no Pokémon that can be purified."))
return
end
pbMessage(_INTL("There's a Pokémon that may open the door to its heart!"))
# Choose a purifiable Pokemon
pbChoosePokemon(1,2,proc { |pkmn|
!pkmn.egg? && pkmn.hp>0 && pkmn.shadowPokemon? && pkmn.heartgauge==0
})
if $game_variables[1]>=0
pbRelicStoneScreen($Trainer.party[$game_variables[1]])
end
end
def pbReadyToPurify(pkmn)
return unless pkmn && pkmn.shadowPokemon?
pkmn.pbUpdateShadowMoves
if pkmn.heartgauge==0
pbMessage(_INTL("{1} can now be purified!",pkmn.name))
end
end
#===============================================================================
# Pokémon class.
#===============================================================================
class PokeBattle_Pokemon
attr_accessor :heartgauge
attr_accessor :shadow
attr_accessor :hypermode
attr_accessor :savedev
attr_accessor :savedexp
attr_accessor :shadowmoves
attr_accessor :shadowmovenum
HEARTGAUGESIZE = 3840
alias :__shadow_expeq :exp=
def exp=(value)
if shadowPokemon?
@savedexp += value-self.exp
else
__shadow_expeq(value)
end
end
alias :__shadow_hpeq :hp=
def hp=(value)
__shadow_hpeq(value)
@hypermode = false if value<=0
end
def hypermode
return (self.heartgauge==0 || self.hp==0) ? false : @hypermode
end
def heartgauge
@heartgauge = 0 if !@heartgauge
return @heartgauge
end
def heartStage
return 0 if !@shadow
hg = HEARTGAUGESIZE/5.0
return ([self.heartgauge,HEARTGAUGESIZE].min/hg).ceil
end
def adjustHeart(value)
return if !@shadow
@heartgauge = 0 if !@heartgauge
@heartgauge += value
@heartgauge = HEARTGAUGESIZE if @heartgauge>HEARTGAUGESIZE
@heartgauge = 0 if @heartgauge<0
end
def shadowPokemon?
return @shadow && @heartgauge && @heartgauge>=0
end
alias :isShadow? :shadowPokemon?
def makeShadow
self.shadow = true
self.heartgauge = HEARTGAUGESIZE
self.savedexp = 0
self.savedev = [0,0,0,0,0,0]
self.shadowmoves = [0,0,0,0,0,0,0,0]
# Retrieve shadow moves
moves = pbLoadShadowMovesets
if moves[self.species] && moves[self.species].length>0
for i in 0...[4,moves[self.species].length].min
self.shadowmoves[i] = moves[self.species][i]
end
self.shadowmovenum = moves[self.species].length
else
# No special shadow moves
self.shadowmoves[0] = getConst(PBMoves,:SHADOWRUSH) || 0
self.shadowmovenum = 1
end
for i in 0...4 # Save old moves
self.shadowmoves[4+i] = self.moves[i].id
end
pbUpdateShadowMoves
end
def pbUpdateShadowMoves(allmoves=false)
return if !@shadowmoves
m = @shadowmoves
if !@shadow
# No shadow moves
pbReplaceMoves(self,m[4],m[5],m[6],m[7])
@shadowmoves = nil
else
moves = []
relearning = (allmoves) ? 3 : [3,3,2,1,1,0][self.heartStage]
relearned = 0
# Add all Shadow moves
for i in 0...4; moves.push(m[i]) if m[i]!=0; end
# Add X regular moves
for i in 0...4
next if i<@shadowmovenum
if m[i+4]!=0 && relearned<relearning
moves.push(m[i+4]); relearned += 1
end
end
pbReplaceMoves(self,moves[0] || 0,moves[1] || 0,moves[2] || 0,moves[3] || 0)
end
end
alias :__shadow_clone :clone
def clone
ret = __shadow_clone
ret.savedev = self.savedev.clone if self.savedev
ret.shadowmoves = self.shadowmoves.clone if self.shadowmoves
return ret
end
end
#===============================================================================
# Shadow Pokémon in battle.
#===============================================================================
class PokeBattle_Battle
alias __shadow__pbCanUseItemOnPokemon? pbCanUseItemOnPokemon?
def pbCanUseItemOnPokemon?(item,pkmn,battler,scene,showMessages=true)
ret = __shadow__pbCanUseItemOnPokemon?(item,pkmn,battler,scene,showMessages)
if ret && pkmn.hypermode &&
!isConst?(item,PBItems,:JOYSCENT) &&
!isConst?(item,PBItems,:EXCITESCENT) &&
!isConst?(item,PBItems,:VIVIDSCENT)
scene.pbDisplay(_INTL("This item can't be used on that Pokémon."))
return false
end
return ret
end
end
class PokeBattle_Battler
alias __shadow__pbInitPokemon pbInitPokemon
def pbInitPokemon(*arg)
if self.pokemonIndex>0 && inHyperMode?
# Called out of Hyper Mode
self.pokemon.hypermode = false
self.pokemon.adjustHeart(-50)
end
__shadow__pbInitPokemon(*arg)
# Called into battle
if shadowPokemon?
if hasConst?(PBTypes,:SHADOW)
self.type1 = getID(PBTypes,:SHADOW)
self.type2 = getID(PBTypes,:SHADOW)
end
self.pokemon.adjustHeart(-30) if pbOwnedByPlayer?
end
end
def shadowPokemon?
p = self.pokemon
return p && p.respond_to?("shadowPokemon?") && p.shadowPokemon?
end
alias isShadow? shadowPokemon?
def inHyperMode?
return false if fainted?
p = self.pokemon
return p && p.respond_to?("hypermode") && p.hypermode
end
def pbHyperMode
return if fainted? || !shadowPokemon? || inHyperMode?
p = self.pokemon
if @battle.pbRandom(p.heartgauge)<=PokeBattle_Pokemon::HEARTGAUGESIZE/4
p.hypermode = true
@battle.pbDisplay(_INTL("{1}'s emotions rose to a fever pitch!\nIt entered Hyper Mode!",self.pbThis))
end
end
def pbHyperModeObedience(move)
return true if !inHyperMode?
return true if !move || isConst?(move.type,PBTypes,:SHADOW)
return rand(100)<20
end
end
#===============================================================================
# Shadow item effects.
#===============================================================================
def pbRaiseHappinessAndReduceHeart(pokemon,scene,amount)
if !pokemon.shadowPokemon?
scene.pbDisplay(_INTL("It won't have any effect."))
return false
end
if pokemon.happiness==255 && pokemon.heartgauge==0
scene.pbDisplay(_INTL("It won't have any effect."))
return false
elsif pokemon.happiness==255
pokemon.adjustHeart(-amount)
scene.pbDisplay(_INTL("{1} adores you!\nThe door to its heart opened a little.",pokemon.name))
pbReadyToPurify(pokemon)
return true
elsif pokemon.heartgauge==0
pokemon.changeHappiness("vitamin")
scene.pbDisplay(_INTL("{1} turned friendly.",pokemon.name))
return true
else
pokemon.changeHappiness("vitamin")
pokemon.adjustHeart(-amount)
scene.pbDisplay(_INTL("{1} turned friendly.\nThe door to its heart opened a little.",pokemon.name))
pbReadyToPurify(pokemon)
return true
end
end
ItemHandlers::UseOnPokemon.add(:JOYSCENT,proc { |item,pokemon,scene|
pbRaiseHappinessAndReduceHeart(pokemon,scene,500)
})
ItemHandlers::UseOnPokemon.add(:EXCITESCENT,proc { |item,pokemon,scene|
pbRaiseHappinessAndReduceHeart(pokemon,scene,1000)
})
ItemHandlers::UseOnPokemon.add(:VIVIDSCENT,proc { |item,pokemon,scene|
pbRaiseHappinessAndReduceHeart(pokemon,scene,2000)
})
ItemHandlers::UseOnPokemon.add(:TIMEFLUTE,proc { |item,pokemon,scene|
if !pokemon.shadowPokemon?
scene.pbDisplay(_INTL("It won't have any effect."))
next false
end
pokemon.heartgauge = 0
pbReadyToPurify(pokemon)
next true
})
ItemHandlers::CanUseInBattle.add(:JOYSCENT,proc { |item,pokemon,battler,move,firstAction,battle,scene,showMessages|
if !battler || !battler.shadowPokemon? || !battler.inHyperMode?
scene.pbDisplay(_INTL("It won't have any effect.")) if showMessages
next false
end
next true
})
ItemHandlers::CanUseInBattle.copy(:JOYSCENT,:EXCITESCENT,:VIVIDSCENT)
ItemHandlers::BattleUseOnBattler.add(:JOYSCENT,proc { |item,battler,scene|
battler.pokemon.hypermode = false
battler.pokemon.adjustHeart(-500)
scene.pbDisplay(_INTL("{1} came to its senses from the {2}!",battler.pbThis,PBItems.getName(item)))
next true
})
ItemHandlers::BattleUseOnBattler.add(:EXCITESCENT,proc { |item,battler,scene|
battler.pokemon.hypermode = false
battler.pokemon.adjustHeart(-1000)
scene.pbDisplay(_INTL("{1} came to its senses from the {2}!",battler.pbThis,PBItems.getName(item)))
next true
})
ItemHandlers::BattleUseOnBattler.add(:VIVIDSCENT,proc { |item,battler,scene|
battler.pokemon.hypermode = false
battler.pokemon.adjustHeart(-2000)
scene.pbDisplay(_INTL("{1} came to its senses from the {2}!",battler.pbThis,PBItems.getName(item)))
next true
})
#===============================================================================
# No additional effect. (Shadow Blast, Shadow Blitz, Shadow Break, Shadow Rave,
# Shadow Rush, Shadow Wave)
#===============================================================================
class PokeBattle_Move_126 < PokeBattle_Move_000
end
#===============================================================================
# Paralyzes the target. (Shadow Bolt)
#===============================================================================
class PokeBattle_Move_127 < PokeBattle_Move_007
end
#===============================================================================
# Burns the target. (Shadow Fire)
#===============================================================================
class PokeBattle_Move_128 < PokeBattle_Move_00A
end
#===============================================================================
# Freezes the target. (Shadow Chill)
#===============================================================================
class PokeBattle_Move_129 < PokeBattle_Move_00C
end
#===============================================================================
# Confuses the target. (Shadow Panic)
#===============================================================================
class PokeBattle_Move_12A < PokeBattle_Move_013
end
#===============================================================================
# Decreases the target's Defense by 2 stages. (Shadow Down)
#===============================================================================
class PokeBattle_Move_12B < PokeBattle_Move_04C
end
#===============================================================================
# Decreases the target's evasion by 2 stages. (Shadow Mist)
#===============================================================================
class PokeBattle_Move_12C < PokeBattle_TargetStatDownMove
def initialize(battle,move)
super
@statDown = [PBStats::EVASION,2]
end
end
#===============================================================================
# Power is doubled if the target is using Dive. (Shadow Storm)
#===============================================================================
class PokeBattle_Move_12D < PokeBattle_Move_075
end
#===============================================================================
# Two turn attack. On first turn, halves the HP of all active Pokémon.
# Skips second turn (if successful). (Shadow Half)
#===============================================================================
class PokeBattle_Move_12E < PokeBattle_Move
def pbMoveFailed?(user,targets)
failed = true
@battle.eachBattler do |b|
next if b.hp==1
failed = false
break
end
if failed
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.eachBattler do |b|
next if b.hp==1
b.pbReduceHP(i.hp/2,false)
end
@battle.pbDisplay(_INTL("Each Pokémon's HP was halved!"))
@battle.eachBattler { |b| b.pbItemHPHealCheck }
user.effects[PBEffects::HyperBeam] = 2
user.currentMove = @id
end
end
#===============================================================================
# Target can no longer switch out or flee, as long as the user remains active.
# (Shadow Hold)
#===============================================================================
class PokeBattle_Move_12F < PokeBattle_Move_0EF
end
#===============================================================================
# User takes recoil damage equal to 1/2 of its current HP. (Shadow End)
#===============================================================================
class PokeBattle_Move_130 < PokeBattle_RecoilMove
def pbRecoilDamage(user,target)
return (target.damageState.totalHPLost/2.0).round
end
def pbEffectAfterAllHits(user,target)
return if user.fainted? || target.damageState.unaffected
# NOTE: This move's recoil is not prevented by Rock Head/Magic Guard.
amt = pbRecoilDamage(user,target)
amt = 1 if amt<1
user.pbReduceHP(amt,false)
@battle.pbDisplay(_INTL("{1} is damaged by recoil!",user.pbThis))
user.pbItemHPHealCheck
end
end
#===============================================================================
# Starts shadow weather. (Shadow Sky)
#===============================================================================
class PokeBattle_Move_131 < PokeBattle_WeatherMove
def initialize(battle,move)
super
@weatherType = PBWeather::ShadowSky
end
end
#===============================================================================
# Ends the effects of Light Screen, Reflect and Safeguard on both sides.
# (Shadow Shed)
#===============================================================================
class PokeBattle_Move_132 < PokeBattle_Move
def pbEffectGeneral(user)
for i in @battle.sides
i.effects[PBEffects::AuroraVeil] = 0
i.effects[PBEffects::Reflect] = 0
i.effects[PBEffects::LightScreen] = 0
i.effects[PBEffects::Safeguard] = 0
end
@battle.pbDisplay(_INTL("It broke all barriers!"))
end
end
#===============================================================================
#
#===============================================================================
class PokemonTemp
attr_accessor :heartgauges
end
Events.onStartBattle += proc { |sender|
# Record current heart gauges of Pokémon in party, to see if they drop to zero
# during battle and need to say they're ready to be purified afterwards
$PokemonTemp.heartgauges = []
for i in 0...$Trainer.party.length
$PokemonTemp.heartgauges[i] = $Trainer.party[i].heartgauge
end
}
Events.onEndBattle += proc { |sender,e|
decision = e[0]
canLose = e[1]
for i in 0...$PokemonTemp.heartgauges.length
pokemon = $Trainer.party[i]
if pokemon && $PokemonTemp.heartgauges[i] &&
$PokemonTemp.heartgauges[i]!=0 && pokemon.heartgauge==0
pbReadyToPurify(pokemon)
end
end
}
Events.onStepTaken += proc {
for pkmn in $Trainer.ablePokemonParty
if pkmn.heartgauge>0
pkmn.adjustHeart(-1)
pbReadyToPurify(pkmn) if pkmn.heartgauge==0
end
end
if ($PokemonGlobal.purifyChamber rescue nil)
$PokemonGlobal.purifyChamber.update
end
for i in 0...2
pkmn = $PokemonGlobal.daycare[i][0]
next if !pkmn
pkmn.adjustHeart(-1)
pkmn.pbUpdateShadowMoves
end
}

View File

@@ -0,0 +1,334 @@
module PBEvolution
None = 0 # Do not use
Happiness = 1
HappinessDay = 2
HappinessNight = 3
Level = 4
Trade = 5
TradeItem = 6
Item = 7
AttackGreater = 8
AtkDefEqual = 9
DefenseGreater = 10
Silcoon = 11
Cascoon = 12
Ninjask = 13
Shedinja = 14
Beauty = 15
ItemMale = 16
ItemFemale = 17
DayHoldItem = 18
NightHoldItem = 19
HasMove = 20
HasInParty = 21
LevelMale = 22
LevelFemale = 23
Location = 24
TradeSpecies = 25
LevelDay = 26
LevelNight = 27
LevelDarkInParty = 28
LevelRain = 29
HappinessMoveType = 30
LevelEvening = 31
Custom1 = 32
Custom2 = 33
Custom3 = 34
Custom4 = 35
EVONAMES = ["None",
"Happiness", "HappinessDay", "HappinessNight", "Level", "Trade",
"TradeItem", "Item", "AttackGreater", "AtkDefEqual", "DefenseGreater",
"Silcoon", "Cascoon", "Ninjask", "Shedinja", "Beauty",
"ItemMale", "ItemFemale", "DayHoldItem", "NightHoldItem", "HasMove",
"HasInParty", "LevelMale", "LevelFemale", "Location", "TradeSpecies",
"LevelDay", "LevelNight", "LevelDarkInParty", "LevelRain", "HappinessMoveType",
"LevelEvening", "Custom1", "Custom2", "Custom3", "Custom4",
]
# 0 = no parameter
# 1 = Positive integer
# 2 = Item internal name
# 3 = Move internal name
# 4 = Species internal name
# 5 = Type internal name
# 6 = Ability internal name
EVOPARAM = [0, # None (do not use)
0,0,0,1,0, # Happiness, HappinessDay, HappinessNight, Level, Trade
2,2,1,1,1, # TradeItem, Item, AttackGreater, AtkDefEqual, DefenseGreater
1,1,1,1,1, # Silcoon, Cascoon, Ninjask, Shedinja, Beauty
2,2,2,2,3, # ItemMale, ItemFemale, DayHoldItem, NightHoldItem, HasMove
4,1,1,1,4, # HasInParty, LevelMale, LevelFemale, Location, TradeSpecies
1,1,1,1,5, # LevelDay, LevelNight, LevelDarkInParty, LevelRain, HappinessMoveType
1,1,1,1,1 # LevelEvening, Custom 1-4
]
end
#===============================================================================
# Evolutions data cache
#===============================================================================
class PokemonTemp
attr_accessor :evolutionsData
end
def pbLoadEvolutionsData
$PokemonTemp = PokemonTemp.new if !$PokemonTemp
if !$PokemonTemp.evolutionsData
$PokemonTemp.evolutionsData = load_data("Data/species_evolutions.dat") || []
end
return $PokemonTemp.evolutionsData
end
def pbGetEvolutionData(species)
species = getID(PBSpecies,species)
evosData = pbLoadEvolutionsData
return evosData[species] || nil
end
alias __evolutionsData__pbClearData pbClearData
def pbClearData
$PokemonTemp.evolutionsData = nil if $PokemonTemp
__evolutionsData__pbClearData
end
#===============================================================================
# Evolution helper functions
#===============================================================================
def pbGetEvolvedFormData(species,ignoreNone=false)
ret = []
evoData = pbGetEvolutionData(species)
return ret if !evoData || evoData.length==0
evoData.each do |evo|
next if evo[3] # Is the prevolution
next if evo[1]==PBEvolution::None && ignoreNone
ret.push([evo[1],evo[2],evo[0]]) # [Method, parameter, species]
end
return ret
end
def pbGetPreviousForm(species) # Unused
evoData = pbGetEvolutionData(species)
return species if !evoData || evoData.length==0
evoData.each do |evo|
return evo[0] if evo[3] # Is the prevolution
end
return species
end
def pbGetBabySpecies(species,item1=-1,item2=-1)
ret = species
evoData = pbGetEvolutionData(species)
return ret if !evoData || evoData.length==0
evoData.each do |evo|
next if !evo[3]
if item1>=0 && item2>=0
incense = pbGetSpeciesData(evo[0],0,SpeciesIncense)
ret = evo[0] if item1==incense || item2==incense
else
ret = evo[0] # Species of prevolution
end
break
end
ret = pbGetBabySpecies(ret) if ret!=species
return ret
end
def pbGetMinimumLevel(species)
methodsWithMinLevel = [
PBEvolution::Level, PBEvolution::LevelMale, PBEvolution::LevelFemale,
PBEvolution::AttackGreater, PBEvolution::AtkDefEqual, PBEvolution::DefenseGreater,
PBEvolution::Silcoon, PBEvolution::Cascoon,
PBEvolution::Ninjask, PBEvolution::Shedinja,
PBEvolution::LevelDay, PBEvolution::LevelNight,
PBEvolution::LevelDarkInParty, PBEvolution::LevelRain
]
evoData = pbGetEvolutionData(species)
return 1 if !evoData || evoData.length==0
ret = -1
evoData.each do |evo|
if evo[3] && methodsWithMinLevel.include?(evo[1]) # Is the prevolution
ret = (ret<0) ? evo[2] : [ret,evo[2]].min
break
end
end
return (ret==-1) ? 1 : ret
end
def pbGetEvolutionFamilyData(species)
evos = pbGetEvolvedFormData(species,true)
return nil if evos.length==0
ret = []
for i in 0...evos.length
ret.push([species].concat(evos[i]))
evoData = pbGetEvolutionFamilyData(evos[i][2])
ret.concat(evoData) if evoData && evoData.length>0
end
return ret
end
# Used by the Moon Ball when checking if a Pokémon's evolution family includes
# an evolution that uses the Moon Stone.
def pbCheckEvolutionFamilyForMethod(species,method,param=-1)
species = pbGetBabySpecies(species)
evos = pbGetEvolutionFamilyData(species)
return false if !evos || evos.length==0
for evo in evos
if method.is_a?(Array)
next if !method.include?(evo[1])
elsif method>=0
next if evo[1]!=method
end
next if param>=0 && evo[2]!=param
return true
end
return false
end
def pbEvoDebug # Unused
evosData = pbLoadEvolutionsData
for species in 1..PBSpecies.maxValueF
echo PBSpecies.getName(pbGetSpeciesFromFSpecies(species)[0])+"\n"
next if !evosData[species] || evosData[species].length==0
for evo in evosData[species]
echo sprintf("name=%s, type=%s (%02X), level=%d, evo/prevo=%s",
PBSpecies.getName(evo[0]),getConstantName(PBEvolution,evo[1]),evo[1],evo[2],
(evo[3]) ? "prevolution" : "evolution")+"\n"
end
end
echo "end\n"
end
#===============================================================================
# Evolution methods
#===============================================================================
def pbMiniCheckEvolution(pokemon,evonib,level,poke)
case evonib
when PBEvolution::Happiness
return poke if pokemon.happiness>=220
when PBEvolution::HappinessDay
return poke if pokemon.happiness>=220 && PBDayNight.isDay?
when PBEvolution::HappinessNight
return poke if pokemon.happiness>=220 && PBDayNight.isNight?
when PBEvolution::HappinessMoveType
if pokemon.happiness>=220
for m in pokemon.moves
return poke if m.id>0 && m.type==level
end
end
when PBEvolution::Level
return poke if pokemon.level>=level
when PBEvolution::LevelDay
return poke if pokemon.level>=level && PBDayNight.isDay?
when PBEvolution::LevelNight
return poke if pokemon.level>=level && PBDayNight.isNight?
when PBEvolution::LevelEvening
return poke if pokemon.level>=level && PBDayNight.isEvening?
when PBEvolution::LevelMale
return poke if pokemon.level>=level && pokemon.male?
when PBEvolution::LevelFemale
return poke if pokemon.level>=level && pokemon.female?
when PBEvolution::AttackGreater # Hitmonlee
return poke if pokemon.level>=level && pokemon.attack>pokemon.defense
when PBEvolution::AtkDefEqual # Hitmontop
return poke if pokemon.level>=level && pokemon.attack==pokemon.defense
when PBEvolution::DefenseGreater # Hitmonchan
return poke if pokemon.level>=level && pokemon.attack<pokemon.defense
when PBEvolution::Silcoon
return poke if pokemon.level>=level && (((pokemon.personalID>>16)&0xFFFF)%10)<5
when PBEvolution::Cascoon
return poke if pokemon.level>=level && (((pokemon.personalID>>16)&0xFFFF)%10)>=5
when PBEvolution::Ninjask
return poke if pokemon.level>=level
when PBEvolution::Shedinja
return -1
when PBEvolution::DayHoldItem
return poke if pokemon.item==level && PBDayNight.isDay?
when PBEvolution::NightHoldItem
return poke if pokemon.item==level && PBDayNight.isNight?
when PBEvolution::HasMove
for m in pokemon.moves
return poke if m.id==level
end
when PBEvolution::HasInParty
for i in $Trainer.pokemonParty
return poke if i.species==level
end
when PBEvolution::LevelDarkInParty
if pokemon.level>=level
for i in $Trainer.pokemonParty
return poke if i.hasType?(:DARK)
end
end
when PBEvolution::Location
return poke if $game_map.map_id==level
when PBEvolution::LevelRain
if pokemon.level>=level
if $game_screen && ($game_screen.weather_type==PBFieldWeather::Rain ||
$game_screen.weather_type==PBFieldWeather::HeavyRain ||
$game_screen.weather_type==PBFieldWeather::Storm)
return poke
end
end
when PBEvolution::Beauty # Feebas
return poke if pokemon.beauty>=level
when PBEvolution::Trade, PBEvolution::TradeItem, PBEvolution::TradeSpecies
return -1
when PBEvolution::Custom1
# Add code for custom evolution type 1
when PBEvolution::Custom2
# Add code for custom evolution type 2
when PBEvolution::Custom3
# Add code for custom evolution type 3
when PBEvolution::Custom4
# Add code for custom evolution type 4
end
return -1
end
def pbMiniCheckEvolutionItem(pokemon,evonib,level,poke,item)
# Checks for when an item is used on the Pokémon (e.g. an evolution stone)
case evonib
when PBEvolution::Item
return poke if level==item
when PBEvolution::ItemMale
return poke if level==item && pokemon.male?
when PBEvolution::ItemFemale
return poke if level==item && pokemon.female?
end
return -1
end
# Checks whether a Pokemon can evolve now. If a block is given, calls the block
# with the following parameters:
# Pokemon to check; evolution type; level or other parameter; ID of the new species
def pbCheckEvolutionEx(pokemon)
return -1 if pokemon.species<=0 || pokemon.egg? || pokemon.shadowPokemon?
return -1 if isConst?(pokemon.item,PBItems,:EVERSTONE)
return -1 if isConst?(pokemon.ability,PBAbilities,:BATTLEBOND)
ret = -1
for form in pbGetEvolvedFormData(pbGetFSpeciesFromForm(pokemon.species,pokemon.form),true)
ret = yield pokemon,form[0],form[1],form[2]
break if ret>0
end
return ret
end
# Checks whether a Pokemon can evolve now. If an item is used on the Pokémon,
# checks whether the Pokemon can evolve with the given item.
def pbCheckEvolution(pokemon,item=0)
if item==0
return pbCheckEvolutionEx(pokemon) { |pokemon,evonib,level,poke|
next pbMiniCheckEvolution(pokemon,evonib,level,poke)
}
else
return pbCheckEvolutionEx(pokemon) { |pokemon,evonib,level,poke|
next pbMiniCheckEvolutionItem(pokemon,evonib,level,poke,item)
}
end
end

View File

@@ -0,0 +1,49 @@
class PokeBattle_Pokemon
attr_accessor :chatter
end
def pbChatter(pokemon)
iconwindow=PictureWindow.new(pbLoadPokemonBitmap(pokemon))
iconwindow.x=(Graphics.width/2)-(iconwindow.width/2)
iconwindow.y=((Graphics.height-96)/2)-(iconwindow.height/2)
if pokemon.chatter
pbMessage(_INTL("It will forget the song it knows.\1"))
if !pbConfirmMessage(_INTL("Are you sure you want to change it?"))
iconwindow.dispose
return
end
end
if pbConfirmMessage(_INTL("Do you want to change its song now?"))
wave=pbRecord(nil,5)
if wave
pokemon.chatter=wave
pbMessage(_INTL("{1} learned a new song!",pokemon.name))
end
end
iconwindow.dispose
return
end
HiddenMoveHandlers::CanUseMove.add(:CHATTER,proc { |move,pkmn,showmsg|
next true
})
HiddenMoveHandlers::UseMove.add(:CHATTER,proc { |move,pokemon|
pbChatter(pokemon)
next true
})
class PokeBattle_Scene
def pbChatter(user,target)
pbPlayCry(user.pokemon,90,100) if user.pokemon
Graphics.frame_rate.times do
Graphics.update
Input.update
end
end
end

View File

@@ -0,0 +1,364 @@
#===============================================================================
# Pokémon sprite (used out of battle)
#===============================================================================
class PokemonSprite < SpriteWrapper
def initialize(viewport=nil)
super(viewport)
@_iconbitmap = nil
end
def dispose
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap = nil
self.bitmap = nil if !self.disposed?
super
end
def clearBitmap
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap = nil
self.bitmap = nil
end
def setOffset(offset=PictureOrigin::Center)
@offset = offset
changeOrigin
end
def changeOrigin
return if !self.bitmap
@offset = PictureOrigin::Center if !@offset
case @offset
when PictureOrigin::TopLeft, PictureOrigin::Left, PictureOrigin::BottomLeft
self.ox = 0
when PictureOrigin::Top, PictureOrigin::Center, PictureOrigin::Bottom
self.ox = self.bitmap.width/2
when PictureOrigin::TopRight, PictureOrigin::Right, PictureOrigin::BottomRight
self.ox = self.bitmap.width
end
case @offset
when PictureOrigin::TopLeft, PictureOrigin::Top, PictureOrigin::TopRight
self.oy = 0
when PictureOrigin::Left, PictureOrigin::Center, PictureOrigin::Right
self.oy = self.bitmap.height/2
when PictureOrigin::BottomLeft, PictureOrigin::Bottom, PictureOrigin::BottomRight
self.oy = self.bitmap.height
end
end
def setPokemonBitmap(pokemon,back=false)
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap = (pokemon) ? pbLoadPokemonBitmap(pokemon,back) : nil
self.bitmap = (@_iconbitmap) ? @_iconbitmap.bitmap : nil
self.color = Color.new(0,0,0,0)
changeOrigin
end
def setPokemonBitmapSpecies(pokemon,species,back=false)
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap = (pokemon) ? pbLoadPokemonBitmapSpecies(pokemon,species,back) : nil
self.bitmap = (@_iconbitmap) ? @_iconbitmap.bitmap : nil
changeOrigin
end
def setSpeciesBitmap(species,female=false,form=0,shiny=false,shadow=false,back=false,egg=false)
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap = pbLoadSpeciesBitmap(species,female,form,shiny,shadow,back,egg)
self.bitmap = (@_iconbitmap) ? @_iconbitmap.bitmap : nil
changeOrigin
end
def update
super
if @_iconbitmap
@_iconbitmap.update
self.bitmap = @_iconbitmap.bitmap
end
end
end
#===============================================================================
# Pokémon icon (for defined Pokémon)
#===============================================================================
class PokemonIconSprite < SpriteWrapper
attr_accessor :selected
attr_accessor :active
attr_reader :pokemon
def initialize(pokemon,viewport=nil)
super(viewport)
@selected = false
@active = false
@numFrames = 0
@currentFrame = 0
@counter = 0
self.pokemon = pokemon
@logical_x = 0 # Actual x coordinate
@logical_y = 0 # Actual y coordinate
@adjusted_x = 0 # Offset due to "jumping" animation in party screen
@adjusted_y = 0 # Offset due to "jumping" animation in party screen
end
def dispose
@animBitmap.dispose if @animBitmap
super
end
def x; return @logical_x; end
def y; return @logical_y; end
def x=(value)
@logical_x = value
super(@logical_x+@adjusted_x)
end
def y=(value)
@logical_y = value
super(@logical_y+@adjusted_y)
end
def pokemon=(value)
@pokemon = value
@animBitmap.dispose if @animBitmap
@animBitmap = nil
if !@pokemon
self.bitmap = nil
@currentFrame = 0
@counter = 0
return
end
@animBitmap = AnimatedBitmap.new(pbPokemonIconFile(value))
self.bitmap = @animBitmap.bitmap
self.src_rect.width = @animBitmap.height
self.src_rect.height = @animBitmap.height
@numFrames = @animBitmap.width/@animBitmap.height
@currentFrame = 0 if @currentFrame>=@numFrames
changeOrigin
end
def setOffset(offset=PictureOrigin::Center)
@offset = offset
changeOrigin
end
def changeOrigin
return if !self.bitmap
@offset = PictureOrigin::TopLeft if !@offset
case @offset
when PictureOrigin::TopLeft, PictureOrigin::Left, PictureOrigin::BottomLeft
self.ox = 0
when PictureOrigin::Top, PictureOrigin::Center, PictureOrigin::Bottom
self.ox = self.src_rect.width/2
when PictureOrigin::TopRight, PictureOrigin::Right, PictureOrigin::BottomRight
self.ox = self.src_rect.width
end
case @offset
when PictureOrigin::TopLeft, PictureOrigin::Top, PictureOrigin::TopRight
self.oy = 0
when PictureOrigin::Left, PictureOrigin::Center, PictureOrigin::Right
# NOTE: This assumes the top quarter of the icon is blank, so oy is placed
# in the middle of the lower three quarters of the image.
self.oy = self.src_rect.height*5/8
when PictureOrigin::BottomLeft, PictureOrigin::Bottom, PictureOrigin::BottomRight
self.oy = self.src_rect.height
end
end
# How long to show each frame of the icon for
def counterLimit
return 0 if @pokemon.fainted? # Fainted - no animation
# ret is initially the time a whole animation cycle lasts. It is divided by
# the number of frames in that cycle at the end.
ret = Graphics.frame_rate/4 # Green HP - 0.25 seconds
if @pokemon.hp<=@pokemon.totalhp/4; ret *= 4 # Red HP - 1 second
elsif @pokemon.hp<=@pokemon.totalhp/2; ret *= 2 # Yellow HP - 0.5 seconds
end
ret /= @numFrames
ret = 1 if ret<1
return ret
end
def update
return if !@animBitmap
super
@animBitmap.update
self.bitmap = @animBitmap.bitmap
# Update animation
cl = self.counterLimit
if cl==0
@currentFrame = 0
else
@counter += 1
if @counter>=cl
@currentFrame = (@currentFrame+1)%@numFrames
@counter = 0
end
end
self.src_rect.x = self.src_rect.width*@currentFrame
# Update "jumping" animation (used in party screen)
if @selected
@adjusted_x = 4
@adjusted_y = (@currentFrame>=@numFrames/2) ? -2 : 6
else
@adjusted_x = 0
@adjusted_y = 0
end
self.x = self.x
self.y = self.y
end
end
#===============================================================================
# Pokémon icon (for species)
#===============================================================================
class PokemonSpeciesIconSprite < SpriteWrapper
attr_reader :species
attr_reader :gender
attr_reader :form
attr_reader :shiny
def initialize(species,viewport=nil)
super(viewport)
@species = species
@gender = 0
@form = 0
@shiny = 0
@numFrames = 0
@currentFrame = 0
@counter = 0
refresh
end
def dispose
@animBitmap.dispose if @animBitmap
super
end
def species=(value)
@species = value
refresh
end
def gender=(value)
@gender = value
refresh
end
def form=(value)
@form = value
refresh
end
def shiny=(value)
@shiny = value
refresh
end
def pbSetParams(species,gender,form,shiny=false)
@species = species
@gender = gender
@form = form
@shiny = shiny
refresh
end
def setOffset(offset=PictureOrigin::Center)
@offset = offset
changeOrigin
end
def changeOrigin
return if !self.bitmap
@offset = PictureOrigin::TopLeft if !@offset
case @offset
when PictureOrigin::TopLeft, PictureOrigin::Left, PictureOrigin::BottomLeft
self.ox = 0
when PictureOrigin::Top, PictureOrigin::Center, PictureOrigin::Bottom
self.ox = self.src_rect.width/2
when PictureOrigin::TopRight, PictureOrigin::Right, PictureOrigin::BottomRight
self.ox = self.src_rect.width
end
case @offset
when PictureOrigin::TopLeft, PictureOrigin::Top, PictureOrigin::TopRight
self.oy = 0
when PictureOrigin::Left, PictureOrigin::Center, PictureOrigin::Right
# NOTE: This assumes the top quarter of the icon is blank, so oy is placed
# in the middle of the lower three quarters of the image.
self.oy = self.src_rect.height*5/8
when PictureOrigin::BottomLeft, PictureOrigin::Bottom, PictureOrigin::BottomRight
self.oy = self.src_rect.height
end
end
# How long to show each frame of the icon for
def counterLimit
# ret is initially the time a whole animation cycle lasts. It is divided by
# the number of frames in that cycle at the end.
ret = Graphics.frame_rate/4 # 0.25 seconds
ret /= @numFrames
ret = 1 if ret<1
return ret
end
def refresh
@animBitmap.dispose if @animBitmap
@animBitmap = nil
bitmapFileName = pbCheckPokemonIconFiles([@species,(@gender==1),@shiny,@form,false])
@animBitmap = AnimatedBitmap.new(bitmapFileName)
self.bitmap = @animBitmap.bitmap
self.src_rect.width = @animBitmap.height
self.src_rect.height = @animBitmap.height
@numFrames = @animBitmap.width/@animBitmap.height
@currentFrame = 0 if @currentFrame>=@numFrames
changeOrigin
end
def update
return if !@animBitmap
super
@animBitmap.update
self.bitmap = @animBitmap.bitmap
# Update animation
@counter += 1
if @counter>=self.counterLimit
@currentFrame = (@currentFrame+1)%@numFrames
@counter = 0
end
self.src_rect.x = self.src_rect.width*@currentFrame
end
end
#===============================================================================
# Sprite position adjustments
#===============================================================================
def pbApplyBattlerMetricsToSprite(sprite,index,species,shadow=false,metrics=nil)
metrics = pbLoadSpeciesMetrics if !metrics
if shadow
if (index&1)==1 # Foe Pokémon
sprite.x += (metrics[MetricBattlerShadowX][species] || 0)*2
end
else
if (index&1)==0 # Player's Pokémon
sprite.x += (metrics[MetricBattlerPlayerX][species] || 0)*2
sprite.y += (metrics[MetricBattlerPlayerY][species] || 0)*2
else # Foe Pokémon
sprite.x += (metrics[MetricBattlerEnemyX][species] || 0)*2
sprite.y += (metrics[MetricBattlerEnemyY][species] || 0)*2
sprite.y -= (metrics[MetricBattlerAltitude][species] || 0)*2
end
end
end
# NOTE: The species parameter here is typically the fSpecies, which contains
# information about both the species and the form.
def showShadow?(species)
return true
# metrics = pbLoadSpeciesMetrics
# return (metrics[MetricBattlerAltitude][species] || 0)>0
end

View File

@@ -0,0 +1,390 @@
class PokemonBox
attr_reader :pokemon
attr_accessor :name
attr_accessor :background
def initialize(name,maxPokemon=30)
@pokemon = []
@name = name
@background = 0
for i in 0...maxPokemon
@pokemon[i] = nil
end
end
def length
return @pokemon.length
end
def nitems
return @pokemon.nitems
end
def full?
return (@pokemon.nitems==self.length)
end
def empty?
return (@pokemon.nitems==0)
end
def [](i)
return @pokemon[i]
end
def []=(i,value)
@pokemon[i] = value
end
def each
@pokemon.each { |item| yield item }
end
def clear
@pokemon.clear
end
end
class PokemonStorage
attr_reader :boxes
attr_accessor :currentBox
attr_writer :unlockedWallpapers
BASICWALLPAPERQTY = 16
def initialize(maxBoxes=NUM_STORAGE_BOXES,maxPokemon=30)
@boxes = []
for i in 0...maxBoxes
@boxes[i] = PokemonBox.new(_INTL("Box {1}",i+1),maxPokemon)
@boxes[i].background = i%BASICWALLPAPERQTY
end
@currentBox = 0
@boxmode = -1
@unlockedWallpapers = []
for i in 0...allWallpapers.length
@unlockedWallpapers[i] = false
end
end
def allWallpapers
return [
# Basic wallpapers
_INTL("Forest"),_INTL("City"),_INTL("Desert"),_INTL("Savanna"),
_INTL("Crag"),_INTL("Volcano"),_INTL("Snow"),_INTL("Cave"),
_INTL("Beach"),_INTL("Seafloor"),_INTL("River"),_INTL("Sky"),
_INTL("Poké Center"),_INTL("Machine"),_INTL("Checks"),_INTL("Simple"),
# Special wallpapers
_INTL("Space"),_INTL("Backyard"),_INTL("Nostalgic 1"),_INTL("Torchic"),
_INTL("Trio 1"),_INTL("PikaPika 1"),_INTL("Legend 1"),_INTL("Team Galactic 1"),
_INTL("Distortion"),_INTL("Contest"),_INTL("Nostalgic 2"),_INTL("Croagunk"),
_INTL("Trio 2"),_INTL("PikaPika 2"),_INTL("Legend 2"),_INTL("Team Galactic 2"),
_INTL("Heart"),_INTL("Soul"),_INTL("Big Brother"),_INTL("Pokéathlon"),
_INTL("Trio 3"),_INTL("Spiky Pika"),_INTL("Kimono Girl"),_INTL("Revival")
]
end
def unlockedWallpapers
@unlockedWallpapers = [] if !@unlockedWallpapers
return @unlockedWallpapers
end
def isAvailableWallpaper?(i)
@unlockedWallpapers = [] if !@unlockedWallpapers
return true if i<BASICWALLPAPERQTY
return true if @unlockedWallpapers[i]
return false
end
def availableWallpapers
ret = [[],[]] # Names, IDs
papers = allWallpapers
@unlockedWallpapers = [] if !@unlockedWallpapers
for i in 0...papers.length
next if !isAvailableWallpaper?(i)
ret[0].push(papers[i]); ret[1].push(i)
end
return ret
end
def party
$Trainer.party
end
def party=(value)
raise ArgumentError.new("Not supported")
end
def maxBoxes
return @boxes.length
end
def maxPokemon(box)
return 0 if box>=self.maxBoxes
return (box<0) ? 6 : self[box].length
end
def full?
for i in 0...self.maxBoxes
return false if !@boxes[i].full?
end
return true
end
def pbFirstFreePos(box)
if box==-1
ret = self.party.nitems
return (ret==6) ? -1 : ret
else
for i in 0...maxPokemon(box)
return i if !self[box,i]
end
return -1
end
end
def [](x,y=nil)
if y==nil
return (x==-1) ? self.party : @boxes[x]
else
for i in @boxes
raise "Box is a Pokémon, not a box" if i.is_a?(PokeBattle_Pokemon)
end
return (x==-1) ? self.party[y] : @boxes[x][y]
end
end
def []=(x,y,value)
if x==-1
self.party[y] = value
else
@boxes[x][y] = value
end
end
def pbCopy(boxDst,indexDst,boxSrc,indexSrc)
if indexDst<0 && boxDst<self.maxBoxes
found = false
for i in 0...maxPokemon(boxDst)
next if self[boxDst,i]
found = true
indexDst = i
break
end
return false if !found
end
if boxDst==-1 # Copying into party
return false if self.party.nitems>=6
self.party[self.party.length] = self[boxSrc,indexSrc]
self.party.compact!
else # Copying into box
pkmn = self[boxSrc,indexSrc]
raise "Trying to copy nil to storage" if !pkmn
pkmn.formTime = nil if pkmn.respond_to?("formTime")
pkmn.form = 0 if isConst?(pkmn.species,PBSpecies,:SHAYMIN)
pkmn.heal
self[boxDst,indexDst] = pkmn
end
return true
end
def pbMove(boxDst,indexDst,boxSrc,indexSrc)
return false if !pbCopy(boxDst,indexDst,boxSrc,indexSrc)
pbDelete(boxSrc,indexSrc)
return true
end
def pbMoveCaughtToParty(pkmn)
return false if self.party.nitems>=6
self.party[self.party.length] = pkmn
end
def pbMoveCaughtToBox(pkmn,box)
for i in 0...maxPokemon(box)
if self[box,i]==nil
if box>=0
pkmn.formTime = nil if pkmn.respond_to?("formTime") && pkmn.formTime
pkmn.form = 0 if isConst?(pkmn.species,PBSpecies,:SHAYMIN)
pkmn.heal
end
self[box,i] = pkmn
return true
end
end
return false
end
def pbStoreCaught(pkmn)
if @currentBox>=0
pkmn.formTime = nil if pkmn.respond_to?("formTime")
pkmn.form = 0 if isConst?(pkmn.species,PBSpecies,:SHAYMIN)
pkmn.heal
end
for i in 0...maxPokemon(@currentBox)
if self[@currentBox,i]==nil
self[@currentBox,i] = pkmn
return @currentBox
end
end
for j in 0...self.maxBoxes
for i in 0...maxPokemon(j)
if self[j,i]==nil
self[j,i] = pkmn
@currentBox = j
return @currentBox
end
end
end
return -1
end
def pbDelete(box,index)
if self[box,index]
self[box,index] = nil
self.party.compact! if box==-1
end
end
def clear
for i in 0...self.maxBoxes
@boxes[i].clear
end
end
end
#===============================================================================
# Regional Storage scripts
#===============================================================================
class RegionalStorage
def initialize
@storages = []
@lastmap = -1
@rgnmap = -1
end
def getCurrentStorage
if !$game_map
raise _INTL("The player is not on a map, so the region could not be determined.")
end
if @lastmap!=$game_map.map_id
@rgnmap = pbGetCurrentRegion # may access file IO, so caching result
@lastmap = $game_map.map_id
end
if @rgnmap<0
raise _INTL("The current map has no region set. Please set the MapPosition metadata setting for this map.")
end
if !@storages[@rgnmap]
@storages[@rgnmap] = PokemonStorage.new
end
return @storages[@rgnmap]
end
def allWallpapers
return getCurrentStorage.allWallpapers
end
def availableWallpapers
return getCurrentStorage.availableWallpapers
end
def unlockWallpaper(index)
getCurrentStorage.unlockWallpaper(index)
end
def boxes
return getCurrentStorage.boxes
end
def party
return getCurrentStorage.party
end
def maxBoxes
return getCurrentStorage.maxBoxes
end
def maxPokemon(box)
return getCurrentStorage.maxPokemon(box)
end
def full?
getCurrentStorage.full?
end
def currentBox
return getCurrentStorage.currentBox
end
def currentBox=(value)
getCurrentStorage.currentBox = value
end
def [](x,y=nil)
getCurrentStorage[x,y]
end
def []=(x,y,value)
getCurrentStorage[x,y] = value
end
def pbFirstFreePos(box)
getCurrentStorage.pbFirstFreePos(box)
end
def pbCopy(boxDst,indexDst,boxSrc,indexSrc)
getCurrentStorage.pbCopy(boxDst,indexDst,boxSrc,indexSrc)
end
def pbMove(boxDst,indexDst,boxSrc,indexSrc)
getCurrentStorage.pbCopy(boxDst,indexDst,boxSrc,indexSrc)
end
def pbMoveCaughtToParty(pkmn)
getCurrentStorage.pbMoveCaughtToParty(pkmn)
end
def pbMoveCaughtToBox(pkmn,box)
getCurrentStorage.pbMoveCaughtToBox(pkmn,box)
end
def pbStoreCaught(pkmn)
getCurrentStorage.pbStoreCaught(pkmn)
end
def pbDelete(box,index)
getCurrentStorage.pbDelete(pkmn)
end
end
#===============================================================================
#
#===============================================================================
def pbUnlockWallpaper(index)
$PokemonStorage.unlockedWallpapers[index] = true
end
def pbLockWallpaper(index) # Don't know why you'd want to do this
$PokemonStorage.unlockedWallpapers[index] = false
end
#===============================================================================
# Look through Pokémon in storage
#===============================================================================
# Yields every Pokémon/egg in storage in turn.
def pbEachPokemon
for i in -1...$PokemonStorage.maxBoxes
for j in 0...$PokemonStorage.maxPokemon(i)
pkmn = $PokemonStorage[i][j]
yield(pkmn,i) if pkmn
end
end
end
# Yields every Pokémon in storage in turn.
def pbEachNonEggPokemon
pbEachPokemon { |pkmn,box| yield(pkmn,box) if !pkmn.egg? }
end