Merge branch 'master' into mkxp-z

This commit is contained in:
Maruno17
2020-11-09 19:26:44 +00:00
79 changed files with 3367 additions and 3235 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
#==============================================================================# #==============================================================================#
# Pokémon Essentials # # Pokémon Essentials #
# Version 18 # # Version 18.1 #
#==============================================================================# #==============================================================================#
#=============================================================================== #===============================================================================
+1 -1
View File
@@ -100,5 +100,5 @@ end
# Well done for finding this place. # Well done for finding this place.
# DO NOT EDIT THESE # DO NOT EDIT THESE
ESSENTIALS_VERSION = "18" ESSENTIALS_VERSION = "18.1.dev"
ERROR_TEXT = "" ERROR_TEXT = ""
@@ -48,6 +48,7 @@ module Console
@apiSetConsoleTitle = Win32API.new("kernel32","SetConsoleTitle","p","s") @apiSetConsoleTitle = Win32API.new("kernel32","SetConsoleTitle","p","s")
access = (GENERIC_READ | GENERIC_WRITE) access = (GENERIC_READ | GENERIC_WRITE)
sharemode = (FILE_SHARE_READ | FILE_SHARE_WRITE) sharemode = (FILE_SHARE_READ | FILE_SHARE_WRITE)
AllocConsole()
@bufferHandle = CreateConsoleScreenBuffer(access,sharemode,CONSOLE_TEXTMODE_BUFFER) @bufferHandle = CreateConsoleScreenBuffer(access,sharemode,CONSOLE_TEXTMODE_BUFFER)
f = File.open("Game.ini") f = File.open("Game.ini")
lines = f.readlines() lines = f.readlines()
@@ -33,7 +33,7 @@ class Game_Character
@y = 0 @y = 0
@real_x = 0 @real_x = 0
@real_y = 0 @real_y = 0
@sprite_size = [Game_Map::TILE_WIDTH,Game_Map::TILE_HEIGHT] @sprite_size = [Game_Map::TILE_WIDTH, Game_Map::TILE_HEIGHT]
@tile_id = 0 @tile_id = 0
@character_name = "" @character_name = ""
@character_hue = 0 @character_hue = 0
@@ -50,7 +50,7 @@ class Game_Character
@original_direction = 2 @original_direction = 2
@original_pattern = 0 @original_pattern = 0
@move_type = 0 @move_type = 0
self.move_speed = 4 self.move_speed = 3
self.move_frequency = 6 self.move_frequency = 6
@move_route = nil @move_route = nil
@move_route_index = 0 @move_route_index = 0
@@ -62,8 +62,10 @@ class Game_Character
@always_on_top = false @always_on_top = false
@anime_count = 0 @anime_count = 0
@stop_count = 0 @stop_count = 0
@jump_count = 0 @jump_peak = 0 # Max height while jumping
@jump_peak = 0 @jump_distance = 0 # Total distance of jump
@jump_distance_left = 0 # Distance left to travel
@jump_count = 0 # Frames left in a stationary jump
@bob_height = 0 @bob_height = 0
@wait_count = 0 @wait_count = 0
@moved_this_frame = false @moved_this_frame = false
@@ -77,13 +79,13 @@ class Game_Character
# @move_speed_real is the number of quarter-pixels to move each frame. There # @move_speed_real is the number of quarter-pixels to move each frame. There
# are 128 quarter-pixels per tile. By default, it is calculated from # are 128 quarter-pixels per tile. By default, it is calculated from
# @move_speed and has these values (assuming 40 fps): # @move_speed and has these values (assuming 40 fps):
# 1 => 1.6 # 80 frames per tile # 1 => 3.2 # 40 frames per tile
# 2 => 3.2 # 40 frames per tile # 2 => 6.4 # 20 frames per tile
# 3 => 6.4 # 20 frames per tile # 3 => 12.8 # 10 frames per tile - walking speed
# 4 => 12.8 # 10 frames per tile - walking speed # 4 => 25.6 # 5 frames per tile - running speed (2x walking speed)
# 5 => 25.6 # 5 frames per tile - running speed (2x walking speed) # 5 => 32 # 4 frames per tile - cycling speed (1.25x running speed)
# 6 => 32 # 4 frames per tile - cycling speed (1.25x running speed) # 6 => 64 # 2 frames per tile
self.move_speed_real = (val == 6) ? 32 : (1 << val) * 0.8 self.move_speed_real = (val == 6) ? 64 : (val == 5) ? 32 : (2 ** (val + 1)) * 0.8
end end
def move_speed_real def move_speed_real
@@ -95,6 +97,10 @@ class Game_Character
@move_speed_real = val * 40.0 / Graphics.frame_rate @move_speed_real = val * 40.0 / Graphics.frame_rate
end end
def jump_speed_real
return (2 ** (3 + 1)) * 0.8 * 40.0 / Graphics.frame_rate # Walking speed
end
def move_frequency=(val) def move_frequency=(val)
return if val==@move_frequency return if val==@move_frequency
@move_frequency = val @move_frequency = val
@@ -160,7 +166,7 @@ class Game_Character
end end
def bush_depth def bush_depth
return 0 if @tile_id > 0 or @always_on_top or @jump_count > 0 return 0 if @tile_id > 0 || @always_on_top or jumping?
xbehind = @x + (@direction==4 ? 1 : @direction==6 ? -1 : 0) xbehind = @x + (@direction==4 ? 1 : @direction==6 ? -1 : 0)
ybehind = @y + (@direction==8 ? 1 : @direction==2 ? -1 : 0) ybehind = @y + (@direction==8 ? 1 : @direction==2 ? -1 : 0)
return Game_Map::TILE_HEIGHT if self.map.deepBush?(@x, @y) and self.map.deepBush?(xbehind, ybehind) return Game_Map::TILE_HEIGHT if self.map.deepBush?(@x, @y) and self.map.deepBush?(xbehind, ybehind)
@@ -219,8 +225,12 @@ class Game_Character
def screen_y def screen_y
ret = screen_y_ground ret = screen_y_ground
if jumping? if jumping?
n = ((2 * @jump_count * 20 / Graphics.frame_rate) - @jump_peak).abs if @jump_count > 0
return ret - (@jump_peak * @jump_peak - n * n) / 2 jump_fraction = ((@jump_count * jump_speed_real / Game_Map::REAL_RES_X) - 0.5).abs # 0.5 to 0 to 0.5
else
jump_fraction = ((@jump_distance_left / @jump_distance) - 0.5).abs # 0.5 to 0 to 0.5
end
ret += @jump_peak * (4 * jump_fraction**2 - 1)
end end
return ret return ret
end end
@@ -248,7 +258,7 @@ class Game_Character
end end
def jumping? def jumping?
return @jump_count > 0 return (@jump_distance_left || 0) > 0 || @jump_count > 0
end end
def straighten def straighten
@@ -422,48 +432,34 @@ class Game_Character
end end
end end
def move_up(turn_enabled = true) def move_generic(dir, turn_enabled = true)
turn_up if turn_enabled turn_generic(dir) if turn_enabled
if passable?(@x, @y, 8) x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0
turn_up y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0
@y -= 1 if passable?(@x, @y, dir)
turn_generic(dir)
@x += x_offset
@y += y_offset
increase_steps increase_steps
else else
check_event_trigger_touch(@x, @y-1) check_event_trigger_touch(@x + x_offset, @y + y_offset)
end end
end end
def move_down(turn_enabled = true) def move_down(turn_enabled = true)
turn_down if turn_enabled move_generic(2, turn_enabled)
if passable?(@x, @y, 2)
turn_down
@y += 1
increase_steps
else
check_event_trigger_touch(@x, @y+1)
end
end end
def move_left(turn_enabled = true) def move_left(turn_enabled = true)
turn_left if turn_enabled move_generic(4, turn_enabled)
if passable?(@x, @y, 4)
turn_left
@x -= 1
increase_steps
else
check_event_trigger_touch(@x-1, @y)
end
end end
def move_right(turn_enabled = true) def move_right(turn_enabled = true)
turn_right if turn_enabled move_generic(6, turn_enabled)
if passable?(@x, @y, 6) end
turn_right
@x += 1 def move_up(turn_enabled = true)
increase_steps move_generic(8, turn_enabled)
else
check_event_trigger_touch(@x+1, @y)
end
end end
def move_upper_left def move_upper_left
@@ -648,12 +644,18 @@ class Game_Character
new_x = @x + x_plus new_x = @x + x_plus
new_y = @y + y_plus new_y = @y + y_plus
if (x_plus == 0 and y_plus == 0) || passable?(new_x, new_y, 0) if (x_plus == 0 and y_plus == 0) || passable?(new_x, new_y, 0)
straighten
@x = new_x @x = new_x
@y = new_y @y = new_y
distance = [4, x_plus * x_plus + y_plus * y_plus].max real_distance = Math::sqrt(x_plus * x_plus + y_plus * y_plus)
@jump_peak = (6 + distance - move_speed).floor distance = [1, real_distance].max
@jump_count = @jump_peak * Graphics.frame_rate / 20 @jump_peak = distance * Game_Map::TILE_HEIGHT * 3 / 8 # 3/4 of tile for ledge jumping
@jump_distance = [x_plus.abs * Game_Map::REAL_RES_X, y_plus.abs * Game_Map::REAL_RES_Y].max
@jump_distance_left = 1 # Just needs to be non-zero
if real_distance > 0 # Jumping to somewhere else
@jump_count = 0
else # Jumping on the spot
@jump_count = Game_Map::REAL_RES_X / jump_speed_real # Number of frames to jump one tile
end
@stop_count = 0 @stop_count = 0
if self.is_a?(Game_Player) if self.is_a?(Game_Player)
$PokemonTemp.dependentEvents.pbMoveDependentEvents $PokemonTemp.dependentEvents.pbMoveDependentEvents
@@ -680,7 +682,7 @@ class Game_Character
end end
end end
def turnGeneric(dir) def turn_generic(dir)
return if @direction_fix return if @direction_fix
oldDirection = @direction oldDirection = @direction
@direction = dir @direction = dir
@@ -688,10 +690,10 @@ class Game_Character
pbCheckEventTriggerAfterTurning if dir != oldDirection pbCheckEventTriggerAfterTurning if dir != oldDirection
end end
def turn_up; turnGeneric(8); end def turn_down; turn_generic(2); end
def turn_down; turnGeneric(2); end def turn_left; turn_generic(4); end
def turn_left; turnGeneric(4); end def turn_right; turn_generic(6); end
def turn_right; turnGeneric(6); end def turn_up; turn_generic(8); end
def turn_right_90 def turn_right_90
case @direction case @direction
@@ -764,10 +766,7 @@ class Game_Character
# Update command # Update command
update_command update_command
# Update movement # Update movement
if jumping?; update_jump (moving? || jumping?) ? update_move : update_stop
elsif moving?; update_move
else; update_stop
end
end end
# Update animation # Update animation
update_pattern update_pattern
@@ -801,18 +800,9 @@ class Game_Character
end end
end end
def update_jump
@jump_count -= 1
@real_x = (@real_x * @jump_count + @x * Game_Map::REAL_RES_X) / (@jump_count + 1)
@real_y = (@real_y * @jump_count + @y * Game_Map::REAL_RES_Y) / (@jump_count + 1)
@moved_this_frame = true
# End of a jump, so perform events that happen at this time
Events.onStepTakenFieldMovement.trigger(self,self) if !jumping? && !moving?
end
def update_move def update_move
# Move the character (the 0.1 catches rounding errors) # Move the character (the 0.1 catches rounding errors)
distance = move_speed_real distance = (jumping?) ? jump_speed_real : move_speed_real
dest_x = @x * Game_Map::REAL_RES_X dest_x = @x * Game_Map::REAL_RES_X
dest_y = @y * Game_Map::REAL_RES_Y dest_y = @y * Game_Map::REAL_RES_Y
if @real_x < dest_x if @real_x < dest_x
@@ -829,8 +819,13 @@ class Game_Character
@real_y -= distance @real_y -= distance
@real_y = dest_y if @real_y < dest_y + 0.1 @real_y = dest_y if @real_y < dest_y + 0.1
end end
# Refresh how far is left to travel in a jump
if jumping?
@jump_count -= 1 if @jump_count > 0 # For stationary jumps only
@jump_distance_left = [(dest_x - @real_x).abs, (dest_y - @real_y).abs].max
end
# End of a step, so perform events that happen at this time # End of a step, so perform events that happen at this time
Events.onStepTakenFieldMovement.trigger(self,self) if !jumping? && !moving? Events.onStepTakenFieldMovement.trigger(self, self) if !jumping? && !moving?
# Increment animation counter # Increment animation counter
@anime_count += 1 if @walk_anime || @step_anime @anime_count += 1 if @walk_anime || @step_anime
@moved_this_frame = true @moved_this_frame = true
@@ -844,6 +839,7 @@ class Game_Character
def update_pattern def update_pattern
return if @lock_pattern return if @lock_pattern
# return if @jump_count > 0 # Don't animate if jumping on the spot
# Character has stopped moving, return to original pattern # Character has stopped moving, return to original pattern
if @moved_last_frame && !@moved_this_frame && !@step_anime if @moved_last_frame && !@moved_this_frame && !@step_anime
@pattern = @original_pattern @pattern = @original_pattern
@@ -851,7 +847,7 @@ class Game_Character
return return
end end
# Character has started to move, change pattern immediately # Character has started to move, change pattern immediately
if !@moved_last_frame && @moved_this_frame && !jumping? && !@step_anime if !@moved_last_frame && @moved_this_frame && !@step_anime
@pattern = (@pattern + 1) % 4 if @walk_anime @pattern = (@pattern + 1) % 4 if @walk_anime
@anime_count = 0 @anime_count = 0
return return
@@ -859,7 +855,8 @@ class Game_Character
# Calculate how many frames each pattern should display for, i.e. the time # Calculate how many frames each pattern should display for, i.e. the time
# it takes to move half a tile (or a whole tile if cycling). We assume the # it takes to move half a tile (or a whole tile if cycling). We assume the
# game uses square tiles. # game uses square tiles.
frames_per_pattern = Game_Map::REAL_RES_X / (move_speed_real * 2.0) real_speed = (jumping?) ? jump_speed_real : move_speed_real
frames_per_pattern = Game_Map::REAL_RES_X / (real_speed * 2.0)
frames_per_pattern *= 2 if move_speed == 6 # Cycling/fastest speed frames_per_pattern *= 2 if move_speed == 6 # Cycling/fastest speed
return if @anime_count < frames_per_pattern return if @anime_count < frames_per_pattern
# Advance to the next animation frame # Advance to the next animation frame
@@ -23,7 +23,7 @@ class Game_Player < Game_Character
end end
def bush_depth def bush_depth
return 0 if @tile_id > 0 or @always_on_top return 0 if @tile_id > 0 || @always_on_top
xbehind = (@direction==4) ? @x+1 : (@direction==6) ? @x-1 : @x xbehind = (@direction==4) ? @x+1 : (@direction==6) ? @x-1 : @x
ybehind = (@direction==8) ? @y+1 : (@direction==2) ? @y-1 : @y ybehind = (@direction==8) ? @y+1 : (@direction==2) ? @y-1 : @y
# Both current tile and previous tile are on the same map; just return super # Both current tile and previous tile are on the same map; just return super
@@ -47,7 +47,7 @@ class Game_Player < Game_Character
behindmap = newbehind[0]; behindx = newbehind[1]; behindy = newbehind[2] behindmap = newbehind[0]; behindx = newbehind[1]; behindy = newbehind[2]
end end
# Return bush depth # Return bush depth
if @jump_count <= 0 if !jumping?
return 32 if heremap.deepBush?(herex, herey) && behindmap.deepBush?(behindx, behindy) return 32 if heremap.deepBush?(herex, herey) && behindmap.deepBush?(behindx, behindy)
return 12 if heremap.bush?(herex, herey) && !moving? return 12 if heremap.bush?(herex, herey) && !moving?
end end
@@ -64,67 +64,36 @@ class Game_Player < Game_Character
@bump_se = Graphics.frame_rate/4 @bump_se = Graphics.frame_rate/4
end end
def move_down(turn_enabled = true) def move_generic(dir, turn_enabled = true)
turn_down if turn_enabled turn_generic(dir, true) if turn_enabled
if passable?(@x, @y, 2) if !$PokemonTemp.encounterTriggered
return if pbLedge(0,1) x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0
return if pbEndSurf(0,1) y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0
turn_down if passable?(@x, @y, dir)
@y += 1 return if pbLedge(x_offset, y_offset)
$PokemonTemp.dependentEvents.pbMoveDependentEvents return if pbEndSurf(x_offset, y_offset)
increase_steps turn_generic(dir, true)
else if !$PokemonTemp.encounterTriggered
if !check_event_trigger_touch(@x, @y+1) @x += x_offset
bump_into_object @y += y_offset
$PokemonTemp.dependentEvents.pbMoveDependentEvents
increase_steps
end
else
if !check_event_trigger_touch(@x + x_offset, @y + y_offset)
bump_into_object
end
end end
end end
$PokemonTemp.encounterTriggered = false
end end
def move_left(turn_enabled = true) def turn_generic(dir, keep_enc_indicator = false)
turn_left if turn_enabled old_direction = @direction
if passable?(@x, @y, 4) super(dir)
return if pbLedge(-1,0) if @direction != old_direction && !@move_route_forcing && !pbMapInterpreterRunning?
return if pbEndSurf(-1,0) Events.onChangeDirection.trigger(self, self)
turn_left $PokemonTemp.encounterTriggered = false if !keep_enc_indicator
@x -= 1
$PokemonTemp.dependentEvents.pbMoveDependentEvents
increase_steps
else
if !check_event_trigger_touch(@x-1, @y)
bump_into_object
end
end
end
def move_right(turn_enabled = true)
turn_right if turn_enabled
if passable?(@x, @y, 6)
return if pbLedge(1,0)
return if pbEndSurf(1,0)
turn_right
@x += 1
$PokemonTemp.dependentEvents.pbMoveDependentEvents
increase_steps
else
if !check_event_trigger_touch(@x+1, @y)
bump_into_object
end
end
end
def move_up(turn_enabled = true)
turn_up if turn_enabled
if passable?(@x, @y, 8)
return if pbLedge(0,-1)
return if pbEndSurf(0,-1)
turn_up
@y -= 1
$PokemonTemp.dependentEvents.pbMoveDependentEvents
increase_steps
else
if !check_event_trigger_touch(@x, @y-1)
bump_into_object
end
end end
end end
@@ -162,8 +131,7 @@ class Game_Player < Game_Character
return result return result
end end
def pbCheckEventTriggerAfterTurning def pbCheckEventTriggerAfterTurning; end
end
def pbCheckEventTriggerFromDistance(triggers) def pbCheckEventTriggerFromDistance(triggers)
ret = pbTriggeredTrainerEvents(triggers) ret = pbTriggeredTrainerEvents(triggers)
@@ -377,17 +345,18 @@ class Game_Player < Game_Character
def update_command_new def update_command_new
dir = Input.dir4 dir = Input.dir4
unless pbMapInterpreterRunning? or $game_temp.message_window_showing or unless pbMapInterpreterRunning? || $game_temp.message_window_showing ||
$PokemonTemp.miniupdate or $game_temp.in_menu $PokemonTemp.miniupdate || $game_temp.in_menu
# Move player in the direction the directional button is being pressed # Move player in the direction the directional button is being pressed
if dir==@lastdir && Graphics.frame_count-@lastdirframe>Graphics.frame_rate/20 if @moved_last_frame ||
(dir > 0 && dir == @lastdir && Graphics.frame_count - @lastdirframe > Graphics.frame_rate / 20)
case dir case dir
when 2; move_down when 2; move_down
when 4; move_left when 4; move_left
when 6; move_right when 6; move_right
when 8; move_up when 8; move_up
end end
elsif dir!=@lastdir elsif dir != @lastdir
case dir case dir
when 2; turn_down when 2; turn_down
when 4; turn_left when 4; turn_left
@@ -397,7 +366,7 @@ class Game_Player < Game_Character
end end
end end
# Record last direction input # Record last direction input
@lastdirframe = Graphics.frame_count if dir!=@lastdir @lastdirframe = Graphics.frame_count if dir != @lastdir
@lastdir = dir @lastdir = dir
end end
@@ -25,7 +25,7 @@ class Game_Player < Game_Character
pbMapInterpreterRunning? pbMapInterpreterRunning?
terrain = pbGetTerrainTag terrain = pbGetTerrainTag
input = ($PokemonSystem.runstyle==1) ? $PokemonGlobal.runtoggle : Input.press?(Input::A) input = ($PokemonSystem.runstyle==1) ? $PokemonGlobal.runtoggle : Input.press?(Input::A)
return input && $PokemonGlobal.runningShoes && return input && $PokemonGlobal.runningShoes && !jumping? &&
!$PokemonGlobal.diving && !$PokemonGlobal.surfing && !$PokemonGlobal.diving && !$PokemonGlobal.surfing &&
!$PokemonGlobal.bicycle && !PBTerrain.onlyWalk?(terrain) !$PokemonGlobal.bicycle && !PBTerrain.onlyWalk?(terrain)
end end
@@ -54,14 +54,14 @@ class Game_Player < Game_Character
def update_command def update_command
if PBTerrain.isIce?(pbGetTerrainTag) if PBTerrain.isIce?(pbGetTerrainTag)
self.move_speed = 5 # Sliding on ice self.move_speed = 4 # Sliding on ice
elsif !moving? && !@move_route_forcing && $PokemonGlobal elsif !moving? && !@move_route_forcing && $PokemonGlobal
if $PokemonGlobal.bicycle if $PokemonGlobal.bicycle
self.move_speed = 6 # Cycling self.move_speed = 5 # Cycling
elsif pbCanRun? || $PokemonGlobal.surfing || $PokemonGlobal.diving elsif pbCanRun? || $PokemonGlobal.surfing
self.move_speed = 5 # Running, surfing or diving self.move_speed = 4 # Running, surfing
else else
self.move_speed = 4 # Walking self.move_speed = 3 # Walking, diving
end end
end end
super super
@@ -103,7 +103,7 @@ class Game_Map
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Autoplays background music # * Autoplays background music
# Plays music called "[normal BGM]n" if it's night time and it exists # Plays music called "[normal BGM]_n" if it's night time and it exists
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def autoplayAsCue def autoplayAsCue
if @map.autoplay_bgm if @map.autoplay_bgm
@@ -119,12 +119,12 @@ class Game_Map
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Plays background music # * Plays background music
# Plays music called "[normal BGM]n" if it's night time and it exists # Plays music called "[normal BGM]_n" if it's night time and it exists
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def autoplay def autoplay
if @map.autoplay_bgm if @map.autoplay_bgm
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/"+ @map.bgm.name+ "n") if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/"+ @map.bgm.name+ "_n")
pbBGMPlay(@map.bgm.name+"n",@map.bgm.volume,@map.bgm.pitch) pbBGMPlay(@map.bgm.name+"_n",@map.bgm.volume,@map.bgm.pitch)
else else
pbBGMPlay(@map.bgm) pbBGMPlay(@map.bgm)
end end
@@ -39,8 +39,8 @@ class Event
# The first argument is the sender of the event, the second argument contains # The first argument is the sender of the event, the second argument contains
# the event's parameters. If three or more arguments are given, this method # the event's parameters. If three or more arguments are given, this method
# supports the following callbacks: # supports the following callbacks:
# proc{ |sender,params| } where params is an array of the other parameters, and # proc { |sender,params| } where params is an array of the other parameters, and
# proc{ |sender,arg0,arg1,...| } # proc { |sender,arg0,arg1,...| }
def trigger(*arg) def trigger(*arg)
arglist = arg[1,arg.length] arglist = arg[1,arg.length]
for callback in @callbacks for callback in @callbacks
@@ -108,7 +108,7 @@ def pbPlaySoundData(samples,volume,async=false,sampleFreq=11025)
ret = name ret = name
break break
end end
return ret next ret
} }
playThenDelete = proc { |path,volume,length,_async| playThenDelete = proc { |path,volume,length,_async|
next if !path || !safeExists?(path) next if !path || !safeExists?(path)
@@ -0,0 +1,992 @@
#===============================================================================
#
#===============================================================================
class SpriteWindowCursorRect < Rect
def initialize(window)
@window=window
@x=0
@y=0
@width=0
@height=0
end
attr_reader :x,:y,:width,:height
def empty
needupdate=@x!=0 || @y!=0 || @width!=0 || @height!=0
if needupdate
@x=0
@y=0
@width=0
@height=0
@window.width=@window.width
end
end
def isEmpty?
return @x==0 && @y==0 && @width==0 && @height==0
end
def set(x,y,width,height)
needupdate=@x!=x || @y!=y || @width!=width || @height!=height
if needupdate
@x=x
@y=y
@width=width
@height=height
@window.width=@window.width
end
end
def height=(value)
@height=value; @window.width=@window.width
end
def width=(value)
@width=value; @window.width=@window.width
end
def x=(value)
@x=value; @window.width=@window.width
end
def y=(value)
@y=value; @window.width=@window.width
end
end
#===============================================================================
# SpriteWindow is a class based on Window which emulates Window's functionality.
# This class is necessary in order to change the viewport of windows (with
# viewport=) and to make windows fade in and out (with tone=).
#===============================================================================
class SpriteWindow < Window
attr_reader :tone
attr_reader :color
attr_reader :viewport
attr_reader :contents
attr_reader :ox
attr_reader :oy
attr_reader :x
attr_reader :y
attr_reader :z
attr_reader :zoom_x
attr_reader :zoom_y
attr_reader :offset_x
attr_reader :offset_y
attr_reader :width
attr_reader :active
attr_reader :pause
attr_reader :height
attr_reader :opacity
attr_reader :back_opacity
attr_reader :contents_opacity
attr_reader :visible
attr_reader :cursor_rect
attr_reader :contents_blend_type
attr_reader :blend_type
attr_reader :openness
def windowskin
@_windowskin
end
# Flags used to preserve compatibility
# with RGSS/RGSS2's version of Window
module CompatBits
CorrectZ = 1
ExpandBack = 2
ShowScrollArrows = 4
StretchSides = 8
ShowPause = 16
ShowCursor = 32
end
attr_reader :compat
def compat=(value)
@compat=value
privRefresh(true)
end
def initialize(viewport=nil)
@sprites={}
@spritekeys=[
"back",
"corner0","side0","scroll0",
"corner1","side1","scroll1",
"corner2","side2","scroll2",
"corner3","side3","scroll3",
"cursor","contents","pause"
]
@viewport=viewport
@sidebitmaps=[nil,nil,nil,nil]
@cursorbitmap=nil
@bgbitmap=nil
for i in @spritekeys
@sprites[i]=Sprite.new(@viewport)
end
@disposed=false
@tone=Tone.new(0,0,0)
@color=Color.new(0,0,0,0)
@blankcontents=Bitmap.new(1,1) # RGSS2 requires this
@contents=@blankcontents
@_windowskin=nil
@rpgvx=false
@compat=CompatBits::ExpandBack|CompatBits::StretchSides
@x=0
@y=0
@width=0
@height=0
@offset_x=0
@offset_y=0
@zoom_x=1.0
@zoom_y=1.0
@ox=0
@oy=0
@z=0
@stretch=true
@visible=true
@active=true
@openness=255
@opacity=255
@back_opacity=255
@blend_type=0
@contents_blend_type=0
@contents_opacity=255
@cursor_rect=SpriteWindowCursorRect.new(self)
@cursorblink=0
@cursoropacity=255
@pause=false
@pauseframe=0
@flash=0
@pauseopacity=0
@skinformat=0
@skinrect=Rect.new(0,0,0,0)
@trim=[16,16,16,16]
privRefresh(true)
end
def dispose
if !self.disposed?
for i in @sprites
i[1].dispose if i[1]
@sprites[i[0]]=nil
end
for i in 0...@sidebitmaps.length
@sidebitmaps[i].dispose if @sidebitmaps[i]
@sidebitmaps[i]=nil
end
@blankcontents.dispose
@cursorbitmap.dispose if @cursorbitmap
@backbitmap.dispose if @backbitmap
@sprites.clear
@sidebitmaps.clear
@_windowskin=nil
@disposed=true
end
end
def stretch=(value)
@stretch=value
privRefresh(true)
end
def visible=(value)
@visible=value
privRefresh
end
def viewport=(value)
@viewport=value
for i in @spritekeys
@sprites[i].dispose if @sprites[i]
end
for i in @spritekeys
if @sprites[i].is_a?(Sprite)
@sprites[i]=Sprite.new(@viewport)
else
@sprites[i]=nil
end
end
privRefresh(true)
end
def z=(value)
@z=value
privRefresh
end
def disposed?
return @disposed
end
def contents=(value)
if @contents!=value
@contents=value
privRefresh if @visible
end
end
def ox=(value)
if @ox!=value
@ox=value
privRefresh if @visible
end
end
def oy=(value)
if @oy!=value
@oy=value
privRefresh if @visible
end
end
def active=(value)
@active=value
privRefresh(true)
end
def cursor_rect=(value)
if !value
@cursor_rect.empty
else
@cursor_rect.set(value.x,value.y,value.width,value.height)
end
end
def openness=(value)
@openness=value
@openness=0 if @openness<0
@openness=255 if @openness>255
privRefresh
end
def width=(value)
@width=value
privRefresh(true)
end
def height=(value)
@height=value
privRefresh(true)
end
def pause=(value)
@pause=value
@pauseopacity=0 if !value
privRefresh if @visible
end
def x=(value)
@x=value
privRefresh if @visible
end
def y=(value)
@y=value
privRefresh if @visible
end
def zoom_x=(value)
@zoom_x=value
privRefresh if @visible
end
def zoom_y=(value)
@zoom_y=value
privRefresh if @visible
end
def offset_x=(value)
@x=value
privRefresh if @visible
end
def offset_y=(value)
@y=value
privRefresh if @visible
end
def opacity=(value)
@opacity=value
@opacity=0 if @opacity<0
@opacity=255 if @opacity>255
privRefresh if @visible
end
def back_opacity=(value)
@back_opacity=value
@back_opacity=0 if @back_opacity<0
@back_opacity=255 if @back_opacity>255
privRefresh if @visible
end
def contents_opacity=(value)
@contents_opacity=value
@contents_opacity=0 if @contents_opacity<0
@contents_opacity=255 if @contents_opacity>255
privRefresh if @visible
end
def tone=(value)
@tone=value
privRefresh if @visible
end
def color=(value)
@color=value
privRefresh if @visible
end
def blend_type=(value)
@blend_type=value
privRefresh if @visible
end
def flash(color,duration)
return if disposed?
@flash=duration+1
for i in @sprites
i[1].flash(color,duration)
end
end
def update
return if disposed?
mustchange=false
if @active
if @cursorblink==0
@cursoropacity-=8
@cursorblink=1 if @cursoropacity<=128
else
@cursoropacity+=8
@cursorblink=0 if @cursoropacity>=255
end
privRefreshCursor
else
@cursoropacity=128
privRefreshCursor
end
if @pause
oldpauseframe=@pauseframe
oldpauseopacity=@pauseopacity
@pauseframe=(Graphics.frame_count / 8) % 4
@pauseopacity=[@pauseopacity+64,255].min
mustchange=@pauseframe!=oldpauseframe || @pauseopacity!=oldpauseopacity
end
privRefresh if mustchange
if @flash>0
for i in @sprites.values
i.update
end
@flash-=1
end
end
#############
attr_reader :skinformat
attr_reader :skinrect
def loadSkinFile(_file)
if (self.windowskin.width==80 || self.windowskin.width==96) &&
self.windowskin.height==48
# Body = X, Y, width, height of body rectangle within windowskin
@skinrect.set(32,16,16,16)
# Trim = X, Y, width, height of trim rectangle within windowskin
@trim=[32,16,16,16]
elsif self.windowskin.width==80 && self.windowskin.height==80
@skinrect.set(32,32,16,16)
@trim=[32,16,16,48]
end
end
def windowskin=(value)
oldSkinWidth=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.width : -1
oldSkinHeight=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.height : -1
@_windowskin=value
if @skinformat==1
@rpgvx=false
if @_windowskin && !@_windowskin.disposed?
if @_windowskin.width!=oldSkinWidth || @_windowskin.height!=oldSkinHeight
# Update skinrect and trim if windowskin's dimensions have changed
@skinrect.set((@_windowskin.width-16)/2,(@_windowskin.height-16)/2,16,16)
@trim=[@skinrect.x,@skinrect.y,@skinrect.x,@skinrect.y]
end
else
@skinrect.set(16,16,16,16)
@trim=[16,16,16,16]
end
else
if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128
@rpgvx=true
else
@rpgvx=false
end
@trim=[16,16,16,16]
end
privRefresh(true)
end
def skinrect=(value)
@skinrect=value
privRefresh
end
def skinformat=(value)
if @skinformat!=value
@skinformat=value
privRefresh(true)
end
end
def borderX
return 32 if !@trim || skinformat==0
if @_windowskin && !@_windowskin.disposed?
return @trim[0]+(@_windowskin.width-@trim[2]-@trim[0])
end
return 32
end
def borderY
return 32 if !@trim || skinformat==0
if @_windowskin && !@_windowskin.disposed?
return @trim[1]+(@_windowskin.height-@trim[3]-@trim[1])
end
return 32
end
def leftEdge; self.startX; end
def topEdge; self.startY; end
def rightEdge; self.borderX-self.leftEdge; end
def bottomEdge; self.borderY-self.topEdge; end
def startX
return !@trim || skinformat==0 ? 16 : @trim[0]
end
def startY
return !@trim || skinformat==0 ? 16 : @trim[1]
end
def endX
return !@trim || skinformat==0 ? 16 : @trim[2]
end
def endY
return !@trim || skinformat==0 ? 16 : @trim[3]
end
def startX=(value)
@trim[0]=value
privRefresh
end
def startY=(value)
@trim[1]=value
privRefresh
end
def endX=(value)
@trim[2]=value
privRefresh
end
def endY=(value)
@trim[3]=value
privRefresh
end
#############
private
def ensureBitmap(bitmap,dwidth,dheight)
if !bitmap||bitmap.disposed?||bitmap.width<dwidth||bitmap.height<dheight
bitmap.dispose if bitmap
bitmap=Bitmap.new([1,dwidth].max,[1,dheight].max)
end
return bitmap
end
def tileBitmap(dstbitmap,dstrect,srcbitmap,srcrect)
return if !srcbitmap || srcbitmap.disposed?
left=dstrect.x
top=dstrect.y
y=0;loop do break unless y<dstrect.height
x=0;loop do break unless x<dstrect.width
dstbitmap.blt(x+left,y+top,srcbitmap,srcrect)
x+=srcrect.width
end
y+=srcrect.height
end
end
def privRefreshCursor
contopac=self.contents_opacity
cursoropac=@cursoropacity*contopac/255
@sprites["cursor"].opacity=cursoropac
end
def privRefresh(changeBitmap=false)
return if !self || self.disposed?
backopac=self.back_opacity*self.opacity/255
contopac=self.contents_opacity
cursoropac=@cursoropacity*contopac/255
haveskin=@_windowskin && !@_windowskin.disposed?
for i in 0...4
@sprites["corner#{i}"].bitmap=@_windowskin
@sprites["scroll#{i}"].bitmap=@_windowskin
end
@sprites["pause"].bitmap=@_windowskin
@sprites["contents"].bitmap=@contents
if haveskin
for i in 0...4
@sprites["corner#{i}"].opacity=@opacity
@sprites["corner#{i}"].tone=@tone
@sprites["corner#{i}"].color=@color
@sprites["corner#{i}"].visible=@visible
@sprites["corner#{i}"].blend_type=@blend_type
@sprites["side#{i}"].opacity=@opacity
@sprites["side#{i}"].tone=@tone
@sprites["side#{i}"].color=@color
@sprites["side#{i}"].blend_type=@blend_type
@sprites["side#{i}"].visible=@visible
@sprites["scroll#{i}"].opacity=@opacity
@sprites["scroll#{i}"].tone=@tone
@sprites["scroll#{i}"].color=@color
@sprites["scroll#{i}"].visible=@visible
@sprites["scroll#{i}"].blend_type=@blend_type
end
for i in ["back","cursor","pause","contents"]
@sprites[i].color=@color
@sprites[i].tone=@tone
@sprites[i].blend_type=@blend_type
end
@sprites["contents"].blend_type=@contents_blend_type
@sprites["back"].opacity=backopac
@sprites["contents"].opacity=contopac
@sprites["cursor"].opacity=cursoropac
@sprites["pause"].opacity=@pauseopacity
supported=(@skinformat==0)
hascontents=(@contents && !@contents.disposed?)
@sprites["back"].visible=@visible
@sprites["contents"].visible=@visible && @openness==255
@sprites["pause"].visible=supported && @visible && @pause &&
(@combat & CompatBits::ShowPause)
@sprites["cursor"].visible=supported && @visible && @openness==255 &&
(@combat & CompatBits::ShowCursor)
@sprites["scroll0"].visible = false
@sprites["scroll1"].visible = false
@sprites["scroll2"].visible = false
@sprites["scroll3"].visible = false
else
for i in 0...4
@sprites["corner#{i}"].visible=false
@sprites["side#{i}"].visible=false
@sprites["scroll#{i}"].visible=false
end
@sprites["contents"].visible=@visible && @openness==255
@sprites["contents"].color=@color
@sprites["contents"].tone=@tone
@sprites["contents"].blend_type=@contents_blend_type
@sprites["contents"].opacity=contopac
@sprites["back"].visible=false
@sprites["pause"].visible=false
@sprites["cursor"].visible=false
end
for i in @spritekeys
@sprites[i].z=@z
end
if (@compat & CompatBits::CorrectZ)>0 && @skinformat==0 && !@rpgvx
# Compatibility Mode: Cursor, pause, and contents have higher Z
@sprites["cursor"].z=@z+1
@sprites["contents"].z=@z+2
@sprites["pause"].z=@z+2
end
if @skinformat==0
startX=16
startY=16
endX=16
endY=16
trimStartX=16
trimStartY=16
trimWidth=32
trimHeight=32
if @rpgvx
trimX=64
trimY=0
backRect=Rect.new(0,0,64,64)
blindsRect=Rect.new(0,64,64,64)
else
trimX=128
trimY=0
backRect=Rect.new(0,0,128,128)
blindsRect=nil
end
if @_windowskin && !@_windowskin.disposed?
@sprites["corner0"].src_rect.set(trimX,trimY+0,16,16);
@sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16);
@sprites["corner2"].src_rect.set(trimX,trimY+48,16,16);
@sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16);
@sprites["scroll0"].src_rect.set(trimX+24, trimY+16, 16, 8) # up
@sprites["scroll3"].src_rect.set(trimX+24, trimY+40, 16, 8) # down
@sprites["scroll1"].src_rect.set(trimX+16, trimY+24, 8, 16) # left
@sprites["scroll2"].src_rect.set(trimX+40, trimY+24, 8, 16) # right
cursorX=trimX
cursorY=trimY+64
sideRects=[
Rect.new(trimX+16,trimY+0,32,16),
Rect.new(trimX,trimY+16,16,32),
Rect.new(trimX+48,trimY+16,16,32),
Rect.new(trimX+16,trimY+48,32,16)
]
pauseRects=[
trimX+32,trimY+64,
trimX+48,trimY+64,
trimX+32,trimY+80,
trimX+48,trimY+80,
]
pauseWidth=16
pauseHeight=16
@sprites["pause"].src_rect.set(
pauseRects[@pauseframe*2],
pauseRects[@pauseframe*2+1],
pauseWidth,pauseHeight
)
end
else
trimStartX=@trim[0]
trimStartY=@trim[1]
trimWidth=@trim[0]+(@skinrect.width-@trim[2]+@trim[0])
trimHeight=@trim[1]+(@skinrect.height-@trim[3]+@trim[1])
if @_windowskin && !@_windowskin.disposed?
# width of left end of window
startX=@skinrect.x
# width of top end of window
startY=@skinrect.y
cx=@skinrect.x+@skinrect.width # right side of BODY rect
cy=@skinrect.y+@skinrect.height # bottom side of BODY rect
# width of right end of window
endX=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.x : @_windowskin.width-cx
# height of bottom end of window
endY=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.y : @_windowskin.height-cy
@sprites["corner0"].src_rect.set(0,0,startX,startY);
@sprites["corner1"].src_rect.set(cx,0,endX,startY);
@sprites["corner2"].src_rect.set(0,cy,startX,endY);
@sprites["corner3"].src_rect.set(cx,cy,endX,endY);
backRect=Rect.new(@skinrect.x,@skinrect.y,
@skinrect.width,@skinrect.height);
blindsRect=nil
sideRects=[
Rect.new(startX,0,@skinrect.width,startY), # side0 (top)
Rect.new(0,startY,startX,@skinrect.height), # side1 (left)
Rect.new(cx,startY,endX,@skinrect.height), # side2 (right)
Rect.new(startX,cy,@skinrect.width,endY) # side3 (bottom)
]
end
end
if @width>trimWidth && @height>trimHeight
@sprites["contents"].src_rect.set(@ox,@oy,@width-trimWidth,@height-trimHeight)
else
@sprites["contents"].src_rect.set(0,0,0,0)
end
@sprites["contents"].x=@x+trimStartX
@sprites["contents"].y=@y+trimStartY
if (@compat & CompatBits::ShowScrollArrows)>0 && @skinformat==0
# Compatibility mode: Make scroll arrows visible
if @skinformat==0 && @_windowskin && !@_windowskin.disposed? &&
@contents && !@contents.disposed?
@sprites["scroll0"].visible = @visible && hascontents && @oy > 0
@sprites["scroll1"].visible = @visible && hascontents && @ox > 0
@sprites["scroll2"].visible = @visible && (@contents.width - @ox) > @width-trimWidth
@sprites["scroll3"].visible = @visible && (@contents.height - @oy) > @height-trimHeight
end
end
if @_windowskin && !@_windowskin.disposed?
borderX=startX+endX
borderY=startY+endY
@sprites["corner0"].x=@x
@sprites["corner0"].y=@y
@sprites["corner1"].x=@x+@width-endX
@sprites["corner1"].y=@y
@sprites["corner2"].x=@x
@sprites["corner2"].y=@y+@height-endY
@sprites["corner3"].x=@x+@width-endX
@sprites["corner3"].y=@y+@height-endY
@sprites["side0"].x=@x+startX
@sprites["side0"].y=@y
@sprites["side1"].x=@x
@sprites["side1"].y=@y+startY
@sprites["side2"].x=@x+@width-endX
@sprites["side2"].y=@y+startY
@sprites["side3"].x=@x+startX
@sprites["side3"].y=@y+@height-endY
@sprites["scroll0"].x = @x+@width / 2 - 8
@sprites["scroll0"].y = @y+8
@sprites["scroll1"].x = @x+8
@sprites["scroll1"].y = @y+@height / 2 - 8
@sprites["scroll2"].x = @x+@width - 16
@sprites["scroll2"].y = @y+@height / 2 - 8
@sprites["scroll3"].x = @x+@width / 2 - 8
@sprites["scroll3"].y = @y+@height - 16
@sprites["cursor"].x=@x+startX+@cursor_rect.x
@sprites["cursor"].y=@y+startY+@cursor_rect.y
if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0
# Compatibility mode: Expand background
@sprites["back"].x=@x+2
@sprites["back"].y=@y+2
else
@sprites["back"].x=@x+startX
@sprites["back"].y=@y+startY
end
end
if changeBitmap && @_windowskin && !@_windowskin.disposed?
if @skinformat==0
@sprites["cursor"].x=@x+startX+@cursor_rect.x
@sprites["cursor"].y=@y+startY+@cursor_rect.y
width=@cursor_rect.width
height=@cursor_rect.height
if width > 0 && height > 0
cursorrects=[
# sides
Rect.new(cursorX+2, cursorY+0, 28, 2),
Rect.new(cursorX+0, cursorY+2, 2, 28),
Rect.new(cursorX+30, cursorY+2, 2, 28),
Rect.new(cursorX+2, cursorY+30, 28, 2),
# corners
Rect.new(cursorX+0, cursorY+0, 2, 2),
Rect.new(cursorX+30, cursorY+0, 2, 2),
Rect.new(cursorX+0, cursorY+30, 2, 2),
Rect.new(cursorX+30, cursorY+30, 2, 2),
# back
Rect.new(cursorX+2, cursorY+2, 28, 28)
]
margin=2
fullmargin=4
@cursorbitmap = ensureBitmap(@cursorbitmap, width, height)
@cursorbitmap.clear
@sprites["cursor"].bitmap=@cursorbitmap
@sprites["cursor"].src_rect.set(0,0,width,height)
rect = Rect.new(margin,margin,width - fullmargin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8])
@cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4])# top left
@cursorbitmap.blt(width-margin, 0, @_windowskin, cursorrects[5]) # top right
@cursorbitmap.blt(0, height-margin, @_windowskin, cursorrects[6]) # bottom right
@cursorbitmap.blt(width-margin, height-margin, @_windowskin, cursorrects[7]) # bottom left
rect = Rect.new(margin, 0,width - fullmargin, margin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0])
rect = Rect.new(0, margin,margin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1])
rect = Rect.new(width - margin, margin, margin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2])
rect = Rect.new(margin, height-margin, width - fullmargin, margin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3])
else
@sprites["cursor"].visible=false
@sprites["cursor"].src_rect.set(0,0,0,0)
end
end
for i in 0..3
case i
when 0
dwidth = @width-startX-endX
dheight = startY
when 1
dwidth = startX
dheight = @height-startY-endY
when 2
dwidth = endX
dheight = @height-startY-endY
when 3
dwidth = @width-startX-endX
dheight = endY
end
@sidebitmaps[i]=ensureBitmap(@sidebitmaps[i],dwidth,dheight)
@sprites["side#{i}"].bitmap=@sidebitmaps[i]
@sprites["side#{i}"].src_rect.set(0,0,dwidth,dheight)
@sidebitmaps[i].clear
if sideRects[i].width>0 && sideRects[i].height>0
if (@compat & CompatBits::StretchSides)>0 && @skinformat==0
# Compatibility mode: Stretch sides
@sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect,
@_windowskin,sideRects[i])
else
tileBitmap(@sidebitmaps[i],@sprites["side#{i}"].src_rect,
@_windowskin,sideRects[i])
end
end
end
if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0
# Compatibility mode: Expand background
backwidth=@width-4
backheight=@height-4
else
backwidth=@width-borderX
backheight=@height-borderY
end
if backwidth>0 && backheight>0
@backbitmap=ensureBitmap(@backbitmap,backwidth,backheight)
@sprites["back"].bitmap=@backbitmap
@sprites["back"].src_rect.set(0,0,backwidth,backheight)
@backbitmap.clear
if @stretch
@backbitmap.stretch_blt(@sprites["back"].src_rect,@_windowskin,backRect)
else
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,backRect)
end
if blindsRect
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,blindsRect)
end
else
@sprites["back"].visible=false
@sprites["back"].src_rect.set(0,0,0,0)
end
end
if @openness!=255
opn=@openness/255.0
for k in @spritekeys
sprite=@sprites[k]
ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height
sprite.zoom_y=opn
sprite.zoom_x=1.0
sprite.oy=0
sprite.y=(@y+(@height/2.0)+(@height*ratio*opn)-(@height/2*opn)).floor
end
else
for k in @spritekeys
sprite=@sprites[k]
sprite.zoom_x=1.0
sprite.zoom_y=1.0
end
end
i=0
# Ensure Z order
for k in @spritekeys
sprite=@sprites[k]
y=sprite.y
sprite.y=i
sprite.oy=(sprite.zoom_y<=0) ? 0 : (i-y)/sprite.zoom_y
sprite.zoom_x*=@zoom_x
sprite.zoom_y*=@zoom_y
sprite.x*=@zoom_x
sprite.y*=@zoom_y
sprite.x+=(@offset_x/sprite.zoom_x)
sprite.y+=(@offset_y/sprite.zoom_y)
end
end
end
#===============================================================================
#
#===============================================================================
class SpriteWindow_Base < SpriteWindow
TEXTPADDING=4 # In pixels
def initialize(x, y, width, height)
super()
self.x = x
self.y = y
self.width = width
self.height = height
self.z = 100
@curframe=MessageConfig.pbGetSystemFrame()
@curfont=MessageConfig.pbGetSystemFontName()
@sysframe=AnimatedBitmap.new(@curframe)
@customskin=nil
__setWindowskin(@sysframe.bitmap)
__resolveSystemFrame()
pbSetSystemFont(self.contents) if self.contents
end
def __setWindowskin(skin)
if skin && (skin.width==192 && skin.height==128) || # RPGXP Windowskin
(skin.width==128 && skin.height==128) # RPGVX Windowskin
self.skinformat=0
else
self.skinformat=1
end
self.windowskin=skin
end
def __resolveSystemFrame
if self.skinformat==1
if !@resolvedFrame
@resolvedFrame=MessageConfig.pbGetSystemFrame()
@resolvedFrame.sub!(/\.[^\.\/\\]+$/,"")
end
self.loadSkinFile("#{@resolvedFrame}.txt") if @resolvedFrame!=""
end
end
def setSkin(skin) # Filename of windowskin to apply. Supports XP, VX, and animated skins.
@customskin.dispose if @customskin
@customskin=nil
resolvedName=pbResolveBitmap(skin)
return if !resolvedName || resolvedName==""
@customskin=AnimatedBitmap.new(resolvedName)
__setWindowskin(@customskin.bitmap)
if self.skinformat==1
skinbase=resolvedName.sub(/\.[^\.\/\\]+$/,"")
self.loadSkinFile("#{skinbase}.txt")
end
end
def setSystemFrame
@customskin.dispose if @customskin
@customskin=nil
__setWindowskin(@sysframe.bitmap)
__resolveSystemFrame()
end
def update
super
if self.windowskin
if @customskin
if @customskin.totalFrames>1
@customskin.update
__setWindowskin(@customskin.bitmap)
end
elsif @sysframe
if @sysframe.totalFrames>1
@sysframe.update
__setWindowskin(@sysframe.bitmap)
end
end
end
if @curframe!=MessageConfig.pbGetSystemFrame()
@curframe=MessageConfig.pbGetSystemFrame()
if @sysframe && !@customskin
@sysframe.dispose if @sysframe
@sysframe=AnimatedBitmap.new(@curframe)
@resolvedFrame=nil
__setWindowskin(@sysframe.bitmap)
__resolveSystemFrame()
end
begin
refresh
rescue NoMethodError
end
end
if @curfont!=MessageConfig.pbGetSystemFontName()
@curfont=MessageConfig.pbGetSystemFontName()
if self.contents && !self.contents.disposed?
pbSetSystemFont(self.contents)
end
begin
refresh
rescue NoMethodError
end
end
end
def dispose
self.contents.dispose if self.contents
@sysframe.dispose
@customskin.dispose if @customskin
super
end
end
File diff suppressed because it is too large Load Diff
@@ -1,998 +1,3 @@
#===============================================================================
#
#===============================================================================
class SpriteWindowCursorRect < Rect
def initialize(window)
@window=window
@x=0
@y=0
@width=0
@height=0
end
attr_reader :x,:y,:width,:height
def empty
needupdate=@x!=0 || @y!=0 || @width!=0 || @height!=0
if needupdate
@x=0
@y=0
@width=0
@height=0
@window.width=@window.width
end
end
def isEmpty?
return @x==0 && @y==0 && @width==0 && @height==0
end
def set(x,y,width,height)
needupdate=@x!=x || @y!=y || @width!=width || @height!=height
if needupdate
@x=x
@y=y
@width=width
@height=height
@window.width=@window.width
end
end
def height=(value)
@height=value; @window.width=@window.width
end
def width=(value)
@width=value; @window.width=@window.width
end
def x=(value)
@x=value; @window.width=@window.width
end
def y=(value)
@y=value; @window.width=@window.width
end
end
#===============================================================================
# SpriteWindow is a class based on Window which emulates Window's functionality.
# This class is necessary in order to change the viewport of windows (with
# viewport=) and to make windows fade in and out (with tone=).
#===============================================================================
class SpriteWindow < Window
attr_reader :tone
attr_reader :color
attr_reader :viewport
attr_reader :contents
attr_reader :ox
attr_reader :oy
attr_reader :x
attr_reader :y
attr_reader :z
attr_reader :zoom_x
attr_reader :zoom_y
attr_reader :offset_x
attr_reader :offset_y
attr_reader :width
attr_reader :active
attr_reader :pause
attr_reader :height
attr_reader :opacity
attr_reader :back_opacity
attr_reader :contents_opacity
attr_reader :visible
attr_reader :cursor_rect
attr_reader :contents_blend_type
attr_reader :blend_type
attr_reader :openness
def windowskin
@_windowskin
end
# Flags used to preserve compatibility
# with RGSS/RGSS2's version of Window
module CompatBits
CorrectZ = 1
ExpandBack = 2
ShowScrollArrows = 4
StretchSides = 8
ShowPause = 16
ShowCursor = 32
end
attr_reader :compat
def compat=(value)
@compat=value
privRefresh(true)
end
def initialize(viewport=nil)
@sprites={}
@spritekeys=[
"back",
"corner0","side0","scroll0",
"corner1","side1","scroll1",
"corner2","side2","scroll2",
"corner3","side3","scroll3",
"cursor","contents","pause"
]
@viewport=viewport
@sidebitmaps=[nil,nil,nil,nil]
@cursorbitmap=nil
@bgbitmap=nil
for i in @spritekeys
@sprites[i]=Sprite.new(@viewport)
end
@disposed=false
@tone=Tone.new(0,0,0)
@color=Color.new(0,0,0,0)
@blankcontents=Bitmap.new(1,1) # RGSS2 requires this
@contents=@blankcontents
@_windowskin=nil
@rpgvx=false
@compat=CompatBits::ExpandBack|CompatBits::StretchSides
@x=0
@y=0
@width=0
@height=0
@offset_x=0
@offset_y=0
@zoom_x=1.0
@zoom_y=1.0
@ox=0
@oy=0
@z=0
@stretch=true
@visible=true
@active=true
@openness=255
@opacity=255
@back_opacity=255
@blend_type=0
@contents_blend_type=0
@contents_opacity=255
@cursor_rect=SpriteWindowCursorRect.new(self)
@cursorblink=0
@cursoropacity=255
@pause=false
@pauseframe=0
@flash=0
@pauseopacity=0
@skinformat=0
@skinrect=Rect.new(0,0,0,0)
@trim=[16,16,16,16]
privRefresh(true)
end
def dispose
if !self.disposed?
for i in @sprites
i[1].dispose if i[1]
@sprites[i[0]]=nil
end
for i in 0...@sidebitmaps.length
@sidebitmaps[i].dispose if @sidebitmaps[i]
@sidebitmaps[i]=nil
end
@blankcontents.dispose
@cursorbitmap.dispose if @cursorbitmap
@backbitmap.dispose if @backbitmap
@sprites.clear
@sidebitmaps.clear
@_windowskin=nil
@disposed=true
end
end
def stretch=(value)
@stretch=value
privRefresh(true)
end
def visible=(value)
@visible=value
privRefresh
end
def viewport=(value)
@viewport=value
for i in @spritekeys
@sprites[i].dispose if @sprites[i]
end
for i in @spritekeys
if @sprites[i].is_a?(Sprite)
@sprites[i]=Sprite.new(@viewport)
else
@sprites[i]=nil
end
end
privRefresh(true)
end
def z=(value)
@z=value
privRefresh
end
def disposed?
return @disposed
end
def contents=(value)
if @contents!=value
@contents=value
privRefresh if @visible
end
end
def ox=(value)
if @ox!=value
@ox=value
privRefresh if @visible
end
end
def oy=(value)
if @oy!=value
@oy=value
privRefresh if @visible
end
end
def active=(value)
@active=value
privRefresh(true)
end
def cursor_rect=(value)
if !value
@cursor_rect.empty
else
@cursor_rect.set(value.x,value.y,value.width,value.height)
end
end
def openness=(value)
@openness=value
@openness=0 if @openness<0
@openness=255 if @openness>255
privRefresh
end
def width=(value)
@width=value
privRefresh(true)
end
def height=(value)
@height=value
privRefresh(true)
end
def pause=(value)
@pause=value
@pauseopacity=0 if !value
privRefresh if @visible
end
def x=(value)
@x=value
privRefresh if @visible
end
def y=(value)
@y=value
privRefresh if @visible
end
def zoom_x=(value)
@zoom_x=value
privRefresh if @visible
end
def zoom_y=(value)
@zoom_y=value
privRefresh if @visible
end
def offset_x=(value)
@x=value
privRefresh if @visible
end
def offset_y=(value)
@y=value
privRefresh if @visible
end
def opacity=(value)
@opacity=value
@opacity=0 if @opacity<0
@opacity=255 if @opacity>255
privRefresh if @visible
end
def back_opacity=(value)
@back_opacity=value
@back_opacity=0 if @back_opacity<0
@back_opacity=255 if @back_opacity>255
privRefresh if @visible
end
def contents_opacity=(value)
@contents_opacity=value
@contents_opacity=0 if @contents_opacity<0
@contents_opacity=255 if @contents_opacity>255
privRefresh if @visible
end
def tone=(value)
@tone=value
privRefresh if @visible
end
def color=(value)
@color=value
privRefresh if @visible
end
def blend_type=(value)
@blend_type=value
privRefresh if @visible
end
def flash(color,duration)
return if disposed?
@flash=duration+1
for i in @sprites
i[1].flash(color,duration)
end
end
def update
return if disposed?
mustchange=false
if @active
if @cursorblink==0
@cursoropacity-=8
@cursorblink=1 if @cursoropacity<=128
else
@cursoropacity+=8
@cursorblink=0 if @cursoropacity>=255
end
privRefreshCursor
else
@cursoropacity=128
privRefreshCursor
end
if @pause
oldpauseframe=@pauseframe
oldpauseopacity=@pauseopacity
@pauseframe=(Graphics.frame_count / 8) % 4
@pauseopacity=[@pauseopacity+64,255].min
mustchange=@pauseframe!=oldpauseframe || @pauseopacity!=oldpauseopacity
end
privRefresh if mustchange
if @flash>0
for i in @sprites.values
i.update
end
@flash-=1
end
end
#############
attr_reader :skinformat
attr_reader :skinrect
def loadSkinFile(_file)
if (self.windowskin.width==80 || self.windowskin.width==96) &&
self.windowskin.height==48
# Body = X, Y, width, height of body rectangle within windowskin
@skinrect.set(32,16,16,16)
# Trim = X, Y, width, height of trim rectangle within windowskin
@trim=[32,16,16,16]
elsif self.windowskin.width==80 && self.windowskin.height==80
@skinrect.set(32,32,16,16)
@trim=[32,16,16,48]
end
end
def windowskin=(value)
oldSkinWidth=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.width : -1
oldSkinHeight=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.height : -1
@_windowskin=value
if @skinformat==1
@rpgvx=false
if @_windowskin && !@_windowskin.disposed?
if @_windowskin.width!=oldSkinWidth || @_windowskin.height!=oldSkinHeight
# Update skinrect and trim if windowskin's dimensions have changed
@skinrect.set((@_windowskin.width-16)/2,(@_windowskin.height-16)/2,16,16)
@trim=[@skinrect.x,@skinrect.y,@skinrect.x,@skinrect.y]
end
else
@skinrect.set(16,16,16,16)
@trim=[16,16,16,16]
end
else
if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128
@rpgvx=true
else
@rpgvx=false
end
@trim=[16,16,16,16]
end
privRefresh(true)
end
def skinrect=(value)
@skinrect=value
privRefresh
end
def skinformat=(value)
if @skinformat!=value
@skinformat=value
privRefresh(true)
end
end
def borderX
return 32 if !@trim || skinformat==0
if @_windowskin && !@_windowskin.disposed?
return @trim[0]+(@_windowskin.width-@trim[2]-@trim[0])
end
return 32
end
def borderY
return 32 if !@trim || skinformat==0
if @_windowskin && !@_windowskin.disposed?
return @trim[1]+(@_windowskin.height-@trim[3]-@trim[1])
end
return 32
end
def leftEdge; self.startX; end
def topEdge; self.startY; end
def rightEdge; self.borderX-self.leftEdge; end
def bottomEdge; self.borderY-self.topEdge; end
def startX
return !@trim || skinformat==0 ? 16 : @trim[0]
end
def startY
return !@trim || skinformat==0 ? 16 : @trim[1]
end
def endX
return !@trim || skinformat==0 ? 16 : @trim[2]
end
def endY
return !@trim || skinformat==0 ? 16 : @trim[3]
end
def startX=(value)
@trim[0]=value
privRefresh
end
def startY=(value)
@trim[1]=value
privRefresh
end
def endX=(value)
@trim[2]=value
privRefresh
end
def endY=(value)
@trim[3]=value
privRefresh
end
#############
private
def ensureBitmap(bitmap,dwidth,dheight)
if !bitmap||bitmap.disposed?||bitmap.width<dwidth||bitmap.height<dheight
bitmap.dispose if bitmap
bitmap=Bitmap.new([1,dwidth].max,[1,dheight].max)
end
return bitmap
end
def tileBitmap(dstbitmap,dstrect,srcbitmap,srcrect)
return if !srcbitmap || srcbitmap.disposed?
left=dstrect.x
top=dstrect.y
y=0;loop do break unless y<dstrect.height
x=0;loop do break unless x<dstrect.width
dstbitmap.blt(x+left,y+top,srcbitmap,srcrect)
x+=srcrect.width
end
y+=srcrect.height
end
end
def privRefreshCursor
contopac=self.contents_opacity
cursoropac=@cursoropacity*contopac/255
@sprites["cursor"].opacity=cursoropac
end
def privRefresh(changeBitmap=false)
return if !self || self.disposed?
backopac=self.back_opacity*self.opacity/255
contopac=self.contents_opacity
cursoropac=@cursoropacity*contopac/255
haveskin=@_windowskin && !@_windowskin.disposed?
for i in 0...4
@sprites["corner#{i}"].bitmap=@_windowskin
@sprites["scroll#{i}"].bitmap=@_windowskin
end
@sprites["pause"].bitmap=@_windowskin
@sprites["contents"].bitmap=@contents
if haveskin
for i in 0...4
@sprites["corner#{i}"].opacity=@opacity
@sprites["corner#{i}"].tone=@tone
@sprites["corner#{i}"].color=@color
@sprites["corner#{i}"].visible=@visible
@sprites["corner#{i}"].blend_type=@blend_type
@sprites["side#{i}"].opacity=@opacity
@sprites["side#{i}"].tone=@tone
@sprites["side#{i}"].color=@color
@sprites["side#{i}"].blend_type=@blend_type
@sprites["side#{i}"].visible=@visible
@sprites["scroll#{i}"].opacity=@opacity
@sprites["scroll#{i}"].tone=@tone
@sprites["scroll#{i}"].color=@color
@sprites["scroll#{i}"].visible=@visible
@sprites["scroll#{i}"].blend_type=@blend_type
end
for i in ["back","cursor","pause","contents"]
@sprites[i].color=@color
@sprites[i].tone=@tone
@sprites[i].blend_type=@blend_type
end
@sprites["contents"].blend_type=@contents_blend_type
@sprites["back"].opacity=backopac
@sprites["contents"].opacity=contopac
@sprites["cursor"].opacity=cursoropac
@sprites["pause"].opacity=@pauseopacity
supported=(@skinformat==0)
hascontents=(@contents && !@contents.disposed?)
@sprites["back"].visible=@visible
@sprites["contents"].visible=@visible && @openness==255
@sprites["pause"].visible=supported && @visible && @pause &&
(@combat & CompatBits::ShowPause)
@sprites["cursor"].visible=supported && @visible && @openness==255 &&
(@combat & CompatBits::ShowCursor)
@sprites["scroll0"].visible = false
@sprites["scroll1"].visible = false
@sprites["scroll2"].visible = false
@sprites["scroll3"].visible = false
else
for i in 0...4
@sprites["corner#{i}"].visible=false
@sprites["side#{i}"].visible=false
@sprites["scroll#{i}"].visible=false
end
@sprites["contents"].visible=@visible && @openness==255
@sprites["contents"].color=@color
@sprites["contents"].tone=@tone
@sprites["contents"].blend_type=@contents_blend_type
@sprites["contents"].opacity=contopac
@sprites["back"].visible=false
@sprites["pause"].visible=false
@sprites["cursor"].visible=false
end
for i in @spritekeys
@sprites[i].z=@z
end
if (@compat & CompatBits::CorrectZ)>0 && @skinformat==0 && !@rpgvx
# Compatibility Mode: Cursor, pause, and contents have higher Z
@sprites["cursor"].z=@z+1
@sprites["contents"].z=@z+2
@sprites["pause"].z=@z+2
end
if @skinformat==0
startX=16
startY=16
endX=16
endY=16
trimStartX=16
trimStartY=16
trimWidth=32
trimHeight=32
if @rpgvx
trimX=64
trimY=0
backRect=Rect.new(0,0,64,64)
blindsRect=Rect.new(0,64,64,64)
else
trimX=128
trimY=0
backRect=Rect.new(0,0,128,128)
blindsRect=nil
end
if @_windowskin && !@_windowskin.disposed?
@sprites["corner0"].src_rect.set(trimX,trimY+0,16,16);
@sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16);
@sprites["corner2"].src_rect.set(trimX,trimY+48,16,16);
@sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16);
@sprites["scroll0"].src_rect.set(trimX+24, trimY+16, 16, 8) # up
@sprites["scroll3"].src_rect.set(trimX+24, trimY+40, 16, 8) # down
@sprites["scroll1"].src_rect.set(trimX+16, trimY+24, 8, 16) # left
@sprites["scroll2"].src_rect.set(trimX+40, trimY+24, 8, 16) # right
cursorX=trimX
cursorY=trimY+64
sideRects=[
Rect.new(trimX+16,trimY+0,32,16),
Rect.new(trimX,trimY+16,16,32),
Rect.new(trimX+48,trimY+16,16,32),
Rect.new(trimX+16,trimY+48,32,16)
]
pauseRects=[
trimX+32,trimY+64,
trimX+48,trimY+64,
trimX+32,trimY+80,
trimX+48,trimY+80,
]
pauseWidth=16
pauseHeight=16
@sprites["pause"].src_rect.set(
pauseRects[@pauseframe*2],
pauseRects[@pauseframe*2+1],
pauseWidth,pauseHeight
)
end
else
trimStartX=@trim[0]
trimStartY=@trim[1]
trimWidth=@trim[0]+(@skinrect.width-@trim[2]+@trim[0])
trimHeight=@trim[1]+(@skinrect.height-@trim[3]+@trim[1])
if @_windowskin && !@_windowskin.disposed?
# width of left end of window
startX=@skinrect.x
# width of top end of window
startY=@skinrect.y
cx=@skinrect.x+@skinrect.width # right side of BODY rect
cy=@skinrect.y+@skinrect.height # bottom side of BODY rect
# width of right end of window
endX=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.x : @_windowskin.width-cx
# height of bottom end of window
endY=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.y : @_windowskin.height-cy
@sprites["corner0"].src_rect.set(0,0,startX,startY);
@sprites["corner1"].src_rect.set(cx,0,endX,startY);
@sprites["corner2"].src_rect.set(0,cy,startX,endY);
@sprites["corner3"].src_rect.set(cx,cy,endX,endY);
backRect=Rect.new(@skinrect.x,@skinrect.y,
@skinrect.width,@skinrect.height);
blindsRect=nil
sideRects=[
Rect.new(startX,0,@skinrect.width,startY), # side0 (top)
Rect.new(0,startY,startX,@skinrect.height), # side1 (left)
Rect.new(cx,startY,endX,@skinrect.height), # side2 (right)
Rect.new(startX,cy,@skinrect.width,endY) # side3 (bottom)
]
end
end
if @width>trimWidth && @height>trimHeight
@sprites["contents"].src_rect.set(@ox,@oy,@width-trimWidth,@height-trimHeight)
else
@sprites["contents"].src_rect.set(0,0,0,0)
end
@sprites["contents"].x=@x+trimStartX
@sprites["contents"].y=@y+trimStartY
if (@compat & CompatBits::ShowScrollArrows)>0 && @skinformat==0
# Compatibility mode: Make scroll arrows visible
if @skinformat==0 && @_windowskin && !@_windowskin.disposed? &&
@contents && !@contents.disposed?
@sprites["scroll0"].visible = @visible && hascontents && @oy > 0
@sprites["scroll1"].visible = @visible && hascontents && @ox > 0
@sprites["scroll2"].visible = @visible && (@contents.width - @ox) > @width-trimWidth
@sprites["scroll3"].visible = @visible && (@contents.height - @oy) > @height-trimHeight
end
end
if @_windowskin && !@_windowskin.disposed?
borderX=startX+endX
borderY=startY+endY
@sprites["corner0"].x=@x
@sprites["corner0"].y=@y
@sprites["corner1"].x=@x+@width-endX
@sprites["corner1"].y=@y
@sprites["corner2"].x=@x
@sprites["corner2"].y=@y+@height-endY
@sprites["corner3"].x=@x+@width-endX
@sprites["corner3"].y=@y+@height-endY
@sprites["side0"].x=@x+startX
@sprites["side0"].y=@y
@sprites["side1"].x=@x
@sprites["side1"].y=@y+startY
@sprites["side2"].x=@x+@width-endX
@sprites["side2"].y=@y+startY
@sprites["side3"].x=@x+startX
@sprites["side3"].y=@y+@height-endY
@sprites["scroll0"].x = @x+@width / 2 - 8
@sprites["scroll0"].y = @y+8
@sprites["scroll1"].x = @x+8
@sprites["scroll1"].y = @y+@height / 2 - 8
@sprites["scroll2"].x = @x+@width - 16
@sprites["scroll2"].y = @y+@height / 2 - 8
@sprites["scroll3"].x = @x+@width / 2 - 8
@sprites["scroll3"].y = @y+@height - 16
@sprites["cursor"].x=@x+startX+@cursor_rect.x
@sprites["cursor"].y=@y+startY+@cursor_rect.y
if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0
# Compatibility mode: Expand background
@sprites["back"].x=@x+2
@sprites["back"].y=@y+2
else
@sprites["back"].x=@x+startX
@sprites["back"].y=@y+startY
end
end
if changeBitmap && @_windowskin && !@_windowskin.disposed?
if @skinformat==0
@sprites["cursor"].x=@x+startX+@cursor_rect.x
@sprites["cursor"].y=@y+startY+@cursor_rect.y
width=@cursor_rect.width
height=@cursor_rect.height
if width > 0 && height > 0
cursorrects=[
# sides
Rect.new(cursorX+2, cursorY+0, 28, 2),
Rect.new(cursorX+0, cursorY+2, 2, 28),
Rect.new(cursorX+30, cursorY+2, 2, 28),
Rect.new(cursorX+2, cursorY+30, 28, 2),
# corners
Rect.new(cursorX+0, cursorY+0, 2, 2),
Rect.new(cursorX+30, cursorY+0, 2, 2),
Rect.new(cursorX+0, cursorY+30, 2, 2),
Rect.new(cursorX+30, cursorY+30, 2, 2),
# back
Rect.new(cursorX+2, cursorY+2, 28, 28)
]
margin=2
fullmargin=4
@cursorbitmap = ensureBitmap(@cursorbitmap, width, height)
@cursorbitmap.clear
@sprites["cursor"].bitmap=@cursorbitmap
@sprites["cursor"].src_rect.set(0,0,width,height)
rect = Rect.new(margin,margin,width - fullmargin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8])
@cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4])# top left
@cursorbitmap.blt(width-margin, 0, @_windowskin, cursorrects[5]) # top right
@cursorbitmap.blt(0, height-margin, @_windowskin, cursorrects[6]) # bottom right
@cursorbitmap.blt(width-margin, height-margin, @_windowskin, cursorrects[7]) # bottom left
rect = Rect.new(margin, 0,width - fullmargin, margin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0])
rect = Rect.new(0, margin,margin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1])
rect = Rect.new(width - margin, margin, margin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2])
rect = Rect.new(margin, height-margin, width - fullmargin, margin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3])
else
@sprites["cursor"].visible=false
@sprites["cursor"].src_rect.set(0,0,0,0)
end
end
for i in 0..3
case i
when 0
dwidth = @width-startX-endX
dheight = startY
when 1
dwidth = startX
dheight = @height-startY-endY
when 2
dwidth = endX
dheight = @height-startY-endY
when 3
dwidth = @width-startX-endX
dheight = endY
end
@sidebitmaps[i]=ensureBitmap(@sidebitmaps[i],dwidth,dheight)
@sprites["side#{i}"].bitmap=@sidebitmaps[i]
@sprites["side#{i}"].src_rect.set(0,0,dwidth,dheight)
@sidebitmaps[i].clear
if sideRects[i].width>0 && sideRects[i].height>0
if (@compat & CompatBits::StretchSides)>0 && @skinformat==0
# Compatibility mode: Stretch sides
@sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect,
@_windowskin,sideRects[i])
else
tileBitmap(@sidebitmaps[i],@sprites["side#{i}"].src_rect,
@_windowskin,sideRects[i])
end
end
end
if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0
# Compatibility mode: Expand background
backwidth=@width-4
backheight=@height-4
else
backwidth=@width-borderX
backheight=@height-borderY
end
if backwidth>0 && backheight>0
@backbitmap=ensureBitmap(@backbitmap,backwidth,backheight)
@sprites["back"].bitmap=@backbitmap
@sprites["back"].src_rect.set(0,0,backwidth,backheight)
@backbitmap.clear
if @stretch
@backbitmap.stretch_blt(@sprites["back"].src_rect,@_windowskin,backRect)
else
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,backRect)
end
if blindsRect
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,blindsRect)
end
else
@sprites["back"].visible=false
@sprites["back"].src_rect.set(0,0,0,0)
end
end
if @openness!=255
opn=@openness/255.0
for k in @spritekeys
sprite=@sprites[k]
ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height
sprite.zoom_y=opn
sprite.zoom_x=1.0
sprite.oy=0
sprite.y=(@y+(@height/2.0)+(@height*ratio*opn)-(@height/2*opn)).floor
end
else
for k in @spritekeys
sprite=@sprites[k]
sprite.zoom_x=1.0
sprite.zoom_y=1.0
end
end
i=0
# Ensure Z order
for k in @spritekeys
sprite=@sprites[k]
y=sprite.y
sprite.y=i
sprite.oy=(sprite.zoom_y<=0) ? 0 : (i-y)/sprite.zoom_y
sprite.zoom_x*=@zoom_x
sprite.zoom_y*=@zoom_y
sprite.x*=@zoom_x
sprite.y*=@zoom_y
sprite.x+=(@offset_x/sprite.zoom_x)
sprite.y+=(@offset_y/sprite.zoom_y)
end
end
end
#===============================================================================
#
#===============================================================================
class SpriteWindow_Base < SpriteWindow
TEXTPADDING=4 # In pixels
def initialize(x, y, width, height)
super()
self.x = x
self.y = y
self.width = width
self.height = height
self.z = 100
@curframe=MessageConfig.pbGetSystemFrame()
@curfont=MessageConfig.pbGetSystemFontName()
@sysframe=AnimatedBitmap.new(@curframe)
@customskin=nil
__setWindowskin(@sysframe.bitmap)
__resolveSystemFrame()
pbSetSystemFont(self.contents) if self.contents
end
def __setWindowskin(skin)
if skin && (skin.width==192 && skin.height==128) || # RPGXP Windowskin
(skin.width==128 && skin.height==128) # RPGVX Windowskin
self.skinformat=0
else
self.skinformat=1
end
self.windowskin=skin
end
def __resolveSystemFrame
if self.skinformat==1
if !@resolvedFrame
@resolvedFrame=MessageConfig.pbGetSystemFrame()
@resolvedFrame.sub!(/\.[^\.\/\\]+$/,"")
end
self.loadSkinFile("#{@resolvedFrame}.txt") if @resolvedFrame!=""
end
end
def setSkin(skin) # Filename of windowskin to apply. Supports XP, VX, and animated skins.
@customskin.dispose if @customskin
@customskin=nil
resolvedName=pbResolveBitmap(skin)
return if !resolvedName || resolvedName==""
@customskin=AnimatedBitmap.new(resolvedName)
__setWindowskin(@customskin.bitmap)
if self.skinformat==1
skinbase=resolvedName.sub(/\.[^\.\/\\]+$/,"")
self.loadSkinFile("#{skinbase}.txt")
end
end
def setSystemFrame
@customskin.dispose if @customskin
@customskin=nil
__setWindowskin(@sysframe.bitmap)
__resolveSystemFrame()
end
def update
super
if self.windowskin
if @customskin
if @customskin.totalFrames>1
@customskin.update
__setWindowskin(@customskin.bitmap)
end
elsif @sysframe
if @sysframe.totalFrames>1
@sysframe.update
__setWindowskin(@sysframe.bitmap)
end
end
end
if @curframe!=MessageConfig.pbGetSystemFrame()
@curframe=MessageConfig.pbGetSystemFrame()
if @sysframe && !@customskin
@sysframe.dispose if @sysframe
@sysframe=AnimatedBitmap.new(@curframe)
@resolvedFrame=nil
__setWindowskin(@sysframe.bitmap)
__resolveSystemFrame()
end
begin
refresh
rescue NoMethodError
end
end
if @curfont!=MessageConfig.pbGetSystemFontName()
@curfont=MessageConfig.pbGetSystemFontName()
if self.contents && !self.contents.disposed?
pbSetSystemFont(self.contents)
end
begin
refresh
rescue NoMethodError
end
end
end
def dispose
self.contents.dispose if self.contents
@sysframe.dispose
@customskin.dispose if @customskin
super
end
end
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
@@ -0,0 +1,121 @@
#===============================================================================
# Displays an icon bitmap in a window. Supports animated images.
#===============================================================================
class IconWindow < SpriteWindow_Base
attr_reader :name
def initialize(x,y,width,height,viewport=nil)
super(x,y,width,height)
self.viewport=viewport
self.contents=nil
@name=""
@_iconbitmap=nil
end
def dispose
clearBitmaps()
super
end
def update
super
if @_iconbitmap
@_iconbitmap.update
self.contents=@_iconbitmap.bitmap
end
end
def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap=nil
self.contents=nil if !self.disposed?
end
# Sets the icon's filename. Alias for setBitmap.
def name=(value)
setBitmap(value)
end
# Sets the icon's filename.
def setBitmap(file,hue=0)
clearBitmaps()
@name=file
return if file==nil
if file!=""
@_iconbitmap=AnimatedBitmap.new(file,hue)
# for compatibility
self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil
else
@_iconbitmap=nil
end
end
end
#===============================================================================
# Displays an icon bitmap in a window. Supports animated images.
# Accepts bitmaps and paths to bitmap files in its constructor.
#===============================================================================
class PictureWindow < SpriteWindow_Base
def initialize(pathOrBitmap)
super(0,0,32,32)
self.viewport=viewport
self.contents=nil
@_iconbitmap=nil
setBitmap(pathOrBitmap)
end
def dispose
clearBitmaps()
super
end
def update
super
if @_iconbitmap
if @_iconbitmap.is_a?(Bitmap)
self.contents=@_iconbitmap
else
@_iconbitmap.update
self.contents=@_iconbitmap.bitmap
end
end
end
def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap=nil
self.contents=nil if !self.disposed?
end
# Sets the icon's bitmap or filename. (hue parameter
# is ignored unless pathOrBitmap is a filename)
def setBitmap(pathOrBitmap,hue=0)
clearBitmaps()
if pathOrBitmap!=nil && pathOrBitmap!=""
if pathOrBitmap.is_a?(Bitmap)
@_iconbitmap=pathOrBitmap
self.contents=@_iconbitmap
self.width=@_iconbitmap.width+self.borderX
self.height=@_iconbitmap.height+self.borderY
elsif pathOrBitmap.is_a?(AnimatedBitmap)
@_iconbitmap=pathOrBitmap
self.contents=@_iconbitmap.bitmap
self.width=@_iconbitmap.bitmap.width+self.borderX
self.height=@_iconbitmap.bitmap.height+self.borderY
else
@_iconbitmap=AnimatedBitmap.new(pathOrBitmap,hue)
self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil
self.width=@_iconbitmap ? @_iconbitmap.bitmap.width+self.borderX :
32+self.borderX
self.height=@_iconbitmap ? @_iconbitmap.bitmap.height+self.borderY :
32+self.borderY
end
else
@_iconbitmap=nil
self.width=32+self.borderX
self.height=32+self.borderY
end
end
end
@@ -0,0 +1,359 @@
#===============================================================================
# SpriteWrapper is a class based on Sprite which wraps Sprite's properties.
#===============================================================================
class SpriteWrapper < Sprite
def initialize(viewport=nil)
@sprite = Sprite.new(viewport)
end
def dispose; @sprite.dispose; end
def disposed?; return @sprite.disposed?; end
def viewport; return @sprite.viewport; end
def flash(color,duration); return @sprite.flash(color,duration); end
def update; return @sprite.update; end
def x; @sprite.x; end
def x=(value); @sprite.x = value; end
def y; @sprite.y; end
def y=(value); @sprite.y = value; end
def bitmap; @sprite.bitmap; end
def bitmap=(value); @sprite.bitmap = value; end
def src_rect; @sprite.src_rect; end
def src_rect=(value); @sprite.src_rect = value; end
def visible; @sprite.visible; end
def visible=(value); @sprite.visible = value; end
def z; @sprite.z; end
def z=(value); @sprite.z = value; end
def ox; @sprite.ox; end
def ox=(value); @sprite.ox = value; end
def oy; @sprite.oy; end
def oy=(value); @sprite.oy = value; end
def zoom_x; @sprite.zoom_x; end
def zoom_x=(value); @sprite.zoom_x = value; end
def zoom_y; @sprite.zoom_y; end
def zoom_y=(value); @sprite.zoom_y = value; end
def angle; @sprite.angle; end
def angle=(value); @sprite.angle = value; end
def mirror; @sprite.mirror; end
def mirror=(value); @sprite.mirror = value; end
def bush_depth; @sprite.bush_depth; end
def bush_depth=(value); @sprite.bush_depth = value; end
def opacity; @sprite.opacity; end
def opacity=(value); @sprite.opacity = value; end
def blend_type; @sprite.blend_type; end
def blend_type=(value); @sprite.blend_type = value; end
def color; @sprite.color; end
def color=(value); @sprite.color = value; end
def tone; @sprite.tone; end
def tone=(value); @sprite.tone = value; end
def viewport=(value)
return if self.viewport==value
bitmap = @sprite.bitmap
src_rect = @sprite.src_rect
visible = @sprite.visible
x = @sprite.x
y = @sprite.y
z = @sprite.z
ox = @sprite.ox
oy = @sprite.oy
zoom_x = @sprite.zoom_x
zoom_y = @sprite.zoom_y
angle = @sprite.angle
mirror = @sprite.mirror
bush_depth = @sprite.bush_depth
opacity = @sprite.opacity
blend_type = @sprite.blend_type
color = @sprite.color
tone = @sprite.tone
@sprite.dispose
@sprite = Sprite.new(value)
@sprite.bitmap = bitmap
@sprite.src_rect = src_rect
@sprite.visible = visible
@sprite.x = x
@sprite.y = y
@sprite.z = z
@sprite.ox = ox
@sprite.oy = oy
@sprite.zoom_x = zoom_x
@sprite.zoom_y = zoom_y
@sprite.angle = angle
@sprite.mirror = mirror
@sprite.bush_depth = bush_depth
@sprite.opacity = opacity
@sprite.blend_type = blend_type
@sprite.color = color
@sprite.tone = tone
end
end
#===============================================================================
# Sprite class that maintains a bitmap of its own.
# This bitmap can't be changed to a different one.
#===============================================================================
class BitmapSprite < SpriteWrapper
def initialize(width,height,viewport=nil)
super(viewport)
self.bitmap=Bitmap.new(width,height)
@initialized=true
end
def bitmap=(value)
super(value) if !@initialized
end
def dispose
self.bitmap.dispose if !self.disposed?
super
end
end
#===============================================================================
#
#===============================================================================
class AnimatedSprite < SpriteWrapper
attr_reader :frame
attr_reader :framewidth
attr_reader :frameheight
attr_reader :framecount
attr_reader :animname
def initializeLong(animname,framecount,framewidth,frameheight,frameskip)
@animname=pbBitmapName(animname)
@realframes=0
@frameskip=[1,frameskip].max
@frameskip *= Graphics.frame_rate/20
raise _INTL("Frame width is 0") if framewidth==0
raise _INTL("Frame height is 0") if frameheight==0
begin
@animbitmap=AnimatedBitmap.new(animname).deanimate
rescue
@animbitmap=Bitmap.new(framewidth,frameheight)
end
if @animbitmap.width%framewidth!=0
raise _INTL("Bitmap's width ({1}) is not a multiple of frame width ({2}) [Bitmap={3}]",
@animbitmap.width,framewidth,animname)
end
if @animbitmap.height%frameheight!=0
raise _INTL("Bitmap's height ({1}) is not a multiple of frame height ({2}) [Bitmap={3}]",
@animbitmap.height,frameheight,animname)
end
@framecount=framecount
@framewidth=framewidth
@frameheight=frameheight
@framesperrow=@animbitmap.width/@framewidth
@playing=false
self.bitmap=@animbitmap
self.src_rect.width=@framewidth
self.src_rect.height=@frameheight
self.frame=0
end
# Shorter version of AnimationSprite. All frames are placed on a single row
# of the bitmap, so that the width and height need not be defined beforehand
def initializeShort(animname,framecount,frameskip)
@animname=pbBitmapName(animname)
@realframes=0
@frameskip=[1,frameskip].max
@frameskip *= Graphics.frame_rate/20
begin
@animbitmap=AnimatedBitmap.new(animname).deanimate
rescue
@animbitmap=Bitmap.new(framecount*4,32)
end
if @animbitmap.width%framecount!=0
raise _INTL("Bitmap's width ({1}) is not a multiple of frame count ({2}) [Bitmap={3}]",
@animbitmap.width,framewidth,animname)
end
@framecount=framecount
@framewidth=@animbitmap.width/@framecount
@frameheight=@animbitmap.height
@framesperrow=framecount
@playing=false
self.bitmap=@animbitmap
self.src_rect.width=@framewidth
self.src_rect.height=@frameheight
self.frame=0
end
def initialize(*args)
if args.length==1
super(args[0][3])
initializeShort(args[0][0],args[0][1],args[0][2])
else
super(args[5])
initializeLong(args[0],args[1],args[2],args[3],args[4])
end
end
def self.create(animname,framecount,frameskip,viewport=nil)
return self.new([animname,framecount,frameskip,viewport])
end
def dispose
return if disposed?
@animbitmap.dispose
@animbitmap=nil
super
end
def playing?
return @playing
end
def frame=(value)
@frame=value
@realframes=0
self.src_rect.x=@frame%@framesperrow*@framewidth
self.src_rect.y=@frame/@framesperrow*@frameheight
end
def start
@playing=true
@realframes=0
end
alias play start
def stop
@playing=false
end
def update
super
if @playing
@realframes+=1
if @realframes==@frameskip
@realframes=0
self.frame+=1
self.frame%=self.framecount
end
end
end
end
#===============================================================================
# Displays an icon bitmap in a sprite. Supports animated images.
#===============================================================================
class IconSprite < SpriteWrapper
attr_reader :name
def initialize(*args)
if args.length==0
super(nil)
self.bitmap=nil
elsif args.length==1
super(args[0])
self.bitmap=nil
elsif args.length==2
super(nil)
self.x=args[0]
self.y=args[1]
else
super(args[2])
self.x=args[0]
self.y=args[1]
end
@name=""
@_iconbitmap=nil
end
def dispose
clearBitmaps()
super
end
# Sets the icon's filename. Alias for setBitmap.
def name=(value)
setBitmap(value)
end
# Sets the icon's filename.
def setBitmap(file,hue=0)
oldrc=self.src_rect
clearBitmaps()
@name=file
return if file==nil
if file!=""
@_iconbitmap=AnimatedBitmap.new(file,hue)
# for compatibility
self.bitmap=@_iconbitmap ? @_iconbitmap.bitmap : nil
self.src_rect=oldrc
else
@_iconbitmap=nil
end
end
def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap=nil
self.bitmap=nil if !self.disposed?
end
def update
super
return if !@_iconbitmap
@_iconbitmap.update
if self.bitmap!=@_iconbitmap.bitmap
oldrc=self.src_rect
self.bitmap=@_iconbitmap.bitmap
self.src_rect=oldrc
end
end
end
#===============================================================================
# Old GifSprite class, retained for compatibility
#===============================================================================
class GifSprite < IconSprite
def initialize(path)
super(0,0)
setBitmap(path)
end
end
#===============================================================================
# SpriteWrapper that stores multiple bitmaps, and displays only one at once.
#===============================================================================
class ChangelingSprite < SpriteWrapper
def initialize(x=0,y=0,viewport=nil)
super(viewport)
self.x = x
self.y = y
@bitmaps = {}
@currentBitmap = nil
end
def addBitmap(key,path)
@bitmaps[key].dispose if @bitmaps[key]
@bitmaps[key] = AnimatedBitmap.new(path)
end
def changeBitmap(key)
@currentBitmap = @bitmaps[key]
self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil
end
def dispose
return if disposed?
for bm in @bitmaps.values; bm.dispose; end
@bitmaps.clear
super
end
def update
return if disposed?
for bm in @bitmaps.values; bm.update; end
self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil
end
end
@@ -0,0 +1,363 @@
module GifLibrary
@@loadlib = Win32API.new("Kernel32.dll","LoadLibrary",'p','')
if safeExists?("gif.dll")
PngDll = @@loadlib.call("gif.dll")
GifToPngFiles = Win32API.new("gif.dll","GifToPngFiles",'pp','l')
GifToPngFilesInMemory = Win32API.new("gif.dll","GifToPngFilesInMemory",'plp','l')
CopyDataString = Win32API.new("gif.dll","CopyDataString",'lpl','l')
FreeDataString = Win32API.new("gif.dll","FreeDataString",'l','')
else
PngDll=nil
end
def self.getDataFromResult(result)
datasize=CopyDataString.call(result,"",0)
ret=nil
if datasize!=0
data="0"*datasize
CopyDataString.call(result,data,datasize)
ret=data.unpack("V*")
end
FreeDataString.call(result)
return ret
end
end
class AnimatedBitmap
def initialize(file,hue=0)
if file==nil
raise "Filename is nil (missing graphic)\r\n\r\n"+
"If you see this error in the Continue/New Game screen, you may be loading another game's save file. "+
"Check your project's title (\"Game > Change Title...\" in RMXP).\r\n"
end
if file.split(/[\\\/]/)[-1][/^\[\d+(?:,\d+)?]/] # Starts with 1 or more digits in square brackets
@bitmap = PngAnimatedBitmap.new(file,hue)
else
@bitmap = GifBitmap.new(file,hue)
end
end
def [](index); @bitmap[index]; end
def width; @bitmap.bitmap.width; end
def height; @bitmap.bitmap.height; end
def length; @bitmap.length; end
def each; @bitmap.each { |item| yield item }; end
def bitmap; @bitmap.bitmap; end
def currentIndex; @bitmap.currentIndex; end
def frameDelay; @bitmap.frameDelay; end
def totalFrames; @bitmap.totalFrames; end
def disposed?; @bitmap.disposed?; end
def update; @bitmap.update; end
def dispose; @bitmap.dispose; end
def deanimate; @bitmap.deanimate; end
def copy; @bitmap.copy; end
end
class PngAnimatedBitmap
# Creates an animated bitmap from a PNG file.
def initialize(file,hue=0)
@frames=[]
@currentFrame=0
@framecount=0
panorama=BitmapCache.load_bitmap(file,hue)
if file.split(/[\\\/]/)[-1][/^\[(\d+)(?:,(\d+))?]/] # Starts with 1 or more digits in brackets
# File has a frame count
numFrames = $1.to_i
delay = $2.to_i
delay = 10 if delay == 0
raise "Invalid frame count in #{file}" if numFrames<=0
raise "Invalid frame delay in #{file}" if delay<=0
if panorama.width % numFrames != 0
raise "Bitmap's width (#{panorama.width}) is not divisible by frame count: #{file}"
end
@frameDelay = delay
subWidth=panorama.width/numFrames
for i in 0...numFrames
subBitmap=BitmapWrapper.new(subWidth,panorama.height)
subBitmap.blt(0,0,panorama,Rect.new(subWidth*i,0,subWidth,panorama.height))
@frames.push(subBitmap)
end
panorama.dispose
else
@frames=[panorama]
end
end
def [](index)
return @frames[index]
end
def width; self.bitmap.width; end
def height; self.bitmap.height; end
def deanimate
for i in 1...@frames.length
@frames[i].dispose
end
@frames=[@frames[0]]
@currentFrame=0
return @frames[0]
end
def bitmap
@frames[@currentFrame]
end
def currentIndex
@currentFrame
end
def frameDelay(_index)
return @frameDelay
end
def length
@frames.length
end
def each
@frames.each { |item| yield item}
end
def totalFrames
@frameDelay*@frames.length
end
def disposed?
@disposed
end
def update
return if disposed?
if @frames.length>1
@framecount+=1
if @framecount>=@frameDelay
@framecount=0
@currentFrame+=1
@currentFrame%=@frames.length
end
end
end
def dispose
if !@disposed
for i in @frames
i.dispose
end
end
@disposed=true
end
attr_accessor :frames # internal
def copy
x=self.clone
x.frames=x.frames.clone
for i in 0...x.frames.length
x.frames[i]=x.frames[i].copy
end
return x
end
end
#internal class
class GifBitmap
# Creates a bitmap from a GIF file with the specified
# optional viewport. Can also load non-animated bitmaps.
def initialize(file,hue=0)
@gifbitmaps=[]
@gifdelays=[]
@totalframes=0
@framecount=0
@currentIndex=0
@disposed=false
bitmap=nil
filestring=nil
filestrName=nil
file="" if !file
file=canonicalize(file)
begin
bitmap=BitmapCache.load_bitmap(file,hue)
rescue
bitmap=nil
end
if !bitmap || (bitmap.width==32 && bitmap.height==32)
if !file || file.length<1 || file[file.length-1]!=0x2F
if (filestring=pbGetFileChar(file))
filestrName=file
elsif (filestring=pbGetFileChar(file+".gif"))
filestrName=file+".gif"
elsif (filestring=pbGetFileChar(file+".png"))
filestrName=file+".png"
elsif (filestring=pbGetFileChar(file+".jpg"))
filestrName=file+".jpg"
elsif (filestring=pbGetFileChar(file+".bmp"))
filestrName=file+".bmp"
end
end
end
if bitmap && filestring && filestring[0]==0x47 &&
bitmap.width==32 && bitmap.height==32
#File.open("debug.txt","ab") { |f| f.puts("rejecting bitmap") }
bitmap.dispose
bitmap=nil
end
if bitmap
#File.open("debug.txt","ab") { |f| f.puts("reusing bitmap") }
# Have a regular non-animated bitmap
@totalframes=1
@framecount=0
@gifbitmaps=[bitmap]
@gifdelays=[1]
else
tmpBase=File.basename(file)+"_tmp_"
filestring=pbGetFileString(filestrName) if filestring
Dir.chdir(ENV["TEMP"]) { # navigate to temp folder since game might be on a CD-ROM
if filestring && filestring[0]==0x47 && GifLibrary::PngDll
result=GifLibrary::GifToPngFilesInMemory.call(filestring,
filestring.length,tmpBase)
else
result=0
end
if result>0
@gifdelays=GifLibrary.getDataFromResult(result)
@totalframes=@gifdelays.pop
for i in 0...@gifdelays.length
@gifdelays[i]=[@gifdelays[i],1].max
bmfile=sprintf("%s%d.png",tmpBase,i)
if safeExists?(bmfile)
gifbitmap=BitmapWrapper.new(bmfile)
@gifbitmaps.push(gifbitmap)
bmfile.hue_change(hue) if hue!=0
if hue==0 && @gifdelays.length==1
BitmapCache.setKey(file,gifbitmap)
end
File.delete(bmfile)
else
@gifbitmaps.push(BitmapWrapper.new(32,32))
end
end
end
}
if @gifbitmaps.length==0
@gifbitmaps=[BitmapWrapper.new(32,32)]
@gifdelays=[1]
end
if @gifbitmaps.length==1
BitmapCache.setKey(file,@gifbitmaps[0])
end
end
end
def [](index)
return @gifbitmaps[index]
end
def deanimate
for i in 1...@gifbitmaps.length
@gifbitmaps[i].dispose
end
@gifbitmaps=[@gifbitmaps[0]]
@currentIndex=0
return @gifbitmaps[0]
end
def bitmap
@gifbitmaps[@currentIndex]
end
def currentIndex
@currentIndex
end
def frameDelay(index)
return @gifdelay[index]/2 # Due to frame count being incremented by 2
end
def length
@gifbitmaps.length
end
def each
@gifbitmaps.each { |item| yield item }
end
def totalFrames
@totalframes/2 # Due to frame count being incremented by 2
end
def disposed?
@disposed
end
def width
@gifbitmaps.length==0 ? 0 : @gifbitmaps[0].width
end
def height
@gifbitmaps.length==0 ? 0 : @gifbitmaps[0].height
end
# This function must be called in order to animate the GIF image.
def update
return if disposed?
if @gifbitmaps.length>0
@framecount+=2
@framecount=@totalframes<=0 ? 0 : @framecount%@totalframes
frametoshow=0
for i in 0...@gifdelays.length
frametoshow=i if @gifdelays[i]<=@framecount
end
@currentIndex=frametoshow
end
end
def dispose
if !@disposed
for i in @gifbitmaps
i.dispose
end
end
@disposed=true
end
attr_accessor :gifbitmaps # internal
attr_accessor :gifdelays # internal
def copy
x=self.clone
x.gifbitmaps=x.gifbitmaps.clone
x.gifdelays=x.gifdelays.clone
for i in 0...x.gifbitmaps.length
x.gifbitmaps[i]=x.gifbitmaps[i].copy
end
return x
end
end
def pbGetTileBitmap(filename, tile_id, hue)
return BitmapCache.tileEx(filename, tile_id, hue) { |f|
AnimatedBitmap.new("Graphics/Tilesets/"+filename).deanimate
}
end
def pbGetTileset(name,hue=0)
return AnimatedBitmap.new("Graphics/Tilesets/"+name,hue).deanimate
end
def pbGetAutotile(name,hue=0)
return AnimatedBitmap.new("Graphics/Autotiles/"+name,hue).deanimate
end
def pbGetAnimation(name,hue=0)
return AnimatedBitmap.new("Graphics/Animations/"+name,hue).deanimate
end
@@ -0,0 +1,232 @@
#===============================================================================
#
#===============================================================================
class Plane
def update; end
def refresh; end
end
#===============================================================================
# This class works around a limitation that planes are always
# 640 by 480 pixels in size regardless of the window's size.
#===============================================================================
class LargePlane < Plane
attr_accessor :borderX
attr_accessor :borderY
def initialize(viewport=nil)
@__sprite=Sprite.new(viewport)
@__disposed=false
@__ox=0
@__oy=0
@__bitmap=nil
@__visible=true
@__sprite.visible=false
@borderX=0
@borderY=0
end
def disposed?
return @__disposed
end
def dispose
if !@__disposed
@__sprite.bitmap.dispose if @__sprite.bitmap
@__sprite.dispose
@__sprite=nil
@__bitmap=nil
@__disposed=true
end
super
end
def ox; @__ox; end
def oy; @__oy; end
def ox=(value);
return if @__ox==value
@__ox = value
refresh
end
def oy=(value);
return if @__oy==value
@__oy = value
refresh
end
def bitmap
return @__bitmap
end
def bitmap=(value)
if value==nil
if @__bitmap!=nil
@__bitmap=nil
@__sprite.visible=(@__visible && !@__bitmap.nil?)
end
elsif @__bitmap!=value && !value.disposed?
@__bitmap=value
refresh
elsif value.disposed?
if @__bitmap!=nil
@__bitmap=nil
@__sprite.visible=(@__visible && !@__bitmap.nil?)
end
end
end
def viewport; @__sprite.viewport; end
def zoom_x; @__sprite.zoom_x; end
def zoom_y; @__sprite.zoom_y; end
def opacity; @__sprite.opacity; end
def blend_type; @__sprite.blend_type; end
def visible; @__visible; end
def z; @__sprite.z; end
def color; @__sprite.color; end
def tone; @__sprite.tone; end
def zoom_x=(v);
return if @__sprite.zoom_x==v
@__sprite.zoom_x = v
refresh
end
def zoom_y=(v);
return if @__sprite.zoom_y==v
@__sprite.zoom_y = v
refresh
end
def opacity=(v); @__sprite.opacity=(v); end
def blend_type=(v); @__sprite.blend_type=(v); end
def visible=(v); @__visible=v; @__sprite.visible=(@__visible && !@__bitmap.nil?); end
def z=(v); @__sprite.z=(v); end
def color=(v); @__sprite.color=(v); end
def tone=(v); @__sprite.tone=(v); end
def update; ;end
def refresh
@__sprite.visible = (@__visible && !@__bitmap.nil?)
if @__bitmap
if !@__bitmap.disposed?
@__ox += @__bitmap.width*@__sprite.zoom_x if @__ox<0
@__oy += @__bitmap.height*@__sprite.zoom_y if @__oy<0
@__ox -= @__bitmap.width*@__sprite.zoom_x if @__ox>@__bitmap.width
@__oy -= @__bitmap.height*@__sprite.zoom_y if @__oy>@__bitmap.height
dwidth = (Graphics.width/@__sprite.zoom_x+@borderX).to_i # +2
dheight = (Graphics.height/@__sprite.zoom_y+@borderY).to_i # +2
@__sprite.bitmap = ensureBitmap(@__sprite.bitmap,dwidth,dheight)
@__sprite.bitmap.clear
tileBitmap(@__sprite.bitmap,@__bitmap,@__bitmap.rect)
else
@__sprite.visible = false
end
end
end
private
def ensureBitmap(bitmap,dwidth,dheight)
if !bitmap || bitmap.disposed? || bitmap.width<dwidth || bitmap.height<dheight
bitmap.dispose if bitmap
bitmap = Bitmap.new([1,dwidth].max,[1,dheight].max)
end
return bitmap
end
def tileBitmap(dstbitmap,srcbitmap,srcrect)
return if !srcbitmap || srcbitmap.disposed?
dstrect = dstbitmap.rect
left = (dstrect.x-@__ox/@__sprite.zoom_x).to_i
top = (dstrect.y-@__oy/@__sprite.zoom_y).to_i
while left>0; left -= srcbitmap.width; end
while top>0; top -= srcbitmap.height; end
y = top
while y<dstrect.height
x = left
while x<dstrect.width
dstbitmap.blt(x+@borderX,y+@borderY,srcbitmap,srcrect)
x += srcrect.width
end
y += srcrect.height
end
end
end
#===============================================================================
# A plane class that displays a single color.
#===============================================================================
class ColoredPlane < LargePlane
def initialize(color,viewport=nil)
super(viewport)
self.bitmap=Bitmap.new(32,32)
setPlaneColor(color)
end
def dispose
self.bitmap.dispose if self.bitmap
super
end
def update; super; end
def setPlaneColor(value)
self.bitmap.fill_rect(0,0,self.bitmap.width,self.bitmap.height,value)
self.refresh
end
end
#===============================================================================
# A plane class that supports animated images.
#===============================================================================
class AnimatedPlane < LargePlane
def initialize(viewport)
super(viewport)
@bitmap=nil
end
def dispose
clearBitmaps()
super
end
def update
super
if @bitmap
@bitmap.update
self.bitmap=@bitmap.bitmap
end
end
def clearBitmaps
@bitmap.dispose if @bitmap
@bitmap=nil
self.bitmap=nil if !self.disposed?
end
def setPanorama(file, hue=0)
clearBitmaps()
return if file==nil
@bitmap=AnimatedBitmap.new("Graphics/Panoramas/"+file,hue)
end
def setFog(file, hue=0)
clearBitmaps()
return if file==nil
@bitmap=AnimatedBitmap.new("Graphics/Fogs/"+file,hue)
end
def setBitmap(file, hue=0)
clearBitmaps()
return if file==nil
@bitmap=AnimatedBitmap.new(file,hue)
end
end
@@ -921,6 +921,15 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
text.gsub!(/\\pog/i,"") text.gsub!(/\\pog/i,"")
text.gsub!(/\\b/i,"<c3=3050C8,D0D0C8>") text.gsub!(/\\b/i,"<c3=3050C8,D0D0C8>")
text.gsub!(/\\r/i,"<c3=E00808,D0D0C8>") text.gsub!(/\\r/i,"<c3=E00808,D0D0C8>")
text.gsub!(/\\[Ww]\[([^\]]*)\]/) {
w = $1.to_s
if w==""
msgwindow.windowskin = nil
else
msgwindow.setSkin("Graphics/Windowskins/#{w}",false)
end
next ""
}
isDarkSkin = isDarkWindowskin(msgwindow.windowskin) isDarkSkin = isDarkWindowskin(msgwindow.windowskin)
text.gsub!(/\\[Cc]\[([0-9]+)\]/) { text.gsub!(/\\[Cc]\[([0-9]+)\]/) {
m = $1.to_i m = $1.to_i
@@ -951,7 +960,7 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
### Controls ### Controls
textchunks=[] textchunks=[]
controls=[] controls=[]
while text[/(?:\\(w|f|ff|ts|cl|me|se|wt|wtnp|ch)\[([^\]]*)\]|\\(g|cn|wd|wm|op|cl|wu|\.|\||\!|\^))/i] while text[/(?:\\(f|ff|ts|cl|me|se|wt|wtnp|ch)\[([^\]]*)\]|\\(g|cn|wd|wm|op|cl|wu|\.|\||\!|\^))/i]
textchunks.push($~.pre_match) textchunks.push($~.pre_match)
if $~[1] if $~[1]
controls.push([$~[1].downcase,$~[2],-1]) controls.push([$~[1].downcase,$~[2],-1])
@@ -1086,12 +1095,6 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
msgback.y = msgwindow.y if msgback msgback.y = msgwindow.y if msgback
pbPositionNearMsgWindow(facewindow,msgwindow,:left) pbPositionNearMsgWindow(facewindow,msgwindow,:left)
msgwindow.y = Graphics.height-msgwindow.height*(signWaitTime-signWaitCount)/signWaitTime msgwindow.y = Graphics.height-msgwindow.height*(signWaitTime-signWaitCount)/signWaitTime
when "w" # Change windowskin
if param==""
msgwindow.windowskin = nil
else
msgwindow.setSkin("Graphics/Windowskins/#{param}",false)
end
when "ts" # Change text speed when "ts" # Change text speed
msgwindow.textspeed = (param=="") ? -999 : param.to_i msgwindow.textspeed = (param=="") ? -999 : param.to_i
when "." # Wait 0.25 seconds when "." # Wait 0.25 seconds
@@ -117,7 +117,7 @@ class PictureEx
end end
def callback(cb) def callback(cb)
if cb.is_a?(Proc); proc.call(self) if cb.is_a?(Proc); cb.call(self)
elsif cb.is_a?(Array); cb[0].method(cb[1]).call(self) elsif cb.is_a?(Array); cb[0].method(cb[1]).call(self)
elsif cb.is_a?(Method); cb.call(self) elsif cb.is_a?(Method); cb.call(self)
end end
@@ -28,6 +28,7 @@ begin
names[EVASION] = _INTL("evasiveness") names[EVASION] = _INTL("evasiveness")
return names[id] return names[id]
end end
def self.getNameBrief(id) def self.getNameBrief(id)
id = getID(PBStats,id) id = getID(PBStats,id)
names = [] names = []
@@ -41,6 +42,7 @@ begin
names[EVASION] = _INTL("eva") names[EVASION] = _INTL("eva")
return names[id] return names[id]
end end
def self.eachStat def self.eachStat
[HP,ATTACK,DEFENSE,SPATK,SPDEF,SPEED].each { |s| yield s } [HP,ATTACK,DEFENSE,SPATK,SPDEF,SPEED].each { |s| yield s }
end end
@@ -220,7 +220,7 @@ class PokeBattle_Battler
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2] stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
stage = @stages[PBStats::SPEED] + 6 stage = @stages[PBStats::SPEED] + 6
speed = @speed*stageMul[stage]/stageDiv[stage] speed = @speed*stageMul[stage]/stageDiv[stage]
speedMult = 0x1000 speedMult = 1.0
# Ability effects that alter calculated Speed # Ability effects that alter calculated Speed
if abilityActive? if abilityActive?
speedMult = BattleHandlers.triggerSpeedCalcAbility(@ability,self,speedMult) speedMult = BattleHandlers.triggerSpeedCalcAbility(@ability,self,speedMult)
@@ -242,7 +242,7 @@ class PokeBattle_Battler
speedMult *= 1.1 speedMult *= 1.1
end end
# Calculation # Calculation
return [(speed.to_f*speedMult/0x1000).round,1].max return [(speed*speedMult).round,1].max
end end
def pbWeight def pbWeight
@@ -65,6 +65,7 @@ class PokeBattle_Battler
def pbInitialize(pkmn,idxParty,batonPass=false) def pbInitialize(pkmn,idxParty,batonPass=false)
pbInitPokemon(pkmn,idxParty) pbInitPokemon(pkmn,idxParty)
pbInitEffects(batonPass) pbInitEffects(batonPass)
@damageState.reset
end end
def pbInitPokemon(pkmn,idxParty) def pbInitPokemon(pkmn,idxParty)
@@ -138,7 +139,6 @@ class PokeBattle_Battler
@effects[PBEffects::Substitute] = 0 @effects[PBEffects::Substitute] = 0
@effects[PBEffects::Telekinesis] = 0 @effects[PBEffects::Telekinesis] = 0
end end
@damageState.reset
@fainted = (@hp==0) @fainted = (@hp==0)
@initialHP = 0 @initialHP = 0
@lastAttacker = [] @lastAttacker = []
@@ -302,7 +302,7 @@ class PokeBattle_Battler
end end
end end
# Used only to erase the battler of a Shadow Pokémon that has been snagged. # Used to erase the battler of a Pokémon that has been caught.
def pbReset def pbReset
@pokemon = nil @pokemon = nil
@pokemonIndex = -1 @pokemonIndex = -1
@@ -171,7 +171,7 @@ class PokeBattle_Battler
return true return true
end end
def pbCanSynchronizeStatus?(status,target) def pbCanSynchronizeStatus?(newStatus,target)
return false if fainted? return false if fainted?
# Trying to replace a status problem with another one # Trying to replace a status problem with another one
return false if self.status!=PBStatuses::NONE return false if self.status!=PBStatuses::NONE
@@ -179,7 +179,7 @@ class PokeBattle_Battler
return false if @battle.field.terrain==PBBattleTerrains::Misty && affectedByTerrain? return false if @battle.field.terrain==PBBattleTerrains::Misty && affectedByTerrain?
# Type immunities # Type immunities
hasImmuneType = false hasImmuneType = false
case self.status case newStatus
when PBStatuses::POISON when PBStatuses::POISON
# NOTE: target will have Synchronize, so it can't have Corrosion. # NOTE: target will have Synchronize, so it can't have Corrosion.
if !(target && target.hasActiveAbility?(:CORROSION)) if !(target && target.hasActiveAbility?(:CORROSION))
@@ -193,15 +193,15 @@ class PokeBattle_Battler
end end
return false if hasImmuneType return false if hasImmuneType
# Ability immunity # Ability immunity
if BattleHandlers.triggerStatusImmunityAbilityNonIgnorable(@ability,self,status) if BattleHandlers.triggerStatusImmunityAbilityNonIgnorable(@ability,self,newStatus)
return false return false
end end
if abilityActive? && BattleHandlers.triggerStatusImmunityAbility(@ability,self,status) if abilityActive? && BattleHandlers.triggerStatusImmunityAbility(@ability,self,newStatus)
return false return false
end end
eachAlly do |b| eachAlly do |b|
next if !b.abilityActive? next if !b.abilityActive?
next if !BattleHandlers.triggerStatusImmunityAllyAbility(b.ability,self,status) next if !BattleHandlers.triggerStatusImmunityAllyAbility(b.ability,self,newStatus)
return false return false
end end
# Safeguard immunity # Safeguard immunity
@@ -8,7 +8,8 @@ class PokeBattle_Battler
if tryFlee && @battle.wildBattle? && opposes? && if tryFlee && @battle.wildBattle? && opposes? &&
@battle.rules["alwaysflee"] && @battle.pbCanRun?(@index) @battle.rules["alwaysflee"] && @battle.pbCanRun?(@index)
pbBeginTurn(choice) pbBeginTurn(choice)
@battle.pbDisplay(_INTL("{1} fled from battle!",pbThis)) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
@battle.pbDisplay(_INTL("{1} fled from battle!",pbThis))
@battle.decision = 3 @battle.decision = 3
pbEndTurn(choice) pbEndTurn(choice)
return true return true
@@ -323,7 +324,7 @@ class PokeBattle_Battler
@battle.pbDisplay(_INTL("When the flame touched the powder on the Pokémon, it exploded!")) @battle.pbDisplay(_INTL("When the flame touched the powder on the Pokémon, it exploded!"))
user.lastMoveFailed = true user.lastMoveFailed = true
w = @battle.pbWeather w = @battle.pbWeather
if w!=PBWeather.RAINDANCE && w!=PBWeather.HEAVYRAIN && user.takesIndirectDamage? if w!=PBWeather::Rain && w!=PBWeather::HeavyRain && user.takesIndirectDamage?
oldHP = user.hp oldHP = user.hp
user.pbReduceHP((user.totalhp/4.0).round,false) user.pbReduceHP((user.totalhp/4.0).round,false)
user.pbFaint if user.fainted? user.pbFaint if user.fainted?
@@ -95,8 +95,8 @@ class PokeBattle_Move
modifiers[BASE_ACC] = baseAcc modifiers[BASE_ACC] = baseAcc
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY] modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION] modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 0x1000 modifiers[ACC_MULT] = 1.0
modifiers[EVA_MULT] = 0x1000 modifiers[EVA_MULT] = 1.0
pbCalcAccuracyModifiers(user,target,modifiers) pbCalcAccuracyModifiers(user,target,modifiers)
# Check if move can't miss # Check if move can't miss
return true if modifiers[BASE_ACC]==0 return true if modifiers[BASE_ACC]==0
@@ -107,8 +107,8 @@ class PokeBattle_Move
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3] stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage] accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage] evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[ACC_MULT] / 0x1000).round accuracy = (accuracy * modifiers[ACC_MULT]).round
evasion = (evasion * modifiers[EVA_MULT] / 0x1000).round evasion = (evasion * modifiers[EVA_MULT]).round
evasion = 1 if evasion<1 evasion = 1 if evasion<1
# Calculation # Calculation
return @battle.pbRandom(100) < modifiers[BASE_ACC] * accuracy / evasion return @battle.pbRandom(100) < modifiers[BASE_ACC] * accuracy / evasion
@@ -140,11 +140,11 @@ class PokeBattle_Move
end end
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values # Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
if @battle.field.effects[PBEffects::Gravity]>0 if @battle.field.effects[PBEffects::Gravity]>0
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*5/3).round modifiers[ACC_MULT] *= 5/3.0
end end
if user.effects[PBEffects::MicleBerry] if user.effects[PBEffects::MicleBerry]
user.effects[PBEffects::MicleBerry] = false user.effects[PBEffects::MicleBerry] = false
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*1.2).round modifiers[ACC_MULT] *= 1.2
end end
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0 modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE]>0 modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE]>0
@@ -244,14 +244,14 @@ class PokeBattle_Move
defense = (defense.to_f*stageMul[defStage]/stageDiv[defStage]).floor defense = (defense.to_f*stageMul[defStage]/stageDiv[defStage]).floor
end end
# Calculate all multiplier effects # Calculate all multiplier effects
multipliers = [0x1000,0x1000,0x1000,0x1000] multipliers = [1.0, 1.0, 1.0, 1.0]
pbCalcDamageMultipliers(user,target,numTargets,type,baseDmg,multipliers) pbCalcDamageMultipliers(user,target,numTargets,type,baseDmg,multipliers)
# Main damage calculation # Main damage calculation
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT] / 0x1000).round,1].max baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
atk = [(atk * multipliers[ATK_MULT] / 0x1000).round,1].max atk = [(atk * multipliers[ATK_MULT]).round, 1].max
defense = [(defense * multipliers[DEF_MULT] / 0x1000).round,1].max defense = [(defense * multipliers[DEF_MULT]).round, 1].max
damage = (((2.0*user.level/5+2).floor*baseDmg*atk/defense).floor/50).floor+2 damage = (((2.0 * user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
damage = [(damage * multipliers[FINAL_DMG_MULT] / 0x1000).round,1].max damage = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
target.damageState.calcDamage = damage target.damageState.calcDamage = damage
end end
@@ -306,10 +306,10 @@ class PokeBattle_Move
end end
# Other # Other
if user.effects[PBEffects::MeFirst] if user.effects[PBEffects::MeFirst]
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round multipliers[BASE_DMG_MULT] *= 1.5
end end
if user.effects[PBEffects::HelpingHand] && !self.is_a?(PokeBattle_Confusion) if user.effects[PBEffects::HelpingHand] && !self.is_a?(PokeBattle_Confusion)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round multipliers[BASE_DMG_MULT] *= 1.5
end end
if user.effects[PBEffects::Charge]>0 && isConst?(type,PBTypes,:ELECTRIC) if user.effects[PBEffects::Charge]>0 && isConst?(type,PBTypes,:ELECTRIC)
multipliers[BASE_DMG_MULT] *= 2 multipliers[BASE_DMG_MULT] *= 2
@@ -341,15 +341,15 @@ class PokeBattle_Move
case @battle.field.terrain case @battle.field.terrain
when PBBattleTerrains::Electric when PBBattleTerrains::Electric
if isConst?(type,PBTypes,:ELECTRIC) if isConst?(type,PBTypes,:ELECTRIC)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round multipliers[BASE_DMG_MULT] *= 1.5
end end
when PBBattleTerrains::Grassy when PBBattleTerrains::Grassy
if isConst?(type,PBTypes,:GRASS) if isConst?(type,PBTypes,:GRASS)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round multipliers[BASE_DMG_MULT] *= 1.5
end end
when PBBattleTerrains::Psychic when PBBattleTerrains::Psychic
if isConst?(type,PBTypes,:PSYCHIC) if isConst?(type,PBTypes,:PSYCHIC)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round multipliers[BASE_DMG_MULT] *= 1.5
end end
end end
end end
@@ -361,28 +361,28 @@ class PokeBattle_Move
if @battle.internalBattle if @battle.internalBattle
if user.pbOwnedByPlayer? if user.pbOwnedByPlayer?
if physicalMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_ATTACK if physicalMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_ATTACK
multipliers[ATK_MULT] = (multipliers[ATK_MULT]*1.1).round multipliers[ATK_MULT] *= 1.1
elsif specialMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPATK elsif specialMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPATK
multipliers[ATK_MULT] = (multipliers[ATK_MULT]*1.1).round multipliers[ATK_MULT] *= 1.1
end end
end end
if target.pbOwnedByPlayer? if target.pbOwnedByPlayer?
if physicalMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE if physicalMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.1).round multipliers[DEF_MULT] *= 1.1
elsif specialMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF elsif specialMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.1).round multipliers[DEF_MULT] *= 1.1
end end
end end
end end
# Multi-targeting attacks # Multi-targeting attacks
if numTargets>1 if numTargets>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*0.75).round multipliers[FINAL_DMG_MULT] *= 0.75
end end
# Weather # Weather
case @battle.pbWeather case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun when PBWeather::Sun, PBWeather::HarshSun
if isConst?(type,PBTypes,:FIRE) if isConst?(type,PBTypes,:FIRE)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round multipliers[FINAL_DMG_MULT] *= 1.5
elsif isConst?(type,PBTypes,:WATER) elsif isConst?(type,PBTypes,:WATER)
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
end end
@@ -390,17 +390,17 @@ class PokeBattle_Move
if isConst?(type,PBTypes,:FIRE) if isConst?(type,PBTypes,:FIRE)
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
elsif isConst?(type,PBTypes,:WATER) elsif isConst?(type,PBTypes,:WATER)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round multipliers[FINAL_DMG_MULT] *= 1.5
end end
when PBWeather::Sandstorm when PBWeather::Sandstorm
if target.pbHasType?(:ROCK) && specialMove? && @function!="122" # Psyshock if target.pbHasType?(:ROCK) && specialMove? && @function!="122" # Psyshock
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.5).round multipliers[DEF_MULT] *= 1.5
end end
end end
# Critical hits # Critical hits
if target.damageState.critical if target.damageState.critical
if NEWEST_BATTLE_MECHANICS if NEWEST_BATTLE_MECHANICS
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round multipliers[FINAL_DMG_MULT] *= 1.5
else else
multipliers[FINAL_DMG_MULT] *= 2 multipliers[FINAL_DMG_MULT] *= 2
end end
@@ -415,12 +415,11 @@ class PokeBattle_Move
if user.hasActiveAbility?(:ADAPTABILITY) if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2 multipliers[FINAL_DMG_MULT] *= 2
else else
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round multipliers[FINAL_DMG_MULT] *= 1.5
end end
end end
# Type effectiveness # Type effectiveness
multipliers[FINAL_DMG_MULT] *= target.damageState.typeMod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE multipliers[FINAL_DMG_MULT] *= target.damageState.typeMod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
multipliers[FINAL_DMG_MULT] = multipliers[FINAL_DMG_MULT].round
# Burn # Burn
if user.status==PBStatuses::BURN && physicalMove? && damageReducedByBurn? && if user.status==PBStatuses::BURN && physicalMove? && damageReducedByBurn? &&
!user.hasActiveAbility?(:GUTS) !user.hasActiveAbility?(:GUTS)
@@ -431,19 +430,19 @@ class PokeBattle_Move
!user.hasActiveAbility?(:INFILTRATOR) !user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
if @battle.pbSideBattlerCount(target)>1 if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round multipliers[FINAL_DMG_MULT] *= 2/3.0
else else
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
end end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && physicalMove? elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && physicalMove?
if @battle.pbSideBattlerCount(target)>1 if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round multipliers[FINAL_DMG_MULT] *= 2/3.0
else else
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
end end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && specialMove? elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && specialMove?
if @battle.pbSideBattlerCount(target)>1 if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round multipliers[FINAL_DMG_MULT] *= 2/3.0
else else
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
end end
@@ -1947,7 +1947,7 @@ class PokeBattle_Move_061 < PokeBattle_Move
def pbEffectAgainstTarget(user,target) def pbEffectAgainstTarget(user,target)
newType = getConst(PBTypes,:WATER) newType = getConst(PBTypes,:WATER)
user.pbChangeTypes(newType) target.pbChangeTypes(newType)
typeName = PBTypes.getName(newType) typeName = PBTypes.getName(newType)
@battle.pbDisplay(_INTL("{1} transformed into the {2} type!",target.pbThis,typeName)) @battle.pbDisplay(_INTL("{1} transformed into the {2} type!",target.pbThis,typeName))
end end
@@ -2465,7 +2465,7 @@ end
class PokeBattle_Move_073 < PokeBattle_FixedDamageMove class PokeBattle_Move_073 < PokeBattle_FixedDamageMove
def pbAddTarget(targets,user) def pbAddTarget(targets,user)
return if user.lastFoeAttacker.length==0 return if user.lastFoeAttacker.length==0
lastAttacker = user.lastFoeAttacker[user.lastFoeAttacker.last] lastAttacker = user.lastFoeAttacker.last
return if lastAttacker<0 || !user.opposes?(lastAttacker) return if lastAttacker<0 || !user.opposes?(lastAttacker)
user.pbAddTarget(targets,user,@battle.battlers[lastAttacker],self,false) user.pbAddTarget(targets,user,@battle.battlers[lastAttacker],self,false)
end end
@@ -2546,7 +2546,7 @@ class PokeBattle_Move_076 < PokeBattle_Move
def pbModifyDamage(damageMult,user,target) def pbModifyDamage(damageMult,user,target)
damageMult *= 2 if target.inTwoTurnAttack?("0CA") # Dig damageMult *= 2 if target.inTwoTurnAttack?("0CA") # Dig
damageMult = (damageMult/2.0).round if @battle.field.terrain==PBBattleTerrains::Grassy damageMult /= 2 if @battle.field.terrain==PBBattleTerrains::Grassy
return damageMult return damageMult
end end
end end
@@ -422,7 +422,7 @@ class PokeBattle_Move_095 < PokeBattle_Move
def pbModifyDamage(damageMult,user,target) def pbModifyDamage(damageMult,user,target)
damageMult *= 2 if target.inTwoTurnAttack?("0CA") # Dig damageMult *= 2 if target.inTwoTurnAttack?("0CA") # Dig
damageMult = (damageMult/2.0).round if @battle.field.terrain==PBBattleTerrains::Grassy damageMult /= 2 if @battle.field.terrain==PBBattleTerrains::Grassy
return damageMult return damageMult
end end
end end
@@ -752,7 +752,7 @@ class PokeBattle_Move_09F < PokeBattle_Move
elsif isConst?(@id,PBMoves,:MULTIATTACK) elsif isConst?(@id,PBMoves,:MULTIATTACK)
@itemTypes = { @itemTypes = {
:FIGHTINGMEMORY => :FIGHTING, :FIGHTINGMEMORY => :FIGHTING,
:SLYINGMEMORY => :FLYING, :FLYINGMEMORY => :FLYING,
:POISONMEMORY => :POISON, :POISONMEMORY => :POISON,
:GROUNDMEMORY => :GROUND, :GROUNDMEMORY => :GROUND,
:ROCKMEMORY => :ROCK, :ROCKMEMORY => :ROCK,
@@ -777,7 +777,7 @@ class PokeBattle_Move_09F < PokeBattle_Move
if user.itemActive? if user.itemActive?
@itemTypes.each do |item, itemType| @itemTypes.each do |item, itemType|
next if !isConst?(user.item,PBItems,item) next if !isConst?(user.item,PBItems,item)
t = hasConst?(PBTypes,itemType) t = getConst(PBTypes,itemType)
ret = t || ret ret = t || ret
break break
end end
@@ -1132,7 +1132,7 @@ class PokeBattle_Move_0AE < PokeBattle_Move
return false return false
end end
def pbEffectGeneral(user) def pbEffectAgainstTarget(user,target)
user.pbUseMoveSimple(target.lastRegularMoveUsed,target.index) user.pbUseMoveSimple(target.lastRegularMoveUsed,target.index)
end end
@@ -2070,9 +2070,7 @@ class PokeBattle_Move_0C4 < PokeBattle_TwoTurnMove
def pbBaseDamageMultiplier(damageMult,user,target) def pbBaseDamageMultiplier(damageMult,user,target)
w = @battle.pbWeather w = @battle.pbWeather
if w>0 && w!=PBWeather::Sun && w!=PBWeather::HarshSun damageMult /= 2 if w>0 && w!=PBWeather::Sun && w!=PBWeather::HarshSun
damageMult = (damageMult/2.0).round
end
return damageMult return damageMult
end end
end end
@@ -2405,18 +2403,19 @@ end
#=============================================================================== #===============================================================================
class PokeBattle_Move_0D3 < PokeBattle_Move class PokeBattle_Move_0D3 < PokeBattle_Move
def pbBaseDamage(baseDmg,user,target) def pbBaseDamage(baseDmg,user,target)
shift = (4-user.effects[PBEffects::Rollout]) # 0-4, where 0 is most powerful shift = (5 - user.effects[PBEffects::Rollout]) # 0-4, where 0 is most powerful
shift = 0 if user.effects[PBEffects::Rollout] == 0 # For first turn
shift += 1 if user.effects[PBEffects::DefenseCurl] shift += 1 if user.effects[PBEffects::DefenseCurl]
baseDmg = baseDmg << shift baseDmg *= 2**shift
return baseDmg return baseDmg
end end
def pbEffectAfterAllHits(user,target) def pbEffectAfterAllHits(user,target)
if !target.damageState.unaffected && user.effects[PBEffects::Rollout]==0 if !target.damageState.unaffected && user.effects[PBEffects::Rollout] == 0
user.effects[PBEffects::Rollout] = 5 user.effects[PBEffects::Rollout] = 5
user.currentMove = @id user.currentMove = @id
end end
user.effects[PBEffects::Rollout] -= 1 if user.effects[PBEffects::Rollout]>0 user.effects[PBEffects::Rollout] -= 1 if user.effects[PBEffects::Rollout] > 0
end end
end end
@@ -3084,7 +3083,7 @@ class PokeBattle_Move_0EC < PokeBattle_Move
switchedBattlers.push(b.index) switchedBattlers.push(b.index)
roarSwitched.push(b.index) roarSwitched.push(b.index)
end end
if roarSwitched>0 if roarSwitched.length>0
@battle.moldBreaker = false if roarSwitched.include?(user.index) @battle.moldBreaker = false if roarSwitched.include?(user.index)
@battle.pbPriority(true).each do |b| @battle.pbPriority(true).each do |b|
b.pbEffectsOnSwitchIn(true) if roarSwitched.include?(b.index) b.pbEffectsOnSwitchIn(true) if roarSwitched.include?(b.index)
@@ -692,9 +692,11 @@ class PokeBattle_Battle
pbDisplay("The mysterious air current has dissipated!") pbDisplay("The mysterious air current has dissipated!")
end end
end end
# Check for form changes caused by the weather changing
if @field.weather!=oldWeather if @field.weather!=oldWeather
# Check for form changes caused by the weather changing
eachBattler { |b| b.pbCheckFormOnWeatherChange } eachBattler { |b| b.pbCheckFormOnWeatherChange }
# Start up the default weather
pbStartWeather(nil,@field.defaultWeather) if @field.defaultWeather!=PBWeather::None
end end
end end
@@ -169,7 +169,7 @@ class PokeBattle_Battle
idxPartyForName = idxPartyNew idxPartyForName = idxPartyNew
enemyParty = pbParty(idxBattler) enemyParty = pbParty(idxBattler)
if isConst?(enemyParty[idxPartyNew].ability,PBAbilities,:ILLUSION) if isConst?(enemyParty[idxPartyNew].ability,PBAbilities,:ILLUSION)
idxPartyForName = pbGetLastPokeInTeam(idxBattler) idxPartyForName = pbLastInTeam(idxBattler)
end end
if pbDisplayConfirm(_INTL("{1} is about to send in {2}. Will you switch your Pokémon?", if pbDisplayConfirm(_INTL("{1} is about to send in {2}. Will you switch your Pokémon?",
opponent.fullname,enemyParty[idxPartyForName].name)) opponent.fullname,enemyParty[idxPartyForName].name))
@@ -245,7 +245,7 @@ class PokeBattle_Battle
pbDisplayBrief(_INTL("{1}, switch out! Come back!",battler.name)) pbDisplayBrief(_INTL("{1}, switch out! Come back!",battler.name))
end end
else else
owner = pbGetOwnerName(b.index) owner = pbGetOwnerName(battler.index)
pbDisplayBrief(_INTL("{1} withdrew {2}!",owner,battler.name)) pbDisplayBrief(_INTL("{1} withdrew {2}!",owner,battler.name))
end end
end end
@@ -83,7 +83,7 @@ class PokeBattle_Battle
end end
end end
# Uses an item on a Pokémon in the player's party. # Uses an item on a Pokémon in the trainer's party.
def pbUseItemOnPokemon(item,idxParty,userBattler) def pbUseItemOnPokemon(item,idxParty,userBattler)
trainerName = pbGetOwnerName(userBattler.index) trainerName = pbGetOwnerName(userBattler.index)
pbUseItemMessage(item,trainerName) pbUseItemMessage(item,trainerName)
@@ -100,14 +100,14 @@ class PokeBattle_Battle
pbReturnUnusedItemToBag(item,userBattler.index) pbReturnUnusedItemToBag(item,userBattler.index)
end end
# Uses an item on a Pokémon in battle that belongs to the player. # Uses an item on a Pokémon in battle that belongs to the trainer.
def pbUseItemOnBattler(item,idxParty,userBattler) def pbUseItemOnBattler(item,idxBattler,userBattler)
trainerName = pbGetOwnerName(userBattler.index) trainerName = pbGetOwnerName(userBattler.index)
pbUseItemMessage(item,trainerName) pbUseItemMessage(item,trainerName)
pkmn = pbParty(userBattler.index)[idxParty] idxBattler = userBattler.index if idxBattler<0
battler = pbFindBattler(idxParty,userBattler.index) battler = @battlers[idxBattler]
ch = @choices[userBattler.index] ch = @choices[userBattler.index]
if ItemHandlers.triggerCanUseInBattle(item,pkmn,battler,ch[3],true,self,@scene,false) if ItemHandlers.triggerCanUseInBattle(item,battler.pokemon,battler,ch[3],true,self,@scene,false)
ItemHandlers.triggerBattleUseOnBattler(item,battler,@scene) ItemHandlers.triggerBattleUseOnBattler(item,battler,@scene)
ch[1] = 0 # Delete item from choice ch[1] = 0 # Delete item from choice
return return
@@ -52,7 +52,8 @@ class PokeBattle_Battle
elsif @internalBattle elsif @internalBattle
pbDisplayPaused(_INTL("No! There's no running from a Trainer battle!")) pbDisplayPaused(_INTL("No! There's no running from a Trainer battle!"))
elsif pbDisplayConfirm(_INTL("Would you like to forfeit the match and quit now?")) elsif pbDisplayConfirm(_INTL("Would you like to forfeit the match and quit now?"))
pbDisplay(_INTL("{1} forfeited the match!",self.pbPlayer.name)) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
pbDisplay(_INTL("{1} forfeited the match!",self.pbPlayer.name))
@decision = 3 @decision = 3
return 1 return 1
end end
@@ -60,7 +61,8 @@ class PokeBattle_Battle
end end
# Fleeing from wild battles # Fleeing from wild battles
if $DEBUG && Input.press?(Input::CTRL) if $DEBUG && Input.press?(Input::CTRL)
pbDisplayPaused(_INTL("You got away safely!")) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("You got away safely!"))
@decision = 3 @decision = 3
return 1 return 1
end end
@@ -70,7 +72,8 @@ class PokeBattle_Battle
end end
if !duringBattle if !duringBattle
if battler.pbHasType?(:GHOST) && NEWEST_BATTLE_MECHANICS if battler.pbHasType?(:GHOST) && NEWEST_BATTLE_MECHANICS
pbDisplayPaused(_INTL("You got away safely!")) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("You got away safely!"))
@decision = 3 @decision = 3
return 1 return 1
end end
@@ -79,7 +82,8 @@ class PokeBattle_Battle
if BattleHandlers.triggerRunFromBattleAbility(battler.ability,battler) if BattleHandlers.triggerRunFromBattleAbility(battler.ability,battler)
pbShowAbilitySplash(battler,true) pbShowAbilitySplash(battler,true)
pbHideAbilitySplash(battler) pbHideAbilitySplash(battler)
pbDisplayPaused(_INTL("You got away safely!")) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("You got away safely!"))
@decision = 3 @decision = 3
return 1 return 1
end end
@@ -87,8 +91,9 @@ class PokeBattle_Battle
# Held items that guarantee escape # Held items that guarantee escape
if battler.itemActive? if battler.itemActive?
if BattleHandlers.triggerRunFromBattleItem(battler.item,battler) if BattleHandlers.triggerRunFromBattleItem(battler.item,battler)
pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("{1} fled using its {2}!", pbDisplayPaused(_INTL("{1} fled using its {2}!",
battler.pbThis,battler.itemName)) { pbSEPlay("Battle flee") } battler.pbThis,battler.itemName))
@decision = 3 @decision = 3
return 1 return 1
end end
@@ -135,7 +140,8 @@ class PokeBattle_Battle
rate += @runCommand*30 rate += @runCommand*30
end end
if rate>=256 || @battleAI.pbAIRandom(256)<rate if rate>=256 || @battleAI.pbAIRandom(256)<rate
pbDisplayPaused(_INTL("You got away safely!")) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("You got away safely!"))
@decision = 3 @decision = 3
return 1 return 1
end end
@@ -20,7 +20,7 @@ class PokeBattle_AI
# NOTE: The AI will only consider using an item on the Pokémon it's currently # NOTE: The AI will only consider using an item on the Pokémon it's currently
# choosing an action for. # choosing an action for.
def pbEnemyItemToUse(idxBattler) def pbEnemyItemToUse(idxBattler)
return 0 if !@internalBattle return 0 if !@battle.internalBattle
items = @battle.pbGetOwnerItems(idxBattler) items = @battle.pbGetOwnerItems(idxBattler)
return 0 if !items || items.length==0 return 0 if !items || items.length==0
# Determine target of item (always the Pokémon choosing the action) # Determine target of item (always the Pokémon choosing the action)
@@ -135,7 +135,7 @@ class PokeBattle_AI
if @battle.pbRegisterSwitch(idxBattler,list[0]) if @battle.pbRegisterSwitch(idxBattler,list[0])
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will switch with " + PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will switch with " +
"#{@battle.pbParty(idxBattler)[list[0]].name}") "#{@battle.pbParty(idxBattler)[list[0]].name}")
return return true
end end
end end
end end
+19 -12
View File
@@ -81,20 +81,27 @@ class PokeBattle_AI
return return
end end
end end
# Randomly choose a move to use # If there are no calculated choices, pick one at random
if choices.length==0 if choices.length==0
# If there are no calculated choices, use Struggle (or an Encored move) PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random")
@battle.pbAutoChooseMove(idxBattler) user.eachMoveWithIndex do |_m,i|
else next if !@battle.pbCanChooseMove?(idxBattler,i,false)
# Randomly choose a move from the choices and register it choices.push([i,100,-1]) # Move index, score, target
randNum = pbAIRandom(totalScore)
choices.each do |c|
randNum -= c[1]
next if randNum>=0
@battle.pbRegisterMove(idxBattler,c[0],false)
@battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0
break
end end
if choices.length==0 # No moves are physically possible to use
user.eachMoveWithIndex do |_m,i|
choices.push([i,100,-1]) # Move index, score, target
end
end
end
# Randomly choose a move from the choices and register it
randNum = pbAIRandom(totalScore)
choices.each do |c|
randNum -= c[1]
next if randNum>=0
@battle.pbRegisterMove(idxBattler,c[0],false)
@battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0
break
end end
# Log the result # Log the result
if @battle.choices[idxBattler][2] if @battle.choices[idxBattler][2]
@@ -1364,7 +1364,7 @@ class PokeBattle_AI
:ROCK, # Cave :ROCK, # Cave
:GROUND # Sand :GROUND # Sand
] ]
type = envtypes[@environment] type = envtypes[@battle.environment]
score -= 90 if user.pbHasType?(type) score -= 90 if user.pbHasType?(type)
end end
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -2806,7 +2806,7 @@ class PokeBattle_AI
when "152" when "152"
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
when "153" when "153"
score -= 95 if target.pbOwnSide.effects[PBEffects::StickyWeb] score -= 95 if user.pbOpposingSide.effects[PBEffects::StickyWeb]
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
when "154" when "154"
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -275,7 +275,7 @@ class PokeBattle_AI
defense = pbRoughStat(target,PBStats::SPDEF,skill) defense = pbRoughStat(target,PBStats::SPDEF,skill)
end end
##### Calculate all multiplier effects ##### ##### Calculate all multiplier effects #####
multipliers = [0x1000,0x1000,0x1000,0x1000] multipliers = [1.0, 1.0, 1.0, 1.0]
# Ability effects that alter damage # Ability effects that alter damage
moldBreaker = false moldBreaker = false
if skill>=PBTrainerAI.highSkill && target.hasMoldBreaker? if skill>=PBTrainerAI.highSkill && target.hasMoldBreaker?
@@ -364,7 +364,7 @@ class PokeBattle_AI
end end
# Parental Bond # Parental Bond
if skill>=PBTrainerAI.mediumSkill && user.hasActiveAbility?(:PARENTALBOND) if skill>=PBTrainerAI.mediumSkill && user.hasActiveAbility?(:PARENTALBOND)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.25).floor multipliers[BASE_DMG_MULT] *= 1.25
end end
# Me First # Me First
# TODO # TODO
@@ -403,15 +403,15 @@ class PokeBattle_AI
case @battle.field.terrain case @battle.field.terrain
when PBBattleTerrains::Electric when PBBattleTerrains::Electric
if isConst?(type,PBTypes,:ELECTRIC) if isConst?(type,PBTypes,:ELECTRIC)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round multipliers[BASE_DMG_MULT] *= 1.5
end end
when PBBattleTerrains::Grassy when PBBattleTerrains::Grassy
if isConst?(type,PBTypes,:GRASS) if isConst?(type,PBTypes,:GRASS)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round multipliers[BASE_DMG_MULT] *= 1.5
end end
when PBBattleTerrains::Psychic when PBBattleTerrains::Psychic
if isConst?(type,PBTypes,:PSYCHIC) if isConst?(type,PBTypes,:PSYCHIC)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round multipliers[BASE_DMG_MULT] *= 1.5
end end
end end
end end
@@ -427,9 +427,9 @@ class PokeBattle_AI
# won't control the player's Pokémon. # won't control the player's Pokémon.
if target.pbOwnedByPlayer? if target.pbOwnedByPlayer?
if move.physicalMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE if move.physicalMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.1).round multipliers[DEF_MULT] *= 1.1
elsif move.specialMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF elsif move.specialMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.1).round multipliers[DEF_MULT] *= 1.1
end end
end end
end end
@@ -437,7 +437,7 @@ class PokeBattle_AI
# Multi-targeting attacks # Multi-targeting attacks
if skill>=PBTrainerAI.highSkill if skill>=PBTrainerAI.highSkill
if pbTargetsMultiple?(move,user) if pbTargetsMultiple?(move,user)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*0.75).round multipliers[FINAL_DMG_MULT] *= 0.75
end end
end end
# Weather # Weather
@@ -445,7 +445,7 @@ class PokeBattle_AI
case @battle.pbWeather case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun when PBWeather::Sun, PBWeather::HarshSun
if isConst?(type,PBTypes,:FIRE) if isConst?(type,PBTypes,:FIRE)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round multipliers[FINAL_DMG_MULT] *= 1.5
elsif isConst?(type,PBTypes,:WATER) elsif isConst?(type,PBTypes,:WATER)
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
end end
@@ -453,11 +453,11 @@ class PokeBattle_AI
if isConst?(type,PBTypes,:FIRE) if isConst?(type,PBTypes,:FIRE)
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
elsif isConst?(type,PBTypes,:WATER) elsif isConst?(type,PBTypes,:WATER)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round multipliers[FINAL_DMG_MULT] *= 1.5
end end
when PBWeather::Sandstorm when PBWeather::Sandstorm
if target.pbHasType?(:ROCK) && move.specialMove?(type) && move.function!="122" # Psyshock if target.pbHasType?(:ROCK) && move.specialMove?(type) && move.function!="122" # Psyshock
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.5).round multipliers[DEF_MULT] *= 1.5
end end
end end
end end
@@ -469,7 +469,7 @@ class PokeBattle_AI
if user.hasActiveAbility?(:ADAPTABILITY) if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2 multipliers[FINAL_DMG_MULT] *= 2
else else
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round multipliers[FINAL_DMG_MULT] *= 1.5
end end
end end
end end
@@ -477,7 +477,6 @@ class PokeBattle_AI
if skill>=PBTrainerAI.mediumSkill if skill>=PBTrainerAI.mediumSkill
typemod = pbCalcTypeMod(type,user,target) typemod = pbCalcTypeMod(type,user,target)
multipliers[FINAL_DMG_MULT] *= typemod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE multipliers[FINAL_DMG_MULT] *= typemod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
multipliers[FINAL_DMG_MULT] = multipliers[FINAL_DMG_MULT].round
end end
# Burn # Burn
if skill>=PBTrainerAI.highSkill if skill>=PBTrainerAI.highSkill
@@ -492,19 +491,19 @@ class PokeBattle_AI
if !move.ignoresReflect? && !user.hasActiveAbility?(:INFILTRATOR) if !move.ignoresReflect? && !user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
if @battle.pbSideBattlerCount(target)>1 if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round multipliers[FINAL_DMG_MULT] *= 2/3.0
else else
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
end end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && move.physicalMove?(type) elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && move.physicalMove?(type)
if @battle.pbSideBattlerCount(target)>1 if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round multipliers[FINAL_DMG_MULT] *= 2/3.0
else else
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
end end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && move.specialMove?(type) elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && move.specialMove?(type)
if @battle.pbSideBattlerCount(target)>1 if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round multipliers[FINAL_DMG_MULT] *= 2/3.0
else else
multipliers[FINAL_DMG_MULT] /= 2 multipliers[FINAL_DMG_MULT] /= 2
end end
@@ -522,11 +521,11 @@ class PokeBattle_AI
# Move-specific final damage modifiers # Move-specific final damage modifiers
# TODO # TODO
##### Main damage calculation ##### ##### Main damage calculation #####
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT] / 0x1000).round,1].max baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
atk = [(atk * multipliers[ATK_MULT] / 0x1000).round,1].max atk = [(atk * multipliers[ATK_MULT]).round, 1].max
defense = [(defense * multipliers[DEF_MULT] / 0x1000).round,1].max defense = [(defense * multipliers[DEF_MULT]).round, 1].max
damage = (((2.0*user.level/5+2).floor*baseDmg*atk/defense).floor/50).floor+2 damage = (((2.0 * user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
damage = [(damage * multipliers[FINAL_DMG_MULT] / 0x1000).round,1].max damage = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
# "AI-specific calculations below" # "AI-specific calculations below"
# Increased critical hit rates # Increased critical hit rates
if skill>=PBTrainerAI.mediumSkill if skill>=PBTrainerAI.mediumSkill
@@ -585,8 +584,8 @@ class PokeBattle_AI
modifiers[BASE_ACC] = baseAcc modifiers[BASE_ACC] = baseAcc
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY] modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION] modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 0x1000 modifiers[ACC_MULT] = 1.0
modifiers[EVA_MULT] = 0x1000 modifiers[EVA_MULT] = 1.0
pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill) pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill)
# Check if move can't miss # Check if move can't miss
return 125 if modifiers[BASE_ACC]==0 return 125 if modifiers[BASE_ACC]==0
@@ -597,8 +596,8 @@ class PokeBattle_AI
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3] stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage] accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage] evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[ACC_MULT] / 0x1000).round accuracy = (accuracy * modifiers[ACC_MULT]).round
evasion = (evasion * modifiers[EVA_MULT] / 0x1000).round evasion = (evasion * modifiers[EVA_MULT]).round
evasion = 1 if evasion<1 evasion = 1 if evasion<1
return modifiers[BASE_ACC] * accuracy / evasion return modifiers[BASE_ACC] * accuracy / evasion
end end
@@ -642,10 +641,10 @@ class PokeBattle_AI
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values # Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
if skill>=PBTrainerAI.mediumSkill if skill>=PBTrainerAI.mediumSkill
if @battle.field.effects[PBEffects::Gravity]>0 if @battle.field.effects[PBEffects::Gravity]>0
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*5/3).round modifiers[ACC_MULT] *= 5/3.0
end end
if user.effects[PBEffects::MicleBerry] if user.effects[PBEffects::MicleBerry]
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*1.2).round modifiers[ACC_MULT] *= 1.2
end end
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0 modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE]>0 modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE]>0
+4 -4
View File
@@ -5,19 +5,19 @@ module PBTargets
User = 10 User = 10
NearAlly = 100 # Aromatic Mist, Helping Hand, Hold Hands NearAlly = 100 # Aromatic Mist, Helping Hand, Hold Hands
UserOrNearAlly = 200 # Acupressure UserOrNearAlly = 200 # Acupressure
UserAndAllies = 5 # Aromatherapy, Gear Up, Heal Bell, Life Dew, Magnetic Flux, Howl (in Gen 8+)
NearFoe = 400 # Me First NearFoe = 400 # Me First
AllNearFoes = 4
RandomNearFoe = 2 # Petal Dance, Outrage, Struggle, Thrash, Uproar RandomNearFoe = 2 # Petal Dance, Outrage, Struggle, Thrash, Uproar
AllNearFoes = 4
Foe = 9 # For throwing a Poké Ball Foe = 9 # For throwing a Poké Ball
AllFoes = 6 # Unused (for completeness)
NearOther = 0 NearOther = 0
AllNearOthers = 8 AllNearOthers = 8
Other = 3 # Most Flying-type moves, pulse moves (hits non-near targets) Other = 3 # Most Flying-type moves, pulse moves (hits non-near targets)
AllBattlers = 7 # Flower Shield, Perish Song, Rototiller, Teatime
UserSide = 40 UserSide = 40
FoeSide = 80 # Entry hazards FoeSide = 80 # Entry hazards
BothSides = 20 BothSides = 20
UserAndAllies = 5 # Aromatherapy, Gear Up, Heal Bell, Life Dew, Magnetic Flux, Howl (in Gen 8+)
AllFoes = 6 # Unused (for completeness)
AllBattlers = 7 # Flower Shield, Perish Song, Rototiller, Teatime
def self.noTargets?(target) def self.noTargets?(target)
return target==None || return target==None ||
@@ -326,7 +326,7 @@ class PokemonDataBox < SpriteWrapper
if @expFlash==0 if @expFlash==0
pbSEStop pbSEStop
@expFlash = Graphics.frame_rate/5 @expFlash = Graphics.frame_rate/5
pbSEPlay("Exp full") pbSEPlay("Pkmn exp full")
self.flash(Color.new(64,200,248,192),@expFlash) self.flash(Color.new(64,200,248,192),@expFlash)
for i in @sprites for i in @sprites
i[1].flash(Color.new(64,200,248,192),@expFlash) if !i[1].disposed? i[1].flash(Color.new(64,200,248,192),@expFlash) if !i[1].disposed?
@@ -578,16 +578,16 @@ def pbBattleGem(user,type,move,mults,moveType)
return if !isConst?(moveType,PBTypes,type) return if !isConst?(moveType,PBTypes,type)
user.effects[PBEffects::GemConsumed] = user.item user.effects[PBEffects::GemConsumed] = user.item
if NEWEST_BATTLE_MECHANICS if NEWEST_BATTLE_MECHANICS
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.3).round mults[BASE_DMG_MULT] *= 1.3
else else
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round mults[BASE_DMG_MULT] *= 1.5
end end
end end
def pbBattleTypeWeakingBerry(type,moveType,target,mults) def pbBattleTypeWeakingBerry(type,moveType,target,mults)
return if !isConst?(moveType,PBTypes,type) return if !isConst?(moveType,PBTypes,type)
return if PBTypes.resistant?(target.damageState.typeMod) && !isConst?(moveType,PBTypes,:NORMAL) return if PBTypes.resistant?(target.damageState.typeMod) && !isConst?(moveType,PBTypes,:NORMAL)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]/2).round mults[FINAL_DMG_MULT] /= 2
target.damageState.berryWeakened = true target.damageState.berryWeakened = true
target.battle.pbCommonAnimation("EatBerry",target) target.battle.pbCommonAnimation("EatBerry",target)
end end
@@ -25,6 +25,10 @@ class PokeBattle_FakeBattler
def shiny?; return @pokemon.shiny?; end def shiny?; return @pokemon.shiny?; end
alias isShiny? shiny? alias isShiny? shiny?
def isSpecies?(check_species)
return @pokemon && @pokemon.isSpecies?(check_species)
end
def fainted?; return false; end def fainted?; return false; end
alias isFainted? fainted? alias isFainted? fainted?
def shadowPokemon?; return false; end def shadowPokemon?; return false; end
@@ -458,7 +462,8 @@ class PokeBattle_SafariZone
catchFactor *= 2 # Easier to catch catchFactor *= 2 # Easier to catch
escapeFactor *= 2 if pbRandom(100)<90 # More likely to escape escapeFactor *= 2 if pbRandom(100)<90 # More likely to escape
when 3 # Run when 3 # Run
pbDisplayPaused(_INTL("You got away safely!")) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("You got away safely!"))
@decision = 3 @decision = 3
end end
catchFactor = [[catchFactor,3].max,20].min catchFactor = [[catchFactor,3].max,20].min
@@ -469,7 +474,8 @@ class PokeBattle_SafariZone
pbDisplay(_INTL("PA: You have no Safari Balls left! Game over!")) pbDisplay(_INTL("PA: You have no Safari Balls left! Game over!"))
@decision = 2 @decision = 2
elsif pbRandom(100)<5*escapeFactor elsif pbRandom(100)<5*escapeFactor
pbDisplay(_INTL("{1} fled!",wildpoke.name)) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
pbDisplay(_INTL("{1} fled!",wildpoke.name))
@decision = 3 @decision = 3
elsif cmd==1 # Bait elsif cmd==1 # Bait
pbDisplay(_INTL("{1} is eating!",wildpoke.name)) pbDisplay(_INTL("{1} is eating!",wildpoke.name))
@@ -11,7 +11,7 @@ BattleHandlers::SpeedCalcAbility.add(:CHLOROPHYLL,
BattleHandlers::SpeedCalcAbility.add(:QUICKFEET, BattleHandlers::SpeedCalcAbility.add(:QUICKFEET,
proc { |ability,battler,mult| proc { |ability,battler,mult|
next (mult*1.5).round if battler.pbHasAnyStatus? next mult*1.5 if battler.pbHasAnyStatus?
} }
) )
@@ -24,7 +24,7 @@ BattleHandlers::SpeedCalcAbility.add(:SANDRUSH,
BattleHandlers::SpeedCalcAbility.add(:SLOWSTART, BattleHandlers::SpeedCalcAbility.add(:SLOWSTART,
proc { |ability,battler,mult| proc { |ability,battler,mult|
next mult/2 if battler.turnCount<=5 next mult/2 if battler.effects[PBEffects::SlowStart]>0
} }
) )
@@ -83,7 +83,8 @@ BattleHandlers::AbilityOnHPDroppedBelowHalf.add(:EMERGENCYEXIT,
next false if !battle.pbCanRun?(battler.index) next false if !battle.pbCanRun?(battler.index)
battle.pbShowAbilitySplash(battler,true) battle.pbShowAbilitySplash(battler,true)
battle.pbHideAbilitySplash(battler) battle.pbHideAbilitySplash(battler)
battle.pbDisplay(_INTL("{1} fled from battle!",battler.pbThis)) { pbSEPlay("Battle flee") } pbSEPlay("Battle flee")
battle.pbDisplay(_INTL("{1} fled from battle!",battler.pbThis))
battle.decision = 3 # Escaped battle.decision = 3 # Escaped
next true next true
end end
@@ -767,13 +768,13 @@ BattleHandlers::MoveBaseTypeModifierAbility.add(:REFRIGERATE,
BattleHandlers::AccuracyCalcUserAbility.add(:COMPOUNDEYES, BattleHandlers::AccuracyCalcUserAbility.add(:COMPOUNDEYES,
proc { |ability,mods,user,target,move,type| proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] = (mods[ACC_MULT]*1.3).round mods[ACC_MULT] *= 1.3
} }
) )
BattleHandlers::AccuracyCalcUserAbility.add(:HUSTLE, BattleHandlers::AccuracyCalcUserAbility.add(:HUSTLE,
proc { |ability,mods,user,target,move,type| proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] = (mods[ACC_MULT]*0.8).round if move.physicalMove? mods[ACC_MULT] *= 0.8 if move.physicalMove?
} }
) )
@@ -797,7 +798,7 @@ BattleHandlers::AccuracyCalcUserAbility.add(:UNAWARE,
BattleHandlers::AccuracyCalcUserAbility.add(:VICTORYSTAR, BattleHandlers::AccuracyCalcUserAbility.add(:VICTORYSTAR,
proc { |ability,mods,user,target,move,type| proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] = (mods[ACC_MULT]*1.1).round mods[ACC_MULT] *= 1.1
} }
) )
@@ -807,7 +808,7 @@ BattleHandlers::AccuracyCalcUserAbility.add(:VICTORYSTAR,
BattleHandlers::AccuracyCalcUserAllyAbility.add(:VICTORYSTAR, BattleHandlers::AccuracyCalcUserAllyAbility.add(:VICTORYSTAR,
proc { |ability,mods,user,target,move,type| proc { |ability,mods,user,target,move,type|
mods[ACC_MULT] = (mods[ACC_MULT]*1.1).round mods[ACC_MULT] *= 1.1
} }
) )
@@ -830,7 +831,7 @@ BattleHandlers::AccuracyCalcTargetAbility.add(:NOGUARD,
BattleHandlers::AccuracyCalcTargetAbility.add(:SANDVEIL, BattleHandlers::AccuracyCalcTargetAbility.add(:SANDVEIL,
proc { |ability,mods,user,target,move,type| proc { |ability,mods,user,target,move,type|
if target.battle.pbWeather==PBWeather::Sandstorm if target.battle.pbWeather==PBWeather::Sandstorm
mods[EVA_MULT] = (mods[EVA_MULT]*1.25).round mods[EVA_MULT] *= 1.25
end end
} }
) )
@@ -838,7 +839,7 @@ BattleHandlers::AccuracyCalcTargetAbility.add(:SANDVEIL,
BattleHandlers::AccuracyCalcTargetAbility.add(:SNOWCLOAK, BattleHandlers::AccuracyCalcTargetAbility.add(:SNOWCLOAK,
proc { |ability,mods,user,target,move,type| proc { |ability,mods,user,target,move,type|
if target.battle.pbWeather==PBWeather::Hail if target.battle.pbWeather==PBWeather::Hail
mods[EVA_MULT] = (mods[EVA_MULT]*1.25).round mods[EVA_MULT] *= 1.25
end end
} }
) )
@@ -875,7 +876,7 @@ BattleHandlers::AccuracyCalcTargetAbility.add(:WONDERSKIN,
BattleHandlers::DamageCalcUserAbility.add(:AERILATE, BattleHandlers::DamageCalcUserAbility.add(:AERILATE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if move.powerBoost mults[BASE_DMG_MULT] *= 1.2 if move.powerBoost
} }
) )
@@ -886,7 +887,7 @@ BattleHandlers::DamageCalcUserAbility.add(:ANALYTIC,
if (target.battle.choices[target.index][0]!=:UseMove && if (target.battle.choices[target.index][0]!=:UseMove &&
target.battle.choices[target.index][0]!=:Shift) || target.battle.choices[target.index][0]!=:Shift) ||
target.movedThisRound? target.movedThisRound?
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.3).round mults[BASE_DMG_MULT] *= 1.3
end end
} }
) )
@@ -894,21 +895,21 @@ BattleHandlers::DamageCalcUserAbility.add(:ANALYTIC,
BattleHandlers::DamageCalcUserAbility.add(:BLAZE, BattleHandlers::DamageCalcUserAbility.add(:BLAZE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.hp<=user.totalhp/3 && isConst?(type,PBTypes,:FIRE) if user.hp<=user.totalhp/3 && isConst?(type,PBTypes,:FIRE)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:DEFEATIST, BattleHandlers::DamageCalcUserAbility.add(:DEFEATIST,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] = (mults[ATK_MULT]*0.5).round if user.hp<=user.totalhp/2 mults[ATK_MULT] /= 2 if user.hp<=user.totalhp/2
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:FLAREBOOST, BattleHandlers::DamageCalcUserAbility.add(:FLAREBOOST,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.burned? && move.specialMove? if user.burned? && move.specialMove?
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round mults[BASE_DMG_MULT] *= 1.5
end end
} }
) )
@@ -916,7 +917,7 @@ BattleHandlers::DamageCalcUserAbility.add(:FLAREBOOST,
BattleHandlers::DamageCalcUserAbility.add(:FLASHFIRE, BattleHandlers::DamageCalcUserAbility.add(:FLASHFIRE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.effects[PBEffects::FlashFire] && isConst?(type,PBTypes,:FIRE) if user.effects[PBEffects::FlashFire] && isConst?(type,PBTypes,:FIRE)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
@@ -925,7 +926,7 @@ BattleHandlers::DamageCalcUserAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather w = user.battle.pbWeather
if move.physicalMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun) if move.physicalMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
@@ -933,7 +934,7 @@ BattleHandlers::DamageCalcUserAbility.add(:FLOWERGIFT,
BattleHandlers::DamageCalcUserAbility.add(:GUTS, BattleHandlers::DamageCalcUserAbility.add(:GUTS,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.pbHasAnyStatus? && move.physicalMove? if user.pbHasAnyStatus? && move.physicalMove?
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
@@ -948,19 +949,19 @@ BattleHandlers::DamageCalcUserAbility.copy(:HUGEPOWER,:PUREPOWER)
BattleHandlers::DamageCalcUserAbility.add(:HUSTLE, BattleHandlers::DamageCalcUserAbility.add(:HUSTLE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round if move.physicalMove? mults[ATK_MULT] *= 1.5 if move.physicalMove?
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:IRONFIST, BattleHandlers::DamageCalcUserAbility.add(:IRONFIST,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if move.punchingMove? mults[BASE_DMG_MULT] *= 1.2 if move.punchingMove?
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:MEGALAUNCHER, BattleHandlers::DamageCalcUserAbility.add(:MEGALAUNCHER,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round if move.pulseMove? mults[BASE_DMG_MULT] *= 1.5 if move.pulseMove?
} }
) )
@@ -969,7 +970,7 @@ BattleHandlers::DamageCalcUserAbility.add(:MINUS,
next if !move.specialMove? next if !move.specialMove?
user.eachAlly do |b| user.eachAlly do |b|
next if !b.hasActiveAbility?([:MINUS,:PLUS]) next if !b.hasActiveAbility?([:MINUS,:PLUS])
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
break break
end end
} }
@@ -980,7 +981,7 @@ BattleHandlers::DamageCalcUserAbility.copy(:MINUS,:PLUS)
BattleHandlers::DamageCalcUserAbility.add(:NEUROFORCE, BattleHandlers::DamageCalcUserAbility.add(:NEUROFORCE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypes.superEffective?(target.damageState.typeMod) if PBTypes.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.25).round mults[FINAL_DMG_MULT] *= 1.25
end end
} }
) )
@@ -988,14 +989,14 @@ BattleHandlers::DamageCalcUserAbility.add(:NEUROFORCE,
BattleHandlers::DamageCalcUserAbility.add(:OVERGROW, BattleHandlers::DamageCalcUserAbility.add(:OVERGROW,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.hp<=user.totalhp/3 && isConst?(type,PBTypes,:GRASS) if user.hp<=user.totalhp/3 && isConst?(type,PBTypes,:GRASS)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:RECKLESS, BattleHandlers::DamageCalcUserAbility.add(:RECKLESS,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if move.recoilMove? mults[BASE_DMG_MULT] *= 1.2 if move.recoilMove?
} }
) )
@@ -1003,9 +1004,9 @@ BattleHandlers::DamageCalcUserAbility.add(:RIVALRY,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.gender!=2 && target.gender!=2 if user.gender!=2 && target.gender!=2
if user.gender==target.gender if user.gender==target.gender
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.25).round mults[BASE_DMG_MULT] *= 1.25
else else
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*0.75).round mults[BASE_DMG_MULT] *= 0.75
end end
end end
} }
@@ -1017,22 +1018,20 @@ BattleHandlers::DamageCalcUserAbility.add(:SANDFORCE,
(isConst?(type,PBTypes,:ROCK) || (isConst?(type,PBTypes,:ROCK) ||
isConst?(type,PBTypes,:GROUND) || isConst?(type,PBTypes,:GROUND) ||
isConst?(type,PBTypes,:STEEL)) isConst?(type,PBTypes,:STEEL))
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.3).round mults[BASE_DMG_MULT] *= 1.3
end end
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:SHEERFORCE, BattleHandlers::DamageCalcUserAbility.add(:SHEERFORCE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.3).round if move.addlEffect>0 mults[BASE_DMG_MULT] *= 1.3 if move.addlEffect>0
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:SLOWSTART, BattleHandlers::DamageCalcUserAbility.add(:SLOWSTART,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.turnCount<=5 && move.physicalMove? mults[ATK_MULT] /= 2 if user.effects[PBEffects::SlowStart]>0 && move.physicalMove?
mults[ATK_MULT] = (mults[ATK_MULT]*0.5).round
end
} }
) )
@@ -1040,7 +1039,7 @@ BattleHandlers::DamageCalcUserAbility.add(:SOLARPOWER,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun) if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
@@ -1048,7 +1047,7 @@ BattleHandlers::DamageCalcUserAbility.add(:SOLARPOWER,
BattleHandlers::DamageCalcUserAbility.add(:SNIPER, BattleHandlers::DamageCalcUserAbility.add(:SNIPER,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if target.damageState.critical if target.damageState.critical
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.5).round mults[FINAL_DMG_MULT] *= 1.5
end end
} }
) )
@@ -1061,28 +1060,28 @@ BattleHandlers::DamageCalcUserAbility.add(:STAKEOUT,
BattleHandlers::DamageCalcUserAbility.add(:STEELWORKER, BattleHandlers::DamageCalcUserAbility.add(:STEELWORKER,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round if isConst?(type,PBTypes,:STEEL) mults[ATK_MULT] *= 1.5 if isConst?(type,PBTypes,:STEEL)
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:STRONGJAW, BattleHandlers::DamageCalcUserAbility.add(:STRONGJAW,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round if move.bitingMove? mults[BASE_DMG_MULT] *= 1.5 if move.bitingMove?
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:SWARM, BattleHandlers::DamageCalcUserAbility.add(:SWARM,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.hp<=user.totalhp/3 && isConst?(type,PBTypes,:BUG) if user.hp<=user.totalhp/3 && isConst?(type,PBTypes,:BUG)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:TECHNICIAN, BattleHandlers::DamageCalcUserAbility.add(:TECHNICIAN,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.index!=target.index && move.id>0 && baseDmg*mults[BASE_DMG_MULT]/0x1000<=60 if user.index!=target.index && move.id>0 && baseDmg*mults[BASE_DMG_MULT]<=60
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round mults[BASE_DMG_MULT] *= 1.5
end end
} }
) )
@@ -1096,21 +1095,21 @@ BattleHandlers::DamageCalcUserAbility.add(:TINTEDLENS,
BattleHandlers::DamageCalcUserAbility.add(:TORRENT, BattleHandlers::DamageCalcUserAbility.add(:TORRENT,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.hp<=user.totalhp/3 && isConst?(type,PBTypes,:WATER) if user.hp<=user.totalhp/3 && isConst?(type,PBTypes,:WATER)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:TOUGHCLAWS, BattleHandlers::DamageCalcUserAbility.add(:TOUGHCLAWS,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*4/3.0).round if move.contactMove? mults[BASE_DMG_MULT] *= 4/3.0 if move.contactMove?
} }
) )
BattleHandlers::DamageCalcUserAbility.add(:TOXICBOOST, BattleHandlers::DamageCalcUserAbility.add(:TOXICBOOST,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.poisoned? && move.physicalMove? if user.poisoned? && move.physicalMove?
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round mults[BASE_DMG_MULT] *= 1.5
end end
} }
) )
@@ -1128,7 +1127,7 @@ BattleHandlers::DamageCalcUserAbility.add(:WATERBUBBLE,
BattleHandlers::DamageCalcUserAllyAbility.add(:BATTERY, BattleHandlers::DamageCalcUserAllyAbility.add(:BATTERY,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
next if !move.specialMove? next if !move.specialMove?
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.3).round mults[FINAL_DMG_MULT] *= 1.3
} }
) )
@@ -1136,7 +1135,7 @@ BattleHandlers::DamageCalcUserAllyAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather w = user.battle.pbWeather
if move.physicalMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun) if move.physicalMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
} }
) )
@@ -1148,7 +1147,7 @@ BattleHandlers::DamageCalcUserAllyAbility.add(:FLOWERGIFT,
BattleHandlers::DamageCalcTargetAbility.add(:DRYSKIN, BattleHandlers::DamageCalcTargetAbility.add(:DRYSKIN,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if isConst?(type,PBTypes,:FIRE) if isConst?(type,PBTypes,:FIRE)
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.25).round mults[BASE_DMG_MULT] *= 1.25
end end
} }
) )
@@ -1156,7 +1155,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:DRYSKIN,
BattleHandlers::DamageCalcTargetAbility.add(:FILTER, BattleHandlers::DamageCalcTargetAbility.add(:FILTER,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypes.superEffective?(target.damageState.typeMod) if PBTypes.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.75).round mults[FINAL_DMG_MULT] *= 0.75
end end
} }
) )
@@ -1167,7 +1166,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun) if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round mults[DEF_MULT] *= 1.5
end end
} }
) )
@@ -1175,7 +1174,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:FLOWERGIFT,
BattleHandlers::DamageCalcTargetAbility.add(:FLUFFY, BattleHandlers::DamageCalcTargetAbility.add(:FLUFFY,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[FINAL_DMG_MULT] *= 2 if isConst?(move.calcType,PBTypes,:FIRE) mults[FINAL_DMG_MULT] *= 2 if isConst?(move.calcType,PBTypes,:FIRE)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.5).round if move.contactMove? mults[FINAL_DMG_MULT] /= 2 if move.contactMove?
} }
) )
@@ -1188,21 +1187,21 @@ BattleHandlers::DamageCalcTargetAbility.add(:FURCOAT,
BattleHandlers::DamageCalcTargetAbility.add(:GRASSPELT, BattleHandlers::DamageCalcTargetAbility.add(:GRASSPELT,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if user.battle.field.terrain==PBBattleTerrains::Grassy if user.battle.field.terrain==PBBattleTerrains::Grassy
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round mults[DEF_MULT] *= 1.5
end end
} }
) )
BattleHandlers::DamageCalcTargetAbility.add(:HEATPROOF, BattleHandlers::DamageCalcTargetAbility.add(:HEATPROOF,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*0.5).round if isConst?(type,PBTypes,:FIRE) mults[BASE_DMG_MULT] /= 2 if isConst?(type,PBTypes,:FIRE)
} }
) )
BattleHandlers::DamageCalcTargetAbility.add(:MARVELSCALE, BattleHandlers::DamageCalcTargetAbility.add(:MARVELSCALE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if target.pbHasAnyStatus? && move.physicalMove? if target.pbHasAnyStatus? && move.physicalMove?
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round mults[DEF_MULT] *= 1.5
end end
} }
) )
@@ -1210,7 +1209,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:MARVELSCALE,
BattleHandlers::DamageCalcTargetAbility.add(:MULTISCALE, BattleHandlers::DamageCalcTargetAbility.add(:MULTISCALE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if target.hp==target.totalhp if target.hp==target.totalhp
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.5).round mults[FINAL_DMG_MULT] /= 2
end end
} }
) )
@@ -1218,7 +1217,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:MULTISCALE,
BattleHandlers::DamageCalcTargetAbility.add(:THICKFAT, BattleHandlers::DamageCalcTargetAbility.add(:THICKFAT,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if isConst?(type,PBTypes,:FIRE) || isConst?(type,PBTypes,:ICE) if isConst?(type,PBTypes,:FIRE) || isConst?(type,PBTypes,:ICE)
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*0.5).round mults[BASE_DMG_MULT] /= 2
end end
} }
) )
@@ -1226,7 +1225,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:THICKFAT,
BattleHandlers::DamageCalcTargetAbility.add(:WATERBUBBLE, BattleHandlers::DamageCalcTargetAbility.add(:WATERBUBBLE,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if isConst?(type,PBTypes,:FIRE) if isConst?(type,PBTypes,:FIRE)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.5).round mults[FINAL_DMG_MULT] /= 2
end end
} }
) )
@@ -1238,7 +1237,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:WATERBUBBLE,
BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:PRISMARMOR, BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:PRISMARMOR,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypes.superEffective?(target.damageState.typeMod) if PBTypes.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.75).round mults[FINAL_DMG_MULT] *= 0.75
end end
} }
) )
@@ -1246,7 +1245,7 @@ BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:PRISMARMOR,
BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:SHADOWSHIELD, BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:SHADOWSHIELD,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
if target.hp==target.totalhp if target.hp==target.totalhp
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.5).round mults[FINAL_DMG_MULT] /= 2
end end
} }
) )
@@ -1259,14 +1258,14 @@ BattleHandlers::DamageCalcTargetAllyAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun) if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round mults[DEF_MULT] *= 1.5
end end
} }
) )
BattleHandlers::DamageCalcTargetAllyAbility.add(:FRIENDGUARD, BattleHandlers::DamageCalcTargetAllyAbility.add(:FRIENDGUARD,
proc { |ability,user,target,move,mults,baseDmg,type| proc { |ability,user,target,move,mults,baseDmg,type|
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.75).round mults[FINAL_DMG_MULT] *= 0.75
} }
) )
@@ -2407,7 +2406,7 @@ BattleHandlers::AbilityOnSwitchOut.add(:NATURALCURE,
BattleHandlers::AbilityOnSwitchOut.add(:REGENERATOR, BattleHandlers::AbilityOnSwitchOut.add(:REGENERATOR,
proc { |ability,battler,endOfBattle| proc { |ability,battler,endOfBattle|
next if !endOfBattle next if endOfBattle
PBDebug.log("[Ability triggered] #{battler.pbThis}'s #{battler.abilityName}") PBDebug.log("[Ability triggered] #{battler.pbThis}'s #{battler.abilityName}")
battler.pbRecoverHP(battler.totalhp/3,false,false) battler.pbRecoverHP(battler.totalhp/3,false,false)
} }
@@ -4,7 +4,7 @@
BattleHandlers::SpeedCalcItem.add(:CHOICESCARF, BattleHandlers::SpeedCalcItem.add(:CHOICESCARF,
proc { |item,battler,mult| proc { |item,battler,mult|
next (mult*1.5).round next mult*1.5
} }
) )
@@ -414,7 +414,7 @@ BattleHandlers::PriorityBracketUseItem.add(:QUICKCLAW,
BattleHandlers::AccuracyCalcUserItem.add(:WIDELENS, BattleHandlers::AccuracyCalcUserItem.add(:WIDELENS,
proc { |item,mods,user,target,move,type| proc { |item,mods,user,target,move,type|
mods[ACC_MULT] = (mods[ACC_MULT]*1.1).round mods[ACC_MULT] *= 1.1
} }
) )
@@ -423,7 +423,7 @@ BattleHandlers::AccuracyCalcUserItem.add(:ZOOMLENS,
if (target.battle.choices[target.index][0]!=:UseMove && if (target.battle.choices[target.index][0]!=:UseMove &&
target.battle.choices[target.index][0]!=:Shift) || target.battle.choices[target.index][0]!=:Shift) ||
target.movedThisRound? target.movedThisRound?
mods[ACC_MULT] = (mods[ACC_MULT]*1.2).round mods[ACC_MULT] *= 1.2
end end
} }
) )
@@ -434,7 +434,7 @@ BattleHandlers::AccuracyCalcUserItem.add(:ZOOMLENS,
BattleHandlers::AccuracyCalcTargetItem.add(:BRIGHTPOWDER, BattleHandlers::AccuracyCalcTargetItem.add(:BRIGHTPOWDER,
proc { |item,mods,user,target,move,type| proc { |item,mods,user,target,move,type|
mods[ACC_MULT] = (mods[ACC_MULT]*0.9).round mods[ACC_MULT] *= 0.9
} }
) )
@@ -448,14 +448,14 @@ BattleHandlers::DamageCalcUserItem.add(:ADAMANTORB,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:DIALGA) && if user.isSpecies?(:DIALGA) &&
(isConst?(type,PBTypes,:DRAGON) || isConst?(type,PBTypes,:STEEL)) (isConst?(type,PBTypes,:DRAGON) || isConst?(type,PBTypes,:STEEL))
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round mults[BASE_DMG_MULT] *= 1.2
end end
} }
) )
BattleHandlers::DamageCalcUserItem.add(:BLACKBELT, BattleHandlers::DamageCalcUserItem.add(:BLACKBELT,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:FIGHTING) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:FIGHTING)
} }
) )
@@ -463,7 +463,7 @@ BattleHandlers::DamageCalcUserItem.copy(:BLACKBELT,:FISTPLATE)
BattleHandlers::DamageCalcUserItem.add(:BLACKGLASSES, BattleHandlers::DamageCalcUserItem.add(:BLACKGLASSES,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:DARK) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:DARK)
} }
) )
@@ -477,7 +477,7 @@ BattleHandlers::DamageCalcUserItem.add(:BUGGEM,
BattleHandlers::DamageCalcUserItem.add(:CHARCOAL, BattleHandlers::DamageCalcUserItem.add(:CHARCOAL,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:FIRE) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:FIRE)
} }
) )
@@ -485,13 +485,13 @@ BattleHandlers::DamageCalcUserItem.copy(:CHARCOAL,:FLAMEPLATE)
BattleHandlers::DamageCalcUserItem.add(:CHOICEBAND, BattleHandlers::DamageCalcUserItem.add(:CHOICEBAND,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round if move.physicalMove? mults[BASE_DMG_MULT] *= 1.5 if move.physicalMove?
} }
) )
BattleHandlers::DamageCalcUserItem.add(:CHOICESPECS, BattleHandlers::DamageCalcUserItem.add(:CHOICESPECS,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round if move.specialMove? mults[BASE_DMG_MULT] *= 1.5 if move.specialMove?
} }
) )
@@ -511,7 +511,7 @@ BattleHandlers::DamageCalcUserItem.add(:DEEPSEATOOTH,
BattleHandlers::DamageCalcUserItem.add(:DRAGONFANG, BattleHandlers::DamageCalcUserItem.add(:DRAGONFANG,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:DRAGON) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:DRAGON)
} }
) )
@@ -532,7 +532,7 @@ BattleHandlers::DamageCalcUserItem.add(:ELECTRICGEM,
BattleHandlers::DamageCalcUserItem.add(:EXPERTBELT, BattleHandlers::DamageCalcUserItem.add(:EXPERTBELT,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
if PBTypes.superEffective?(target.damageState.typeMod) if PBTypes.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.2).round mults[FINAL_DMG_MULT] *= 1.2
end end
} }
) )
@@ -577,7 +577,7 @@ BattleHandlers::DamageCalcUserItem.add(:GRISEOUSORB,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:GIRATINA) && if user.isSpecies?(:GIRATINA) &&
(isConst?(type,PBTypes,:DRAGON) || isConst?(type,PBTypes,:GHOST)) (isConst?(type,PBTypes,:DRAGON) || isConst?(type,PBTypes,:GHOST))
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round mults[BASE_DMG_MULT] *= 1.2
end end
} }
) )
@@ -590,7 +590,7 @@ BattleHandlers::DamageCalcUserItem.add(:GROUNDGEM,
BattleHandlers::DamageCalcUserItem.add(:HARDSTONE, BattleHandlers::DamageCalcUserItem.add(:HARDSTONE,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:ROCK) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:ROCK)
} }
) )
@@ -605,7 +605,7 @@ BattleHandlers::DamageCalcUserItem.add(:ICEGEM,
BattleHandlers::DamageCalcUserItem.add(:LIFEORB, BattleHandlers::DamageCalcUserItem.add(:LIFEORB,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
if !move.is_a?(PokeBattle_Confusion) if !move.is_a?(PokeBattle_Confusion)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.3).round mults[FINAL_DMG_MULT] *= 1.3
end end
} }
) )
@@ -622,14 +622,14 @@ BattleHandlers::DamageCalcUserItem.add(:LUSTROUSORB,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:PALKIA) && if user.isSpecies?(:PALKIA) &&
(isConst?(type,PBTypes,:DRAGON) || isConst?(type,PBTypes,:WATER)) (isConst?(type,PBTypes,:DRAGON) || isConst?(type,PBTypes,:WATER))
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round mults[BASE_DMG_MULT] *= 1.2
end end
} }
) )
BattleHandlers::DamageCalcUserItem.add(:MAGNET, BattleHandlers::DamageCalcUserItem.add(:MAGNET,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:ELECTRIC) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:ELECTRIC)
} }
) )
@@ -637,7 +637,7 @@ BattleHandlers::DamageCalcUserItem.copy(:MAGNET,:ZAPPLATE)
BattleHandlers::DamageCalcUserItem.add(:METALCOAT, BattleHandlers::DamageCalcUserItem.add(:METALCOAT,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:STEEL) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:STEEL)
} }
) )
@@ -646,13 +646,13 @@ BattleHandlers::DamageCalcUserItem.copy(:METALCOAT,:IRONPLATE)
BattleHandlers::DamageCalcUserItem.add(:METRONOME, BattleHandlers::DamageCalcUserItem.add(:METRONOME,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
met = 1+0.2*[user.effects[PBEffects::Metronome],5].min met = 1+0.2*[user.effects[PBEffects::Metronome],5].min
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*met).round mults[FINAL_DMG_MULT] *= met
} }
) )
BattleHandlers::DamageCalcUserItem.add(:MIRACLESEED, BattleHandlers::DamageCalcUserItem.add(:MIRACLESEED,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:GRASS) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:GRASS)
} }
) )
@@ -660,13 +660,13 @@ BattleHandlers::DamageCalcUserItem.copy(:MIRACLESEED,:MEADOWPLATE,:ROSEINCENSE)
BattleHandlers::DamageCalcUserItem.add(:MUSCLEBAND, BattleHandlers::DamageCalcUserItem.add(:MUSCLEBAND,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.1).round if move.physicalMove? mults[BASE_DMG_MULT] *= 1.1 if move.physicalMove?
} }
) )
BattleHandlers::DamageCalcUserItem.add(:MYSTICWATER, BattleHandlers::DamageCalcUserItem.add(:MYSTICWATER,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:WATER) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:WATER)
} }
) )
@@ -674,7 +674,7 @@ BattleHandlers::DamageCalcUserItem.copy(:MYSTICWATER,:SPLASHPLATE,:SEAINCENSE,:W
BattleHandlers::DamageCalcUserItem.add(:NEVERMELTICE, BattleHandlers::DamageCalcUserItem.add(:NEVERMELTICE,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:ICE) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:ICE)
} }
) )
@@ -688,13 +688,13 @@ BattleHandlers::DamageCalcUserItem.add(:NORMALGEM,
BattleHandlers::DamageCalcUserItem.add(:PIXIEPLATE, BattleHandlers::DamageCalcUserItem.add(:PIXIEPLATE,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:FAIRY) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:FAIRY)
} }
) )
BattleHandlers::DamageCalcUserItem.add(:POISONBARB, BattleHandlers::DamageCalcUserItem.add(:POISONBARB,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:POISON) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:POISON)
} }
) )
@@ -720,7 +720,7 @@ BattleHandlers::DamageCalcUserItem.add(:ROCKGEM,
BattleHandlers::DamageCalcUserItem.add(:SHARPBEAK, BattleHandlers::DamageCalcUserItem.add(:SHARPBEAK,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:FLYING) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:FLYING)
} }
) )
@@ -728,13 +728,13 @@ BattleHandlers::DamageCalcUserItem.copy(:SHARPBEAK,:SKYPLATE)
BattleHandlers::DamageCalcUserItem.add(:SILKSCARF, BattleHandlers::DamageCalcUserItem.add(:SILKSCARF,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:NORMAL) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:NORMAL)
} }
) )
BattleHandlers::DamageCalcUserItem.add(:SILVERPOWDER, BattleHandlers::DamageCalcUserItem.add(:SILVERPOWDER,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:BUG) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:BUG)
} }
) )
@@ -742,7 +742,7 @@ BattleHandlers::DamageCalcUserItem.copy(:SILVERPOWDER,:INSECTPLATE)
BattleHandlers::DamageCalcUserItem.add(:SOFTSAND, BattleHandlers::DamageCalcUserItem.add(:SOFTSAND,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:GROUND) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:GROUND)
} }
) )
@@ -753,11 +753,11 @@ BattleHandlers::DamageCalcUserItem.add(:SOULDEW,
next if !user.isSpecies?(:LATIAS) && !user.isSpecies?(:LATIOS) next if !user.isSpecies?(:LATIAS) && !user.isSpecies?(:LATIOS)
if NEWEST_BATTLE_MECHANICS if NEWEST_BATTLE_MECHANICS
if isConst?(type,PBTypes,:PSYCHIC) || isConst?(type,PBTypes,:DRAGON) if isConst?(type,PBTypes,:PSYCHIC) || isConst?(type,PBTypes,:DRAGON)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.2).round mults[FINAL_DMG_MULT] *= 1.2
end end
else else
if move.specialMove? && !user.battle.rules["souldewclause"] if move.specialMove? && !user.battle.rules["souldewclause"]
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round mults[ATK_MULT] *= 1.5
end end
end end
} }
@@ -765,7 +765,7 @@ BattleHandlers::DamageCalcUserItem.add(:SOULDEW,
BattleHandlers::DamageCalcUserItem.add(:SPELLTAG, BattleHandlers::DamageCalcUserItem.add(:SPELLTAG,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:GHOST) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:GHOST)
} }
) )
@@ -787,7 +787,7 @@ BattleHandlers::DamageCalcUserItem.add(:THICKCLUB,
BattleHandlers::DamageCalcUserItem.add(:TWISTEDSPOON, BattleHandlers::DamageCalcUserItem.add(:TWISTEDSPOON,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.2).round if isConst?(type,PBTypes,:PSYCHIC) mults[BASE_DMG_MULT] *= 1.2 if isConst?(type,PBTypes,:PSYCHIC)
} }
) )
@@ -801,7 +801,7 @@ BattleHandlers::DamageCalcUserItem.add(:WATERGEM,
BattleHandlers::DamageCalcUserItem.add(:WISEGLASSES, BattleHandlers::DamageCalcUserItem.add(:WISEGLASSES,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.1).round if move.specialMove? mults[BASE_DMG_MULT] *= 1.1 if move.specialMove?
} }
) )
@@ -814,7 +814,7 @@ BattleHandlers::DamageCalcUserItem.add(:WISEGLASSES,
BattleHandlers::DamageCalcTargetItem.add(:ASSAULTVEST, BattleHandlers::DamageCalcTargetItem.add(:ASSAULTVEST,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round if move.specialMove? mults[DEF_MULT] *= 1.5 if move.specialMove?
} }
) )
@@ -869,7 +869,7 @@ BattleHandlers::DamageCalcTargetItem.add(:EVIOLITE,
# evolve even if the species generally can, and such forms are not # evolve even if the species generally can, and such forms are not
# affected by Eviolite. # affected by Eviolite.
evos = pbGetEvolvedFormData(target.pokemon.fSpecies,true) evos = pbGetEvolvedFormData(target.pokemon.fSpecies,true)
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round if evos && evos.length>0 mults[DEF_MULT] *= 1.5 if evos && evos.length>0
} }
) )
@@ -894,7 +894,7 @@ BattleHandlers::DamageCalcTargetItem.add(:KEBIABERRY,
BattleHandlers::DamageCalcTargetItem.add(:METALPOWDER, BattleHandlers::DamageCalcTargetItem.add(:METALPOWDER,
proc { |item,user,target,move,mults,baseDmg,type| proc { |item,user,target,move,mults,baseDmg,type|
if target.isSpecies?(:DITTO) && !target.effects[PBEffects::Transform] if target.isSpecies?(:DITTO) && !target.effects[PBEffects::Transform]
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round mults[DEF_MULT] *= 1.5
end end
} }
) )
@@ -940,7 +940,7 @@ BattleHandlers::DamageCalcTargetItem.add(:SOULDEW,
next if NEWEST_BATTLE_MECHANICS next if NEWEST_BATTLE_MECHANICS
next if !target.isSpecies?(:LATIAS) && !target.isSpecies?(:LATIOS) next if !target.isSpecies?(:LATIAS) && !target.isSpecies?(:LATIOS)
if move.specialMove? && !user.battle.rules["souldewclause"] if move.specialMove? && !user.battle.rules["souldewclause"]
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round mults[DEF_MULT] *= 1.5
end end
} }
) )
@@ -1003,7 +1003,7 @@ BattleHandlers::TargetItemOnHit.add(:ABSORBBULB,
next if !target.pbCanRaiseStatStage?(PBStats::SPATK,target) next if !target.pbCanRaiseStatStage?(PBStats::SPATK,target)
battle.pbCommonAnimation("UseItem",target) battle.pbCommonAnimation("UseItem",target)
target.pbRaiseStatStageByCause(PBStats::SPATK,1,target,target.itemName) target.pbRaiseStatStageByCause(PBStats::SPATK,1,target,target.itemName)
target.pbConsumeItem target.pbHeldItemTriggered(item)
} }
) )
@@ -1011,6 +1011,7 @@ BattleHandlers::TargetItemOnHit.add(:AIRBALLOON,
proc { |item,user,target,move,battle| proc { |item,user,target,move,battle|
battle.pbDisplay(_INTL("{1}'s {2} popped!",target.pbThis,target.itemName)) battle.pbDisplay(_INTL("{1}'s {2} popped!",target.pbThis,target.itemName))
target.pbConsumeItem(false,true) target.pbConsumeItem(false,true)
target.pbSymbiosis
} }
) )
@@ -1020,7 +1021,7 @@ BattleHandlers::TargetItemOnHit.add(:CELLBATTERY,
next if !target.pbCanRaiseStatStage?(PBStats::ATTACK,target) next if !target.pbCanRaiseStatStage?(PBStats::ATTACK,target)
battle.pbCommonAnimation("UseItem",target) battle.pbCommonAnimation("UseItem",target)
target.pbRaiseStatStageByCause(PBStats::ATTACK,1,target,target.itemName) target.pbRaiseStatStageByCause(PBStats::ATTACK,1,target,target.itemName)
target.pbConsumeItem target.pbHeldItemTriggered(item)
} }
) )
@@ -1028,7 +1029,9 @@ BattleHandlers::TargetItemOnHit.add(:ENIGMABERRY,
proc { |item,user,target,move,battle| proc { |item,user,target,move,battle|
next if target.damageState.substitute || target.damageState.disguise next if target.damageState.substitute || target.damageState.disguise
next if !PBTypes.superEffective?(target.damageState.typeMod) next if !PBTypes.superEffective?(target.damageState.typeMod)
BattleHandlers.triggerTargetItemOnHitPositiveBerry(item,target,battle,false) if BattleHandlers.triggerTargetItemOnHitPositiveBerry(item,target,battle,false)
target.pbHeldItemTriggered(item)
end
} }
) )
@@ -1042,7 +1045,7 @@ BattleHandlers::TargetItemOnHit.add(:JABOCABERRY,
user.pbReduceHP(user.totalhp/8,false) user.pbReduceHP(user.totalhp/8,false)
battle.pbDisplay(_INTL("{1} consumed its {2} and hurt {3}!",target.pbThis, battle.pbDisplay(_INTL("{1} consumed its {2} and hurt {3}!",target.pbThis,
target.itemName,user.pbThis(true))) target.itemName,user.pbThis(true)))
target.pbConsumeItem target.pbHeldItemTriggered(item)
} }
) )
@@ -1054,7 +1057,9 @@ BattleHandlers::TargetItemOnHit.add(:JABOCABERRY,
BattleHandlers::TargetItemOnHit.add(:KEEBERRY, BattleHandlers::TargetItemOnHit.add(:KEEBERRY,
proc { |item,user,target,move,battle| proc { |item,user,target,move,battle|
next if !move.physicalMove? next if !move.physicalMove?
BattleHandlers.triggerTargetItemOnHitPositiveBerry(item,target,battle,false) if BattleHandlers.triggerTargetItemOnHitPositiveBerry(item,target,battle,false)
target.pbHeldItemTriggered(item)
end
} }
) )
@@ -1064,7 +1069,7 @@ BattleHandlers::TargetItemOnHit.add(:LUMINOUSMOSS,
next if !target.pbCanRaiseStatStage?(PBStats::SPDEF,target) next if !target.pbCanRaiseStatStage?(PBStats::SPDEF,target)
battle.pbCommonAnimation("UseItem",target) battle.pbCommonAnimation("UseItem",target)
target.pbRaiseStatStageByCause(PBStats::SPDEF,1,target,target.itemName) target.pbRaiseStatStageByCause(PBStats::SPDEF,1,target,target.itemName)
target.pbConsumeItem target.pbHeldItemTriggered(item)
} }
) )
@@ -1076,7 +1081,9 @@ BattleHandlers::TargetItemOnHit.add(:LUMINOUSMOSS,
BattleHandlers::TargetItemOnHit.add(:MARANGABERRY, BattleHandlers::TargetItemOnHit.add(:MARANGABERRY,
proc { |item,user,target,move,battle| proc { |item,user,target,move,battle|
next if !move.specialMove? next if !move.specialMove?
BattleHandlers.triggerTargetItemOnHitPositiveBerry(item,target,battle,false) if BattleHandlers.triggerTargetItemOnHitPositiveBerry(item,target,battle,false)
target.pbHeldItemTriggered(item)
end
} }
) )
@@ -1100,7 +1107,7 @@ BattleHandlers::TargetItemOnHit.add(:ROWAPBERRY,
user.pbReduceHP(user.totalhp/8,false) user.pbReduceHP(user.totalhp/8,false)
battle.pbDisplay(_INTL("{1} consumed its {2} and hurt {3}!",target.pbThis, battle.pbDisplay(_INTL("{1} consumed its {2} and hurt {3}!",target.pbThis,
target.itemName,user.pbThis(true))) target.itemName,user.pbThis(true)))
target.pbConsumeItem target.pbHeldItemTriggered(item)
} }
) )
@@ -1110,7 +1117,7 @@ BattleHandlers::TargetItemOnHit.add(:SNOWBALL,
next if !target.pbCanRaiseStatStage?(PBStats::ATTACK,target) next if !target.pbCanRaiseStatStage?(PBStats::ATTACK,target)
battle.pbCommonAnimation("UseItem",target) battle.pbCommonAnimation("UseItem",target)
target.pbRaiseStatStageByCause(PBStats::ATTACK,1,target,target.itemName) target.pbRaiseStatStageByCause(PBStats::ATTACK,1,target,target.itemName)
target.pbConsumeItem target.pbHeldItemTriggered(item)
} }
) )
@@ -1147,7 +1154,7 @@ BattleHandlers::TargetItemOnHit.add(:WEAKNESSPOLICY,
if target.pbCanRaiseStatStage?(PBStats::SPATK,target) if target.pbCanRaiseStatStage?(PBStats::SPATK,target)
target.pbRaiseStatStageByCause(PBStats::SPATK,2,target,target.itemName,showAnim) target.pbRaiseStatStageByCause(PBStats::SPATK,2,target,target.itemName,showAnim)
end end
target.pbConsumeItem target.pbHeldItemTriggered(item)
} }
) )
@@ -1509,7 +1516,7 @@ BattleHandlers::EORHealingItem.add(:LEFTOVERS,
BattleHandlers::EOREffectItem.add(:FLAMEORB, BattleHandlers::EOREffectItem.add(:FLAMEORB,
proc { |item,battler,battle| proc { |item,battler,battle|
next if !battler.pbCanBurn?(battler,false) next if !battler.pbCanBurn?(nil,false)
battler.pbBurn(nil,_INTL("{1} was burned by the {2}!",battler.pbThis,battler.itemName)) battler.pbBurn(nil,_INTL("{1} was burned by the {2}!",battler.pbThis,battler.itemName))
} }
) )
@@ -1529,7 +1536,7 @@ BattleHandlers::EOREffectItem.add(:STICKYBARB,
BattleHandlers::EOREffectItem.add(:TOXICORB, BattleHandlers::EOREffectItem.add(:TOXICORB,
proc { |item,battler,battle| proc { |item,battler,battle|
next if !battler.pbCanPoison?(battler,false) next if !battler.pbCanPoison?(nil,false)
battler.pbPoison(nil,_INTL("{1} was badly poisoned by the {2}!", battler.pbPoison(nil,_INTL("{1} was badly poisoned by the {2}!",
battler.pbThis,battler.itemName),true) battler.pbThis,battler.itemName),true)
} }
+436 -416
View File
@@ -54,6 +54,7 @@ module Events
@@OnWildBattleOverride = Event.new @@OnWildBattleOverride = Event.new
@@OnWildBattleEnd = Event.new @@OnWildBattleEnd = Event.new
@@OnTrainerPartyLoad = Event.new @@OnTrainerPartyLoad = Event.new
@@OnChangeDirection = Event.new
# Fires whenever a map is created. Event handler receives two parameters: the # Fires whenever a map is created. Event handler receives two parameters: the
# map (RPG::Map) and the tileset (RPG::Tileset) # map (RPG::Map) and the tileset (RPG::Tileset)
@@ -159,6 +160,10 @@ module Events
# e[2] - Party # e[2] - Party
def self.onTrainerPartyLoad; @@OnTrainerPartyLoad; end def self.onTrainerPartyLoad; @@OnTrainerPartyLoad; end
def self.onTrainerPartyLoad=(v); @@OnTrainerPartyLoad = v; end def self.onTrainerPartyLoad=(v); @@OnTrainerPartyLoad = v; end
# Fires whenever the player changes direction.
def self.onChangeDirection; @@OnChangeDirection; end
def self.onChangeDirection=(v); @@OnChangeDirection = v; end
end end
@@ -254,7 +259,7 @@ Events.onMapUpdate += proc { |_sender,_e|
# Checks per step # Checks per step
#=============================================================================== #===============================================================================
# Party Pokémon gain happiness from walking # Party Pokémon gain happiness from walking
Events.onStepTaken += proc{ Events.onStepTaken += proc {
$PokemonGlobal.happinessSteps = 0 if !$PokemonGlobal.happinessSteps $PokemonGlobal.happinessSteps = 0 if !$PokemonGlobal.happinessSteps
$PokemonGlobal.happinessSteps += 1 $PokemonGlobal.happinessSteps += 1
if $PokemonGlobal.happinessSteps>=128 if $PokemonGlobal.happinessSteps>=128
@@ -363,26 +368,34 @@ def pbOnStepTaken(eventTriggered)
Events.onStepTakenTransferPossible.trigger(nil,handled) Events.onStepTakenTransferPossible.trigger(nil,handled)
return if handled[0] return if handled[0]
pbBattleOnStepTaken(repel) if !eventTriggered && !$game_temp.in_menu pbBattleOnStepTaken(repel) if !eventTriggered && !$game_temp.in_menu
$PokemonTemp.encounterTriggered = false # This info isn't needed
end end
def pbBattleOnStepTaken(repel=false) # Start wild encounters while turning on the spot
return if $Trainer.ablePokemonCount==0 Events.onChangeDirection += proc {
repel = ($PokemonGlobal.repel > 0)
pbBattleOnStepTaken(repel) if !$game_temp.in_menu
}
def pbBattleOnStepTaken(repel = false)
return if $Trainer.ablePokemonCount == 0
encounterType = $PokemonEncounters.pbEncounterType encounterType = $PokemonEncounters.pbEncounterType
return if encounterType<0 return if encounterType < 0
return if !$PokemonEncounters.isEncounterPossibleHere? return if !$PokemonEncounters.isEncounterPossibleHere?
$PokemonTemp.encounterType = encounterType $PokemonTemp.encounterType = encounterType
encounter = $PokemonEncounters.pbGenerateEncounter(encounterType) encounter = $PokemonEncounters.pbGenerateEncounter(encounterType)
encounter = EncounterModifier.trigger(encounter) encounter = EncounterModifier.trigger(encounter)
if $PokemonEncounters.pbCanEncounter?(encounter,repel) if $PokemonEncounters.pbCanEncounter?(encounter, repel)
if !$PokemonTemp.forceSingleBattle && !pbInSafari? && ($PokemonGlobal.partner || if !$PokemonTemp.forceSingleBattle && !pbInSafari? && ($PokemonGlobal.partner ||
($Trainer.ablePokemonCount>1 && PBTerrain.isDoubleWildBattle?(pbGetTerrainTag) && rand(100)<30)) ($Trainer.ablePokemonCount > 1 && PBTerrain.isDoubleWildBattle?(pbGetTerrainTag) && rand(100) < 30))
encounter2 = $PokemonEncounters.pbEncounteredPokemon(encounterType) encounter2 = $PokemonEncounters.pbEncounteredPokemon(encounterType)
encounter2 = EncounterModifier.trigger(encounter2) encounter2 = EncounterModifier.trigger(encounter2)
pbDoubleWildBattle(encounter[0],encounter[1],encounter2[0],encounter2[1]) pbDoubleWildBattle(encounter[0], encounter[1], encounter2[0], encounter2[1])
else else
pbWildBattle(encounter[0],encounter[1]) pbWildBattle(encounter[0], encounter[1])
end end
$PokemonTemp.encounterType = -1 $PokemonTemp.encounterType = -1
$PokemonTemp.encounterTriggered = true
end end
$PokemonTemp.forceSingleBattle = false $PokemonTemp.forceSingleBattle = false
EncounterModifier.triggerEncounterEnd EncounterModifier.triggerEncounterEnd
@@ -489,6 +502,421 @@ Events.onMapSceneChange += proc { |_sender,e|
#===============================================================================
# Event locations, terrain tags
#===============================================================================
def pbEventFacesPlayer?(event,player,distance)
return false if distance<=0
# Event can't reach player if no coordinates coincide
return false if event.x!=player.x && event.y!=player.y
deltaX = (event.direction==6) ? 1 : (event.direction==4) ? -1 : 0
deltaY = (event.direction==2) ? 1 : (event.direction==8) ? -1 : 0
# Check for existence of player
curx = event.x
cury = event.y
found = false
distance.times do
curx += deltaX
cury += deltaY
if player.x==curx && player.y==cury
found = true
break
end
end
return found
end
def pbEventCanReachPlayer?(event,player,distance)
return false if distance<=0
# Event can't reach player if no coordinates coincide
return false if event.x!=player.x && event.y!=player.y
deltaX = (event.direction==6) ? 1 : (event.direction==4) ? -1 : 0
deltaY = (event.direction==2) ? 1 : (event.direction==8) ? -1 : 0
# Check for existence of player
curx = event.x
cury = event.y
found = false
realdist = 0
distance.times do
curx += deltaX
cury += deltaY
if player.x==curx && player.y==cury
found = true
break
end
realdist += 1
end
return false if !found
# Check passibility
curx = event.x
cury = event.y
realdist.times do
return false if !event.passable?(curx,cury,event.direction)
curx += deltaX
cury += deltaY
end
return true
end
def pbFacingTileRegular(direction=nil,event=nil)
event = $game_player if !event
return [0,0,0] if !event
x = event.x
y = event.y
direction = event.direction if !direction
case direction
when 1; y += 1; x -= 1
when 2; y += 1
when 3; y += 1; x += 1
when 4; x -= 1
when 6; x += 1
when 7; y -= 1; x -= 1
when 8; y -= 1
when 9; y -= 1; x += 1
end
return [$game_map.map_id,x,y]
end
def pbFacingTile(direction=nil,event=nil)
return $MapFactory.getFacingTile(direction,event) if $MapFactory
return pbFacingTileRegular(direction,event)
end
def pbFacingEachOther(event1,event2)
return false if !event1 || !event2
if $MapFactory
tile1 = $MapFactory.getFacingTile(nil,event1)
tile2 = $MapFactory.getFacingTile(nil,event2)
return false if !tile1 || !tile2
return tile1[0]==event2.map.map_id &&
tile1[1]==event2.x && tile1[2]==event2.y &&
tile2[0]==event1.map.map_id &&
tile2[1]==event1.x && tile2[2]==event1.y
else
tile1 = pbFacingTile(nil,event1)
tile2 = pbFacingTile(nil,event2)
return false if !tile1 || !tile2
return tile1[1]==event2.x && tile1[2]==event2.y &&
tile2[1]==event1.x && tile2[2]==event1.y
end
end
def pbGetTerrainTag(event=nil,countBridge=false)
event = $game_player if !event
return 0 if !event
if $MapFactory
return $MapFactory.getTerrainTag(event.map.map_id,event.x,event.y,countBridge)
end
$game_map.terrain_tag(event.x,event.y,countBridge)
end
def pbFacingTerrainTag(event=nil,dir=nil)
if $MapFactory
return $MapFactory.getFacingTerrainTag(dir,event)
end
event = $game_player if !event
return 0 if !event
facing = pbFacingTile(dir,event)
return $game_map.terrain_tag(facing[1],facing[2])
end
#===============================================================================
# Events
#===============================================================================
class Game_Event
def cooledDown?(seconds)
return true if expired?(seconds) && tsOff?("A")
self.need_refresh = true
return false
end
def cooledDownDays?(days)
return true if expiredDays?(days) && tsOff?("A")
self.need_refresh = true
return false
end
end
module InterpreterFieldMixin
# Used in boulder events. Allows an event to be pushed. To be used in
# a script event command.
def pbPushThisEvent
event = get_character(0)
oldx = event.x
oldy = event.y
# Apply strict version of passable, which makes impassable
# tiles that are passable only from certain directions
return if !event.passableStrict?(event.x,event.y,$game_player.direction)
case $game_player.direction
when 2; event.move_down # down
when 4; event.move_left # left
when 6; event.move_right # right
when 8; event.move_up # up
end
$PokemonMap.addMovedEvent(@event_id) if $PokemonMap
if oldx!=event.x || oldy!=event.y
$game_player.lock
loop do
Graphics.update
Input.update
pbUpdateSceneMap
break if !event.moving?
end
$game_player.unlock
end
end
def pbPushThisBoulder
pbPushThisEvent if $PokemonMap.strengthUsed
return true
end
def pbSmashThisEvent
event = get_character(0)
pbSmashEvent(event) if event
@index += 1
return true
end
def pbTrainerIntro(symbol)
return if $DEBUG && !pbTrainerTypeCheck(symbol)
trtype = PBTrainers.const_get(symbol)
pbGlobalLock
pbPlayTrainerIntroME(trtype)
return true
end
def pbTrainerEnd
pbGlobalUnlock
e = get_character(0)
e.erase_route if e
end
def pbParams
(@parameters) ? @parameters : @params
end
def pbGetPokemon(id)
return $Trainer.party[pbGet(id)]
end
def pbSetEventTime(*arg)
$PokemonGlobal.eventvars = {} if !$PokemonGlobal.eventvars
time = pbGetTimeNow
time = time.to_i
pbSetSelfSwitch(@event_id,"A",true)
$PokemonGlobal.eventvars[[@map_id,@event_id]]=time
for otherevt in arg
pbSetSelfSwitch(otherevt,"A",true)
$PokemonGlobal.eventvars[[@map_id,otherevt]]=time
end
end
def getVariable(*arg)
if arg.length==0
return nil if !$PokemonGlobal.eventvars
return $PokemonGlobal.eventvars[[@map_id,@event_id]]
else
return $game_variables[arg[0]]
end
end
def setVariable(*arg)
if arg.length==1
$PokemonGlobal.eventvars = {} if !$PokemonGlobal.eventvars
$PokemonGlobal.eventvars[[@map_id,@event_id]]=arg[0]
else
$game_variables[arg[0]] = arg[1]
$game_map.need_refresh = true
end
end
def tsOff?(c)
get_character(0).tsOff?(c)
end
def tsOn?(c)
get_character(0).tsOn?(c)
end
alias isTempSwitchOn? tsOn?
alias isTempSwitchOff? tsOff?
def setTempSwitchOn(c)
get_character(0).setTempSwitchOn(c)
end
def setTempSwitchOff(c)
get_character(0).setTempSwitchOff(c)
end
# Must use this approach to share the methods because the methods already
# defined in a class override those defined in an included module
CustomEventCommands=<<_END_
def command_352
scene = PokemonSave_Scene.new
screen = PokemonSaveScreen.new(scene)
screen.pbSaveScreen
return true
end
def command_125
value = operate_value(pbParams[0], pbParams[1], pbParams[2])
$Trainer.money += value
return true
end
def command_132
($PokemonGlobal.nextBattleBGM = pbParams[0]) ? pbParams[0].clone : nil
return true
end
def command_133
($PokemonGlobal.nextBattleME = pbParams[0]) ? pbParams[0].clone : nil
return true
end
def command_353
pbBGMFade(1.0)
pbBGSFade(1.0)
pbFadeOutIn { pbStartOver(true) }
end
def command_314
pbHealAll if pbParams[0]==0
return true
end
_END_
end
class Interpreter
include InterpreterFieldMixin
eval(InterpreterFieldMixin::CustomEventCommands)
end
class Game_Interpreter
include InterpreterFieldMixin
eval(InterpreterFieldMixin::CustomEventCommands)
end
#===============================================================================
# Audio playing
#===============================================================================
def pbCueBGM(bgm,seconds,volume=nil,pitch=nil)
return if !bgm
bgm = pbResolveAudioFile(bgm,volume,pitch)
playingBGM = $game_system.playing_bgm
if !playingBGM || playingBGM.name!=bgm.name || playingBGM.pitch!=bgm.pitch
pbBGMFade(seconds)
if !$PokemonTemp.cueFrames
$PokemonTemp.cueFrames = (seconds*Graphics.frame_rate)*3/5
end
$PokemonTemp.cueBGM=bgm
elsif playingBGM
pbBGMPlay(bgm)
end
end
def pbAutoplayOnTransition
surfbgm = pbGetMetadata(0,MetadataSurfBGM)
if $PokemonGlobal.surfing && surfbgm
pbBGMPlay(surfbgm)
else
$game_map.autoplayAsCue
end
end
def pbAutoplayOnSave
surfbgm = pbGetMetadata(0,MetadataSurfBGM)
if $PokemonGlobal.surfing && surfbgm
pbBGMPlay(surfbgm)
else
$game_map.autoplay
end
end
#===============================================================================
# Voice recorder
#===============================================================================
def pbRecord(text,maxtime=30.0)
text = "" if !text
textwindow = Window_UnformattedTextPokemon.newWithSize(text,0,0,Graphics.width,Graphics.height-96)
textwindow.z=99999
if text==""
textwindow.visible = false
end
wave = nil
msgwindow = pbCreateMessageWindow
oldvolume = Audio_bgm_get_volume()
Audio_bgm_set_volume(0)
delay = 2
delay.times do |i|
pbMessageDisplay(msgwindow,_INTL("Recording in {1} second(s)...\nPress ESC to cancel.",delay-i),false)
Graphics.frame_rate.times do
Graphics.update
Input.update
textwindow.update
msgwindow.update
if Input.trigger?(Input::B)
Audio_bgm_set_volume(oldvolume)
pbDisposeMessageWindow(msgwindow)
textwindow.dispose
return nil
end
end
end
pbMessageDisplay(msgwindow,_INTL("NOW RECORDING\nPress ESC to stop recording."),false)
if beginRecordUI
frames = (maxtime*Graphics.frame_rate).to_i
frames.times do
Graphics.update
Input.update
textwindow.update
msgwindow.update
if Input.trigger?(Input::B)
break
end
end
tmpFile = ENV["TEMP"]+"\\record.wav"
endRecord(tmpFile)
wave = getWaveDataUI(tmpFile,true)
if wave
pbMessageDisplay(msgwindow,_INTL("PLAYING BACK..."),false)
textwindow.update
msgwindow.update
Graphics.update
Input.update
wave.play
(Graphics.frame_rate*wave.time).to_i.times do
Graphics.update
Input.update
textwindow.update
msgwindow.update
end
end
end
Audio_bgm_set_volume(oldvolume)
pbDisposeMessageWindow(msgwindow)
textwindow.dispose
return wave
end
#=============================================================================== #===============================================================================
# Event movement # Event movement
#=============================================================================== #===============================================================================
@@ -895,414 +1323,6 @@ end
#===============================================================================
# Event locations, terrain tags
#===============================================================================
def pbEventFacesPlayer?(event,player,distance)
return false if distance<=0
# Event can't reach player if no coordinates coincide
return false if event.x!=player.x && event.y!=player.y
deltaX = (event.direction==6) ? 1 : (event.direction==4) ? -1 : 0
deltaY = (event.direction==2) ? 1 : (event.direction==8) ? -1 : 0
# Check for existence of player
curx = event.x
cury = event.y
found = false
distance.times do
curx += deltaX
cury += deltaY
if player.x==curx && player.y==cury
found = true
break
end
end
return found
end
def pbEventCanReachPlayer?(event,player,distance)
return false if distance<=0
# Event can't reach player if no coordinates coincide
return false if event.x!=player.x && event.y!=player.y
deltaX = (event.direction==6) ? 1 : (event.direction==4) ? -1 : 0
deltaY = (event.direction==2) ? 1 : (event.direction==8) ? -1 : 0
# Check for existence of player
curx = event.x
cury = event.y
found = false
realdist = 0
distance.times do
curx += deltaX
cury += deltaY
if player.x==curx && player.y==cury
found = true
break
end
realdist += 1
end
return false if !found
# Check passibility
curx = event.x
cury = event.y
realdist.times do
return false if !event.passable?(curx,cury,event.direction)
curx += deltaX
cury += deltaY
end
return true
end
def pbFacingTileRegular(direction=nil,event=nil)
event = $game_player if !event
return [0,0,0] if !event
x = event.x
y = event.y
direction = event.direction if !direction
case direction
when 1; y += 1; x -= 1
when 2; y += 1
when 3; y += 1; x += 1
when 4; x -= 1
when 6; x += 1
when 7; y -= 1; x -= 1
when 8; y -= 1
when 9; y -= 1; x += 1
end
return [$game_map.map_id,x,y]
end
def pbFacingTile(direction=nil,event=nil)
return $MapFactory.getFacingTile(direction,event) if $MapFactory
return pbFacingTileRegular(direction,event)
end
def pbFacingEachOther(event1,event2)
return false if !event1 || !event2
if $MapFactory
tile1 = $MapFactory.getFacingTile(nil,event1)
tile2 = $MapFactory.getFacingTile(nil,event2)
return false if !tile1 || !tile2
return tile1[0]==event2.map.map_id &&
tile1[1]==event2.x && tile1[2]==event2.y &&
tile2[0]==event1.map.map_id &&
tile2[1]==event1.x && tile2[2]==event1.y
else
tile1 = pbFacingTile(nil,event1)
tile2 = pbFacingTile(nil,event2)
return false if !tile1 || !tile2
return tile1[1]==event2.x && tile1[2]==event2.y &&
tile2[1]==event1.x && tile2[2]==event1.y
end
end
def pbGetTerrainTag(event=nil,countBridge=false)
event = $game_player if !event
return 0 if !event
if $MapFactory
return $MapFactory.getTerrainTag(event.map.map_id,event.x,event.y,countBridge)
end
$game_map.terrain_tag(event.x,event.y,countBridge)
end
def pbFacingTerrainTag(event=nil,dir=nil)
if $MapFactory
return $MapFactory.getFacingTerrainTag(dir,event)
end
event = $game_player if !event
return 0 if !event
facing = pbFacingTile(dir,event)
return $game_map.terrain_tag(facing[1],facing[2])
end
#===============================================================================
# Events
#===============================================================================
class Game_Event
def cooledDown?(seconds)
return true if expired?(seconds) && tsOff?("A")
self.need_refresh = true
return false
end
def cooledDownDays?(days)
return true if expiredDays?(days) && tsOff?("A")
self.need_refresh = true
return false
end
end
module InterpreterFieldMixin
# Used in boulder events. Allows an event to be pushed. To be used in
# a script event command.
def pbPushThisEvent
event = get_character(0)
oldx = event.x
oldy = event.y
# Apply strict version of passable, which makes impassable
# tiles that are passable only from certain directions
return if !event.passableStrict?(event.x,event.y,$game_player.direction)
case $game_player.direction
when 2; event.move_down # down
when 4; event.move_left # left
when 6; event.move_right # right
when 8; event.move_up # up
end
$PokemonMap.addMovedEvent(@event_id) if $PokemonMap
if oldx!=event.x || oldy!=event.y
$game_player.lock
loop do
Graphics.update
Input.update
pbUpdateSceneMap
break if !event.moving?
end
$game_player.unlock
end
end
def pbPushThisBoulder
pbPushThisEvent if $PokemonMap.strengthUsed
return true
end
def pbSmashThisEvent
event = get_character(0)
pbSmashEvent(event) if event
@index += 1
return true
end
def pbTrainerIntro(symbol)
return if $DEBUG && !pbTrainerTypeCheck(symbol)
trtype = PBTrainers.const_get(symbol)
pbGlobalLock
pbPlayTrainerIntroME(trtype)
return true
end
def pbTrainerEnd
pbGlobalUnlock
e = get_character(0)
e.erase_route if e
end
def pbParams
(@parameters) ? @parameters : @params
end
def pbGetPokemon(id)
return $Trainer.party[pbGet(id)]
end
def pbSetEventTime(*arg)
$PokemonGlobal.eventvars = {} if !$PokemonGlobal.eventvars
time = pbGetTimeNow
time = time.to_i
pbSetSelfSwitch(@event_id,"A",true)
$PokemonGlobal.eventvars[[@map_id,@event_id]]=time
for otherevt in arg
pbSetSelfSwitch(otherevt,"A",true)
$PokemonGlobal.eventvars[[@map_id,otherevt]]=time
end
end
def getVariable(*arg)
if arg.length==0
return nil if !$PokemonGlobal.eventvars
return $PokemonGlobal.eventvars[[@map_id,@event_id]]
else
return $game_variables[arg[0]]
end
end
def setVariable(*arg)
if arg.length==1
$PokemonGlobal.eventvars = {} if !$PokemonGlobal.eventvars
$PokemonGlobal.eventvars[[@map_id,@event_id]]=arg[0]
else
$game_variables[arg[0]] = arg[1]
$game_map.need_refresh = true
end
end
def tsOff?(c)
get_character(0).tsOff?(c)
end
def tsOn?(c)
get_character(0).tsOn?(c)
end
alias isTempSwitchOn? tsOn?
alias isTempSwitchOff? tsOff?
def setTempSwitchOn(c)
get_character(0).setTempSwitchOn(c)
end
def setTempSwitchOff(c)
get_character(0).setTempSwitchOff(c)
end
# Must use this approach to share the methods because the methods already
# defined in a class override those defined in an included module
CustomEventCommands=<<_END_
def command_352
scene = PokemonSave_Scene.new
screen = PokemonSaveScreen.new(scene)
screen.pbSaveScreen
return true
end
def command_125
value = operate_value(pbParams[0], pbParams[1], pbParams[2])
$Trainer.money += value
return true
end
def command_132
($PokemonGlobal.nextBattleBGM = pbParams[0]) ? pbParams[0].clone : nil
return true
end
def command_133
($PokemonGlobal.nextBattleME = pbParams[0]) ? pbParams[0].clone : nil
return true
end
def command_353
pbBGMFade(1.0)
pbBGSFade(1.0)
pbFadeOutIn { pbStartOver(true) }
end
def command_314
pbHealAll if pbParams[0]==0
return true
end
_END_
end
class Interpreter
include InterpreterFieldMixin
eval(InterpreterFieldMixin::CustomEventCommands)
end
#===============================================================================
# Audio playing
#===============================================================================
def pbCueBGM(bgm,seconds,volume=nil,pitch=nil)
return if !bgm
bgm = pbResolveAudioFile(bgm,volume,pitch)
playingBGM = $game_system.playing_bgm
if !playingBGM || playingBGM.name!=bgm.name || playingBGM.pitch!=bgm.pitch
pbBGMFade(seconds)
if !$PokemonTemp.cueFrames
$PokemonTemp.cueFrames = (seconds*Graphics.frame_rate)*3/5
end
$PokemonTemp.cueBGM=bgm
elsif playingBGM
pbBGMPlay(bgm)
end
end
def pbAutoplayOnTransition
surfbgm = pbGetMetadata(0,MetadataSurfBGM)
if $PokemonGlobal.surfing && surfbgm
pbBGMPlay(surfbgm)
else
$game_map.autoplayAsCue
end
end
def pbAutoplayOnSave
surfbgm = pbGetMetadata(0,MetadataSurfBGM)
if $PokemonGlobal.surfing && surfbgm
pbBGMPlay(surfbgm)
else
$game_map.autoplay
end
end
#===============================================================================
# Voice recorder
#===============================================================================
def pbRecord(text,maxtime=30.0)
text = "" if !text
textwindow = Window_UnformattedTextPokemon.newWithSize(text,0,0,Graphics.width,Graphics.height-96)
textwindow.z=99999
if text==""
textwindow.visible = false
end
wave = nil
msgwindow = pbCreateMessageWindow
oldvolume = Audio_bgm_get_volume()
Audio_bgm_set_volume(0)
delay = 2
delay.times do |i|
pbMessageDisplay(msgwindow,_INTL("Recording in {1} second(s)...\nPress ESC to cancel.",delay-i),false)
Graphics.frame_rate.times do
Graphics.update
Input.update
textwindow.update
msgwindow.update
if Input.trigger?(Input::B)
Audio_bgm_set_volume(oldvolume)
pbDisposeMessageWindow(msgwindow)
textwindow.dispose
return nil
end
end
end
pbMessageDisplay(msgwindow,_INTL("NOW RECORDING\nPress ESC to stop recording."),false)
if beginRecordUI
frames = (maxtime*Graphics.frame_rate).to_i
frames.times do
Graphics.update
Input.update
textwindow.update
msgwindow.update
if Input.trigger?(Input::B)
break
end
end
tmpFile = ENV["TEMP"]+"\\record.wav"
endRecord(tmpFile)
wave = getWaveDataUI(tmpFile,true)
if wave
pbMessageDisplay(msgwindow,_INTL("PLAYING BACK..."),false)
textwindow.update
msgwindow.update
Graphics.update
Input.update
wave.play
(Graphics.frame_rate*wave.time).to_i.times do
Graphics.update
Input.update
textwindow.update
msgwindow.update
end
end
end
Audio_bgm_set_volume(oldvolume)
pbDisposeMessageWindow(msgwindow)
textwindow.dispose
return wave
end
#=============================================================================== #===============================================================================
# Picking up an item found on the ground # Picking up an item found on the ground
#=============================================================================== #===============================================================================
+225 -225
View File
@@ -1,228 +1,3 @@
#===============================================================================
# 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.height = 64
@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 # Battle start animation
#=============================================================================== #===============================================================================
@@ -541,6 +316,231 @@ def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
end end
#===============================================================================
# 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))
}
#=============================================================================== #===============================================================================
# Entering/exiting cave animations # Entering/exiting cave animations
#=============================================================================== #===============================================================================
@@ -11,6 +11,7 @@ end
class PokemonTemp class PokemonTemp
attr_accessor :encounterTriggered
attr_accessor :encounterType attr_accessor :encounterType
attr_accessor :evolutionLevels attr_accessor :evolutionLevels
@@ -34,8 +35,8 @@ class PokemonTemp
when "canrun"; rules["canRun"] = true when "canrun"; rules["canRun"] = true
when "cannotrun"; rules["canRun"] = false when "cannotrun"; rules["canRun"] = false
when "roamerflees"; rules["roamerFlees"] = true when "roamerflees"; rules["roamerFlees"] = true
when "noExp"; rules["expGain"] = false when "noexp"; rules["expGain"] = false
when "noMoney"; rules["moneyGain"] = false when "nomoney"; rules["moneyGain"] = false
when "switchstyle"; rules["switchStyle"] = true when "switchstyle"; rules["switchStyle"] = true
when "setstyle"; rules["switchStyle"] = false when "setstyle"; rules["switchStyle"] = false
when "anims"; rules["battleAnims"] = true when "anims"; rules["battleAnims"] = true
@@ -45,7 +46,7 @@ class PokemonTemp
when "environment", "environ"; rules["environment"] = getID(PBEnvironment,var) when "environment", "environ"; rules["environment"] = getID(PBEnvironment,var)
when "backdrop", "battleback"; rules["backdrop"] = var when "backdrop", "battleback"; rules["backdrop"] = var
when "base"; rules["base"] = var when "base"; rules["base"] = var
when "outcomevar", "outcome"; rules["outcomeVar"] = var when "outcome", "outcomevar"; rules["outcomeVar"] = var
when "nopartner"; rules["noPartner"] = true when "nopartner"; rules["noPartner"] = true
else else
raise _INTL("Battle rule \"{1}\" does not exist.",rule) raise _INTL("Battle rule \"{1}\" does not exist.",rule)
@@ -64,7 +65,7 @@ def setBattleRule(*args)
else else
case arg.downcase case arg.downcase
when "terrain", "weather", "environment", "environ", "backdrop", when "terrain", "weather", "environment", "environ", "backdrop",
"battleback", "base", "outcomevar", "outcome" "battleback", "base", "outcome", "outcomevar"
r = arg r = arg
next next
end end
@@ -251,7 +252,12 @@ def pbWildBattleCore(*args)
playerTrainers = [$Trainer] playerTrainers = [$Trainer]
playerParty = $Trainer.party playerParty = $Trainer.party
playerPartyStarts = [0] playerPartyStarts = [0]
if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && foeParty.length>1 room_for_partner = (foeParty.length > 1)
if !room_for_partner && $PokemonTemp.battleRules["size"] &&
!["single", "1v1", "1v2", "1v3"].include?($PokemonTemp.battleRules["size"])
room_for_partner = true
end
if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && room_for_partner
ally = PokeBattle_Trainer.new($PokemonGlobal.partner[1],$PokemonGlobal.partner[0]) ally = PokeBattle_Trainer.new($PokemonGlobal.partner[1],$PokemonGlobal.partner[0])
ally.id = $PokemonGlobal.partner[2] ally.id = $PokemonGlobal.partner[2]
ally.party = $PokemonGlobal.partner[3] ally.party = $PokemonGlobal.partner[3]
@@ -391,7 +397,12 @@ def pbTrainerBattleCore(*args)
playerTrainers = [$Trainer] playerTrainers = [$Trainer]
playerParty = $Trainer.party playerParty = $Trainer.party
playerPartyStarts = [0] playerPartyStarts = [0]
if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && foeParty.length>1 room_for_partner = (foeParty.length > 1)
if !room_for_partner && $PokemonTemp.battleRules["size"] &&
!["single", "1v1", "1v2", "1v3"].include?($PokemonTemp.battleRules["size"])
room_for_partner = true
end
if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && room_for_partner
ally = PokeBattle_Trainer.new($PokemonGlobal.partner[1],$PokemonGlobal.partner[0]) ally = PokeBattle_Trainer.new($PokemonGlobal.partner[1],$PokemonGlobal.partner[0])
ally.id = $PokemonGlobal.partner[2] ally.id = $PokemonGlobal.partner[2]
ally.party = $PokemonGlobal.partner[3] ally.party = $PokemonGlobal.partner[3]
@@ -553,6 +564,7 @@ def pbAfterBattle(decision,canLose)
end end
end end
Events.onEndBattle.trigger(nil,decision,canLose) Events.onEndBattle.trigger(nil,decision,canLose)
$game_player.straighten
end end
Events.onEndBattle += proc { |_sender,e| Events.onEndBattle += proc { |_sender,e|
@@ -241,6 +241,6 @@ def pbRoamingPokemonBattle(species, level)
return (decision!=2 && decision!=5) return (decision!=2 && decision!=5)
end end
EncounterModifier.registerEncounterEnd(proc{ EncounterModifier.registerEncounterEnd(proc {
$PokemonTemp.roamerIndex = nil $PokemonTemp.roamerIndex = nil
}) })
@@ -393,7 +393,7 @@ Events.onAction += proc { |_sender,_e|
divemap = i; break divemap = i; break
end end
end end
if PBTerrain.isDeepWater?($MapFactory.getTerrainTag(divemap,$game_player.x,$game_player.y)) if divemap && PBTerrain.isDeepWater?($MapFactory.getTerrainTag(divemap,$game_player.x,$game_player.y))
pbSurfacing pbSurfacing
end end
end end
@@ -2,7 +2,7 @@ class PokemonTemp
attr_writer :dependentEvents attr_writer :dependentEvents
def dependentEvents def dependentEvents
@dependentEvents=DependentEvents.new if !@dependentEvents @dependentEvents = DependentEvents.new if !@dependentEvents
return @dependentEvents return @dependentEvents
end end
end end
@@ -41,7 +41,8 @@ class PokemonGlobalMetadata
attr_writer :dependentEvents attr_writer :dependentEvents
def dependentEvents def dependentEvents
return @dependentEvents || [] @dependentEvents = [] if !@dependentEvents
return @dependentEvents
end end
end end
@@ -112,9 +112,9 @@ ItemHandlers::UseInField.add(:MAXREPEL,proc { |item|
next pbRepel(item,250) next pbRepel(item,250)
}) })
Events.onStepTaken += proc{ Events.onStepTaken += proc {
if !PBTerrain.isIce?($game_player.terrain_tag) # Shouldn't count down if on ice if $PokemonGlobal.repel>0
if $PokemonGlobal.repel>0 if !PBTerrain.isIce?($game_player.terrain_tag) # Shouldn't count down if on ice
$PokemonGlobal.repel -= 1 $PokemonGlobal.repel -= 1
if $PokemonGlobal.repel<=0 if $PokemonGlobal.repel<=0
if $PokemonBag.pbHasItem?(:REPEL) || if $PokemonBag.pbHasItem?(:REPEL) ||
@@ -955,6 +955,7 @@ ItemHandlers::UseOnPokemon.add(:DNASPLICERS,proc { |item,pkmn,scene|
end end
if pkmn.fainted? if pkmn.fainted?
scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon.")) scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon."))
next false
end end
# Fusing # Fusing
if pkmn.fused==nil if pkmn.fused==nil
@@ -963,13 +964,17 @@ ItemHandlers::UseOnPokemon.add(:DNASPLICERS,proc { |item,pkmn,scene|
poke2 = $Trainer.party[chosen] poke2 = $Trainer.party[chosen]
if pkmn==poke2 if pkmn==poke2
scene.pbDisplay(_INTL("It cannot be fused with itself.")) scene.pbDisplay(_INTL("It cannot be fused with itself."))
next false
elsif poke2.egg? elsif poke2.egg?
scene.pbDisplay(_INTL("It cannot be fused with an Egg.")) scene.pbDisplay(_INTL("It cannot be fused with an Egg."))
next false
elsif poke2.fainted? elsif poke2.fainted?
scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon.")) scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon."))
next false
elsif !poke2.isSpecies?(:RESHIRAM) && elsif !poke2.isSpecies?(:RESHIRAM) &&
!poke2.isSpecies?(:ZEKROM) !poke2.isSpecies?(:ZEKROM)
scene.pbDisplay(_INTL("It cannot be fused with that Pokémon.")) scene.pbDisplay(_INTL("It cannot be fused with that Pokémon."))
next false
end end
newForm = 0 newForm = 0
newForm = 1 if poke2.isSpecies?(:RESHIRAM) newForm = 1 if poke2.isSpecies?(:RESHIRAM)
@@ -997,12 +1002,13 @@ ItemHandlers::UseOnPokemon.add(:DNASPLICERS,proc { |item,pkmn,scene|
}) })
ItemHandlers::UseOnPokemon.add(:NSOLARIZER,proc { |item,pkmn,scene| ItemHandlers::UseOnPokemon.add(:NSOLARIZER,proc { |item,pkmn,scene|
if !pkmn.isSpecies?(:NECROZMA) || pkmn.form==0 if !pkmn.isSpecies?(:NECROZMA) || pkmn.form == 2
scene.pbDisplay(_INTL("It had no effect.")) scene.pbDisplay(_INTL("It had no effect."))
next false next false
end end
if pkmn.fainted? if pkmn.fainted?
scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon.")) scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon."))
next false
end end
# Fusing # Fusing
if pkmn.fused==nil if pkmn.fused==nil
@@ -1011,12 +1017,16 @@ ItemHandlers::UseOnPokemon.add(:NSOLARIZER,proc { |item,pkmn,scene|
poke2 = $Trainer.party[chosen] poke2 = $Trainer.party[chosen]
if pkmn==poke2 if pkmn==poke2
scene.pbDisplay(_INTL("It cannot be fused with itself.")) scene.pbDisplay(_INTL("It cannot be fused with itself."))
next false
elsif poke2.egg? elsif poke2.egg?
scene.pbDisplay(_INTL("It cannot be fused with an Egg.")) scene.pbDisplay(_INTL("It cannot be fused with an Egg."))
next false
elsif poke2.fainted? elsif poke2.fainted?
scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon.")) scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon."))
next false
elsif !poke2.isSpecies?(:SOLGALEO) elsif !poke2.isSpecies?(:SOLGALEO)
scene.pbDisplay(_INTL("It cannot be fused with that Pokémon.")) scene.pbDisplay(_INTL("It cannot be fused with that Pokémon."))
next false
end end
pkmn.setForm(1) { pkmn.setForm(1) {
pkmn.fused = poke2 pkmn.fused = poke2
@@ -1041,12 +1051,13 @@ ItemHandlers::UseOnPokemon.add(:NSOLARIZER,proc { |item,pkmn,scene|
}) })
ItemHandlers::UseOnPokemon.add(:NLUNARIZER,proc { |item,pkmn,scene| ItemHandlers::UseOnPokemon.add(:NLUNARIZER,proc { |item,pkmn,scene|
if !pkmn.isSpecies?(:NECROZMA) || pkmn.form==1 if !pkmn.isSpecies?(:NECROZMA) || pkmn.form == 1
scene.pbDisplay(_INTL("It had no effect.")) scene.pbDisplay(_INTL("It had no effect."))
next false next false
end end
if pkmn.fainted? if pkmn.fainted?
scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon.")) scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon."))
next false
end end
# Fusing # Fusing
if pkmn.fused==nil if pkmn.fused==nil
@@ -1055,12 +1066,16 @@ ItemHandlers::UseOnPokemon.add(:NLUNARIZER,proc { |item,pkmn,scene|
poke2 = $Trainer.party[chosen] poke2 = $Trainer.party[chosen]
if pkmn==poke2 if pkmn==poke2
scene.pbDisplay(_INTL("It cannot be fused with itself.")) scene.pbDisplay(_INTL("It cannot be fused with itself."))
next false
elsif poke2.egg? elsif poke2.egg?
scene.pbDisplay(_INTL("It cannot be fused with an Egg.")) scene.pbDisplay(_INTL("It cannot be fused with an Egg."))
next false
elsif poke2.fainted? elsif poke2.fainted?
scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon.")) scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon."))
next false
elsif !poke2.isSpecies?(:LUNALA) elsif !poke2.isSpecies?(:LUNALA)
scene.pbDisplay(_INTL("It cannot be fused with that Pokémon.")) scene.pbDisplay(_INTL("It cannot be fused with that Pokémon."))
next false
end end
pkmn.setForm(2) { pkmn.setForm(2) {
pkmn.fused = poke2 pkmn.fused = poke2
@@ -37,15 +37,6 @@ class PokeBattle_Pokemon
return pbGetFSpeciesFromForm(@species,formSimple) return pbGetFSpeciesFromForm(@species,formSimple)
end end
alias __mf_compatibleWithMove? compatibleWithMove? # Deprecated
def compatibleWithMove?(move)
v = MultipleForms.call("getMoveCompatibility",self)
if v!=nil
return v.any? { |j| j==move }
end
return __mf_compatibleWithMove?(move)
end
alias __mf_initialize initialize alias __mf_initialize initialize
def initialize(*args) def initialize(*args)
@form = (pbGetSpeciesFromFSpecies(args[0])[1] rescue 0) @form = (pbGetSpeciesFromFSpecies(args[0])[1] rescue 0)
+7 -1
View File
@@ -165,9 +165,15 @@ class PokemonRegionMap_Scene
def pbSaveMapData def pbSaveMapData
File.open("PBS/townmap.txt","wb") { |f| File.open("PBS/townmap.txt","wb") { |f|
f.write(0xEF.chr)
f.write(0xBB.chr)
f.write(0xBF.chr)
f.write("\# "+_INTL("See the documentation on the wiki to learn how to edit this file."))
f.write("\r\n")
for i in 0...@mapdata.length for i in 0...@mapdata.length
map = @mapdata[i] map = @mapdata[i]
return if !map next if !map
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n",i)) f.write(sprintf("[%d]\r\n",i))
f.write(sprintf("Name=%s\r\nFilename=%s\r\n",csvQuote(map[0]),csvQuote(map[1]))) f.write(sprintf("Name=%s\r\nFilename=%s\r\n",csvQuote(map[0]),csvQuote(map[1])))
for loc in map[2] for loc in map[2]
@@ -77,7 +77,7 @@ def pbAddPokemon(pokemon,level=nil,seeform=true)
pokemon = pbNewPkmn(pokemon,level) pokemon = pbNewPkmn(pokemon,level)
end end
speciesname = PBSpecies.getName(pokemon.species) speciesname = PBSpecies.getName(pokemon.species)
pbMessage(_INTL("\\me[Pkmn get]{1} obtained {2}!\1",$Trainer.name,speciesname)) pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[80]\1",$Trainer.name,speciesname))
pbNicknameAndStore(pokemon) pbNicknameAndStore(pokemon)
pbSeenForm(pokemon) if seeform pbSeenForm(pokemon) if seeform
return true return true
@@ -113,7 +113,7 @@ def pbAddToParty(pokemon,level=nil,seeform=true)
pokemon = pbNewPkmn(pokemon,level) pokemon = pbNewPkmn(pokemon,level)
end end
speciesname = PBSpecies.getName(pokemon.species) speciesname = PBSpecies.getName(pokemon.species)
pbMessage(_INTL("\\me[Pkmn get]{1} obtained {2}!\1",$Trainer.name,speciesname)) pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[80]\1",$Trainer.name,speciesname))
pbNicknameAndStore(pokemon) pbNicknameAndStore(pokemon)
pbSeenForm(pokemon) if seeform pbSeenForm(pokemon) if seeform
return true return true
@@ -286,7 +286,7 @@ end
#=============================================================================== #===============================================================================
# JavaScript-related utilities # Json-related utilities
#=============================================================================== #===============================================================================
# Returns true if the given string represents a valid object in JavaScript # Returns true if the given string represents a valid object in JavaScript
# Object Notation, and false otherwise. # Object Notation, and false otherwise.
@@ -1172,10 +1172,10 @@ def pbLoadRpgxpScene(scene)
end end
Graphics.transition(20) Graphics.transition(20)
Graphics.freeze Graphics.freeze
oldscene.createSpritesets $scene = oldscene
$scene.createSpritesets
pbShowObjects(visibleObjects) pbShowObjects(visibleObjects)
Graphics.transition(20) Graphics.transition(20)
$scene = oldscene
end end
+6 -2
View File
@@ -208,6 +208,8 @@ def pbDebugMenuCommands(showall=true)
_INTL("Fully compile all data.")) _INTL("Fully compile all data."))
commands.add("othermenu","debugconsole",_INTL("Debug Console"), commands.add("othermenu","debugconsole",_INTL("Debug Console"),
_INTL("Open the Debug Console.")) _INTL("Open the Debug Console."))
commands.add("othermenu","invalidtiles",_INTL("Fix Invalid Tiles"),
_INTL("Scans all maps and erases non-existent tiles."))
return commands return commands
end end
@@ -348,7 +350,7 @@ def pbDebugMenuActions(cmd="",sprites=nil,viewport=nil)
params.setCancelValue(0) params.setCancelValue(0)
level = pbMessageChooseNumber(_INTL("Set the wild {1}'s level.",PBSpecies.getName(species)),params) level = pbMessageChooseNumber(_INTL("Set the wild {1}'s level.",PBSpecies.getName(species)),params)
if level>0 if level>0
pkmn.push(pbNewPkmn(species,level)) pkmn.push(pbGenerateWildPokemon(species,level))
end end
end end
else # Edit a Pokémon else # Edit a Pokémon
@@ -366,7 +368,7 @@ def pbDebugMenuActions(cmd="",sprites=nil,viewport=nil)
battle = pbListScreen(_INTL("SINGLE TRAINER"),TrainerBattleLister.new(0,false)) battle = pbListScreen(_INTL("SINGLE TRAINER"),TrainerBattleLister.new(0,false))
if battle if battle
trainerdata = battle[1] trainerdata = battle[1]
pbTrainerBattle(trainerdata[0],trainerdata[1],"...",false,trainerdata[4],true) pbTrainerBattle(trainerdata[0],trainerdata[1],nil,false,trainerdata[4],true)
end end
when "testtrainerbattleadvanced" when "testtrainerbattleadvanced"
trainers = [] trainers = []
@@ -795,6 +797,8 @@ def pbDebugMenuActions(cmd="",sprites=nil,viewport=nil)
pbDisposeMessageWindow(msgwindow) pbDisposeMessageWindow(msgwindow)
when "debugconsole" when "debugconsole"
Console::setup_console Console::setup_console
when "invalidtiles"
pbDebugFixInvalidTiles
end end
return false return false
end end
+80 -3
View File
@@ -82,9 +82,16 @@ class SpriteWindow_DebugVariables < Window_DrawableCommand
name = $data_system.switches[index+1] name = $data_system.switches[index+1]
codeswitch = (name[/^s\:/]) codeswitch = (name[/^s\:/])
val = (codeswitch) ? (eval($~.post_match) rescue nil) : $game_switches[index+1] val = (codeswitch) ? (eval($~.post_match) rescue nil) : $game_switches[index+1]
if val==nil; status = "[-]"; colors = 0; codeswitch = true if val==nil
elsif val; status = "[ON]"; colors = 2 status = "[-]"
else; status = "[OFF]"; colors = 1 colors = 0
codeswitch = true
elsif val
status = "[ON]"
colors = 2
else
status = "[OFF]"
colors = 1
end end
else else
name = $data_system.variables[index+1] name = $data_system.variables[index+1]
@@ -791,6 +798,76 @@ def pbImportAllAnimations
end end
end end
#===============================================================================
# Properly erases all non-existent tiles in maps (including event graphics)
#===============================================================================
def pbDebugFixInvalidTiles
num_errors = 0
num_error_maps = 0
@tilesets = pbLoadRxData("Data/Tilesets")
mapData = MapData.new
t = Time.now.to_i
Graphics.update
for id in mapData.mapinfos.keys.sort
if Time.now.to_i - t >= 5
Graphics.update
t = Time.now.to_i
end
changed = false
map = mapData.getMap(id)
next if !map || !mapData.mapinfos[id]
Win32API.SetWindowText(_INTL("Processing map {1} ({2})", id, mapData.mapinfos[id].name))
passages = mapData.getTilesetPassages(map, id)
# Check all tiles in map for non-existent tiles
for x in 0...map.data.xsize
for y in 0...map.data.ysize
for i in 0...map.data.zsize
tile_id = map.data[x, y, i]
next if pbCheckTileValidity(tile_id, map, @tilesets, passages)
map.data[x, y, i] = 0
changed = true
num_errors += 1
end
end
end
# Check all events in map for page graphics using a non-existent tile
for key in map.events.keys
event = map.events[key]
for page in event.pages
next if page.graphic.tile_id <= 0
next if pbCheckTileValidity(page.graphic.tile_id, map, @tilesets, passages)
page.graphic.tile_id = 0
changed = true
num_errors += 1
end
end
next if !changed
# Map was changed; save it
num_error_maps += 1
mapData.saveMap(id)
end
if num_error_maps == 0
pbMessage(_INTL("No invalid tiles were found."))
else
pbMessage(_INTL("{1} error(s) were found across {2} map(s) and fixed.", num_errors, num_error_maps))
pbMessage(_INTL("Close RPG Maker XP to ensure the changes are applied properly."))
end
end
def pbCheckTileValidity(tile_id, map, tilesets, passages)
return false if !tile_id
if tile_id > 0 && tile_id < 384
# Check for defined autotile
autotile_id = tile_id / 48 - 1
autotile_name = tilesets[map.tileset_id].autotile_names[autotile_id]
return true if autotile_name && autotile_name != ""
else
# Check for tileset data
return true if passages[tile_id]
end
return false
end
#=============================================================================== #===============================================================================
@@ -669,13 +669,6 @@ def pbItemEditorNew(defaultname)
itemdata = pbLoadItemsData itemdata = pbLoadItemsData
# Get the first blank ID for the new item to use. # Get the first blank ID for the new item to use.
maxid = PBItems.maxValue+1 maxid = PBItems.maxValue+1
for i in 1..PBItems.maxValue
name = itemdata[i][1]
if !name || name=="" || itemdata[i][ITEM_POCKET]==0
maxid = i
break
end
end
index = maxid index = maxid
itemname = pbMessageFreeText(_INTL("Please enter the item's name."), itemname = pbMessageFreeText(_INTL("Please enter the item's name."),
(defaultname) ? defaultname.gsub(/_+/," ") : "",false,30) (defaultname) ? defaultname.gsub(/_+/," ") : "",false,30)
+17 -11
View File
@@ -550,7 +550,7 @@ def pbSaveTownMap
f.write("\r\n") f.write("\r\n")
for i in 0...mapdata.length for i in 0...mapdata.length
map = mapdata[i] map = mapdata[i]
return if !map next if !map
f.write("\#-------------------------------\r\n") f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n",i)) f.write(sprintf("[%d]\r\n",i))
rname = pbGetMessage(MessageTypes::RegionNames,i) rname = pbGetMessage(MessageTypes::RegionNames,i)
@@ -839,11 +839,14 @@ def pbSavePokemonData
pokedata.write(",") if count>0 pokedata.write(",") if count>0
pokedata.write(sprintf("%s,%s,",cnew_species,evoname)) pokedata.write(sprintf("%s,%s,",cnew_species,evoname))
param_type = PBEvolution.getFunction(method, "parameterType") param_type = PBEvolution.getFunction(method, "parameterType")
if param_type has_param = !PBEvolution.hasFunction?(method, "parameterType") || param_type != nil
cparameter = getConstantName(param_type,parameter) rescue "" if has_param
pokedata.write("#{cparameter}") if param_type
else cparameter = (getConstantName(param_type, parameter) rescue parameter)
pokedata.write("#{parameter}") pokedata.write("#{cparameter}")
else
pokedata.write("#{parameter}")
end
end end
count += 1 count += 1
end end
@@ -1299,11 +1302,14 @@ def pbSavePokemonFormsData
next if !cnew_species || cnew_species=="" next if !cnew_species || cnew_species==""
pokedata.write(sprintf("%s,%s,",cnew_species,evoname)) pokedata.write(sprintf("%s,%s,",cnew_species,evoname))
param_type = PBEvolution.getFunction(method, "parameterType") param_type = PBEvolution.getFunction(method, "parameterType")
if param_type has_param = !PBEvolution.hasFunction?(method, "parameterType") || param_type != nil
cparameter = getConstantName(param_type,parameter) rescue "" if has_param
pokedata.write("#{cparameter}") if param_type
else cparameter = (getConstantName(param_type, parameter) rescue parameter)
pokedata.write("#{parameter}") pokedata.write("#{cparameter}")
else
pokedata.write("#{parameter}")
end
end end
pokedata.write(",") if k<evos.length-1 pokedata.write(",") if k<evos.length-1
end end
@@ -407,6 +407,7 @@ class ItemLister
@itemdata = pbLoadItemsData @itemdata = pbLoadItemsData
cmds = [] cmds = []
for i in 1..PBItems.maxValue for i in 1..PBItems.maxValue
next if !@itemdata[i]
name = @itemdata[i][ITEM_NAME] name = @itemdata[i][ITEM_NAME]
if name && name!="" && @itemdata[i][ITEM_POCKET]!=0 if name && name!="" && @itemdata[i][ITEM_POCKET]!=0
cmds.push([i,name]) cmds.push([i,name])
@@ -3093,8 +3093,8 @@ class PointPath
return ret return ret
end end
step=1.0/frames step=1.0/frames
t=0.0; t=0.0
for i in 0..frames+1 (frames+2).times do
point=pointOnPath(t) point=pointOnPath(t)
if roundValues if roundValues
ret.addPoint(point[0].round,point[1].round) ret.addPoint(point[0].round,point[1].round)
@@ -793,6 +793,7 @@ end
def pbGetConst(mod,item,err) def pbGetConst(mod,item,err)
isDef = false isDef = false
begin begin
mod = Object.const_get(mod) if mod.is_a?(Symbol)
isDef = mod.const_defined?(item.to_sym) isDef = mod.const_defined?(item.to_sym)
rescue rescue
raise sprintf(err,item) raise sprintf(err,item)
@@ -802,6 +803,7 @@ def pbGetConst(mod,item,err)
end end
def getConstantName(mod,value) def getConstantName(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants for c in mod.constants
return c if mod.const_get(c.to_sym)==value return c if mod.const_get(c.to_sym)==value
end end
@@ -809,6 +811,7 @@ def getConstantName(mod,value)
end end
def getConstantNameOrValue(mod,value) def getConstantNameOrValue(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants for c in mod.constants
return c if mod.const_get(c.to_sym)==value return c if mod.const_get(c.to_sym)==value
end end
@@ -816,6 +819,7 @@ def getConstantNameOrValue(mod,value)
end end
def setConstantName(mod,value,name) def setConstantName(mod,value,name)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants for c in mod.constants
mod.send(:remove_const,c.to_sym) if mod.const_get(c.to_sym)==value mod.send(:remove_const,c.to_sym) if mod.const_get(c.to_sym)==value
end end
@@ -823,6 +827,7 @@ def setConstantName(mod,value,name)
end end
def removeConstantValue(mod,value) def removeConstantValue(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants for c in mod.constants
mod.send(:remove_const,c.to_sym) if mod.const_get(c.to_sym)==value mod.send(:remove_const,c.to_sym) if mod.const_get(c.to_sym)==value
end end
+46 -25
View File
@@ -13,20 +13,22 @@ def pbCompileMetadata
sectionname = $~[1] sectionname = $~[1]
if currentmap==0 if currentmap==0
if sections[currentmap][MetadataHome]==nil if sections[currentmap][MetadataHome]==nil
raise _INTL("The entry Home is required in metadata.txt section [{1}]",sectionname) raise _INTL("The entry Home is required in metadata.txt section [{1}].",sectionname)
end elsif sections[currentmap][MetadataPlayerA]==nil
if sections[currentmap][MetadataPlayerA]==nil raise _INTL("The entry PlayerA is required in metadata.txt section [{1}].",sectionname)
raise _INTL("The entry PlayerA is required in metadata.txt section [{1}]",sectionname)
end end
end end
currentmap = sectionname.to_i currentmap = sectionname.to_i
if sections[currentmap]
raise _INTL("Section [{1}] is defined twice in metadata.txt.\r\n{2}",currentmap,FileLineData.linereport)
end
sections[currentmap] = [] sections[currentmap] = []
else else
if currentmap<0 if currentmap<0
raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport) raise _INTL("Expected a section at the beginning of the file.\r\n{1}",FileLineData.linereport)
end end
if !line[/^\s*(\w+)\s*=\s*(.*)$/] if !line[/^\s*(\w+)\s*=\s*(.*)$/]
raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport) raise _INTL("Bad line syntax (expected syntax like XXX=YYY).\r\n{1}",FileLineData.linereport)
end end
matchData = $~ matchData = $~
schema = nil schema = nil
@@ -354,7 +356,7 @@ def pbCompileTypes
if currentmap>=0 if currentmap>=0
for reqtype in requiredtypes.keys for reqtype in requiredtypes.keys
if !foundtypes.include?(reqtype) if !foundtypes.include?(reqtype)
raise _INTL("Required value '{1}' not given in section '{2}'\r\n{3}",reqtype,currentmap,FileLineData.linereport) raise _INTL("Required value '{1}' not given in section [{2}].\r\n{3}",reqtype,currentmap,FileLineData.linereport)
end end
end end
foundtypes.clear foundtypes.clear
@@ -363,10 +365,10 @@ def pbCompileTypes
types[currentmap] = [currentmap,nil,nil,false,false,[],[],[]] types[currentmap] = [currentmap,nil,nil,false,false,[],[],[]]
else else
if currentmap<0 if currentmap<0
raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport) raise _INTL("Expected a section at the beginning of the file.\r\n{1}",FileLineData.linereport)
end end
if !line[/^\s*(\w+)\s*=\s*(.*)$/] if !line[/^\s*(\w+)\s*=\s*(.*)$/]
raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport) raise _INTL("Bad line syntax (expected syntax like XXX=YYY).\r\n{1}",FileLineData.linereport)
end end
matchData = $~ matchData = $~
schema = nil schema = nil
@@ -401,17 +403,17 @@ def pbCompileTypes
n = type[1] n = type[1]
for w in type[5] for w in type[5]
if !typeinames.include?(w) if !typeinames.include?(w)
raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Weaknesses)",w,n) raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Weaknesses).",w,n)
end end
end end
for w in type[6] for w in type[6]
if !typeinames.include?(w) if !typeinames.include?(w)
raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Resistances)",w,n) raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Resistances).",w,n)
end end
end end
for w in type[7] for w in type[7]
if !typeinames.include?(w) if !typeinames.include?(w)
raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Immunities)",w,n) raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Immunities).",w,n)
end end
end end
end end
@@ -463,6 +465,9 @@ def pbCompileAbilities
maxValue = 0 maxValue = 0
pbCompilerEachPreppedLine("PBS/abilities.txt") { |line,lineno| pbCompilerEachPreppedLine("PBS/abilities.txt") { |line,lineno|
record = pbGetCsvRecord(line,lineno,[0,"vnss"]) record = pbGetCsvRecord(line,lineno,[0,"vnss"])
if movenames[record[0]]
raise _INTL("Ability ID number '{1}' is used twice.\r\n{2}",record[0],FileLineData.linereport)
end
movenames[record[0]] = record[2] movenames[record[0]] = record[2]
movedescs[record[0]] = record[3] movedescs[record[0]] = record[3]
maxValue = [maxValue,record[0]].max maxValue = [maxValue,record[0]].max
@@ -545,6 +550,9 @@ def pbCompileItems
pbCompilerEachCommentedLine("PBS/items.txt") { |line,lineno| pbCompilerEachCommentedLine("PBS/items.txt") { |line,lineno|
linerecord = pbGetCsvRecord(line,lineno,[0,"vnssuusuuUN"]) linerecord = pbGetCsvRecord(line,lineno,[0,"vnssuusuuUN"])
id = linerecord[0] id = linerecord[0]
if records[id]
raise _INTL("Item ID number '{1}' is used twice.\r\n{2}",id,FileLineData.linereport)
end
record = [] record = []
record[ITEM_ID] = id record[ITEM_ID] = id
constant = linerecord[1] constant = linerecord[1]
@@ -603,11 +611,14 @@ def pbCompileMoves
nil,nil,nil,nil,nil,PBTypes,["Physical","Special","Status"], nil,nil,nil,nil,nil,PBTypes,["Physical","Special","Status"],
nil,nil,nil,PBTargets,nil,nil,nil nil,nil,nil,PBTargets,nil,nil,nil
]) ])
if records[lineRecord[0]]
raise _INTL("Move ID number '{1}' is used twice.\r\n{2}",lineRecord[0],FileLineData.linereport)
end
if lineRecord[6]==2 && lineRecord[4]!=0 if lineRecord[6]==2 && lineRecord[4]!=0
raise _INTL("Status moves must have a base damage of 0, use either Physical or Special\r\n{1}",FileLineData.linereport) raise _INTL("Status moves must have a base damage of 0, use either Physical or Special.\r\n{1}",FileLineData.linereport)
end end
if lineRecord[6]!=2 && lineRecord[4]==0 if lineRecord[6]!=2 && lineRecord[4]==0
print _INTL("Warning: Physical and special moves can't have a base damage of 0, changing to a Status move\r\n{1}",FileLineData.linereport) print _INTL("Warning: Physical and special moves can't have a base damage of 0, changing to a Status move.\r\n{1}",FileLineData.linereport)
lineRecord[6] = 2 lineRecord[6] = 2
end end
record[MOVE_ID] = lineRecord[0] record[MOVE_ID] = lineRecord[0]
@@ -717,6 +728,14 @@ def pbCompilePokemonData
# contents is a hash containing all the XXX=YYY lines in that section, where # contents is a hash containing all the XXX=YYY lines in that section, where
# the keys are the XXX and the values are the YYY (as unprocessed strings). # the keys are the XXX and the values are the YYY (as unprocessed strings).
pbEachFileSection(f) { |contents,speciesID| pbEachFileSection(f) { |contents,speciesID|
# Raise an error if the species ID is 0.
if speciesID==0
raise _INTL("A Pokémon species can't be numbered 0 (PBS/pokemon.txt)")
end
# Raise an error if the species ID has already been defined.
if speciesData[speciesID]
raise _INTL("Species ID number '{1}' is used twice.\r\n{2}",speciesID,FileLineData.linereport)
end
# Create array to store compiled data in. # Create array to store compiled data in.
speciesData[speciesID] = [] speciesData[speciesID] = []
# Copy Type1 into Type2 if Type2 is undefined. (All species must have two # Copy Type1 into Type2 if Type2 is undefined. (All species must have two
@@ -733,10 +752,6 @@ def pbCompilePokemonData
FileLineData.setSection(speciesID,key,contents[key]) # For error reporting FileLineData.setSection(speciesID,key,contents[key]) # For error reporting
maxValue = [maxValue,speciesID].max # Set highest species ID maxValue = [maxValue,speciesID].max # Set highest species ID
next if hash[key][0]<0 # Property is not to be compiled; skip it next if hash[key][0]<0 # Property is not to be compiled; skip it
# Raise an error if the species ID is 0.
if speciesID==0
raise _INTL("A Pokémon species can't be numbered 0 (PBS/pokemon.txt)")
end
# Skip empty optional properties, or raise an error if a required # Skip empty optional properties, or raise an error if a required
# property is empty. # property is empty.
if !contents[key] || contents[key]=="" if !contents[key] || contents[key]==""
@@ -854,7 +869,6 @@ def pbCompilePokemonData
end end
# Add prevolution data to all species as the first "evolution method". # Add prevolution data to all species as the first "evolution method".
for sp in 1..maxValue for sp in 1..maxValue
next if !evolutions[sp]
preSpecies = -1 preSpecies = -1
evoData = nil evoData = nil
# Check for another species that evolves into sp. # Check for another species that evolves into sp.
@@ -870,6 +884,7 @@ def pbCompilePokemonData
end end
next if !evoData # evoData[1]=method, evoData[2]=level - both are unused next if !evoData # evoData[1]=method, evoData[2]=level - both are unused
# Found a species that evolves into e, record it as a prevolution. # Found a species that evolves into e, record it as a prevolution.
evolutions[sp] = [] if !evolutions[sp]
evolutions[sp] = [[preSpecies,evoData[1],evoData[2],true]].concat(evolutions[sp]) evolutions[sp] = [[preSpecies,evoData[1],evoData[2],true]].concat(evolutions[sp])
end end
# Save evolutions data. # Save evolutions data.
@@ -1162,6 +1177,9 @@ def pbCompileMachines
if !line[/^\#/] && !line[/^\s*$/] if !line[/^\#/] && !line[/^\s*$/]
if line[/^\s*\[\s*(.*)\s*\]\s*$/] if line[/^\s*\[\s*(.*)\s*\]\s*$/]
sectionname = parseMove($~[1]) sectionname = parseMove($~[1])
if sections[sectionname]
raise _INTL("TM section [{1}] is defined twice.\r\n{2}",sectionname,FileLineData.linereport)
end
sections[sectionname] = WordArray.new sections[sectionname] = WordArray.new
havesection = true havesection = true
else else
@@ -1261,13 +1279,16 @@ def pbCompileEncounters
mapid = line[/^\d+$/] mapid = line[/^\d+$/]
if mapid if mapid
lastmapid = mapid lastmapid = mapid
if encounters[mapid.to_i]
raise _INTL("Encounters for map ID '{1}' are defined twice.\r\n{2}",mapid,FileLineData.linereport)
end
if thisenc && (thisenc[1][EncounterTypes::Land] || if thisenc && (thisenc[1][EncounterTypes::Land] ||
thisenc[1][EncounterTypes::LandMorning] || thisenc[1][EncounterTypes::LandMorning] ||
thisenc[1][EncounterTypes::LandDay] || thisenc[1][EncounterTypes::LandDay] ||
thisenc[1][EncounterTypes::LandNight] || thisenc[1][EncounterTypes::LandNight] ||
thisenc[1][EncounterTypes::BugContest]) && thisenc[1][EncounterTypes::BugContest]) &&
thisenc[1][EncounterTypes::Cave] thisenc[1][EncounterTypes::Cave]
raise _INTL("Can't define both Land and Cave encounters in the same area (map ID {1})",mapid) raise _INTL("Can't define both Land and Cave encounters in the same area (map ID '{1}')",mapid)
end end
thisenc = [EncounterTypes::EnctypeDensities.clone,[]] thisenc = [EncounterTypes::EnctypeDensities.clone,[]]
encounters[mapid.to_i] = thisenc encounters[mapid.to_i] = thisenc
@@ -1393,10 +1414,10 @@ def pbCompileTrainers
if line[/^\s*\[\s*(.+)\s*\]\s*$/] if line[/^\s*\[\s*(.+)\s*\]\s*$/]
# Section [trainertype,trainername] or [trainertype,trainername,partyid] # Section [trainertype,trainername] or [trainertype,trainername,partyid]
if oldcompilerline>0 if oldcompilerline>0
raise _INTL("Previous trainer not defined with as many Pokémon as expected\r\n{1}",FileLineData.linereport) raise _INTL("Previous trainer not defined with as many Pokémon as expected.\r\n{1}",FileLineData.linereport)
end end
if pokemonindex==-1 if pokemonindex==-1
raise _INTL("Started new trainer while previous trainer has no Pokémon\r\n{1}",FileLineData.linereport) raise _INTL("Started new trainer while previous trainer has no Pokémon.\r\n{1}",FileLineData.linereport)
end end
section = pbGetCsvRecord($~[1],lineno,[0,"esU",PBTrainers]) section = pbGetCsvRecord($~[1],lineno,[0,"esU",PBTrainers])
trainerindex += 1 trainerindex += 1
@@ -1409,10 +1430,10 @@ def pbCompileTrainers
elsif line[/^\s*(\w+)\s*=\s*(.*)$/] elsif line[/^\s*(\w+)\s*=\s*(.*)$/]
# XXX=YYY lines # XXX=YYY lines
if trainerindex<0 if trainerindex<0
raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport) raise _INTL("Expected a section at the beginning of the file.\r\n{1}",FileLineData.linereport)
end end
if oldcompilerline>0 if oldcompilerline>0
raise _INTL("Previous trainer not defined with as many Pokémon as expected\r\n{1}",FileLineData.linereport) raise _INTL("Previous trainer not defined with as many Pokémon as expected.\r\n{1}",FileLineData.linereport)
end end
settingname = $~[1] settingname = $~[1]
schema = trainer_info_types[settingname] schema = trainer_info_types[settingname]
@@ -1429,7 +1450,7 @@ def pbCompileTrainers
record.compact! record.compact!
when "Ability" when "Ability"
if record>5 if record>5
raise _INTL("Bad ability flag: {1} (must be 0 or 1 or 2-5)\r\n{2}",record,FileLineData.linereport) raise _INTL("Bad ability flag: {1} (must be 0 or 1 or 2-5).\r\n{2}",record,FileLineData.linereport)
end end
when "IV" when "IV"
record = [record] if record.is_a?(Integer) record = [record] if record.is_a?(Integer)
@@ -565,7 +565,7 @@ def pbConvertToTrainerEvent(event,trainerChecker)
end end
pbPushScript(firstpage.list,"setBattleRule(\"double\")") if doublebattle pbPushScript(firstpage.list,"setBattleRule(\"double\")") if doublebattle
pbPushScript(firstpage.list,sprintf("setBattleRule(\"backdrop\",\"%s\")",safequote(backdrop))) if backdrop pbPushScript(firstpage.list,sprintf("setBattleRule(\"backdrop\",\"%s\")",safequote(backdrop))) if backdrop
pbPushScript(firstpage.list,sprintf("setBattleRule(\"outcomeVar\",%d)",outcomeVar)) if outcome>1 pbPushScript(firstpage.list,sprintf("setBattleRule(\"outcomeVar\",%d)",outcome)) if outcome>1
pbPushScript(firstpage.list,"setBattleRule(\"canLose\")") if continue pbPushScript(firstpage.list,"setBattleRule(\"canLose\")") if continue
espeech = (endspeeches[0]) ? sprintf("_I(\"%s\")",safequote2(endspeeches[0])) : "nil" espeech = (endspeeches[0]) ? sprintf("_I(\"%s\")",safequote2(endspeeches[0])) : "nil"
if battleid>0 if battleid>0
@@ -614,7 +614,7 @@ def pbConvertToTrainerEvent(event,trainerChecker)
pbPushText(rematchpage.list,battles[i],1) pbPushText(rematchpage.list,battles[i],1)
pbPushScript(rematchpage.list,"setBattleRule(\"double\")",1) if doublebattle pbPushScript(rematchpage.list,"setBattleRule(\"double\")",1) if doublebattle
pbPushScript(rematchpage.list,sprintf("setBattleRule(\"backdrop\",%s)",safequote(backdrop)),1) if backdrop pbPushScript(rematchpage.list,sprintf("setBattleRule(\"backdrop\",%s)",safequote(backdrop)),1) if backdrop
pbPushScript(rematchpage.list,sprintf("setBattleRule(\"outcomeVar\",%d)",outcomeVar),1) if outcome>1 pbPushScript(rematchpage.list,sprintf("setBattleRule(\"outcomeVar\",%d)",outcome),1) if outcome>1
pbPushScript(rematchpage.list,"setBattleRule(\"canLose\")",1) if continue pbPushScript(rematchpage.list,"setBattleRule(\"canLose\")",1) if continue
espeech = nil espeech = nil
if endspeeches.length>0 if endspeeches.length>0
+6 -12
View File
@@ -1,7 +1,5 @@
pbCompiler pbCompiler
class Scene_DebugIntro class Scene_DebugIntro
def main def main
Graphics.transition(0) Graphics.transition(0)
@@ -12,8 +10,6 @@ class Scene_DebugIntro
end end
end end
def pbCallTitle def pbCallTitle
return Scene_DebugIntro.new if $DEBUG return Scene_DebugIntro.new if $DEBUG
# First parameter is an array of images in the Titles # First parameter is an array of images in the Titles
@@ -34,9 +30,9 @@ end
def mainFunctionDebug def mainFunctionDebug
begin begin
getCurrentProcess = Win32API.new("kernel32.dll","GetCurrentProcess","","l") getCurrentProcess = Win32API.new("kernel32.dll", "GetCurrentProcess", "", "l")
setPriorityClass = Win32API.new("kernel32.dll","SetPriorityClass",%w(l i),"") setPriorityClass = Win32API.new("kernel32.dll", "SetPriorityClass", %w(l i), "")
setPriorityClass.call(getCurrentProcess.call(),32768) # "Above normal" priority class setPriorityClass.call(getCurrentProcess.call(), 32768) # "Above normal" priority class
$data_animations = pbLoadRxData("Data/Animations") $data_animations = pbLoadRxData("Data/Animations")
$data_tilesets = pbLoadRxData("Data/Tilesets") $data_tilesets = pbLoadRxData("Data/Tilesets")
$data_common_events = pbLoadRxData("Data/CommonEvents") $data_common_events = pbLoadRxData("Data/CommonEvents")
@@ -46,9 +42,7 @@ def mainFunctionDebug
Graphics.update Graphics.update
Graphics.freeze Graphics.freeze
$scene = pbCallTitle $scene = pbCallTitle
while $scene!=nil $scene.main until $scene.nil?
$scene.main
end
Graphics.transition(20) Graphics.transition(20)
rescue Hangup rescue Hangup
pbPrintException($!) if !$DEBUG pbPrintException($!) if !$DEBUG
@@ -59,11 +53,11 @@ end
loop do loop do
retval = mainFunction retval = mainFunction
if retval==0 # failed if retval == 0 # failed
loop do loop do
Graphics.update Graphics.update
end end
elsif retval==1 # ended successfully elsif retval == 1 # ended successfully
break break
end end
end end
+2 -2
View File
@@ -815,7 +815,7 @@ Habitat = Forest
RegionalNumbers = 25,22 RegionalNumbers = 25,22
Kind = Mouse Kind = Mouse
Pokedex = It stores electricity in the electric sacs on its cheeks. When it releases pent-up energy in a burst, the electric power is equal to a lightning bolt. Pokedex = It stores electricity in the electric sacs on its cheeks. When it releases pent-up energy in a burst, the electric power is equal to a lightning bolt.
WildItemuNCOMMON = LIGHTBALL WildItemUncommon = LIGHTBALL
BattlerPlayerX = -5 BattlerPlayerX = -5
BattlerPlayerY = 0 BattlerPlayerY = 0
BattlerEnemyX = 4 BattlerEnemyX = 4
@@ -9618,7 +9618,7 @@ BattlerEnemyX = -1
BattlerEnemyY = 29 BattlerEnemyY = 29
BattlerShadowX = 0 BattlerShadowX = 0
BattlerShadowSize = 2 BattlerShadowSize = 2
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,20 Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,
#------------------------------- #-------------------------------
[291] [291]
Name = Ninjask Name = Ninjask
+11 -11
View File
@@ -122,16 +122,16 @@
116,DISARMINGVOICE,Disarming Voice,0A5,40,FAIRY,Special,0,15,0,AllNearFoes,0,befk,"Letting out a charming cry, the user does emotional damage to foes. This attack never misses." 116,DISARMINGVOICE,Disarming Voice,0A5,40,FAIRY,Special,0,15,0,AllNearFoes,0,befk,"Letting out a charming cry, the user does emotional damage to foes. This attack never misses."
117,FAIRYWIND,Fairy Wind,000,40,FAIRY,Special,100,30,0,NearOther,0,bef,"The user stirs up a fairy wind and strikes the target with it." 117,FAIRYWIND,Fairy Wind,000,40,FAIRY,Special,100,30,0,NearOther,0,bef,"The user stirs up a fairy wind and strikes the target with it."
118,AROMATICMIST,Aromatic Mist,138,0,FAIRY,Status,0,20,0,NearAlly,0,,"The user raises the Sp. Def stat of an ally Pokémon by using a mysterious aroma." 118,AROMATICMIST,Aromatic Mist,138,0,FAIRY,Status,0,20,0,NearAlly,0,,"The user raises the Sp. Def stat of an ally Pokémon by using a mysterious aroma."
119,BABYDOLLEYES,Baby-Doll Eyes,042,0,FAIRY,Status,100,30,0,NearOther,1,bce,"The user stares with its baby-doll eyes, which lowers the target's Attack stat. Always goes first." 119,NATURESMADNESS,Nature's Madness,06C,1,FAIRY,Special,90,10,0,NearOther,0,bef,"The user hits the target with the force of nature. It halves the target's HP."
120,CHARM,Charm,04B,0,FAIRY,Status,100,20,0,NearOther,0,bce,"The user charmingly gazes at the foe, making it less wary. The target's Attack is harshly lowered." 120,BABYDOLLEYES,Baby-Doll Eyes,042,0,FAIRY,Status,100,30,0,NearOther,1,bce,"The user stares with its baby-doll eyes, which lowers the target's Attack stat. Always goes first."
121,CRAFTYSHIELD,Crafty Shield,14A,0,FAIRY,Status,0,10,0,UserSide,3,,"The user protects itself and its allies from status moves with a mysterious power." 121,CHARM,Charm,04B,0,FAIRY,Status,100,20,0,NearOther,0,bce,"The user charmingly gazes at the foe, making it less wary. The target's Attack is harshly lowered."
122,FAIRYLOCK,Fairy Lock,152,0,FAIRY,Status,0,10,0,BothSides,0,e,"By locking down the battlefield, the user keeps all Pokémon from fleeing during the next turn." 122,CRAFTYSHIELD,Crafty Shield,14A,0,FAIRY,Status,0,10,0,UserSide,3,,"The user protects itself and its allies from status moves with a mysterious power."
123,FLORALHEALING,Floral Healing,16E,0,FAIRY,Status,0,10,0,NearOther,0,bc,"The user restores the target's HP by up to half of its max HP. It restores more HP when the terrain is grass." 123,FAIRYLOCK,Fairy Lock,152,0,FAIRY,Status,0,10,0,BothSides,0,e,"By locking down the battlefield, the user keeps all Pokémon from fleeing during the next turn."
124,FLOWERSHIELD,Flower Shield,13F,0,FAIRY,Status,0,10,0,AllBattlers,0,,"The user raises the Defense stats of all Grass-type Pokémon in battle with a mysterious power." 124,FLORALHEALING,Floral Healing,16E,0,FAIRY,Status,0,10,0,NearOther,0,bc,"The user restores the target's HP by up to half of its max HP. It restores more HP when the terrain is grass."
125,GEOMANCY,Geomancy,14E,0,FAIRY,Status,0,10,0,User,0,,"The user absorbs energy and sharply raises its Sp. Atk, Sp. Def, and Speed stats on the next turn." 125,FLOWERSHIELD,Flower Shield,13F,0,FAIRY,Status,0,10,0,AllBattlers,0,,"The user raises the Defense stats of all Grass-type Pokémon in battle with a mysterious power."
126,MISTYTERRAIN,Misty Terrain,156,0,FAIRY,Status,0,10,0,BothSides,0,,"The user covers the ground with mist for five turns. Grounded Pokémon can't gain status conditions." 126,GEOMANCY,Geomancy,14E,0,FAIRY,Status,0,10,0,User,0,,"The user absorbs energy and sharply raises its Sp. Atk, Sp. Def, and Speed stats on the next turn."
127,MOONLIGHT,Moonlight,0D8,0,FAIRY,Status,0,5,0,User,0,d,"The user restores its own HP. The amount of HP regained varies with the weather." 127,MISTYTERRAIN,Misty Terrain,156,0,FAIRY,Status,0,10,0,BothSides,0,,"The user covers the ground with mist for five turns. Grounded Pokémon can't gain status conditions."
128,NATURESMADNESS,Nature's Madness,06C,0,FAIRY,Status,90,10,0,NearOther,0,bef,"The user hits the target with the force of nature. It halves the target's HP." 128,MOONLIGHT,Moonlight,0D8,0,FAIRY,Status,0,5,0,User,0,d,"The user restores its own HP. The amount of HP regained varies with the weather."
129,SWEETKISS,Sweet Kiss,013,0,FAIRY,Status,75,10,0,NearOther,0,bce,"The user kisses the target with a sweet, angelic cuteness that causes confusion." 129,SWEETKISS,Sweet Kiss,013,0,FAIRY,Status,75,10,0,NearOther,0,bce,"The user kisses the target with a sweet, angelic cuteness that causes confusion."
#------------------------------- #-------------------------------
130,FOCUSPUNCH,Focus Punch,115,150,FIGHTING,Physical,100,20,0,NearOther,-3,abfj,"The user focuses its mind before launching a punch. It will fail if the user is hit before it is used." 130,FOCUSPUNCH,Focus Punch,115,150,FIGHTING,Physical,100,20,0,NearOther,-3,abfj,"The user focuses its mind before launching a punch. It will fail if the user is hit before it is used."
@@ -161,7 +161,7 @@
154,STORMTHROW,Storm Throw,0A0,60,FIGHTING,Physical,100,10,0,NearOther,0,abef,"The user strikes the target with a fierce blow. This attack always results in a critical hit." 154,STORMTHROW,Storm Throw,0A0,60,FIGHTING,Physical,100,10,0,NearOther,0,abef,"The user strikes the target with a fierce blow. This attack always results in a critical hit."
155,KARATECHOP,Karate Chop,000,50,FIGHTING,Physical,100,25,0,NearOther,0,abefh,"The target is attacked with a sharp chop. Critical hits land more easily." 155,KARATECHOP,Karate Chop,000,50,FIGHTING,Physical,100,25,0,NearOther,0,abefh,"The target is attacked with a sharp chop. Critical hits land more easily."
156,MACHPUNCH,Mach Punch,000,40,FIGHTING,Physical,100,30,0,NearOther,1,abefj,"The user throws a punch at blinding speed. It is certain to strike first." 156,MACHPUNCH,Mach Punch,000,40,FIGHTING,Physical,100,30,0,NearOther,1,abefj,"The user throws a punch at blinding speed. It is certain to strike first."
157,POWERUPPUNCH,Power-Up Punch,01C,40,FIGHTING,Physical,100,20,0,NearOther,0,abefj,"Striking opponents repeatedly makes the user's fists harder, raising the user's Attack stat." 157,POWERUPPUNCH,Power-Up Punch,01C,40,FIGHTING,Physical,100,20,100,NearOther,0,abefj,"Striking opponents repeatedly makes the user's fists harder, raising the user's Attack stat."
158,ROCKSMASH,Rock Smash,043,40,FIGHTING,Physical,100,15,50,NearOther,0,abef,"The user attacks with a punch that can shatter a rock. It may also lower the foe's Defense stat." 158,ROCKSMASH,Rock Smash,043,40,FIGHTING,Physical,100,15,50,NearOther,0,abef,"The user attacks with a punch that can shatter a rock. It may also lower the foe's Defense stat."
159,VACUUMWAVE,Vacuum Wave,000,40,FIGHTING,Special,100,30,0,NearOther,1,bef,"The user whirls its fists to send a wave of pure vacuum at the target. This move always goes first." 159,VACUUMWAVE,Vacuum Wave,000,40,FIGHTING,Special,100,30,0,NearOther,1,bef,"The user whirls its fists to send a wave of pure vacuum at the target. This move always goes first."
160,DOUBLEKICK,Double Kick,0BD,30,FIGHTING,Physical,100,30,0,NearOther,0,abef,"The target is quickly kicked twice in succession using both feet." 160,DOUBLEKICK,Double Kick,0BD,30,FIGHTING,Physical,100,30,0,NearOther,0,abef,"The target is quickly kicked twice in succession using both feet."
+2 -1
View File
@@ -816,6 +816,7 @@ Habitat = Forest
RegionalNumbers = 25,22 RegionalNumbers = 25,22
Kind = Mouse Kind = Mouse
Pokedex = It stores electricity in the electric sacs on its cheeks. When it releases pent-up energy in a burst, the electric power is equal to a lightning bolt. Pokedex = It stores electricity in the electric sacs on its cheeks. When it releases pent-up energy in a burst, the electric power is equal to a lightning bolt.
WildItemUncommon = LIGHTBALL
BattlerPlayerX = -5 BattlerPlayerX = -5
BattlerPlayerY = 0 BattlerPlayerY = 0
BattlerEnemyX = 4 BattlerEnemyX = 4
@@ -9617,7 +9618,7 @@ BattlerEnemyX = -1
BattlerEnemyY = 29 BattlerEnemyY = 29
BattlerShadowX = 0 BattlerShadowX = 0
BattlerShadowSize = 2 BattlerShadowSize = 2
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,20 Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,
#------------------------------- #-------------------------------
[291] [291]
Name = Ninjask Name = Ninjask
-1
View File
@@ -150,7 +150,6 @@ Moves = 0,DAZZLINGGLEAM,1,DAZZLINGGLEAM,1,IMPRISON,1,NASTYPLOT,1,ICEBEAM,1,ICESH
Color = Blue Color = Blue
Pokedex = It lives on mountains perpetually covered in snow and is revered as a deity incarnate. It appears draped in a blizzard. Pokedex = It lives on mountains perpetually covered in snow and is revered as a deity incarnate. It appears draped in a blizzard.
WildItemUncommon = SNOWBALL WildItemUncommon = SNOWBALL
Evolutions = NINETALES,Item,ICESTONE
#------------------------------- #-------------------------------
[DIGLETT,1] [DIGLETT,1]
FormName = Alolan FormName = Alolan
+12 -12
View File
@@ -121,17 +121,17 @@
115,DRAININGKISS,Draining Kiss,14F,50,FAIRY,Special,100,10,0,NearOther,0,abef,"The user steals the target's HP with a kiss. The user's HP is restored by over half of the damage dealt." 115,DRAININGKISS,Draining Kiss,14F,50,FAIRY,Special,100,10,0,NearOther,0,abef,"The user steals the target's HP with a kiss. The user's HP is restored by over half of the damage dealt."
116,DISARMINGVOICE,Disarming Voice,0A5,40,FAIRY,Special,0,15,0,AllNearFoes,0,befk,"Letting out a charming cry, the user does emotional damage to foes. This attack never misses." 116,DISARMINGVOICE,Disarming Voice,0A5,40,FAIRY,Special,0,15,0,AllNearFoes,0,befk,"Letting out a charming cry, the user does emotional damage to foes. This attack never misses."
117,FAIRYWIND,Fairy Wind,000,40,FAIRY,Special,100,30,0,NearOther,0,bef,"The user stirs up a fairy wind and strikes the target with it." 117,FAIRYWIND,Fairy Wind,000,40,FAIRY,Special,100,30,0,NearOther,0,bef,"The user stirs up a fairy wind and strikes the target with it."
118,AROMATICMIST,Aromatic Mist,138,0,FAIRY,Status,0,20,0,NearAlly,0,,"The user raises the Sp. Def stat of an ally Pokémon by using a mysterious aroma." 118,NATURESMADNESS,Nature's Madness,06C,1,FAIRY,Special,90,10,0,NearOther,0,bef,"The user hits the target with the force of nature. It halves the target's HP."
119,BABYDOLLEYES,Baby-Doll Eyes,042,0,FAIRY,Status,100,30,0,NearOther,1,bce,"The user stares with its baby-doll eyes, which lowers the target's Attack stat. Always goes first." 119,AROMATICMIST,Aromatic Mist,138,0,FAIRY,Status,0,20,0,NearAlly,0,,"The user raises the Sp. Def stat of an ally Pokémon by using a mysterious aroma."
120,CHARM,Charm,04B,0,FAIRY,Status,100,20,0,NearOther,0,bce,"The user charmingly gazes at the foe, making it less wary. The target's Attack is harshly lowered." 120,BABYDOLLEYES,Baby-Doll Eyes,042,0,FAIRY,Status,100,30,0,NearOther,1,bce,"The user stares with its baby-doll eyes, which lowers the target's Attack stat. Always goes first."
121,CRAFTYSHIELD,Crafty Shield,14A,0,FAIRY,Status,0,10,0,UserSide,3,,"The user protects itself and its allies from status moves with a mysterious power." 121,CHARM,Charm,04B,0,FAIRY,Status,100,20,0,NearOther,0,bce,"The user charmingly gazes at the foe, making it less wary. The target's Attack is harshly lowered."
122,FAIRYLOCK,Fairy Lock,152,0,FAIRY,Status,0,10,0,BothSides,0,e,"By locking down the battlefield, the user keeps all Pokémon from fleeing during the next turn." 122,CRAFTYSHIELD,Crafty Shield,14A,0,FAIRY,Status,0,10,0,UserSide,3,,"The user protects itself and its allies from status moves with a mysterious power."
123,FLORALHEALING,Floral Healing,16E,0,FAIRY,Status,0,10,0,NearOther,0,bc,"The user restores the target's HP by up to half of its max HP. It restores more HP when the terrain is grass." 123,FAIRYLOCK,Fairy Lock,152,0,FAIRY,Status,0,10,0,BothSides,0,e,"By locking down the battlefield, the user keeps all Pokémon from fleeing during the next turn."
124,FLOWERSHIELD,Flower Shield,13F,0,FAIRY,Status,0,10,0,AllBattlers,0,,"The user raises the Defense stats of all Grass-type Pokémon in battle with a mysterious power." 124,FLORALHEALING,Floral Healing,16E,0,FAIRY,Status,0,10,0,NearOther,0,bc,"The user restores the target's HP by up to half of its max HP. It restores more HP when the terrain is grass."
125,GEOMANCY,Geomancy,14E,0,FAIRY,Status,0,10,0,User,0,,"The user absorbs energy and sharply raises its Sp. Atk, Sp. Def, and Speed stats on the next turn." 125,FLOWERSHIELD,Flower Shield,13F,0,FAIRY,Status,0,10,0,AllBattlers,0,,"The user raises the Defense stats of all Grass-type Pokémon in battle with a mysterious power."
126,MISTYTERRAIN,Misty Terrain,156,0,FAIRY,Status,0,10,0,BothSides,0,,"The user covers the ground with mist for five turns. Grounded Pokémon can't gain status conditions." 126,GEOMANCY,Geomancy,14E,0,FAIRY,Status,0,10,0,User,0,,"The user absorbs energy and sharply raises its Sp. Atk, Sp. Def, and Speed stats on the next turn."
127,MOONLIGHT,Moonlight,0D8,0,FAIRY,Status,0,5,0,User,0,d,"The user restores its own HP. The amount of HP regained varies with the weather." 127,MISTYTERRAIN,Misty Terrain,156,0,FAIRY,Status,0,10,0,BothSides,0,,"The user covers the ground with mist for five turns. Grounded Pokémon can't gain status conditions."
128,NATURESMADNESS,Nature's Madness,06C,0,FAIRY,Status,90,10,0,NearOther,0,bef,"The user hits the target with the force of nature. It halves the target's HP." 128,MOONLIGHT,Moonlight,0D8,0,FAIRY,Status,0,5,0,User,0,d,"The user restores its own HP. The amount of HP regained varies with the weather."
129,SWEETKISS,Sweet Kiss,013,0,FAIRY,Status,75,10,0,NearOther,0,bce,"The user kisses the target with a sweet, angelic cuteness that causes confusion." 129,SWEETKISS,Sweet Kiss,013,0,FAIRY,Status,75,10,0,NearOther,0,bce,"The user kisses the target with a sweet, angelic cuteness that causes confusion."
#------------------------------- #-------------------------------
130,FOCUSPUNCH,Focus Punch,115,150,FIGHTING,Physical,100,20,0,NearOther,-3,abfj,"The user focuses its mind before launching a punch. It will fail if the user is hit before it is used." 130,FOCUSPUNCH,Focus Punch,115,150,FIGHTING,Physical,100,20,0,NearOther,-3,abfj,"The user focuses its mind before launching a punch. It will fail if the user is hit before it is used."
@@ -161,7 +161,7 @@
154,STORMTHROW,Storm Throw,0A0,60,FIGHTING,Physical,100,10,0,NearOther,0,abef,"The user strikes the target with a fierce blow. This attack always results in a critical hit." 154,STORMTHROW,Storm Throw,0A0,60,FIGHTING,Physical,100,10,0,NearOther,0,abef,"The user strikes the target with a fierce blow. This attack always results in a critical hit."
155,KARATECHOP,Karate Chop,000,50,FIGHTING,Physical,100,25,0,NearOther,0,abefh,"The target is attacked with a sharp chop. Critical hits land more easily." 155,KARATECHOP,Karate Chop,000,50,FIGHTING,Physical,100,25,0,NearOther,0,abefh,"The target is attacked with a sharp chop. Critical hits land more easily."
156,MACHPUNCH,Mach Punch,000,40,FIGHTING,Physical,100,30,0,NearOther,1,abefj,"The user throws a punch at blinding speed. It is certain to strike first." 156,MACHPUNCH,Mach Punch,000,40,FIGHTING,Physical,100,30,0,NearOther,1,abefj,"The user throws a punch at blinding speed. It is certain to strike first."
157,POWERUPPUNCH,Power-Up Punch,01C,40,FIGHTING,Physical,100,20,0,NearOther,0,abefj,"Striking opponents repeatedly makes the user's fists harder, raising the user's Attack stat." 157,POWERUPPUNCH,Power-Up Punch,01C,40,FIGHTING,Physical,100,20,100,NearOther,0,abefj,"Striking opponents repeatedly makes the user's fists harder, raising the user's Attack stat."
158,ROCKSMASH,Rock Smash,043,40,FIGHTING,Physical,100,15,50,NearOther,0,abef,"The user attacks with a punch that can shatter a rock. It may also lower the foe's Defense stat." 158,ROCKSMASH,Rock Smash,043,40,FIGHTING,Physical,100,15,50,NearOther,0,abef,"The user attacks with a punch that can shatter a rock. It may also lower the foe's Defense stat."
159,VACUUMWAVE,Vacuum Wave,000,40,FIGHTING,Special,100,30,0,NearOther,1,bef,"The user whirls its fists to send a wave of pure vacuum at the target. This move always goes first." 159,VACUUMWAVE,Vacuum Wave,000,40,FIGHTING,Special,100,30,0,NearOther,1,bef,"The user whirls its fists to send a wave of pure vacuum at the target. This move always goes first."
160,DOUBLEKICK,Double Kick,0BD,30,FIGHTING,Physical,100,30,0,NearOther,0,abef,"The target is quickly kicked twice in succession using both feet." 160,DOUBLEKICK,Double Kick,0BD,30,FIGHTING,Physical,100,30,0,NearOther,0,abef,"The target is quickly kicked twice in succession using both feet."
+2 -1
View File
@@ -816,6 +816,7 @@ Habitat = Forest
RegionalNumbers = 25,22 RegionalNumbers = 25,22
Kind = Mouse Kind = Mouse
Pokedex = It stores electricity in the electric sacs on its cheeks. When it releases pent-up energy in a burst, the electric power is equal to a lightning bolt. Pokedex = It stores electricity in the electric sacs on its cheeks. When it releases pent-up energy in a burst, the electric power is equal to a lightning bolt.
WildItemUncommon = LIGHTBALL
BattlerPlayerX = -5 BattlerPlayerX = -5
BattlerPlayerY = 0 BattlerPlayerY = 0
BattlerEnemyX = 4 BattlerEnemyX = 4
@@ -9617,7 +9618,7 @@ BattlerEnemyX = -1
BattlerEnemyY = 29 BattlerEnemyY = 29
BattlerShadowX = 0 BattlerShadowX = 0
BattlerShadowSize = 2 BattlerShadowSize = 2
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,20 Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,
#------------------------------- #-------------------------------
[291] [291]
Name = Ninjask Name = Ninjask
-1
View File
@@ -150,7 +150,6 @@ Moves = 0,DAZZLINGGLEAM,1,DAZZLINGGLEAM,1,IMPRISON,1,NASTYPLOT,1,ICEBEAM,1,ICESH
Color = Blue Color = Blue
Pokedex = It lives on mountains perpetually covered in snow and is revered as a deity incarnate. It appears draped in a blizzard. Pokedex = It lives on mountains perpetually covered in snow and is revered as a deity incarnate. It appears draped in a blizzard.
WildItemUncommon = SNOWBALL WildItemUncommon = SNOWBALL
Evolutions = NINETALES,Item,ICESTONE
#------------------------------- #-------------------------------
[DIGLETT,1] [DIGLETT,1]
FormName = Alolan FormName = Alolan