class BugContestState attr_accessor :ballcount attr_accessor :decision attr_accessor :lastPokemon attr_reader :timer ContestantNames = [ _INTL("Bug Catcher Ed"), _INTL("Bug Catcher Benny"), _INTL("Bug Catcher Josh"), _INTL("Camper Barry"), _INTL("Cool Trainer Nick"), _INTL("Lass Abby"), _INTL("Picnicker Cindy"), _INTL("Youngster Samuel") ] TimerSeconds = Settings::BUG_CONTEST_TIME def initialize clear @lastContest=nil end def pbContestHeld? return false if !@lastContest timenow=pbGetTimeNow return timenow.to_i-@lastContest<86400 end def expired? return false if !undecided? return false if TimerSeconds<=0 curtime=@timer+TimerSeconds*Graphics.frame_rate curtime=[curtime-Graphics.frame_count,0].max return (curtime<=0) end def clear @ballcount=0 @ended=false @inProgress=false @decision=0 @encounterMap=0 @lastPokemon=nil @otherparty=[] @contestants=[] @places=[] @start=nil @reception=[] end def inProgress? return @inProgress end def undecided? return (@inProgress && @decision==0) end def decided? return (@inProgress && @decision!=0) || @ended end def pbSetPokemon(chosenpoke) @chosenPokemon=chosenpoke end # Reception map is handled separately from contest map since the reception map # can be outdoors, with its own grassy patches. def pbSetReception(*arg) @reception=[] for i in arg @reception.push(i) end end def pbOffLimits?(map) # p [map,@contestMap,@reception] return false if map==@contestMap for i in @reception return false if map==i end return true end def pbSetJudgingPoint(startMap,startX,startY,dir=8) @start=[startMap,startX,startY,dir] end def pbSetContestMap(map) @contestMap=map end def pbJudge judgearray=[] if @lastPokemon judgearray.push([-1,@lastPokemon.species,pbBugContestScore(@lastPokemon)]) end @contestants=[] [5,ContestantNames.length].min.times do loop do value=rand(ContestantNames.length) if !@contestants.any? { |i| i==value } @contestants.push(value) break end end end enctype = :BugContest if !$PokemonEncounters.map_has_encounter_type?(@contestMap, enctype) enctype = :Land end for cont in @contestants enc=$PokemonEncounters.choose_wild_pokemon_for_map(@contestMap,enctype) if !enc raise _INTL("No encounters for map {1}, so can't judge contest",@contestMap) end pokemon=Pokemon.new(enc[0],enc[1]) pokemon.hp = rand(1..pokemon.totalhp - 1) score=pbBugContestScore(pokemon) judgearray.push([cont,pokemon.species,score]) end if judgearray.length<3 raise _INTL("Too few bug catching contestants") end judgearray.sort! { |a,b| b[2]<=>a[2] } # sort by score in descending order @places.push(judgearray[0]) @places.push(judgearray[1]) @places.push(judgearray[2]) end def pbGetPlaceInfo(place) cont=@places[place][0] if cont<0 $game_variables[1]=$Trainer.name else $game_variables[1]=ContestantNames[cont] end $game_variables[2]=GameData::Species.get(@places[place][1]).name $game_variables[3]=@places[place][2] end def pbClearIfEnded clear if !@inProgress && (!@start || @start[0] != $game_map.map_id) end def pbStartJudging @decision=1 pbJudge if $scene.is_a?(Scene_Map) pbFadeOutIn { $game_temp.player_transferring = true $game_temp.player_new_map_id = @start[0] $game_temp.player_new_x = @start[1] $game_temp.player_new_y = @start[2] $game_temp.player_new_direction = @start[3] $scene.transfer_player $game_map.need_refresh = true # in case player moves to the same map } end end def pbIsContestant?(i) return @contestants.any? { |item| i==item } end def pbStart(ballcount) @ballcount=ballcount @inProgress=true @otherparty=[] @lastPokemon=nil @lastContest=nil @timer=Graphics.frame_count @places=[] chosenpkmn=$Trainer.party[@chosenPokemon] for i in 0...$Trainer.party.length @otherparty.push($Trainer.party[i]) if i!=@chosenPokemon end @contestants=[] [5,ContestantNames.length].min.times do loop do value=rand(ContestantNames.length) if !@contestants.any? { |i| i==value } @contestants.push(value) break end end end $Trainer.party=[chosenpkmn] @decision=0 @ended=false end def place for i in 0...3 return i if @places[i][0]<0 end return 3 end def pbEnd(interrupted=false) return if !@inProgress for poke in @otherparty $Trainer.party.push(poke) end if !interrupted if @lastPokemon pbNicknameAndStore(@lastPokemon) end @ended=true else @ended=false end @lastPokemon=nil @otherparty=[] @reception=[] @ballcount=0 @inProgress=false @decision=0 timenow=pbGetTimeNow @lastContest=timenow.to_i $game_map.need_refresh=true end end class TimerDisplay # :nodoc: def initialize(start,maxtime) @timer=Window_AdvancedTextPokemon.newWithSize("",Graphics.width-120,0,120,64) @timer.z=99999 @total_sec=nil @start=start @maxtime=maxtime end def dispose @timer.dispose end def disposed? @timer.disposed? end def update curtime=[(@start+@maxtime)-Graphics.frame_count,0].max curtime/=Graphics.frame_rate if curtime != @total_sec # Calculate total number of seconds @total_sec = curtime # Make a string for displaying the timer min = @total_sec / 60 sec = @total_sec % 60 @timer.text = _ISPRINTF("{1:02d}:{2:02d}", min, sec) end end end # Returns a score for this Pokemon in the Bug Catching Contest. # Not exactly the HGSS calculation, but it should be decent enough. def pbBugContestScore(pkmn) levelscore = pkmn.level * 4 ivscore = 0 pkmn.iv.each_value { |iv| ivscore += iv.to_f / Pokemon::IV_STAT_LIMIT } ivscore = (ivscore * 100).floor hpscore = (100.0 * pkmn.hp / pkmn.totalhp).floor catch_rate = pkmn.species_data.catch_rate rarescore = 60 rarescore += 20 if catch_rate <= 120 rarescore += 20 if catch_rate <= 60 return levelscore + ivscore + hpscore + rarescore end def pbBugContestState if !$PokemonGlobal.bugContestState $PokemonGlobal.bugContestState=BugContestState.new end return $PokemonGlobal.bugContestState end # Returns true if the Bug Catching Contest in progress def pbInBugContest? return pbBugContestState.inProgress? end # Returns true if the Bug Catching Contest in progress and has not yet been judged def pbBugContestUndecided? return pbBugContestState.undecided? end # Returns true if the Bug Catching Contest in progress and is being judged def pbBugContestDecided? return pbBugContestState.decided? end Events.onMapChange += proc { |_sender,_e| pbBugContestState.pbClearIfEnded } Events.onMapSceneChange += proc { |_sender,e| scene=e[0] if pbInBugContest? && pbBugContestState.decision==0 && BugContestState::TimerSeconds>0 scene.spriteset.addUserSprite(TimerDisplay.new( pbBugContestState.timer, BugContestState::TimerSeconds*Graphics.frame_rate)) end } Events.onMapUpdate += proc { |_sender,_e| if !$game_player.move_route_forcing && !pbMapInterpreterRunning? && !$game_temp.message_window_showing if pbBugContestState.expired? pbMessage(_INTL("ANNOUNCER: BEEEEEP!")) pbMessage(_INTL("Time's up!")) pbBugContestState.pbStartJudging end end } Events.onMapChanging += proc { |_sender,e| newmapID=e[0] if pbInBugContest? if pbBugContestState.pbOffLimits?(newmapID) # Clear bug contest if player flies/warps/teleports out of the contest pbBugContestState.pbEnd(true) end end } def pbBugContestStartOver $Trainer.party.each do |pkmn| pkmn.heal pkmn.makeUnmega pkmn.makeUnprimal end pbBugContestState.pbStartJudging end Events.onWildBattleOverride += proc { |_sender,e| species = e[0] level = e[1] handled = e[2] next if handled[0]!=nil next if !pbInBugContest? handled[0] = pbBugContestBattle(species,level) } def pbBugContestBattle(species,level) # Record information about party Pokémon to be used at the end of battle (e.g. # comparing levels for an evolution check) Events.onStartBattle.trigger(nil) # Generate a wild Pokémon based on the species and level pkmn = pbGenerateWildPokemon(species,level) foeParty = [pkmn] # Calculate who the trainers and their party are playerTrainer = [$Trainer] playerParty = $Trainer.party playerPartyStarts = [0] # Create the battle scene (the visual side of it) scene = pbNewBattleScene # Create the battle class (the mechanics side of it) battle = PokeBattle_BugContestBattle.new(scene,playerParty,foeParty,playerTrainer,nil) battle.party1starts = playerPartyStarts battle.ballCount = pbBugContestState.ballcount setBattleRule("single") pbPrepareBattle(battle) # Perform the battle itself decision = 0 pbBattleAnimation(pbGetWildBattleBGM(foeParty),0,foeParty) { decision = battle.pbStartBattle pbAfterBattle(decision,true) if decision==2 || decision==5 # Lost or drew $game_system.bgm_unpause $game_system.bgs_unpause pbBugContestStartOver end } Input.update # Update Bug Contest game data based on result of battle pbBugContestState.ballcount = battle.ballCount if pbBugContestState.ballcount==0 pbMessage(_INTL("ANNOUNCER: The Bug-Catching Contest is over!")) pbBugContestState.pbStartJudging end # Save the result of the battle in Game Variable 1 # 0 - Undecided or aborted # 1 - Player won # 2 - Player lost # 3 - Player or wild Pokémon ran from battle, or player forfeited the match # 4 - Wild Pokémon was caught # 5 - Draw pbSet(1,decision) # Used by the Poké Radar to update/break the chain Events.onWildBattleEnd.trigger(nil,species,level,decision) # Return false if the player lost or drew the battle, and true if any other result return (decision!=2 && decision!=5) end