Files
infinitefusion-e18/Data/Scripts/018_Alternate battle modes/002_BugContest.rb
2021-04-17 23:45:42 +01:00

399 lines
10 KiB
Ruby

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("<ac>{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