#=============================================================================== # * Hall of Fame - by FL (Credits will be apreciated) #=============================================================================== # # This script is for Pokémon Essentials. It makes a recordable Hall of Fame # like the Gen 3 games. # #=============================================================================== # # To this scripts works, put it above main, put a 512x384 picture in # hallfamebars and a 8x24 background picture in hallfamebg. To call this script, # use 'pbHallOfFameEntry'. After you recorder the first entry, you can access # the hall teams using a PC. You can also check the player Hall of Fame last # number using '$PokemonGlobal.hallOfFameLastNumber'. # #=============================================================================== class HallOfFame_Scene # When true, all pokémon will be in one line # When false, all pokémon will be in two lines SINGLEROW = false # Make the pokémon movement ON in hall entry ANIMATION = true # Speed in pokémon movement in hall entry. Don't use less than 2! ANIMATIONSPEED = 32 # Entry wait time (in 1/20 seconds) between showing each Pokémon (and trainer) ENTRYWAITTIME = 64 # Maximum number limit of simultaneous hall entries saved. # 0 = Doesn't save any hall. -1 = no limit # Prefer to use larger numbers (like 500 and 1000) than don't put a limit # If a player exceed this limit, the first one will be removed HALLLIMIT = 50 # The entry music name. Put "" to doesn't play anything ENTRYMUSIC = "Hall of Fame" # Allow eggs to be show and saved in hall ALLOWEGGS = true # Remove the hallbars when the trainer sprite appears REMOVEBARS = true # The final fade speed on entry FINALFADESPEED = 16 # Sprites opacity value when them aren't selected OPACITY = 64 BASECOLOR = Color.new(248, 248, 248) SHADOWCOLOR = Color.new(0, 0, 0) # Placement for pokemon icons def pbStartScene @sprites = {} @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @viewport.z = 99999 # Comment the below line to doesn't use a background addBackgroundPlane(@sprites, "bg", "hallfamebg", @viewport) @sprites["hallbars"] = IconSprite.new(@viewport) @sprites["hallbars"].setBitmap("Graphics/Pictures/hallfamebars") @sprites["overlay"] = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) @sprites["overlay"].z = 10 pbSetSystemFont(@sprites["overlay"].bitmap) @alreadyFadedInEnd = false @useMusic = false @battlerIndex = 0 @hallEntry = [] end def pbStartSceneEntry pbStartScene @useMusic = (ENTRYMUSIC && ENTRYMUSIC != "") pbBGMPlay(ENTRYMUSIC) if @useMusic saveHallEntry @xmovement = [] @ymovement = [] createBattlers pbFadeInAndShow(@sprites) { pbUpdate } end def pbStartScenePC pbStartScene @hallIndex = $PokemonGlobal.hallOfFame.size - 1 @hallEntry = $PokemonGlobal.hallOfFame[-1] createBattlers(false) pbFadeInAndShow(@sprites) { pbUpdate } pbUpdatePC end def pbEndScene $game_map.autoplay if @useMusic pbDisposeMessageWindow(@sprites["msgwindow"]) if @sprites.include?("msgwindow") pbFadeOutAndHide(@sprites) { pbUpdate } if !@alreadyFadedInEnd pbDisposeSpriteHash(@sprites) @viewport.dispose end def slowFadeOut(sprites, exponent) # 2 exponent # To handle values above 8 extraWaitExponent = exponent - 9 exponent = 8 if 8 < exponent max = 2 ** exponent speed = (2 ** 8) / max for j in 0..max if extraWaitExponent > -1 (2 ** extraWaitExponent).times do Graphics.update Input.update pbUpdate end end pbSetSpritesToColor(sprites, Color.new(0, 0, 0, j * speed)) block_given? ? yield : pbUpdateSpriteHash(sprites) end end # Dispose the sprite if the sprite exists and make it null def restartSpritePosition(sprites, spritename) sprites[spritename].dispose if sprites.include?(spritename) && sprites[spritename] sprites[spritename] = nil end # Change the pokémon sprites opacity except the index one def setPokemonSpritesOpacity(index, opacity = 255) for n in 0...@hallEntry.size @sprites["pokemon#{n}"].opacity = (n == index) ? 255 : opacity if @sprites["pokemon#{n}"] end end def saveHallEntry for i in 0...$Trainer.party.length # Clones every pokémon object @hallEntry.push($Trainer.party[i].clone) if !$Trainer.party[i].egg? || ALLOWEGGS end # Update the global variables $PokemonGlobal.hallOfFame.push(@hallEntry) $PokemonGlobal.hallOfFameLastNumber += 1 $PokemonGlobal.hallOfFame.delete_at(0) if HALLLIMIT > -1 && $PokemonGlobal.hallOfFame.size > HALLLIMIT end # Return the x/y point position in screen for battler index number # Don't use odd numbers! def xpointformula(battlernumber) ret = 0 if !SINGLEROW ret = 92 + 160 * xpositionformula(battlernumber) #32 else ret = (60 * (battlernumber / 2) + 48) * (xpositionformula(battlernumber) - 1) ret += Graphics.width / 2 - 56 end return ret end def ypointformula(battlernumber) ret = 0 if !SINGLEROW ret = 92 + 128 * ypositionformula(battlernumber) / 2 else ret = 96 - 8 * (battlernumber / 2) end return ret end # Returns 0, 1 or 2 as the x/y column value def xpositionformula(battlernumber) ret = 0 if !SINGLEROW ret = (battlernumber / 3 % 2 == 0) ? (19 - battlernumber) % 3 : (19 + battlernumber) % 3 else ret = battlernumber % 2 * 2 end return ret end def ypositionformula(battlernumber) ret = 0 if !SINGLEROW ret = (battlernumber / 3) % 2 * 2 else ret = 1 end return ret end def moveSprite(i) spritename = (i > -1) ? "pokemon#{i}" : "trainer" speed = (i > -1) ? ANIMATIONSPEED : 2 if (!ANIMATION) # Skips animation @sprites[spritename].x -= speed * @xmovement[i] @xmovement[i] = 0 @sprites[spritename].y -= speed * @ymovement[i] @ymovement[i] = 0 end if (@xmovement[i] != 0) direction = (@xmovement[i] > 0) ? -1 : 1 @sprites[spritename].x += speed * direction @xmovement[i] += direction end if (@ymovement[i] != 0) direction = (@ymovement[i] > 0) ? -1 : 1 @sprites[spritename].y += speed * direction @ymovement[i] += direction end end def createBattlers(hide = true) # Movement in animation for i in 0...6 # Clear all 6 pokémon sprites and dispose the ones that exists every time # that this method is call restartSpritePosition(@sprites, "pokemon#{i}") next if i >= @hallEntry.size xpoint = xpointformula(i) ypoint = ypointformula(i) pok = @hallEntry[i] @sprites["pokemon#{i}"] = PokemonSprite.new(@viewport) @sprites["pokemon#{i}"].setOffset(PictureOrigin::TopLeft) @sprites["pokemon#{i}"].setPokemonBitmap(pok) @sprites["pokemon#{i}"].zoom_x = Settings::FRONTSPRITE_SCALE @sprites["pokemon#{i}"].zoom_y = Settings::FRONTSPRITE_SCALE # This method doesn't put the exact coordinates @sprites["pokemon#{i}"].x = xpoint @sprites["pokemon#{i}"].y = ypoint if @sprites["pokemon#{i}"].bitmap && !@sprites["pokemon#{i}"].disposed? @sprites["pokemon#{i}"].x += (128 - @sprites["pokemon#{i}"].bitmap.width) / 2 @sprites["pokemon#{i}"].y += (128 - @sprites["pokemon#{i}"].bitmap.height) / 2 end @sprites["pokemon#{i}"].z = 7 - i if SINGLEROW next if !hide # Animation distance calculation horizontal = 1 - xpositionformula(i) vertical = 1 - ypositionformula(i) xdistance = (horizontal == -1) ? -@sprites["pokemon#{i}"].bitmap.width : Graphics.width ydistance = (vertical == -1) ? -@sprites["pokemon#{i}"].bitmap.height : Graphics.height xdistance = ((xdistance - @sprites["pokemon#{i}"].x) / ANIMATIONSPEED).abs + 1 ydistance = ((ydistance - @sprites["pokemon#{i}"].y) / ANIMATIONSPEED).abs + 1 biggerdistance = (xdistance > ydistance) ? xdistance : ydistance @xmovement[i] = biggerdistance @xmovement[i] *= -1 if horizontal == -1 @xmovement[i] = 0 if horizontal == 0 @ymovement[i] = biggerdistance @ymovement[i] *= -1 if vertical == -1 @ymovement[i] = 0 if vertical == 0 # Hide the battlers @sprites["pokemon#{i}"].x += @xmovement[i] * ANIMATIONSPEED @sprites["pokemon#{i}"].y += @ymovement[i] * ANIMATIONSPEED end end def createTrainerBattler @sprites["trainer"] = IconSprite.new(@viewport) @sprites["trainer"].setBitmap(GameData::TrainerType.front_sprite_filename($Trainer.trainer_type)) if !SINGLEROW @sprites["trainer"].x = Graphics.width - 96 @sprites["trainer"].y = 160 else @sprites["trainer"].x = Graphics.width / 2 @sprites["trainer"].y = 178 end @sprites["trainer"].z = 9 @sprites["trainer"].ox = @sprites["trainer"].bitmap.width / 2 @sprites["trainer"].oy = @sprites["trainer"].bitmap.height / 2 if REMOVEBARS @sprites["overlay"].bitmap.clear @sprites["hallbars"].visible = false end @xmovement[@battlerIndex] = 0 @ymovement[@battlerIndex] = 0 if (ANIMATION && !SINGLEROW) # Trainer Animation startpoint = Graphics.width / 2 # 2 is the trainer speed @xmovement[@battlerIndex] = (startpoint - @sprites["trainer"].x) / 2 @sprites["trainer"].x = startpoint else ENTRYWAITTIME.times do Graphics.update Input.update pbUpdate end end end def getDifficulty if $game_switches[SWITCH_GAME_DIFFICULTY_EASY] return "Easy" elsif $game_switches[SWITCH_GAME_DIFFICULTY_HARD] return "Hard" else return "Normal" end end def writeTrainerData totalsec = Graphics.frame_count / Graphics.frame_rate hour = totalsec / 60 / 60 min = totalsec / 60 % 60 pubid = sprintf("%05d", $Trainer.public_ID) lefttext = _INTL("Name{1}
", $Trainer.name) lefttext += _INTL("IDNo.{1}
", pubid) lefttext += _ISPRINTF("Time{1:02d}:{2:02d}
", hour, min) lefttext += _INTL("Pokédex{1}/{2}
", $Trainer.pokedex.owned_count, $Trainer.pokedex.seen_count) lefttext += _INTL("Difficulty{1}
", getDifficulty()) @sprites["messagebox"] = Window_AdvancedTextPokemon.new(lefttext) @sprites["messagebox"].viewport = @viewport @sprites["messagebox"].width = 192 if @sprites["messagebox"].width < 192 @sprites["msgwindow"] = pbCreateMessageWindow(@viewport) pbMessageDisplay(@sprites["msgwindow"], _INTL("League champion!\nCongratulations!\\^")) end def writePokemonData(pokemon, hallNumber = -1) overlay = @sprites["overlay"].bitmap overlay.clear pokename = pokemon.name speciesname = pokemon.speciesName if pokemon.male? speciesname += "♂" elsif pokemon.female? speciesname += "♀" end pokename += "/" + speciesname pokename = _INTL("Egg") + "/" + _INTL("Egg") if pokemon.egg? idno = (pokemon.owner.name.empty? || pokemon.egg?) ? "?????" : sprintf("%05d", pokemon.owner.public_id) dexnumber = _INTL("No. ???") if !pokemon.egg? species_data = GameData::Species.get(pokemon.species) dexnumber = _ISPRINTF("No. {1:03d}", species_data.id_number) end textPositions = [ [dexnumber, 32, Graphics.height - 86, 0, BASECOLOR, SHADOWCOLOR], [pokename, Graphics.width - 192, Graphics.height - 86, 2, BASECOLOR, SHADOWCOLOR], [_INTL("Lv. {1}", pokemon.egg? ? "?" : pokemon.level), 64, Graphics.height - 54, 0, BASECOLOR, SHADOWCOLOR], [_INTL("IDNo.{1}", pokemon.egg? ? "?????" : idno), Graphics.width - 192, Graphics.height - 54, 2, BASECOLOR, SHADOWCOLOR] ] if (hallNumber > -1) textPositions.push([_INTL("Hall of Fame No."), Graphics.width / 2 - 104, -6, 0, BASECOLOR, SHADOWCOLOR]) textPositions.push([hallNumber.to_s, Graphics.width / 2 + 104, -6, 1, BASECOLOR, SHADOWCOLOR]) end pbDrawTextPositions(overlay, textPositions) end def writeWelcome overlay = @sprites["overlay"].bitmap overlay.clear pbDrawTextPositions(overlay, [[_INTL("Welcome to the Hall of Fame!"), Graphics.width / 2, Graphics.height - 80, 2, BASECOLOR, SHADOWCOLOR]]) writeCurrentDate(overlay, 120 , Graphics.height - 50) writeGameMode(overlay, (Graphics.width / 2) + 100, Graphics.height - 50) end def writeCurrentDate(overlay, x, y) currentTime = Time.new timeString = currentTime.year.to_s + "-" + ("%02d" % currentTime.month) + "-" + ("%02d" % currentTime.day) pbDrawTextPositions(overlay, [[_INTL("{1}", timeString), x, y, 2, BASECOLOR, SHADOWCOLOR]]) end def writeGameMode(overlay, x, y) gameMode = "Classic mode" if $game_switches[SWITCH_MODERN_MODE] gameMode = "Remix mode" end if $game_switches[SWITCH_EXPERT_MODE] gameMode = "Expert mode" end if $game_switches[SWITCH_SINGLE_POKEMON_MODE] pokemon_number = pbGet(VAR_SINGLE_POKEMON_MODE) if pokemon_number.is_a?(Integer) && pokemon_number >0 pokemon = GameData::Species.get(pokemon_number) gameMode = pokemon.real_name + " mode" else gameMode = "Debug mode" end end if $game_switches[SWITCH_RANDOMIZED_AT_LEAST_ONCE] gameMode = "Randomized mode" end if $game_switches[ENABLED_DEBUG_MODE_AT_LEAST_ONCE] || $DEBUG gameMode = "Debug mode" end pbDrawTextPositions(overlay, [[_INTL("{1} ({2})", gameMode, getDifficulty), x, y, 2, BASECOLOR, SHADOWCOLOR]]) end def pbAnimationLoop loop do Graphics.update Input.update pbUpdate pbUpdateAnimation break if @battlerIndex == @hallEntry.size + 2 end end def pbPCSelection loop do Graphics.update Input.update pbUpdate continueScene = true break if Input.trigger?(Input::BACK) # Exits if Input.trigger?(Input::USE) # Moves the selection one entry backward @battlerIndex += 10 continueScene = pbUpdatePC end if Input.trigger?(Input::LEFT) # Moves the selection one pokémon forward @battlerIndex -= 1 continueScene = pbUpdatePC end if Input.trigger?(Input::RIGHT) # Moves the selection one pokémon backward @battlerIndex += 1 continueScene = pbUpdatePC end break if !continueScene end end def pbUpdate pbUpdateSpriteHash(@sprites) end def pbUpdateAnimation if @battlerIndex <= @hallEntry.size if @xmovement[@battlerIndex] != 0 || @ymovement[@battlerIndex] != 0 spriteIndex = (@battlerIndex < @hallEntry.size) ? @battlerIndex : -1 moveSprite(spriteIndex) else @battlerIndex += 1 if @battlerIndex <= @hallEntry.size # If it is a pokémon, write the pokémon text, wait the # ENTRYWAITTIME and goes to the next battler @hallEntry[@battlerIndex - 1].play_cry writePokemonData(@hallEntry[@battlerIndex - 1]) (ENTRYWAITTIME * Graphics.frame_rate / 20).times do Graphics.update Input.update pbUpdate end if @battlerIndex < @hallEntry.size # Preparates the next battler setPokemonSpritesOpacity(@battlerIndex, OPACITY) @sprites["overlay"].bitmap.clear else # Show the welcome message and preparates the trainer setPokemonSpritesOpacity(-1) writeWelcome (ENTRYWAITTIME * 2 * Graphics.frame_rate / 20).times do Graphics.update Input.update pbUpdate end while !(waitForInput) Graphics.update Input.update pbUpdate end setPokemonSpritesOpacity(-1, OPACITY) if !SINGLEROW createTrainerBattler end end end elsif @battlerIndex > @hallEntry.size # Write the trainer data and fade writeTrainerData (ENTRYWAITTIME * Graphics.frame_rate / 20).times do Graphics.update Input.update pbUpdate end fadeSpeed = ((Math.log(2 ** 12) - Math.log(FINALFADESPEED)) / Math.log(2)).floor pbBGMFade((2 ** fadeSpeed).to_f / 20) if @useMusic slowFadeOut(@sprites, fadeSpeed) { pbUpdate } @alreadyFadedInEnd = true @battlerIndex += 1 end end def waitForInput if Input.trigger?(Input::USE) || Input.trigger?(Input::BACK) return true end return false end def pbUpdatePC # Change the team if @battlerIndex >= @hallEntry.size @hallIndex -= 1 return false if @hallIndex == -1 @hallEntry = $PokemonGlobal.hallOfFame[@hallIndex] @battlerIndex = 0 createBattlers(false) elsif @battlerIndex < 0 @hallIndex += 1 return false if @hallIndex >= $PokemonGlobal.hallOfFame.size @hallEntry = $PokemonGlobal.hallOfFame[@hallIndex] @battlerIndex = @hallEntry.size - 1 createBattlers(false) end # Change the pokemon @hallEntry[@battlerIndex].play_cry setPokemonSpritesOpacity(@battlerIndex, OPACITY) hallNumber = $PokemonGlobal.hallOfFameLastNumber + @hallIndex - $PokemonGlobal.hallOfFame.size + 1 writePokemonData(@hallEntry[@battlerIndex], hallNumber) return true end end #=============================================================================== # #=============================================================================== class HallOfFameScreen def initialize(scene) @scene = scene end def pbStartScreenEntry @scene.pbStartSceneEntry @scene.pbAnimationLoop @scene.pbEndScene end def pbStartScreenPC @scene.pbStartScenePC @scene.pbPCSelection @scene.pbEndScene end end #=============================================================================== # #=============================================================================== class HallOfFamePC def shouldShow? return $PokemonGlobal.hallOfFameLastNumber > 0 end def name return _INTL("Hall of Fame") end def access pbMessage(_INTL("\\se[PC access]Accessed the Hall of Fame.")) pbHallOfFamePC end end #=============================================================================== # #=============================================================================== PokemonPCList.registerPC(HallOfFamePC.new) #=============================================================================== # #=============================================================================== class PokemonGlobalMetadata attr_writer :hallOfFame # Number necessary if hallOfFame array reach in its size limit attr_writer :hallOfFameLastNumber def hallOfFame @hallOfFame = [] if !@hallOfFame return @hallOfFame end def hallOfFameLastNumber return @hallOfFameLastNumber || 0 end end #=============================================================================== # #=============================================================================== def pbHallOfFameEntry scene = HallOfFame_Scene.new screen = HallOfFameScreen.new(scene) screen.pbStartScreenEntry end def pbHallOfFamePC scene = HallOfFame_Scene.new screen = HallOfFameScreen.new(scene) screen.pbStartScreenPC end