################################################################################ # General purpose utilities ################################################################################ def _pbNextComb(comb,length) i=comb.length-1 begin valid=true for j in i...comb.length if j==i comb[j]+=1 else comb[j]=comb[i]+(j-i) end if comb[j]>=length valid=false break end end return true if valid i-=1 end while i>=0 return false end # Iterates through the array and yields each combination of _num_ elements in # the array. def pbEachCombination(array,num) return if array.length> 16) + ((((@seed & 0xffff0000) >> 16) * (@s1 & 0x0000ffff)) & 0x0000ffff) + (((@seed & 0x0000ffff) * ((@s1 & 0xffff0000) >> 16)) & 0x0000ffff)) & 0x0000ffff) << 16)) + @s2 r=(@seed>>16) r=(r+0xFFFFFFFF)+1 if r<0 return r end def getNext r=(getNext16()<<16)|(getNext16()) r=(r+0xFFFFFFFF)+1 if r<0 return r end end ################################################################################ # JavaScript-related utilities ################################################################################ # Returns true if the given string represents a valid object in JavaScript # Object Notation, and false otherwise. def pbIsJsonString(str) return false if !str || str.strip.empty? # Regular expressions for matching parts of a JSON string d = /(?:^|:|,)(?: ?\[)+/ charEscapes = /\\[\"\\\/nrtubf]/ # Match string literals that may contain escaped characters # This will match strings with valid JSON escapes, such as \", \\, \n, \r, etc. stringLiterals = /"(?:[^"\\\n\r\x00-\x1f\x7f\x80-\x9f\\]|\\.)*"/ # White space matching whiteSpace = /[\s]+/ # Pre-process the string to replace escapes, literals, and whitespace str = str.gsub(charEscapes, "@").gsub(stringLiterals, "true").gsub(whiteSpace, " ") # Prevent cases like "truetrue", "true true", "true[true]", or other malformed patterns otherLiterals = /(true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)(?! ?[0-9a-z\-\[\{\"])/ str = str.gsub(otherLiterals, "]").gsub(d, "") # Check if the string matches the format of a valid JSON-like structure return str =~ /^[\],:{}\s]*$/ ? true : false end # Returns a Ruby object that corresponds to the given string, which is encoded in # JavaScript Object Notation (JSON). Returns nil if the string is not valid JSON. def pbParseJson(str) if !pbIsJsonString(str) return nil end stringRE=/(\"(\\[\"\'\\rntbf]|\\u[0-9A-Fa-f]{4,4}|[^\\\"])*\")/ #" strings=[] str=str.gsub(stringRE){ sl=strings.length ss=$1 if ss.include?("\\u") ss.gsub!(/\\u([0-9A-Fa-f]{4,4})/){ codepoint=$1.to_i(16) if codepoint<=0x7F next sprintf("\\x%02X",codepoint) elsif codepoint<=0x7FF next sprintf("%s%s", (0xC0|((codepoint>>6)&0x1F)).chr, (0x80|(codepoint &0x3F)).chr) else next sprintf("%s%s%s", (0xE0|((codepoint>>12)&0x0F)).chr, (0x80|((codepoint>>6)&0x3F)).chr, (0x80|(codepoint &0x3F)).chr) end } end strings.push(eval(ss)) next sprintf("strings[%d]",sl) } str=str.gsub(/\:/,"=>") str=str.gsub(/null/,"nil") return eval("("+str+")") end ################################################################################ # XML-related utilities ################################################################################ # Represents XML content. class MiniXmlContent attr_reader :value def initialize(value) @value=value end end # Represents an XML element. class MiniXmlElement attr_accessor :name,:attributes,:children def initialize(name) @name=name @attributes={} @children=[] end # Gets the value of the attribute with the given name, or nil if it doesn't # exist. def a(name) self.attributes[name] end # Gets the entire text of this element. def value ret="" for c in @children ret+=c.value end return ret end # Gets the first child of this element with the given name, or nil if it # doesn't exist. def e(name) for c in @children return c if c.is_a?(MiniXmlElement) && c.name==name end return nil end def eachElementNamed(name) for c in @children yield c if c.is_a?(MiniXmlElement) && c.name==name end end end # A small class for reading simple XML documents. Such documents must # meet the following restrictions: # They may contain comments and processing instructions, but they are # ignored. # They can't contain any entity references other than 'gt', 'lt', # 'amp', 'apos', or 'quot'. # They can't contain a DOCTYPE declaration or DTDs. class MiniXmlReader def initialize(data) @root=nil @elements=[] @done=false @data=data @content="" end def createUtf8(codepoint) #:nodoc: raise ArgumentError.new("Illegal character") if codepoint<9 || codepoint==11||codepoint==12||(codepoint>=14 && codepoint<32) || codepoint==0xFFFE||codepoint==0xFFFF||(codepoint>=0xD800 && codepoint<0xE000) if codepoint<=0x7F return codepoint.chr elsif codepoint<=0x7FF str=(0xC0|((codepoint>>6)&0x1F)).chr str+=(0x80|(codepoint &0x3F)).chr return str elsif codepoint<=0xFFFF str=(0xE0|((codepoint>>12)&0x0F)).chr str+=(0x80|((codepoint>>6)&0x3F)).chr str+=(0x80|(codepoint &0x3F)).chr return str elsif codepoint<=0x10FFFF str=(0xF0|((codepoint>>18)&0x07)).chr str+=(0x80|((codepoint>>12)&0x3F)).chr str+=(0x80|((codepoint>>6)&0x3F)).chr str+=(0x80|(codepoint &0x3F)).chr return str else raise ArgumentError.new("Illegal character") end return str end def unescape(attr) #:nodoc: attr=attr.gsub(/\r(\n|$|(?=[^\n]))/,"\n") raise ArgumentError.new("Attribute value contains '<'") if attr.include?("<") attr=attr.gsub(/&(lt|gt|apos|quot|amp|\#([0-9]+)|\#x([0-9a-fA-F]+));|([\n\r\t])/){ next " " if $4=="\n"||$4=="\r"||$4=="\t" next "<" if $1=="lt" next ">" if $1=="gt" next "'" if $1=="apos" next "\"" if $1=="quot" next "&" if $1=="amp" next createUtf8($2.to_i) if $2 next createUtf8($3.to_i(16)) if $3 } return attr end def readAttributes(attribs) #:nodoc: ret={} while attribs.length>0 if attribs[/(\s+([\w\-]+)\s*\=\s*\"([^\"]*)\")/] attribs=attribs[$1.length,attribs.length] name=$2; value=$3 if ret[name]!=nil raise ArgumentError.new("Attribute already exists") end ret[name]=unescape(value) elsif attribs[/(\s+([\w\-]+)\s*\=\s*\'([^\']*)\')/] attribs=attribs[$1.length,attribs.length] name=$2; value=$3 if ret[name]!=nil raise ArgumentError.new("Attribute already exists") end ret[name]=unescape(value) else raise ArgumentError.new("Can't parse attributes") end end return ret end # Reads the entire contents of an XML document. Returns the root element of # the document or raises an ArgumentError if an error occurs. def read if @data[/\A((\xef\xbb\xbf)?<\?xml\s+version\s*=\s*(\"1\.[0-9]\"|\'1\.[0-9]\')(\s+encoding\s*=\s*(\"[^\"]*\"|\'[^\']*\'))?(\s+standalone\s*=\s*(\"(yes|no)\"|\'(yes|no)\'))?\s*\?>)/] # Ignore XML declaration @data=@data[$1.length,@data.length] end while readOneElement(); end return @root end def readOneElement #:nodoc: if @data[/\A\s*\z/] @data="" if !@root raise ArgumentError.new("Not an XML document.") elsif !@done raise ArgumentError.new("Unexpected end of document.") end return false end if @data[/\A(\s*<([\w\-]+)((?:\s+[\w\-]+\s*\=\s*(?:\"[^\"]*\"|\'[^\']*\'))*)\s*(\/>|>))/] @data=@data[$1.length,@data.length] elementName=$2 attributes=$3 endtag=$4 if @done raise ArgumentError.new("Element tag at end of document") end if @content.length>0 && @elements.length>0 @elements[@elements.length-1].children.push(MiniXmlContent.new(@content)) @content="" end element=MiniXmlElement.new(elementName) element.attributes=readAttributes(attributes) if !@root @root=element else @elements[@elements.length-1].children.push(element) end if endtag==">" @elements.push(element) else if @elements.length==0 @done=true end end elsif @data[/\A()/] # ignore comments if $2.include?("--") raise ArgumentError.new("Incorrect comment") end @data=@data[$1.length,@data.length] elsif @data[/\A(<\?([\w\-]+)\s+[\s\S]*?\?>)/] # ignore processing instructions @data=@data[$1.length,@data.length] if $2.downcase=="xml" raise ArgumentError.new("'xml' processing instruction not allowed") end elsif @data[/\A(<\?([\w\-]+)\?>)/] # ignore processing instructions @data=@data[$1.length,@data.length] if $2.downcase=="xml" raise ArgumentError.new("'xml' processing instruction not allowed") end elsif @data[/\A(\s*<\/([\w\-]+)>)/] @data=@data[$1.length,@data.length] elementName=$2 if @done raise ArgumentError.new("End tag at end of document") end if @elements.length==0 raise ArgumentError.new("Unexpected end tag") elsif @elements[@elements.length-1].name!=elementName raise ArgumentError.new("Incorrect end tag") else if @content.length>0 @elements[@elements.length-1].children.push(MiniXmlContent.new(@content)) @content="" end @elements.pop() if @elements.length==0 @done=true end end else if @elements.length>0 # Parse content if @data[/\A([^<&]+)/] content=$1 @data=@data[content.length,@data.length] if content.include?("]]>") raise ArgumentError.new("Incorrect content") end content.gsub!(/\r(\n|\z|(?=[^\n]))/,"\n") @content+=content elsif @data[/\A(<\!\[CDATA\[([\s\S]*?)\]\]>)/] content=$2 @data=@data[$1.length,@data.length] content.gsub!(/\r(\n|\z|(?=[^\n]))/,"\n") @content+=content elsif @data[/\A(&(lt|gt|apos|quot|amp|\#([0-9]+)|\#x([0-9a-fA-F]+));)/] @data=@data[$1.length,@data.length] content="" if $2=="lt"; content="<" elsif $2=="gt"; content=">" elsif $2=="apos"; content="'" elsif $2=="quot"; content="\"" elsif $2=="amp"; content="&" elsif $3; content=createUtf8($2.to_i) elsif $4; content=createUtf8($3.to_i(16)) end @content+=content elsif !@data[/\A=8 meta=pbGetMetadata(0,MetadataPlayerA+id) return false if !meta $Trainer.trainertype=meta[0] if $Trainer $game_player.character_name=meta[1] $game_player.character_hue=0 $PokemonGlobal.playerID=id $Trainer.metaID=id if $Trainer end def pbGetPlayerGraphic id=$PokemonGlobal.playerID return "" if id<0 || id>=8 meta=pbGetMetadata(0,MetadataPlayerA+id) return "" if !meta return pbPlayerSpriteFile(meta[0]) end def pbGetPlayerTrainerType id=$PokemonGlobal.playerID return 0 if id<0 || id>=8 meta=pbGetMetadata(0,MetadataPlayerA+id) return 0 if !meta return meta[0] end def pbGetTrainerTypeGender(trainertype) ret=2 # 2 = gender unknown pbRgssOpen("Data/trainertypes.dat","rb"){|f| trainertypes=Marshal.load(f) if !trainertypes[trainertype] ret=2 else ret=trainertypes[trainertype][7] ret=2 if !ret end } return ret end def pbTrainerName(name=nil,outfit=0) if $PokemonGlobal.playerID<0 pbChangePlayer(0) end trainertype=pbGetPlayerTrainerType trname=name $Trainer=PokeBattle_Trainer.new(trname,trainertype) $Trainer.outfit=outfit if trname==nil trname=pbEnterPlayerName(_INTL("Your name?"),0,7) if trname=="" # gender=pbGetTrainerTypeGender(trainertype) # trname=pbSuggestTrainerName(gender) #REDMAGE - replaced the above two lines with the one below trname=[_INTL("Simon"),_INTL("Sofia")][$PokemonGlobal.playerID] end end $Trainer.name=trname $PokemonBag=PokemonBag.new $PokemonTemp.begunNewGame=true end def pbSuggestTrainerName(gender) userName=pbGetUserName() userName=userName.gsub(/\s+.*$/,"") if userName.length>0 && userName.length<7 userName[0,1]=userName[0,1].upcase return userName end userName=userName.gsub(/\d+$/,"") if userName.length>0 && userName.length<7 userName[0,1]=userName[0,1].upcase return userName end owner=MiniRegistry.get(MiniRegistry::HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "RegisteredOwner","") owner=owner.gsub(/\s+.*$/,"") if owner.length>0 && owner.length<7 owner[0,1]=owner[0,1].upcase return owner end return getRandomNameEx(gender,nil,1,7) end def pbGetUserName() buffersize=100 getUserName=Win32API.new('advapi32.dll','GetUserName','pp','i') 10.times do size=[buffersize].pack("V") buffer="\0"*buffersize if getUserName.call(buffer,size)!=0 return buffer.gsub(/\0/,"") end buffersize+=200 end return "" end def getRandomNameEx(type,variable,upper,maxLength=100) return "" if maxLength<=0 name="" 50.times { name="" formats=[] case type when 0 # Names for males formats=%w( F5 BvE FE FE5 FEvE ) when 1 # Names for females formats=%w( vE6 vEvE6 BvE6 B4 v3 vEv3 Bv3 ) when 2 # Neutral gender names formats=%w( WE WEU WEvE BvE BvEU BvEvE ) else return "" end format=formats[rand(formats.length)] format.scan(/./) {|c| case c when "c" # consonant set=%w( b c d f g h j k l m n p r s t v w x z ) name+=set[rand(set.length)] when "v" # vowel set=%w( a a a e e e i i i o o o u u u ) name+=set[rand(set.length)] when "W" # beginning vowel set=%w( a a a e e e i i i o o o u u u au au ay ay ea ea ee ee oo oo ou ou ) name+=set[rand(set.length)] when "U" # ending vowel set=%w( a a a a a e e e i i i o o o o o u u ay ay ie ie ee ue oo ) name+=set[rand(set.length)] when "B" # beginning consonant set1=%w( b c d f g h j k l l m n n p r r s s t t v w y z ) set2=%w( bl br ch cl cr dr fr fl gl gr kh kl kr ph pl pr sc sk sl sm sn sp st sw th tr tw vl zh ) name+=rand(3)>0 ? set1[rand(set1.length)] : set2[rand(set2.length)] when "E" # ending consonant set1=%w( b c d f g h j k k l l m n n p r r s s t t v z ) set2=%w( bb bs ch cs ds fs ft gs gg ld ls nd ng nk rn kt ks ms ns ph pt ps sk sh sp ss st rd rn rp rm rt rk ns th zh) name+=rand(3)>0 ? set1[rand(set1.length)] : set2[rand(set2.length)] when "f" # consonant and vowel set=%w( iz us or ) name+=set[rand(set.length)] when "F" # consonant and vowel set=%w( bo ba be bu re ro si mi zho se nya gru gruu glee gra glo ra do zo ri di ze go ga pree pro po pa ka ki ku de da ma mo le la li ) name+=set[rand(set.length)] when "2" set=%w( c f g k l p r s t ) name+=set[rand(set.length)] when "3" set=%w( nka nda la li ndra sta cha chie ) name+=set[rand(set.length)] when "4" set=%w( una ona ina ita ila ala ana ia iana ) name+=set[rand(set.length)] when "5" set=%w( e e o o ius io u u ito io ius us ) name+=set[rand(set.length)] when "6" set=%w( a a a elle ine ika ina ita ila ala ana ) name+=set[rand(set.length)] end } break if name.length<=maxLength } name=name[0,maxLength] case upper when 0 name=name.upcase when 1 name[0,1]=name[0,1].upcase end if $game_variables && variable $game_variables[variable]=name $game_map.need_refresh = true if $game_map end return name end def getRandomName(maxLength=100) return getRandomNameEx(2,nil,nil,maxLength) end ################################################################################ # Event timing utilities ################################################################################ def pbTimeEvent(variableNumber,secs=86400) if variableNumber && variableNumber>=0 if $game_variables secs=0 if secs<0 timenow=pbGetTimeNow $game_variables[variableNumber]=[timenow.to_f,secs] $game_map.refresh if $game_map end end end def pbTimeEventDays(variableNumber,days=0) if variableNumber && variableNumber>=0 if $game_variables days=0 if days<0 timenow=pbGetTimeNow time=timenow.to_f expiry=(time%86400.0)+(days*86400.0) $game_variables[variableNumber]=[time,expiry-time] $game_map.refresh if $game_map end end end def pbTimeEventValid(variableNumber) retval=false if variableNumber && variableNumber>=0 && $game_variables value=$game_variables[variableNumber] if value.is_a?(Array) timenow=pbGetTimeNow retval=(timenow.to_f - value[0] > value[1]) # value[1] is age in seconds retval=false if value[1]<=0 # zero age end if !retval $game_variables[variableNumber]=0 $game_map.refresh if $game_map end end return retval end ################################################################################ # Constants utilities ################################################################################ def isConst?(val,mod,constant) begin isdef=mod.const_defined?(constant.to_sym) return false if !isdef rescue return false end return (val==mod.const_get(constant.to_sym)) end def hasConst?(mod,constant) return false if !mod || !constant || constant=="" return mod.const_defined?(constant.to_sym) rescue false end def getConst(mod,constant) return nil if !mod || !constant || constant=="" return mod.const_get(constant.to_sym) rescue nil end def getID(mod,constant) return nil if !mod || !constant || constant=="" if constant.is_a?(Symbol) || constant.is_a?(String) if (mod.const_defined?(constant.to_sym) rescue false) return mod.const_get(constant.to_sym) rescue 0 else return 0 end else return constant end end ################################################################################ # Implements methods that act on arrays of items. Each element in an item # array is itself an array of [itemID, itemCount]. # Used by the Bag, PC item storage, and Triple Triad. ################################################################################ module ItemStorageHelper # Returns the quantity of the given item in the items array, maximum size per slot, and item ID def self.pbQuantity(items,maxsize,item) ret=0 for i in 0...maxsize itemslot=items[i] if itemslot && itemslot[0]==item ret+=itemslot[1] end end return ret end # Deletes an item from items array, maximum size per slot, item, and number of items to delete def self.pbDeleteItem(items,maxsize,item,qty) raise "Invalid value for qty: #{qty}" if qty<0 return true if qty==0 ret=false for i in 0...maxsize itemslot=items[i] if itemslot && itemslot[0]==item amount=[qty,itemslot[1]].min itemslot[1]-=amount qty-=amount items[i]=nil if itemslot[1]==0 if qty==0 ret=true break end end end items.compact! return ret end def self.pbCanStore?(items,maxsize,maxPerSlot,item,qty) raise "Invalid value for qty: #{qty}" if qty<0 return true if qty==0 for i in 0...maxsize itemslot=items[i] if !itemslot qty-=[qty,maxPerSlot].min return true if qty==0 elsif itemslot[0]==item && itemslot[1]=0 $game_variables[id]=value if $game_variables $game_map.need_refresh = true if $game_map end end # Runs a common event and waits until the common event is finished. # Requires the script "PokemonMessages" def pbCommonEvent(id) return false if id<0 ce=$data_common_events[id] return false if !ce celist=ce.list interp=Interpreter.new interp.setup(celist,0) begin Graphics.update Input.update interp.update pbUpdateSceneMap end while interp.running? return true end def pbExclaim(event,id=EXCLAMATION_ANIMATION_ID,tinting=false) if event.is_a?(Array) sprite=nil done=[] for i in event if !done.include?(i.id) sprite=$scene.spriteset.addUserAnimation(id,i.x,i.y,tinting) done.push(i.id) end end else sprite=$scene.spriteset.addUserAnimation(id,event.x,event.y-1,tinting) #Nave exclamaition mark fix (added that -1) end while !sprite.disposed? Graphics.update Input.update pbUpdateSceneMap end end def pbNoticePlayer(event) if !pbFacingEachOther(event,$game_player) || !Input.press?(Input::C) pbExclaim(event) end pbTurnTowardEvent($game_player,event) Kernel.pbMoveTowardPlayer(event) end ################################################################################ # Loads Pokémon/item/trainer graphics ################################################################################ def pbPokemonBitmapFile(species, shiny, back=false) # Unused if shiny # Load shiny bitmap ret=sprintf("Graphics/Battlers/%ss%s",getConstantName(PBSpecies,species),back ? "b" : "") rescue nil if !pbResolveBitmap(ret) ret=sprintf("Graphics/Battlers/%03ds%s",species,back ? "b" : "") end return ret else # Load normal bitmap ret=sprintf("Graphics/Battlers/%s%s",getConstantName(PBSpecies,species),back ? "b" : "") rescue nil if !pbResolveBitmap(ret) ret=sprintf("Graphics/Battlers/%03d%s",species,back ? "b" : "") end return ret end end def pbLoadPokemonBitmap(pokemon, back=false) return pbLoadPokemonBitmapSpecies(pokemon,pokemon.species,back) end # Note: Returns an AnimatedBitmap, not a Bitmap def pbLoadPokemonBitmapSpecies(pokemon, species, back=false) ret=nil if pokemon.isEgg? bitmapFileName=sprintf("Graphics/Battlers/%segg",getConstantName(PBSpecies,species)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Battlers/%03degg",species) if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Battlers/egg") end end bitmapFileName=pbResolveBitmap(bitmapFileName) else bitmapFileName=pbCheckPokemonBitmapFiles([species,back, (pokemon.isFemale?), pokemon.isShiny?, (pokemon.form rescue 0), (pokemon.isShadow? rescue false)]) # Alter bitmap if supported alterBitmap=(MultipleForms.getFunction(species,"alterBitmap") rescue nil) end if bitmapFileName && alterBitmap animatedBitmap=AnimatedBitmap.new(bitmapFileName) copiedBitmap=animatedBitmap.copy animatedBitmap.dispose copiedBitmap.each {|bitmap| alterBitmap.call(pokemon,bitmap) } ret=copiedBitmap elsif bitmapFileName ret=AnimatedBitmap.new(bitmapFileName) end return ret end # Note: Returns an AnimatedBitmap, not a Bitmap def pbLoadSpeciesBitmap(species,female=false,form=0,shiny=false,shadow=false,back=false,egg=false) ret=nil if egg bitmapFileName=sprintf("Graphics/Battlers/%segg",getConstantName(PBSpecies,species)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Battlers/%03degg",species) if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Battlers/egg") end end bitmapFileName=pbResolveBitmap(bitmapFileName) else bitmapFileName=pbCheckPokemonBitmapFiles([species,back,female,shiny,form,shadow]) end if bitmapFileName ret=AnimatedBitmap.new(bitmapFileName) end return ret end def pbCheckPokemonBitmapFiles(params) species=params[0] back=params[1] factors=[] factors.push([5,params[5],false]) if params[5] && params[5]!=false # shadow factors.push([2,params[2],false]) if params[2] && params[2]!=false # gender factors.push([3,params[3],false]) if params[3] && params[3]!=false # shiny factors.push([4,params[4].to_s,""]) if params[4] && params[4].to_s!="" && params[4].to_s!="0" # form tshadow=false tgender=false tshiny=false tform="" for i in 0...2**factors.length for j in 0...factors.length case factors[j][0] when 2 # gender tgender=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2] when 3 # shiny tshiny=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2] when 4 # form tform=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2] when 5 # shadow tshadow=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2] end end bitmapFileName=sprintf("Graphics/Battlers/%s%s%s%s%s%s", getConstantName(PBSpecies,species), tgender ? "f" : "", tshiny ? "s" : "", back ? "b" : "", (tform!="" ? "_"+tform : ""), tshadow ? "_shadow" : "") rescue nil ret=pbResolveBitmap(bitmapFileName) return ret if ret bitmapFileName=sprintf("Graphics/Battlers/%03d%s%s%s%s%s", species, tgender ? "f" : "", tshiny ? "s" : "", back ? "b" : "", (tform!="" ? "_"+tform : ""), tshadow ? "_shadow" : "") ret=pbResolveBitmap(bitmapFileName) return ret if ret end return nil end def pbLoadPokemonIcon(pokemon) return AnimatedBitmap.new(pbPokemonIconFile(pokemon)).deanimate end def pbPokemonIconFile(pokemon) bitmapFileName=nil bitmapFileName=pbCheckPokemonIconFiles([pokemon.species, (pokemon.isFemale?), pokemon.isShiny?, (pokemon.form rescue 0), (pokemon.isShadow? rescue false)], pokemon.isEgg?) return bitmapFileName end def pbCheckPokemonIconFiles(params,egg=false) species=params[0] if egg bitmapFileName=sprintf("Graphics/Icons/icon%segg",getConstantName(PBSpecies,species)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Icons/icon%03degg",species) if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Icons/iconEgg") end end return pbResolveBitmap(bitmapFileName) else factors=[] factors.push([4,params[4],false]) if params[4] && params[4]!=false # shadow factors.push([1,params[1],false]) if params[1] && params[1]!=false # gender factors.push([2,params[2],false]) if params[2] && params[2]!=false # shiny factors.push([3,params[3].to_s,""]) if params[3] && params[3].to_s!="" && params[3].to_s!="0" # form tshadow=false tgender=false tshiny=false tform="" for i in 0...2**factors.length for j in 0...factors.length case factors[j][0] when 1 # gender tgender=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2] when 2 # shiny tshiny=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2] when 3 # form tform=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2] when 4 # shadow tshadow=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2] end end bitmapFileName=sprintf("Graphics/Icons/icon%s%s%s%s%s", getConstantName(PBSpecies,species), tgender ? "f" : "", tshiny ? "s" : "", (tform!="" ? "_"+tform : ""), tshadow ? "_shadow" : "") rescue nil ret=pbResolveBitmap(bitmapFileName) return ret if ret bitmapFileName=sprintf("Graphics/Icons/icon%03d%s%s%s%s", species, tgender ? "f" : "", tshiny ? "s" : "", (tform!="" ? "_"+tform : ""), tshadow ? "_shadow" : "") ret=pbResolveBitmap(bitmapFileName) return ret if ret end end return nil end def pbPokemonFootprintFile(pokemon) # Used by the Pokédex return nil if !pokemon if pokemon.is_a?(Numeric) bitmapFileName=sprintf("Graphics/Icons/Footprints/footprint%s",getConstantName(PBSpecies,pokemon)) rescue nil bitmapFileName=sprintf("Graphics/Icons/Footprints/footprint%03d",pokemon) if !pbResolveBitmap(bitmapFileName) else bitmapFileName=sprintf("Graphics/Icons/Footprints/footprint%s_%d",getConstantName(PBSpecies,pokemon.species),(pokemon.form rescue 0)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Icons/Footprints/footprint%03d_%d",pokemon.species,(pokemon.form rescue 0)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Icons/Footprints/footprint%s",getConstantName(PBSpecies,pokemon.species)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Icons/Footprints/footprint%03d",pokemon.species) end end end end return pbResolveBitmap(bitmapFileName) end def pbItemIconFile(item) return nil if !item bitmapFileName=nil if item==0 bitmapFileName=sprintf("Graphics/Icons/itemBack") else bitmapFileName=sprintf("Graphics/Icons/item%s",getConstantName(PBItems,item)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Icons/item%03d",item) end end return bitmapFileName end def pbMailBackFile(item) return nil if !item bitmapFileName=sprintf("Graphics/Pictures/mail%s",getConstantName(PBItems,item)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Pictures/mail%03d",item) end return bitmapFileName end def pbTrainerCharFile(type) return nil if !type bitmapFileName=sprintf("Graphics/Characters/trchar%s",getConstantName(PBTrainers,type)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Characters/trchar%03d",type) end return bitmapFileName end def pbTrainerCharNameFile(type) return nil if !type bitmapFileName=sprintf("trchar%s",getConstantName(PBTrainers,type)) rescue nil if !pbResolveBitmap(sprintf("Graphics/Characters/"+bitmapFileName)) bitmapFileName=sprintf("trchar%03d",type) end return bitmapFileName end def pbTrainerHeadFile(type) return nil if !type bitmapFileName=sprintf("Graphics/Pictures/mapPlayer%s",getConstantName(PBTrainers,type)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Pictures/mapPlayer%03d",type) end return bitmapFileName end def pbPlayerHeadFile(type) return nil if !type outfit=$Trainer ? $Trainer.outfit : 0 bitmapFileName=sprintf("Graphics/Pictures/mapPlayer%s_%d", getConstantName(PBTrainers,type),outfit) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Pictures/mapPlayer%03d_%d",type,outfit) if !pbResolveBitmap(bitmapFileName) bitmapFileName=pbTrainerHeadFile(type) end end return bitmapFileName end def pbTrainerSpriteFile(type) return nil if !type bitmapFileName=sprintf("Graphics/Characters/trainer%s",getConstantName(PBTrainers,type)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Characters/trainer%03d",type) end return bitmapFileName end def pbTrainerSpriteBackFile(type) return nil if !type bitmapFileName=sprintf("Graphics/Characters/trback%s",getConstantName(PBTrainers,type)) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Characters/trback%03d",type) end return bitmapFileName end def pbPlayerSpriteFile(type) return nil if !type outfit=$Trainer ? $Trainer.outfit : 0 bitmapFileName=sprintf("Graphics/Characters/trainer%s_%d", getConstantName(PBTrainers,type),outfit) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Characters/trainer%03d_%d",type,outfit) if !pbResolveBitmap(bitmapFileName) bitmapFileName=pbTrainerSpriteFile(type) end end return bitmapFileName end def pbPlayerSpriteBackFile(type) return nil if !type outfit=$Trainer ? $Trainer.outfit : 0 bitmapFileName=sprintf("Graphics/Characters/trback%s_%d", getConstantName(PBTrainers,type),outfit) rescue nil if !pbResolveBitmap(bitmapFileName) bitmapFileName=sprintf("Graphics/Characters/trback%03d_%d",type,outfit) if !pbResolveBitmap(bitmapFileName) bitmapFileName=pbTrainerSpriteBackFile(type) end end return bitmapFileName end ################################################################################ # Loads music and sound effects ################################################################################ def pbResolveAudioSE(file) return nil if !file if RTP.exists?("Audio/SE/"+file,["",".wav",".mp3",".ogg"]) return RTP.getPath("Audio/SE/"+file,["",".wav",".mp3",".ogg"]) end return nil end def pbCryFrameLength(pokemon,pitch=nil) return 0 if !pokemon pitch=100 if !pitch pitch=pitch.to_f/100 return 0 if pitch<=0 playtime=0.0 if pokemon.is_a?(Numeric) pkmnwav=pbResolveAudioSE(pbCryFile(pokemon)) playtime=getPlayTime(pkmnwav) if pkmnwav elsif !pokemon.isEgg? if pokemon.respond_to?("chatter") && pokemon.chatter playtime=pokemon.chatter.time pitch=1.0 else pkmnwav=pbResolveAudioSE(pbCryFile(pokemon)) playtime=getPlayTime(pkmnwav) if pkmnwav end end playtime/=pitch # sound is lengthened the lower the pitch # 4 is added to provide a buffer between sounds return (playtime*Graphics.frame_rate).ceil+4 end def pbPlayCry(pokemon,volume=90,pitch=nil) return if !pokemon if pokemon.is_a?(Numeric) pkmnwav=pbCryFile(pokemon) if pkmnwav pbSEPlay(RPG::AudioFile.new(pkmnwav,volume,pitch ? pitch : 100)) rescue nil end elsif !pokemon.isEgg? if pokemon.respond_to?("chatter") && pokemon.chatter pokemon.chatter.play else pkmnwav=pbCryFile(pokemon) if pkmnwav pbSEPlay(RPG::AudioFile.new(pkmnwav,volume, pitch ? pitch : (pokemon.hp*25/pokemon.totalhp)+75)) rescue nil end end end end def pbCryFile(pokemon) return nil if !pokemon if pokemon.is_a?(Numeric) filename=sprintf("Cries/%sCry",getConstantName(PBSpecies,pokemon)) rescue nil filename=sprintf("Cries/%03dCry",pokemon) if !pbResolveAudioSE(filename) return filename if pbResolveAudioSE(filename) elsif !pokemon.isEgg? filename=sprintf("Cries/%sCry_%d",getConstantName(PBSpecies,pokemon.species),(pokemon.form rescue 0)) rescue nil filename=sprintf("Cries/%03dCry_%d",pokemon.species,(pokemon.form rescue 0)) if !pbResolveAudioSE(filename) if !pbResolveAudioSE(filename) filename=sprintf("Cries/%sCry",getConstantName(PBSpecies,pokemon.species)) rescue nil end filename=sprintf("Cries/%03dCry",pokemon.species) if !pbResolveAudioSE(filename) return filename if pbResolveAudioSE(filename) end return nil end def pbGetWildBattleBGM(species) if $PokemonGlobal.nextBattleBGM return $PokemonGlobal.nextBattleBGM.clone end ret=nil if !ret && $game_map # Check map-specific metadata music=pbGetMetadata($game_map.map_id,MetadataMapWildBattleBGM) if music && music!="" ret=pbStringToAudioFile(music) end end if !ret # Check global metadata music=pbGetMetadata(0,MetadataWildBattleBGM) if music && music!="" ret=pbStringToAudioFile(music) end end ret=pbStringToAudioFile("BT-Wild.mp3") if !ret return ret end def pbGetWildVictoryME if $PokemonGlobal.nextBattleME return $PokemonGlobal.nextBattleME.clone end ret=nil if !ret && $game_map # Check map-specific metadata music=pbGetMetadata($game_map.map_id,MetadataMapWildVictoryME) if music && music!="" ret=pbStringToAudioFile(music) end end if !ret # Check global metadata music=pbGetMetadata(0,MetadataWildVictoryME) if music && music!="" ret=pbStringToAudioFile(music) end end ret=pbStringToAudioFile("001-Victory01") if !ret ret.name="../../Audio/ME/"+ret.name return ret end def pbPlayTrainerIntroME(trainertype) pbRgssOpen("Data/trainertypes.dat","rb"){|f| trainertypes=Marshal.load(f) if trainertypes[trainertype] bgm=trainertypes[trainertype][6] if bgm && bgm!="" bgm=pbStringToAudioFile(bgm) pbMEPlay(bgm) return end end } end def pbGetTrainerBattleBGM(trainer) # can be a PokeBattle_Trainer or an array of PokeBattle_Trainer if $PokemonGlobal.nextBattleBGM return $PokemonGlobal.nextBattleBGM.clone end music=nil pbRgssOpen("Data/trainertypes.dat","rb"){|f| trainertypes=Marshal.load(f) if !trainer.is_a?(Array) trainerarray=[trainer] else trainerarray=trainer end for i in 0...trainerarray.length trainertype=trainerarray[i].trainertype if trainertypes[trainertype] music=trainertypes[trainertype][4] end end } ret=nil if music && music!="" ret=pbStringToAudioFile(music) end if !ret && $game_map # Check map-specific metadata music=pbGetMetadata($game_map.map_id,MetadataMapTrainerBattleBGM) if music && music!="" ret=pbStringToAudioFile(music) end end if !ret # Check global metadata music=pbGetMetadata(0,MetadataTrainerBattleBGM) if music && music!="" ret=pbStringToAudioFile(music) end end ret=pbStringToAudioFile("005-Boss01") if !ret return ret end def pbGetTrainerBattleBGMFromType(trainertype) if $PokemonGlobal.nextBattleBGM return $PokemonGlobal.nextBattleBGM.clone end music=nil pbRgssOpen("Data/trainertypes.dat","rb"){|f| trainertypes=Marshal.load(f) if trainertypes[trainertype] music=trainertypes[trainertype][4] end } ret=nil if music && music!="" ret=pbStringToAudioFile(music) end if !ret && $game_map # Check map-specific metadata music=pbGetMetadata($game_map.map_id,MetadataMapTrainerBattleBGM) if music && music!="" ret=pbStringToAudioFile(music) end end if !ret # Check global metadata music=pbGetMetadata(0,MetadataTrainerBattleBGM) if music && music!="" ret=pbStringToAudioFile(music) end end ret=pbStringToAudioFile("005-Boss01") if !ret return ret end def pbGetTrainerVictoryME(trainer) # can be a PokeBattle_Trainer or an array of PokeBattle_Trainer if $PokemonGlobal.nextBattleME return $PokemonGlobal.nextBattleME.clone end music=nil pbRgssOpen("Data/trainertypes.dat","rb"){|f| trainertypes=Marshal.load(f) if !trainer.is_a?(Array) trainerarray=[trainer] else trainerarray=trainer end for i in 0...trainerarray.length trainertype=trainerarray[i].trainertype if trainertypes[trainertype] music=trainertypes[trainertype][5] end end } ret=nil if music && music!="" ret=pbStringToAudioFile(music) end if !ret && $game_map # Check map-specific metadata music=pbGetMetadata($game_map.map_id,MetadataMapTrainerVictoryME) if music && music!="" ret=pbStringToAudioFile(music) end end if !ret # Check global metadata music=pbGetMetadata(0,MetadataTrainerVictoryME) if music && music!="" ret=pbStringToAudioFile(music) end end ret=pbStringToAudioFile("001-Victory01") if !ret ret.name="../../Audio/ME/"+ret.name return ret end ################################################################################ # Creating and storing Pokémon ################################################################################ # For demonstration purposes only, not to be used in a real game. def pbCreatePokemon party=[] species=[:PIKACHU,:PIDGEOTTO,:KADABRA,:GYARADOS,:DIGLETT,:CHANSEY] for id in species party.push(getConst(PBSpecies,id)) if hasConst?(PBSpecies,id) end # Species IDs of the Pokémon to be created for i in 0...party.length species=party[i] # Generate Pokémon with species and level 20 $Trainer.party[i]=PokeBattle_Pokemon.new(species,20,$Trainer) $Trainer.seen[species]=true # Set this species to seen and owned $Trainer.owned[species]=true pbSeenForm($Trainer.party[i]) end $Trainer.party[1].pbLearnMove(:FLY) $Trainer.party[2].pbLearnMove(:FLASH) $Trainer.party[2].pbLearnMove(:TELEPORT) $Trainer.party[3].pbLearnMove(:SURF) $Trainer.party[3].pbLearnMove(:DIVE) $Trainer.party[3].pbLearnMove(:WATERFALL) $Trainer.party[4].pbLearnMove(:DIG) $Trainer.party[4].pbLearnMove(:CUT) $Trainer.party[4].pbLearnMove(:HEADBUTT) $Trainer.party[4].pbLearnMove(:ROCKSMASH) $Trainer.party[5].pbLearnMove(:SOFTBOILED) $Trainer.party[5].pbLearnMove(:STRENGTH) $Trainer.party[5].pbLearnMove(:SWEETSCENT) for i in 0...party.length $Trainer.party[i].pbRecordFirstMoves end end def pbBoxesFull? return !$Trainer || ($Trainer.party.length==6 && $PokemonStorage.full?) end def pbNickname(pokemon) speciesname=PBSpecies.getName(pokemon.species) if Kernel.pbConfirmMessage(_INTL("Would you like to give a nickname to {1}?",speciesname)) helptext=_INTL("{1}'s nickname?",speciesname) newname=pbEnterPokemonName(helptext,0,10,"",pokemon) pokemon.name=newname if newname!="" end end def pbStorePokemon(pokemon) if pbBoxesFull? Kernel.pbMessage(_INTL("There's no more room for Pokémon!\1")) Kernel.pbMessage(_INTL("The Pokémon Boxes are full and can't accept any more!")) return end pokemon.pbRecordFirstMoves if $Trainer.party.length<6 $Trainer.party[$Trainer.party.length]=pokemon else oldcurbox=$PokemonStorage.currentBox storedbox=$PokemonStorage.pbStoreCaught(pokemon) curboxname=$PokemonStorage[oldcurbox].name boxname=$PokemonStorage[storedbox].name creator=nil creator=Kernel.pbGetStorageCreator if $PokemonGlobal.seenStorageCreator if storedbox!=oldcurbox if creator Kernel.pbMessage(_INTL("Box \"{1}\" on {2}'s PC was full.\1",curboxname,creator)) else Kernel.pbMessage(_INTL("Box \"{1}\" on someone's PC was full.\1",curboxname)) end Kernel.pbMessage(_INTL("{1} was transferred to box \"{2}.\"",pokemon.name,boxname)) else if creator Kernel.pbMessage(_INTL("{1} was transferred to {2}'s PC.\1",pokemon.name,creator)) else Kernel.pbMessage(_INTL("{1} was transferred to someone's PC.\1",pokemon.name)) end Kernel.pbMessage(_INTL("It was stored in box \"{1}.\"",boxname)) end end end def pbNicknameAndStore(pokemon) if pbBoxesFull? Kernel.pbMessage(_INTL("There's no more room for Pokémon!\1")) Kernel.pbMessage(_INTL("The Pokémon Boxes are full and can't accept any more!")) return end $Trainer.seen[pokemon.species]=true $Trainer.owned[pokemon.species]=true pbNickname(pokemon) pbStorePokemon(pokemon) end def pbAddPokemon(pokemon,level=nil,seeform=true) return if !pokemon || !$Trainer if pbBoxesFull? Kernel.pbMessage(_INTL("There's no more room for Pokémon!\1")) Kernel.pbMessage(_INTL("The Pokémon Boxes are full and can't accept any more!")) return false end if pokemon.is_a?(String) || pokemon.is_a?(Symbol) pokemon=getID(PBSpecies,pokemon) end if pokemon.is_a?(Integer) && level.is_a?(Integer) pokemon=PokeBattle_Pokemon.new(pokemon,level,$Trainer) end speciesname=PBSpecies.getName(pokemon.species) if $Trainer.party.length==0 pbMEPlay("fffirstpokemon") Kernel.pbMessage(_INTL("{1} obtained {2}!\1",$Trainer.name,speciesname)) else pbMEPlay("PokemonGet") Kernel.pbMessage(_INTL("{1} obtained {2}!\1",$Trainer.name,speciesname)) end pbNicknameAndStore(pokemon) pbSeenForm(pokemon) if seeform return true end def pbAddPokemonSilent(pokemon,level=nil,seeform=true) return false if !pokemon || pbBoxesFull? || !$Trainer if pokemon.is_a?(String) || pokemon.is_a?(Symbol) pokemon=getID(PBSpecies,pokemon) end if pokemon.is_a?(Integer) && level.is_a?(Integer) pokemon=PokeBattle_Pokemon.new(pokemon,level,$Trainer) end $Trainer.seen[pokemon.species]=true $Trainer.owned[pokemon.species]=true pbSeenForm(pokemon) if seeform pokemon.pbRecordFirstMoves if $Trainer.party.length<6 $Trainer.party[$Trainer.party.length]=pokemon else $PokemonStorage.pbStoreCaught(pokemon) end return true end def pbAddToParty(pokemon,level=nil,seeform=true) return false if !pokemon || !$Trainer || $Trainer.party.length>=6 if pokemon.is_a?(String) || pokemon.is_a?(Symbol) pokemon=getID(PBSpecies,pokemon) end if pokemon.is_a?(Integer) && level.is_a?(Integer) pokemon=PokeBattle_Pokemon.new(pokemon,level,$Trainer) end speciesname=PBSpecies.getName(pokemon.species) Kernel.pbMessage(_INTL("{1} obtained {2}!\\se[PokemonGet]\1",$Trainer.name,speciesname)) pbNicknameAndStore(pokemon) pbSeenForm(pokemon) if seeform return true end def pbAddToPartySilent(pokemon,level=nil,seeform=true) return false if !pokemon || !$Trainer || $Trainer.party.length>=6 if pokemon.is_a?(String) || pokemon.is_a?(Symbol) pokemon=getID(PBSpecies,pokemon) end if pokemon.is_a?(Integer) && level.is_a?(Integer) pokemon=PokeBattle_Pokemon.new(pokemon,level,$Trainer) end $Trainer.seen[pokemon.species]=true $Trainer.owned[pokemon.species]=true pbSeenForm(pokemon) if seeform pokemon.pbRecordFirstMoves $Trainer.party[$Trainer.party.length]=pokemon return true end def pbAddForeignPokemon(pokemon,level=nil,ownerName=nil,nickname=nil,ownerGender=0,seeform=true) return false if !pokemon || !$Trainer || $Trainer.party.length>=6 if pokemon.is_a?(String) || pokemon.is_a?(Symbol) pokemon=getID(PBSpecies,pokemon) end if pokemon.is_a?(Integer) && level.is_a?(Integer) pokemon=PokeBattle_Pokemon.new(pokemon,level,$Trainer) end # Set original trainer to a foreign one (if ID isn't already foreign) if pokemon.trainerID==$Trainer.id pokemon.trainerID=$Trainer.getForeignID pokemon.ot=ownerName if ownerName && ownerName!="" pokemon.otgender=ownerGender end # Set nickname pokemon.name=nickname[0,10] if nickname && nickname!="" # Recalculate stats pokemon.calcStats if ownerName Kernel.pbMessage(_INTL("{1} received a Pokémon from {2}.\\se[PokemonGet]\1",$Trainer.name,ownerName)) else Kernel.pbMessage(_INTL("{1} received a Pokémon.\\se[PokemonGet]\1",$Trainer.name)) end pbStorePokemon(pokemon) $Trainer.seen[pokemon.species]=true $Trainer.owned[pokemon.species]=true pbSeenForm(pokemon) if seeform return true end def pbGenerateEgg(pokemon,text="") return false if !pokemon || !$Trainer || $Trainer.party.length>=6 if pokemon.is_a?(String) || pokemon.is_a?(Symbol) pokemon=getID(PBSpecies,pokemon) end if pokemon.is_a?(Integer) pokemon=PokeBattle_Pokemon.new(pokemon,EGGINITIALLEVEL,$Trainer) end # Get egg steps dexdata=pbOpenDexData pbDexDataOffset(dexdata,pokemon.species,21) eggsteps=dexdata.fgetw dexdata.close # Set egg's details pokemon.name=_INTL("Egg") pokemon.eggsteps=eggsteps pokemon.obtainText=text pokemon.calcStats # Add egg to party $Trainer.party[$Trainer.party.length]=pokemon return true end def pbRemovePokemonAt(index) return false if index<0 || !$Trainer || index>=$Trainer.party.length haveAble=false for i in 0...$Trainer.party.length next if i==index haveAble=true if $Trainer.party[i].hp>0 && !$Trainer.party[i].isEgg? end return false if !haveAble $Trainer.party.delete_at(index) return true end def pbSeenForm(poke,gender=0,form=0) $Trainer.formseen=[] if !$Trainer.formseen $Trainer.formlastseen=[] if !$Trainer.formlastseen if poke.is_a?(String) || poke.is_a?(Symbol) poke=getID(PBSpecies,poke) end if poke.is_a?(PokeBattle_Pokemon) gender=poke.gender form=(poke.form rescue 0) species=poke.species else species=poke end return if !species || species<=0 gender=0 if gender>1 formnames=pbGetMessage(MessageTypes::FormNames,species) form=0 if !formnames || formnames=="" #Emily 7-23 $Trainer.formseen[species]=[[],[]] if !$Trainer.formseen[species] $Trainer.formseen[species][gender][form]=true $Trainer.formlastseen[species]=[] if !$Trainer.formlastseen[species] $Trainer.formlastseen[species]=[gender,form] if $Trainer.formlastseen[species]==[] end ################################################################################ # Analysing Pokémon ################################################################################ # Heals all Pokémon in the party. def pbHealAll return if !$Trainer for i in $Trainer.party i.heal end end # Returns the first unfainted, non-egg Pokémon in the player's party. def pbFirstAblePokemon(variableNumber) for i in 0...$Trainer.party.length p=$Trainer.party[i] if p && !p.isEgg? && p.hp>0 pbSet(variableNumber,i) return $Trainer.party[i] end end pbSet(variableNumber,-1) return nil end # Checks whether the player would still have an unfainted Pokémon if the # Pokémon given by _pokemonIndex_ were removed from the party. def pbCheckAble(pokemonIndex) for i in 0...$Trainer.party.length p=$Trainer.party[i] next if i==pokemonIndex return true if p && !p.isEgg? && p.hp>0 end return false end # Returns true if there are no usable Pokémon in the player's party. def pbAllFainted for i in $Trainer.party return false if !i.isEgg? && i.hp>0 end return true end def pbBalancedLevel(party) return 1 if party.length==0 # Calculate the mean of all levels sum=0 party.each{|p| sum+=p.level } return 1 if sum==0 average=sum.to_f/party.length.to_f # Calculate the standard deviation varianceTimesN=0 for i in 0...party.length deviation=party[i].level-average varianceTimesN+=deviation*deviation end # Note: This is the "population" standard deviation calculation, since no # sample is being taken stdev=Math.sqrt(varianceTimesN/party.length) mean=0 weights=[] # Skew weights according to standard deviation for i in 0...party.length weight=party[i].level.to_f/sum.to_f if weight<0.5 weight-=(stdev/PBExperience::MAXLEVEL.to_f) weight=0.001 if weight<=0.001 else weight+=(stdev/PBExperience::MAXLEVEL.to_f) weight=0.999 if weight>=0.999 end weights.push(weight) end weightSum=0 weights.each{|weight| weightSum+=weight } # Calculate the weighted mean, assigning each weight to each level's # contribution to the sum for i in 0...party.length mean+=party[i].level*weights[i] end mean/=weightSum # Round to nearest number mean=mean.round # Adjust level to minimum mean=1 if mean<1 # Add 2 to the mean to challenge the player mean+=2 # Adjust level to maximum mean=PBExperience::MAXLEVEL if mean>PBExperience::MAXLEVEL return mean end # Returns the Pokémon's size in millimeters. def pbSize(pokemon) dexdata=pbOpenDexData pbDexDataOffset(dexdata,pokemon.species,33) baseheight=dexdata.fgetw # Gets the base height in tenths of a meter dexdata.close hpiv=pokemon.iv[0]&15 ativ=pokemon.iv[1]&15 dfiv=pokemon.iv[2]&15 spiv=pokemon.iv[3]&15 saiv=pokemon.iv[4]&15 sdiv=pokemon.iv[5]&15 m=pokemon.personalID&0xFF n=(pokemon.personalID>>8)&0xFF s=(((ativ^dfiv)*hpiv)^m)*256+(((saiv^sdiv)*spiv)^n) xyz=[] if s<10 xyz=[290,1,0] elsif s<110 xyz=[300,1,10] elsif s<310 xyz=[400,2,110] elsif s<710 xyz=[500,4,310] elsif s<2710 xyz=[600,20,710] elsif s<7710 xyz=[700,50,2710] elsif s<17710 xyz=[800,100,7710] elsif s<32710 xyz=[900,150,17710] elsif s<47710 xyz=[1000,150,32710] elsif s<57710 xyz=[1100,100,47710] elsif s<62710 xyz=[1200,50,57710] elsif s<64710 xyz=[1300,20,62710] elsif s<65210 xyz=[1400,5,64710] elsif s<65410 xyz=[1500,2,65210] else xyz=[1700,1,65510] end return (((s-xyz[2])/xyz[1]+xyz[0]).floor*baseheight/10).floor end # Returns true if the given species can be legitimately obtained as an egg. def pbHasEgg?(species) if species.is_a?(String) || species.is_a?(Symbol) species=getID(PBSpecies,species) end evospecies=pbGetEvolvedFormData(species) compatspecies=(evospecies && evospecies[0]) ? evospecies[0][2] : species dexdata=pbOpenDexData pbDexDataOffset(dexdata,compatspecies,31) compat1=dexdata.fgetb # Get egg group 1 of this species compat2=dexdata.fgetb # Get egg group 2 of this species dexdata.close return false if isConst?(compat1,PBEggGroups,:Ditto) || isConst?(compat1,PBEggGroups,:Undiscovered) || isConst?(compat2,PBEggGroups,:Ditto) || isConst?(compat2,PBEggGroups,:Undiscovered) baby=pbGetBabySpecies(species) return true if species==baby # Is a basic species baby=pbGetBabySpecies(species,0,0) return true if species==baby # Is an egg species without incense return false end ################################################################################ # Look through Pokémon in storage, choose a Pokémon in the party ################################################################################ # Yields every Pokémon/egg in storage in turn. def pbEachPokemon for i in -1...$PokemonStorage.maxBoxes for j in 0...$PokemonStorage.maxPokemon(i) poke=$PokemonStorage[i][j] yield(poke,i) if poke end end end # Yields every Pokémon in storage in turn. def pbEachNonEggPokemon pbEachPokemon{|pokemon,box| yield(pokemon,box) if !pokemon.isEgg? } end # Choose a Pokémon/egg from the party. # Stores result in variable _variableNumber_ and the chosen Pokémon's name in # variable _nameVarNumber_; result is -1 if no Pokémon was chosen def pbChoosePokemon(variableNumber,nameVarNumber,ableProc=nil, allowIneligible=false) chosen=0 pbFadeOutIn(99999){ scene=PokemonScreen_Scene.new screen=PokemonScreen.new(scene,$Trainer.party) if ableProc chosen=screen.pbChooseAblePokemon(ableProc,allowIneligible) else screen.pbStartScene(_INTL("Choose a Pokémon."),false) chosen=screen.pbChoosePokemon screen.pbEndScene end } pbSet(variableNumber,chosen) if chosen>=0 pbSet(nameVarNumber,$Trainer.party[chosen].name) else pbSet(nameVarNumber,"") end end def pbChooseNonEggPokemon(variableNumber,nameVarNumber) pbChoosePokemon(variableNumber,nameVarNumber,proc {|poke| !poke.isEgg? }) end def pbChooseAblePokemon(variableNumber,nameVarNumber) pbChoosePokemon(variableNumber,nameVarNumber,proc {|poke| !poke.isEgg? && poke.hp>0 }) end def pbChoosePokemonForTrade(variableNumber,nameVarNumber,wanted) pbChoosePokemon(variableNumber,nameVarNumber,proc {|poke| if wanted.is_a?(String) || wanted.is_a?(Symbol) wanted=getID(PBSpecies,wanted) end return !poke.isEgg? && !(poke.isShadow? rescue false) && poke.species==wanted }) end ################################################################################ # Checks through the party for something ################################################################################ def pbHasSpecies?(species) if species.is_a?(String) || species.is_a?(Symbol) species=getID(PBSpecies,species) end for pokemon in $Trainer.party next if pokemon.isEgg? return true if pokemon.species==species end return false end def pbHasFatefulSpecies?(species) if species.is_a?(String) || species.is_a?(Symbol) species=getID(PBSpecies,species) end for pokemon in $Trainer.party next if pokemon.isEgg? return true if pokemon.species==species && pokemon.obtainMode==4 end return false end def pbHasType?(type) if type.is_a?(String) || type.is_a?(Symbol) type=getID(PBTypes,type) end for pokemon in $Trainer.party next if pokemon.isEgg? return true if pokemon.hasType?(type) end return false end # Checks whether any Pokémon in the party knows the given move, and returns # the index of that Pokémon, or nil if no Pokémon has that move. def pbCheckMove(move) move=getID(PBMoves,move) return nil if !move || move<=0 for i in $Trainer.party next if i.isEgg? for j in i.moves return i if j.id==move end end return nil end ################################################################################ # Regional and National Pokédexes ################################################################################ # Gets the Regional Pokédex number of the national species for the specified # Regional Dex. The parameter "region" is zero-based. For example, if two # regions are defined, they would each be specified as 0 and 1. def pbGetRegionalNumber(region, nationalSpecies) if nationalSpecies<=0 || nationalSpecies>PBSpecies.maxValue # Return 0 if national species is outside range return 0 end pbRgssOpen("Data/regionals.dat","rb"){|f| numRegions=f.fgetw numDexDatas=f.fgetw if region>=0 && region=0 && region=0 && region=$PokemonGlobal.pokedexUnlocked.length-1 if $Trainer.pokedexSeen(region)>0 $PokemonGlobal.pokedexViable[0]=region end else numDexes=$PokemonGlobal.pokedexUnlocked.length case numDexes when 1 # National Dex only if $PokemonGlobal.pokedexUnlocked[0] if $Trainer.pokedexSeen>0 $PokemonGlobal.pokedexViable.push(0) end end else # Regional dexes + National Dex for i in 0...numDexes regionToCheck=(i==numDexes-1) ? -1 : i if $PokemonGlobal.pokedexUnlocked[i] if $Trainer.pokedexSeen(regionToCheck)>0 $PokemonGlobal.pokedexViable.push(i) end end end end end end # Unlocks a Dex list. The National Dex is -1 here (or nil argument). def pbUnlockDex(dex=-1) index=dex index=$PokemonGlobal.pokedexUnlocked.length-1 if index<0 index=$PokemonGlobal.pokedexUnlocked.length-1 if index>$PokemonGlobal.pokedexUnlocked.length-1 $PokemonGlobal.pokedexUnlocked[index]=true end # Locks a Dex list. The National Dex is -1 here (or nil argument). def pbLockDex(dex=-1) index=dex index=$PokemonGlobal.pokedexUnlocked.length-1 if index<0 index=$PokemonGlobal.pokedexUnlocked.length-1 if index>$PokemonGlobal.pokedexUnlocked.length-1 $PokemonGlobal.pokedexUnlocked[index]=false end ################################################################################ # Other utilities ################################################################################ def pbTextEntry(helptext,minlength,maxlength,variableNumber) $game_variables[variableNumber]=pbEnterText(helptext,minlength,maxlength) $game_map.need_refresh = true if $game_map end def pbMoveTutorAnnotations(move,movelist=nil) ret=[] for i in 0...6 ret[i]=nil next if i>=$Trainer.party.length found=false for j in 0...4 if !$Trainer.party[i].isEgg? && $Trainer.party[i].moves[j].id==move ret[i]=_INTL("LEARNED") found=true end end next if found species=$Trainer.party[i].species if !$Trainer.party[i].isEgg? && movelist && movelist.any?{|j| j==species } # Checked data from movelist ret[i]=_INTL("ABLE") elsif !$Trainer.party[i].isEgg? && $Trainer.party[i].isCompatibleWithMove?(move) # Checked data from PBS/tm.txt ret[i]=_INTL("ABLE") else ret[i]=_INTL("NOT ABLE") end end return ret end def pbMoveTutorChoose(move,movelist=nil,bymachine=false) ret=false if move.is_a?(String) || move.is_a?(Symbol) move=getID(PBMoves,move) end if movelist!=nil && movelist.is_a?(Array) for i in 0...movelist.length if movelist[i].is_a?(String) || movelist[i].is_a?(Symbol) movelist[i]=getID(PBSpecies,movelist[i]) end end end pbFadeOutIn(99999){ scene=PokemonScreen_Scene.new movename=PBMoves.getName(move) screen=PokemonScreen.new(scene,$Trainer.party) annot=pbMoveTutorAnnotations(move,movelist) screen.pbStartScene(_INTL("Teach which Pokémon?"),false,annot) loop do chosen=screen.pbChoosePokemon if chosen>=0 pokemon=$Trainer.party[chosen] if pokemon.isEgg? Kernel.pbMessage(_INTL("{1} can't be taught to an Egg.",movename)) elsif (pokemon.isShadow? rescue false) Kernel.pbMessage(_INTL("Shadow Pokémon can't be taught any moves.")) elsif movelist && !movelist.any?{|j| j==pokemon.species } Kernel.pbMessage(_INTL("{1} and {2} are not compatible.",pokemon.name,movename)) Kernel.pbMessage(_INTL("{1} can't be learned.",movename)) elsif !pokemon.isCompatibleWithMove?(move) Kernel.pbMessage(_INTL("{1} and {2} are not compatible.",pokemon.name,movename)) Kernel.pbMessage(_INTL("{1} can't be learned.",movename)) else if pbLearnMove(pokemon,move,false,bymachine) ret=true break end end else break end end screen.pbEndScene } return ret # Returns whether the move was learned by a Pokemon end def pbChooseMove(pokemon,variableNumber,nameVarNumber) return if !pokemon ret=-1 pbFadeOutIn(99999){ scene=PokemonSummaryScene.new screen=PokemonSummary.new(scene) ret=screen.pbStartForgetScreen([pokemon],0,0) } $game_variables[variableNumber]=ret if ret>=0 $game_variables[nameVarNumber]=PBMoves.getName(pokemon.moves[ret].id) else $game_variables[nameVarNumber]="" end $game_map.need_refresh = true if $game_map end # Opens the Pokémon screen def pbPokemonScreen return if !$Trainer sscene=PokemonScreen_Scene.new sscreen=PokemonScreen.new(sscene,$Trainer.party) pbFadeOutIn(99999) { sscreen.pbPokemonScreen } end def pbSaveScreen ret=false scene=PokemonSaveScene.new screen=PokemonSave.new(scene) ret=screen.pbSaveScreen return ret end def pbConvertItemToItem(variable,array) item=pbGet(variable) pbSet(variable,0) for i in 0...(array.length/2) if isConst?(item,PBItems,array[2*i]) pbSet(variable,getID(PBItems,array[2*i+1])) return end end end def pbConvertItemToPokemon(variable,array) item=pbGet(variable) pbSet(variable,0) for i in 0...(array.length/2) if isConst?(item,PBItems,array[2*i]) pbSet(variable,getID(PBSpecies,array[2*i+1])) return end end end class PokemonGlobalMetadata attr_accessor :trainerRecording end def pbRecordTrainer wave=pbRecord(nil,10) if wave $PokemonGlobal.trainerRecording=wave return true end return false end