Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #===============================================================================
- # SOS Battles - By Vendily [v17]
- #===============================================================================
- # This script adds in SOS Battles, the added mechanic from Alola, where
- # Pokémon have a chance of calling for aid while in battle.
- # This version of the script does not implement special weather based encounters
- # but does have a method that can be edited to do so.
- # The script also defines the manually used effect of the Adrenaline Orb item.
- #===============================================================================
- # To use it, you must add species that are able to SOS call in the SOS_CALL_RATES
- # hash. The key is the species symbol, and the value is the rate in percentage
- # the mon will call at.
- # AKA. :BULBASAUR=>100 is a valid entry
- #
- # Optionally, you may add species to SOS_CALL_MONS, the species that
- # the mon will call for. Add more entries of the same species to make them more
- # likely. The Key is the species symbol, and the value is an array of species.
- # AKA. :BULBASAUR=>[:BULBASAUR,:BULBASAUR,:BULBASAUR,:IVYSAUR,:IVYSAUR,:VENUSAUR]
- # is a valid entry.
- # If you don't have an entry for a calling species, it will call another mon of
- # the same species as itself.
- #
- # To implement the doubled EV points in an SOS battle, there is an additional
- # edit to "def pbGainExpOne" in PokeBattle_Battle
- # under:
- # evgain*=2 if thispoke.pokerusStage>=1 # Infected or cured
- # put:
- # evgain*=2 if @sosbattle
- #
- # If you wish to implement special called allies, edit the array returned by
- # pbSpecialSOSMons. By default, it just passes through the regular array used.
- # The method also takes the calling battler, if you wish to check its properties.
- #===============================================================================
- # * Hash containing base species call rates
- # * Hash containing species called allies
- # * Switch id to enable/disable SOS battles. Set to <1 to not check.
- #===============================================================================
- SOS_CALL_RATES={}
- SOS_CALL_MONS={}
- NO_SOS_BATTLES = -1
- class PokeBattle_Battle
- attr_accessor :adrenalineorb
- attr_accessor :lastturncalled
- attr_accessor :lastturnanswered
- attr_accessor :soschain
- attr_accessor :sosbattle
- attr_accessor :wasdoublebattle
- def soschain
- return @soschain || 0
- end
- def pbSpecialSOSMons(caller,mons)
- return mons
- end
- def pbCallForHelp(index,caller)
- cspecies=getConstantName(PBSpecies,caller.species).to_sym
- rate=SOS_CALL_RATES[cspecies] || 0
- return if rate==0 # should never trigger anyways but you never know.
- pbDisplay(_INTL("{1} called for help!", caller.pbThis))
- rate*=4 # base rate
- rate=rate.to_f # don't want to lose decimal points
- pbattler=@battlers[0]
- if pbattler.hasWorkingAbility(:INTIMIDATE) ||
- pbattler.hasWorkingAbility(:UNNERVE) ||
- pbattler.hasWorkingAbility(:PRESSURE)
- rate*=1.2
- end
- if @lastturncalled==@turncount-1
- rate*=1.5
- end
- if !@lastturnanswered
- rate*=3.0
- end
- rate=rate.round # rounding it off.
- pbDisplayBrief(_INTL("... ... ..."))
- if pbRandom(100)<rate
- @lastturnanswered=true
- @lastturncalled=@turncount
- mons=SOS_CALL_MONS[cspecies] || [caller.species]
- mons=pbSpecialSOSMons(caller,mons)
- mon=mons[pbRandom(mons.length)]
- alevel=caller.level-1
- alevel=1 if alevel<1
- ally=pbGenerateSOSPokemon(getID(PBSpecies,mon),alevel)
- @battlers[index].pbInitialize(ally,(index>>1),false)
- @wasdoublebattle=@doublebattle if @wasdoublebattle.nil?
- @doublebattle=true if !@doublebattle
- @sosbattle=true
- @scene.pbSOSJoin(index,ally)
- pbDisplayBrief(_INTL("{1} appeared!",@battlers[index].pbThis))
- caller.pbPartner.effects[PBEffects::SkipTurn]=true
- caller.effects[PBEffects::SkipTurn]=true
- @party2.push(ally)
- else
- @lastturnanswered=false
- pbDisplay(_INTL("Its help didn't appear!"))
- end
- end
- def pbGenerateSOSPokemon(species,level)
- genwildpoke = PokeBattle_Pokemon.new(species,level,$Trainer)
- items = genwildpoke.wildHoldItems
- firstpoke = @battlers[0]
- chances = [50,5,1]
- chances = [60,20,5] if firstpoke.hasWorkingAbility(:COMPOUNDEYES)
- itemrnd = rand(100)
- if itemrnd<chances[0] || (items[0]==items[1] && items[1]==items[2])
- genwildpoke.setItem(items[0])
- elsif itemrnd<(chances[0]+chances[1])
- genwildpoke.setItem(items[1])
- elsif itemrnd<(chances[0]+chances[1]+chances[2])
- genwildpoke.setItem(items[2])
- end
- if hasConst?(PBItems,:SHINYCHARM) && $PokemonBag.pbHasItem?(:SHINYCHARM)
- for i in 0...2 # 3 times as likely
- break if genwildpoke.isShiny?
- genwildpoke.personalID = rand(65536)|(rand(65536)<<16)
- end
- end
- chain=self.soschain
- shinychain=(chain/10)
- shinychain-=1 if chain%10==0
- if shinychain>0
- for i in 0...shinychain
- break if genwildpoke.isShiny?
- genwildpoke.personalID = rand(65536)|(rand(65536)<<16)
- end
- end
- ivchain=(chain/10)
- ivchain+=1 if chain>=5
- ivs=(0..5).to_a
- ivs.shuffle!
- if ivchain>0
- for i in 0...ivchain
- break if ivs.length==0
- iv=ivs.shift
- genwildpoke.ivs[iv]=31
- end
- end
- hachain=(chain/10)
- if hachain>0
- genwildpoke.setAbility(2) if pbRandom(100)<hachain*5
- end
- if rand(65536)<POKERUSCHANCE
- genwildpoke.givePokerus
- end
- if firstpoke.hasWorkingAbility(:CUTECHARM) && !genwildpoke.isSingleGendered?
- if firstpoke.gender==0
- (rand(3)<2) ? genwildpoke.makeFemale : genwildpoke.makeMale
- elsif firstpoke.gender==1
- (rand(3)<2) ? genwildpoke.makeMale : genwildpoke.makeFemale
- end
- elsif firstpoke.hasWorkingAbility(:SYNCHRONIZE)
- genwildpoke.setNature(firstpoke.nature) if rand(10)<5
- end
- Events.onWildPokemonCreate.trigger(nil,genwildpoke)
- return genwildpoke
- end
- def pbSwitch(favorDraws=false)
- if !favorDraws
- return if @decision>0
- else
- return if @decision==5
- end
- pbJudge()
- return if @decision>0
- firstbattlerhp=@battlers[0].hp
- switched=[]
- for index in 0...4
- next if !@doublebattle && pbIsDoubleBattler?(index)
- next if @battlers[index] && !@battlers[index].fainted?
- next if !pbCanChooseNonActive?(index)
- if !pbOwnedByPlayer?(index)
- if !pbIsOpposing?(index) || (@opponent && pbIsOpposing?(index))
- newenemy=pbSwitchInBetween(index,false,false)
- newenemyname=newenemy
- if newenemy>=0 && isConst?(pbParty(index)[newenemy].ability,PBAbilities,:ILLUSION)
- newenemyname=pbGetLastPokeInTeam(index)
- end
- opponent=pbGetOwner(index)
- if !@doublebattle && firstbattlerhp>0 && @shiftStyle && @opponent &&
- @internalbattle && pbCanChooseNonActive?(0) && pbIsOpposing?(index) &&
- @battlers[0].effects[PBEffects::Outrage]==0
- pbDisplayPaused(_INTL("{1} is about to send in {2}.",opponent.fullname,pbParty(index)[newenemyname].name))
- if pbDisplayConfirm(_INTL("Will {1} change Pokémon?",self.pbPlayer.name))
- newpoke=pbSwitchPlayer(0,true,true)
- if newpoke>=0
- newpokename=newpoke
- if isConst?(@party1[newpoke].ability,PBAbilities,:ILLUSION)
- newpokename=pbGetLastPokeInTeam(0)
- end
- pbDisplayBrief(_INTL("{1}, that's enough! Come back!",@battlers[0].name))
- pbRecallAndReplace(0,newpoke,newpokename)
- switched.push(0)
- end
- end
- end
- pbRecallAndReplace(index,newenemy,newenemyname,false,false)
- switched.push(index)
- end
- elsif @opponent
- newpoke=pbSwitchInBetween(index,true,false)
- newpokename=newpoke
- if isConst?(@party1[newpoke].ability,PBAbilities,:ILLUSION)
- newpokename=pbGetLastPokeInTeam(index)
- end
- pbRecallAndReplace(index,newpoke,newpokename)
- switched.push(index)
- else
- next if @sosbattle && !@wasdoublebattle
- switch=false
- if !pbDisplayConfirm(_INTL("Use next Pokémon?"))
- switch=(pbRun(index,true)<=0)
- else
- switch=true
- end
- if switch
- newpoke=pbSwitchInBetween(index,true,false)
- newpokename=newpoke
- if isConst?(@party1[newpoke].ability,PBAbilities,:ILLUSION)
- newpokename=pbGetLastPokeInTeam(index)
- end
- pbRecallAndReplace(index,newpoke,newpokename)
- switched.push(index)
- end
- end
- end
- if switched.length>0
- priority=pbPriority
- for i in priority
- i.pbAbilitiesOnSwitchIn(true) if switched.include?(i.index)
- end
- end
- end
- end
- class PokeBattle_Battler
- def pbCanCall?
- return false if NO_SOS_BATTLES>0 && $game_switches[NO_SOS_BATTLES]
- # only wild battles
- return false if @opponent
- # only wild mons
- return false if !@battle.pbIsOpposing?(self.index)
- # can't call if partner already in
- return false if !self.pbPartner.fainted?
- # just to be safe
- return false if self.fainted?
- # no call if status
- return false if self.status!=0
- # no call if multiturn attack
- return false if self.effects[PBEffects::TwoTurnAttack]>0
- return false if self.effects[PBEffects::HyperBeam]>0
- return false if self.effects[PBEffects::Rollout]>0
- return false if self.effects[PBEffects::Outrage]>0
- return false if self.effects[PBEffects::Uproar]>0
- return false if self.effects[PBEffects::Bide]>0
- species=getConstantName(PBSpecies,self.species).to_sym
- rate=SOS_CALL_RATES[species] || 0
- # not a species that calls
- return false if rate==0
- rate*=3 if self.hp>(self.totalhp/4) && self.hp<=(self.totalhp/2)
- rate*=5 if self.hp<=(self.totalhp/4)
- rate*=2 if @battle.adrenalineorb
- return @battle.pbRandom(100)<rate
- end
- def pbProcessTurn(choice)
- # Can't use a move if fainted
- return false if fainted?
- # Wild roaming Pokémon always flee if possible
- if !@battle.opponent && @battle.pbIsOpposing?(self.index) &&
- @battle.rules["alwaysflee"] && @battle.pbCanRun?(self.index)
- pbBeginTurn(choice)
- @battle.pbDisplay(_INTL("{1} fled!",self.pbThis))
- @battle.decision=3
- pbEndTurn(choice)
- PBDebug.log("[Escape] #{pbThis} fled")
- return true
- end
- if pbCanCall?
- pbCancelMoves
- @battle.pbCallForHelp(self.pbPartner.index,self)
- pbEndTurn(choice)
- return true
- end
- # If this battler's action for this round wasn't "use a move"
- if choice[0]!=1
- # Clean up effects that end at battler's turn
- pbBeginTurn(choice)
- pbEndTurn(choice)
- return false
- end
- # Turn is skipped if Pursuit was used during switch
- if @effects[PBEffects::Pursuit]
- @effects[PBEffects::Pursuit]=false
- pbCancelMoves
- pbEndTurn(choice)
- @battle.pbJudge # @battle.pbSwitch
- return false
- end
- # Use the move
- # @battle.pbDisplayPaused("Before: [#{@lastMoveUsedSketch},#{@lastMoveUsed}]")
- PBDebug.log("#{pbThis} used #{choice[2].name}")
- PBDebug.logonerr{
- pbUseMove(choice,choice[2]==@battle.struggle)
- }
- # @battle.pbDisplayPaused("After: [#{@lastMoveUsedSketch},#{@lastMoveUsed}]")
- return true
- end
- end
- class PokeBattle_Scene
- def pbSelectBattler(index,selectmode=1)
- numwindows=@battle.doublebattle ? 4 : 2
- for i in 0...numwindows
- next if @battle.sosbattle && !@battle.wasdoublebattle && i == 2
- sprite=@sprites["battlebox#{i}"]
- sprite.selected=(i==index) ? selectmode : 0
- sprite=@sprites["pokemon#{i}"]
- sprite.selected=(i==index) ? selectmode : 0
- end
- end
- def pbUpdateSelected(index)
- numwindows=@battle.doublebattle ? 4 : 2
- for i in 0...numwindows
- next if @battle.sosbattle && !@battle.wasdoublebattle && (i == 2)
- if i==index
- @sprites["battlebox#{i}"].selected=2
- @sprites["pokemon#{i}"].selected=2
- else
- @sprites["battlebox#{i}"].selected=0
- @sprites["pokemon#{i}"].selected=0
- end
- end
- pbFrameUpdate
- end
- def pbSOSJoin(battlerindex,pkmn)
- @briefmessage=false
- frame=0
- if !@sprites["pokemon#{battlerindex}"]
- @sprites["pokemon#{battlerindex}"]=PokemonBattlerSprite.new(@battle.doublebattle,battlerindex,@viewport)
- @sprites["pokemon#{battlerindex}"].z=(battlerindex==3)? 11 : 26
- if battlerindex&1==1
- pbAddSprite("shadow#{battlerindex}",0,0,"Graphics/Pictures/Battle/object_shadow",@viewport)
- else
- @sprites["shadow#{battlerindex}"]=IconSprite.new(0,0,@viewport)
- end
- @sprites["shadow#{battlerindex}"].z=3
- @sprites["shadow#{battlerindex}"].visible=false
- end
- @sprites["pokemon#{battlerindex}"].setPokemonBitmap(pkmn,false)
- sendout=SOSJoinAnimation.new(@sprites["pokemon#{battlerindex}"],
- @sprites,@battle.battlers[battlerindex],@battle.doublebattle,@battle)
- partnerindex=-1
- if !@sprites["battlebox#{battlerindex}"]
- partnerindex=(battlerindex&1)|((battlerindex&2)^2)
- @sprites["battlebox#{battlerindex}"]=PokemonDataBox.new(@battle.battlers[battlerindex],@battle.doublebattle,@viewport)
- @sprites["battlebox#{partnerindex}"].dispose
- @sprites["battlebox#{partnerindex}"]=PokemonDataBox.new(@battle.battlers[partnerindex],@battle.doublebattle,@viewport)
- end
- loop do
- frame+=1
- if frame==1
- @sprites["battlebox#{battlerindex}"].appear
- if partnerindex>=0
- @sprites["battlebox#{partnerindex}"].appear
- end
- end
- if frame>=6
- sendout.update
- end
- pbGraphicsUpdate
- pbInputUpdate
- pbFrameUpdate
- break if sendout.animdone? &&
- !@sprites["battlebox#{battlerindex}"].appearing
- end
- if @battle.battlers[battlerindex].isShiny? && @battle.battlescene
- pbCommonAnimation("Shiny",@battle.battlers[battlerindex],nil)
- end
- sendout.dispose
- pbRefresh
- end
- end
- class SOSJoinAnimation
- def initialize(sprite,spritehash,pkmn,doublebattle,battle)
- @disposed=false
- @PokemonBattlerSprite=sprite
- @PokemonBattlerSprite.visible=false
- @PokemonBattlerSprite.src_rect.height=@PokemonBattlerSprite.bitmap.height
- @PokemonBattlerSprite.oy=0
- @PokemonBattlerSprite.tone=Tone.new(0,0,0,248)
- if doublebattle
- @spritex=PokeBattle_SceneConstants::FOEBATTLERD1_X if pkmn.index==1
- @spritex=PokeBattle_SceneConstants::FOEBATTLERD2_X if pkmn.index==3
- else
- @spritex=PokeBattle_SceneConstants::FOEBATTLER_X
- end
- @spritey=adjustBattleSpriteY(sprite,pkmn.species,pkmn.index)
- if doublebattle
- @spritey+=PokeBattle_SceneConstants::FOEBATTLERD1_Y if pkmn.index==1
- @spritey+=PokeBattle_SceneConstants::FOEBATTLERD2_Y if pkmn.index==3
- else
- @spritey+=PokeBattle_SceneConstants::FOEBATTLER_Y
- end
- @spritehash=spritehash
- @pkmn=pkmn
- @shadowX=@spritex
- @shadowY=@spritey/2
- if @spritehash["shadow#{@pkmn.index}"] && @spritehash["shadow#{@pkmn.index}"].bitmap!=nil
- @shadowX-=@spritehash["shadow#{@pkmn.index}"].bitmap.width/2
- @shadowY-=@spritehash["shadow#{@pkmn.index}"].bitmap.height/2
- end
- if @spritehash["pokemon#{@pkmn.pbPartner.index}"]
- pindex=@pkmn.pbPartner.index
- pmon=battle.battlers[pindex]
- case pindex
- when 1
- @spritehash["pokemon#{pindex}"].x=PokeBattle_SceneConstants::FOEBATTLERD1_X
- @spritehash["pokemon#{pindex}"].y=PokeBattle_SceneConstants::FOEBATTLERD1_Y
- when 3
- @spritehash["pokemon#{pindex}"].x=PokeBattle_SceneConstants::FOEBATTLERD2_X
- @spritehash["pokemon#{pindex}"].y=PokeBattle_SceneConstants::FOEBATTLERD2_Y
- end
- @spritehash["pokemon#{pindex}"].x-=@spritehash["pokemon#{pindex}"].bitmap.width/2
- @spritehash["pokemon#{pindex}"].y+=adjustBattleSpriteY(@spritehash["pokemon#{pindex}"],pmon.species,pmon.index)
- if @spritehash["shadow#{@pkmn.index}"] && @spritehash["shadow#{@pkmn.index}"].bitmap!=nil
- @spritehash["shadow#{@pkmn.index}"].x=@spritehash["pokemon#{pindex}"].x
- @spritehash["shadow#{@pkmn.index}"].x-=@spritehash["shadow#{@pkmn.index}"].bitmap.width/2
- @spritehash["shadow#{@pkmn.index}"].y=@spritehash["pokemon#{pindex}"].y/2
- @spritehash["shadow#{@pkmn.index}"].y-=@spritehash["shadow#{@pkmn.index}"].bitmap.height/2
- end
- end
- @shadowVisible=showShadow?(pkmn.species)
- @animdone=false
- @frame=0
- end
- def disposed?
- return @disposed
- end
- def animdone?
- return @animdone
- end
- def dispose
- return if disposed?
- @disposed=true
- end
- def update
- return if disposed?
- @frame+=1
- if @frame==4
- if @spritehash["shadow#{@pkmn.index}"]
- @spritehash["shadow#{@pkmn.index}"].x=@shadowX
- @spritehash["shadow#{@pkmn.index}"].y=@shadowY
- @spritehash["shadow#{@pkmn.index}"].visible=@shadowVisible
- end
- @PokemonBattlerSprite.visible=true
- pbSpriteSetCenter(@PokemonBattlerSprite,@spritex,@spritey)
- @PokemonBattlerSprite.y=@spritey
- if @pkmn.pokemon
- pbPlayCry(@pkmn.pokemon)
- else
- pbPlayCrySpecies(@pkmn.species,@pkmn.form)
- end
- end
- if @frame>8 && @frame<=24
- tone=(16-@frame)*32
- @PokemonBattlerSprite.tone=Tone.new(0,0,0,tone)
- end
- if @PokemonBattlerSprite.tone.gray<=0
- @animdone=true
- end
- end
- end
- ItemHandlers::BattleUseOnBattler.add(:ADRENALINEORB,proc{|item,battler,scene|
- battle=battler.battle
- if battle.adrenalineorb
- scene.pbDisplay(_INTL("Already used that."))
- return false
- end
- playername=battle.pbPlayer.name
- scene.pbDisplay(_INTL("{1} used the {2}.",playername,PBItems.getName(item)))
- return true
- })
- ItemHandlers::UseInBattle.add(:ADRENALINEORB,proc{|item,battler,battle|
- battle.adrenalineorb=true
- battle.pbDisplayPaused(_INTL("The {1} makes the wild Pokémon nervous!",PBItems.getName(item)))
- })
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement