Initial commit

This commit is contained in:
Maruno17
2020-09-04 22:00:59 +01:00
commit ba94119d02
300 changed files with 227558 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
#===============================================================================
# Terrain tags
#===============================================================================
module PBTerrain
Ledge = 1
Grass = 2
Sand = 3
Rock = 4
DeepWater = 5
StillWater = 6
Water = 7
Waterfall = 8
WaterfallCrest = 9
TallGrass = 10
UnderwaterGrass = 11
Ice = 12
Neutral = 13
SootGrass = 14
Bridge = 15
Puddle = 16
def self.isSurfable?(tag)
return PBTerrain.isWater?(tag)
end
def self.isWater?(tag)
return tag==PBTerrain::Water ||
tag==PBTerrain::StillWater ||
tag==PBTerrain::DeepWater ||
tag==PBTerrain::WaterfallCrest ||
tag==PBTerrain::Waterfall
end
def self.isPassableWater?(tag)
return tag==PBTerrain::Water ||
tag==PBTerrain::StillWater ||
tag==PBTerrain::DeepWater ||
tag==PBTerrain::WaterfallCrest
end
def self.isJustWater?(tag)
return tag==PBTerrain::Water ||
tag==PBTerrain::StillWater ||
tag==PBTerrain::DeepWater
end
def self.isDeepWater?(tag)
return tag==PBTerrain::DeepWater
end
def self.isWaterfall?(tag)
return tag==PBTerrain::WaterfallCrest ||
tag==PBTerrain::Waterfall
end
def self.isGrass?(tag)
return tag==PBTerrain::Grass ||
tag==PBTerrain::TallGrass ||
tag==PBTerrain::UnderwaterGrass ||
tag==PBTerrain::SootGrass
end
def self.isJustGrass?(tag) # The Poké Radar only works in these tiles
return tag==PBTerrain::Grass ||
tag==PBTerrain::SootGrass
end
def self.isLedge?(tag)
return tag==PBTerrain::Ledge
end
def self.isIce?(tag)
return tag==PBTerrain::Ice
end
def self.isBridge?(tag)
return tag==PBTerrain::Bridge
end
def self.hasReflections?(tag)
return tag==PBTerrain::StillWater ||
tag==PBTerrain::Puddle
end
def self.onlyWalk?(tag)
return tag==PBTerrain::TallGrass ||
tag==PBTerrain::Ice
end
def self.isDoubleWildBattle?(tag)
return tag==PBTerrain::TallGrass
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,729 @@
#===============================================================================
# Location signpost
#===============================================================================
class LocationWindow
def initialize(name)
@window = Window_AdvancedTextPokemon.new(name)
@window.resizeToFit(name,Graphics.width)
@window.x = 0
@window.y = -@window.height
@window.viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
@window.viewport.z = 99999
@currentmap = $game_map.map_id
@frames = 0
end
def disposed?
@window.disposed?
end
def dispose
@window.dispose
end
def update
return if @window.disposed?
@window.update
if $game_temp.message_window_showing || @currentmap!=$game_map.map_id
@window.dispose
return
end
if @frames>80
@window.y -= 4
@window.dispose if @window.y+@window.height<0
else
@window.y += 4 if @window.y<0
@frames += 1
end
end
end
#===============================================================================
# Visibility circle in dark maps
#===============================================================================
class DarknessSprite < SpriteWrapper
attr_reader :radius
def initialize(viewport=nil)
super(viewport)
@darkness = BitmapWrapper.new(Graphics.width,Graphics.height)
@radius = radiusMin
self.bitmap = @darkness
self.z = 99998
refresh
end
def dispose
@darkness.dispose
super
end
def radiusMin; return 64; end # Before using Flash
def radiusMax; return 176; end # After using Flash
def radius=(value)
@radius = value
refresh
end
def refresh
@darkness.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(0,0,0,255))
cx = Graphics.width/2
cy = Graphics.height/2
cradius = @radius
numfades = 5
for i in 1..numfades
for j in cx-cradius..cx+cradius
diff2 = (cradius * cradius) - ((j - cx) * (j - cx))
diff = Math.sqrt(diff2)
@darkness.fill_rect(j,cy-diff,1,diff*2,Color.new(0,0,0,255.0*(numfades-i)/numfades))
end
cradius = (cradius*0.9).floor
end
end
end
#===============================================================================
# Lights
#===============================================================================
class LightEffect
def initialize(event,viewport=nil,map=nil,filename=nil)
@light = IconSprite.new(0,0,viewport)
if filename!=nil && filename!="" && pbResolveBitmap("Graphics/Pictures/"+filename)
@light.setBitmap("Graphics/Pictures/"+filename)
else
@light.setBitmap("Graphics/Pictures/LE")
end
@light.z = 1000
@event = event
@map = (map) ? map : $game_map
@disposed = false
end
def disposed?
return @disposed
end
def dispose
@light.dispose
@map = nil
@event = nil
@disposed = true
end
def update
@light.update
end
end
class LightEffect_Lamp < LightEffect
def initialize(event,viewport=nil,map=nil)
lamp = AnimatedBitmap.new("Graphics/Pictures/LE")
@light = Sprite.new(viewport)
@light.bitmap = Bitmap.new(128,64)
src_rect = Rect.new(0, 0, 64, 64)
@light.bitmap.blt(0, 0, lamp.bitmap, src_rect)
@light.bitmap.blt(20, 0, lamp.bitmap, src_rect)
@light.visible = true
@light.z = 1000
lamp.dispose
@map = (map) ? map : $game_map
@event = event
end
end
class LightEffect_Basic < LightEffect
def update
return if !@light || !@event
super
@light.opacity = 100
@light.ox = 32
@light.oy = 48
if (Object.const_defined?(:ScreenPosHelper) rescue false)
@light.x = ScreenPosHelper.pbScreenX(@event)
@light.y = ScreenPosHelper.pbScreenY(@event)
@light.zoom_x = ScreenPosHelper.pbScreenZoomX(@event)
else
@light.x = @event.screen_x
@light.y = @event.screen_y
@light.zoom_x = 1.0
end
@light.zoom_y = @light.zoom_x
@light.tone = $game_screen.tone
end
end
class LightEffect_DayNight < LightEffect
def update
return if !@light || !@event
super
shade = PBDayNight.getShade
if shade>=144 # If light enough, call it fully day
shade = 255
elsif shade<=64 # If dark enough, call it fully night
shade = 0
else
shade = 255-(255*(144-shade)/(144-64))
end
@light.opacity = 255-shade
if @light.opacity>0
@light.ox = 32
@light.oy = 48
if (Object.const_defined?(:ScreenPosHelper) rescue false)
@light.x = ScreenPosHelper.pbScreenX(@event)
@light.y = ScreenPosHelper.pbScreenY(@event)
@light.zoom_x = ScreenPosHelper.pbScreenZoomX(@event)
@light.zoom_y = ScreenPosHelper.pbScreenZoomY(@event)
else
@light.x = @event.screen_x
@light.y = @event.screen_y
@light.zoom_x = 1.0
@light.zoom_y = 1.0
end
@light.tone.set($game_screen.tone.red,
$game_screen.tone.green,
$game_screen.tone.blue,
$game_screen.tone.gray)
end
end
end
Events.onSpritesetCreate += proc { |sender,e|
spriteset = e[0] # Spriteset being created
viewport = e[1] # Viewport used for tilemap and characters
map = spriteset.map # Map associated with the spriteset (not necessarily the current map)
for i in map.events.keys
if map.events[i].name[/^outdoorlight\((\w+)\)$/i]
filename = $~[1].to_s
spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i],viewport,map,filename))
elsif map.events[i].name.downcase=="outdoorlight"
spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i],viewport,map))
elsif map.events[i].name[/^light\((\w+)\)$/i]
filename = $~[1].to_s
spriteset.addUserSprite(LightEffect_Basic.new(map.events[i],viewport,map,filename))
elsif map.events[i].name.downcase=="light"
spriteset.addUserSprite(LightEffect_Basic.new(map.events[i],viewport,map))
end
end
spriteset.addUserSprite(Particle_Engine.new(viewport,map))
}
#===============================================================================
# Battle start animation
#===============================================================================
class Game_Temp
attr_accessor :background_bitmap
end
def pbSceneStandby
$scene.disposeSpritesets if $scene && $scene.is_a?(Scene_Map)
GC.start
Graphics.frame_reset
yield
$scene.createSpritesets if $scene && $scene.is_a?(Scene_Map)
end
def pbBattleAnimation(bgm=nil,battletype=0,foe=nil)
$game_temp.in_battle = true
handled = false
viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
viewport.z = 99999
# Set up audio
playingBGS = nil
playingBGM = nil
if $game_system && $game_system.is_a?(Game_System)
playingBGS = $game_system.getPlayingBGS
playingBGM = $game_system.getPlayingBGM
$game_system.bgm_pause
$game_system.bgs_pause
end
pbMEFade(0.25)
pbWait(Graphics.frame_rate/4)
pbMEStop
# Play battle music
bgm = pbGetWildBattleBGM([0]) if !bgm
pbBGMPlay(bgm)
# Take screenshot of game, for use in some animations
$game_temp.background_bitmap.dispose if $game_temp.background_bitmap
$game_temp.background_bitmap = Graphics.snap_to_bitmap
# Check for custom battle intro animations
handled = pbBattleAnimationOverride(viewport,battletype,foe)
# Default battle intro animation
if !handled
# Determine which animation is played
location = 0 # 0=outside, 1=inside, 2=cave, 3=water
if $PokemonGlobal.surfing || $PokemonGlobal.diving
location = 3
elsif $PokemonTemp.encounterType &&
($PokemonTemp.encounterType==EncounterTypes::OldRod ||
$PokemonTemp.encounterType==EncounterTypes::GoodRod ||
$PokemonTemp.encounterType==EncounterTypes::SuperRod)
location = 3
elsif $PokemonEncounters.isCave?
location = 2
elsif !pbGetMetadata($game_map.map_id,MetadataOutdoor)
location = 1
end
anim = ""
if PBDayNight.isDay?
case battletype
when 0, 2 # Wild, double wild
anim = ["SnakeSquares","DiagonalBubbleTL","DiagonalBubbleBR","RisingSplash"][location]
when 1 # Trainer
anim = ["TwoBallPass","ThreeBallDown","BallDown","WavyThreeBallUp"][location]
when 3 # Double trainer
anim = "FourBallBurst"
end
else
case battletype
when 0, 2 # Wild, double wild
anim = ["SnakeSquares","DiagonalBubbleBR","DiagonalBubbleBR","RisingSplash"][location]
when 1 # Trainer
anim = ["SpinBallSplit","BallDown","BallDown","WavySpinBall"][location]
when 3 # Double trainer
anim = "FourBallBurst"
end
end
# Initial screen flashing
if location==2 || PBDayNight.isNight?
viewport.color = Color.new(0,0,0) # Fade to black a few times
else
viewport.color = Color.new(255,255,255) # Fade to white a few times
end
halfFlashTime = Graphics.frame_rate*2/10 # 0.2 seconds, 8 frames
alphaDiff = (255.0/halfFlashTime).ceil
2.times do
viewport.color.alpha = 0
for i in 0...halfFlashTime*2
if i<halfFlashTime; viewport.color.alpha += alphaDiff
else; viewport.color.alpha -= alphaDiff
end
Graphics.update
pbUpdateSceneMap
end
end
# Play main animation
Graphics.freeze
Graphics.transition(Graphics.frame_rate*1.25,sprintf("Graphics/Transitions/%s",anim))
viewport.color = Color.new(0,0,0,255) # Ensure screen is black
# Slight pause after animation before starting up the battle scene
(Graphics.frame_rate/10).times do
Graphics.update
Input.update
pbUpdateSceneMap
end
end
pbPushFade
# Yield to the battle scene
yield if block_given?
# After the battle
pbPopFade
if $game_system && $game_system.is_a?(Game_System)
$game_system.bgm_resume(playingBGM)
$game_system.bgs_resume(playingBGS)
end
$PokemonGlobal.nextBattleBGM = nil
$PokemonGlobal.nextBattleME = nil
$PokemonGlobal.nextBattleCaptureME = nil
$PokemonGlobal.nextBattleBack = nil
$PokemonEncounters.clearStepCount
# Fade back to the overworld
viewport.color = Color.new(0,0,0,255)
numFrames = Graphics.frame_rate*4/10 # 0.4 seconds, 16 frames
alphaDiff = (255.0/numFrames).ceil
numFrames.times do
viewport.color.alpha -= alphaDiff
Graphics.update
Input.update
pbUpdateSceneMap
end
viewport.dispose
$game_temp.in_battle = false
end
def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
##### VS. animation, by Luka S.J. #####
##### Tweaked by Maruno #####
if (battletype==1 || battletype==3) && foe.length==1 # Against single trainer
trainerid = (foe[0].trainertype rescue -1)
if trainerid>=0
tbargraphic = sprintf("Graphics/Transitions/vsBar%s",getConstantName(PBTrainers,trainerid)) rescue nil
tbargraphic = sprintf("Graphics/Transitions/vsBar%d",trainerid) if !pbResolveBitmap(tbargraphic)
tgraphic = sprintf("Graphics/Transitions/vsTrainer%s",getConstantName(PBTrainers,trainerid)) rescue nil
tgraphic = sprintf("Graphics/Transitions/vsTrainer%d",trainerid) if !pbResolveBitmap(tgraphic)
if pbResolveBitmap(tbargraphic) && pbResolveBitmap(tgraphic)
outfit = $Trainer.outfit
# Set up
viewplayer = Viewport.new(0,Graphics.height/3,Graphics.width/2,128)
viewplayer.z = viewport.z
viewopp = Viewport.new(Graphics.width/2,Graphics.height/3,Graphics.width/2,128)
viewopp.z = viewport.z
viewvs = Viewport.new(0,0,Graphics.width,Graphics.height)
viewvs.z = viewport.z
fade = Sprite.new(viewport)
fade.bitmap = BitmapCache.load_bitmap("Graphics/Transitions/vsFlash")
fade.tone = Tone.new(-255,-255,-255)
fade.opacity = 100
overlay = Sprite.new(viewport)
overlay.bitmap = Bitmap.new(Graphics.width,Graphics.height)
pbSetSystemFont(overlay.bitmap)
pbargraphic = sprintf("Graphics/Transitions/vsBar%s_%d",getConstantName(PBTrainers,$Trainer.trainertype),outfit) rescue nil
pbargraphic = sprintf("Graphics/Transitions/vsBar%d_%d",$Trainer.trainertype,outfit) if !pbResolveBitmap(pbargraphic)
if !pbResolveBitmap(pbargraphic)
pbargraphic = sprintf("Graphics/Transitions/vsBar%s",getConstantName(PBTrainers,$Trainer.trainertype)) rescue nil
end
pbargraphic = sprintf("Graphics/Transitions/vsBar%d",$Trainer.trainertype) if !pbResolveBitmap(pbargraphic)
xoffset = ((Graphics.width/2)/10)*10
bar1 = Sprite.new(viewplayer)
bar1.bitmap = BitmapCache.load_bitmap(pbargraphic)
bar1.x = -xoffset
bar2 = Sprite.new(viewopp)
bar2.bitmap = BitmapCache.load_bitmap(tbargraphic)
bar2.x = xoffset
vs = Sprite.new(viewvs)
vs.bitmap = BitmapCache.load_bitmap("Graphics/Transitions/vs")
vs.ox = vs.bitmap.width/2
vs.oy = vs.bitmap.height/2
vs.x = Graphics.width/2
vs.y = Graphics.height/1.5
vs.visible = false
flash = Sprite.new(viewvs)
flash.bitmap = BitmapCache.load_bitmap("Graphics/Transitions/vsFlash")
flash.opacity = 0
# Animate bars sliding in from either side
slideInTime = (Graphics.frame_rate*0.25).floor
for i in 0...slideInTime
bar1.x = xoffset*(i+1-slideInTime)/slideInTime
bar2.x = xoffset*(slideInTime-i-1)/slideInTime
pbWait(1)
end
bar1.dispose
bar2.dispose
# Make whole screen flash white
pbSEPlay("Vs flash")
pbSEPlay("Vs sword")
flash.opacity = 255
# Replace bar sprites with AnimatedPlanes, set up trainer sprites
bar1 = AnimatedPlane.new(viewplayer)
bar1.bitmap = BitmapCache.load_bitmap(pbargraphic)
bar2 = AnimatedPlane.new(viewopp)
bar2.bitmap = BitmapCache.load_bitmap(tbargraphic)
pgraphic = sprintf("Graphics/Transitions/vsTrainer%s_%d",getConstantName(PBTrainers,$Trainer.trainertype),outfit) rescue nil
pgraphic = sprintf("Graphics/Transitions/vsTrainer%d_%d",$Trainer.trainertype,outfit) if !pbResolveBitmap(pgraphic)
if !pbResolveBitmap(pgraphic)
pgraphic = sprintf("Graphics/Transitions/vsTrainer%s",getConstantName(PBTrainers,$Trainer.trainertype)) rescue nil
end
pgraphic = sprintf("Graphics/Transitions/vsTrainer%d",$Trainer.trainertype) if !pbResolveBitmap(pgraphic)
player = Sprite.new(viewplayer)
player.bitmap = BitmapCache.load_bitmap(pgraphic)
player.x = -xoffset
trainer = Sprite.new(viewopp)
trainer.bitmap = BitmapCache.load_bitmap(tgraphic)
trainer.x = xoffset
trainer.tone = Tone.new(-255,-255,-255)
# Dim the flash and make the trainer sprites appear, while animating bars
animTime = (Graphics.frame_rate*1.2).floor
for i in 0...animTime
flash.opacity -= 52*20/Graphics.frame_rate if flash.opacity>0
bar1.ox -= 32*20/Graphics.frame_rate
bar2.ox += 32*20/Graphics.frame_rate
if i>=animTime/2 && i<slideInTime+animTime/2
player.x = xoffset*(i+1-slideInTime-animTime/2)/slideInTime
trainer.x = xoffset*(slideInTime-i-1+animTime/2)/slideInTime
end
pbWait(1)
end
player.x = 0
trainer.x = 0
# Make whole screen flash white again
flash.opacity = 255
pbSEPlay("Vs sword")
# Make the Vs logo and trainer names appear, and reset trainer's tone
vs.visible = true
trainer.tone = Tone.new(0,0,0)
trainername = foe[0].name
textpos = [
[$Trainer.name,Graphics.width/4,(Graphics.height/1.5)+10,2,
Color.new(248,248,248),Color.new(12*6,12*6,12*6)],
[trainername,(Graphics.width/4)+(Graphics.width/2),(Graphics.height/1.5)+10,2,
Color.new(248,248,248),Color.new(12*6,12*6,12*6)]
]
pbDrawTextPositions(overlay.bitmap,textpos)
# Fade out flash, shudder Vs logo and expand it, and then fade to black
animTime = (Graphics.frame_rate*2.75).floor
shudderTime = (Graphics.frame_rate*1.75).floor
zoomTime = (Graphics.frame_rate*2.5).floor
shudderDelta = [4*20/Graphics.frame_rate,1].max
for i in 0...animTime
if i<shudderTime # Fade out the white flash
flash.opacity -= 52*20/Graphics.frame_rate if flash.opacity>0
elsif i==shudderTime # Make the flash black
flash.tone = Tone.new(-255,-255,-255)
elsif i>=zoomTime # Fade to black
flash.opacity += 52*20/Graphics.frame_rate if flash.opacity<255
end
bar1.ox -= 32*20/Graphics.frame_rate
bar2.ox += 32*20/Graphics.frame_rate
if i<shudderTime
j = i%(2*Graphics.frame_rate/20)
if j>=0.5*Graphics.frame_rate/20 && j<1.5*Graphics.frame_rate/20
vs.x += shudderDelta
vs.y -= shudderDelta
else
vs.x -= shudderDelta
vs.y += shudderDelta
end
elsif i<zoomTime
vs.zoom_x += 0.4*20/Graphics.frame_rate
vs.zoom_y += 0.4*20/Graphics.frame_rate
end
pbWait(1)
end
# End of animation
player.dispose
trainer.dispose
flash.dispose
vs.dispose
bar1.dispose
bar2.dispose
overlay.dispose
fade.dispose
viewvs.dispose
viewopp.dispose
viewplayer.dispose
viewport.color = Color.new(0,0,0,255)
return true
end
end
end
return false
end
# If you want to add a custom battle intro animation, copy the following alias
# line and method into a new script section. Change the name of the alias part
# ("__over1__") in your copied code in both places. Then add in your custom
# transition code in the place shown.
# Note that $game_temp.background_bitmap contains an image of the current game
# screen.
# When the custom animation has finished, the screen should have faded to black
# somehow.
alias __over1__pbBattleAnimationOverride pbBattleAnimationOverride
def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
# The following example runs a common event that ought to do a custom
# animation if some condition is true:
#
# if $game_map.map_id==20 # If on map 20
# pbCommonEvent(20)
# return true # Note that the battle animation is done
# end
#
# The following line needs to call the aliased method if the custom transition
# animation was NOT shown.
return __over1__pbBattleAnimationOverride(viewport,battletype,foe)
end
#===============================================================================
# Entering/exiting cave animations
#===============================================================================
def pbCaveEntranceEx(exiting)
# Create bitmap
sprite = BitmapSprite.new(Graphics.width,Graphics.height)
sprite.z = 100000
# Define values used for the animation
totalFrames = (Graphics.frame_rate*0.4).floor
increment = (255.0/totalFrames).ceil
totalBands = 15
bandheight = ((Graphics.height/2.0)-10)/totalBands
bandwidth = ((Graphics.width/2.0)-12)/totalBands
# Create initial array of band colors (black if exiting, white if entering)
grays = Array.new(totalBands) { |i| (exiting) ? 0 : 255 }
# Animate bands changing color
totalFrames.times do |j|
x = 0
y = 0
# Calculate color of each band
for k in 0...totalBands
next if k>=totalBands*j/totalFrames
inc = increment
inc *= -1 if exiting
grays[k] -= inc
grays[k] = 0 if grays[k]<0
end
# Draw gray rectangles
rectwidth = Graphics.width
rectheight = Graphics.height
for i in 0...totalBands
currentGray = grays[i]
sprite.bitmap.fill_rect(Rect.new(x,y,rectwidth,rectheight),
Color.new(currentGray,currentGray,currentGray))
x += bandwidth
y += bandheight
rectwidth -= bandwidth*2
rectheight -= bandheight*2
end
Graphics.update
Input.update
end
# Set the tone at end of band animation
if exiting
pbToneChangeAll(Tone.new(255,255,255),0)
else
pbToneChangeAll(Tone.new(-255,-255,-255),0)
end
# Animate fade to white (if exiting) or black (if entering)
for j in 0...totalFrames
if exiting
sprite.color = Color.new(255,255,255,j*increment)
else
sprite.color = Color.new(0,0,0,j*increment)
end
Graphics.update
Input.update
end
# Set the tone at end of fading animation
pbToneChangeAll(Tone.new(0,0,0),8)
# Pause briefly
(Graphics.frame_rate/10).times do
Graphics.update
Input.update
end
sprite.dispose
end
def pbCaveEntrance
pbSetEscapePoint
pbCaveEntranceEx(false)
end
def pbCaveExit
pbEraseEscapePoint
pbCaveEntranceEx(true)
end
#===============================================================================
# Blacking out animation
#===============================================================================
def pbRxdataExists?(file)
if $RPGVX
return pbRgssExists?(file+".rvdata")
else
return pbRgssExists?(file+".rxdata")
end
end
def pbStartOver(gameover=false)
if pbInBugContest?
pbBugContestStartOver
return
end
pbHealAll
if $PokemonGlobal.pokecenterMapId && $PokemonGlobal.pokecenterMapId>=0
if gameover
pbMessage(_INTL("\\w[]\\wm\\c[8]\\l[3]After the unfortunate defeat, you scurry back to a Pokémon Center."))
else
pbMessage(_INTL("\\w[]\\wm\\c[8]\\l[3]You scurry back to a Pokémon Center, protecting your exhausted Pokémon from any further harm..."))
end
pbCancelVehicles
pbRemoveDependencies
$game_switches[STARTING_OVER_SWITCH] = true
$game_temp.player_new_map_id = $PokemonGlobal.pokecenterMapId
$game_temp.player_new_x = $PokemonGlobal.pokecenterX
$game_temp.player_new_y = $PokemonGlobal.pokecenterY
$game_temp.player_new_direction = $PokemonGlobal.pokecenterDirection
$scene.transfer_player if $scene.is_a?(Scene_Map)
$game_map.refresh
else
homedata = pbGetMetadata(0,MetadataHome)
if homedata && !pbRxdataExists?(sprintf("Data/Map%03d",homedata[0]))
if $DEBUG
pbMessage(_ISPRINTF("Can't find the map 'Map{1:03d}' in the Data folder. The game will resume at the player's position.",homedata[0]))
end
pbHealAll
return
end
if gameover
pbMessage(_INTL("\\w[]\\wm\\c[8]\\l[3]After the unfortunate defeat, you scurry back home."))
else
pbMessage(_INTL("\\w[]\\wm\\c[8]\\l[3]You scurry back home, protecting your exhausted Pokémon from any further harm..."))
end
if homedata
pbCancelVehicles
pbRemoveDependencies
$game_switches[STARTING_OVER_SWITCH] = true
$game_temp.player_new_map_id = homedata[0]
$game_temp.player_new_x = homedata[1]
$game_temp.player_new_y = homedata[2]
$game_temp.player_new_direction = homedata[3]
$scene.transfer_player if $scene.is_a?(Scene_Map)
$game_map.refresh
else
pbHealAll
end
end
pbEraseEscapePoint
end
#===============================================================================
# Various other screen effects
#===============================================================================
def pbToneChangeAll(tone,duration)
$game_screen.start_tone_change(tone,duration*Graphics.frame_rate/20)
for picture in $game_screen.pictures
picture.start_tone_change(tone,duration*Graphics.frame_rate/20) if picture
end
end
def pbShake(power,speed,frames)
$game_screen.start_shake(power,speed,frames*Graphics.frame_rate/20)
end
def pbFlash(color,frames)
$game_screen.start_flash(color,frames*Graphics.frame_rate/20)
end
def pbScrollMap(direction,distance,speed)
if speed==0
case direction
when 2; $game_map.scroll_down(distance * Game_Map::REAL_RES_Y)
when 4; $game_map.scroll_left(distance * Game_Map::REAL_RES_X)
when 6; $game_map.scroll_right(distance * Game_Map::REAL_RES_X)
when 8; $game_map.scroll_up(distance * Game_Map::REAL_RES_Y)
end
else
$game_map.start_scroll(direction, distance, speed)
oldx = $game_map.display_x
oldy = $game_map.display_y
loop do
Graphics.update
Input.update
break if !$game_map.scrolling?
pbUpdateSceneMap
break if $game_map.display_x==oldx && $game_map.display_y==oldy
oldx = $game_map.display_x
oldy = $game_map.display_y
end
end
end

View File

@@ -0,0 +1,274 @@
begin
module PBFieldWeather
None = 0 # None must be 0 (preset RMXP weather)
Rain = 1 # Rain must be 1 (preset RMXP weather)
Storm = 2 # Storm must be 2 (preset RMXP weather)
Snow = 3 # Snow must be 3 (preset RMXP weather)
Blizzard = 4
Sandstorm = 5
HeavyRain = 6
Sun = Sunny = 7
def PBFieldWeather.maxValue; return 7; end
end
rescue Exception
if $!.is_a?(SystemExit) || "#{$!.class}"=="Reset"
raise $!
end
end
module RPG
class Weather
attr_reader :type
attr_reader :max
attr_reader :ox
attr_reader :oy
def initialize(viewport = nil)
@type = 0
@max = 0
@ox = 0
@oy = 0
@sunValue = 0
@sun = 0
@viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
@viewport.z = viewport.z+1
@origViewport = viewport
# [array of bitmaps, +x per frame, +y per frame, +opacity per frame]
@weatherTypes = []
@weatherTypes[PBFieldWeather::None] = nil
@weatherTypes[PBFieldWeather::Rain] = [[], -6, 24, -8]
@weatherTypes[PBFieldWeather::HeavyRain] = [[], -24, 24, -4]
@weatherTypes[PBFieldWeather::Storm] = [[], -24, 24, -4]
@weatherTypes[PBFieldWeather::Snow] = [[], -4, 8, 0]
@weatherTypes[PBFieldWeather::Blizzard] = [[], -16, 16, -4]
@weatherTypes[PBFieldWeather::Sandstorm] = [[], -12, 4, -2]
@weatherTypes[PBFieldWeather::Sun] = nil
@sprites = []
end
def dispose
@sprites.each { |s| s.dispose }
@viewport.dispose
@weatherTypes.each do |weather|
next if !weather
weather[0].each { |bitmap| bitmap.dispose if bitmap }
end
end
def ox=(ox)
return if @ox==ox
@ox = ox
@sprites.each { |s| s.ox = @ox }
end
def oy=(oy)
return if @oy==oy
@oy = oy
@sprites.each { |s| s.oy = @oy }
end
def prepareRainBitmap
rainColor = Color.new(255,255,255,255)
@rain_bitmap = Bitmap.new(32,128)
for i in 0...16
@rain_bitmap.fill_rect(30-(i*2),i*8,2,8,rainColor)
end
@weatherTypes[PBFieldWeather::Rain][0][0] = @rain_bitmap
end
def prepareStormBitmap
rainColor = Color.new(255,255,255,255)
@storm_bitmap = Bitmap.new(192,192)
for i in 0...96
@storm_bitmap.fill_rect(190-(i*2),i*2,2,2,rainColor)
end
@weatherTypes[PBFieldWeather::HeavyRain][0][0] = @storm_bitmap
@weatherTypes[PBFieldWeather::Storm][0][0] = @storm_bitmap
end
def prepareSnowBitmaps
return if @snowBitmap1
bmWidth = 10
bmHeight = 10
@snowBitmap1 = Bitmap.new(bmWidth,bmHeight)
@snowBitmap2 = Bitmap.new(bmWidth,bmHeight)
@snowBitmap3 = Bitmap.new(bmWidth,bmHeight)
snowColor = Color.new(224, 232, 240)
# Small + shape
@snowBitmap1.fill_rect(4,2,2,2,snowColor)
@snowBitmap1.fill_rect(2,4,6,2,snowColor)
@snowBitmap1.fill_rect(4,6,2,2,snowColor)
# Fatter + shape
@snowBitmap2.fill_rect(2,0,4,2,snowColor)
@snowBitmap2.fill_rect(0,2,8,4,snowColor)
@snowBitmap2.fill_rect(2,6,4,2,snowColor)
# Diamond shape
@snowBitmap3.fill_rect(4,0,2,2,snowColor)
@snowBitmap3.fill_rect(2,2,6,2,snowColor)
@snowBitmap3.fill_rect(0,4,10,2,snowColor)
@snowBitmap3.fill_rect(2,6,6,2,snowColor)
@snowBitmap3.fill_rect(4,8,2,2,snowColor)
@weatherTypes[PBFieldWeather::Snow][0] = [@snowBitmap1,@snowBitmap2,@snowBitmap3]
end
def prepareBlizzardBitmaps
return if @blizzardBitmap1
bmWidth = 10; bmHeight = 10
@blizzardBitmap1 = Bitmap.new(bmWidth,bmHeight)
@blizzardBitmap2 = Bitmap.new(bmWidth,bmHeight)
bmWidth = 200; bmHeight = 200
@blizzardBitmap3 = Bitmap.new(bmWidth,bmHeight)
@blizzardBitmap4 = Bitmap.new(bmWidth,bmHeight)
snowColor = Color.new(224,232,240,255)
# Fatter + shape
@blizzardBitmap1.fill_rect(2,0,4,2,snowColor)
@blizzardBitmap1.fill_rect(0,2,8,4,snowColor)
@blizzardBitmap1.fill_rect(2,6,4,2,snowColor)
# Diamond shape
@blizzardBitmap2.fill_rect(4,0,2,2,snowColor)
@blizzardBitmap2.fill_rect(2,2,6,2,snowColor)
@blizzardBitmap2.fill_rect(0,4,10,2,snowColor)
@blizzardBitmap2.fill_rect(2,6,6,2,snowColor)
@blizzardBitmap2.fill_rect(4,8,2,2,snowColor)
for i in 0...540
@blizzardBitmap3.fill_rect(rand(bmWidth/2)*2,rand(bmHeight/2)*2,2,2,snowColor)
@blizzardBitmap4.fill_rect(rand(bmWidth/2)*2,rand(bmHeight/2)*2,2,2,snowColor)
end
@weatherTypes[PBFieldWeather::Blizzard][0][0] = @blizzardBitmap1
@weatherTypes[PBFieldWeather::Blizzard][0][1] = @blizzardBitmap2
@weatherTypes[PBFieldWeather::Blizzard][0][2] = @blizzardBitmap3 # Tripled to make them 3x as common
@weatherTypes[PBFieldWeather::Blizzard][0][3] = @blizzardBitmap3
@weatherTypes[PBFieldWeather::Blizzard][0][4] = @blizzardBitmap3
@weatherTypes[PBFieldWeather::Blizzard][0][5] = @blizzardBitmap4 # Tripled to make them 3x as common
@weatherTypes[PBFieldWeather::Blizzard][0][6] = @blizzardBitmap4
@weatherTypes[PBFieldWeather::Blizzard][0][7] = @blizzardBitmap4
end
def prepareSandstormBitmaps
return if @sandstormBitmap1
sandstormColors = [
Color.new(31*8, 28*8, 17*8),
Color.new(23*8, 16*8, 9*8),
Color.new(29*8, 24*8, 15*8),
Color.new(26*8, 20*8, 12*8),
Color.new(20*8, 13*8, 6*8),
Color.new(31*8, 30*8, 20*8),
Color.new(27*8, 25*8, 20*8)
]
bmWidth = 200
bmHeight = 200
@sandstormBitmap1 = Bitmap.new(bmWidth,bmHeight)
@sandstormBitmap2 = Bitmap.new(bmWidth,bmHeight)
for i in 0...540
@sandstormBitmap1.fill_rect(rand(bmWidth/2)*2,rand(bmHeight/2)*2,2,2,
sandstormColors[rand(sandstormColors.length)])
@sandstormBitmap2.fill_rect(rand(bmWidth/2)*2,rand(bmHeight/2)*2,2,2,
sandstormColors[rand(sandstormColors.length)])
end
@weatherTypes[PBFieldWeather::Sandstorm][0] = [@sandstormBitmap1,@sandstormBitmap2]
end
def ensureSprites
return if @sprites.length>=40
for i in 0...40
if !@sprites[i]
sprite = Sprite.new(@origViewport)
sprite.z = 1000
sprite.ox = @ox
sprite.oy = @oy
sprite.opacity = 0
@sprites.push(sprite)
end
@sprites[i].visible = (i<=@max)
end
end
def max=(max)
return if @max==max
@max = [[max,0].max,40].min
if @max==0
@sprites.each { |s| s.dispose }
@sprites.clear
else
@sprites.each_with_index { |s,i| s.visible = (i<=@max) if s }
end
end
def type=(type)
return if @type==type
@type = type
case @type
when PBFieldWeather::None
@sprites.each { |s| s.dispose }
@sprites.clear
return
when PBFieldWeather::Rain; prepareRainBitmap
when PBFieldWeather::HeavyRain, PBFieldWeather::Storm; prepareStormBitmap
when PBFieldWeather::Snow; prepareSnowBitmaps
when PBFieldWeather::Blizzard; prepareBlizzardBitmaps
when PBFieldWeather::Sandstorm; prepareSandstormBitmaps
end
weatherBitmaps = (@type==PBFieldWeather::None || @type==PBFieldWeather::Sun) ? nil : @weatherTypes[@type][0]
ensureSprites
@sprites.each_with_index do |s,i|
next if !s
s.mirror = false
s.mirror = (rand(2)==0) if @type==PBFieldWeather::Blizzard || @type==PBFieldWeather::Sandstorm
s.bitmap = (weatherBitmaps) ? weatherBitmaps[i%weatherBitmaps.length]: nil
end
end
def update
# @max is (power+1)*4, where power is between 1 and 9
# Set tone of viewport (general screen brightening/darkening)
case @type
when PBFieldWeather::None; @viewport.tone.set(0,0,0,0)
when PBFieldWeather::Rain; @viewport.tone.set(-@max*3/4, -@max*3/4, -@max*3/4, 10)
when PBFieldWeather::HeavyRain; @viewport.tone.set(-@max*6/4, -@max*6/4, -@max*6/4, 20)
when PBFieldWeather::Storm; @viewport.tone.set(-@max*6/4, -@max*6/4, -@max*6/4, 20)
when PBFieldWeather::Snow; @viewport.tone.set( @max/2, @max/2, @max/2, 0)
when PBFieldWeather::Blizzard; @viewport.tone.set( @max*3/4, @max*3/4, max*3/4, 0)
when PBFieldWeather::Sandstorm; @viewport.tone.set( @max/2, 0, -@max/2, 0)
when PBFieldWeather::Sun
@sun = @max if @sun!=@max && @sun!=-@max
@sun = -@sun if @sunValue>@max || @sunValue<0
@sunValue = @sunValue+@sun/32
@viewport.tone.set(@sunValue+63,@sunValue+63,@sunValue/2+31,0)
end
# Storm flashes
if @type==PBFieldWeather::Storm
rnd = rand(300)
@viewport.flash(Color.new(255,255,255,230),rnd*20) if rnd<4
end
@viewport.update
return if @type==PBFieldWeather::None || @type==PBFieldWeather::Sun
# Update weather particles (raindrops, snowflakes, etc.)
ensureSprites
for i in 1..@max
sprite = @sprites[i]
break if sprite==nil
sprite.x += @weatherTypes[@type][1]
sprite.x += [2,0,0,-2][rand(4)] if @type==PBFieldWeather::Snow || @type==PBFieldWeather::Blizzard
sprite.y += @weatherTypes[@type][2]
sprite.opacity += @weatherTypes[@type][3]
# Check if sprite is off-screen; if so, reset it
x = sprite.x-@ox
y = sprite.y-@oy
nomWidth = Graphics.width
nomHeight = Graphics.height
if sprite.opacity<64 || x<-50 || x>nomWidth+128 || y<-300 || y>nomHeight+20
sprite.x = rand(nomWidth+150)-50+@ox
sprite.y = rand(nomHeight+150)-200+@oy
sprite.opacity = 255
sprite.mirror = false
sprite.mirror = (rand(2)==0) if @type==PBFieldWeather::Blizzard || @type==PBFieldWeather::Sandstorm
end
pbDayNightTint(sprite)
end
end
end
end

View File

@@ -0,0 +1,225 @@
#===============================================================================
# Global metadata not specific to a map. This class holds field state data that
# span multiple maps.
#===============================================================================
class PokemonGlobalMetadata
# Movement
attr_accessor :bicycle
attr_accessor :surfing
attr_accessor :diving
attr_accessor :sliding
attr_accessor :fishing
attr_accessor :runningShoes
attr_accessor :runtoggle
# Player data
attr_accessor :startTime
attr_accessor :stepcount
attr_accessor :playerID
attr_accessor :coins
attr_accessor :sootsack
attr_accessor :seenStorageCreator
attr_accessor :pcItemStorage
attr_accessor :mailbox
attr_accessor :phoneNumbers
attr_accessor :phoneTime
attr_accessor :partner
attr_accessor :snagMachine
attr_accessor :creditsPlayed
# Pokédex
attr_accessor :pokedexUnlocked # Array storing which Dexes are unlocked
attr_accessor :pokedexViable # All Dexes of non-zero length and unlocked
attr_accessor :pokedexDex # Dex currently looking at (-1 is National Dex)
attr_accessor :pokedexIndex # Last species viewed per Dex
attr_accessor :pokedexMode # Search mode
# Day Care
attr_accessor :daycare
attr_accessor :daycareEgg
attr_accessor :daycareEggSteps
# Special battle modes
attr_accessor :safariState
attr_accessor :bugContestState
attr_accessor :challenge
attr_accessor :lastbattle # Saved recording of a battle
# Events
attr_accessor :eventvars
# Affecting the map
attr_accessor :bridge
attr_accessor :repel
attr_accessor :flashUsed
# Map transfers
attr_accessor :healingSpot
attr_accessor :escapePoint
attr_accessor :pokecenterMapId
attr_accessor :pokecenterX
attr_accessor :pokecenterY
attr_accessor :pokecenterDirection
# Movement history
attr_accessor :visitedMaps
attr_accessor :mapTrail
# Counters
attr_accessor :happinessSteps
attr_accessor :pokerusTime
# Save file
attr_accessor :safesave
def initialize
# Movement
@bicycle = false
@surfing = false
@diving = false
@sliding = false
@fishing = false
@runningShoes = false
@runtoggle = false
# Player data
@startTime = Time.now
@stepcount = 0
@playerID = -1
@coins = 0
@sootsack = 0
@seenStorageCreator = false
@pcItemStorage = nil
@mailbox = nil
@phoneNumbers = []
@phoneTime = 0
@partner = nil
@snagMachine = false
@creditsPlayed = false
# Pokédex
numRegions = pbLoadRegionalDexes.length
@pokedexUnlocked = []
@pokedexViable = []
@pokedexDex = (numRegions==0) ? -1 : 0
@pokedexIndex = []
@pokedexMode = 0
for i in 0...numRegions+1 # National Dex isn't a region, but is included
@pokedexIndex[i] = 0
@pokedexUnlocked[i] = (i==0)
end
# Day Care
@daycare = [[nil,0],[nil,0]]
@daycareEgg = false
@daycareEggSteps = 0
# Special battle modes
@safariState = nil
@bugContestState = nil
@challenge = nil
@lastbattle = nil
# Events
@eventvars = {}
# Affecting the map
@bridge = 0
@repel = 0
@flashused = false
# Map transfers
@healingSpot = nil
@escapePoint = []
@pokecenterMapId = -1
@pokecenterX = -1
@pokecenterY = -1
@pokecenterDirection = -1
# Movement history
@visitedMaps = []
@mapTrail = []
# Counters
@happinessSteps = 0
@pokerusTime = nil
# Save file
@safesave = false
end
def bridge
return @bridge || 0
end
end
#===============================================================================
# This class keeps track of erased and moved events so their position
# can remain after a game is saved and loaded. This class also includes
# variables that should remain valid only for the current map.
#===============================================================================
class PokemonMapMetadata
attr_reader :erasedEvents
attr_reader :movedEvents
attr_accessor :strengthUsed
attr_accessor :blackFluteUsed
attr_accessor :whiteFluteUsed
def initialize
clear
end
def clear
@erasedEvents = {}
@movedEvents = {}
@strengthUsed = false
@blackFluteUsed = false
@whiteFluteUsed = false
end
def addErasedEvent(eventID)
key = [$game_map.map_id,eventID]
@erasedEvents[key] = true
end
def addMovedEvent(eventID)
key = [$game_map.map_id,eventID]
event = $game_map.events[eventID] if eventID.is_a?(Integer)
@movedEvents[key] = [event.x,event.y,event.direction,event.through] if event
end
def updateMap
for i in @erasedEvents
if i[0][0]==$game_map.map_id && i[1]
event = $game_map.events[i[0][1]]
event.erase if event
end
end
for i in @movedEvents
if i[0][0]==$game_map.map_id && i[1]
next if !$game_map.events[i[0][1]]
$game_map.events[i[0][1]].moveto(i[1][0],i[1][1])
case i[1][2]
when 2; $game_map.events[i[0][1]].turn_down
when 4; $game_map.events[i[0][1]].turn_left
when 6; $game_map.events[i[0][1]].turn_right
when 8; $game_map.events[i[0][1]].turn_up
end
end
if i[1][3]!=nil
$game_map.events[i[0][1]].through = i[1][3]
end
end
end
end
#===============================================================================
# Temporary data which is not saved and which is erased when a game restarts.
#===============================================================================
class PokemonTemp
attr_accessor :menuLastChoice
attr_accessor :keyItemCalling
attr_accessor :hiddenMoveEventCalling
attr_accessor :begunNewGame
attr_accessor :miniupdate
attr_accessor :waitingTrainer
attr_accessor :darknessSprite
attr_accessor :lastbattle
attr_accessor :flydata
attr_accessor :surfJump
attr_accessor :endSurf
attr_accessor :forceSingleBattle
def initialize
@menuLastChoice = 0
@keyItemCalling = false
@hiddenMoveEventCalling = false
@begunNewGame = false
@miniupdate = false
@forceSingleBattle = false
end
end

View File

@@ -0,0 +1,681 @@
#===============================================================================
# Battle preparation
#===============================================================================
class PokemonGlobalMetadata
attr_accessor :nextBattleBGM
attr_accessor :nextBattleME
attr_accessor :nextBattleCaptureME
attr_accessor :nextBattleBack
end
class PokemonTemp
attr_accessor :encounterType
attr_accessor :evolutionLevels
def battleRules
@battleRules = {} if !@battleRules
return @battleRules
end
def clearBattleRules
self.battleRules.clear
end
def recordBattleRule(rule,var=nil)
rules = self.battleRules
case rule.to_s.downcase
when "single", "1v1", "1v2", "2v1", "1v3", "3v1",
"double", "2v2", "2v3", "3v2", "triple", "3v3"
rules["size"] = rule.to_s.downcase
when "canlose"; rules["canLose"] = true
when "cannotlose"; rules["canLose"] = false
when "canrun"; rules["canRun"] = true
when "cannotrun"; rules["canRun"] = false
when "roamerflees"; rules["roamerFlees"] = true
when "noExp"; rules["expGain"] = false
when "noMoney"; rules["moneyGain"] = false
when "switchstyle"; rules["switchStyle"] = true
when "setstyle"; rules["switchStyle"] = false
when "anims"; rules["battleAnims"] = true
when "noanims"; rules["battleAnims"] = false
when "terrain"; rules["defaultTerrain"] = getID(PBBattleTerrains,var)
when "weather"; rules["defaultWeather"] = getID(PBWeather,var)
when "environment", "environ"; rules["environment"] = getID(PBEnvironment,var)
when "backdrop", "battleback"; rules["backdrop"] = var
when "base"; rules["base"] = var
when "outcomevar", "outcome"; rules["outcomeVar"] = var
when "nopartner"; rules["noPartner"] = true
else
raise _INTL("Battle rule \"{1}\" does not exist.",rule)
end
end
end
def setBattleRule(*args)
r = nil
for arg in args
if r
$PokemonTemp.recordBattleRule(r,arg)
r = nil
else
case arg.downcase
when "terrain", "weather", "environment", "environ", "backdrop",
"battleback", "base", "outcomevar", "outcome"
r = arg
next
end
$PokemonTemp.recordBattleRule(arg)
end
end
raise _INTL("Argument {1} expected a variable after it but didn't have one.",r) if r
end
def pbNewBattleScene
return PokeBattle_Scene.new
end
# Sets up various battle parameters and applies special rules.
def pbPrepareBattle(battle)
battleRules = $PokemonTemp.battleRules
# The size of the battle, i.e. how many Pokémon on each side (default: "single")
battle.setBattleMode(battleRules["size"]) if !battleRules["size"].nil?
# Whether the game won't black out even if the player loses (default: false)
battle.canLose = battleRules["canLose"] if !battleRules["canLose"].nil?
# Whether the player can choose to run from the battle (default: true)
battle.canRun = battleRules["canRun"] if !battleRules["canRun"].nil?
# Whether wild Pokémon always try to run from battle (default: nil)
battle.rules["alwaysflee"] = battleRules["roamerFlees"]
# Whether Pokémon gain Exp/EVs from defeating/catching a Pokémon (default: true)
battle.expGain = battleRules["expGain"] if !battleRules["expGain"].nil?
# Whether the player gains/loses money at the end of the battle (default: true)
battle.moneyGain = battleRules["moneyGain"] if !battleRules["moneyGain"].nil?
# Whether the player is able to switch when an opponent's Pokémon faints
battle.switchStyle = ($PokemonSystem.battlestyle==0)
battle.switchStyle = battleRules["switchStyle"] if !battleRules["switchStyle"].nil?
# Whether battle animations are shown
battle.showAnims = ($PokemonSystem.battlescene==0)
battle.showAnims = battleRules["battleAnims"] if !battleRules["battleAnims"].nil?
# Terrain
battle.defaultTerrain = battleRules["defaultTerrain"] if !battleRules["defaultTerrain"].nil?
# Weather
if battleRules["defaultWeather"].nil?
case $game_screen.weather_type
when PBFieldWeather::Rain, PBFieldWeather::HeavyRain, PBFieldWeather::Storm
battle.defaultWeather = PBWeather::Rain
when PBFieldWeather::Snow, PBFieldWeather::Blizzard
battle.defaultWeather = PBWeather::Hail
when PBFieldWeather::Sandstorm
battle.defaultWeather = PBWeather::Sandstorm
when PBFieldWeather::Sun
battle.defaultWeather = PBWeather::Sun
end
else
battle.defaultWeather = battleRules["defaultWeather"]
end
# Environment
if battleRules["environment"].nil?
battle.environment = pbGetEnvironment
else
battle.environment = battleRules["environment"]
end
# Backdrop graphic filename
if !battleRules["backdrop"].nil?
backdrop = battleRules["backdrop"]
elsif $PokemonGlobal.nextBattleBack
backdrop = $PokemonGlobal.nextBattleBack
elsif $PokemonGlobal.surfing
backdrop = "water" # This applies wherever you are, including in caves
else
back = pbGetMetadata($game_map.map_id,MetadataBattleBack)
backdrop = back if back && back!=""
end
backdrop = "indoor1" if !backdrop
battle.backdrop = backdrop
# Choose a name for bases depending on environment
if battleRules["base"].nil?
case battle.environment
when PBEnvironment::Grass, PBEnvironment::TallGrass,
PBEnvironment::ForestGrass; base = "grass"
# when PBEnvironment::Rock; base = "rock"
when PBEnvironment::Sand; base = "sand"
when PBEnvironment::MovingWater, PBEnvironment::StillWater; base = "water"
when PBEnvironment::Puddle; base = "puddle"
when PBEnvironment::Ice; base = "ice"
end
else
base = battleRules["base"]
end
battle.backdropBase = base if base
# Time of day
if pbGetMetadata($game_map.map_id,MetadataEnvironment)==PBEnvironment::Cave
battle.time = 2 # This makes Dusk Balls work properly in caves
elsif TIME_SHADING
timeNow = pbGetTimeNow
if PBDayNight.isNight?(timeNow); battle.time = 2
elsif PBDayNight.isEvening?(timeNow); battle.time = 1
else; battle.time = 0
end
end
end
# Used to determine the environment in battle, and also the form of Burmy/
# Wormadam.
def pbGetEnvironment
ret = pbGetMetadata($game_map.map_id,MetadataEnvironment)
ret = PBEnvironment::None if !ret
if $PokemonTemp.encounterType==EncounterTypes::OldRod ||
$PokemonTemp.encounterType==EncounterTypes::GoodRod ||
$PokemonTemp.encounterType==EncounterTypes::SuperRod
terrainTag = pbFacingTerrainTag
else
terrainTag = $game_player.terrain_tag
end
case terrainTag
when PBTerrain::Grass, PBTerrain::SootGrass
ret = (ret==PBEnvironment::Forest) ? PBEnvironment::ForestGrass : PBEnvironment::Grass
when PBTerrain::TallGrass
ret = (ret==PBEnvironment::Forest) ? PBEnvironment::ForestGrass : PBEnvironment::TallGrass
when PBTerrain::Rock; ret = PBEnvironment::Rock
when PBTerrain::Sand; ret = PBEnvironment::Sand
when PBTerrain::DeepWater, PBTerrain::Water; ret = PBEnvironment::MovingWater
when PBTerrain::StillWater; ret = PBEnvironment::StillWater
when PBTerrain::Puddle; ret = PBEnvironment::Puddle
when PBTerrain::Ice; ret = PBEnvironment::Ice
end
return ret
end
Events.onStartBattle += proc { |sender|
# Record current levels of Pokémon in party, to see if they gain a level
# during battle and may need to evolve afterwards
$PokemonTemp.evolutionLevels = []
for i in 0...$Trainer.party.length
$PokemonTemp.evolutionLevels[i] = $Trainer.party[i].level
end
}
def pbCanDoubleBattle?
return $PokemonGlobal.partner || $Trainer.ablePokemonCount>=2
end
def pbCanTripleBattle?
return true if $Trainer.ablePokemonCount>=3
return $PokemonGlobal.partner && $Trainer.ablePokemonCount>=2
end
#===============================================================================
# Start a wild battle
#===============================================================================
def pbWildBattleCore(*args)
outcomeVar = $PokemonTemp.battleRules["outcomeVar"] || 1
canLose = $PokemonTemp.battleRules["canLose"] || false
# Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode
if $Trainer.ablePokemonCount==0 || ($DEBUG && Input.press?(Input::CTRL))
pbMessage(_INTL("SKIPPING BATTLE...")) if $Trainer.pokemonCount>0
pbSet(outcomeVar,1) # Treat it as a win
$PokemonTemp.clearBattleRules
$PokemonGlobal.nextBattleBGM = nil
$PokemonGlobal.nextBattleME = nil
$PokemonGlobal.nextBattleCaptureME = nil
$PokemonGlobal.nextBattleBack = nil
return 1 # Treat it as a win
end
# 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 wild Pokémon based on the species and level
foeParty = []
sp = nil
for arg in args
if arg.is_a?(PokeBattle_Pokemon)
foeParty.push(arg)
elsif arg.is_a?(Array)
species = getID(PBSpecies,arg[0])
pkmn = pbGenerateWildPokemon(species,arg[1])
foeParty.push(pkmn)
elsif sp
species = getID(PBSpecies,sp)
pkmn = pbGenerateWildPokemon(species,arg)
foeParty.push(pkmn)
sp = nil
else
sp = arg
end
end
raise _INTL("Expected a level after being given {1}, but one wasn't found.",sp) if sp
# Calculate who the trainers and their party are
playerTrainers = [$Trainer]
playerParty = $Trainer.party
playerPartyStarts = [0]
if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && foeParty.length>1
ally = PokeBattle_Trainer.new($PokemonGlobal.partner[1],$PokemonGlobal.partner[0])
ally.id = $PokemonGlobal.partner[2]
ally.party = $PokemonGlobal.partner[3]
playerTrainers.push(ally)
playerParty = []
$Trainer.party.each { |pkmn| playerParty.push(pkmn) }
playerPartyStarts.push(playerParty.length)
ally.party.each { |pkmn| playerParty.push(pkmn) }
end
# Create the battle scene (the visual side of it)
scene = pbNewBattleScene
# Create the battle class (the mechanics side of it)
battle = PokeBattle_Battle.new(scene,playerParty,foeParty,playerTrainers,nil)
battle.party1starts = playerPartyStarts
# Set various other properties in the battle class
pbPrepareBattle(battle)
$PokemonTemp.clearBattleRules
# Perform the battle itself
decision = 0
pbBattleAnimation(pbGetWildBattleBGM(foeParty),(foeParty.length==1) ? 0 : 2,foeParty) {
pbSceneStandby {
decision = battle.pbStartBattle
}
pbAfterBattle(decision,canLose)
}
Input.update
# Save the result of the battle in a Game Variable (1 by default)
# 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(outcomeVar,decision)
return decision
end
#===============================================================================
# Standard methods that start a wild battle of various sizes
#===============================================================================
# Used when walking in tall grass, hence the additional code.
def pbWildBattle(species, level, outcomeVar=1, canRun=true, canLose=false)
species = getID(PBSpecies,species)
# Potentially call a different pbWildBattle-type method instead (for roaming
# Pokémon, Safari battles, Bug Contest battles)
handled = [nil]
Events.onWildBattleOverride.trigger(nil,species,level,handled)
return handled[0] if handled[0]!=nil
# Set some battle rules
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
setBattleRule("cannotRun") if !canRun
setBattleRule("canLose") if canLose
# Perform the battle
decision = pbWildBattleCore(species, level)
# 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
def pbDoubleWildBattle(species1, level1, species2, level2,
outcomeVar=1, canRun=true, canLose=false)
# Set some battle rules
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
setBattleRule("cannotRun") if !canRun
setBattleRule("canLose") if canLose
setBattleRule("double")
# Perform the battle
decision = pbWildBattleCore(species1, level1, species2, level2)
# Return false if the player lost or drew the battle, and true if any other result
return (decision!=2 && decision!=5)
end
def pbTripleWildBattle(species1, level1, species2, level2, species3, level3,
outcomeVar=1, canRun=true, canLose=false)
# Set some battle rules
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
setBattleRule("cannotRun") if !canRun
setBattleRule("canLose") if canLose
setBattleRule("triple")
# Perform the battle
decision = pbWildBattleCore(species1, level1, species2, level2, species3, level3)
# Return false if the player lost or drew the battle, and true if any other result
return (decision!=2 && decision!=5)
end
#===============================================================================
# Start a trainer battle
#===============================================================================
def pbTrainerBattleCore(*args)
outcomeVar = $PokemonTemp.battleRules["outcomeVar"] || 1
canLose = $PokemonTemp.battleRules["canLose"] || false
# Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode
if $Trainer.ablePokemonCount==0 || ($DEBUG && Input.press?(Input::CTRL))
pbMessage(_INTL("SKIPPING BATTLE...")) if $DEBUG
pbMessage(_INTL("AFTER WINNING...")) if $DEBUG && $Trainer.ablePokemonCount>0
pbSet(outcomeVar,($Trainer.ablePokemonCount==0) ? 0 : 1) # Treat it as undecided/a win
$PokemonTemp.clearBattleRules
$PokemonGlobal.nextBattleBGM = nil
$PokemonGlobal.nextBattleME = nil
$PokemonGlobal.nextBattleCaptureME = nil
$PokemonGlobal.nextBattleBack = nil
return ($Trainer.ablePokemonCount==0) ? 0 : 1 # Treat it as undecided/a win
end
# 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 trainers and their parties based on the arguments given
foeTrainers = []
foeItems = []
foeEndSpeeches = []
foeParty = []
foePartyStarts = []
for arg in args
raise _INTL("Expected an array of trainer data, got {1}.",arg) if !arg.is_a?(Array)
if arg[0].is_a?(PokeBattle_Trainer)
# [trainer object, party, end speech, items]
foeTrainers.push(arg[0])
foePartyStarts.push(foeParty.length)
arg[1].each { |pkmn| foeParty.push(pkmn) }
foeEndSpeeches.push(arg[2])
foeItems.push(arg[3])
else
# [trainer type, trainer name, ID, speech (optional)]
trainer = pbLoadTrainer(arg[0],arg[1],arg[2])
pbMissingTrainer(arg[0],arg[1],arg[2]) if !trainer
return 0 if !trainer
Events.onTrainerPartyLoad.trigger(nil,trainer)
foeTrainers.push(trainer[0])
foePartyStarts.push(foeParty.length)
trainer[2].each { |pkmn| foeParty.push(pkmn) }
foeEndSpeeches.push(arg[3] || trainer[3])
foeItems.push(trainer[1])
end
end
# Calculate who the player trainer(s) and their party are
playerTrainers = [$Trainer]
playerParty = $Trainer.party
playerPartyStarts = [0]
if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && foeParty.length>1
ally = PokeBattle_Trainer.new($PokemonGlobal.partner[1],$PokemonGlobal.partner[0])
ally.id = $PokemonGlobal.partner[2]
ally.party = $PokemonGlobal.partner[3]
playerTrainers.push(ally)
playerParty = []
$Trainer.party.each { |pkmn| playerParty.push(pkmn) }
playerPartyStarts.push(playerParty.length)
ally.party.each { |pkmn| playerParty.push(pkmn) }
end
# Create the battle scene (the visual side of it)
scene = pbNewBattleScene
# Create the battle class (the mechanics side of it)
battle = PokeBattle_Battle.new(scene,playerParty,foeParty,playerTrainers,foeTrainers)
battle.party1starts = playerPartyStarts
battle.party2starts = foePartyStarts
battle.items = foeItems
battle.endSpeeches = foeEndSpeeches
# Set various other properties in the battle class
pbPrepareBattle(battle)
$PokemonTemp.clearBattleRules
# End the trainer intro music
Audio.me_stop
# Perform the battle itself
decision = 0
pbBattleAnimation(pbGetTrainerBattleBGM(foeTrainers),(battle.singleBattle?) ? 1 : 3,foeTrainers) {
pbSceneStandby {
decision = battle.pbStartBattle
}
pbAfterBattle(decision,canLose)
}
Input.update
# Save the result of the battle in a Game Variable (1 by default)
# 0 - Undecided or aborted
# 1 - Player won
# 2 - Player lost
# 3 - Player or wild Pokémon ran from battle, or player forfeited the match
# 5 - Draw
pbSet(outcomeVar,decision)
return decision
end
#===============================================================================
# Standard methods that start a trainer battle of various sizes
#===============================================================================
# Used by most trainer events, which can be positioned in such a way that
# multiple trainer events spot the player at once. The extra code in this method
# deals with that case and can cause a double trainer battle instead.
def pbTrainerBattle(trainerID, trainerName, endSpeech=nil,
doubleBattle=false, trainerPartyID=0, canLose=false, outcomeVar=1)
# If there is another NPC trainer who spotted the player at the same time, and
# it is possible to have a double battle (the player has 2+ able Pokémon or
# has a partner trainer), then record this first NPC trainer into
# $PokemonTemp.waitingTrainer and end this method. That second NPC event will
# then trigger and cause the battle to happen against this first trainer and
# themselves.
if !$PokemonTemp.waitingTrainer && pbMapInterpreterRunning? &&
($Trainer.ablePokemonCount>1 ||
($Trainer.ablePokemonCount>0 && $PokemonGlobal.partner))
thisEvent = pbMapInterpreter.get_character(0)
# Find all other triggered trainer events
triggeredEvents = $game_player.pbTriggeredTrainerEvents([2],false)
otherEvent = []
for i in triggeredEvents
next if i.id==thisEvent.id
next if $game_self_switches[[$game_map.map_id,i.id,"A"]]
otherEvent.push(i)
end
# Load the trainer's data, and call an event which might modify it
trainer = pbLoadTrainer(trainerID,trainerName,trainerPartyID)
pbMissingTrainer(trainerID,trainerName,trainerPartyID) if !trainer
return false if !trainer
Events.onTrainerPartyLoad.trigger(nil,trainer)
# If there is exactly 1 other triggered trainer event, and this trainer has
# 6 or fewer Pokémon, record this trainer for a double battle caused by the
# other triggered trainer event
if otherEvent.length==1 && trainer[2].length<=6
$PokemonTemp.waitingTrainer = [trainer,endSpeech || trainer[3],thisEvent.id]
return false
end
end
# Set some battle rules
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
setBattleRule("canLose") if canLose
setBattleRule("double") if doubleBattle || $PokemonTemp.waitingTrainer
# Perform the battle
if $PokemonTemp.waitingTrainer
waitingTrainer = $PokemonTemp.waitingTrainer
decision = pbTrainerBattleCore(
[waitingTrainer[0][0],waitingTrainer[0][2],waitingTrainer[1],waitingTrainer[0][1]],
[trainerID,trainerName,trainerPartyID,endSpeech]
)
else
decision = pbTrainerBattleCore([trainerID,trainerName,trainerPartyID,endSpeech])
end
# Finish off the recorded waiting trainer, because they have now been battled
if decision==1 && $PokemonTemp.waitingTrainer # Win
pbMapInterpreter.pbSetSelfSwitch($PokemonTemp.waitingTrainer[2],"A",true)
end
$PokemonTemp.waitingTrainer = nil
# Return true if the player won the battle, and false if any other result
return (decision==1)
end
def pbDoubleTrainerBattle(trainerID1, trainerName1, trainerPartyID1, endSpeech1,
trainerID2, trainerName2, trainerPartyID2=0, endSpeech2=nil,
canLose=false, outcomeVar=1)
# Set some battle rules
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
setBattleRule("canLose") if canLose
setBattleRule("double")
# Perform the battle
decision = pbTrainerBattleCore(
[trainerID1,trainerName1,trainerPartyID1,endSpeech1],
[trainerID2,trainerName2,trainerPartyID2,endSpeech2]
)
# Return true if the player won the battle, and false if any other result
return (decision==1)
end
def pbTripleTrainerBattle(trainerID1, trainerName1, trainerPartyID1, endSpeech1,
trainerID2, trainerName2, trainerPartyID2, endSpeech2,
trainerID3, trainerName3, trainerPartyID3=0, endSpeech3=nil,
canLose=false, outcomeVar=1)
# Set some battle rules
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
setBattleRule("canLose") if canLose
setBattleRule("triple")
# Perform the battle
decision = pbTrainerBattleCore(
[trainerID1,trainerName1,trainerPartyID1,endSpeech1],
[trainerID2,trainerName2,trainerPartyID2,endSpeech2],
[trainerID3,trainerName3,trainerPartyID3,endSpeech3]
)
# Return true if the player won the battle, and false if any other result
return (decision==1)
end
#===============================================================================
# After battles
#===============================================================================
def pbAfterBattle(decision,canLose)
$Trainer.party.each do |pkmn|
pkmn.statusCount = 0 if pkmn.status==PBStatuses::POISON # Bad poison becomes regular
pkmn.makeUnmega
pkmn.makeUnprimal
end
if $PokemonGlobal.partner
pbHealAll
$PokemonGlobal.partner[3].each do |pkmn|
pkmn.heal
pkmn.makeUnmega
pkmn.makeUnprimal
end
end
if decision==2 || decision==5 # if loss or draw
if canLose
$Trainer.party.each { |pkmn| pkmn.heal }
(Graphics.frame_rate/4).times { Graphics.update }
end
end
Events.onEndBattle.trigger(nil,decision,canLose)
end
Events.onEndBattle += proc { |sender,e|
decision = e[0]
canLose = e[1]
if NEWEST_BATTLE_MECHANICS || (decision!=2 && decision!=5) # not a loss or a draw
if $PokemonTemp.evolutionLevels
pbEvolutionCheck($PokemonTemp.evolutionLevels)
$PokemonTemp.evolutionLevels = nil
end
end
case decision
when 1, 4 # Win, capture
$Trainer.pokemonParty.each do |pkmn|
pbPickup(pkmn)
pbHoneyGather(pkmn)
end
when 2, 5 # Lose, draw
if !canLose
$game_system.bgm_unpause
$game_system.bgs_unpause
pbStartOver
end
end
}
def pbEvolutionCheck(currentLevels)
for i in 0...currentLevels.length
pkmn = $Trainer.party[i]
next if !pkmn || (pkmn.hp==0 && !NEWEST_BATTLE_MECHANICS)
next if currentLevels[i] && pkmn.level==currentLevels[i]
newSpecies = pbCheckEvolution(pkmn)
next if newSpecies<=0
evo = PokemonEvolutionScene.new
evo.pbStartScreen(pkmn,newSpecies)
evo.pbEvolution
evo.pbEndScreen
end
end
def pbDynamicItemList(*args)
ret = []
for i in 0...args.length
next if !hasConst?(PBItems,args[i])
ret.push(getConst(PBItems,args[i].to_sym))
end
return ret
end
# Try to gain an item after a battle if a Pokemon has the ability Pickup.
def pbPickup(pkmn)
return if pkmn.egg? || !pkmn.hasAbility?(:PICKUP)
return if pkmn.hasItem?
return unless rand(100)<10 # 10% chance
# Common items to find (9 items from this list are added to the pool)
pickupList = pbDynamicItemList(
:POTION,
:ANTIDOTE,
:SUPERPOTION,
:GREATBALL,
:REPEL,
:ESCAPEROPE,
:FULLHEAL,
:HYPERPOTION,
:ULTRABALL,
:REVIVE,
:RARECANDY,
:SUNSTONE,
:MOONSTONE,
:HEARTSCALE,
:FULLRESTORE,
:MAXREVIVE,
:PPUP,
:MAXELIXIR
)
# Rare items to find (2 items from this list are added to the pool)
pickupListRare = pbDynamicItemList(
:HYPERPOTION,
:NUGGET,
:KINGSROCK,
:FULLRESTORE,
:ETHER,
:IRONBALL,
:DESTINYKNOT,
:ELIXIR,
:DESTINYKNOT,
:LEFTOVERS,
:DESTINYKNOT
)
return if pickupList.length<18
return if pickupListRare.length<11
# Generate a pool of items depending on the Pokémon's level
items = []
pkmnLevel = [100,pkmn.level].min
itemStartIndex = (pkmnLevel-1)/10
itemStartIndex = 0 if itemStartIndex<0
for i in 0...9
items.push(pickupList[itemStartIndex+i])
end
for i in 0...2
items.push(pickupListRare[itemStartIndex+i])
end
# Probabilities of choosing each item in turn from the pool
chances = [30,10,10,10,10,10,10,4,4,1,1] # Needs to be 11 numbers
chanceSum = 0
chances.each { |c| chanceSum += c }
# Randomly choose an item from the pool to give to the Pokémon
rnd = rand(chanceSum)
cumul = 0
chances.each_with_index do |c,i|
cumul += c
next if rnd>=cumul
pkmn.setItem(items[i])
break
end
end
# Try to gain a Honey item after a battle if a Pokemon has the ability Honey Gather.
def pbHoneyGather(pkmn)
return if pkmn.egg? || !pkmn.hasAbility?(:HONEYGATHER)
return if pkmn.hasItem?
return if !hasConst?(PBItems,:HONEY)
chance = 5+((pkmn.level-1)/10)*5
return unless rand(100)<chance
pkmn.setItem(:HONEY)
end

View File

@@ -0,0 +1,468 @@
module EncounterTypes
Land = 0
Cave = 1
Water = 2
RockSmash = 3
OldRod = 4
GoodRod = 5
SuperRod = 6
HeadbuttLow = 7
HeadbuttHigh = 8
LandMorning = 9
LandDay = 10
LandNight = 11
BugContest = 12
Names = [
"Land",
"Cave",
"Water",
"RockSmash",
"OldRod",
"GoodRod",
"SuperRod",
"HeadbuttLow",
"HeadbuttHigh",
"LandMorning",
"LandDay",
"LandNight",
"BugContest"
]
EnctypeChances = [
[20,20,10,10,10,10,5,5,4,4,1,1],
[20,20,10,10,10,10,5,5,4,4,1,1],
[60,30,5,4,1],
[60,30,5,4,1],
[70,30],
[60,20,20],
[40,40,15,4,1],
[30,25,20,10,5,5,4,1],
[30,25,20,10,5,5,4,1],
[20,20,10,10,10,10,5,5,4,4,1,1],
[20,20,10,10,10,10,5,5,4,4,1,1],
[20,20,10,10,10,10,5,5,4,4,1,1],
[20,20,10,10,10,10,5,5,4,4,1,1]
]
EnctypeDensities = [25, 10, 10, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25]
EnctypeCompileDens = [ 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
end
#===============================================================================
#
#===============================================================================
class PokemonEncounters
attr_reader :stepcount
def initialize
@enctypes = []
@density = nil
end
def setup(mapID)
@stepcount = 0
@density = nil
@enctypes = []
begin
data = pbLoadEncountersData
if data.is_a?(Hash) && data[mapID]
@density = data[mapID][0]
@enctypes = data[mapID][1]
else
@density = nil
@enctypes = []
end
rescue
@density = nil
@enctypes = []
end
end
def clearStepCount; @stepcount = 0; end
# Returns whether encounters for the given encounter type have been defined
# for the current map.
def hasEncounter?(enc)
return false if @density==nil || enc<0
return @enctypes[enc] ? true : false
end
# Returns whether encounters for the given encounter type have been defined
# for the given map. Only called by Bug Catching Contest to see if it can use
# the map's BugContest encounter type to generate caught Pokémon for the other
# contestants.
def pbMapHasEncounter?(mapID,enctype)
data = pbLoadEncountersData
if data.is_a?(Hash) && data[mapID]
density = data[mapID][0]
enctypes = data[mapID][1]
else
return false
end
return false if density==nil || enctype<0
return enctypes[enctype] ? true : false
end
# Returns whether cave-like encounters have been defined for the current map.
# Applies only to encounters triggered by moving around.
def isCave?
return false if @density==nil
return @enctypes[EncounterTypes::Cave] ? true : false
end
# Returns whether grass-like encounters have been defined for the current map.
# Applies only to encounters triggered by moving around.
def isGrass?
return false if @density==nil
return (@enctypes[EncounterTypes::Land] ||
@enctypes[EncounterTypes::LandMorning] ||
@enctypes[EncounterTypes::LandDay] ||
@enctypes[EncounterTypes::LandNight] ||
@enctypes[EncounterTypes::BugContest]) ? true : false
end
# Returns whether grass-like encounters have been defined for the current map
# (ignoring the Bug Catching Contest one).
# Applies only to encounters triggered by moving around.
def isRegularGrass?
return false if @density==nil
return (@enctypes[EncounterTypes::Land] ||
@enctypes[EncounterTypes::LandMorning] ||
@enctypes[EncounterTypes::LandDay] ||
@enctypes[EncounterTypes::LandNight]) ? true : false
end
# Returns whether water-like encounters have been defined for the current map.
# Applies only to encounters triggered by moving around (i.e. not fishing).
def isWater?
return false if @density==nil
return @enctypes[EncounterTypes::Water] ? true : false
end
# Returns whether it is theoretically possible to have an encounter in the
# player's current location.
def isEncounterPossibleHere?
if $PokemonGlobal.surfing
return true
elsif PBTerrain.isIce?(pbGetTerrainTag($game_player))
return false
elsif self.isCave?
return true
elsif self.isGrass?
return PBTerrain.isGrass?($game_map.terrain_tag($game_player.x,$game_player.y))
end
return false
end
# Returns the encounter method that the current encounter should be generated
# from, depending on the player's current location.
def pbEncounterType
if $PokemonGlobal.surfing
return EncounterTypes::Water
elsif self.isCave?
return EncounterTypes::Cave
elsif self.isGrass?
time = pbGetTimeNow
enctype = EncounterTypes::Land
enctype = EncounterTypes::LandNight if self.hasEncounter?(EncounterTypes::LandNight) && PBDayNight.isNight?(time)
enctype = EncounterTypes::LandDay if self.hasEncounter?(EncounterTypes::LandDay) && PBDayNight.isDay?(time)
enctype = EncounterTypes::LandMorning if self.hasEncounter?(EncounterTypes::LandMorning) && PBDayNight.isMorning?(time)
if pbInBugContest? && self.hasEncounter?(EncounterTypes::BugContest)
enctype = EncounterTypes::BugContest
end
return enctype
end
return -1
end
# Returns all the encounter tables for the given map.
# You can alias this method and modify the returned array's contents if you
# want to change the encounter table for some reason. Note that each sub-array
# should contain the right number of entries for that encounter type.
# Each encounter table element is an array: [species, minLevel, maxLevel]
def pbGetEncounterTables(mapID=-1)
if mapID>0
data = pbLoadEncountersData
return nil if !data.is_a?(Hash) || !data[mapID]
return data[mapID][1]
else # Current map
return Marshal.load(Marshal.dump(@enctypes))
end
end
# Returns an array of the encounter table for the given map/encounter type.
def pbGetEncounterTable(encType,mapID=-1)
ret = pbGetEncounterTables(mapID)
return ret[encType]
end
# Only called by Bug Catching Contest, when determining what the other
# contestants caught.
def pbMapEncounter(mapID,encType)
if encType<0 || encType>EncounterTypes::EnctypeChances.length
raise ArgumentError.new(_INTL("Encounter type out of range"))
end
# Get the encounter table
encList = pbGetEncounterTable(encType,mapID)
return nil if encList==nil
# Calculate the total probability value
chances = EncounterTypes::EnctypeChances[encType]
chanceTotal = 0
chances.each { |a| chanceTotal += a }
# Choose a random entry in the encounter table based on entry weights
rnd = rand(chanceTotal)
chance = 0
chosenPkmn = 0 # Index of the chosen entry
for i in 0...chances.length
chance += chances[i]
if rnd<chance
chosenPkmn = i
break
end
end
# Return the chosen species and level
encounter = encList[chosenPkmn]
level = encounter[1]+rand(1+encounter[2]-encounter[1])
return [encounter[0],level]
end
# Determines the species and level of the Pokémon to be encountered on the
# current map, given the encounter type. May return nil if the given encounter
# type has no encounters defined for it for the current map.
def pbEncounteredPokemon(enctype,tries=1)
if enctype<0 || enctype>EncounterTypes::EnctypeChances.length
raise ArgumentError.new(_INTL("Encounter type out of range"))
end
# Get the encounter table
encList = pbGetEncounterTable(enctype)
return nil if encList==nil
chances = EncounterTypes::EnctypeChances[enctype]
# Static/Magnet Pull prefer wild encounters of certain types, if possible.
# If they activate, they remove all Pokémon from the encounter table that do
# not have the type they favor. If none have that type, nothing is changed.
firstPkmn = $Trainer.firstPokemon
if firstPkmn && rand(100)<50 # 50% chance of happening
favoredType = -1
if isConst?(firstPkmn.ability,PBAbilities,:STATIC) && hasConst?(PBTypes,:ELECTRIC)
favoredType = getConst(PBTypes,:ELECTRIC)
elsif isConst?(firstPkmn.ability,PBAbilities,:MAGNETPULL) && hasConst?(PBTypes,:STEEL)
favoredType = getConst(PBTypes,:STEEL)
end
if favoredType>=0
newEncList = []
newChances = []
speciesData = pbLoadSpeciesData
for i in 0...encList.length
t1 = speciesData[encList[i][0]][SpeciesType1]
t2 = speciesData[encList[i][0]][SpeciesType2]
next if t1!=favoredType && (!t2 || t2!=favoredType)
newEncList.push(encList[i])
newChances.push(chances[i])
end
if newEncList.length>0
encList = newEncList
chances = newChances
end
end
end
# Calculate the total probability value
chanceTotal = 0
chances.each { |a| chanceTotal += a }
# Choose a random entry in the encounter table based on entry weights
rnd = 0
tries.times do
r = rand(chanceTotal)
rnd = r if rnd<r
end
chance = 0
chosenPkmn = 0 # Index of the chosen entry
for i in 0...chances.length
chance += chances[i]
if rnd<chance
chosenPkmn = i
break
end
end
# Get the chosen species and level
encounter = encList[chosenPkmn]
return nil if !encounter
level = encounter[1]+rand(1+encounter[2]-encounter[1])
# Some abilities alter the level of the wild Pokémon
if firstPkmn && rand(100)<50 # 50% chance of happening
if isConst?(firstPkmn.ability,PBAbilities,:HUSTLE) ||
isConst?(firstPkmn.ability,PBAbilities,:VITALSPIRIT) ||
isConst?(firstPkmn.ability,PBAbilities,:PRESSURE)
level2 = encounter[1]+rand(1+encounter[2]-encounter[1])
level = level2 if level2>level # Higher level is more likely
end
end
# Black Flute and White Flute alter the level of the wild Pokémon
if NEWEST_BATTLE_MECHANICS
if $PokemonMap.blackFluteUsed
level = [level+1+rand(3),PBExperience.maxLevel].min
elsif $PokemonMap.whiteFluteUsed
level = [level-1-rand(3),1].max
end
end
# Return [species, level]
return [encounter[0],level]
end
# Returns the encountered Pokémon's species/level, taking into account factors
# that alter the probability of an encounter (cycling, Flutes, lead party
# Pokémon's item/ability).
def pbGenerateEncounter(enctype)
if enctype<0 || enctype>EncounterTypes::EnctypeChances.length
raise ArgumentError.new(_INTL("Encounter type out of range"))
end
# Check if an encounter table is defined
return nil if @density==nil
return nil if @density[enctype]==0 || !@density[enctype]
return nil if @enctypes[enctype]==nil
# Wild encounters cannot happen for the first 3 steps after a previous wild
# encounter
@stepcount += 1
return nil if @stepcount<=3
# Determine the encounter density (probability of a wild encounter
# happening). The actual probability is the written encounter density, with
# modifiers applied, divided by 180 (numbers are multiplied by 16 below to
# increase precision).
encount = @density[enctype]*16
encount = encount*0.8 if $PokemonGlobal.bicycle
if !NEWEST_BATTLE_MECHANICS
if $PokemonMap.blackFluteUsed
encount = encount/2
elsif $PokemonMap.whiteFluteUsed
encount = encount*1.5
end
end
firstPkmn = $Trainer.firstPokemon
if firstPkmn
if isConst?(firstPkmn.item,PBItems,:CLEANSETAG)
encount = encount*2/3
elsif isConst?(firstPkmn.item,PBItems,:PUREINCENSE)
encount = encount*2/3
else # Ignore ability effects if an item effect applies
if isConst?(firstPkmn.ability,PBAbilities,:STENCH)
encount = encount/2
elsif isConst?(firstPkmn.ability,PBAbilities,:WHITESMOKE)
encount = encount/2
elsif isConst?(firstPkmn.ability,PBAbilities,:QUICKFEET)
encount = encount/2
elsif isConst?(firstPkmn.ability,PBAbilities,:SNOWCLOAK)
encount = encount/2 if $game_screen.weather_type==PBFieldWeather::Snow ||
$game_screen.weather_type==PBFieldWeather::Blizzard
elsif isConst?(firstPkmn.ability,PBAbilities,:SANDVEIL)
encount = encount/2 if $game_screen.weather_type==PBFieldWeather::Sandstorm
elsif isConst?(firstPkmn.ability,PBAbilities,:SWARM)
encount = encount*1.5
elsif isConst?(firstPkmn.ability,PBAbilities,:ILLUMINATE)
encount = encount*2
elsif isConst?(firstPkmn.ability,PBAbilities,:ARENATRAP)
encount = encount*2
elsif isConst?(firstPkmn.ability,PBAbilities,:NOGUARD)
encount = encount*2
end
end
end
# Decide whether the wild encounter should actually happen
return nil if rand(180*16)>=encount
# A wild encounter will happen; choose a species and level for it
encPkmn = pbEncounteredPokemon(enctype)
return nil if !encPkmn
# Some abilities make wild encounters less likely if the wild Pokémon is
# sufficiently weaker than the Pokémon with the ability
if firstPkmn && rand(100)<50 # 50% chance of happening
if isConst?(firstPkmn.ability,PBAbilities,:INTIMIDATE) ||
isConst?(firstPkmn.ability,PBAbilities,:KEENEYE)
return nil if encPkmn[1]<=firstPkmn.level-5 # 5 or more levels weaker
end
end
return encPkmn
end
# Returns whether it is possible to have an encounter, based on some factors
# that would prevent it (holding Ctrl in Debug mode, Repels).
def pbCanEncounter?(encounter,repel)
return false if $game_system.encounter_disabled
return false if !encounter || !$Trainer
return false if $DEBUG && Input.press?(Input::CTRL)
if !pbPokeRadarOnShakingGrass
if $PokemonGlobal.repel>0 || repel
firstPkmn = (NEWEST_BATTLE_MECHANICS) ? $Trainer.firstPokemon : $Trainer.firstAblePokemon
return false if firstPkmn && encounter[1]<firstPkmn.level
end
end
return true
end
end
#===============================================================================
#
#===============================================================================
# Returns a Pokémon generated by a wild encounter, given its species and level.
def pbGenerateWildPokemon(species,level,isRoamer=false)
genwildpoke = pbNewPkmn(species,level)
# Give the wild Pokémon a held item
items = genwildpoke.wildHoldItems
firstPkmn = $Trainer.firstPokemon
chances = [50,5,1]
chances = [60,20,5] if firstPkmn && isConst?(firstPkmn.ability,PBAbilities,:COMPOUNDEYES)
itemrnd = rand(100)
if (items[0]==items[1] && items[1]==items[2]) || itemrnd<chances[0]
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
# Shiny Charm makes shiny Pokémon more likely to generate
if hasConst?(PBItems,:SHINYCHARM) && $PokemonBag.pbHasItem?(:SHINYCHARM)
for i in 0...2 # 3 times as likely
break if genwildpoke.shiny?
genwildpoke.personalID = rand(65536)|(rand(65536)<<16)
end
end
# Give Pokérus
if rand(65536)<POKERUS_CHANCE
genwildpoke.givePokerus
end
# Change wild Pokémon's gender/nature depending on the lead party Pokémon's
# ability
if firstPkmn
if isConst?(firstPkmn.ability,PBAbilities,:CUTECHARM) && !genwildpoke.singleGendered?
if firstPkmn.male?
(rand(3)<2) ? genwildpoke.makeFemale : genwildpoke.makeMale
elsif firstPkmn.female?
(rand(3)<2) ? genwildpoke.makeMale : genwildpoke.makeFemale
end
elsif isConst?(firstPkmn.ability,PBAbilities,:SYNCHRONIZE)
genwildpoke.setNature(firstPkmn.nature) if !isRoamer && rand(100)<50
end
end
# Trigger events that may alter the generated Pokémon further
Events.onWildPokemonCreate.trigger(nil,genwildpoke)
return genwildpoke
end
# Used by fishing rods and Headbutt/Rock Smash/Sweet Scent. Skips the
# probability checks in def pbGenerateEncounter above.
def pbEncounter(enctype)
$PokemonTemp.encounterType = enctype
encounter1 = $PokemonEncounters.pbEncounteredPokemon(enctype)
encounter1 = EncounterModifier.trigger(encounter1)
return false if !encounter1
encounter2 = nil
if $PokemonGlobal.partner
encounter2 = $PokemonEncounters.pbEncounteredPokemon(enctype)
encounter2 = EncounterModifier.trigger(encounter2)
return false if !encounter2
pbDoubleWildBattle(encounter1[0],encounter1[1],encounter2[0],encounter2[1])
else
pbWildBattle(encounter1[0],encounter1[1])
end
$PokemonTemp.encounterType = -1
return true
end

View File

@@ -0,0 +1,45 @@
################################################################################
# This section was created solely for you to put various bits of code that
# modify various wild Pokémon and trainers immediately prior to battling them.
# Be sure that any code you use here ONLY applies to the Pokémon/trainers you
# want it to apply to!
################################################################################
# Make all wild Pokémon shiny while a certain Switch is ON (see Settings).
Events.onWildPokemonCreate += proc { |sender,e|
pokemon = e[0]
if $game_switches[SHINY_WILD_POKEMON_SWITCH]
pokemon.makeShiny
end
}
# Used in the random dungeon map. Makes the levels of all wild Pokémon in that
# map depend on the levels of Pokémon in the player's party.
# This is a simple method, and can/should be modified to account for evolutions
# and other such details. Of course, you don't HAVE to use this code.
Events.onWildPokemonCreate += proc { |sender,e|
pokemon = e[0]
if $game_map.map_id==51
mLevel = PBExperience.maxLevel
newlevel = pbBalancedLevel($Trainer.party) - 4 + rand(5) # For variety
newlevel = 1 if newlevel<1
newlevel = mLevel if newlevel>mLevel
pokemon.level = newlevel
pokemon.calcStats
pokemon.resetMoves
end
}
# This is the basis of a trainer modifier. It works both for trainers loaded
# when you battle them, and for partner trainers when they are registered.
# Note that you can only modify a partner trainer's Pokémon, and not the trainer
# themselves nor their items this way, as those are generated from scratch
# before each battle.
#Events.onTrainerPartyLoad += proc { |sender,e|
# if e[0] # Trainer data should exist to be loaded, but may not exist somehow
# trainer = e[0][0] # A PokeBattle_Trainer object of the loaded trainer
# items = e[0][1] # An array of the trainer's items they can use
# party = e[0][2] # An array of the trainer's Pokémon
# YOUR CODE HERE
# end
#}

View File

@@ -0,0 +1,247 @@
class PokemonGlobalMetadata
attr_accessor :roamPosition
attr_accessor :roamedAlready # Whether a roamer has been encountered on current map
attr_accessor :roamEncounter
attr_accessor :roamPokemon
attr_accessor :roamPokemonCaught
def roamPokemonCaught
@roamPokemonCaught = [] if !@roamPokemonCaught
return @roamPokemonCaught
end
end
#===============================================================================
# Making roaming Pokémon roam around.
#===============================================================================
# Resets all roaming Pokemon that were defeated without having been caught.
def pbResetAllRoamers
return if !$PokemonGlobal.roamPokemon
for i in 0...$PokemonGlobal.roamPokemon.length
next if $PokemonGlobal.roamPokemon[i]!=true || !$PokemonGlobal.roamPokemonCaught[i]
$PokemonGlobal.roamPokemon[i] = nil
end
end
# Gets the roaming areas for a particular Pokémon.
def pbRoamingAreas(idxRoamer)
# [species symbol, level, Game Switch, encounter type, battle BGM, area maps hash]
roamData = RoamingSpecies[idxRoamer]
return roamData[5] if roamData && roamData[5]
return RoamingAreas
end
# Puts a roamer in a completely random map available to it.
def pbRandomRoam(index)
return if !$PokemonGlobal.roamPosition
keys = pbRoamingAreas(index).keys
$PokemonGlobal.roamPosition[index] = keys[rand(keys.length)]
end
# Makes all roaming Pokémon roam to another map.
def pbRoamPokemon
$PokemonGlobal.roamPokemon = [] if !$PokemonGlobal.roamPokemon
# Start all roamers off in random maps
if !$PokemonGlobal.roamPosition
$PokemonGlobal.roamPosition = {}
for i in 0...RoamingSpecies.length
species = getID(PBSpecies,RoamingSpecies[i][0])
next if !species || species<=0
keys = pbRoamingAreas(i).keys
$PokemonGlobal.roamPosition[i] = keys[rand(keys.length)]
end
end
# Roam each Pokémon in turn
for i in 0...RoamingSpecies.length
pbRoamPokemonOne(i)
end
end
# Makes a single roaming Pokémon roam to another map. Doesn't roam if it isn't
# currently possible to encounter it (i.e. its Game Switch is off).
def pbRoamPokemonOne(idxRoamer)
# [species symbol, level, Game Switch, encounter type, battle BGM, area maps hash]
roamData = RoamingSpecies[idxRoamer]
return if roamData[2]>0 && !$game_switches[roamData[2]] # Game Switch is off
# Ensure species is a number rather than a string/symbol
species = getID(PBSpecies,roamData[0])
return if !species || species<=0
# Get hash of area patrolled by the roaming Pokémon
mapIDs = pbRoamingAreas(idxRoamer).keys
return if !mapIDs || mapIDs.length==0 # No roaming area defined somehow
# Get the roaming Pokémon's current map
currentMap = $PokemonGlobal.roamPosition[idxRoamer]
if !currentMap
currentMap = mapIDs[rand(mapIDs.length)]
$PokemonGlobal.roamPosition[idxRoamer] = currentMap
end
# Make an array of all possible maps the roaming Pokémon could roam to
newMapChoices = []
nextMaps = pbRoamingAreas(idxRoamer)[currentMap]
return if !nextMaps
for map in nextMaps
# Only add map as a choice if the player hasn't been there recently
newMapChoices.push(map)
end
# Rarely, add a random possible map into the mix
if rand(32)==0
newMapChoices.push(mapIDs[rand(mapIDs.length)])
end
# Choose a random new map to roam to
if newMapChoices.length>0
$PokemonGlobal.roamPosition[idxRoamer] = newMapChoices[rand(newMapChoices.length)]
end
end
# When the player moves to a new map (with a different name), make all roaming
# Pokémon roam.
Events.onMapChange += proc { |sender,e|
oldMapID = e[0]
# Get and compare map names
mapInfos = $RPGVX ? load_data("Data/MapInfos.rvdata") : load_data("Data/MapInfos.rxdata")
next if mapInfos && oldMapID>0 && mapInfos[oldMapID] &&
mapInfos[oldMapID].name && $game_map.name==mapInfos[oldMapID].name
# Make roaming Pokémon roam
pbRoamPokemon
$PokemonGlobal.roamedAlready = false
}
#===============================================================================
# Encountering a roaming Pokémon in a wild battle.
#===============================================================================
class PokemonTemp
attr_accessor :roamerIndex # Index of roaming Pokémon to encounter next
end
# Returns whether the given category of encounter contains the actual encounter
# method that will occur in the player's current position.
def pbRoamingMethodAllowed(encType)
encounter = $PokemonEncounters.pbEncounterType
case encType
when 0 # Any encounter method (except triggered ones and Bug Contest)
return true if encounter==EncounterTypes::Land ||
encounter==EncounterTypes::LandMorning ||
encounter==EncounterTypes::LandDay ||
encounter==EncounterTypes::LandNight ||
encounter==EncounterTypes::Water ||
encounter==EncounterTypes::Cave
when 1 # Grass (except Bug Contest)/walking in caves only
return true if encounter==EncounterTypes::Land ||
encounter==EncounterTypes::LandMorning ||
encounter==EncounterTypes::LandDay ||
encounter==EncounterTypes::LandNight ||
encounter==EncounterTypes::Cave
when 2 # Surfing only
return true if encounter==EncounterTypes::Water
when 3 # Fishing only
return true if encounter==EncounterTypes::OldRod ||
encounter==EncounterTypes::GoodRod ||
encounter==EncounterTypes::SuperRod
when 4 # Water-based only
return true if encounter==EncounterTypes::Water ||
encounter==EncounterTypes::OldRod ||
encounter==EncounterTypes::GoodRod ||
encounter==EncounterTypes::SuperRod
end
return false
end
EncounterModifier.register(proc { |encounter|
$PokemonTemp.roamerIndex = nil
next nil if !encounter
# Give the regular encounter if encountering a roaming Pokémon isn't possible
next encounter if $PokemonGlobal.roamedAlready
next encounter if $PokemonGlobal.partner
next encounter if $PokemonTemp.pokeradar
next encounter if rand(100)<75 # 25% chance of encountering a roaming Pokémon
# Look at each roaming Pokémon in turn and decide whether it's possible to
# encounter it
roamerChoices = []
for i in 0...RoamingSpecies.length
# [species symbol, level, Game Switch, encounter type, battle BGM, area maps hash]
roamData = RoamingSpecies[i]
next if roamData[2]>0 && !$game_switches[roamData[2]] # Game Switch is off
next if $PokemonGlobal.roamPokemon[i]==true # Roaming Pokémon has been caught
# Ensure species is a number rather than a string/symbol
species = getID(PBSpecies,roamData[0])
next if !species || species<=0
# Get the roaming Pokémon's current map
roamerMap = $PokemonGlobal.roamPosition[i]
if !roamerMap
mapIDs = pbRoamingAreas(i).keys # Hash of area patrolled by the roaming Pokémon
next if !mapIDs || mapIDs.length==0 # No roaming area defined somehow
roamerMap = mapIDs[rand(mapIDs.length)]
$PokemonGlobal.roamPosition[i] = roamerMap
end
# Check if roaming Pokémon is on the current map. If not, check if roaming
# Pokémon is on a map with the same name as the current map and both maps
# are in the same region
if roamerMap!=$game_map.map_id
currentRegion = pbGetCurrentRegion
next if pbGetMetadata(roamerMap,MetadataMapPosition)[0]!=currentRegion
currentMapName = pbGetMessage(MessageTypes::MapNames,$game_map.map_id)
next if pbGetMessage(MessageTypes::MapNames,roamerMap)!=currentMapName
end
# Check whether the roaming Pokémon's category of encounter is currently possible
next if !pbRoamingMethodAllowed(roamData[3])
# Add this roaming Pokémon to the list of possible roaming Pokémon to encounter
roamerChoices.push([i,species,roamData[1],roamData[4]])
end
# No encounterable roaming Pokémon were found, just have the regular encounter
next encounter if roamerChoices.length==0
# Pick a roaming Pokémon to encounter out of those available
chosenRoamer = roamerChoices[rand(roamerChoices.length)]
$PokemonGlobal.roamEncounter = chosenRoamer
$PokemonTemp.roamerIndex = chosenRoamer[0] # Roaming Pokémon's index
if chosenRoamer[3] && chosenRoamer[3]!=""
$PokemonGlobal.nextBattleBGM = chosenRoamer[3]
end
$PokemonTemp.forceSingleBattle = true
next [chosenRoamer[1],chosenRoamer[2]] # Species, level
})
Events.onWildBattleOverride += proc { |sender,e|
species = e[0]
level = e[1]
handled = e[2]
next if handled[0]!=nil
next if !$PokemonGlobal.roamEncounter
next if $PokemonTemp.roamerIndex==nil
handled[0] = pbRoamingPokemonBattle(species,level)
}
def pbRoamingPokemonBattle(species, level)
# Get the roaming Pokémon to encounter; generate it based on the species and
# level if it doesn't already exist
idxRoamer = $PokemonTemp.roamerIndex
if !$PokemonGlobal.roamPokemon[idxRoamer] ||
!$PokemonGlobal.roamPokemon[idxRoamer].is_a?(PokeBattle_Pokemon)
$PokemonGlobal.roamPokemon[idxRoamer] = pbGenerateWildPokemon(species,level,true)
end
# Set some battle rules
setBattleRule("single")
setBattleRule("roamerFlees")
# Perform the battle
decision = pbWildBattleCore($PokemonGlobal.roamPokemon[idxRoamer])
# Update Roaming Pokémon data based on result of battle
if decision==1 || decision==4 # Defeated or caught
$PokemonGlobal.roamPokemon[idxRoamer] = true
$PokemonGlobal.roamPokemonCaught[idxRoamer] = (decision==4)
end
$PokemonGlobal.roamEncounter = nil
$PokemonGlobal.roamedAlready = true
# 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
EncounterModifier.registerEncounterEnd(proc{
$PokemonTemp.roamerIndex = nil
})

View File

@@ -0,0 +1,584 @@
# This class is designed to favor different values more than a uniform
# random generator does
class AntiRandom
def initialize(size)
@old=[]
@new=[]
for i in 0...size
@new[i]=i
end
end
def get
if @new.length==0
# No new values
@new=@old.clone
@old.clear
end
if @old.length>0 && rand(7)==0
# Get old value
value=rand(@old.length)
return @old[value]
else
if @new.length>0
# Get new value
value=rand(@new.length)
ret=@new.delete_at(value)
@old.push(ret)
return ret
else
# Get old value
value=rand(@old.length)
return @old[value]
end
end
return 0
end
end
class DungeonMaze
TILE_WIDTH = 13
TILE_HEIGHT = 13
def self.paintRect(tile,x,y,w,h) # paints a room
for j in 0...h
for i in 0...w
tile[(j+y)*TILE_WIDTH+(i+x)]=3
end
end
end
def self.paintTile(dungeon,dstX,dstY,tile,rotation) # paints a tile
if rotation==None
for y in 0...TILE_HEIGHT;for x in 0...TILE_WIDTH
dungeon[x+dstX,y+dstY]=tile[y*TILE_WIDTH+x]
end;end
elsif rotation==TurnLeft
for y in 0...TILE_HEIGHT;for x in 0...TILE_WIDTH
dungeon[y+dstX,TILE_WIDTH-1-x+dstY]=tile[y*TILE_WIDTH+x]
end;end
elsif rotation==TurnRight
for y in 0...TILE_HEIGHT;for x in 0...TILE_WIDTH
dungeon[TILE_HEIGHT-1-y+dstX,x+dstY]=tile[y*TILE_WIDTH+x]
end;end
elsif rotation==Turn180
for y in 0...TILE_HEIGHT;for x in 0...TILE_WIDTH
dungeon[TILE_WIDTH-1-x+dstX,TILE_HEIGHT-1-y+dstY]=tile[y*TILE_WIDTH+x]
end;end
end
end
MINWIDTH = 5
MINHEIGHT = 4
MAXWIDTH = 11
MAXHEIGHT = 10
None = 0
TurnLeft = 1
TurnRight = 2
Turn180 = 3
def self.paintCell(dungeon,xDst,yDst,tile,rotation)
return false if !tile
paintTile(dungeon,xDst,yDst,tile,rotation)
if rand(10)<7
# Generate a randomly placed room
width=MINWIDTH+rand(MAXWIDTH-MINWIDTH+1)
height=MINHEIGHT+rand(MAXHEIGHT-MINHEIGHT+1)
return false if width<=0 || height<=0
centerX=TILE_WIDTH/2
centerY=TILE_HEIGHT/2
centerX=(rand(2)==0) ? centerX-rand(3) : centerX+rand(3)
centerY=(rand(2)==0) ? centerY-rand(3) : centerY+rand(3)
x=centerX-(width/2)
y=centerY-(height/2)
rect=[x,y,width,height]
rect[0]=1 if rect[0]<1
rect[1]=2 if rect[1]<2
rect[0]=TILE_WIDTH-1-width if rect[0]+width>TILE_WIDTH-1
rect[1]=TILE_HEIGHT-1-height if rect[0]+height>TILE_HEIGHT-1
dungeon.paint(rect,xDst,yDst)
return true
end
return false
end
def self.generateTiles
tiles=[]
for i in 0...6
tiles[i]=[]
for j in 0...TILE_WIDTH*TILE_HEIGHT
tiles[i][j]=0
end
end
paintRect(tiles[0],5,0,3,10) # N
paintRect(tiles[1],5,0,3,8) # N E
paintRect(tiles[1],5,5,8,3)
paintRect(tiles[2],5,0,3,8) # N W E
paintRect(tiles[2],0,5,13,3)
paintRect(tiles[3],5,0,3,13) # N S
paintRect(tiles[4],5,0,3,13)
paintRect(tiles[4],0,5,13,3)
realtiles=[
[tiles[4],None], # N W E S
[tiles[2],Turn180], # W E S
[tiles[2],TurnRight], # N E S
[tiles[1],TurnRight], # E S
[tiles[2],TurnLeft], # N W S
[tiles[1],Turn180], # W S
[tiles[3],None], # N S
[tiles[0],Turn180], # S
[tiles[2],None], # N W E
[tiles[3],TurnLeft], # W E
[tiles[1],None], # N E
[tiles[0],TurnRight], # E
[tiles[1],TurnLeft], # N W
[tiles[0],TurnLeft], # W
[tiles[0],None], # N
[nil,None]
]
return realtiles
end
end
module EdgeMasks
North=1;West=2;East=4;South=8;Visited=16
end
# Dungeon generation algorithm found at:
# http://members.gamedev.net/potentialwell/ProceduralDungeonGeneration-JTippets.pdf
class MazeNode
def initialize
@edges=0
end
def setEdge(e); @edges|=e; end
def clearEdge(e); @edges&=~e; end
def clear; @edges=0; end
def set; @edges=15; end
def getEdge(e); return (@edges&e)!=0; end
def isBlocked?; return @edges!=0; end
end
class NodeListElement
attr_accessor :x,:y
def initialize(x,y)
@x=x;@y=y
end
end
class Maze
attr_accessor :cellWidth,:cellHeight,:nodeWidth,:nodeHeight
def initialize(cw,ch)
@nodes=[]
@cells=[]
raise ArgumentError.new if cw==0 || ch==0
@cellWidth=cw
@cellHeight=ch
@nodeWidth=cw+1
@nodeHeight=ch+1
for i in 0...@nodeWidth*@nodeHeight
@nodes[i]=MazeNode.new
end
for i in 0...cw*ch
@cells[i]=0
end
clearAllEdges()
clearAllCells()
end
def buildNodeList
list=[]
for x in 0...nodeWidth
for y in 0...nodeHeight
list.push(NodeListElement.new(x,y))
end
end
list.shuffle!
return list
end
def setEdgeNode(x,y,edge)
return if x<0||x>=nodeWidth||y<0||y>=nodeHeight
@nodes[y*nodeWidth+x].setEdge(edge)
e=0;nx=0;ny=0
if edge==EdgeMasks::North
e=EdgeMasks::South;nx=x;ny=y-1
elsif edge==EdgeMasks::South
e=EdgeMasks::North;nx=x;ny=y+1
elsif edge==EdgeMasks::East
e=EdgeMasks::West;nx=x+1;ny=y
elsif edge==EdgeMasks::West
e=EdgeMasks::East;nx=x-1;ny=y
else
return
end
return if nx<0||ny<0||nx>=nodeWidth||ny>=nodeHeight
@nodes[ny*nodeWidth+nx].setEdge(e)
end
def clearEdgeNode(x,y,edge)
return if x<0||x>=nodeWidth||y<0||y>=nodeHeight
@nodes[y*nodeWidth+x].clearEdge(edge)
e=0;nx=0;ny=0
if edge==EdgeMasks::North
e=EdgeMasks::South;nx=x;ny=y-1
elsif edge==EdgeMasks::South
e=EdgeMasks::North;nx=x;ny=y+1
elsif edge==EdgeMasks::East
e=EdgeMasks::West;nx=x+1;ny=y
elsif edge==EdgeMasks::West
e=EdgeMasks::East;nx=x-1;ny=y
else
raise ArgumentError.new
end
return if nx<0||ny<0||nx>=nodeWidth||ny>=nodeHeight
@nodes[ny*nodeWidth+nx].clearEdge(e)
end
def isBlockedNode?(x,y)
return false if x<0||y<0||x>=nodeWidth||y>=nodeHeight
return @nodes[y*nodeWidth+x].isBlocked?
end
def getEdgeNode(x,y,edge)
return false if x<0||y<0||x>=nodeWidth||y>=nodeHeight
return @nodes[y*nodeWidth+x].getEdge(edge)
end
def getEdgePattern(x,y)
pattern=0
pattern|=EdgeMasks::North if getEdgeNode(x,y,EdgeMasks::North)
pattern|=EdgeMasks::South if getEdgeNode(x,y,EdgeMasks::South)
pattern|=EdgeMasks::East if getEdgeNode(x,y,EdgeMasks::East)
pattern|=EdgeMasks::West if getEdgeNode(x,y,EdgeMasks::West)
return pattern
end
def setAllEdges
for c in 0...nodeWidth*nodeHeight
@nodes[c].set
end
end
def clearAllEdges
for c in 0...nodeWidth*nodeHeight
@nodes[c].clear
end
end
def clearAllCells
for c in 0...cellWidth*cellHeight
@cells[c]=0
end
end
def setVisited(x,y)
return if x<0||y<0||x>=cellWidth||x>=cellHeight
@cells[y*cellWidth+x]|=EdgeMasks::Visited
end
def getVisited(x,y)
return false if x<0||y<0||x>=cellWidth||x>=cellHeight
return (@cells[y*cellWidth+x]&EdgeMasks::Visited)!=0
end
def clearVisited(x,y)
return if x<0||y<0||x>=cellWidth||x>=cellHeight
@cells[y*cellWidth+x]&=~EdgeMasks::Visited
end
@@dirs=[EdgeMasks::North,EdgeMasks::South,
EdgeMasks::East,EdgeMasks::West]
def randomDir
return @@dirs[rand(4)]
end
def buildMazeWall(x,y,dir,len)
wx=x;wy=y
return if isBlockedNode?(x,y)
for c in 0...len
ox=wx;oy=wy
wy-=1 if dir==EdgeMasks::North
wx-=1 if dir==EdgeMasks::West
wx+=1 if dir==EdgeMasks::East
wy+=1 if dir==EdgeMasks::South
if isBlockedNode?(wx,wy)
setEdgeNode(ox,oy,dir); return
else
setEdgeNode(ox,oy,dir)
end
end
end
def generateWallGrowthMaze(minWall=nil,maxWall=nil)
minWall=0 if !minWall
maxWall=cellWidth if !maxWall
nlist=buildNodeList()
return if nlist.length==0
for c in 0...nlist.length
d=randomDir()
len=rand(minWall+(maxWall-minWall)+1)
x=nlist[c].x
y=nlist[c].y
buildMazeWall(x,y,d,len)
end
end
def recurseDepthFirst(x,y,depth)
setVisited(x,y)
dirs=@@dirs.shuffle!
success=0
for c in 0...4
d=dirs[c]
cx=0;cy=0
case d
when EdgeMasks::North; cx=x; cy=y-1
when EdgeMasks::South; cx=x; cy=y+1
when EdgeMasks::East; cx=x+1; cy=y
when EdgeMasks::West; cx=x-1; cy=y
end
if cx>=0 && cy>=0 && cx<cellWidth && cy<cellHeight
if !getVisited(cx,cy)
clearEdgeNode(x,y,d)
recurseDepthFirst(cx,cy,depth+1)
end
end
end
end
def generateDepthFirstMaze
sx=rand(cellWidth)
sy=rand(cellHeight)
setAllEdges()
recurseDepthFirst(sx,sy,0)
end
end
class Dungeon
attr_accessor :width,:height
XBUFFER = 7
YBUFFER = 5
class DungeonTable
def initialize(dungeon)
@dungeon=dungeon
end
def xsize; @dungeon.width; end
def ysize; @dungeon.height; end
def [](x,y)
[1,2,3,2][@dungeon[x,y]]
end
end
def initialize(width,height)
@width=width
@height=height
@array=[]
end
def clear
for i in 0...width*height
@array[i]=0
end
end
def write
ret=""
i=0
for y in 0...@height
for x in 0...@width
ret+=[" ",".","~"][value(x,y)]
i+=1
end
ret+="\r\n"
end
return ret
end
def [](x,y)
@array[y*@width+x]
end
def []=(x,y,value)
@array[y*@width+x]=value
end
def value(x,y)
return 0 if x<0||y<0||x>=@width||y>=@height
@array[y*@width+x]
end
def get(x,y)
return false if x<0||y<0||x>=@width||y>=@height
@array[y*@width+x]!=0
end
def isWall?(x,y)
if value(x,y)==0
v1=value(x,y+1)
return true if (v1==1||v1==3)
if v1==0
v1=value(x,y+2)
return true if (v1==1||v1==3)
end
end
return false
end
def isRoom?(x,y)
if value(x,y)==1
return false if value(x-1,y-1)==3
return false if value(x,y-1)==3
return false if value(x+1,y-1)==3
return false if value(x-1,y)==3
return false if value(x+1,y)==3
return false if value(x-1,y+1)==3
return false if value(x,y+1)==3
return false if value(x+1,y+1)==3
return true
end
return false
end
def generate
self.clear
maxWidth=@width-(XBUFFER*2)
maxHeight=@height-(YBUFFER*2)
cellWidth=DungeonMaze::TILE_WIDTH
cellHeight=DungeonMaze::TILE_HEIGHT
return if maxWidth<0 || maxHeight<0
if maxWidth<cellWidth || maxHeight<cellHeight
for x in 0...maxWidth
for y in 0...maxHeight
self[x+XBUFFER,y+YBUFFER]=1
end
end
return
end
maze=Maze.new(maxWidth/cellWidth,maxHeight/cellHeight)
maze.generateDepthFirstMaze()
tiles=DungeonMaze.generateTiles()
roomcount=0
for y in 0...maxHeight/cellHeight
for x in 0...maxWidth/cellWidth
tile=maze.getEdgePattern(x,y)
if DungeonMaze.paintCell(self,XBUFFER+x*cellWidth,
YBUFFER+y*cellHeight,tiles[tile][0],tiles[tile][1])
roomcount+=1
end
end
end
if roomcount==0
# Handle situation where no rooms were generated
for x in 0...maxWidth
for y in 0...maxHeight
self[x+XBUFFER,y+YBUFFER]=1
end
end
end
# Generate walls
for y in 0...@height
for x in 0...@width
if isWall?(x,y)
self[x,y]=2
end
end
end
end
def generateMapInPlace(map)
tbl=DungeonTable.new(self)
for i in 0...map.width
for j in 0...map.height
nb=TileDrawingHelper.tableNeighbors(tbl,i,j)
tile=TileDrawingHelper::NeighborsToTiles[nb]
map.data[i,j,0]=tile+48*(tbl[i,j])
map.data[i,j,1]=0
map.data[i,j,2]=0
end
end
end
def paint(rect,offsetX,offsetY)
for y in (rect[1]+offsetY...rect[1]+offsetY+rect[3])
for x in (rect[0]+offsetX...rect[0]+offsetX+rect[2])
self[x,y]=1 # room tile
end
end
end
def intersects?(r1,r2)
return !((( r2[0] + r2[2] <= r1[0] ) ||
( r2[0] >= r1[0] + r1[2] ) ||
( r2[1] + r2[3] <= r1[1] ) ||
( r2[1] >= r1[1] + r1[3] ) ) &&
(( r1[0] <= r2[0] + r2[2] )||
( r1[0] >= r2[0] + r2[2] ) ||
( r1[1] + r1[3] <= r2[1] ) ||
( r1[1] >= r2[1] + r2[3] ))
);
end
end
def pbRandomRoomTile(dungeon,tiles)
ar1=AntiRandom.new(dungeon.width)
ar2=AntiRandom.new(dungeon.height)
for i in 0...(tiles.length+1)*1000
x=ar1.get()
y=ar2.get()
if dungeon.isRoom?(x,y) &&
!tiles.any? { |item| (item[0]-x).abs<2 && (item[1]-y).abs<2 }
ret=[x,y]
tiles.push(ret)
return ret
end
end
return nil
end
Events.onMapCreate += proc { |sender, e|
mapID=e[0]
map=e[1]
tileset=e[2]
if pbGetMetadata(mapID,MetadataDungeon)
# this map is a randomly generated dungeon
dungeon=Dungeon.new(map.width,map.height)
dungeon.generate
dungeon.generateMapInPlace(map)
roomtiles=[]
# Reposition events
for event in map.events.values
tile=pbRandomRoomTile(dungeon,roomtiles)
if tile
event.x=tile[0]
event.y=tile[1]
end
end
# Override transfer X and Y
tile=pbRandomRoomTile(dungeon,roomtiles)
if tile
$game_temp.player_new_x=tile[0]
$game_temp.player_new_y=tile[1]
end
end
}

View File

@@ -0,0 +1,996 @@
#===============================================================================
# Hidden move handlers
#===============================================================================
class MoveHandlerHash < HandlerHash
def initialize
super(:PBMoves)
end
end
module HiddenMoveHandlers
CanUseMove = MoveHandlerHash.new
ConfirmUseMove = MoveHandlerHash.new
UseMove = MoveHandlerHash.new
def self.addCanUseMove(item,proc); CanUseMove.add(item,proc); end
def self.addConfirmUseMove(item,proc); ConfirmUseMove.add(item,proc); end
def self.addUseMove(item,proc); UseMove.add(item,proc); end
def self.hasHandler(item)
return CanUseMove[item]!=nil && UseMove[item]!=nil
end
# Returns whether move can be used
def self.triggerCanUseMove(item,pokemon,showmsg)
return false if !CanUseMove[item]
return CanUseMove.trigger(item,pokemon,showmsg)
end
# Returns whether the player confirmed that they want to use the move
def self.triggerConfirmUseMove(item,pokemon)
return true if !ConfirmUseMove[item]
return ConfirmUseMove.trigger(item,pokemon)
end
# Returns whether move was used
def self.triggerUseMove(item,pokemon)
return false if !UseMove[item]
return UseMove.trigger(item,pokemon)
end
end
def pbCanUseHiddenMove?(pkmn,move,showmsg=true)
return HiddenMoveHandlers.triggerCanUseMove(move,pkmn,showmsg)
end
def pbConfirmUseHiddenMove(pokemon,move)
return HiddenMoveHandlers.triggerConfirmUseMove(move,pokemon)
end
def pbUseHiddenMove(pokemon,move)
return HiddenMoveHandlers.triggerUseMove(move,pokemon)
end
# Unused
def pbHiddenMoveEvent
Events.onAction.trigger(nil)
end
def pbCheckHiddenMoveBadge(badge=-1,showmsg=true)
return true if badge<0 # No badge requirement
return true if $DEBUG
if (FIELD_MOVES_COUNT_BADGES) ? $Trainer.numbadges>=badge : $Trainer.badges[badge]
return true
end
pbMessage(_INTL("Sorry, a new Badge is required.")) if showmsg
return false
end
#===============================================================================
# Hidden move animation
#===============================================================================
def pbHiddenMoveAnimation(pokemon)
return false if !pokemon
viewport=Viewport.new(0,0,0,0)
viewport.z=99999
bg=Sprite.new(viewport)
bg.bitmap=BitmapCache.load_bitmap("Graphics/Pictures/hiddenMovebg")
sprite=PokemonSprite.new(viewport)
sprite.setOffset(PictureOrigin::Center)
sprite.setPokemonBitmap(pokemon)
sprite.z=1
sprite.visible=false
strobebitmap=AnimatedBitmap.new("Graphics/Pictures/hiddenMoveStrobes")
strobes=[]
15.times do |i|
strobe=BitmapSprite.new(26*2,8*2,viewport)
strobe.bitmap.blt(0,0,strobebitmap.bitmap,Rect.new(0,(i%2)*8*2,26*2,8*2))
strobe.z=((i%2)==0 ? 2 : 0)
strobe.visible=false
strobes.push(strobe)
end
strobebitmap.dispose
interp=RectInterpolator.new(
Rect.new(0,Graphics.height/2,Graphics.width,0),
Rect.new(0,(Graphics.height-bg.bitmap.height)/2,Graphics.width,bg.bitmap.height),
Graphics.frame_rate/4)
ptinterp=nil
phase=1
frames=0
strobeSpeed = 64*20/Graphics.frame_rate
begin
Graphics.update
Input.update
sprite.update
case phase
when 1 # Expand viewport height from zero to full
interp.update
interp.set(viewport.rect)
bg.oy=(bg.bitmap.height-viewport.rect.height)/2
if interp.done?
phase=2
ptinterp=PointInterpolator.new(
Graphics.width+(sprite.bitmap.width/2),bg.bitmap.height/2,
Graphics.width/2,bg.bitmap.height/2,
Graphics.frame_rate*4/10)
end
when 2 # Slide Pokémon sprite in from right to centre
ptinterp.update
sprite.x=ptinterp.x
sprite.y=ptinterp.y
sprite.visible=true
if ptinterp.done?
phase=3
pbPlayCry(pokemon)
frames=0
end
when 3 # Wait
frames+=1
if frames>Graphics.frame_rate*3/4
phase=4
ptinterp=PointInterpolator.new(
Graphics.width/2,bg.bitmap.height/2,
-(sprite.bitmap.width/2),bg.bitmap.height/2,
Graphics.frame_rate*4/10)
frames=0
end
when 4 # Slide Pokémon sprite off from centre to left
ptinterp.update
sprite.x=ptinterp.x
sprite.y=ptinterp.y
if ptinterp.done?
phase=5
sprite.visible=false
interp=RectInterpolator.new(
Rect.new(0,(Graphics.height-bg.bitmap.height)/2,Graphics.width,bg.bitmap.height),
Rect.new(0,Graphics.height/2,Graphics.width,0),
Graphics.frame_rate/4)
end
when 5 # Shrink viewport height from full to zero
interp.update
interp.set(viewport.rect)
bg.oy=(bg.bitmap.height-viewport.rect.height)/2
phase=6 if interp.done?
end
# Constantly stream the strobes across the screen
for strobe in strobes
strobe.ox=strobe.viewport.rect.x
strobe.oy=strobe.viewport.rect.y
if !strobe.visible # Initial placement of strobes
randomY = 16*(1+rand(bg.bitmap.height/16-2))
strobe.y = randomY+(Graphics.height-bg.bitmap.height)/2
strobe.x = rand(Graphics.width)
strobe.visible = true
elsif strobe.x<Graphics.width # Move strobe right
strobe.x += strobeSpeed
else # Strobe is off the screen, reposition it to the left of the screen
randomY = 16*(1+rand(bg.bitmap.height/16-2))
strobe.y = randomY+(Graphics.height-bg.bitmap.height)/2
strobe.x = -strobe.bitmap.width-rand(Graphics.width/4)
end
end
pbUpdateSceneMap
end while phase!=6
sprite.dispose
for strobe in strobes
strobe.dispose
end
strobes.clear
bg.dispose
viewport.dispose
return true
end
#===============================================================================
# Cut
#===============================================================================
def pbCut
move = getID(PBMoves,:CUT)
movefinder = pbCheckMove(move)
if !pbCheckHiddenMoveBadge(BADGE_FOR_CUT,false) || (!$DEBUG && !movefinder)
pbMessage(_INTL("This tree looks like it can be cut down."))
return false
end
pbMessage(_INTL("This tree looks like it can be cut down!\1"))
if pbConfirmMessage(_INTL("Would you like to cut it?"))
speciesname = (movefinder) ? movefinder.name : $Trainer.name
pbMessage(_INTL("{1} used {2}!",speciesname,PBMoves.getName(move)))
pbHiddenMoveAnimation(movefinder)
return true
end
return false
end
HiddenMoveHandlers::CanUseMove.add(:CUT,proc { |move,pkmn,showmsg|
next false if !pbCheckHiddenMoveBadge(BADGE_FOR_CUT,showmsg)
facingEvent = $game_player.pbFacingEvent
if !facingEvent || facingEvent.name.downcase!="tree"
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:CUT,proc { |move,pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
facingEvent = $game_player.pbFacingEvent
if facingEvent
pbSmashEvent(facingEvent)
end
next true
})
def pbSmashEvent(event)
return if !event
if event.name.downcase=="tree"; pbSEPlay("Cut",80)
elsif event.name.downcase=="rock"; pbSEPlay("Rock Smash",80)
end
pbMoveRoute(event,[
PBMoveRoute::Wait,2,
PBMoveRoute::TurnLeft,
PBMoveRoute::Wait,2,
PBMoveRoute::TurnRight,
PBMoveRoute::Wait,2,
PBMoveRoute::TurnUp,
PBMoveRoute::Wait,2
])
pbWait(Graphics.frame_rate*4/10)
event.erase
$PokemonMap.addErasedEvent(event.id) if $PokemonMap
end
#===============================================================================
# Dig
#===============================================================================
HiddenMoveHandlers::CanUseMove.add(:DIG,proc { |move,pkmn,showmsg|
escape = ($PokemonGlobal.escapePoint rescue nil)
if !escape || escape==[]
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
if $game_player.pbHasDependentEvents?
pbMessage(_INTL("It can't be used when you have someone with you.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::ConfirmUseMove.add(:DIG,proc { |move,pkmn|
escape = ($PokemonGlobal.escapePoint rescue nil)
next false if !escape || escape==[]
mapname = pbGetMapNameFromId(escape[0])
next pbConfirmMessage(_INTL("Want to escape from here and return to {1}?",mapname))
})
HiddenMoveHandlers::UseMove.add(:DIG,proc { |move,pokemon|
escape = ($PokemonGlobal.escapePoint rescue nil)
if escape
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
pbFadeOutIn {
$game_temp.player_new_map_id = escape[0]
$game_temp.player_new_x = escape[1]
$game_temp.player_new_y = escape[2]
$game_temp.player_new_direction = escape[3]
$scene.transfer_player
$game_map.autoplay
$game_map.refresh
}
pbEraseEscapePoint
next true
end
next false
})
#===============================================================================
# Dive
#===============================================================================
def pbDive
divemap = pbGetMetadata($game_map.map_id,MetadataDiveMap)
return false if !divemap
move = getID(PBMoves,:DIVE)
movefinder = pbCheckMove(move)
if !pbCheckHiddenMoveBadge(BADGE_FOR_DIVE,false) || (!$DEBUG && !movefinder)
pbMessage(_INTL("The sea is deep here. A Pokémon may be able to go underwater."))
return false
end
if pbConfirmMessage(_INTL("The sea is deep here. Would you like to use Dive?"))
speciesname = (movefinder) ? movefinder.name : $Trainer.name
pbMessage(_INTL("{1} used {2}!",speciesname,PBMoves.getName(move)))
pbHiddenMoveAnimation(movefinder)
pbFadeOutIn {
$game_temp.player_new_map_id = divemap
$game_temp.player_new_x = $game_player.x
$game_temp.player_new_y = $game_player.y
$game_temp.player_new_direction = $game_player.direction
$PokemonGlobal.surfing = false
$PokemonGlobal.diving = true
pbUpdateVehicle
$scene.transfer_player(false)
$game_map.autoplay
$game_map.refresh
}
return true
end
return false
end
def pbSurfacing
return if !$PokemonGlobal.diving
divemap = nil
meta = pbLoadMetadata
for i in 0...meta.length
if meta[i] && meta[i][MetadataDiveMap] && meta[i][MetadataDiveMap]==$game_map.map_id
divemap = i; break
end
end
return if !divemap
move = getID(PBMoves,:DIVE)
movefinder = pbCheckMove(move)
if !pbCheckHiddenMoveBadge(BADGE_FOR_DIVE,false) || (!$DEBUG && !movefinder)
pbMessage(_INTL("Light is filtering down from above. A Pokémon may be able to surface here."))
return false
end
if pbConfirmMessage(_INTL("Light is filtering down from above. Would you like to use Dive?"))
speciesname = (movefinder) ? movefinder.name : $Trainer.name
pbMessage(_INTL("{1} used {2}!",speciesname,PBMoves.getName(move)))
pbHiddenMoveAnimation(movefinder)
pbFadeOutIn {
$game_temp.player_new_map_id = divemap
$game_temp.player_new_x = $game_player.x
$game_temp.player_new_y = $game_player.y
$game_temp.player_new_direction = $game_player.direction
$PokemonGlobal.surfing = true
$PokemonGlobal.diving = false
pbUpdateVehicle
$scene.transfer_player(false)
surfbgm = pbGetMetadata(0,MetadataSurfBGM)
(surfbgm) ? pbBGMPlay(surfbgm) : $game_map.autoplayAsCue
$game_map.refresh
}
return true
end
return false
end
def pbTransferUnderwater(mapid,x,y,direction=$game_player.direction)
pbFadeOutIn {
$game_temp.player_new_map_id = mapid
$game_temp.player_new_x = x
$game_temp.player_new_y = y
$game_temp.player_new_direction = direction
$scene.transfer_player(false)
$game_map.autoplay
$game_map.refresh
}
end
Events.onAction += proc { |sender,e|
if $PokemonGlobal.diving
if DIVING_SURFACE_ANYWHERE
pbSurfacing
else
divemap = nil
meta = pbLoadMetadata
for i in 0...meta.length
if meta[i] && meta[i][MetadataDiveMap] && meta[i][MetadataDiveMap]==$game_map.map_id
divemap = i; break
end
end
if PBTerrain.isDeepWater?($MapFactory.getTerrainTag(divemap,$game_player.x,$game_player.y))
pbSurfacing
end
end
else
pbDive if PBTerrain.isDeepWater?($game_player.terrain_tag)
end
}
HiddenMoveHandlers::CanUseMove.add(:DIVE,proc { |move,pkmn,showmsg|
next false if !pbCheckHiddenMoveBadge(BADGE_FOR_DIVE,showmsg)
if $PokemonGlobal.diving
next true if DIVING_SURFACE_ANYWHERE
divemap = nil
meta = pbLoadMetadata
for i in 0...meta.length
if meta[i] && meta[i][MetadataDiveMap] && meta[i][MetadataDiveMap]==$game_map.map_id
divemap = i; break
end
end
if !PBTerrain.isDeepWater?($MapFactory.getTerrainTag(divemap,$game_player.x,$game_player.y))
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
else
if !pbGetMetadata($game_map.map_id,MetadataDiveMap)
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
if !PBTerrain.isDeepWater?($game_player.terrain_tag)
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
end
next true
})
HiddenMoveHandlers::UseMove.add(:DIVE,proc { |move,pokemon|
wasdiving = $PokemonGlobal.diving
if $PokemonGlobal.diving
divemap = nil
meta = pbLoadMetadata
for i in 0...meta.length
if meta[i] && meta[i][MetadataDiveMap] && meta[i][MetadataDiveMap]==$game_map.map_id
divemap = i; break
end
end
else
divemap = pbGetMetadata($game_map.map_id,MetadataDiveMap)
end
next false if !divemap
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
pbFadeOutIn {
$game_temp.player_new_map_id = divemap
$game_temp.player_new_x = $game_player.x
$game_temp.player_new_y = $game_player.y
$game_temp.player_new_direction = $game_player.direction
$PokemonGlobal.surfing = wasdiving
$PokemonGlobal.diving = !wasdiving
pbUpdateVehicle
$scene.transfer_player(false)
$game_map.autoplay
$game_map.refresh
}
next true
})
#===============================================================================
# Flash
#===============================================================================
HiddenMoveHandlers::CanUseMove.add(:FLASH,proc { |move,pkmn,showmsg|
next false if !pbCheckHiddenMoveBadge(BADGE_FOR_FLASH,showmsg)
if !pbGetMetadata($game_map.map_id,MetadataDarkMap)
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
if $PokemonGlobal.flashUsed
pbMessage(_INTL("Flash is already being used.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:FLASH,proc { |move,pokemon|
darkness = $PokemonTemp.darknessSprite
next false if !darkness || darkness.disposed?
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
$PokemonGlobal.flashUsed = true
radiusDiff = 8*20/Graphics.frame_rate
while darkness.radius<darkness.radiusMax
Graphics.update
Input.update
pbUpdateSceneMap
darkness.radius += radiusDiff
darkness.radius = darkness.radiusMax if darkness.radius>darkness.radiusMax
end
next true
})
#===============================================================================
# Fly
#===============================================================================
HiddenMoveHandlers::CanUseMove.add(:FLY,proc { |move,pkmn,showmsg|
next false if !pbCheckHiddenMoveBadge(BADGE_FOR_FLY,showmsg)
if $game_player.pbHasDependentEvents?
pbMessage(_INTL("It can't be used when you have someone with you.")) if showmsg
next false
end
if !pbGetMetadata($game_map.map_id,MetadataOutdoor)
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:FLY,proc { |move,pokemon|
if !$PokemonTemp.flydata
pbMessage(_INTL("Can't use that here."))
next false
end
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
pbFadeOutIn {
$game_temp.player_new_map_id = $PokemonTemp.flydata[0]
$game_temp.player_new_x = $PokemonTemp.flydata[1]
$game_temp.player_new_y = $PokemonTemp.flydata[2]
$game_temp.player_new_direction = 2
$PokemonTemp.flydata = nil
$scene.transfer_player
$game_map.autoplay
$game_map.refresh
}
pbEraseEscapePoint
next true
})
#===============================================================================
# Headbutt
#===============================================================================
def pbHeadbuttEffect(event=nil)
event = $game_player.pbFacingEvent(true) if !event
a = (event.x+(event.x/24).floor+1)*(event.y+(event.y/24).floor+1)
a = (a*2/5)%10 # Even 2x as likely as odd, 0 is 1.5x as likely as odd
b = ($Trainer.publicID)%10 # Practically equal odds of each value
chance = 1 # ~50%
if a==b; chance = 8 # 10%
elsif a>b && (a-b).abs<5; chance = 5 # ~30.3%
elsif a<b && (a-b).abs>5; chance = 5 # ~9.7%
end
if rand(10)>=chance
pbMessage(_INTL("Nope. Nothing..."))
else
enctype = (chance==1) ? EncounterTypes::HeadbuttLow : EncounterTypes::HeadbuttHigh
if !pbEncounter(enctype)
pbMessage(_INTL("Nope. Nothing..."))
end
end
end
def pbHeadbutt(event=nil)
move = getID(PBMoves,:HEADBUTT)
movefinder = pbCheckMove(move)
if !$DEBUG && !movefinder
pbMessage(_INTL("A Pokémon could be in this tree. Maybe a Pokémon could shake it."))
return false
end
if pbConfirmMessage(_INTL("A Pokémon could be in this tree. Would you like to use Headbutt?"))
speciesname = (movefinder) ? movefinder.name : $Trainer.name
pbMessage(_INTL("{1} used {2}!",speciesname,PBMoves.getName(move)))
pbHiddenMoveAnimation(movefinder)
pbHeadbuttEffect(event)
return true
end
return false
end
HiddenMoveHandlers::CanUseMove.add(:HEADBUTT,proc { |move,pkmn,showmsg|
facingEvent = $game_player.pbFacingEvent
if !facingEvent || facingEvent.name.downcase!="headbutttree"
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:HEADBUTT,proc { |move,pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
facingEvent = $game_player.pbFacingEvent
pbHeadbuttEffect(facingEvent)
})
#===============================================================================
# Rock Smash
#===============================================================================
def pbRockSmashRandomEncounter
if rand(100)<25
pbEncounter(EncounterTypes::RockSmash)
end
end
def pbRockSmash
move = getID(PBMoves,:ROCKSMASH)
movefinder = pbCheckMove(move)
if !pbCheckHiddenMoveBadge(BADGE_FOR_ROCKSMASH,false) || (!$DEBUG && !movefinder)
pbMessage(_INTL("It's a rugged rock, but a Pokémon may be able to smash it."))
return false
end
if pbConfirmMessage(_INTL("This rock appears to be breakable. Would you like to use Rock Smash?"))
speciesname = (movefinder) ? movefinder.name : $Trainer.name
pbMessage(_INTL("{1} used {2}!",speciesname,PBMoves.getName(move)))
pbHiddenMoveAnimation(movefinder)
return true
end
return false
end
HiddenMoveHandlers::CanUseMove.add(:ROCKSMASH,proc { |move,pkmn,showmsg|
next false if !pbCheckHiddenMoveBadge(BADGE_FOR_ROCKSMASH,showmsg)
facingEvent = $game_player.pbFacingEvent
if !facingEvent || facingEvent.name.downcase!="rock"
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:ROCKSMASH,proc { |move,pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
facingEvent = $game_player.pbFacingEvent
if facingEvent
pbSmashEvent(facingEvent)
pbRockSmashRandomEncounter
end
next true
})
#===============================================================================
# Strength
#===============================================================================
def pbStrength
if $PokemonMap.strengthUsed
pbMessage(_INTL("Strength made it possible to move boulders around."))
return false
end
move = getID(PBMoves,:STRENGTH)
movefinder = pbCheckMove(move)
if !pbCheckHiddenMoveBadge(BADGE_FOR_STRENGTH,false) || (!$DEBUG && !movefinder)
pbMessage(_INTL("It's a big boulder, but a Pokémon may be able to push it aside."))
return false
end
pbMessage(_INTL("It's a big boulder, but a Pokémon may be able to push it aside.\1"))
if pbConfirmMessage(_INTL("Would you like to use Strength?"))
speciesname = (movefinder) ? movefinder.name : $Trainer.name
pbMessage(_INTL("{1} used {2}!",speciesname,PBMoves.getName(move)))
pbHiddenMoveAnimation(movefinder)
pbMessage(_INTL("{1}'s Strength made it possible to move boulders around!",speciesname))
$PokemonMap.strengthUsed = true
return true
end
return false
end
Events.onAction += proc { |sender,e|
facingEvent = $game_player.pbFacingEvent
pbStrength if facingEvent && facingEvent.name.downcase=="boulder"
}
HiddenMoveHandlers::CanUseMove.add(:STRENGTH,proc { |move,pkmn,showmsg|
next false if !pbCheckHiddenMoveBadge(BADGE_FOR_STRENGTH,showmsg)
if $PokemonMap.strengthUsed
pbMessage(_INTL("Strength is already being used.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:STRENGTH,proc { |move,pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!\1",pokemon.name,PBMoves.getName(move)))
end
pbMessage(_INTL("{1}'s Strength made it possible to move boulders around!",pokemon.name))
$PokemonMap.strengthUsed = true
next true
})
#===============================================================================
# Surf
#===============================================================================
def pbSurf
return false if $game_player.pbFacingEvent
return false if $game_player.pbHasDependentEvents?
move = getID(PBMoves,:SURF)
movefinder = pbCheckMove(move)
if !pbCheckHiddenMoveBadge(BADGE_FOR_SURF,false) || (!$DEBUG && !movefinder)
return false
end
if pbConfirmMessage(_INTL("The water is a deep blue...\nWould you like to surf on it?"))
speciesname = (movefinder) ? movefinder.name : $Trainer.name
pbMessage(_INTL("{1} used {2}!",speciesname,PBMoves.getName(move)))
pbCancelVehicles
pbHiddenMoveAnimation(movefinder)
surfbgm = pbGetMetadata(0,MetadataSurfBGM)
pbCueBGM(surfbgm,0.5) if surfbgm
pbStartSurfing
return true
end
return false
end
def pbStartSurfing
pbCancelVehicles
$PokemonEncounters.clearStepCount
$PokemonGlobal.surfing = true
pbUpdateVehicle
$PokemonTemp.surfJump = $MapFactory.getFacingCoords($game_player.x,$game_player.y,$game_player.direction)
pbJumpToward
$PokemonTemp.surfJump = nil
$game_player.check_event_trigger_here([1,2])
end
def pbEndSurf(xOffset,yOffset)
return false if !$PokemonGlobal.surfing
x = $game_player.x
y = $game_player.y
currentTag = $game_map.terrain_tag(x,y)
facingTag = pbFacingTerrainTag
if PBTerrain.isSurfable?(currentTag) && !PBTerrain.isSurfable?(facingTag)
$PokemonTemp.surfJump = [x,y]
if pbJumpToward(1,false,true)
$game_map.autoplayAsCue
$game_player.increase_steps
result = $game_player.check_event_trigger_here([1,2])
pbOnStepTaken(result)
end
$PokemonTemp.surfJump = nil
return true
end
return false
end
def pbTransferSurfing(mapid,xcoord,ycoord,direction=$game_player.direction)
pbFadeOutIn {
$game_temp.player_new_map_id = mapid
$game_temp.player_new_x = xcoord
$game_temp.player_new_y = ycoord
$game_temp.player_new_direction = direction
$scene.transfer_player(false)
$game_map.autoplay
$game_map.refresh
}
end
Events.onAction += proc { |sender,e|
next if $PokemonGlobal.surfing
next if pbGetMetadata($game_map.map_id,MetadataBicycleAlways)
next if !PBTerrain.isSurfable?(pbFacingTerrainTag)
next if !$game_map.passable?($game_player.x,$game_player.y,$game_player.direction,$game_player)
pbSurf
}
HiddenMoveHandlers::CanUseMove.add(:SURF,proc { |move,pkmn,showmsg|
next false if !pbCheckHiddenMoveBadge(BADGE_FOR_SURF,showmsg)
if $PokemonGlobal.surfing
pbMessage(_INTL("You're already surfing.")) if showmsg
next false
end
if $game_player.pbHasDependentEvents?
pbMessage(_INTL("It can't be used when you have someone with you.")) if showmsg
next false
end
if pbGetMetadata($game_map.map_id,MetadataBicycleAlways)
pbMessage(_INTL("Let's enjoy cycling!")) if showmsg
next false
end
if !PBTerrain.isSurfable?(pbFacingTerrainTag) ||
!$game_map.passable?($game_player.x,$game_player.y,$game_player.direction,$game_player)
pbMessage(_INTL("No surfing here!")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:SURF,proc { |move,pokemon|
$game_temp.in_menu = false
pbCancelVehicles
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
surfbgm = pbGetMetadata(0,MetadataSurfBGM)
pbCueBGM(surfbgm,0.5) if surfbgm
pbStartSurfing
next true
})
#===============================================================================
# Sweet Scent
#===============================================================================
def pbSweetScent
if $game_screen.weather_type!=PBFieldWeather::None
pbMessage(_INTL("The sweet scent faded for some reason..."))
return
end
viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
viewport.z = 99999
count = 0
viewport.color.red = 255
viewport.color.green = 0
viewport.color.blue = 0
viewport.color.alpha -= 10
alphaDiff = 12 * 20 / Graphics.frame_rate
begin
if count==0 && viewport.color.alpha<128
viewport.color.alpha += alphaDiff
elsif count>Graphics.frame_rate/4
viewport.color.alpha -= alphaDiff
else
count += 1
end
Graphics.update
Input.update
pbUpdateSceneMap
end until viewport.color.alpha<=0
viewport.dispose
encounter = nil
enctype = $PokemonEncounters.pbEncounterType
if enctype<0 || !$PokemonEncounters.isEncounterPossibleHere? ||
!pbEncounter(enctype)
pbMessage(_INTL("There appears to be nothing here..."))
end
end
HiddenMoveHandlers::CanUseMove.add(:SWEETSCENT,proc { |move,pkmn,showmsg|
next true
})
HiddenMoveHandlers::UseMove.add(:SWEETSCENT,proc { |move,pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
pbSweetScent
next true
})
#===============================================================================
# Teleport
#===============================================================================
HiddenMoveHandlers::CanUseMove.add(:TELEPORT,proc { |move,pkmn,showmsg|
if !pbGetMetadata($game_map.map_id,MetadataOutdoor)
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
healing = $PokemonGlobal.healingSpot
healing = pbGetMetadata(0,MetadataHome) if !healing # Home
if !healing
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
if $game_player.pbHasDependentEvents?
pbMessage(_INTL("It can't be used when you have someone with you.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::ConfirmUseMove.add(:TELEPORT,proc { |move,pkmn|
healing = $PokemonGlobal.healingSpot
healing = pbGetMetadata(0,MetadataHome) if !healing # Home
next false if !healing
mapname = pbGetMapNameFromId(healing[0])
next pbConfirmMessage(_INTL("Want to return to the healing spot used last in {1}?",mapname))
})
HiddenMoveHandlers::UseMove.add(:TELEPORT,proc { |move,pokemon|
healing = $PokemonGlobal.healingSpot
healing = pbGetMetadata(0,MetadataHome) if !healing # Home
next false if !healing
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
pbFadeOutIn {
$game_temp.player_new_map_id = healing[0]
$game_temp.player_new_x = healing[1]
$game_temp.player_new_y = healing[2]
$game_temp.player_new_direction = 2
$scene.transfer_player
$game_map.autoplay
$game_map.refresh
}
pbEraseEscapePoint
next true
})
#===============================================================================
# Waterfall
#===============================================================================
def pbAscendWaterfall(event=nil)
event = $game_player if !event
return if !event
return if event.direction!=8 # can't ascend if not facing up
oldthrough = event.through
oldmovespeed = event.move_speed
terrain = pbFacingTerrainTag
return if !PBTerrain.isWaterfall?(terrain)
event.through = true
event.move_speed = 2
loop do
event.move_up
terrain = pbGetTerrainTag(event)
break if !PBTerrain.isWaterfall?(terrain)
end
event.through = oldthrough
event.move_speed = oldmovespeed
end
def pbDescendWaterfall(event=nil)
event = $game_player if !event
return if !event
return if event.direction!=2 # Can't descend if not facing down
oldthrough = event.through
oldmovespeed = event.move_speed
terrain = pbFacingTerrainTag
return if !PBTerrain.isWaterfall?(terrain)
event.through = true
event.move_speed = 2
loop do
event.move_down
terrain = pbGetTerrainTag(event)
break if !PBTerrain.isWaterfall?(terrain)
end
event.through = oldthrough
event.move_speed = oldmovespeed
end
def pbWaterfall
move = getID(PBMoves,:WATERFALL)
movefinder = pbCheckMove(move)
if !pbCheckHiddenMoveBadge(BADGE_FOR_WATERFALL,false) || (!$DEBUG && !movefinder)
pbMessage(_INTL("A wall of water is crashing down with a mighty roar."))
return false
end
if pbConfirmMessage(_INTL("It's a large waterfall. Would you like to use Waterfall?"))
speciesname = (movefinder) ? movefinder.name : $Trainer.name
pbMessage(_INTL("{1} used {2}!",speciesname,PBMoves.getName(move)))
pbHiddenMoveAnimation(movefinder)
pbAscendWaterfall
return true
end
return false
end
Events.onAction += proc { |sender,e|
terrain = pbFacingTerrainTag
if terrain==PBTerrain::Waterfall
pbWaterfall
elsif terrain==PBTerrain::WaterfallCrest
pbMessage(_INTL("A wall of water is crashing down with a mighty roar."))
end
}
HiddenMoveHandlers::CanUseMove.add(:WATERFALL,proc { |move,pkmn,showmsg|
next false if !pbCheckHiddenMoveBadge(BADGE_FOR_WATERFALL,showmsg)
if pbFacingTerrainTag!=PBTerrain::Waterfall
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:WATERFALL,proc { |move,pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!",pokemon.name,PBMoves.getName(move)))
end
pbAscendWaterfall
next true
})

View File

@@ -0,0 +1,584 @@
class PokemonTemp
attr_accessor :berryPlantData
end
def pbLoadBerryPlantData
$PokemonTemp = PokemonTemp.new if !$PokemonTemp
if !$PokemonTemp.berryPlantData
if pbRgssExists?("Data/berry_plants.dat")
$PokemonTemp.berryPlantData = load_data("Data/berry_plants.dat")
else
$PokemonTemp.berryPlantData = []
end
end
return $PokemonTemp.berryPlantData
end
def pbGetBerryPlantData(item)
data = pbLoadBerryPlantData
return data[item] if data[item]
return [3,15,2,5] # Hours/stage, drying/hour, min yield, max yield
end
alias __berryPlant__pbClearData pbClearData
def pbClearData
$PokemonTemp.berryPlantData = nil if $PokemonTemp
__berryPlant__pbClearData
end
Events.onSpritesetCreate += proc { |sender,e|
spriteset = e[0]
viewport = e[1]
map = spriteset.map
for i in map.events.keys
if map.events[i].name.downcase=="berryplant"
spriteset.addUserSprite(BerryPlantMoistureSprite.new(map.events[i],map,viewport))
spriteset.addUserSprite(BerryPlantSprite.new(map.events[i],map,viewport))
end
end
}
class BerryPlantMoistureSprite
def initialize(event,map,viewport=nil)
@event=event
@map=map
@light = IconSprite.new(0,0,viewport)
@light.ox=16
@light.oy=24
@oldmoisture=-1 # -1=none, 0=dry, 1=damp, 2=wet
updateGraphic
@disposed=false
end
def disposed?
return @disposed
end
def dispose
@light.dispose
@map=nil
@event=nil
@disposed=true
end
def updateGraphic
case @oldmoisture
when -1; @light.setBitmap("")
when 0; @light.setBitmap("Graphics/Characters/berrytreeDry")
when 1; @light.setBitmap("Graphics/Characters/berrytreeDamp")
when 2; @light.setBitmap("Graphics/Characters/berrytreeWet")
end
end
def update
return if !@light || !@event
newmoisture=-1
if @event.variable && @event.variable.length>6 && @event.variable[1]>0
# Berry was planted, show moisture patch
newmoisture=(@event.variable[4]>50) ? 2 : (@event.variable[4]>0) ? 1 : 0
end
if @oldmoisture!=newmoisture
@oldmoisture=newmoisture
updateGraphic
end
@light.update
if (Object.const_defined?(:ScreenPosHelper) rescue false)
@light.x = ScreenPosHelper.pbScreenX(@event)
@light.y = ScreenPosHelper.pbScreenY(@event)
@light.zoom_x = ScreenPosHelper.pbScreenZoomX(@event)
else
@light.x = @event.screen_x
@light.y = @event.screen_y
@light.zoom_x = 1.0
end
@light.zoom_y = @light.zoom_x
pbDayNightTint(@light)
end
end
class BerryPlantSprite
REPLANTS = 9
def initialize(event,map,viewport)
@event=event
@map=map
@oldstage=0
@disposed=false
berryData=event.variable
return if !berryData
@oldstage=berryData[0]
@event.character_name=""
berryData=updatePlantDetails(berryData)
setGraphic(berryData,true) # Set the event's graphic
@event.setVariable(berryData) # Set new berry data
end
def dispose
@event=nil
@map=nil
@disposed=true
end
def disposed?
@disposed
end
def update # Constantly updates, used only to immediately
berryData=@event.variable # change sprite when planting/picking berries
if berryData
berryData=updatePlantDetails(berryData) if berryData.length>6
setGraphic(berryData)
@event.setVariable(berryData)
end
end
def updatePlantDetails(berryData)
return berryData if berryData[0]==0
berryvalues=pbGetBerryPlantData(berryData[1])
timeperstage=berryvalues[0]*3600
timenow=pbGetTimeNow
if berryData.length>6
# Gen 4 growth mechanisms
# Check time elapsed since last check
timeDiff=(timenow.to_i-berryData[3]) # in seconds
return berryData if timeDiff<=0
berryData[3]=timenow.to_i # last updated now
# Mulch modifiers
dryingrate=berryvalues[1]
maxreplants=REPLANTS
ripestages=4
if isConst?(berryData[7],PBItems,:GROWTHMULCH)
timeperstage=(timeperstage*0.75).to_i
dryingrate=(dryingrate*1.5).ceil
elsif isConst?(berryData[7],PBItems,:DAMPMULCH)
timeperstage=(timeperstage*1.25).to_i
dryingrate=(dryingrate*0.5).floor
elsif isConst?(berryData[7],PBItems,:GOOEYMULCH)
maxreplants=(maxreplants*1.5).ceil
elsif isConst?(berryData[7],PBItems,:STABLEMULCH)
ripestages=6
end
# Cycle through all replants since last check
loop do
secondsalive=berryData[2]
growinglife=(berryData[5]>0) ? 3 : 4 # number of growing stages
numlifestages=growinglife+ripestages # number of growing + ripe stages
# Should replant itself?
if secondsalive+timeDiff>=timeperstage*numlifestages
# Should replant
if berryData[5]>=maxreplants # Too many replants
return [0,0,0,0,0,0,0,0]
end
# Replant
berryData[0]=2 # replants start in sprouting stage
berryData[2]=0 # seconds alive
berryData[5]+=1 # add to replant count
berryData[6]=0 # yield penalty
timeDiff-=(timeperstage*numlifestages-secondsalive)
else
break
end
end
# Update current stage and dampness
if berryData[0]>0
# Advance growth stage
oldlifetime=berryData[2]
newlifetime=oldlifetime+timeDiff
if berryData[0]<5
berryData[0]=1+(newlifetime/timeperstage).floor
berryData[0]+=1 if berryData[5]>0 # replants start at stage 2
berryData[0]=5 if berryData[0]>5
end
# Update the "seconds alive" counter
berryData[2]=newlifetime
# Reduce dampness, apply yield penalty if dry
growinglife=(berryData[5]>0) ? 3 : 4 # number of growing stages
oldhourtick=(oldlifetime/3600).floor
newhourtick=(([newlifetime,timeperstage*growinglife].min)/3600).floor
(newhourtick-oldhourtick).times do
if berryData[4]>0
berryData[4]=[berryData[4]-dryingrate,0].max
else
berryData[6]+=1
end
end
end
else
# Gen 3 growth mechanics
loop do
if berryData[0]>0 && berryData[0]<5
levels=0
# Advance time
timeDiff=(timenow.to_i-berryData[3]) # in seconds
if timeDiff>=timeperstage
levels+=1
if timeDiff>=timeperstage*2
levels+=1
if timeDiff>=timeperstage*3
levels+=1
if timeDiff>=timeperstage*4
levels+=1
end
end
end
end
levels=5-berryData[0] if levels>5-berryData[0]
break if levels==0
berryData[2]=false # not watered this stage
berryData[3]+=levels*timeperstage # add to time existed
berryData[0]+=levels # increase growth stage
berryData[0]=5 if berryData[0]>5
end
if berryData[0]>=5
# Advance time
timeDiff=(timenow.to_i-berryData[3]) # in seconds
if timeDiff>=timeperstage*4 # ripe for 4 times as long as a stage
# Replant
berryData[0]=2 # replants start at stage 2
berryData[2]=false # not watered this stage
berryData[3]+=timeperstage*4 # add to time existed
berryData[4]=0 # reset total waterings count
berryData[5]+=1 # add to replanted count
if berryData[5]>REPLANTS # Too many replants
berryData=[0,0,false,0,0,0]
break
end
else
break
end
end
end
# Check auto-watering
if berryData[0]>0 && berryData[0]<5
# Reset watering
if $game_screen &&
($game_screen.weather_type==PBFieldWeather::Rain ||
$game_screen.weather_type==PBFieldWeather::HeavyRain ||
$game_screen.weather_type==PBFieldWeather::Storm)
# If raining, plant is already watered
if berryData[2]==false
berryData[2]=true
berryData[4]+=1
end
end
end
end
return berryData
end
def setGraphic(berryData,fullcheck=false)
return if !berryData || (@oldstage==berryData[0] && !fullcheck)
case berryData[0]
when 0
@event.character_name=""
when 1
@event.character_name="berrytreeplanted" # Common to all berries
@event.turn_down
else
filename=sprintf("berrytree%s",getConstantName(PBItems,berryData[1])) rescue nil
filename=sprintf("berrytree%03d",berryData[1]) if !pbResolveBitmap("Graphics/Characters/"+filename)
if pbResolveBitmap("Graphics/Characters/"+filename)
@event.character_name=filename
case berryData[0]
when 2; @event.turn_down # X sprouted
when 3; @event.turn_left # X taller
when 4; @event.turn_right # X flowering
when 5; @event.turn_up # X berries
end
else
@event.character_name="Object ball"
end
if @oldstage!=berryData[0] && berryData.length>6 # Gen 4 growth mechanisms
$scene.spriteset.addUserAnimation(PLANT_SPARKLE_ANIMATION_ID,@event.x,@event.y,false,1) if $scene.spriteset
end
end
@oldstage=berryData[0]
end
end
def pbBerryPlant
interp=pbMapInterpreter
thisEvent=interp.get_character(0)
berryData=interp.getVariable
if !berryData
if NEW_BERRY_PLANTS
berryData=[0,0,0,0,0,0,0,0]
else
berryData=[0,0,false,0,0,0]
end
end
# Stop the event turning towards the player
case berryData[0]
when 1; thisEvent.turn_down # X planted
when 2; thisEvent.turn_down # X sprouted
when 3; thisEvent.turn_left # X taller
when 4; thisEvent.turn_right # X flowering
when 5; thisEvent.turn_up # X berries
end
watering=[]
watering.push(getConst(PBItems,:SPRAYDUCK))
watering.push(getConst(PBItems,:SQUIRTBOTTLE))
watering.push(getConst(PBItems,:WAILMERPAIL))
watering.push(getConst(PBItems,:SPRINKLOTAD))
watering.compact!
berry=berryData[1]
case berryData[0]
when 0 # empty
if NEW_BERRY_PLANTS
# Gen 4 planting mechanics
if !berryData[7] || berryData[7]==0 # No mulch used yet
cmd=pbMessage(_INTL("It's soft, earthy soil."),[
_INTL("Fertilize"),
_INTL("Plant Berry"),
_INTL("Exit")],-1)
if cmd==0 # Fertilize
ret=0
pbFadeOutIn {
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene,$PokemonBag)
ret = screen.pbChooseItemScreen(Proc.new { |item| pbIsMulch?(item) })
}
if ret>0
if pbIsMulch?(ret)
berryData[7]=ret
pbMessage(_INTL("The {1} was scattered on the soil.\1",PBItems.getName(ret)))
if pbConfirmMessage(_INTL("Want to plant a Berry?"))
pbFadeOutIn {
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene,$PokemonBag)
berry = screen.pbChooseItemScreen(Proc.new { |item| pbIsBerry?(item) })
}
if berry>0
timenow=pbGetTimeNow
berryData[0]=1 # growth stage (1-5)
berryData[1]=berry # item ID of planted berry
berryData[2]=0 # seconds alive
berryData[3]=timenow.to_i # time of last checkup (now)
berryData[4]=100 # dampness value
berryData[5]=0 # number of replants
berryData[6]=0 # yield penalty
$PokemonBag.pbDeleteItem(berry,1)
pbMessage(_INTL("The {1} was planted in the soft, earthy soil.",
PBItems.getName(berry)))
end
end
interp.setVariable(berryData)
else
pbMessage(_INTL("That won't fertilize the soil!"))
end
return
end
elsif cmd==1 # Plant Berry
pbFadeOutIn {
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene,$PokemonBag)
berry = screen.pbChooseItemScreen(Proc.new { |item| pbIsBerry?(item) })
}
if berry>0
timenow=pbGetTimeNow
berryData[0]=1 # growth stage (1-5)
berryData[1]=berry # item ID of planted berry
berryData[2]=0 # seconds alive
berryData[3]=timenow.to_i # time of last checkup (now)
berryData[4]=100 # dampness value
berryData[5]=0 # number of replants
berryData[6]=0 # yield penalty
$PokemonBag.pbDeleteItem(berry,1)
pbMessage(_INTL("The {1} was planted in the soft, earthy soil.",
PBItems.getName(berry)))
interp.setVariable(berryData)
end
return
end
else
pbMessage(_INTL("{1} has been laid down.\1",PBItems.getName(berryData[7])))
if pbConfirmMessage(_INTL("Want to plant a Berry?"))
pbFadeOutIn {
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene,$PokemonBag)
berry = screen.pbChooseItemScreen(Proc.new { |item| pbIsBerry?(item) })
}
if berry>0
timenow=pbGetTimeNow
berryData[0]=1 # growth stage (1-5)
berryData[1]=berry # item ID of planted berry
berryData[2]=0 # seconds alive
berryData[3]=timenow.to_i # time of last checkup (now)
berryData[4]=100 # dampness value
berryData[5]=0 # number of replants
berryData[6]=0 # yield penalty
$PokemonBag.pbDeleteItem(berry,1)
pbMessage(_INTL("The {1} was planted in the soft, earthy soil.",
PBItems.getName(berry)))
interp.setVariable(berryData)
end
return
end
end
else
# Gen 3 planting mechanics
if pbConfirmMessage(_INTL("It's soft, loamy soil.\nPlant a berry?"))
pbFadeOutIn {
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene,$PokemonBag)
berry = screen.pbChooseItemScreen(Proc.new { |item| pbIsBerry?(item) })
}
if berry>0
timenow=pbGetTimeNow
berryData[0]=1 # growth stage (1-5)
berryData[1]=berry # item ID of planted berry
berryData[2]=false # watered in this stage?
berryData[3]=timenow.to_i # time planted
berryData[4]=0 # total waterings
berryData[5]=0 # number of replants
berryData[6]=nil; berryData[7]=nil; berryData.compact! # for compatibility
$PokemonBag.pbDeleteItem(berry,1)
pbMessage(_INTL("{1} planted a {2} in the soft loamy soil.",
$Trainer.name,PBItems.getName(berry)))
interp.setVariable(berryData)
end
return
end
end
when 1 # X planted
pbMessage(_INTL("A {1} was planted here.",PBItems.getName(berry)))
when 2 # X sprouted
pbMessage(_INTL("The {1} has sprouted.",PBItems.getName(berry)))
when 3 # X taller
pbMessage(_INTL("The {1} plant is growing bigger.",PBItems.getName(berry)))
when 4 # X flowering
if NEW_BERRY_PLANTS
pbMessage(_INTL("This {1} plant is in bloom!",PBItems.getName(berry)))
else
case berryData[4]
when 4
pbMessage(_INTL("This {1} plant is in fabulous bloom!",PBItems.getName(berry)))
when 3
pbMessage(_INTL("This {1} plant is blooming very beautifully!",PBItems.getName(berry)))
when 2
pbMessage(_INTL("This {1} plant is blooming prettily!",PBItems.getName(berry)))
when 1
pbMessage(_INTL("This {1} plant is blooming cutely!",PBItems.getName(berry)))
else
pbMessage(_INTL("This {1} plant is in bloom!",PBItems.getName(berry)))
end
end
when 5 # X berries
berryvalues=pbGetBerryPlantData(berryData[1])
# Get berry yield (berrycount)
berrycount=1
if berryData.length>6
# Gen 4 berry yield calculation
berrycount=[berryvalues[3]-berryData[6],berryvalues[2]].max
else
# Gen 3 berry yield calculation
if berryData[4]>0
randomno=rand(1+berryvalues[3]-berryvalues[2])
berrycount=(((berryvalues[3]-berryvalues[2])*(berryData[4]-1)+randomno)/4).floor+berryvalues[2]
else
berrycount=berryvalues[2]
end
end
itemname=(berrycount>1) ? PBItems.getNamePlural(berry) : PBItems.getName(berry)
if berrycount>1
message=_INTL("There are {1} \\c[1]{2}\\c[0]!\nWant to pick them?",berrycount,itemname)
else
message=_INTL("There is 1 \\c[1]{1}\\c[0]!\nWant to pick it?",itemname)
end
if pbConfirmMessage(message)
if !$PokemonBag.pbCanStore?(berry,berrycount)
pbMessage(_INTL("Too bad...\nThe Bag is full..."))
return
end
$PokemonBag.pbStoreItem(berry,berrycount)
if berrycount>1
pbMessage(_INTL("You picked the {1} \\c[1]{2}\\c[0].\\wtnp[30]",berrycount,itemname))
else
pbMessage(_INTL("You picked the \\c[1]{1}\\c[0].\\wtnp[30]",itemname))
end
pocket = pbGetPocket(berry)
pbMessage(_INTL("{1} put the \\c[1]{2}\\c[0] in the <icon=bagPocket{3}>\\c[1]{4}\\c[0] Pocket.\1",
$Trainer.name,itemname,pocket,PokemonBag.pocketNames()[pocket]))
if NEW_BERRY_PLANTS
pbMessage(_INTL("The soil returned to its soft and earthy state."))
berryData=[0,0,0,0,0,0,0,0]
else
pbMessage(_INTL("The soil returned to its soft and loamy state."))
berryData=[0,0,false,0,0,0]
end
interp.setVariable(berryData)
end
end
case berryData[0]
when 1, 2, 3, 4
for i in watering
if i!=0 && $PokemonBag.pbHasItem?(i)
if pbConfirmMessage(_INTL("Want to sprinkle some water with the {1}?",PBItems.getName(i)))
if berryData.length>6
# Gen 4 berry watering mechanics
berryData[4]=100
else
# Gen 3 berry watering mechanics
if berryData[2]==false
berryData[4]+=1
berryData[2]=true
end
end
interp.setVariable(berryData)
pbMessage(_INTL("{1} watered the plant.\\wtnp[40]",$Trainer.name))
if NEW_BERRY_PLANTS
pbMessage(_INTL("There! All happy!"))
else
pbMessage(_INTL("The plant seemed to be delighted."))
end
end
break
end
end
end
end
def pbPickBerry(berry,qty=1)
interp=pbMapInterpreter
thisEvent=interp.get_character(0)
berryData=interp.getVariable
berry=getID(PBItems,berry)
itemname=(qty>1) ? PBItems.getNamePlural(berry) : PBItems.getName(berry)
if qty>1
message=_INTL("There are {1} \\c[1]{2}\\c[0]!\nWant to pick them?",qty,itemname)
else
message=_INTL("There is 1 \\c[1]{1}\\c[0]!\nWant to pick it?",itemname)
end
if pbConfirmMessage(message)
if !$PokemonBag.pbCanStore?(berry,qty)
pbMessage(_INTL("Too bad...\nThe Bag is full..."))
return
end
$PokemonBag.pbStoreItem(berry,qty)
if qty>1
pbMessage(_INTL("You picked the {1} \\c[1]{2}\\c[0].\\wtnp[30]",qty,itemname))
else
pbMessage(_INTL("You picked the \\c[1]{1}\\c[0].\\wtnp[30]",itemname))
end
pocket = pbGetPocket(berry)
pbMessage(_INTL("{1} put the \\c[1]{2}\\c[0] in the <icon=bagPocket{3}>\\c[1]{4}\\c[0] Pocket.\1",
$Trainer.name,itemname,pocket,PokemonBag.pocketNames()[pocket]))
if NEW_BERRY_PLANTS
pbMessage(_INTL("The soil returned to its soft and earthy state."))
berryData=[0,0,0,0,0,0,0,0]
else
pbMessage(_INTL("The soil returned to its soft and loamy state."))
berryData=[0,0,false,0,0,0]
end
interp.setVariable(berryData)
pbSetSelfSwitch(thisEvent.id,"A",true)
end
end

View File

@@ -0,0 +1,443 @@
#===============================================================================
# Query information about Pokémon in the Day Care.
#===============================================================================
# Returns the number of Pokémon in the Day Care.
def pbDayCareDeposited
ret = 0
for i in 0...2
ret += 1 if $PokemonGlobal.daycare[i][0]
end
return ret
end
# Get name/cost info of a particular Pokémon in the Day Care.
def pbDayCareGetDeposited(index,nameVariable,costVariable)
pkmn = $PokemonGlobal.daycare[index][0]
return false if !pkmn
cost = pbDayCareGetCost(index)
$game_variables[nameVariable] = pkmn.name if nameVariable>=0
$game_variables[costVariable] = cost if costVariable>=0
end
# Get name/levels gained info of a particular Pokémon in the Day Care.
def pbDayCareGetLevelGain(index,nameVariable,levelVariable)
pkmn = $PokemonGlobal.daycare[index][0]
return false if !pkmn
$game_variables[nameVariable] = pkmn.name
$game_variables[levelVariable] = pkmn.level-$PokemonGlobal.daycare[index][1]
return true
end
def pbDayCareGetCost(index)
pkmn = $PokemonGlobal.daycare[index][0]
return 0 if !pkmn
cost = pkmn.level-$PokemonGlobal.daycare[index][1]+1
cost *= 100
return cost
end
# Returns whether an egg is waiting to be collected.
def pbEggGenerated?
return false if pbDayCareDeposited!=2
return $PokemonGlobal.daycareEgg==1
end
#===============================================================================
# Manipulate Pokémon in the Day Care.
#===============================================================================
def pbDayCareDeposit(index)
for i in 0...2
next if $PokemonGlobal.daycare[i][0]
$PokemonGlobal.daycare[i][0] = $Trainer.party[index]
$PokemonGlobal.daycare[i][1] = $Trainer.party[index].level
$PokemonGlobal.daycare[i][0].heal
$Trainer.party[index] = nil
$Trainer.party.compact!
$PokemonGlobal.daycareEgg = 0
$PokemonGlobal.daycareEggSteps = 0
return
end
raise _INTL("No room to deposit a Pokémon")
end
def pbDayCareWithdraw(index)
if !$PokemonGlobal.daycare[index][0]
raise _INTL("There's no Pokémon here...")
elsif $Trainer.party.length>=6
raise _INTL("Can't store the Pokémon...")
else
$Trainer.party[$Trainer.party.length] = $PokemonGlobal.daycare[index][0]
$PokemonGlobal.daycare[index][0] = nil
$PokemonGlobal.daycare[index][1] = 0
$PokemonGlobal.daycareEgg = 0
end
end
def pbDayCareChoose(text,variable)
count = pbDayCareDeposited
if count==0
raise _INTL("There's no Pokémon here...")
elsif count==1
$game_variables[variable] = ($PokemonGlobal.daycare[0][0]) ? 0 : 1
else
choices = []
for i in 0...2
pokemon = $PokemonGlobal.daycare[i][0]
if pokemon.male?
choices.push(_ISPRINTF("{1:s} (♂, Lv.{2:d})",pokemon.name,pokemon.level))
elsif pokemon.female?
choices.push(_ISPRINTF("{1:s} (♀, Lv.{2:d})",pokemon.name,pokemon.level))
else
choices.push(_ISPRINTF("{1:s} (Lv.{2:d})",pokemon.name,pokemon.level))
end
end
choices.push(_INTL("CANCEL"))
command = pbMessage(text,choices,choices.length)
$game_variables[variable] = (command==2) ? -1 : command
end
end
#===============================================================================
# Check compatibility of Pokémon in the Day Care.
#===============================================================================
def pbIsDitto?(pkmn)
compat = pbGetSpeciesData(pkmn.species,pkmn.form,SpeciesCompatibility)
if compat.is_a?(Array)
return compat.include?(getConst(PBEggGroups,:Ditto))
end
return compat && isConst?(compat,PBEggGroups,:Ditto)
end
def pbDayCareCompatibleGender(pkmn1,pkmn2)
return true if pkmn1.female? && pkmn2.male?
return true if pkmn1.male? && pkmn2.female?
ditto1 = pbIsDitto?(pkmn1)
ditto2 = pbIsDitto?(pkmn2)
return true if ditto1 && !ditto2
return true if ditto2 && !ditto1
return false
end
def pbDayCareGetCompat
return 0 if pbDayCareDeposited!=2
pkmn1 = $PokemonGlobal.daycare[0][0]
pkmn2 = $PokemonGlobal.daycare[1][0]
return 0 if pkmn1.shadowPokemon?
return 0 if pkmn2.shadowPokemon?
# Insert code here if certain forms of certain species cannot breed
compat1 = pbGetSpeciesData(pkmn1.species,pkmn1.form,SpeciesCompatibility)
if compat1.is_a?(Array)
compat10 = compat1[0] || 0
compat11 = compat1[1] || compat10
else
compat10 = compat11 = compat || 0
end
compat2 = pbGetSpeciesData(pkmn2.species,pkmn2.form,SpeciesCompatibility)
if compat2.is_a?(Array)
compat20 = compat2[0] || 0
compat21 = compat2[1] || compat20
else
compat20 = compat21 = compat || 0
end
return 0 if isConst?(compat10,PBEggGroups,:Undiscovered) ||
isConst?(compat11,PBEggGroups,:Undiscovered) ||
isConst?(compat20,PBEggGroups,:Undiscovered) ||
isConst?(compat21,PBEggGroups,:Undiscovered)
if compat10==compat20 || compat11==compat20 ||
compat10==compat21 || compat11==compat21 ||
isConst?(compat10,PBEggGroups,:Ditto) ||
isConst?(compat11,PBEggGroups,:Ditto) ||
isConst?(compat20,PBEggGroups,:Ditto) ||
isConst?(compat21,PBEggGroups,:Ditto)
if pbDayCareCompatibleGender(pkmn1,pkmn2)
ret = 1
ret += 1 if pkmn1.species==pkmn2.species
ret += 1 if pkmn1.trainerID!=pkmn2.trainerID
return ret
end
end
return 0
end
def pbDayCareGetCompatibility(variable)
$game_variables[variable] = pbDayCareGetCompat
end
#===============================================================================
# Generate an Egg based on Pokémon in the Day Care.
#===============================================================================
def pbDayCareGenerateEgg
return if pbDayCareDeposited!=2
raise _INTL("Can't store the egg") if $Trainer.party.length>=6
pokemon0 = $PokemonGlobal.daycare[0][0]
pokemon1 = $PokemonGlobal.daycare[1][0]
mother = nil
father = nil
babyspecies = 0
ditto0 = pbIsDitto?(pokemon0)
ditto1 = pbIsDitto?(pokemon1)
if pokemon0.female? || ditto0
babyspecies = (ditto0) ? pokemon1.species : pokemon0.species
mother = pokemon0
father = pokemon1
else
babyspecies = (ditto1) ? pokemon0.species : pokemon1.species
mother = pokemon1
father = pokemon0
end
# Determine the egg's species
babyspecies = pbGetBabySpecies(babyspecies,mother.item,father.item)
if isConst?(babyspecies,PBSpecies,:MANAPHY) && hasConst?(PBSpecies,:PHIONE)
babyspecies = getConst(PBSpecies,:PHIONE)
elsif (isConst?(babyspecies,PBSpecies,:NIDORANfE) && hasConst?(PBSpecies,:NIDORANmA)) ||
(isConst?(babyspecies,PBSpecies,:NIDORANmA) && hasConst?(PBSpecies,:NIDORANfE))
babyspecies = [getConst(PBSpecies,:NIDORANmA),
getConst(PBSpecies,:NIDORANfE)][rand(2)]
elsif (isConst?(babyspecies,PBSpecies,:VOLBEAT) && hasConst?(PBSpecies,:ILLUMISE)) ||
(isConst?(babyspecies,PBSpecies,:ILLUMISE) && hasConst?(PBSpecies,:VOLBEAT))
babyspecies = [getConst(PBSpecies,:VOLBEAT),
getConst(PBSpecies,:ILLUMISE)][rand(2)]
end
# Generate egg
egg = pbNewPkmn(babyspecies,EGG_LEVEL)
# Randomise personal ID
pid = rand(65536)
pid |= (rand(65536)<<16)
egg.personalID = pid
# Inheriting form
if isConst?(babyspecies,PBSpecies,:BURMY) ||
isConst?(babyspecies,PBSpecies,:SHELLOS) ||
isConst?(babyspecies,PBSpecies,:BASCULIN) ||
isConst?(babyspecies,PBSpecies,:FLABEBE) ||
isConst?(babyspecies,PBSpecies,:PUMPKABOO) ||
isConst?(babyspecies,PBSpecies,:ORICORIO) ||
isConst?(babyspecies,PBSpecies,:ROCKRUFF) ||
isConst?(babyspecies,PBSpecies,:MINIOR)
newForm = mother.form
newForm = 0 if isConst?(mother.species,PBSpecies,:MOTHIM)
egg.form = newForm
end
# Inheriting Alolan form
if isConst?(babyspecies,PBSpecies,:RATTATA) ||
isConst?(babyspecies,PBSpecies,:SANDSHREW) ||
isConst?(babyspecies,PBSpecies,:VULPIX) ||
isConst?(babyspecies,PBSpecies,:DIGLETT) ||
isConst?(babyspecies,PBSpecies,:MEOWTH) ||
isConst?(babyspecies,PBSpecies,:GEODUDE) ||
isConst?(babyspecies,PBSpecies,:GRIMER)
if mother.form==1
egg.form = 1 if mother.hasItem?(:EVERSTONE)
elsif pbGetBabySpecies(father.species,mother.item,father.item)==babyspecies
egg.form = 1 if father.form==1 && father.hasItem?(:EVERSTONE)
end
end
# Inheriting Moves
moves = []
othermoves = []
movefather = father; movemother = mother
if pbIsDitto?(movefather) && !mother.female?
movefather = mother; movemother = father
end
# Initial Moves
initialmoves = egg.getMoveList
for k in initialmoves
if k[0]<=EGG_LEVEL
moves.push(k[1])
else
next if !mother.hasMove?(k[1]) || !father.hasMove?(k[1])
othermoves.push(k[1])
end
end
# Inheriting Natural Moves
for move in othermoves
moves.push(move)
end
# Inheriting Machine Moves
if !NEWEST_BATTLE_MECHANICS
itemsData = pbLoadItemsData
for i in 0...itemsData.length
next if !itemsData[i]
atk = itemsData[i][ITEM_MACHINE]
next if !atk || atk==0
next if !egg.compatibleWithMove?(atk)
next if !movefather.hasMove?(atk)
moves.push(atk)
end
end
# Inheriting Egg Moves
babyEggMoves = pbGetSpeciesEggMoves(egg.species,egg.form)
if movefather.male?
babyEggMoves.each { |m| moves.push(m) if movefather.hasMove?(m) }
end
if NEWEST_BATTLE_MECHANICS
babyEggMoves.each { |m| moves.push(m) if movemother.hasMove?(m) }
end
# Volt Tackle
lightball = false
if (isConst?(father.species,PBSpecies,:PIKACHU) ||
isConst?(father.species,PBSpecies,:RAICHU)) &&
isConst?(father.item,PBItems,:LIGHTBALL)
lightball = true
end
if (isConst?(mother.species,PBSpecies,:PIKACHU) ||
isConst?(mother.species,PBSpecies,:RAICHU)) &&
isConst?(mother.item,PBItems,:LIGHTBALL)
lightball = true
end
if lightball && isConst?(babyspecies,PBSpecies,:PICHU) &&
hasConst?(PBMoves,:VOLTTACKLE)
moves.push(getConst(PBMoves,:VOLTTACKLE))
end
moves = moves.reverse
moves |= [] # remove duplicates
moves = moves.reverse
# Assembling move list
finalmoves = []
listend = moves.length-4
listend = 0 if listend<0
for i in listend...listend+4
moveid = (i>=moves.length) ? 0 : moves[i]
finalmoves[finalmoves.length] = PBMove.new(moveid)
end
# Inheriting Individual Values
ivs = []
for i in 0...6
ivs[i] = rand(32)
end
ivinherit = []
for i in 0...2
parent = [mother,father][i]
ivinherit[i] = PBStats::HP if isConst?(parent.item,PBItems,:POWERWEIGHT)
ivinherit[i] = PBStats::ATTACK if isConst?(parent.item,PBItems,:POWERBRACER)
ivinherit[i] = PBStats::DEFENSE if isConst?(parent.item,PBItems,:POWERBELT)
ivinherit[i] = PBStats::SPATK if isConst?(parent.item,PBItems,:POWERLENS)
ivinherit[i] = PBStats::SPDEF if isConst?(parent.item,PBItems,:POWERBAND)
ivinherit[i] = PBStats::SPEED if isConst?(parent.item,PBItems,:POWERANKLET)
end
num = 0; r = rand(2)
for i in 0...2
if ivinherit[r]!=nil
parent = [mother,father][r]
ivs[ivinherit[r]] = parent.iv[ivinherit[r]]
num += 1
break
end
r = (r+1)%2
end
limit = (NEWEST_BATTLE_MECHANICS && (isConst?(mother.item,PBItems,:DESTINYKNOT) ||
isConst?(father.item,PBItems,:DESTINYKNOT))) ? 5 : 3
loop do
freestats = []
PBStats.eachStat { |s| freestats.push(s) if !ivinherit.include?(s) }
break if freestats.length==0
r = freestats[rand(freestats.length)]
parent = [mother,father][rand(2)]
ivs[r] = parent.iv[r]
ivinherit.push(r)
num += 1
break if num>=limit
end
# Inheriting nature
newnatures = []
newnatures.push(mother.nature) if isConst?(mother.item,PBItems,:EVERSTONE)
newnatures.push(father.nature) if isConst?(father.item,PBItems,:EVERSTONE)
if newnatures.length>0
egg.setNature(newnatures[rand(newnatures.length)])
end
# Masuda method and Shiny Charm
shinyretries = 0
shinyretries += 5 if father.language!=mother.language
shinyretries += 2 if hasConst?(PBItems,:SHINYCHARM) && $PokemonBag.pbHasItem?(:SHINYCHARM)
if shinyretries>0
for i in 0...shinyretries
break if egg.shiny?
egg.personalID = rand(65536)|(rand(65536)<<16)
end
end
# Inheriting ability from the mother
if !ditto0 && !ditto1
if mother.hasHiddenAbility?
egg.setAbility(mother.abilityIndex) if rand(10)<6
else
if rand(10)<8
egg.setAbility(mother.abilityIndex)
else
egg.setAbility((mother.abilityIndex+1)%2)
end
end
elsif !(ditto0 && ditto1) && NEWEST_BATTLE_MECHANICS
parent = (!ditto0) ? mother : father
if parent.hasHiddenAbility?
egg.setAbility(parent.abilityIndex) if rand(10)<6
end
end
# Inheriting Poké Ball from the mother
if mother.female? &&
!isConst?(pbBallTypeToItem(mother.ballused),PBItems,:MASTERBALL) &&
!isConst?(pbBallTypeToItem(mother.ballused),PBItems,:CHERISHBALL)
egg.ballused = mother.ballused
end
# Set all stats
egg.happiness = 120
egg.iv[0] = ivs[0]
egg.iv[1] = ivs[1]
egg.iv[2] = ivs[2]
egg.iv[3] = ivs[3]
egg.iv[4] = ivs[4]
egg.iv[5] = ivs[5]
egg.moves[0] = finalmoves[0]
egg.moves[1] = finalmoves[1]
egg.moves[2] = finalmoves[2]
egg.moves[3] = finalmoves[3]
egg.calcStats
egg.obtainText = _INTL("Day-Care Couple")
egg.name = _INTL("Egg")
eggSteps = pbGetSpeciesData(babyspecies,egg.form,SpeciesStepsToHatch)
egg.eggsteps = eggSteps
egg.givePokerus if rand(65536)<POKERUS_CHANCE
# Add egg to party
$Trainer.party[$Trainer.party.length] = egg
end
#===============================================================================
# Code that happens every step the player takes.
#===============================================================================
Events.onStepTaken += proc { |sender,e|
# Make an egg available at the Day Care
deposited = pbDayCareDeposited
if deposited==2 && $PokemonGlobal.daycareEgg==0
$PokemonGlobal.daycareEggSteps = 0 if !$PokemonGlobal.daycareEggSteps
$PokemonGlobal.daycareEggSteps += 1
if $PokemonGlobal.daycareEggSteps==256
$PokemonGlobal.daycareEggSteps = 0
compatval = [0,20,50,70][pbDayCareGetCompat]
if hasConst?(PBItems,:OVALCHARM) && $PokemonBag.pbHasItem?(:OVALCHARM)
compatval = [0,40,80,88][pbDayCareGetCompat]
end
$PokemonGlobal.daycareEgg = 1 if rand(100)<compatval # Egg is generated
end
end
# Day Care Pokémon gain Exp/moves
for i in 0...2
pkmn = $PokemonGlobal.daycare[i][0]
next if !pkmn
maxexp = PBExperience.pbGetMaxExperience(pkmn.growthrate)
next if pkmn.exp>=maxexp
oldlevel = pkmn.level
pkmn.exp += 1 # Gain Exp
next if pkmn.level==oldlevel
pkmn.calcStats
movelist = pkmn.getMoveList
for i in movelist
pkmn.pbLearnMove(i[1]) if i[0]==pkmn.level # Learned a new move
end
end
}

View File

@@ -0,0 +1,568 @@
class PokemonTemp
attr_accessor :dependentEvents
def dependentEvents
@dependentEvents=DependentEvents.new if !@dependentEvents
return @dependentEvents
end
end
def pbRemoveDependencies()
$PokemonTemp.dependentEvents.removeAllEvents()
pbDeregisterPartner() rescue nil
end
def pbAddDependency(event)
$PokemonTemp.dependentEvents.addEvent(event)
end
def pbRemoveDependency(event)
$PokemonTemp.dependentEvents.removeEvent(event)
end
def pbAddDependency2(eventID, eventName, commonEvent)
$PokemonTemp.dependentEvents.addEvent($game_map.events[eventID],eventName,commonEvent)
end
# Gets the Game_Character object associated with a dependent event.
def pbGetDependency(eventName)
return $PokemonTemp.dependentEvents.getEventByName(eventName)
end
def pbRemoveDependency2(eventName)
$PokemonTemp.dependentEvents.removeEventByName(eventName)
end
class PokemonGlobalMetadata
attr_accessor :dependentEvents
def dependentEvents
@dependentEvents=[] if !@dependentEvents
return @dependentEvents
end
end
class Game_Event
def set_starting
@starting=true
end
end
def pbTestPass(follower,x,y,direction=nil)
return $MapFactory.isPassableStrict?(follower.map.map_id,x,y,follower)
end
# Same map only
def moveThrough(follower,direction)
oldThrough=follower.through
follower.through=true
case direction
when 2; follower.move_down # down
when 4; follower.move_left # left
when 6; follower.move_right # right
when 8; follower.move_up # up
end
follower.through=oldThrough
end
# Same map only
def moveFancy(follower,direction)
deltaX=(direction == 6 ? 1 : (direction == 4 ? -1 : 0))
deltaY=(direction == 2 ? 1 : (direction == 8 ? -1 : 0))
newX = follower.x + deltaX
newY = follower.y + deltaY
# Move if new position is the player's, or the new position is passable,
# or the current position is not passable
if ($game_player.x==newX && $game_player.y==newY) ||
pbTestPass(follower,newX,newY,0) ||
!pbTestPass(follower,follower.x,follower.y,0)
oldThrough=follower.through
follower.through=true
case direction
when 2; follower.move_down # down
when 4; follower.move_left # left
when 6; follower.move_right # right
when 8; follower.move_up # up
end
follower.through=oldThrough
end
end
# Same map only
def jumpFancy(follower,direction)
deltaX=(direction == 6 ? 2 : (direction == 4 ? -2 : 0))
deltaY=(direction == 2 ? 2 : (direction == 8 ? -2 : 0))
halfDeltaX=(direction == 6 ? 1 : (direction == 4 ? -1 : 0))
halfDeltaY=(direction == 2 ? 1 : (direction == 8 ? -1 : 0))
middle=pbTestPass(follower,follower.x+halfDeltaX,follower.y+halfDeltaY,0)
ending=pbTestPass(follower,follower.x+deltaX, follower.y+deltaY, 0)
if middle
moveFancy(follower,direction)
moveFancy(follower,direction)
elsif ending
if pbTestPass(follower,follower.x,follower.y,0)
follower.jump(deltaX,deltaY)
else
moveThrough(follower,direction)
moveThrough(follower,direction)
end
end
end
def pbFancyMoveTo(follower,newX,newY)
if follower.x-newX==-1 && follower.y==newY
moveFancy(follower,6)
elsif follower.x-newX==1 && follower.y==newY
moveFancy(follower,4)
elsif follower.y-newY==-1 && follower.x==newX
moveFancy(follower,2)
elsif follower.y-newY==1 && follower.x==newX
moveFancy(follower,8)
elsif follower.x-newX==-2 && follower.y==newY
jumpFancy(follower,6)
elsif follower.x-newX==2 && follower.y==newY
jumpFancy(follower,4)
elsif follower.y-newY==-2 && follower.x==newX
jumpFancy(follower,2)
elsif follower.y-newY==2 && follower.x==newX
jumpFancy(follower,8)
elsif follower.x!=newX || follower.y!=newY
follower.moveto(newX,newY)
end
end
class DependentEvents
attr_reader :lastUpdate
def createEvent(eventData)
rpgEvent = RPG::Event.new(eventData[3],eventData[4])
rpgEvent.id = eventData[1]
if eventData[9]
# Must setup common event list here and now
commonEvent = Game_CommonEvent.new(eventData[9])
rpgEvent.pages[0].list = commonEvent.list
end
newEvent = Game_Event.new(eventData[0],rpgEvent,$MapFactory.getMap(eventData[2]))
newEvent.character_name = eventData[6]
newEvent.character_hue = eventData[7]
case eventData[5] # direction
when 2; newEvent.turn_down
when 4; newEvent.turn_left
when 6; newEvent.turn_right
when 8; newEvent.turn_up
end
return newEvent
end
def initialize
# Original map, Event ID, Current map, X, Y, Direction
events=$PokemonGlobal.dependentEvents
@realEvents=[]
@lastUpdate=-1
for event in events
@realEvents.push(createEvent(event))
end
end
def pbEnsureEvent(event, newMapID)
events=$PokemonGlobal.dependentEvents
found=-1
for i in 0...events.length
# Check original map ID and original event ID
if events[i][0]==event.map_id && events[i][1]==event.id
# Change current map ID
events[i][2]=newMapID
newEvent=createEvent(events[i])
# Replace event
@realEvents[i]=newEvent
@lastUpdate+=1
return i
end
end
return -1
end
def pbFollowEventAcrossMaps(leader,follower,instant=false,leaderIsTrueLeader=true)
d=leader.direction
areConnected=$MapFactory.areConnected?(leader.map.map_id,follower.map.map_id)
# Get the rear facing tile of leader
facingDirection=10-d
if !leaderIsTrueLeader && areConnected
relativePos=$MapFactory.getThisAndOtherEventRelativePos(leader,follower)
if (relativePos[1]==0 && relativePos[0]==2) # 2 spaces to the right of leader
facingDirection=6
elsif (relativePos[1]==0 && relativePos[0]==-2) # 2 spaces to the left of leader
facingDirection=4
elsif relativePos[1]==-2 && relativePos[0]==0 # 2 spaces above leader
facingDirection=8
elsif relativePos[1]==2 && relativePos[0]==0 # 2 spaces below leader
facingDirection=2
end
end
facings=[facingDirection] # Get facing from behind
facings.push([0,0,4,0,8,0,2,0,6][d]) # Get right facing
facings.push([0,0,6,0,2,0,8,0,4][d]) # Get left facing
if !leaderIsTrueLeader
facings.push(d) # Get forward facing
end
mapTile=nil
if areConnected
bestRelativePos=-1
oldthrough=follower.through
follower.through=false
for i in 0...facings.length
facing=facings[i]
tile=$MapFactory.getFacingTile(facing,leader)
passable=tile && $MapFactory.isPassableStrict?(tile[0],tile[1],tile[2],follower)
if i==0 && !passable && tile &&
PBTerrain.isLedge?($MapFactory.getTerrainTag(tile[0],tile[1],tile[2]))
# If the tile isn't passable and the tile is a ledge,
# get tile from further behind
tile=$MapFactory.getFacingTileFromPos(tile[0],tile[1],tile[2],facing)
passable=tile && $MapFactory.isPassableStrict?(tile[0],tile[1],tile[2],follower)
end
if passable
relativePos=$MapFactory.getThisAndOtherPosRelativePos(
follower,tile[0],tile[1],tile[2])
distance=Math.sqrt(relativePos[0]*relativePos[0]+relativePos[1]*relativePos[1])
if bestRelativePos==-1 || bestRelativePos>distance
bestRelativePos=distance
mapTile=tile
end
if i==0 && distance<=1 # Prefer behind if tile can move up to 1 space
break
end
end
end
follower.through=oldthrough
else
tile=$MapFactory.getFacingTile(facings[0],leader)
passable=tile && $MapFactory.isPassableStrict?(tile[0],tile[1],tile[2],follower)
mapTile=passable ? mapTile : nil
end
if mapTile && follower.map.map_id==mapTile[0]
# Follower is on same map
newX=mapTile[1]
newY=mapTile[2]
deltaX=(d == 6 ? -1 : d == 4 ? 1 : 0)
deltaY=(d == 2 ? -1 : d == 8 ? 1 : 0)
posX = newX + deltaX
posY = newY + deltaY
follower.move_speed=leader.move_speed # sync movespeed
if (follower.x-newX==-1 && follower.y==newY) ||
(follower.x-newX==1 && follower.y==newY) ||
(follower.y-newY==-1 && follower.x==newX) ||
(follower.y-newY==1 && follower.x==newX)
if instant
follower.moveto(newX,newY)
else
pbFancyMoveTo(follower,newX,newY)
end
elsif (follower.x-newX==-2 && follower.y==newY) ||
(follower.x-newX==2 && follower.y==newY) ||
(follower.y-newY==-2 && follower.x==newX) ||
(follower.y-newY==2 && follower.x==newX)
if instant
follower.moveto(newX,newY)
else
pbFancyMoveTo(follower,newX,newY)
end
elsif follower.x!=posX || follower.y!=posY
if instant
follower.moveto(newX,newY)
else
pbFancyMoveTo(follower,posX,posY)
pbFancyMoveTo(follower,newX,newY)
end
end
pbTurnTowardEvent(follower,leader)
else
if !mapTile
# Make current position into leader's position
mapTile=[leader.map.map_id,leader.x,leader.y]
end
if follower.map.map_id==mapTile[0]
# Follower is on same map as leader
follower.moveto(leader.x,leader.y)
pbTurnTowardEvent(follower,leader)
else
# Follower will move to different map
events=$PokemonGlobal.dependentEvents
eventIndex=pbEnsureEvent(follower,mapTile[0])
if eventIndex>=0
newFollower=@realEvents[eventIndex]
newEventData=events[eventIndex]
newFollower.moveto(mapTile[1],mapTile[2])
newEventData[3]=mapTile[1]
newEventData[4]=mapTile[2]
if mapTile[0]==leader.map.map_id
pbTurnTowardEvent(follower,leader)
end
end
end
end
end
def debugEcho
self.eachEvent { |e,d|
echoln d
echoln [e.map_id,e.map.map_id,e.id]
}
end
def pbMapChangeMoveDependentEvents
events=$PokemonGlobal.dependentEvents
updateDependentEvents
leader=$game_player
for i in 0...events.length
event=@realEvents[i]
pbFollowEventAcrossMaps(leader,event,true,i==0)
# Update X and Y for this event
events[i][3]=event.x
events[i][4]=event.y
events[i][5]=event.direction
# Set leader to this event
leader=event
end
end
def pbMoveDependentEvents
events=$PokemonGlobal.dependentEvents
updateDependentEvents
leader=$game_player
for i in 0...events.length
event=@realEvents[i]
pbFollowEventAcrossMaps(leader,event,false,i==0)
# Update X and Y for this event
events[i][3]=event.x
events[i][4]=event.y
events[i][5]=event.direction
# Set leader to this event
leader=event
end
end
def pbTurnDependentEvents
events=$PokemonGlobal.dependentEvents
updateDependentEvents
leader=$game_player
for i in 0...events.length
event=@realEvents[i]
pbTurnTowardEvent(event,leader)
# Update direction for this event
events[i][5]=event.direction
# Set leader to this event
leader=event
end
end
def eachEvent
events=$PokemonGlobal.dependentEvents
for i in 0...events.length
yield @realEvents[i],events[i]
end
end
def updateDependentEvents
events=$PokemonGlobal.dependentEvents
return if events.length==0
for i in 0...events.length
event=@realEvents[i]
next if !@realEvents[i]
event.transparent=$game_player.transparent
if event.jumping? || event.moving? ||
!($game_player.jumping? || $game_player.moving?)
event.update
elsif !event.starting
event.set_starting
event.update
event.clear_starting
end
events[i][3]=event.x
events[i][4]=event.y
events[i][5]=event.direction
end
# Check event triggers
if Input.trigger?(Input::C) && !$game_temp.in_menu && !$game_temp.in_battle &&
!$game_player.move_route_forcing && !$game_temp.message_window_showing &&
!pbMapInterpreterRunning?
# Get position of tile facing the player
facingTile=$MapFactory.getFacingTile()
self.eachEvent { |e,d|
next if !d[9]
if e.x==$game_player.x && e.y==$game_player.y
# On same position
if not e.jumping? && (!e.respond_to?("over_trigger") || e.over_trigger?)
if e.list.size>1
# Start event
$game_map.refresh if $game_map.need_refresh
e.lock
pbMapInterpreter.setup(e.list,e.id,e.map.map_id)
end
end
elsif facingTile && e.map.map_id==facingTile[0] &&
e.x==facingTile[1] && e.y==facingTile[2]
# On facing tile
if not e.jumping? && (!e.respond_to?("over_trigger") || !e.over_trigger?)
if e.list.size>1
# Start event
$game_map.refresh if $game_map.need_refresh
e.lock
pbMapInterpreter.setup(e.list,e.id,e.map.map_id)
end
end
end
}
end
end
def removeEvent(event)
events=$PokemonGlobal.dependentEvents
mapid=$game_map.map_id
for i in 0...events.length
if events[i][2]==mapid && # Refer to current map
events[i][0]==event.map_id && # Event's map ID is original ID
events[i][1]==event.id
events[i]=nil
@realEvents[i]=nil
@lastUpdate+=1
end
events.compact!
@realEvents.compact!
end
end
def getEventByName(name)
events=$PokemonGlobal.dependentEvents
for i in 0...events.length
if events[i] && events[i][8]==name # Arbitrary name given to dependent event
return @realEvents[i]
end
end
return nil
end
def removeAllEvents
events=$PokemonGlobal.dependentEvents
events.clear
@realEvents.clear
@lastUpdate+=1
end
def removeEventByName(name)
events=$PokemonGlobal.dependentEvents
for i in 0...events.length
if events[i] && events[i][8]==name # Arbitrary name given to dependent event
events[i]=nil
@realEvents[i]=nil
@lastUpdate+=1
end
events.compact!
@realEvents.compact!
end
end
def addEvent(event,eventName=nil,commonEvent=nil)
return if !event
events=$PokemonGlobal.dependentEvents
for i in 0...events.length
if events[i] && events[i][0]==$game_map.map_id && events[i][1]==event.id
# Already exists
return
end
end
# Original map ID, original event ID, current map ID,
# event X, event Y, event direction,
# event's filename,
# event's hue, event's name, common event ID
eventData=[
$game_map.map_id,event.id,$game_map.map_id,
event.x,event.y,event.direction,
event.character_name.clone,
event.character_hue,eventName,commonEvent
]
newEvent=createEvent(eventData)
events.push(eventData)
@realEvents.push(newEvent)
@lastUpdate+=1
event.erase
end
end
class DependentEventSprites
def initialize(viewport,map)
@disposed=false
@sprites=[]
@map=map
@viewport=viewport
refresh
@lastUpdate=nil
end
def refresh
for sprite in @sprites
sprite.dispose
end
@sprites.clear
$PokemonTemp.dependentEvents.eachEvent { |event,data|
if data[0]==@map.map_id # Check original map
@map.events[data[1]].erase
end
if data[2]==@map.map_id # Check current map
@sprites.push(Sprite_Character.new(@viewport,event))
end
}
end
def update
if $PokemonTemp.dependentEvents.lastUpdate!=@lastUpdate
refresh
@lastUpdate=$PokemonTemp.dependentEvents.lastUpdate
end
for sprite in @sprites
sprite.update
end
end
def dispose
return if @disposed
for sprite in @sprites
sprite.dispose
end
@sprites.clear
@disposed=true
end
def disposed?
@disposed
end
end
Events.onSpritesetCreate += proc { |sender,e|
spriteset = e[0] # Spriteset being created
viewport = e[1] # Viewport used for tilemap and characters
map = spriteset.map # Map associated with the spriteset (not necessarily the current map)
spriteset.addUserSprite(DependentEventSprites.new(viewport,map))
}
Events.onMapSceneChange += proc { |sender,e|
scene = e[0]
mapChanged = e[1]
if mapChanged
$PokemonTemp.dependentEvents.pbMapChangeMoveDependentEvents
end
}

View File

@@ -0,0 +1,313 @@
#===============================================================================
# Day and night system
#===============================================================================
def pbGetTimeNow
return Time.now
end
module PBDayNight
HourlyTones = [
Tone.new(-70, -90, 15, 55), # Night # Midnight
Tone.new(-70, -90, 15, 55), # Night
Tone.new(-70, -90, 15, 55), # Night
Tone.new(-70, -90, 15, 55), # Night
Tone.new(-60, -70, -5, 50), # Night
Tone.new(-40, -50, -35, 50), # Day/morning
Tone.new(-40, -50, -35, 50), # Day/morning # 6AM
Tone.new(-40, -50, -35, 50), # Day/morning
Tone.new(-40, -50, -35, 50), # Day/morning
Tone.new(-20, -25, -15, 20), # Day/morning
Tone.new( 0, 0, 0, 0), # Day
Tone.new( 0, 0, 0, 0), # Day
Tone.new( 0, 0, 0, 0), # Day # Noon
Tone.new( 0, 0, 0, 0), # Day
Tone.new( 0, 0, 0, 0), # Day/afternoon
Tone.new( 0, 0, 0, 0), # Day/afternoon
Tone.new( 0, 0, 0, 0), # Day/afternoon
Tone.new( 0, 0, 0, 0), # Day/afternoon
Tone.new( -5, -30, -20, 0), # Day/evening # 6PM
Tone.new(-15, -60, -10, 20), # Day/evening
Tone.new(-15, -60, -10, 20), # Day/evening
Tone.new(-40, -75, 5, 40), # Night
Tone.new(-70, -90, 15, 55), # Night
Tone.new(-70, -90, 15, 55) # Night
]
@cachedTone = nil
@dayNightToneLastUpdate = nil
@oneOverSixty = 1/60.0
# Returns true if it's day.
def self.isDay?(time=nil)
time = pbGetTimeNow if !time
return (time.hour>=5 && time.hour<20)
end
# Returns true if it's night.
def self.isNight?(time=nil)
time = pbGetTimeNow if !time
return (time.hour>=20 || time.hour<5)
end
# Returns true if it's morning.
def self.isMorning?(time=nil)
time = pbGetTimeNow if !time
return (time.hour>=5 && time.hour<10)
end
# Returns true if it's the afternoon.
def self.isAfternoon?(time=nil)
time = pbGetTimeNow if !time
return (time.hour>=14 && time.hour<17)
end
# Returns true if it's the evening.
def self.isEvening?(time=nil)
time = pbGetTimeNow if !time
return (time.hour>=17 && time.hour<20)
end
# Gets a number representing the amount of daylight (0=full night, 255=full day).
def self.getShade
time = pbGetDayNightMinutes
time = (24*60)-time if time>(12*60)
shade=255*time/(12*60)
end
# Gets a Tone object representing a suggested shading
# tone for the current time of day.
def self.getTone
@cachedTone = Tone.new(0,0,0) if !@cachedTone
return @cachedTone if !TIME_SHADING
if !@dayNightToneLastUpdate ||
Graphics.frame_count-@dayNightToneLastUpdate>=Graphics.frame_rate*30
getToneInternal
@dayNightToneLastUpdate = Graphics.frame_count
end
return @cachedTone
end
def self.pbGetDayNightMinutes
now = pbGetTimeNow # Get the current in-game time
return (now.hour*60)+now.min
end
private
# Internal function
def self.getToneInternal
# Calculates the tone for the current frame, used for day/night effects
realMinutes = pbGetDayNightMinutes
hour = realMinutes/60
minute = realMinutes%60
tone = PBDayNight::HourlyTones[hour]
nexthourtone = PBDayNight::HourlyTones[(hour+1)%24]
# Calculate current tint according to current and next hour's tint and
# depending on current minute
@cachedTone.red = ((nexthourtone.red-tone.red)*minute*@oneOverSixty)+tone.red
@cachedTone.green = ((nexthourtone.green-tone.green)*minute*@oneOverSixty)+tone.green
@cachedTone.blue = ((nexthourtone.blue-tone.blue)*minute*@oneOverSixty)+tone.blue
@cachedTone.gray = ((nexthourtone.gray-tone.gray)*minute*@oneOverSixty)+tone.gray
end
end
def pbDayNightTint(object)
return if !$scene.is_a?(Scene_Map)
if TIME_SHADING && pbGetMetadata($game_map.map_id,MetadataOutdoor)
tone = PBDayNight.getTone
object.tone.set(tone.red,tone.green,tone.blue,tone.gray)
else
object.tone.set(0,0,0,0)
end
end
#===============================================================================
# Moon phases and Zodiac
#===============================================================================
# Calculates the phase of the moon.
# 0 - New Moon
# 1 - Waxing Crescent
# 2 - First Quarter
# 3 - Waxing Gibbous
# 4 - Full Moon
# 5 - Waning Gibbous
# 6 - Last Quarter
# 7 - Waning Crescent
def moonphase(time=nil) # in UTC
time = pbGetTimeNow if !time
transitions = [
1.8456618033125,
5.5369854099375,
9.2283090165625,
12.9196326231875,
16.6109562298125,
20.3022798364375,
23.9936034430625,
27.6849270496875]
yy = time.year-((12-time.mon)/10.0).floor
j = (365.25*(4712+yy)).floor + (((time.mon+9)%12)*30.6+0.5).floor + time.day+59
j -= (((yy/100.0)+49).floor*0.75).floor-38 if j>2299160
j += (((time.hour*60)+time.min*60)+time.sec)/86400.0
v = (j-2451550.1)/29.530588853
v = ((v-v.floor)+(v<0 ? 1 : 0))
ag = v*29.53
for i in 0...transitions.length
return i if ag<=transitions[i]
end
return 0
end
# Calculates the zodiac sign based on the given month and day:
# 0 is Aries, 11 is Pisces. Month is 1 if January, and so on.
def zodiac(month,day)
time = [
3,21,4,19, # Aries
4,20,5,20, # Taurus
5,21,6,20, # Gemini
6,21,7,20, # Cancer
7,23,8,22, # Leo
8,23,9,22, # Virgo
9,23,10,22, # Libra
10,23,11,21, # Scorpio
11,22,12,21, # Sagittarius
12,22,1,19, # Capricorn
1,20,2,18, # Aquarius
2,19,3,20 # Pisces
]
for i in 0...12
return i if month==time[i*4] && day>=time[i*4+1]
return i if month==time[i*4+2] && day<=time[i*4+3]
end
return 0
end
# Returns the opposite of the given zodiac sign.
# 0 is Aries, 11 is Pisces.
def zodiacOpposite(sign)
return (sign+6)%12
end
# 0 is Aries, 11 is Pisces.
def zodiacPartners(sign)
return [(sign+4)%12,(sign+8)%12]
end
# 0 is Aries, 11 is Pisces.
def zodiacComplements(sign)
return [(sign+1)%12,(sign+11)%12]
end
#===============================================================================
# Days of the week
#===============================================================================
def pbIsWeekday(wdayVariable,*arg)
timenow = pbGetTimeNow
wday = timenow.wday
ret = false
for wd in arg
ret = true if wd==wday
end
if wdayVariable>0
$game_variables[wdayVariable] = [
_INTL("Sunday"),
_INTL("Monday"),
_INTL("Tuesday"),
_INTL("Wednesday"),
_INTL("Thursday"),
_INTL("Friday"),
_INTL("Saturday")][wday]
$game_map.need_refresh = true if $game_map
end
return ret
end
#===============================================================================
# Months
#===============================================================================
def pbIsMonth(monVariable,*arg)
timenow = pbGetTimeNow
thismon = timenow.mon
ret = false
for wd in arg
ret = true if wd==thismon
end
if monVariable>0
$game_variables[monVariable] = pbGetMonthName(thismon)
$game_map.need_refresh = true if $game_map
end
return ret
end
def pbGetMonthName(month)
return [_INTL("January"),
_INTL("February"),
_INTL("March"),
_INTL("April"),
_INTL("May"),
_INTL("June"),
_INTL("July"),
_INTL("August"),
_INTL("September"),
_INTL("October"),
_INTL("November"),
_INTL("December")][month-1]
end
def pbGetAbbrevMonthName(month)
return ["",
_INTL("Jan."),
_INTL("Feb."),
_INTL("Mar."),
_INTL("Apr."),
_INTL("May"),
_INTL("Jun."),
_INTL("Jul."),
_INTL("Aug."),
_INTL("Sep."),
_INTL("Oct."),
_INTL("Nov."),
_INTL("Dec.")][month]
end
#===============================================================================
# Seasons
#===============================================================================
def pbGetSeason
return (pbGetTimeNow.mon-1)%4
end
def pbIsSeason(seasonVariable,*arg)
thisseason = pbGetSeason
ret = false
for wd in arg
ret = true if wd==thisseason
end
if seasonVariable>0
$game_variables[seasonVariable] = [
_INTL("Spring"),
_INTL("Summer"),
_INTL("Autumn"),
_INTL("Winter")][thisseason]
$game_map.need_refresh = true if $game_map
end
return ret
end
def pbIsSpring; return pbIsSeason(0,0); end # Jan, May, Sep
def pbIsSummer; return pbIsSeason(0,1); end # Feb, Jun, Oct
def pbIsAutumn; return pbIsSeason(0,2); end # Mar, Jul, Nov
def pbIsFall; return pbIsAutumn; end
def pbIsWinter; return pbIsSeason(0,3); end # Apr, Aug, Dec
def pbGetSeasonName(season)
return [_INTL("Spring"),
_INTL("Summer"),
_INTL("Autumn"),
_INTL("Winter")][season]
end