Changed: PokemonPokedex @@ -50,0 +50,1 @@ + indexNumber=@commands[i][4] @@ -56,1 +57,1 @@ - text=_ISPRINTF("No.{1:03d} {2:s}",@commands[i][0],@commands[i][1]) + text=_ISPRINTF("No.{1:03d} {2:s}",indexNumber,@commands[i][1]) @@ -58,1 +59,1 @@ - text=_ISPRINTF("No.{1:03d} ----------",@commands[i][0]) + text=_ISPRINTF("No.{1:03d} ----------",indexNumber) @@ -237,0 +238,13 @@ +end + +# +# Gets the region used for displaying Pokedex entries. +# Species will be listed according to the given region's +# numbering and the returned region can have any value +# defined in the town map data file. It's currently +# set to the return value of pbGetCurrentRegion, +# and thus will change according to the current map's +# MapPosition metadata setting. +# +def pbGetPokedexRegion + return pbGetCurrentRegion() @@ -268,0 +282,9 @@ +=begin +# Suggestion for changing the background depending on region. You +# can change the line below with the following: + if pbGetPokedexRegion()==-1 # Using national Pokedex + addBackgroundPlane(@sprites,"background","pokedexbg_national.png",@viewport) + elsif pbGetPokedexRegion()==0 # Using regional Pokedex + addBackgroundPlane(@sprites,"background","pokedexbg_regional.png",@viewport) + end +=end @@ -305,1 +328,1 @@ -def pbCanAddForModeList?(mode,species) +def pbCanAddForModeList?(mode,nationalSpecies) @@ -310,1 +333,1 @@ - return $Trainer.seen[species] + return $Trainer.seen[nationalSpecies] @@ -312,5 +335,5 @@ - return $Trainer.owned[species] - end -end - -def pbCanAddForModeSearch?(mode,species) + return $Trainer.owned[nationalSpecies] + end +end + +def pbCanAddForModeSearch?(mode,nationalSpecies) @@ -319,1 +342,1 @@ - return $Trainer.seen[species] + return $Trainer.seen[nationalSpecies] @@ -321,6 +344,6 @@ - return $Trainer.owned[species] - end -end - - -def pbRefreshDexList(index=0) + return $Trainer.owned[nationalSpecies] + end +end + + +def pbGetDexList() @@ -329,3 +352,13 @@ - for i in 1..PBSpecies.getCount - if pbCanAddForModeList?($PokemonGlobal.pokedexMode,i) - pbDexDataOffset(dexdata,i,33) + region=pbGetPokedexRegion() + regionalSpecies=pbAllRegionalSpecies(region) + if regionalSpecies.length==1 + # No regional species defined, + # use national Pokedex order + for i in 1..PBSpecies.getCount + regionalSpecies.push(i) + end + end + for i in 1...regionalSpecies.length + nationalSpecies=regionalSpecies[i] + if pbCanAddForModeList?($PokemonGlobal.pokedexMode,nationalSpecies) + pbDexDataOffset(dexdata,nationalSpecies,33) @@ -334,1 +367,3 @@ - dexlist.push([i,PBSpecies.getName(i),height,weight]) + # Pushing national species, name, height, weight, index number + dexlist.push([nationalSpecies, + PBSpecies.getName(nationalSpecies),height,weight,i]) @@ -338,0 +373,5 @@ + return dexlist +end + +def pbRefreshDexList(index=0) + dexlist=pbGetDexList() @@ -340,0 +380,1 @@ + # Remove species not seen from the list @@ -351,0 +392,3 @@ + # Sort species in ascending order by + # index number, not national species + dexlist.sort!{|a,b| a[4]<=>b[4]} @@ -377,10 +421,1 @@ - dexlist=[] - dexdata=pbOpenDexData - for i in 1..PBSpecies.getCount - if pbCanAddForModeSearch?(params[4],i) - pbDexDataOffset(dexdata,i,33) - height=dexdata.fgetw - weight=dexdata.fgetw - dexlist.push([i,PBSpecies.getName(i),height,weight]) - end - end + dexlist=pbGetDexList() @@ -418,0 +453,1 @@ + # Find species that match both types @@ -421,0 +457,1 @@ + # Find species that match first type entered @@ -423,0 +460,1 @@ + # Find species that match second type entered @@ -430,1 +468,3 @@ - dexlist.sort!{|a,b| a[0]<=>b[0]} + # Sort by index number, not + # national number + dexlist.sort!{|a,b| a[4]<=>b[4]} @@ -492,0 +532,2 @@ + indexNumber=pbGetRegionalNumber(pbGetPokedexRegion(),species) + indexNumber=species if indexNumber==0 @@ -493,1 +535,1 @@ - [_ISPRINTF("No. {1:03d} {2:s}",species,PBSpecies.getName(species)),96*2,24*2,0,basecolor,shadowcolor], + [_ISPRINTF("No. {1:03d} {2:s}",indexNumber,PBSpecies.getName(species)),96*2,24*2,0,basecolor,shadowcolor], Changed: PokeBattle_Move @@ -477,1 +477,2 @@ - @battle.pbDisplayPaused(_INTL("The Substitute took damage for {1}!",opponent.name)) + @battle.scene.pbDamageAnimation(opponent,0) + @battle.pbDisplayPaused(_INTL("The substitute took damage for {1}!",opponent.name)) @@ -480,1 +481,1 @@ - @battle.pbDisplayPaused(_INTL("{1}'s Substitute faded!",opponent.name)) + @battle.pbDisplayPaused(_INTL("{1}'s substitute faded!",opponent.name)) Changed: PokemonNetwork @@ -119,2 +119,3 @@ - command = self.gets.sub(/\s+$/,"") - command="" if !command + begin + command = self.gets.sub(/\s+$/,"") + command="" if !command @@ -122,5 +123,6 @@ - if update == true - Graphics.update - Input.update - $scene.update if $scene.methods.include?("update") - end + if update == true + Graphics.update + Input.update + $scene.update if $scene.methods.include?("update") + end + end while command=="" @@ -232,4 +234,17 @@ - def get_password(name,email) - send("name=#{name} email=#{email}\n") - result = get_command("", true) - return result + # Begins a loop with the specified timeout, in seconds + # _prc_ is the procedure called whenever a new message + # arrives. + def loopTimeout(timeout,prc) + oldmessageproc=Network.messageproc + Network.messageproc=prc + ret=nil + oldtime=Time.new.to_i + while ret==nil + Graphics.update + Input.update + ret=Network.update + newtime=Time.new.to_i-oldtime + break if newtime>=timeout + end + Network.messageproc=oldmessageproc + return ret @@ -398,2 +413,23 @@ - - +# +# Sends data to another user. The currently logged +# in user is the sender. This is a lower-level function +# than networkGetData. +# +# message - ID of the message. Can be any value +# from the NetworkMessage module. +# data - Data to send to the recipient. +# recipient - Recipient of the message +# +# The return value is a four-item array: +# First item is the result of the function: +# NetworkState::Ack - The operation was successful. +# NetworkState::Nack - The operation failed, or the +# recipient refused the message. +# NetworkState::Missing - The recipient is missing +# or no longer online. +# Second item is the recipient of the message. +# Third item is the sender of the message (always the +# logged-in user.) +# Fourth item is the data block returned by +# the recipient. +# @@ -425,0 +461,1 @@ +# Sends an acknowledge to another user. @@ -430,0 +467,1 @@ +# Sends a negative acknowledge to another user. @@ -433,0 +471,70 @@ +end + +# +# Sends data to another user. Either the sender +# or the receiver should be the currently logged in +# user. +# sender - Sender of the message. +# receiver - Recipient of the message +# message - ID of the message. Can be any value +# from the NetworkMessage module. +# data - Data to send to the recipient. +# +# Returns an array containing an error code and +# data returned from the recipient. The error +# code can be one of the following: +# 0 - The operation completed successfully. +# -1 - The receiver is missing or no longer online. +# -2 - The sender is missing or no longer online, +# or the attempt to receive the message timed +# out (after 15 seconds). +# -3 - The logged-in user is neither sender nor +# receiver. +# -4 - The receiver refused the message five times. +# +def networkGetData(sender,receiver,message,data) + if Network.get_id==sender + for i in 0...5 + Graphics.update + Input.update + nsdata=networkSendData(message,data,receiver) + if nsdata[0]==NetworkState::Ack + # Successful + return [0,nsdata[3]] + elsif nsdata[0]==NetworkState::Missing + # Missing or no longer online + return [-1,nil] + end + Network.update + end + if !otherparty # Five nacks in a row + return [-4,nil] + end + otheruser=receiver + elsif Network.get_id==receiver + retval=nil + loopret=Network.loopTimeout 15,proc {|msgid,s,r,msgdata| + if s.to_i!=sender.to_i + networkSendNack([1,msgid],s) + next nil + end + case msgid + when message + retval=msgdata # Receive data + networkSendAck(data,s) + next true + else + networkSendNack([1,msgid],s) + next nil + end + } + otheruser=sender + if loopret==nil + # Sender is missing or no longer online + return [-2,retval] + else + return [0,retval] + end + else + return [-3,nil] + end @@ -452,0 +560,6 @@ + +##################### +# +# Login Screen +# +##################### @@ -675,1 +789,5 @@ - +# +# These are the messages defined for this +# game client. Currently they all involve +# the trade system. +# @@ -677,5 +795,5 @@ -TradeRequest=1 -TradeAccept=2 -TradeDecline=3 -TradeSendParty=4 -TradeNotifyChoice=5 + TradeRequest=1 + TradeAccept=2 + TradeDecline=3 + TradeSendParty=4 + TradeNotifyChoice=5 @@ -876,15 +994,0 @@ - def pbNetworkLoopTimeout(timeout,prc) - oldmessageproc=Network.messageproc - Network.messageproc=prc - ret=nil - oldtime=Time.new.to_i - while ret==nil - Graphics.update - Input.update - ret=Network.update - newtime=Time.new.to_i-oldtime - break if newtime>=timeout - end - Network.messageproc=oldmessageproc - return ret - end @@ -927,0 +1030,2 @@ + # Accept only TradeAccept and TradeDecline messages, reject + # all others @@ -946,0 +1051,2 @@ + # Notify the sender that the trade request + # was received @@ -966,45 +1073,0 @@ - def pbGetData(sender,receiver,message,data) - if Network.get_id==sender - for i in 0...5 - Graphics.update - Input.update - nsdata=networkSendData(message,data,receiver) - if nsdata[0]==NetworkState::Ack - return [0,nsdata[3]] - elsif nsdata[0]==NetworkState::Missing - return [-1,nil] - end - Network.update - end - if !otherparty # Five nacks in a row - return [-4,nil] - end - otheruser=receiver - elsif Network.get_id==receiver - retval=nil - loopret=pbNetworkLoopTimeout 15,proc {|msgid,s,r,msgdata| - if s.to_i!=sender.to_i - networkSendNack([1,msgid],s) - next nil - end - case msgid - when message - retval=msgdata # Receive data - networkSendAck(data,s) - next true - else - networkSendNack([1,msgid],s) - next nil - end - } - otheruser=sender - if loopret==nil - return [-2,retval] - else - return [0,retval] - end - else - return [-3,nil] - end - end - @@ -1015,1 +1077,1 @@ - data=pbGetData(sender,receiver,NetworkMessage::TradeSendParty,$Trainer.party) + data=networkGetData(sender,receiver,NetworkMessage::TradeSendParty,$Trainer.party) @@ -1078,1 +1140,1 @@ - data=pbGetData(sender,receiver,NetworkMessage::TradeNotifyChoice,currentChoice) + data=networkGetData(sender,receiver,NetworkMessage::TradeNotifyChoice,currentChoice) @@ -1080,0 +1142,1 @@ + # Success @@ -1201,0 +1264,155 @@ + +###################################################### + +def pbPostData(url, postdata, filename=nil, depth=0) + if url[/^http:\/\/([^\/]+)(.*)$/] + host=$1 + path=$2 + body = postdata.map {|key, value| + keyString=key.to_s + valueString=value.to_s + keyString.gsub!(/[^a-zA-Z0-9_\.\-]/n) {|s| sprintf('%%%02x', s[0]) } + valueString.gsub!(/[^a-zA-Z0-9_\.\-]/n) {|s| sprintf('%%%02x', s[0]) } + next "#{keyString}=#{valueString}" + }.join('&') + request="POST #{path} HTTP/1.1\nUser-Agent: Ruby Agent\nPragma: no-cache\nHost: #{host}\nProxy-Connection: Close\n" + request+="Content-Type: application/x-www-form-urlencoded\n" + request+="Content-Length: #{body.length}\n" + request+="\n" + request+=body + return pbHttpRequest(host, request, filename, depth) + end +end + +def pbDownloadData(url, filename=nil, depth=0) + if depth>10 + raise "Redirection level too deep" + end + if url[/^http:\/\/([^\/]+)(.*)$/] + host=$1 + path=$2 + request="GET #{path} HTTP/1.1\nUser-Agent: Ruby Agent\nPragma: no-cache\nHost: #{host}\nProxy-Connection: Close\n\n" + return pbHttpRequest(host, request, filename, depth) + end +end + +def pbHttpRequest(host, request, filename=nil, depth=0) + if depth>10 + raise "Redirection level too deep" + end + socket=::TCPSocket.new(host, 80) + time=Time.now.to_i + begin + socket.send(request) + result=socket.gets + data="" + # Get the HTTP result + if result[/^HTTP\/1\.[01] (\d+).*/] + errorcode=$1.to_i + if errorcode>=400 && errorcode<500 + raise "HTTP Error #{errorcode}" + end + headers={} + # Get the response headers + while true + result=socket.gets.sub(/\r$/,"") + break if result=="" + if result[/^([^:]+):\s*(.*)/] + headers[$1]=$2 + end + end + length=-1 + chunked=false + if headers["Content-Length"] + length=headers["Content-Length"].to_i + end + if headers["Transfer-Encoding"]=="chunked" + chunked=true + end + if headers["Location"] && errorcode >= 300 && errorcode < 400 + socket.close rescue socket=nil + return pbDownloadData(headers["Location"],filename,depth+1) + end + if chunked==true + # Chunked content + while true + lengthline=socket.gets.sub(/\r$/,"") + length=lengthline.to_i(16) + break if length==0 + while Time.now.to_i-time>=5 || socket.select(10)==0 + time=Time.now.to_i + Graphics.update + end + data+=socket.recv(length) + socket.gets + end + elsif length==-1 + # No content length specified + while true + if socket.select(500)==0 + break + else + while Time.now.to_i-time>=5 || socket.select(10)==0 + time=Time.now.to_i + Graphics.update + end + data+=socket.recv(1) + end + end + else + # Content length specified + while length>0 + chunk=[length,4096].min + while Time.now.to_i-time>=5 || socket.select(10)==0 + time=Time.now.to_i + Graphics.update + end + data+=socket.recv(chunk) + length-=chunk + end + end + end + if filename + File.open(filename,"wb"){|f| + f.write(data) + } + else + return data + end + ensure + socket.close rescue socket=nil + end + return "" +end + +def pbDownloadToString(url) + begin + data=pbDownloadData(url) + return data + rescue + return "" + end +end + +def pbDownloadToFile(url, file) + begin + pbDownloadData(url,file) + rescue + end +end + +def pbPostToString(url, postdata) + begin + data=pbPostData(url, postdata) + return data + rescue + return "" + end +end + +def pbPostToFile(url, postdata, file) + begin + pbPostData(url, postdata,file) + rescue + end +end Changed: Sockets @@ -457,1 +457,1 @@ - # ● Returns recieved data. + # ● Returns received data. @@ -460,3 +460,11 @@ - buf = "\0" * len - SocketError.check if Winsock.recv(@fd, buf, buf.size, flags) == -1 - buf + retString="" + remainLen=len + while remainLen > 0 + buf = "\0" * remainLen + retval=Winsock.recv(@fd, buf, buf.size, flags) + SocketError.check if retval == -1 + # Note: Return value may not equal requested length + remainLen-=retval + retString+=buf[0,retval] + end + return retString Changed: Main @@ -34,2 +34,2 @@ -# setThreadPriority.call(getCurrentThread.call(),2) - setThreadPriority.call(getCurrentThread.call(),1) + setThreadPriority.call(getCurrentThread.call(),2) +# setThreadPriority.call(getCurrentThread.call(),1) Changed: PokemonTriad @@ -25,1 +25,1 @@ - 2000,5000,8000,12000 + 2000,5000,8000,12000,20000 @@ -132,1 +132,0 @@ - @@ -199,0 +198,1 @@ + @sprites["helpwindow"].update @@ -268,0 +268,1 @@ + @sprites["helpwindow"].update @@ -306,0 +307,1 @@ + @sprites["helpwindow"].update @@ -403,0 +405,1 @@ + @sprites["helpwindow"].update @@ -461,0 +464,1 @@ + @sprites["helpwindow"].update @@ -959,1 +963,1 @@ - a[1]<=>b[1] # sort by price + a[1]<=>b[1] # sort by name @@ -961,1 +965,1 @@ - a[0]<=>b[0] # sort by name + a[0]<=>b[0] # sort by price Changed: PokemonEditor @@ -1539,1 +1539,1 @@ - [_INTL("Unused"),PictureProperty, + [_INTL("Unused"),ReadOnlyProperty, @@ -1599,1 +1599,1 @@ - if !propobj.is_a?(ReadOnlyProperty) && + if propobj!=ReadOnlyProperty && !propobj.is_a?(ReadOnlyProperty) && Changed: SpriteWindow @@ -809,0 +809,1 @@ + @flash=0 @@ -954,0 +955,1 @@ + @flash=duration+1 @@ -975,0 +977,2 @@ + oldpauseframe=@pauseframe + oldpauseopacity=@pauseopacity @@ -977,1 +981,1 @@ - mustchange=true + mustchange=@pauseframe!=oldpauseframe || @pauseopacity!=oldpauseopacity @@ -980,2 +984,5 @@ - for i in @sprites - i[1].update + if @flash>0 + for i in @sprites.values + i.update + end + @flash-=1 @@ -1924,0 +1931,95 @@ + +# Represents a single-line scrolling window. +class Window_SingleLineScroll < SpriteWindow_Base + attr_reader :text + attr_reader :baseColor + attr_reader :shadowColor + # Letter-by-letter mode. This mode is not supported + # in this class. + attr_accessor :letterbyletter + def text=(value) + oldDisplay=@displaytext + @text=value + @displaytext=value.gsub(/\n/," ").gsub(/[\r\0\1]/,"") + if oldDisplay!=@displaytext + @frame=0 + self.ox=0 + end + refresh + end + def baseColor=(value) + @baseColor=value + refresh + end + def shadowColor=(value) + @shadowColor=value + refresh + end + def initialize(text) + super(0,0,33,33) + self.contents=Bitmap.new(1,1) + pbSetSystemFont(self.contents) + @text=text + @displaytext=text.gsub(/\n/," ").gsub(/[\r\0\1]/,"") + @letterbyletter=false # Not supported in this class + colors=getDefaultTextColors(self.windowskin) + @baseColor=colors[0] + @shadowColor=colors[1] + @frame=0 + @textwidth=0 + resizeToFit(text) + end + def self.newWithSize(text,x,y,width,height,viewport=nil) + ret=self.new(text) + ret.x=x + ret.y=y + ret.width=width + ret.height=height + ret.viewport=viewport + ret.refresh + return ret + end + def resizeToFitInternal(text,maxwidth) + dims=[0,0] + cwidth=maxwidth<0 ? Graphics.width : maxwidth + displaytext=text.gsub(/\n/," ").gsub(/[\r\0\1]/,"") + getLineBrokenChunks(self.contents,text,cwidth,dims,true) + return dims + end + def resizeToFit(text,maxwidth=-1) + displaytext=text.gsub(/\n/," ").gsub(/[\r\0\1]/,"") + dims=resizeToFitInternal(text,maxwidth) + self.width=dims[0]+self.borderX+2+6 + self.height=dims[1]+self.borderY + refresh + end + def resizeHeightToFit(text,width=-1) + displaytext=text.gsub(/\n/," ").gsub(/[\r\0\1]/,"") + dims=resizeToFitInternal(text,width) + self.width=width<0 ? Graphics.width : width + self.height=dims[1]+self.borderY + refresh + end + def refresh + dims=[0,0] + getLineBrokenChunks(self.contents,@displaytext,0x7FFFFFFF,dims,true) + @textwidth=dims[0]+2+6 + self.contents=pbDoEnsureBitmap(self.contents,@textwidth,32) + self.contents.clear + drawTextEx(self.contents,0,0,self.contents.width,0, + @displaytext,@baseColor,@shadowColor) + end + def update + super + if @frame<60 + @frame+=1 + elsif self.width-self.borderX < @textwidth + self.ox+=2 + if self.ox>=@textwidth+8 + self.ox=0 + @frame=0 + end + end + end +end + Changed: PokemonUtilities @@ -379,0 +379,3 @@ + bitmapFileName=sprintf("Graphics/Battlers/%03d%s%s.png",pokemon.species, + pokemon.isShiny? ? "s" : "", + back ? "b" : "") @@ -380,2 +383,15 @@ - bitmap=Bitmap.new( - sprintf("Graphics/Battlers/%03d%s%s.png",pokemon.species, + bitmap=Bitmap.new(bitmapFileName) + pbSpindaSpots(pokemon,bitmap) + return bitmap + elsif isConst?(pokemon.species,PBSpecies,:UNOWN) + d=pokemon.personalID&3 + d|=((pokemon.personalID>>8)&3)<<2 + d|=((pokemon.personalID>>16)&3)<<4 + d|=((pokemon.personalID>>24)&3)<<6 + d%=28 # index of letter : ABCDEFGHIJKLMNOPQRSTUVWXYZ!? + p d + begin + # Load special bitmap if found + # Example: 201b_02 for the letter C + return BitmapCache.load_bitmap( + sprintf("Graphics/Battlers/%03d%s%s_%02d.png",pokemon.species, @@ -383,13 +399,7 @@ - back ? "b" : "")) - pbSpindaSpots(pokemon,bitmap) - elsif pokemon.isShiny? - # Load shiny bitmap - bitmap=BitmapCache.load_bitmap( - sprintf("Graphics/Battlers/%03ds%s.png",pokemon.species,back ? "b" : "")) - else - # Load normal bitmap - bitmap=BitmapCache.load_bitmap( - sprintf("Graphics/Battlers/%03d%s.png",pokemon.species,back ? "b" : "")) - end - # TODO: Unown - return bitmap + back ? "b" : "", d) + ) + rescue + # Load plain bitmap as usual (see below) + end + end + return BitmapCache.load_bitmap(bitmapFileName) @@ -403,15 +413,26 @@ - if isConst?(pokemon.species,PBSpecies,:SPINDA) && !back - bitmap=Bitmap.new( - sprintf("Graphics/Battlers/%03ds%s.png",species,back ? "b" : "")) - pbSpindaSpots(pokemon,bitmap) - elsif pokemon.isShiny? - # Load shiny bitmap - bitmap=BitmapCache.load_bitmap( - sprintf("Graphics/Battlers/%03ds%s.png",species,back ? "b" : "")) - else - # Load normal bitmap - bitmap=BitmapCache.load_bitmap( - sprintf("Graphics/Battlers/%03d%s.png",species,back ? "b" : "")) - end - # TODO: Unown - return bitmap + bitmapFileName=sprintf("Graphics/Battlers/%03d%s%s.png",species, + pokemon.isShiny? ? "s" : "", + back ? "b" : "") + if isConst?(species,PBSpecies,:SPINDA) && !back + bitmap=Bitmap.new(bitmapFileName) + pbSpindaSpots(pokemon,bitmap) + return bitmap + elsif isConst?(species,PBSpecies,:UNOWN) + d=pokemon.personalID&3 + d|=((pokemon.personalID>>8)&3)<<2 + d|=((pokemon.personalID>>16)&3)<<4 + d|=((pokemon.personalID>>24)&3)<<6 + d%=28 # index of letter : ABCDEFGHIJKLMNOPQRSTUVWXYZ!? + begin + # Load special bitmap if found + # Example: 201b_02 for the letter C + return BitmapCache.load_bitmap( + sprintf("Graphics/Battlers/%03d%s%s_%02d.png",species, + pokemon.isShiny? ? "s" : "", + back ? "b" : "", d) + ) + rescue + # Load plain bitmap as usual (see below) + end + end + return BitmapCache.load_bitmap(bitmapFileName) Changed: PokemonPokedex Changed: PokeBattle_Move Changed: PokemonNetwork Changed: Sockets Changed: Main Changed: PokemonTriad Changed: PokemonEditor Changed: SpriteWindow Changed: PokemonUtilities