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

View File

@@ -1,6 +1,6 @@
#==============================================================================#
# Pokémon Essentials #
# Version 18 #
# Version 18.1 #
#==============================================================================#
#===============================================================================

View File

@@ -100,5 +100,5 @@ end
# Well done for finding this place.
# DO NOT EDIT THESE
ESSENTIALS_VERSION = "18"
ESSENTIALS_VERSION = "18.1.dev"
ERROR_TEXT = ""

View File

@@ -48,6 +48,7 @@ module Console
@apiSetConsoleTitle = Win32API.new("kernel32","SetConsoleTitle","p","s")
access = (GENERIC_READ | GENERIC_WRITE)
sharemode = (FILE_SHARE_READ | FILE_SHARE_WRITE)
AllocConsole()
@bufferHandle = CreateConsoleScreenBuffer(access,sharemode,CONSOLE_TEXTMODE_BUFFER)
f = File.open("Game.ini")
lines = f.readlines()

View File

@@ -33,7 +33,7 @@ class Game_Character
@y = 0
@real_x = 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
@character_name = ""
@character_hue = 0
@@ -50,7 +50,7 @@ class Game_Character
@original_direction = 2
@original_pattern = 0
@move_type = 0
self.move_speed = 4
self.move_speed = 3
self.move_frequency = 6
@move_route = nil
@move_route_index = 0
@@ -62,8 +62,10 @@ class Game_Character
@always_on_top = false
@anime_count = 0
@stop_count = 0
@jump_count = 0
@jump_peak = 0
@jump_peak = 0 # Max height while jumping
@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
@wait_count = 0
@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
# are 128 quarter-pixels per tile. By default, it is calculated from
# @move_speed and has these values (assuming 40 fps):
# 1 => 1.6 # 80 frames per tile
# 2 => 3.2 # 40 frames per tile
# 3 => 6.4 # 20 frames per tile
# 4 => 12.8 # 10 frames per tile - walking speed
# 5 => 25.6 # 5 frames per tile - running speed (2x walking speed)
# 6 => 32 # 4 frames per tile - cycling speed (1.25x running speed)
self.move_speed_real = (val == 6) ? 32 : (1 << val) * 0.8
# 1 => 3.2 # 40 frames per tile
# 2 => 6.4 # 20 frames per tile
# 3 => 12.8 # 10 frames per tile - walking speed
# 4 => 25.6 # 5 frames per tile - running speed (2x walking speed)
# 5 => 32 # 4 frames per tile - cycling speed (1.25x running speed)
# 6 => 64 # 2 frames per tile
self.move_speed_real = (val == 6) ? 64 : (val == 5) ? 32 : (2 ** (val + 1)) * 0.8
end
def move_speed_real
@@ -95,6 +97,10 @@ class Game_Character
@move_speed_real = val * 40.0 / Graphics.frame_rate
end
def jump_speed_real
return (2 ** (3 + 1)) * 0.8 * 40.0 / Graphics.frame_rate # Walking speed
end
def move_frequency=(val)
return if val==@move_frequency
@move_frequency = val
@@ -160,7 +166,7 @@ class Game_Character
end
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)
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)
@@ -219,8 +225,12 @@ class Game_Character
def screen_y
ret = screen_y_ground
if jumping?
n = ((2 * @jump_count * 20 / Graphics.frame_rate) - @jump_peak).abs
return ret - (@jump_peak * @jump_peak - n * n) / 2
if @jump_count > 0
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
return ret
end
@@ -248,7 +258,7 @@ class Game_Character
end
def jumping?
return @jump_count > 0
return (@jump_distance_left || 0) > 0 || @jump_count > 0
end
def straighten
@@ -422,48 +432,34 @@ class Game_Character
end
end
def move_up(turn_enabled = true)
turn_up if turn_enabled
if passable?(@x, @y, 8)
turn_up
@y -= 1
def move_generic(dir, turn_enabled = true)
turn_generic(dir) if turn_enabled
x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0
y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0
if passable?(@x, @y, dir)
turn_generic(dir)
@x += x_offset
@y += y_offset
increase_steps
else
check_event_trigger_touch(@x, @y-1)
check_event_trigger_touch(@x + x_offset, @y + y_offset)
end
end
def move_down(turn_enabled = true)
turn_down if turn_enabled
if passable?(@x, @y, 2)
turn_down
@y += 1
increase_steps
else
check_event_trigger_touch(@x, @y+1)
end
move_generic(2, turn_enabled)
end
def move_left(turn_enabled = true)
turn_left if turn_enabled
if passable?(@x, @y, 4)
turn_left
@x -= 1
increase_steps
else
check_event_trigger_touch(@x-1, @y)
end
move_generic(4, turn_enabled)
end
def move_right(turn_enabled = true)
turn_right if turn_enabled
if passable?(@x, @y, 6)
turn_right
@x += 1
increase_steps
else
check_event_trigger_touch(@x+1, @y)
end
move_generic(6, turn_enabled)
end
def move_up(turn_enabled = true)
move_generic(8, turn_enabled)
end
def move_upper_left
@@ -648,12 +644,18 @@ class Game_Character
new_x = @x + x_plus
new_y = @y + y_plus
if (x_plus == 0 and y_plus == 0) || passable?(new_x, new_y, 0)
straighten
@x = new_x
@y = new_y
distance = [4, x_plus * x_plus + y_plus * y_plus].max
@jump_peak = (6 + distance - move_speed).floor
@jump_count = @jump_peak * Graphics.frame_rate / 20
real_distance = Math::sqrt(x_plus * x_plus + y_plus * y_plus)
distance = [1, real_distance].max
@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
if self.is_a?(Game_Player)
$PokemonTemp.dependentEvents.pbMoveDependentEvents
@@ -680,7 +682,7 @@ class Game_Character
end
end
def turnGeneric(dir)
def turn_generic(dir)
return if @direction_fix
oldDirection = @direction
@direction = dir
@@ -688,10 +690,10 @@ class Game_Character
pbCheckEventTriggerAfterTurning if dir != oldDirection
end
def turn_up; turnGeneric(8); end
def turn_down; turnGeneric(2); end
def turn_left; turnGeneric(4); end
def turn_right; turnGeneric(6); end
def turn_down; turn_generic(2); end
def turn_left; turn_generic(4); end
def turn_right; turn_generic(6); end
def turn_up; turn_generic(8); end
def turn_right_90
case @direction
@@ -764,10 +766,7 @@ class Game_Character
# Update command
update_command
# Update movement
if jumping?; update_jump
elsif moving?; update_move
else; update_stop
end
(moving? || jumping?) ? update_move : update_stop
end
# Update animation
update_pattern
@@ -801,18 +800,9 @@ class Game_Character
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
# 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_y = @y * Game_Map::REAL_RES_Y
if @real_x < dest_x
@@ -829,8 +819,13 @@ class Game_Character
@real_y -= distance
@real_y = dest_y if @real_y < dest_y + 0.1
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
Events.onStepTakenFieldMovement.trigger(self,self) if !jumping? && !moving?
Events.onStepTakenFieldMovement.trigger(self, self) if !jumping? && !moving?
# Increment animation counter
@anime_count += 1 if @walk_anime || @step_anime
@moved_this_frame = true
@@ -844,6 +839,7 @@ class Game_Character
def update_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
if @moved_last_frame && !@moved_this_frame && !@step_anime
@pattern = @original_pattern
@@ -851,7 +847,7 @@ class Game_Character
return
end
# 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
@anime_count = 0
return
@@ -859,7 +855,8 @@ class Game_Character
# 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
# 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
return if @anime_count < frames_per_pattern
# Advance to the next animation frame

View File

@@ -23,7 +23,7 @@ class Game_Player < Game_Character
end
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
ybehind = (@direction==8) ? @y+1 : (@direction==2) ? @y-1 : @y
# 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]
end
# Return bush depth
if @jump_count <= 0
if !jumping?
return 32 if heremap.deepBush?(herex, herey) && behindmap.deepBush?(behindx, behindy)
return 12 if heremap.bush?(herex, herey) && !moving?
end
@@ -64,67 +64,36 @@ class Game_Player < Game_Character
@bump_se = Graphics.frame_rate/4
end
def move_down(turn_enabled = true)
turn_down if turn_enabled
if passable?(@x, @y, 2)
return if pbLedge(0,1)
return if pbEndSurf(0,1)
turn_down
@y += 1
$PokemonTemp.dependentEvents.pbMoveDependentEvents
increase_steps
else
if !check_event_trigger_touch(@x, @y+1)
bump_into_object
def move_generic(dir, turn_enabled = true)
turn_generic(dir, true) if turn_enabled
if !$PokemonTemp.encounterTriggered
x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0
y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0
if passable?(@x, @y, dir)
return if pbLedge(x_offset, y_offset)
return if pbEndSurf(x_offset, y_offset)
turn_generic(dir, true)
if !$PokemonTemp.encounterTriggered
@x += x_offset
@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
$PokemonTemp.encounterTriggered = false
end
def move_left(turn_enabled = true)
turn_left if turn_enabled
if passable?(@x, @y, 4)
return if pbLedge(-1,0)
return if pbEndSurf(-1,0)
turn_left
@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
def turn_generic(dir, keep_enc_indicator = false)
old_direction = @direction
super(dir)
if @direction != old_direction && !@move_route_forcing && !pbMapInterpreterRunning?
Events.onChangeDirection.trigger(self, self)
$PokemonTemp.encounterTriggered = false if !keep_enc_indicator
end
end
@@ -162,8 +131,7 @@ class Game_Player < Game_Character
return result
end
def pbCheckEventTriggerAfterTurning
end
def pbCheckEventTriggerAfterTurning; end
def pbCheckEventTriggerFromDistance(triggers)
ret = pbTriggeredTrainerEvents(triggers)
@@ -377,17 +345,18 @@ class Game_Player < Game_Character
def update_command_new
dir = Input.dir4
unless pbMapInterpreterRunning? or $game_temp.message_window_showing or
$PokemonTemp.miniupdate or $game_temp.in_menu
unless pbMapInterpreterRunning? || $game_temp.message_window_showing ||
$PokemonTemp.miniupdate || $game_temp.in_menu
# 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
when 2; move_down
when 4; move_left
when 6; move_right
when 8; move_up
end
elsif dir!=@lastdir
elsif dir != @lastdir
case dir
when 2; turn_down
when 4; turn_left
@@ -397,7 +366,7 @@ class Game_Player < Game_Character
end
end
# Record last direction input
@lastdirframe = Graphics.frame_count if dir!=@lastdir
@lastdirframe = Graphics.frame_count if dir != @lastdir
@lastdir = dir
end

View File

@@ -25,7 +25,7 @@ class Game_Player < Game_Character
pbMapInterpreterRunning?
terrain = pbGetTerrainTag
input = ($PokemonSystem.runstyle==1) ? $PokemonGlobal.runtoggle : Input.press?(Input::A)
return input && $PokemonGlobal.runningShoes &&
return input && $PokemonGlobal.runningShoes && !jumping? &&
!$PokemonGlobal.diving && !$PokemonGlobal.surfing &&
!$PokemonGlobal.bicycle && !PBTerrain.onlyWalk?(terrain)
end
@@ -54,14 +54,14 @@ class Game_Player < Game_Character
def update_command
if PBTerrain.isIce?(pbGetTerrainTag)
self.move_speed = 5 # Sliding on ice
self.move_speed = 4 # Sliding on ice
elsif !moving? && !@move_route_forcing && $PokemonGlobal
if $PokemonGlobal.bicycle
self.move_speed = 6 # Cycling
elsif pbCanRun? || $PokemonGlobal.surfing || $PokemonGlobal.diving
self.move_speed = 5 # Running, surfing or diving
self.move_speed = 5 # Cycling
elsif pbCanRun? || $PokemonGlobal.surfing
self.move_speed = 4 # Running, surfing
else
self.move_speed = 4 # Walking
self.move_speed = 3 # Walking, diving
end
end
super

View File

@@ -103,7 +103,7 @@ class Game_Map
end
#-----------------------------------------------------------------------------
# * 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
if @map.autoplay_bgm
@@ -119,12 +119,12 @@ class Game_Map
end
#-----------------------------------------------------------------------------
# * 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
if @map.autoplay_bgm
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/"+ @map.bgm.name+ "n")
pbBGMPlay(@map.bgm.name+"n",@map.bgm.volume,@map.bgm.pitch)
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/"+ @map.bgm.name+ "_n")
pbBGMPlay(@map.bgm.name+"_n",@map.bgm.volume,@map.bgm.pitch)
else
pbBGMPlay(@map.bgm)
end

View File

@@ -39,8 +39,8 @@ class Event
# 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
# supports the following callbacks:
# proc{ |sender,params| } where params is an array of the other parameters, and
# proc{ |sender,arg0,arg1,...| }
# proc { |sender,params| } where params is an array of the other parameters, and
# proc { |sender,arg0,arg1,...| }
def trigger(*arg)
arglist = arg[1,arg.length]
for callback in @callbacks

View File

@@ -108,7 +108,7 @@ def pbPlaySoundData(samples,volume,async=false,sampleFreq=11025)
ret = name
break
end
return ret
next ret
}
playThenDelete = proc { |path,volume,length,_async|
next if !path || !safeExists?(path)

View File

@@ -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

View File

@@ -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
#===============================================================================
#
#===============================================================================

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -921,6 +921,15 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
text.gsub!(/\\pog/i,"")
text.gsub!(/\\b/i,"<c3=3050C8,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)
text.gsub!(/\\[Cc]\[([0-9]+)\]/) {
m = $1.to_i
@@ -951,7 +960,7 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
### Controls
textchunks=[]
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)
if $~[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
pbPositionNearMsgWindow(facewindow,msgwindow,:left)
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
msgwindow.textspeed = (param=="") ? -999 : param.to_i
when "." # Wait 0.25 seconds

View File

@@ -117,7 +117,7 @@ class PictureEx
end
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?(Method); cb.call(self)
end

View File

@@ -28,6 +28,7 @@ begin
names[EVASION] = _INTL("evasiveness")
return names[id]
end
def self.getNameBrief(id)
id = getID(PBStats,id)
names = []
@@ -41,6 +42,7 @@ begin
names[EVASION] = _INTL("eva")
return names[id]
end
def self.eachStat
[HP,ATTACK,DEFENSE,SPATK,SPDEF,SPEED].each { |s| yield s }
end

View File

@@ -220,7 +220,7 @@ class PokeBattle_Battler
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
stage = @stages[PBStats::SPEED] + 6
speed = @speed*stageMul[stage]/stageDiv[stage]
speedMult = 0x1000
speedMult = 1.0
# Ability effects that alter calculated Speed
if abilityActive?
speedMult = BattleHandlers.triggerSpeedCalcAbility(@ability,self,speedMult)
@@ -242,7 +242,7 @@ class PokeBattle_Battler
speedMult *= 1.1
end
# Calculation
return [(speed.to_f*speedMult/0x1000).round,1].max
return [(speed*speedMult).round,1].max
end
def pbWeight

View File

@@ -65,6 +65,7 @@ class PokeBattle_Battler
def pbInitialize(pkmn,idxParty,batonPass=false)
pbInitPokemon(pkmn,idxParty)
pbInitEffects(batonPass)
@damageState.reset
end
def pbInitPokemon(pkmn,idxParty)
@@ -138,7 +139,6 @@ class PokeBattle_Battler
@effects[PBEffects::Substitute] = 0
@effects[PBEffects::Telekinesis] = 0
end
@damageState.reset
@fainted = (@hp==0)
@initialHP = 0
@lastAttacker = []
@@ -302,7 +302,7 @@ class PokeBattle_Battler
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
@pokemon = nil
@pokemonIndex = -1

View File

@@ -171,7 +171,7 @@ class PokeBattle_Battler
return true
end
def pbCanSynchronizeStatus?(status,target)
def pbCanSynchronizeStatus?(newStatus,target)
return false if fainted?
# Trying to replace a status problem with another one
return false if self.status!=PBStatuses::NONE
@@ -179,7 +179,7 @@ class PokeBattle_Battler
return false if @battle.field.terrain==PBBattleTerrains::Misty && affectedByTerrain?
# Type immunities
hasImmuneType = false
case self.status
case newStatus
when PBStatuses::POISON
# NOTE: target will have Synchronize, so it can't have Corrosion.
if !(target && target.hasActiveAbility?(:CORROSION))
@@ -193,15 +193,15 @@ class PokeBattle_Battler
end
return false if hasImmuneType
# Ability immunity
if BattleHandlers.triggerStatusImmunityAbilityNonIgnorable(@ability,self,status)
if BattleHandlers.triggerStatusImmunityAbilityNonIgnorable(@ability,self,newStatus)
return false
end
if abilityActive? && BattleHandlers.triggerStatusImmunityAbility(@ability,self,status)
if abilityActive? && BattleHandlers.triggerStatusImmunityAbility(@ability,self,newStatus)
return false
end
eachAlly do |b|
next if !b.abilityActive?
next if !BattleHandlers.triggerStatusImmunityAllyAbility(b.ability,self,status)
next if !BattleHandlers.triggerStatusImmunityAllyAbility(b.ability,self,newStatus)
return false
end
# Safeguard immunity

View File

@@ -8,7 +8,8 @@ class PokeBattle_Battler
if tryFlee && @battle.wildBattle? && opposes? &&
@battle.rules["alwaysflee"] && @battle.pbCanRun?(@index)
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
pbEndTurn(choice)
return true
@@ -323,7 +324,7 @@ class PokeBattle_Battler
@battle.pbDisplay(_INTL("When the flame touched the powder on the Pokémon, it exploded!"))
user.lastMoveFailed = true
w = @battle.pbWeather
if w!=PBWeather.RAINDANCE && w!=PBWeather.HEAVYRAIN && user.takesIndirectDamage?
if w!=PBWeather::Rain && w!=PBWeather::HeavyRain && user.takesIndirectDamage?
oldHP = user.hp
user.pbReduceHP((user.totalhp/4.0).round,false)
user.pbFaint if user.fainted?

View File

@@ -95,8 +95,8 @@ class PokeBattle_Move
modifiers[BASE_ACC] = baseAcc
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 0x1000
modifiers[EVA_MULT] = 0x1000
modifiers[ACC_MULT] = 1.0
modifiers[EVA_MULT] = 1.0
pbCalcAccuracyModifiers(user,target,modifiers)
# Check if move can't miss
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]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[ACC_MULT] / 0x1000).round
evasion = (evasion * modifiers[EVA_MULT] / 0x1000).round
accuracy = (accuracy * modifiers[ACC_MULT]).round
evasion = (evasion * modifiers[EVA_MULT]).round
evasion = 1 if evasion<1
# Calculation
return @battle.pbRandom(100) < modifiers[BASE_ACC] * accuracy / evasion
@@ -140,11 +140,11 @@ class PokeBattle_Move
end
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
if @battle.field.effects[PBEffects::Gravity]>0
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*5/3).round
modifiers[ACC_MULT] *= 5/3.0
end
if user.effects[PBEffects::MicleBerry]
user.effects[PBEffects::MicleBerry] = false
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*1.2).round
modifiers[ACC_MULT] *= 1.2
end
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
@@ -244,14 +244,14 @@ class PokeBattle_Move
defense = (defense.to_f*stageMul[defStage]/stageDiv[defStage]).floor
end
# 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)
# Main damage calculation
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT] / 0x1000).round,1].max
atk = [(atk * multipliers[ATK_MULT] / 0x1000).round,1].max
defense = [(defense * multipliers[DEF_MULT] / 0x1000).round,1].max
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
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
atk = [(atk * multipliers[ATK_MULT]).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 = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
target.damageState.calcDamage = damage
end
@@ -306,10 +306,10 @@ class PokeBattle_Move
end
# Other
if user.effects[PBEffects::MeFirst]
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
multipliers[BASE_DMG_MULT] *= 1.5
end
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
if user.effects[PBEffects::Charge]>0 && isConst?(type,PBTypes,:ELECTRIC)
multipliers[BASE_DMG_MULT] *= 2
@@ -341,15 +341,15 @@ class PokeBattle_Move
case @battle.field.terrain
when PBBattleTerrains::Electric
if isConst?(type,PBTypes,:ELECTRIC)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
multipliers[BASE_DMG_MULT] *= 1.5
end
when PBBattleTerrains::Grassy
if isConst?(type,PBTypes,:GRASS)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
multipliers[BASE_DMG_MULT] *= 1.5
end
when PBBattleTerrains::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
@@ -361,28 +361,28 @@ class PokeBattle_Move
if @battle.internalBattle
if user.pbOwnedByPlayer?
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
multipliers[ATK_MULT] = (multipliers[ATK_MULT]*1.1).round
multipliers[ATK_MULT] *= 1.1
end
end
if target.pbOwnedByPlayer?
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
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.1).round
multipliers[DEF_MULT] *= 1.1
end
end
end
# Multi-targeting attacks
if numTargets>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*0.75).round
multipliers[FINAL_DMG_MULT] *= 0.75
end
# Weather
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
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)
multipliers[FINAL_DMG_MULT] /= 2
end
@@ -390,17 +390,17 @@ class PokeBattle_Move
if isConst?(type,PBTypes,:FIRE)
multipliers[FINAL_DMG_MULT] /= 2
elsif isConst?(type,PBTypes,:WATER)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
multipliers[FINAL_DMG_MULT] *= 1.5
end
when PBWeather::Sandstorm
if target.pbHasType?(:ROCK) && specialMove? && @function!="122" # Psyshock
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.5).round
multipliers[DEF_MULT] *= 1.5
end
end
# Critical hits
if target.damageState.critical
if NEWEST_BATTLE_MECHANICS
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
multipliers[FINAL_DMG_MULT] *= 1.5
else
multipliers[FINAL_DMG_MULT] *= 2
end
@@ -415,12 +415,11 @@ class PokeBattle_Move
if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2
else
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
multipliers[FINAL_DMG_MULT] *= 1.5
end
end
# Type effectiveness
multipliers[FINAL_DMG_MULT] *= target.damageState.typeMod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
multipliers[FINAL_DMG_MULT] = multipliers[FINAL_DMG_MULT].round
# Burn
if user.status==PBStatuses::BURN && physicalMove? && damageReducedByBurn? &&
!user.hasActiveAbility?(:GUTS)
@@ -431,19 +430,19 @@ class PokeBattle_Move
!user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && physicalMove?
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && specialMove?
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end

View File

@@ -1947,7 +1947,7 @@ class PokeBattle_Move_061 < PokeBattle_Move
def pbEffectAgainstTarget(user,target)
newType = getConst(PBTypes,:WATER)
user.pbChangeTypes(newType)
target.pbChangeTypes(newType)
typeName = PBTypes.getName(newType)
@battle.pbDisplay(_INTL("{1} transformed into the {2} type!",target.pbThis,typeName))
end
@@ -2465,7 +2465,7 @@ end
class PokeBattle_Move_073 < PokeBattle_FixedDamageMove
def pbAddTarget(targets,user)
return if user.lastFoeAttacker.length==0
lastAttacker = user.lastFoeAttacker[user.lastFoeAttacker.last]
lastAttacker = user.lastFoeAttacker.last
return if lastAttacker<0 || !user.opposes?(lastAttacker)
user.pbAddTarget(targets,user,@battle.battlers[lastAttacker],self,false)
end
@@ -2546,7 +2546,7 @@ class PokeBattle_Move_076 < PokeBattle_Move
def pbModifyDamage(damageMult,user,target)
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
end
end

View File

@@ -422,7 +422,7 @@ class PokeBattle_Move_095 < PokeBattle_Move
def pbModifyDamage(damageMult,user,target)
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
end
end
@@ -752,7 +752,7 @@ class PokeBattle_Move_09F < PokeBattle_Move
elsif isConst?(@id,PBMoves,:MULTIATTACK)
@itemTypes = {
:FIGHTINGMEMORY => :FIGHTING,
:SLYINGMEMORY => :FLYING,
:FLYINGMEMORY => :FLYING,
:POISONMEMORY => :POISON,
:GROUNDMEMORY => :GROUND,
:ROCKMEMORY => :ROCK,
@@ -777,7 +777,7 @@ class PokeBattle_Move_09F < PokeBattle_Move
if user.itemActive?
@itemTypes.each do |item, itemType|
next if !isConst?(user.item,PBItems,item)
t = hasConst?(PBTypes,itemType)
t = getConst(PBTypes,itemType)
ret = t || ret
break
end
@@ -1132,7 +1132,7 @@ class PokeBattle_Move_0AE < PokeBattle_Move
return false
end
def pbEffectGeneral(user)
def pbEffectAgainstTarget(user,target)
user.pbUseMoveSimple(target.lastRegularMoveUsed,target.index)
end
@@ -2070,9 +2070,7 @@ class PokeBattle_Move_0C4 < PokeBattle_TwoTurnMove
def pbBaseDamageMultiplier(damageMult,user,target)
w = @battle.pbWeather
if w>0 && w!=PBWeather::Sun && w!=PBWeather::HarshSun
damageMult = (damageMult/2.0).round
end
damageMult /= 2 if w>0 && w!=PBWeather::Sun && w!=PBWeather::HarshSun
return damageMult
end
end
@@ -2405,18 +2403,19 @@ end
#===============================================================================
class PokeBattle_Move_0D3 < PokeBattle_Move
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]
baseDmg = baseDmg << shift
baseDmg *= 2**shift
return baseDmg
end
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.currentMove = @id
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
@@ -3084,7 +3083,7 @@ class PokeBattle_Move_0EC < PokeBattle_Move
switchedBattlers.push(b.index)
roarSwitched.push(b.index)
end
if roarSwitched>0
if roarSwitched.length>0
@battle.moldBreaker = false if roarSwitched.include?(user.index)
@battle.pbPriority(true).each do |b|
b.pbEffectsOnSwitchIn(true) if roarSwitched.include?(b.index)

View File

@@ -692,9 +692,11 @@ class PokeBattle_Battle
pbDisplay("The mysterious air current has dissipated!")
end
end
# Check for form changes caused by the weather changing
if @field.weather!=oldWeather
# Check for form changes caused by the weather changing
eachBattler { |b| b.pbCheckFormOnWeatherChange }
# Start up the default weather
pbStartWeather(nil,@field.defaultWeather) if @field.defaultWeather!=PBWeather::None
end
end

View File

@@ -169,7 +169,7 @@ class PokeBattle_Battle
idxPartyForName = idxPartyNew
enemyParty = pbParty(idxBattler)
if isConst?(enemyParty[idxPartyNew].ability,PBAbilities,:ILLUSION)
idxPartyForName = pbGetLastPokeInTeam(idxBattler)
idxPartyForName = pbLastInTeam(idxBattler)
end
if pbDisplayConfirm(_INTL("{1} is about to send in {2}. Will you switch your Pokémon?",
opponent.fullname,enemyParty[idxPartyForName].name))
@@ -245,7 +245,7 @@ class PokeBattle_Battle
pbDisplayBrief(_INTL("{1}, switch out! Come back!",battler.name))
end
else
owner = pbGetOwnerName(b.index)
owner = pbGetOwnerName(battler.index)
pbDisplayBrief(_INTL("{1} withdrew {2}!",owner,battler.name))
end
end

View File

@@ -83,7 +83,7 @@ class PokeBattle_Battle
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)
trainerName = pbGetOwnerName(userBattler.index)
pbUseItemMessage(item,trainerName)
@@ -100,14 +100,14 @@ class PokeBattle_Battle
pbReturnUnusedItemToBag(item,userBattler.index)
end
# Uses an item on a Pokémon in battle that belongs to the player.
def pbUseItemOnBattler(item,idxParty,userBattler)
# Uses an item on a Pokémon in battle that belongs to the trainer.
def pbUseItemOnBattler(item,idxBattler,userBattler)
trainerName = pbGetOwnerName(userBattler.index)
pbUseItemMessage(item,trainerName)
pkmn = pbParty(userBattler.index)[idxParty]
battler = pbFindBattler(idxParty,userBattler.index)
idxBattler = userBattler.index if idxBattler<0
battler = @battlers[idxBattler]
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)
ch[1] = 0 # Delete item from choice
return

View File

@@ -52,7 +52,8 @@ class PokeBattle_Battle
elsif @internalBattle
pbDisplayPaused(_INTL("No! There's no running from a Trainer battle!"))
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
return 1
end
@@ -60,7 +61,8 @@ class PokeBattle_Battle
end
# Fleeing from wild battles
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
return 1
end
@@ -70,7 +72,8 @@ class PokeBattle_Battle
end
if !duringBattle
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
return 1
end
@@ -79,7 +82,8 @@ class PokeBattle_Battle
if BattleHandlers.triggerRunFromBattleAbility(battler.ability,battler)
pbShowAbilitySplash(battler,true)
pbHideAbilitySplash(battler)
pbDisplayPaused(_INTL("You got away safely!")) { pbSEPlay("Battle flee") }
pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("You got away safely!"))
@decision = 3
return 1
end
@@ -87,8 +91,9 @@ class PokeBattle_Battle
# Held items that guarantee escape
if battler.itemActive?
if BattleHandlers.triggerRunFromBattleItem(battler.item,battler)
pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("{1} fled using its {2}!",
battler.pbThis,battler.itemName)) { pbSEPlay("Battle flee") }
battler.pbThis,battler.itemName))
@decision = 3
return 1
end
@@ -135,7 +140,8 @@ class PokeBattle_Battle
rate += @runCommand*30
end
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
return 1
end

View File

@@ -20,7 +20,7 @@ class PokeBattle_AI
# NOTE: The AI will only consider using an item on the Pokémon it's currently
# choosing an action for.
def pbEnemyItemToUse(idxBattler)
return 0 if !@internalBattle
return 0 if !@battle.internalBattle
items = @battle.pbGetOwnerItems(idxBattler)
return 0 if !items || items.length==0
# Determine target of item (always the Pokémon choosing the action)

View File

@@ -135,7 +135,7 @@ class PokeBattle_AI
if @battle.pbRegisterSwitch(idxBattler,list[0])
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will switch with " +
"#{@battle.pbParty(idxBattler)[list[0]].name}")
return
return true
end
end
end

View File

@@ -81,20 +81,27 @@ class PokeBattle_AI
return
end
end
# Randomly choose a move to use
# If there are no calculated choices, pick one at random
if choices.length==0
# If there are no calculated choices, use Struggle (or an Encored move)
@battle.pbAutoChooseMove(idxBattler)
else
# 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
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random")
user.eachMoveWithIndex do |_m,i|
next if !@battle.pbCanChooseMove?(idxBattler,i,false)
choices.push([i,100,-1]) # Move index, score, target
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
# Log the result
if @battle.choices[idxBattler][2]

View File

@@ -1364,7 +1364,7 @@ class PokeBattle_AI
:ROCK, # Cave
:GROUND # Sand
]
type = envtypes[@environment]
type = envtypes[@battle.environment]
score -= 90 if user.pbHasType?(type)
end
#---------------------------------------------------------------------------
@@ -2806,7 +2806,7 @@ class PokeBattle_AI
when "152"
#---------------------------------------------------------------------------
when "153"
score -= 95 if target.pbOwnSide.effects[PBEffects::StickyWeb]
score -= 95 if user.pbOpposingSide.effects[PBEffects::StickyWeb]
#---------------------------------------------------------------------------
when "154"
#---------------------------------------------------------------------------

View File

@@ -275,7 +275,7 @@ class PokeBattle_AI
defense = pbRoughStat(target,PBStats::SPDEF,skill)
end
##### Calculate all multiplier effects #####
multipliers = [0x1000,0x1000,0x1000,0x1000]
multipliers = [1.0, 1.0, 1.0, 1.0]
# Ability effects that alter damage
moldBreaker = false
if skill>=PBTrainerAI.highSkill && target.hasMoldBreaker?
@@ -364,7 +364,7 @@ class PokeBattle_AI
end
# Parental Bond
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
# Me First
# TODO
@@ -403,15 +403,15 @@ class PokeBattle_AI
case @battle.field.terrain
when PBBattleTerrains::Electric
if isConst?(type,PBTypes,:ELECTRIC)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
multipliers[BASE_DMG_MULT] *= 1.5
end
when PBBattleTerrains::Grassy
if isConst?(type,PBTypes,:GRASS)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
multipliers[BASE_DMG_MULT] *= 1.5
end
when PBBattleTerrains::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
@@ -427,9 +427,9 @@ class PokeBattle_AI
# won't control the player's Pokémon.
if target.pbOwnedByPlayer?
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
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.1).round
multipliers[DEF_MULT] *= 1.1
end
end
end
@@ -437,7 +437,7 @@ class PokeBattle_AI
# Multi-targeting attacks
if skill>=PBTrainerAI.highSkill
if pbTargetsMultiple?(move,user)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*0.75).round
multipliers[FINAL_DMG_MULT] *= 0.75
end
end
# Weather
@@ -445,7 +445,7 @@ class PokeBattle_AI
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
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)
multipliers[FINAL_DMG_MULT] /= 2
end
@@ -453,11 +453,11 @@ class PokeBattle_AI
if isConst?(type,PBTypes,:FIRE)
multipliers[FINAL_DMG_MULT] /= 2
elsif isConst?(type,PBTypes,:WATER)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
multipliers[FINAL_DMG_MULT] *= 1.5
end
when PBWeather::Sandstorm
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
@@ -469,7 +469,7 @@ class PokeBattle_AI
if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2
else
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
multipliers[FINAL_DMG_MULT] *= 1.5
end
end
end
@@ -477,7 +477,6 @@ class PokeBattle_AI
if skill>=PBTrainerAI.mediumSkill
typemod = pbCalcTypeMod(type,user,target)
multipliers[FINAL_DMG_MULT] *= typemod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
multipliers[FINAL_DMG_MULT] = multipliers[FINAL_DMG_MULT].round
end
# Burn
if skill>=PBTrainerAI.highSkill
@@ -492,19 +491,19 @@ class PokeBattle_AI
if !move.ignoresReflect? && !user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && move.physicalMove?(type)
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && move.specialMove?(type)
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end
@@ -522,11 +521,11 @@ class PokeBattle_AI
# Move-specific final damage modifiers
# TODO
##### Main damage calculation #####
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT] / 0x1000).round,1].max
atk = [(atk * multipliers[ATK_MULT] / 0x1000).round,1].max
defense = [(defense * multipliers[DEF_MULT] / 0x1000).round,1].max
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
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
atk = [(atk * multipliers[ATK_MULT]).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 = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
# "AI-specific calculations below"
# Increased critical hit rates
if skill>=PBTrainerAI.mediumSkill
@@ -585,8 +584,8 @@ class PokeBattle_AI
modifiers[BASE_ACC] = baseAcc
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 0x1000
modifiers[EVA_MULT] = 0x1000
modifiers[ACC_MULT] = 1.0
modifiers[EVA_MULT] = 1.0
pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill)
# Check if move can't miss
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]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[ACC_MULT] / 0x1000).round
evasion = (evasion * modifiers[EVA_MULT] / 0x1000).round
accuracy = (accuracy * modifiers[ACC_MULT]).round
evasion = (evasion * modifiers[EVA_MULT]).round
evasion = 1 if evasion<1
return modifiers[BASE_ACC] * accuracy / evasion
end
@@ -642,10 +641,10 @@ class PokeBattle_AI
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
if skill>=PBTrainerAI.mediumSkill
if @battle.field.effects[PBEffects::Gravity]>0
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*5/3).round
modifiers[ACC_MULT] *= 5/3.0
end
if user.effects[PBEffects::MicleBerry]
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*1.2).round
modifiers[ACC_MULT] *= 1.2
end
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

View File

@@ -5,19 +5,19 @@ module PBTargets
User = 10
NearAlly = 100 # Aromatic Mist, Helping Hand, Hold Hands
UserOrNearAlly = 200 # Acupressure
UserAndAllies = 5 # Aromatherapy, Gear Up, Heal Bell, Life Dew, Magnetic Flux, Howl (in Gen 8+)
NearFoe = 400 # Me First
AllNearFoes = 4
RandomNearFoe = 2 # Petal Dance, Outrage, Struggle, Thrash, Uproar
AllNearFoes = 4
Foe = 9 # For throwing a Poké Ball
AllFoes = 6 # Unused (for completeness)
NearOther = 0
AllNearOthers = 8
Other = 3 # Most Flying-type moves, pulse moves (hits non-near targets)
AllBattlers = 7 # Flower Shield, Perish Song, Rototiller, Teatime
UserSide = 40
FoeSide = 80 # Entry hazards
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)
return target==None ||

View File

@@ -326,7 +326,7 @@ class PokemonDataBox < SpriteWrapper
if @expFlash==0
pbSEStop
@expFlash = Graphics.frame_rate/5
pbSEPlay("Exp full")
pbSEPlay("Pkmn exp full")
self.flash(Color.new(64,200,248,192),@expFlash)
for i in @sprites
i[1].flash(Color.new(64,200,248,192),@expFlash) if !i[1].disposed?

View File

@@ -578,16 +578,16 @@ def pbBattleGem(user,type,move,mults,moveType)
return if !isConst?(moveType,PBTypes,type)
user.effects[PBEffects::GemConsumed] = user.item
if NEWEST_BATTLE_MECHANICS
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.3).round
mults[BASE_DMG_MULT] *= 1.3
else
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round
mults[BASE_DMG_MULT] *= 1.5
end
end
def pbBattleTypeWeakingBerry(type,moveType,target,mults)
return if !isConst?(moveType,PBTypes,type)
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.battle.pbCommonAnimation("EatBerry",target)
end

View File

@@ -25,6 +25,10 @@ class PokeBattle_FakeBattler
def shiny?; return @pokemon.shiny?; end
alias isShiny? shiny?
def isSpecies?(check_species)
return @pokemon && @pokemon.isSpecies?(check_species)
end
def fainted?; return false; end
alias isFainted? fainted?
def shadowPokemon?; return false; end
@@ -458,7 +462,8 @@ class PokeBattle_SafariZone
catchFactor *= 2 # Easier to catch
escapeFactor *= 2 if pbRandom(100)<90 # More likely to escape
when 3 # Run
pbDisplayPaused(_INTL("You got away safely!")) { pbSEPlay("Battle flee") }
pbSEPlay("Battle flee")
pbDisplayPaused(_INTL("You got away safely!"))
@decision = 3
end
catchFactor = [[catchFactor,3].max,20].min
@@ -469,7 +474,8 @@ class PokeBattle_SafariZone
pbDisplay(_INTL("PA: You have no Safari Balls left! Game over!"))
@decision = 2
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
elsif cmd==1 # Bait
pbDisplay(_INTL("{1} is eating!",wildpoke.name))

View File

@@ -11,7 +11,7 @@ BattleHandlers::SpeedCalcAbility.add(:CHLOROPHYLL,
BattleHandlers::SpeedCalcAbility.add(:QUICKFEET,
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,
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)
battle.pbShowAbilitySplash(battler,true)
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
next true
end
@@ -767,13 +768,13 @@ BattleHandlers::MoveBaseTypeModifierAbility.add(:REFRIGERATE,
BattleHandlers::AccuracyCalcUserAbility.add(:COMPOUNDEYES,
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,
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,
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,
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,
proc { |ability,mods,user,target,move,type|
if target.battle.pbWeather==PBWeather::Sandstorm
mods[EVA_MULT] = (mods[EVA_MULT]*1.25).round
mods[EVA_MULT] *= 1.25
end
}
)
@@ -838,7 +839,7 @@ BattleHandlers::AccuracyCalcTargetAbility.add(:SANDVEIL,
BattleHandlers::AccuracyCalcTargetAbility.add(:SNOWCLOAK,
proc { |ability,mods,user,target,move,type|
if target.battle.pbWeather==PBWeather::Hail
mods[EVA_MULT] = (mods[EVA_MULT]*1.25).round
mods[EVA_MULT] *= 1.25
end
}
)
@@ -875,7 +876,7 @@ BattleHandlers::AccuracyCalcTargetAbility.add(:WONDERSKIN,
BattleHandlers::DamageCalcUserAbility.add(:AERILATE,
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 &&
target.battle.choices[target.index][0]!=:Shift) ||
target.movedThisRound?
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.3).round
mults[BASE_DMG_MULT] *= 1.3
end
}
)
@@ -894,21 +895,21 @@ BattleHandlers::DamageCalcUserAbility.add(:ANALYTIC,
BattleHandlers::DamageCalcUserAbility.add(:BLAZE,
proc { |ability,user,target,move,mults,baseDmg,type|
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
}
)
BattleHandlers::DamageCalcUserAbility.add(:DEFEATIST,
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,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.burned? && move.specialMove?
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round
mults[BASE_DMG_MULT] *= 1.5
end
}
)
@@ -916,7 +917,7 @@ BattleHandlers::DamageCalcUserAbility.add(:FLAREBOOST,
BattleHandlers::DamageCalcUserAbility.add(:FLASHFIRE,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.effects[PBEffects::FlashFire] && isConst?(type,PBTypes,:FIRE)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round
mults[ATK_MULT] *= 1.5
end
}
)
@@ -925,7 +926,7 @@ BattleHandlers::DamageCalcUserAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.physicalMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round
mults[ATK_MULT] *= 1.5
end
}
)
@@ -933,7 +934,7 @@ BattleHandlers::DamageCalcUserAbility.add(:FLOWERGIFT,
BattleHandlers::DamageCalcUserAbility.add(:GUTS,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.pbHasAnyStatus? && move.physicalMove?
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round
mults[ATK_MULT] *= 1.5
end
}
)
@@ -948,19 +949,19 @@ BattleHandlers::DamageCalcUserAbility.copy(:HUGEPOWER,:PUREPOWER)
BattleHandlers::DamageCalcUserAbility.add(:HUSTLE,
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,
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,
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?
user.eachAlly do |b|
next if !b.hasActiveAbility?([:MINUS,:PLUS])
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round
mults[ATK_MULT] *= 1.5
break
end
}
@@ -980,7 +981,7 @@ BattleHandlers::DamageCalcUserAbility.copy(:MINUS,:PLUS)
BattleHandlers::DamageCalcUserAbility.add(:NEUROFORCE,
proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypes.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.25).round
mults[FINAL_DMG_MULT] *= 1.25
end
}
)
@@ -988,14 +989,14 @@ BattleHandlers::DamageCalcUserAbility.add(:NEUROFORCE,
BattleHandlers::DamageCalcUserAbility.add(:OVERGROW,
proc { |ability,user,target,move,mults,baseDmg,type|
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
}
)
BattleHandlers::DamageCalcUserAbility.add(:RECKLESS,
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|
if user.gender!=2 && target.gender!=2
if user.gender==target.gender
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.25).round
mults[BASE_DMG_MULT] *= 1.25
else
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*0.75).round
mults[BASE_DMG_MULT] *= 0.75
end
end
}
@@ -1017,22 +1018,20 @@ BattleHandlers::DamageCalcUserAbility.add(:SANDFORCE,
(isConst?(type,PBTypes,:ROCK) ||
isConst?(type,PBTypes,:GROUND) ||
isConst?(type,PBTypes,:STEEL))
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.3).round
mults[BASE_DMG_MULT] *= 1.3
end
}
)
BattleHandlers::DamageCalcUserAbility.add(:SHEERFORCE,
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,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.turnCount<=5 && move.physicalMove?
mults[ATK_MULT] = (mults[ATK_MULT]*0.5).round
end
mults[ATK_MULT] /= 2 if user.effects[PBEffects::SlowStart]>0 && move.physicalMove?
}
)
@@ -1040,7 +1039,7 @@ BattleHandlers::DamageCalcUserAbility.add(:SOLARPOWER,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round
mults[ATK_MULT] *= 1.5
end
}
)
@@ -1048,7 +1047,7 @@ BattleHandlers::DamageCalcUserAbility.add(:SOLARPOWER,
BattleHandlers::DamageCalcUserAbility.add(:SNIPER,
proc { |ability,user,target,move,mults,baseDmg,type|
if target.damageState.critical
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.5).round
mults[FINAL_DMG_MULT] *= 1.5
end
}
)
@@ -1061,28 +1060,28 @@ BattleHandlers::DamageCalcUserAbility.add(:STAKEOUT,
BattleHandlers::DamageCalcUserAbility.add(:STEELWORKER,
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,
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,
proc { |ability,user,target,move,mults,baseDmg,type|
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
}
)
BattleHandlers::DamageCalcUserAbility.add(:TECHNICIAN,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.index!=target.index && move.id>0 && baseDmg*mults[BASE_DMG_MULT]/0x1000<=60
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round
if user.index!=target.index && move.id>0 && baseDmg*mults[BASE_DMG_MULT]<=60
mults[BASE_DMG_MULT] *= 1.5
end
}
)
@@ -1096,21 +1095,21 @@ BattleHandlers::DamageCalcUserAbility.add(:TINTEDLENS,
BattleHandlers::DamageCalcUserAbility.add(:TORRENT,
proc { |ability,user,target,move,mults,baseDmg,type|
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
}
)
BattleHandlers::DamageCalcUserAbility.add(:TOUGHCLAWS,
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,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.poisoned? && move.physicalMove?
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.5).round
mults[BASE_DMG_MULT] *= 1.5
end
}
)
@@ -1128,7 +1127,7 @@ BattleHandlers::DamageCalcUserAbility.add(:WATERBUBBLE,
BattleHandlers::DamageCalcUserAllyAbility.add(:BATTERY,
proc { |ability,user,target,move,mults,baseDmg,type|
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|
w = user.battle.pbWeather
if move.physicalMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round
mults[ATK_MULT] *= 1.5
end
}
)
@@ -1148,7 +1147,7 @@ BattleHandlers::DamageCalcUserAllyAbility.add(:FLOWERGIFT,
BattleHandlers::DamageCalcTargetAbility.add(:DRYSKIN,
proc { |ability,user,target,move,mults,baseDmg,type|
if isConst?(type,PBTypes,:FIRE)
mults[BASE_DMG_MULT] = (mults[BASE_DMG_MULT]*1.25).round
mults[BASE_DMG_MULT] *= 1.25
end
}
)
@@ -1156,7 +1155,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:DRYSKIN,
BattleHandlers::DamageCalcTargetAbility.add(:FILTER,
proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypes.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.75).round
mults[FINAL_DMG_MULT] *= 0.75
end
}
)
@@ -1167,7 +1166,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round
mults[DEF_MULT] *= 1.5
end
}
)
@@ -1175,7 +1174,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:FLOWERGIFT,
BattleHandlers::DamageCalcTargetAbility.add(:FLUFFY,
proc { |ability,user,target,move,mults,baseDmg,type|
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,
proc { |ability,user,target,move,mults,baseDmg,type|
if user.battle.field.terrain==PBBattleTerrains::Grassy
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round
mults[DEF_MULT] *= 1.5
end
}
)
BattleHandlers::DamageCalcTargetAbility.add(:HEATPROOF,
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,
proc { |ability,user,target,move,mults,baseDmg,type|
if target.pbHasAnyStatus? && move.physicalMove?
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round
mults[DEF_MULT] *= 1.5
end
}
)
@@ -1210,7 +1209,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:MARVELSCALE,
BattleHandlers::DamageCalcTargetAbility.add(:MULTISCALE,
proc { |ability,user,target,move,mults,baseDmg,type|
if target.hp==target.totalhp
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.5).round
mults[FINAL_DMG_MULT] /= 2
end
}
)
@@ -1218,7 +1217,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:MULTISCALE,
BattleHandlers::DamageCalcTargetAbility.add(:THICKFAT,
proc { |ability,user,target,move,mults,baseDmg,type|
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
}
)
@@ -1226,7 +1225,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:THICKFAT,
BattleHandlers::DamageCalcTargetAbility.add(:WATERBUBBLE,
proc { |ability,user,target,move,mults,baseDmg,type|
if isConst?(type,PBTypes,:FIRE)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.5).round
mults[FINAL_DMG_MULT] /= 2
end
}
)
@@ -1238,7 +1237,7 @@ BattleHandlers::DamageCalcTargetAbility.add(:WATERBUBBLE,
BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:PRISMARMOR,
proc { |ability,user,target,move,mults,baseDmg,type|
if PBTypes.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.75).round
mults[FINAL_DMG_MULT] *= 0.75
end
}
)
@@ -1246,7 +1245,7 @@ BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:PRISMARMOR,
BattleHandlers::DamageCalcTargetAbilityNonIgnorable.add(:SHADOWSHIELD,
proc { |ability,user,target,move,mults,baseDmg,type|
if target.hp==target.totalhp
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*0.5).round
mults[FINAL_DMG_MULT] /= 2
end
}
)
@@ -1259,14 +1258,14 @@ BattleHandlers::DamageCalcTargetAllyAbility.add(:FLOWERGIFT,
proc { |ability,user,target,move,mults,baseDmg,type|
w = user.battle.pbWeather
if move.specialMove? && (w==PBWeather::Sun || w==PBWeather::HarshSun)
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round
mults[DEF_MULT] *= 1.5
end
}
)
BattleHandlers::DamageCalcTargetAllyAbility.add(:FRIENDGUARD,
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,
proc { |ability,battler,endOfBattle|
next if !endOfBattle
next if endOfBattle
PBDebug.log("[Ability triggered] #{battler.pbThis}'s #{battler.abilityName}")
battler.pbRecoverHP(battler.totalhp/3,false,false)
}

View File

@@ -4,7 +4,7 @@
BattleHandlers::SpeedCalcItem.add(:CHOICESCARF,
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,
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 &&
target.battle.choices[target.index][0]!=:Shift) ||
target.movedThisRound?
mods[ACC_MULT] = (mods[ACC_MULT]*1.2).round
mods[ACC_MULT] *= 1.2
end
}
)
@@ -434,7 +434,7 @@ BattleHandlers::AccuracyCalcUserItem.add(:ZOOMLENS,
BattleHandlers::AccuracyCalcTargetItem.add(:BRIGHTPOWDER,
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|
if user.isSpecies?(:DIALGA) &&
(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
}
)
BattleHandlers::DamageCalcUserItem.add(:BLACKBELT,
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,
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,
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,
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,
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,
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,
proc { |item,user,target,move,mults,baseDmg,type|
if PBTypes.superEffective?(target.damageState.typeMod)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.2).round
mults[FINAL_DMG_MULT] *= 1.2
end
}
)
@@ -577,7 +577,7 @@ BattleHandlers::DamageCalcUserItem.add(:GRISEOUSORB,
proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:GIRATINA) &&
(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
}
)
@@ -590,7 +590,7 @@ BattleHandlers::DamageCalcUserItem.add(:GROUNDGEM,
BattleHandlers::DamageCalcUserItem.add(:HARDSTONE,
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,
proc { |item,user,target,move,mults,baseDmg,type|
if !move.is_a?(PokeBattle_Confusion)
mults[FINAL_DMG_MULT] = (mults[FINAL_DMG_MULT]*1.3).round
mults[FINAL_DMG_MULT] *= 1.3
end
}
)
@@ -622,14 +622,14 @@ BattleHandlers::DamageCalcUserItem.add(:LUSTROUSORB,
proc { |item,user,target,move,mults,baseDmg,type|
if user.isSpecies?(:PALKIA) &&
(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
}
)
BattleHandlers::DamageCalcUserItem.add(:MAGNET,
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,
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,
proc { |item,user,target,move,mults,baseDmg,type|
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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)
if NEWEST_BATTLE_MECHANICS
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
else
if move.specialMove? && !user.battle.rules["souldewclause"]
mults[ATK_MULT] = (mults[ATK_MULT]*1.5).round
mults[ATK_MULT] *= 1.5
end
end
}
@@ -765,7 +765,7 @@ BattleHandlers::DamageCalcUserItem.add(:SOULDEW,
BattleHandlers::DamageCalcUserItem.add(:SPELLTAG,
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,
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,
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,
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
# affected by Eviolite.
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,
proc { |item,user,target,move,mults,baseDmg,type|
if target.isSpecies?(:DITTO) && !target.effects[PBEffects::Transform]
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round
mults[DEF_MULT] *= 1.5
end
}
)
@@ -940,7 +940,7 @@ BattleHandlers::DamageCalcTargetItem.add(:SOULDEW,
next if NEWEST_BATTLE_MECHANICS
next if !target.isSpecies?(:LATIAS) && !target.isSpecies?(:LATIOS)
if move.specialMove? && !user.battle.rules["souldewclause"]
mults[DEF_MULT] = (mults[DEF_MULT]*1.5).round
mults[DEF_MULT] *= 1.5
end
}
)
@@ -1003,7 +1003,7 @@ BattleHandlers::TargetItemOnHit.add(:ABSORBBULB,
next if !target.pbCanRaiseStatStage?(PBStats::SPATK,target)
battle.pbCommonAnimation("UseItem",target)
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|
battle.pbDisplay(_INTL("{1}'s {2} popped!",target.pbThis,target.itemName))
target.pbConsumeItem(false,true)
target.pbSymbiosis
}
)
@@ -1020,7 +1021,7 @@ BattleHandlers::TargetItemOnHit.add(:CELLBATTERY,
next if !target.pbCanRaiseStatStage?(PBStats::ATTACK,target)
battle.pbCommonAnimation("UseItem",target)
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|
next if target.damageState.substitute || target.damageState.disguise
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)
battle.pbDisplay(_INTL("{1} consumed its {2} and hurt {3}!",target.pbThis,
target.itemName,user.pbThis(true)))
target.pbConsumeItem
target.pbHeldItemTriggered(item)
}
)
@@ -1054,7 +1057,9 @@ BattleHandlers::TargetItemOnHit.add(:JABOCABERRY,
BattleHandlers::TargetItemOnHit.add(:KEEBERRY,
proc { |item,user,target,move,battle|
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)
battle.pbCommonAnimation("UseItem",target)
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,
proc { |item,user,target,move,battle|
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)
battle.pbDisplay(_INTL("{1} consumed its {2} and hurt {3}!",target.pbThis,
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)
battle.pbCommonAnimation("UseItem",target)
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)
target.pbRaiseStatStageByCause(PBStats::SPATK,2,target,target.itemName,showAnim)
end
target.pbConsumeItem
target.pbHeldItemTriggered(item)
}
)
@@ -1509,7 +1516,7 @@ BattleHandlers::EORHealingItem.add(:LEFTOVERS,
BattleHandlers::EOREffectItem.add(:FLAMEORB,
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))
}
)
@@ -1529,7 +1536,7 @@ BattleHandlers::EOREffectItem.add(:STICKYBARB,
BattleHandlers::EOREffectItem.add(:TOXICORB,
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.pbThis,battler.itemName),true)
}

View File

@@ -54,6 +54,7 @@ module Events
@@OnWildBattleOverride = Event.new
@@OnWildBattleEnd = Event.new
@@OnTrainerPartyLoad = Event.new
@@OnChangeDirection = Event.new
# Fires whenever a map is created. Event handler receives two parameters: the
# map (RPG::Map) and the tileset (RPG::Tileset)
@@ -159,6 +160,10 @@ module Events
# e[2] - Party
def self.onTrainerPartyLoad; @@OnTrainerPartyLoad; 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
@@ -254,7 +259,7 @@ Events.onMapUpdate += proc { |_sender,_e|
# Checks per step
#===============================================================================
# Party Pokémon gain happiness from walking
Events.onStepTaken += proc{
Events.onStepTaken += proc {
$PokemonGlobal.happinessSteps = 0 if !$PokemonGlobal.happinessSteps
$PokemonGlobal.happinessSteps += 1
if $PokemonGlobal.happinessSteps>=128
@@ -363,26 +368,34 @@ def pbOnStepTaken(eventTriggered)
Events.onStepTakenTransferPossible.trigger(nil,handled)
return if handled[0]
pbBattleOnStepTaken(repel) if !eventTriggered && !$game_temp.in_menu
$PokemonTemp.encounterTriggered = false # This info isn't needed
end
def pbBattleOnStepTaken(repel=false)
return if $Trainer.ablePokemonCount==0
# Start wild encounters while turning on the spot
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
return if encounterType<0
return if encounterType < 0
return if !$PokemonEncounters.isEncounterPossibleHere?
$PokemonTemp.encounterType = encounterType
encounter = $PokemonEncounters.pbGenerateEncounter(encounterType)
encounter = EncounterModifier.trigger(encounter)
if $PokemonEncounters.pbCanEncounter?(encounter,repel)
if $PokemonEncounters.pbCanEncounter?(encounter, repel)
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 = EncounterModifier.trigger(encounter2)
pbDoubleWildBattle(encounter[0],encounter[1],encounter2[0],encounter2[1])
pbDoubleWildBattle(encounter[0], encounter[1], encounter2[0], encounter2[1])
else
pbWildBattle(encounter[0],encounter[1])
pbWildBattle(encounter[0], encounter[1])
end
$PokemonTemp.encounterType = -1
$PokemonTemp.encounterTriggered = true
end
$PokemonTemp.forceSingleBattle = false
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
#===============================================================================
@@ -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
#===============================================================================

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
#===============================================================================
@@ -541,6 +316,231 @@ def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
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
#===============================================================================

View File

@@ -11,6 +11,7 @@ end
class PokemonTemp
attr_accessor :encounterTriggered
attr_accessor :encounterType
attr_accessor :evolutionLevels
@@ -34,8 +35,8 @@ class PokemonTemp
when "canrun"; rules["canRun"] = true
when "cannotrun"; rules["canRun"] = false
when "roamerflees"; rules["roamerFlees"] = true
when "noExp"; rules["expGain"] = false
when "noMoney"; rules["moneyGain"] = false
when "noexp"; rules["expGain"] = false
when "nomoney"; rules["moneyGain"] = false
when "switchstyle"; rules["switchStyle"] = true
when "setstyle"; rules["switchStyle"] = false
when "anims"; rules["battleAnims"] = true
@@ -45,7 +46,7 @@ class PokemonTemp
when "environment", "environ"; rules["environment"] = getID(PBEnvironment,var)
when "backdrop", "battleback"; rules["backdrop"] = var
when "base"; rules["base"] = var
when "outcomevar", "outcome"; rules["outcomeVar"] = var
when "outcome", "outcomevar"; rules["outcomeVar"] = var
when "nopartner"; rules["noPartner"] = true
else
raise _INTL("Battle rule \"{1}\" does not exist.",rule)
@@ -64,7 +65,7 @@ def setBattleRule(*args)
else
case arg.downcase
when "terrain", "weather", "environment", "environ", "backdrop",
"battleback", "base", "outcomevar", "outcome"
"battleback", "base", "outcome", "outcomevar"
r = arg
next
end
@@ -251,7 +252,12 @@ def pbWildBattleCore(*args)
playerTrainers = [$Trainer]
playerParty = $Trainer.party
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.id = $PokemonGlobal.partner[2]
ally.party = $PokemonGlobal.partner[3]
@@ -391,7 +397,12 @@ def pbTrainerBattleCore(*args)
playerTrainers = [$Trainer]
playerParty = $Trainer.party
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.id = $PokemonGlobal.partner[2]
ally.party = $PokemonGlobal.partner[3]
@@ -553,6 +564,7 @@ def pbAfterBattle(decision,canLose)
end
end
Events.onEndBattle.trigger(nil,decision,canLose)
$game_player.straighten
end
Events.onEndBattle += proc { |_sender,e|

View File

@@ -241,6 +241,6 @@ def pbRoamingPokemonBattle(species, level)
return (decision!=2 && decision!=5)
end
EncounterModifier.registerEncounterEnd(proc{
EncounterModifier.registerEncounterEnd(proc {
$PokemonTemp.roamerIndex = nil
})

View File

@@ -393,7 +393,7 @@ Events.onAction += proc { |_sender,_e|
divemap = i; break
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
end
end

View File

@@ -2,7 +2,7 @@ class PokemonTemp
attr_writer :dependentEvents
def dependentEvents
@dependentEvents=DependentEvents.new if !@dependentEvents
@dependentEvents = DependentEvents.new if !@dependentEvents
return @dependentEvents
end
end
@@ -41,7 +41,8 @@ class PokemonGlobalMetadata
attr_writer :dependentEvents
def dependentEvents
return @dependentEvents || []
@dependentEvents = [] if !@dependentEvents
return @dependentEvents
end
end

View File

@@ -112,9 +112,9 @@ ItemHandlers::UseInField.add(:MAXREPEL,proc { |item|
next pbRepel(item,250)
})
Events.onStepTaken += proc{
if !PBTerrain.isIce?($game_player.terrain_tag) # Shouldn't count down if on ice
if $PokemonGlobal.repel>0
Events.onStepTaken += proc {
if $PokemonGlobal.repel>0
if !PBTerrain.isIce?($game_player.terrain_tag) # Shouldn't count down if on ice
$PokemonGlobal.repel -= 1
if $PokemonGlobal.repel<=0
if $PokemonBag.pbHasItem?(:REPEL) ||
@@ -955,6 +955,7 @@ ItemHandlers::UseOnPokemon.add(:DNASPLICERS,proc { |item,pkmn,scene|
end
if pkmn.fainted?
scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon."))
next false
end
# Fusing
if pkmn.fused==nil
@@ -963,13 +964,17 @@ ItemHandlers::UseOnPokemon.add(:DNASPLICERS,proc { |item,pkmn,scene|
poke2 = $Trainer.party[chosen]
if pkmn==poke2
scene.pbDisplay(_INTL("It cannot be fused with itself."))
next false
elsif poke2.egg?
scene.pbDisplay(_INTL("It cannot be fused with an Egg."))
next false
elsif poke2.fainted?
scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon."))
next false
elsif !poke2.isSpecies?(:RESHIRAM) &&
!poke2.isSpecies?(:ZEKROM)
scene.pbDisplay(_INTL("It cannot be fused with that Pokémon."))
next false
end
newForm = 0
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|
if !pkmn.isSpecies?(:NECROZMA) || pkmn.form==0
if !pkmn.isSpecies?(:NECROZMA) || pkmn.form == 2
scene.pbDisplay(_INTL("It had no effect."))
next false
end
if pkmn.fainted?
scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon."))
next false
end
# Fusing
if pkmn.fused==nil
@@ -1011,12 +1017,16 @@ ItemHandlers::UseOnPokemon.add(:NSOLARIZER,proc { |item,pkmn,scene|
poke2 = $Trainer.party[chosen]
if pkmn==poke2
scene.pbDisplay(_INTL("It cannot be fused with itself."))
next false
elsif poke2.egg?
scene.pbDisplay(_INTL("It cannot be fused with an Egg."))
next false
elsif poke2.fainted?
scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon."))
next false
elsif !poke2.isSpecies?(:SOLGALEO)
scene.pbDisplay(_INTL("It cannot be fused with that Pokémon."))
next false
end
pkmn.setForm(1) {
pkmn.fused = poke2
@@ -1041,12 +1051,13 @@ ItemHandlers::UseOnPokemon.add(:NSOLARIZER,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."))
next false
end
if pkmn.fainted?
scene.pbDisplay(_INTL("This can't be used on the fainted Pokémon."))
next false
end
# Fusing
if pkmn.fused==nil
@@ -1055,12 +1066,16 @@ ItemHandlers::UseOnPokemon.add(:NLUNARIZER,proc { |item,pkmn,scene|
poke2 = $Trainer.party[chosen]
if pkmn==poke2
scene.pbDisplay(_INTL("It cannot be fused with itself."))
next false
elsif poke2.egg?
scene.pbDisplay(_INTL("It cannot be fused with an Egg."))
next false
elsif poke2.fainted?
scene.pbDisplay(_INTL("It cannot be fused with that fainted Pokémon."))
next false
elsif !poke2.isSpecies?(:LUNALA)
scene.pbDisplay(_INTL("It cannot be fused with that Pokémon."))
next false
end
pkmn.setForm(2) {
pkmn.fused = poke2

View File

@@ -37,15 +37,6 @@ class PokeBattle_Pokemon
return pbGetFSpeciesFromForm(@species,formSimple)
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
def initialize(*args)
@form = (pbGetSpeciesFromFSpecies(args[0])[1] rescue 0)

View File

@@ -165,9 +165,15 @@ class PokemonRegionMap_Scene
def pbSaveMapData
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
map = @mapdata[i]
return if !map
next if !map
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n",i))
f.write(sprintf("Name=%s\r\nFilename=%s\r\n",csvQuote(map[0]),csvQuote(map[1])))
for loc in map[2]

View File

@@ -77,7 +77,7 @@ def pbAddPokemon(pokemon,level=nil,seeform=true)
pokemon = pbNewPkmn(pokemon,level)
end
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)
pbSeenForm(pokemon) if seeform
return true
@@ -113,7 +113,7 @@ def pbAddToParty(pokemon,level=nil,seeform=true)
pokemon = pbNewPkmn(pokemon,level)
end
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)
pbSeenForm(pokemon) if seeform
return true

View File

@@ -286,7 +286,7 @@ end
#===============================================================================
# JavaScript-related utilities
# Json-related utilities
#===============================================================================
# Returns true if the given string represents a valid object in JavaScript
# Object Notation, and false otherwise.
@@ -1172,10 +1172,10 @@ def pbLoadRpgxpScene(scene)
end
Graphics.transition(20)
Graphics.freeze
oldscene.createSpritesets
$scene = oldscene
$scene.createSpritesets
pbShowObjects(visibleObjects)
Graphics.transition(20)
$scene = oldscene
end

View File

@@ -208,6 +208,8 @@ def pbDebugMenuCommands(showall=true)
_INTL("Fully compile all data."))
commands.add("othermenu","debugconsole",_INTL("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
end
@@ -348,7 +350,7 @@ def pbDebugMenuActions(cmd="",sprites=nil,viewport=nil)
params.setCancelValue(0)
level = pbMessageChooseNumber(_INTL("Set the wild {1}'s level.",PBSpecies.getName(species)),params)
if level>0
pkmn.push(pbNewPkmn(species,level))
pkmn.push(pbGenerateWildPokemon(species,level))
end
end
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))
if battle
trainerdata = battle[1]
pbTrainerBattle(trainerdata[0],trainerdata[1],"...",false,trainerdata[4],true)
pbTrainerBattle(trainerdata[0],trainerdata[1],nil,false,trainerdata[4],true)
end
when "testtrainerbattleadvanced"
trainers = []
@@ -795,6 +797,8 @@ def pbDebugMenuActions(cmd="",sprites=nil,viewport=nil)
pbDisposeMessageWindow(msgwindow)
when "debugconsole"
Console::setup_console
when "invalidtiles"
pbDebugFixInvalidTiles
end
return false
end

View File

@@ -82,9 +82,16 @@ class SpriteWindow_DebugVariables < Window_DrawableCommand
name = $data_system.switches[index+1]
codeswitch = (name[/^s\:/])
val = (codeswitch) ? (eval($~.post_match) rescue nil) : $game_switches[index+1]
if val==nil; status = "[-]"; colors = 0; codeswitch = true
elsif val; status = "[ON]"; colors = 2
else; status = "[OFF]"; colors = 1
if val==nil
status = "[-]"
colors = 0
codeswitch = true
elsif val
status = "[ON]"
colors = 2
else
status = "[OFF]"
colors = 1
end
else
name = $data_system.variables[index+1]
@@ -791,6 +798,76 @@ def pbImportAllAnimations
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
#===============================================================================

View File

@@ -669,13 +669,6 @@ def pbItemEditorNew(defaultname)
itemdata = pbLoadItemsData
# Get the first blank ID for the new item to use.
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
itemname = pbMessageFreeText(_INTL("Please enter the item's name."),
(defaultname) ? defaultname.gsub(/_+/," ") : "",false,30)

View File

@@ -550,7 +550,7 @@ def pbSaveTownMap
f.write("\r\n")
for i in 0...mapdata.length
map = mapdata[i]
return if !map
next if !map
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n",i))
rname = pbGetMessage(MessageTypes::RegionNames,i)
@@ -839,11 +839,14 @@ def pbSavePokemonData
pokedata.write(",") if count>0
pokedata.write(sprintf("%s,%s,",cnew_species,evoname))
param_type = PBEvolution.getFunction(method, "parameterType")
if param_type
cparameter = getConstantName(param_type,parameter) rescue ""
pokedata.write("#{cparameter}")
else
pokedata.write("#{parameter}")
has_param = !PBEvolution.hasFunction?(method, "parameterType") || param_type != nil
if has_param
if param_type
cparameter = (getConstantName(param_type, parameter) rescue parameter)
pokedata.write("#{cparameter}")
else
pokedata.write("#{parameter}")
end
end
count += 1
end
@@ -1299,11 +1302,14 @@ def pbSavePokemonFormsData
next if !cnew_species || cnew_species==""
pokedata.write(sprintf("%s,%s,",cnew_species,evoname))
param_type = PBEvolution.getFunction(method, "parameterType")
if param_type
cparameter = getConstantName(param_type,parameter) rescue ""
pokedata.write("#{cparameter}")
else
pokedata.write("#{parameter}")
has_param = !PBEvolution.hasFunction?(method, "parameterType") || param_type != nil
if has_param
if param_type
cparameter = (getConstantName(param_type, parameter) rescue parameter)
pokedata.write("#{cparameter}")
else
pokedata.write("#{parameter}")
end
end
pokedata.write(",") if k<evos.length-1
end

View File

@@ -407,6 +407,7 @@ class ItemLister
@itemdata = pbLoadItemsData
cmds = []
for i in 1..PBItems.maxValue
next if !@itemdata[i]
name = @itemdata[i][ITEM_NAME]
if name && name!="" && @itemdata[i][ITEM_POCKET]!=0
cmds.push([i,name])

View File

@@ -3093,8 +3093,8 @@ class PointPath
return ret
end
step=1.0/frames
t=0.0;
for i in 0..frames+1
t=0.0
(frames+2).times do
point=pointOnPath(t)
if roundValues
ret.addPoint(point[0].round,point[1].round)

View File

@@ -793,6 +793,7 @@ end
def pbGetConst(mod,item,err)
isDef = false
begin
mod = Object.const_get(mod) if mod.is_a?(Symbol)
isDef = mod.const_defined?(item.to_sym)
rescue
raise sprintf(err,item)
@@ -802,6 +803,7 @@ def pbGetConst(mod,item,err)
end
def getConstantName(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
return c if mod.const_get(c.to_sym)==value
end
@@ -809,6 +811,7 @@ def getConstantName(mod,value)
end
def getConstantNameOrValue(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
return c if mod.const_get(c.to_sym)==value
end
@@ -816,6 +819,7 @@ def getConstantNameOrValue(mod,value)
end
def setConstantName(mod,value,name)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
mod.send(:remove_const,c.to_sym) if mod.const_get(c.to_sym)==value
end
@@ -823,6 +827,7 @@ def setConstantName(mod,value,name)
end
def removeConstantValue(mod,value)
mod = Object.const_get(mod) if mod.is_a?(Symbol)
for c in mod.constants
mod.send(:remove_const,c.to_sym) if mod.const_get(c.to_sym)==value
end

View File

@@ -13,20 +13,22 @@ def pbCompileMetadata
sectionname = $~[1]
if currentmap==0
if sections[currentmap][MetadataHome]==nil
raise _INTL("The entry Home is required in metadata.txt section [{1}]",sectionname)
end
if sections[currentmap][MetadataPlayerA]==nil
raise _INTL("The entry PlayerA is required in metadata.txt section [{1}]",sectionname)
raise _INTL("The entry Home is required in metadata.txt section [{1}].",sectionname)
elsif sections[currentmap][MetadataPlayerA]==nil
raise _INTL("The entry PlayerA is required in metadata.txt section [{1}].",sectionname)
end
end
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] = []
else
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
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
matchData = $~
schema = nil
@@ -354,7 +356,7 @@ def pbCompileTypes
if currentmap>=0
for reqtype in requiredtypes.keys
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
foundtypes.clear
@@ -363,10 +365,10 @@ def pbCompileTypes
types[currentmap] = [currentmap,nil,nil,false,false,[],[],[]]
else
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
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
matchData = $~
schema = nil
@@ -401,17 +403,17 @@ def pbCompileTypes
n = type[1]
for w in type[5]
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
for w in type[6]
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
for w in type[7]
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
@@ -463,6 +465,9 @@ def pbCompileAbilities
maxValue = 0
pbCompilerEachPreppedLine("PBS/abilities.txt") { |line,lineno|
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]
movedescs[record[0]] = record[3]
maxValue = [maxValue,record[0]].max
@@ -545,6 +550,9 @@ def pbCompileItems
pbCompilerEachCommentedLine("PBS/items.txt") { |line,lineno|
linerecord = pbGetCsvRecord(line,lineno,[0,"vnssuusuuUN"])
id = linerecord[0]
if records[id]
raise _INTL("Item ID number '{1}' is used twice.\r\n{2}",id,FileLineData.linereport)
end
record = []
record[ITEM_ID] = id
constant = linerecord[1]
@@ -603,11 +611,14 @@ def pbCompileMoves
nil,nil,nil,nil,nil,PBTypes,["Physical","Special","Status"],
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
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
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
end
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
# the keys are the XXX and the values are the YYY (as unprocessed strings).
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.
speciesData[speciesID] = []
# 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
maxValue = [maxValue,speciesID].max # Set highest species ID
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
# property is empty.
if !contents[key] || contents[key]==""
@@ -854,7 +869,6 @@ def pbCompilePokemonData
end
# Add prevolution data to all species as the first "evolution method".
for sp in 1..maxValue
next if !evolutions[sp]
preSpecies = -1
evoData = nil
# Check for another species that evolves into sp.
@@ -870,6 +884,7 @@ def pbCompilePokemonData
end
next if !evoData # evoData[1]=method, evoData[2]=level - both are unused
# 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])
end
# Save evolutions data.
@@ -1162,6 +1177,9 @@ def pbCompileMachines
if !line[/^\#/] && !line[/^\s*$/]
if line[/^\s*\[\s*(.*)\s*\]\s*$/]
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
havesection = true
else
@@ -1261,13 +1279,16 @@ def pbCompileEncounters
mapid = line[/^\d+$/]
if 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] ||
thisenc[1][EncounterTypes::LandMorning] ||
thisenc[1][EncounterTypes::LandDay] ||
thisenc[1][EncounterTypes::LandNight] ||
thisenc[1][EncounterTypes::BugContest]) &&
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
thisenc = [EncounterTypes::EnctypeDensities.clone,[]]
encounters[mapid.to_i] = thisenc
@@ -1393,10 +1414,10 @@ def pbCompileTrainers
if line[/^\s*\[\s*(.+)\s*\]\s*$/]
# Section [trainertype,trainername] or [trainertype,trainername,partyid]
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
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
section = pbGetCsvRecord($~[1],lineno,[0,"esU",PBTrainers])
trainerindex += 1
@@ -1409,10 +1430,10 @@ def pbCompileTrainers
elsif line[/^\s*(\w+)\s*=\s*(.*)$/]
# XXX=YYY lines
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
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
settingname = $~[1]
schema = trainer_info_types[settingname]
@@ -1429,7 +1450,7 @@ def pbCompileTrainers
record.compact!
when "Ability"
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
when "IV"
record = [record] if record.is_a?(Integer)

View File

@@ -565,7 +565,7 @@ def pbConvertToTrainerEvent(event,trainerChecker)
end
pbPushScript(firstpage.list,"setBattleRule(\"double\")") if doublebattle
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
espeech = (endspeeches[0]) ? sprintf("_I(\"%s\")",safequote2(endspeeches[0])) : "nil"
if battleid>0
@@ -614,7 +614,7 @@ def pbConvertToTrainerEvent(event,trainerChecker)
pbPushText(rematchpage.list,battles[i],1)
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(\"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
espeech = nil
if endspeeches.length>0

View File

@@ -1,7 +1,5 @@
pbCompiler
class Scene_DebugIntro
def main
Graphics.transition(0)
@@ -12,8 +10,6 @@ class Scene_DebugIntro
end
end
def pbCallTitle
return Scene_DebugIntro.new if $DEBUG
# First parameter is an array of images in the Titles
@@ -34,9 +30,9 @@ end
def mainFunctionDebug
begin
getCurrentProcess = Win32API.new("kernel32.dll","GetCurrentProcess","","l")
setPriorityClass = Win32API.new("kernel32.dll","SetPriorityClass",%w(l i),"")
setPriorityClass.call(getCurrentProcess.call(),32768) # "Above normal" priority class
getCurrentProcess = Win32API.new("kernel32.dll", "GetCurrentProcess", "", "l")
setPriorityClass = Win32API.new("kernel32.dll", "SetPriorityClass", %w(l i), "")
setPriorityClass.call(getCurrentProcess.call(), 32768) # "Above normal" priority class
$data_animations = pbLoadRxData("Data/Animations")
$data_tilesets = pbLoadRxData("Data/Tilesets")
$data_common_events = pbLoadRxData("Data/CommonEvents")
@@ -46,9 +42,7 @@ def mainFunctionDebug
Graphics.update
Graphics.freeze
$scene = pbCallTitle
while $scene!=nil
$scene.main
end
$scene.main until $scene.nil?
Graphics.transition(20)
rescue Hangup
pbPrintException($!) if !$DEBUG
@@ -59,11 +53,11 @@ end
loop do
retval = mainFunction
if retval==0 # failed
if retval == 0 # failed
loop do
Graphics.update
end
elsif retval==1 # ended successfully
elsif retval == 1 # ended successfully
break
end
end

View File

@@ -815,7 +815,7 @@ Habitat = Forest
RegionalNumbers = 25,22
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.
WildItemuNCOMMON = LIGHTBALL
WildItemUncommon = LIGHTBALL
BattlerPlayerX = -5
BattlerPlayerY = 0
BattlerEnemyX = 4
@@ -9618,7 +9618,7 @@ BattlerEnemyX = -1
BattlerEnemyY = 29
BattlerShadowX = 0
BattlerShadowSize = 2
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,20
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,
#-------------------------------
[291]
Name = Ninjask

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."
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."
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."
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."
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."
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."
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."
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."
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."
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."
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."
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."
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,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,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,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,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,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,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,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,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,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."
#-------------------------------
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."
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."
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."
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."

View File

@@ -816,6 +816,7 @@ Habitat = Forest
RegionalNumbers = 25,22
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.
WildItemUncommon = LIGHTBALL
BattlerPlayerX = -5
BattlerPlayerY = 0
BattlerEnemyX = 4
@@ -9617,7 +9618,7 @@ BattlerEnemyX = -1
BattlerEnemyY = 29
BattlerShadowX = 0
BattlerShadowSize = 2
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,20
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,
#-------------------------------
[291]
Name = Ninjask

View File

@@ -150,7 +150,6 @@ Moves = 0,DAZZLINGGLEAM,1,DAZZLINGGLEAM,1,IMPRISON,1,NASTYPLOT,1,ICEBEAM,1,ICESH
Color = Blue
Pokedex = It lives on mountains perpetually covered in snow and is revered as a deity incarnate. It appears draped in a blizzard.
WildItemUncommon = SNOWBALL
Evolutions = NINETALES,Item,ICESTONE
#-------------------------------
[DIGLETT,1]
FormName = Alolan

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."
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."
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."
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."
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."
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."
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."
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."
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."
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."
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."
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."
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,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,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,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,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,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,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,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,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,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,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."
#-------------------------------
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."
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."
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."
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."

View File

@@ -816,6 +816,7 @@ Habitat = Forest
RegionalNumbers = 25,22
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.
WildItemUncommon = LIGHTBALL
BattlerPlayerX = -5
BattlerPlayerY = 0
BattlerEnemyX = 4
@@ -9617,7 +9618,7 @@ BattlerEnemyX = -1
BattlerEnemyY = 29
BattlerShadowX = 0
BattlerShadowSize = 2
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,20
Evolutions = NINJASK,Ninjask,20,SHEDINJA,Shedinja,
#-------------------------------
[291]
Name = Ninjask

View File

@@ -150,7 +150,6 @@ Moves = 0,DAZZLINGGLEAM,1,DAZZLINGGLEAM,1,IMPRISON,1,NASTYPLOT,1,ICEBEAM,1,ICESH
Color = Blue
Pokedex = It lives on mountains perpetually covered in snow and is revered as a deity incarnate. It appears draped in a blizzard.
WildItemUncommon = SNOWBALL
Evolutions = NINETALES,Item,ICESTONE
#-------------------------------
[DIGLETT,1]
FormName = Alolan