Release 6.9.0

This commit is contained in:
chardub
2026-11-02 11:34:46 -05:00
parent 060726298d
commit ae6e2ebc64
5697 changed files with 131795 additions and 17423 deletions
BIN
View File
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
.idea
LocalSettings.rb
+25 -20
View File
@@ -5,14 +5,15 @@
#==============================================================================#
module Settings
# The version of your game. It has to adhere to the MAJOR.MINOR.PATCH format.
GAME_VERSION_NUMBER = "6.8.3"
LATEST_GAME_RELEASE = "6.8"
GAME_VERSION_NUMBER = "6.9"
LATEST_GAME_RELEASE = "6.9.0"
HOENN_VERSION_NUMBER = "1.1.0"
HOENN_LATEST_GAME_RELEASE = "1.1.0"
HOENN_VERSION_NUMBER = "1.3"
HOENN_LATEST_GAME_RELEASE = "1.2.0"
SNOW_DAY = false
SNOW_DAY = true
EXPERIMENTAL_FEATURES = false
KANTO = GAME_ID == :IF_KANTO
HOENN = GAME_ID == :IF_HOENN
@@ -36,7 +37,7 @@ module Settings
ANIMATE_REFLECTIONS = false # GAME_ID == :IF_HOENN #true
USE_REFLECTIONS = false
# Infinite fusion settings
NB_POKEMON = 576
NB_POKEMON = 582
TRANSFER_BOX_DISCLAIMER_MESSAGE = ""
CUSTOM_BASE_SPRITES_FOLDER = "Graphics/CustomBattlers/local_sprites/BaseSprites/"
CUSTOM_BATTLERS_FOLDER = "Graphics/CustomBattlers/"
@@ -47,9 +48,13 @@ module Settings
DOWNLOADED_SPRITES_FOLDER = "Graphics/temp/"
DEFAULT_SPRITE_PATH = "Graphics/Battlers/Special/000.png"
CREDITS_FILE_PATH = "Data/sprites/Sprite_Credits.csv"
VERSION_FILE_PATH = "Data/VERSION"
CUSTOM_SPRITES_FILE_PATH = "Data/sprites/CUSTOM_SPRITES"
BASE_SPRITES_FILE_PATH = "Data/sprites/BASE_SPRITES"
REFERENCES_FILE_PATH = "Data/sprites/SELECTED_REFERENCES"
CUSTOM_DEX_ENTRIES_PATH = "Data/pokedex/dex.json"
AI_DEX_ENTRIES_PATH = "Data/pokedex/generated_entries.json"
POKEDEX_ENTRIES_PATH = "Data/pokedex/all_entries.json"
@@ -115,11 +120,6 @@ module Settings
WIKI_URL = "https://infinitefusion.fandom.com/"
FAQ_URL = "https://hackmd.io/@PIF-Staff/PIF-Hoenn-FAQ"
AI_ENTRIES_URL = "https://ai-entries.pkmninfinitefusion.workers.dev/"
AI_ENTRIES_RATE_MAX_NB_REQUESTS = 10 # Nb. requests allowed in each time window
AI_ENTRIES_RATE_TIME_WINDOW = 120 # In seconds
AI_ENTRIES_RATE_LOG_FILE = 'Data/pokedex/dex_rate_limit.log' # Path to the log file
CUSTOMSPRITES_RATE_MAX_NB_REQUESTS = 15 # Nb. requests allowed in each time window
CUSTOMSPRITES_ENTRIES_RATE_TIME_WINDOW = 120 # In seconds
CUSTOMSPRITES_RATE_LOG_FILE = 'Data/sprites/sprites_rate_limit.log' # Path to the log file
@@ -279,7 +279,7 @@ module Settings
#=============================================================================
# The number of steps allowed before a Safari Zone game is over (0=infinite).
SAFARI_STEPS = 600
SAFARI_STEPS = Settings::KANTO ? 600 : -1
# The number of seconds a Bug Catching Contest lasts for (0=infinite).
BUG_CONTEST_TIME = 20 * 60 # 20 minutes
@@ -312,7 +312,7 @@ module Settings
BADGE_FOR_FLY = 3
BADGE_FOR_STRENGTH = 5
BADGE_FOR_DIVE = 9
BADGE_FOR_WATERFALL = 9
BADGE_FOR_WATERFALL = 10
BADGE_FOR_TELEPORT = 1
BADGE_FOR_BOUNCE = 8
BADGE_FOR_ROCKCLIMB = 16
@@ -562,6 +562,8 @@ module Settings
ANGRY_ANIMATION_ID = 24
ANGRY_SHORT_ANIMATION_ID = 34
STEAM_ANIMATION = 38
FUSE_ANIMATION_ID = 33
# ID of the animation played when a patch of grass rustles due to using the
@@ -584,6 +586,7 @@ module Settings
CUT_TREE_ANIMATION_ID = 19
ROCK_SMASH_ANIMATION_ID = 20
ANIMATION_OW_ATTACK = 14
#=============================================================================
# An array of available languages in the game, and their corresponding message
@@ -591,15 +594,17 @@ module Settings
# from.
LANGUAGES = {
:IF_KANTO => [
["English", "english.dat"],
["Français", "french.dat"],
["中文", "chinese.dat"]
["English", "english.dat", :ENGLISH],
["Français", "french.dat", :FRENCH],
["Français (Québec)", "french.dat", :FRENCH_QC],
["中文", "chinese.dat", :CHINESE]
],
:IF_HOENN => [
["English", "english.dat"],
["Français", "french.dat"],
#["Español", "spanish.dat"],
["中文", "chinese.dat"]
["English", "english.dat", :ENGLISH],
["Français", "french.dat",:FRENCH],
["Français (Québec)", "french.dat", :FRENCH_QC],
#["Español", "spanish.dat", :SPANISH],
["中文", "chinese.dat", :CHINESE]
]
}
+17 -2
View File
@@ -2,7 +2,22 @@ module Encryption
ENCRYPTION_KEY = [0x4A, 0x8F, 0x2C, 0xE1, 0x73, 0xB5, 0x96, 0x0D,
0x5E, 0xA2, 0x3F, 0xC7, 0x81, 0x14, 0x6B, 0xD9]
CHUNK_SIZE = 1 << 20
def self.xor(data)
data.bytes.each_with_index.map { |b, i| b ^ ENCRYPTION_KEY[i % ENCRYPTION_KEY.length] }.pack("C*")
key = ENCRYPTION_KEY.pack("C*")
@full_chunk_key ||= (key * (CHUNK_SIZE / key.length)).unpack1("H*").to_i(16)
full_chunk_key = @full_chunk_key
result = String.new(capacity: data.bytesize, encoding: Encoding::BINARY)
offset = 0
while offset < data.bytesize
chunk = data.byteslice(offset, CHUNK_SIZE)
size = chunk.bytesize
chunk_key = size == CHUNK_SIZE ? full_chunk_key : (key * (size / key.length + 1)).byteslice(0, size).unpack1("H*").to_i(16)
xored = chunk.unpack1("H*").to_i(16) ^ chunk_key
result << [xored.to_s(16).rjust(size * 2, "0")].pack("H*")
offset += CHUNK_SIZE
end
return result
end
end
end
@@ -39,7 +39,7 @@ end
module Kernel
def echo(string)
return unless $DEBUG
printf(string.is_a?(String) ? string : string.inspect)
printf("%s", string.is_a?(String) ? string : string.inspect)
end
def echoln(string)
@@ -1,11 +1,20 @@
def pbAddScriptTexts(items, script)
script.force_encoding(Encoding::UTF_8)
script.scan(/(?:_I|sign)\s*\(\s*\"((?:[^\\\"]*\\\"?)*[^\"]*)\"/) do |s|
string = s[0]
string.gsub!(/\\\"/, "\"")
string.gsub!(/\\\\/, "\\")
items.push(string)
end
# extract pbTrainerBattle(..., "TrainerName", "LoseText", ...) in PIF1
script.scan(/pbTrainerBattle\s*\(\s*[^,]+,\s*"[^"]*"\s*,\s*"([^"]*)"/) do |s|
string = s[0]
string.gsub!(/\\\"/, "\"")
string.gsub!(/\\\\/, "\\")
items.push(string)
end
end
def pbAddRgssScriptTexts(items, script)
@@ -509,7 +518,6 @@ class Messages
end
def extract(outfile)
# return if !@messages
origMessages = Messages.new("Data/messages.dat")
File.open(outfile, "wb") { |f|
f.write(0xef.chr)
@@ -517,12 +525,18 @@ class Messages
f.write(0xbf.chr)
f.write("# To localize this text for a particular language, please\r\n")
f.write("# translate every second line of this file.\r\n")
if origMessages.messages[0]
for i in 0...origMessages.messages[0].length
msgs = origMessages.messages[0][i]
# Map messages use the newly collected messages in @messages.
# This includes text extracted from map events, such as
# pbTrainerBattle(..., "Trainer", "LoseText", ...).
if @messages && @messages[0]
for i in 0...@messages[0].length
msgs = @messages[0][i]
Messages.writeObject(f, msgs, "Map#{i}", origMessages)
end
end
# Keep the original behavior for non-map message sections.
for i in 1...origMessages.messages.length
msgs = origMessages.messages[i]
Messages.writeObject(f, msgs, i, origMessages)
@@ -534,7 +548,7 @@ class Messages
@messages = [] if !@messages
arr = []
for i in 0...array.length
arr[i] = (array[i]) ? array[i] : ""
arr[i] = (array[i] == "") ? nil : array[i]
end
@messages[type] = arr
end
@@ -543,7 +557,8 @@ class Messages
@messages = [] if !@messages
arr = (@messages[type]) ? @messages[type] : []
for i in 0...array.length
arr[i] = (array[i]) ? array[i] : (arr[i]) ? arr[i] : ""
arr[i] = array[i] if array[i]
arr[i] = nil if arr[i] == ""
end
@messages[type] = arr
end
@@ -751,6 +766,10 @@ module MessageTypes
@@messages.loadMessageFile(filename)
end
def self.loadFallbackMessageFile(filename)
@@messagesFallback.loadMessageFile(filename)
end
def self.get(type, id)
ret = @@messages.get(type, id)
if ret == ""
+11 -11
View File
@@ -8,18 +8,18 @@ module Input
AUX1 = L
AUX2 = R
unless defined?(update_KGC_ScreenCapture)
class << Input
alias update_KGC_ScreenCapture update
end
end
# unless defined?(update_KGC_ScreenCapture)
# class << Input
# alias update_KGC_ScreenCapture update
# end
# end
def self.update
update_KGC_ScreenCapture
if trigger?(Input::F8)
pbScreenCapture
end
end
# def self.update
# update_KGC_ScreenCapture
# if trigger?(Input::F8)
# pbScreenCapture
# end
# end
end
module Mouse
@@ -128,6 +128,7 @@ class SpriteAnimation
end
def effect?
return false unless @_animation_duration
return @_animation_duration > 0
end
@@ -126,6 +126,16 @@ module Game
pokemon.exp_when_fused_body=nil
pokemon.exp_gained_since_fused=nil
pokemon.level = 5
if pokemon.original_body
pokemon.original_body.level = 5
pokemon.original_body.exp_gained_with_player = 0
end
if pokemon.original_head
pokemon.original_head.level = 5
pokemon.original_head.exp_gained_with_player = 0
end
pokemon.pif_sprite =nil
pokemon.owner.id = $Trainer.id
@@ -145,10 +145,15 @@ class Scene_Map
$game_temp.in_menu = true
$game_player.straighten
$game_map.update
if $PokemonTemp.overworld_safari
caught_pokemon_icons = displayCaughtPokemonIcons
end
sscene = PokemonPauseMenu_Scene.new
sscreen = PokemonPauseMenu.new(sscene)
sscreen.pbStartPokemonMenu
$game_temp.in_menu = false
caught_pokemon_icons.dispose if $PokemonTemp.overworld_safari
end
def call_debug
@@ -415,6 +415,7 @@ class Interpreter
end
def pbPushThisBoulder
pbSEPlay("strength")
pbPushThisEvent if $PokemonMap.strengthUsed
return true
end
@@ -523,6 +523,14 @@ class Game_Map
end
end
def set_tile(x, y, layer, id = 0)
self.data[x, y, layer] = id
end
def erase_tile(x, y, layer)
set_tile(x, y, layer, 0)
end
def refresh
for event in @events.values
event.refresh
@@ -202,10 +202,10 @@ class PokemonMapFactory
return true if thisEvent.through
if thisEvent==$game_player
if !($DEBUG && Input.press?(Input::CTRL))
return false if !map.passableStrict?(x,y,0,thisEvent)
return false if !map.playerPassable?(x,y,0,thisEvent)
end
else
return false if !map.passableStrict?(x,y,0,thisEvent)
return false if !map.playerPassable?(x,y,0,thisEvent)
end
for event in map.events.values
next if event == thisEvent || !event.at_coordinate?(x, y)
@@ -23,6 +23,8 @@ class Game_Character
attr_accessor :animation_id
attr_accessor :transparent
attr_reader :move_speed
attr_accessor :move_speed_override
attr_accessor :walk_anime
attr_writer :bob_height
attr_accessor :under_everything # under even grass
@@ -34,6 +36,8 @@ class Game_Character
attr_accessor :shadow_offset
attr_accessor :animation_speed
attr_accessor :step_anime
attr_accessor :can_hop_cliff
def initialize(map = nil)
@map = map
@id = 0
@@ -89,6 +93,8 @@ class Game_Character
@forced_bush_depth = nil
@shadow_offset =0
@animation_speed = nil #override if the animation speed needs to be different from move speed
@move_speed_override = nil
@can_hop_cliff = false
end
def at_coordinate?(check_x, check_y)
@@ -242,7 +248,7 @@ class Game_Character
this_map = (self.map.valid?(@x, @y)) ? [self.map, @x, @y] : $MapFactory.getNewMap(@x, @y)
if this_map[0].deepBush?(this_map[1], this_map[2]) && self.map.deepBush?(xbehind, ybehind)
@bush_depth = Game_Map::TILE_HEIGHT
elsif !moving? && this_map[0].bush?(this_map[1], this_map[2])
elsif this_map[0].bush?(this_map[1], this_map[2])
@bush_depth = 12
else
@bush_depth = 0
@@ -690,6 +696,10 @@ class Game_Character
@x += (dir == 4) ? -1 : (dir == 6) ? 1 : 0
@y += (dir == 8) ? -1 : (dir == 2) ? 1 : 0
increase_steps
elsif @can_hop_cliff && (pbFacingTerrainTag.is_cliff || terrain_tag.is_cliff)
@through = true
jump_forward(1)
@through = false
else
check_event_trigger_touch(dir)
end
@@ -1286,9 +1296,21 @@ class Game_Character
@stopped_this_frame = false
end
def play_step_animation(nb_times)
return if @lock_pattern
return if @step_anime_once
@step_anime_once = true
@step_animation_nb_times = nb_times
@step_animation_current_time = 0
@step_anime_once_frame_count = 0
@old_step_anime = @step_anime
@step_anime = true
@pattern = 0
@anime_count = 0
end
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
@@ -1301,21 +1323,33 @@ class Game_Character
@anime_count = 0
return
end
# 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.
# Calculate how many frames each pattern should display for
real_speed = (jumping?) ? jump_speed_real : move_speed_real
if @animation_speed
base = Game_Map::REAL_RES_X / 2.0
frames_per_pattern = base / @animation_speed
else
frames_per_pattern = Game_Map::REAL_RES_X / (real_speed * 2.0)
frames_per_pattern *= 2 if move_speed >= 5 # Cycling speed or faster
frames_per_pattern *= 2 if move_speed >= 5
end
return if @anime_count < frames_per_pattern
# Advance to the next animation frame
@pattern = (@pattern + 1) % 4
@anime_count -= frames_per_pattern
advance_step_animation_once if @step_anime_once
end
def advance_step_animation_once
@step_anime_once_frame_count += 1
total_frames = @step_animation_nb_times * 4
if @step_anime_once_frame_count % 4 == 0
@pattern = 0 #loop
end
return if @step_anime_once_frame_count < total_frames
@pattern = 0
@step_anime = @old_step_anime
@step_anime_once = false
end
# def distance_from_player
@@ -1330,6 +1364,13 @@ class Game_Character
return (dx + dy) - 1
end
def distance_from_target(target)
return Float::INFINITY if self.map_id != $game_map.map_id
dx = (@x - target.x).abs
dy = (@y - target.y).abs
return (dx + dy) - 1
end
def move_diagonal_freeform(distance_horizontal, distance_vertical, speed)
real_dx = distance_horizontal * Game_Map::REAL_RES_X
real_dy = distance_vertical * Game_Map::REAL_RES_Y
@@ -10,6 +10,8 @@ class Game_Event < Game_Character
attr_reader :page
attr_reader :on_bridge
attr_accessor :refresh_hue
attr_accessor :is_rival_following
attr_accessor :forced_bush_depth
def initialize(map_id, event, map=nil)
super(map)
@@ -38,6 +40,9 @@ class Game_Event < Game_Character
if @event.name[/forced_z\s*=\s*(-?\d+)/i]
@forced_z = $1.to_i
end
if @event.name.include?("under_player")
@under_player = true
end
if @event.name.include?("on_bridge")
@on_bridge = true
end
@@ -45,6 +50,11 @@ class Game_Event < Game_Character
refresh
end
# def forced_bush_depth=(value)
# @bush_depth = value
# update
# end
def through
return true if @on_bridge && $PokemonGlobal.bridge <= 0
return @through
@@ -65,11 +75,23 @@ class Game_Event < Game_Character
@starting = true if @list.size > 1
end
def name=(value)
@event.name = value
end
def erase
@erased = true
refresh
end
def despawn #Should only ever be called on dynamically created events
erase
$game_map.events.delete(@id)
$PokemonTemp.tempEvents&.each { |_, events| events.delete(self) }
$PokemonTemp.tempEvents&.delete_if { |_, v| v.empty? }
end
def erase_route
@route_erased = true
refresh
@@ -236,6 +258,9 @@ class Game_Event < Game_Character
@interpreter = nil
return
end
if @forced_bush_depth && @page&.graphic&.character_name == "shadow_event" #hardcoded hack for ninjakids that hide in the water...
@forced_bush_depth = false
end
@tile_id = @page.graphic.tile_id
@character_name = @page.graphic.character_name
@character_hue = @page.graphic.character_hue if @refresh_hue
@@ -315,4 +340,8 @@ class Game_Event < Game_Character
end
def is_on_water
return self.terrain_tag.can_surf
end
end
@@ -74,6 +74,8 @@ class Game_Player < Game_Character
if $game_player.pbTerrainTag.ice
reset_bike_speed
self.move_speed = 4
elsif $game_player.move_speed_override
self.move_speed = $game_player.move_speed_override
elsif !@move_route_forcing && $PokemonGlobal
if $PokemonGlobal.bicycle
self.move_speed = current_bicycle_speed
@@ -74,9 +74,7 @@ def moveFancy(follower,direction)
newY = follower.y + deltaY
# Move if new position is the player's, or the new position is passable,
# or the current position is not passable
if ($game_player.x==newX && $game_player.y==newY) ||
pbTestPass(follower,newX,newY,0) ||
!pbTestPass(follower,follower.x,follower.y,0)
if can_move_to_new_position(newX,newY,follower)
oldThrough=follower.through
follower.through=true
case direction
@@ -89,6 +87,13 @@ def moveFancy(follower,direction)
end
end
def can_move_to_new_position(newX,newY, follower)
return true if ($game_player.x==newX && $game_player.y==newY)
return true if pbTestPass(follower,newX,newY,0)
return true unless !pbTestPass(follower,follower.x,follower.y,0)
return false
end
# Same map only
def jumpFancy(follower,direction,leader)
deltaX=(direction == 6 ? 2 : (direction == 4 ? -2 : 0))
@@ -44,12 +44,11 @@ class BushBitmap
ret = Bitmap.new(bitmap.width, bitmap.height)
charheight = ret.height
cy = charheight - depth - 2
y = charheight
if cy >= 0
ret.blt(0, y, bitmap, Rect.new(0, y, ret.width, cy))
ret.blt(0, y + cy, bitmap, Rect.new(0, y + cy, ret.width, 2), 170)
ret.blt(0, 0, bitmap, Rect.new(0, 0, ret.width, cy))
ret.blt(0, cy, bitmap, Rect.new(0, cy, ret.width, 2), 170)
end
ret.blt(0, y + cy + 2, bitmap, Rect.new(0, y + cy + 2, ret.width, 2), 85) if cy + 2 >= 0
ret.blt(0, cy + 2, bitmap, Rect.new(0, cy + 2, ret.width, 2), 85) if cy + 2 >= 0
return ret
end
end
@@ -263,7 +262,8 @@ class Sprite_Character < RPG::Sprite
self.bitmap = (@charbitmapAnimated) ? @charbitmap.bitmap : @charbitmap
end
else
@bushbitmap = BushBitmap.new(@charbitmap, (@tile_id >= 384), bushdepth) if !@bushbitmap
source = (@character == $game_player) ? getClothedPlayerSprite() : (@charbitmapAnimated ? @charbitmap.bitmap : @charbitmap)
@bushbitmap = BushBitmap.new(source, (@tile_id >= 384), bushdepth) if !@bushbitmap
self.bitmap = @bushbitmap.bitmap
end
self.visible = !@character.transparent
@@ -25,7 +25,7 @@ class Particle_Engine
"flare" => Particle_Engine::Flare,
"splash" => Particle_Engine::Splash,
# By Peter O.
"starteleport" => Particle_Engine::StarTeleport
"starteleport" => Particle_Engine::StarTeleport,
}
end
@@ -373,14 +373,12 @@ end
class Particle_Engine::Smoke < ParticleEffect_Event
def initialize(event, viewport)
super
setParameters([0, 0, 0, 80, 20, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -15, 5, 80])
initParticles("smoke", 250)
setParameters([0, 0, 0, 30, 20, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.05, -5, -15, 5, 80])
initParticles("smoke", 100)
end
end
class Particle_Engine::Teleport < ParticleEffect_Event
def initialize(event, viewport)
super
@@ -201,6 +201,36 @@ class TilemapRenderer
}
}
#path: 276 -
EMPTY_TILE = 0
GROUND_SNOW_TILE = 418
TILESET_SUPPORTING_SNOW_TREES = [1,2,5,7,8,9,12,13,15,34]
SNOW_SUBSTITUTIONS = {
#Trees
864 =>868, 865=>869,
872=>876, 873=>877,
880=>884, 881=>885,
866=>870, 867=>871,
874=>878, 875=>879,
#Grass
424=> GROUND_SNOW_TILE, 425 => GROUND_SNOW_TILE,426=> GROUND_SNOW_TILE,427=> GROUND_SNOW_TILE,
432=> GROUND_SNOW_TILE,433=> GROUND_SNOW_TILE,434=> GROUND_SNOW_TILE,435=> GROUND_SNOW_TILE,
440=> GROUND_SNOW_TILE,441=> GROUND_SNOW_TILE,442=> GROUND_SNOW_TILE,443=> GROUND_SNOW_TILE,
448=> GROUND_SNOW_TILE,449=> GROUND_SNOW_TILE,450=> GROUND_SNOW_TILE,451=>GROUND_SNOW_TILE,
# grass details, flowers,
1009=>GROUND_SNOW_TILE, 1010=>GROUND_SNOW_TILE,
992=>GROUND_SNOW_TILE, 993=>GROUND_SNOW_TILE,
#Ledges
1352=>1357,1353=>1358,1354=>1359,1355=>1350,1356=>1351,
1360=>1365, 1361=>1366,1362=>1367,
1368 =>1373, 1369=>1374, 1370=>1375,
}
# SNOW_TREES_TILES = [864,865,872,873,880,881,
# 866,867,874,875]
WIND_TREE_AUTOTILES = {
1 => { # Route-field
864 => "tree_sway_single_1",
@@ -327,6 +357,20 @@ class TilemapRenderer
875 => "tree_sway_group_4",
},
36 => { # Route-tropical
832 => "tree_sway_tropical_single_1",
833 => "tree_sway_tropical_single_2",
840 => "tree_sway_tropical_single_3",
841 => "tree_sway_tropical_single_4",
848 => "tree_sway_tropical_single_5",
889 => "tree_sway_tropical_single_6",
834 => "tree_sway_tropical_group_1",
835 => "tree_sway_tropical_group_2",
842 => "tree_sway_tropical_group_3",
843 => "tree_sway_tropical_group_4",
},
}
#=============================================================================
@@ -694,9 +738,28 @@ class TilemapRenderer
end
INVISIBLE_WALL_TILE_ID = 384
def get_snow_tile_id(tile_id, current_tileset)
return tile_id unless Settings::HOENN
return tile_id unless TILESET_SUPPORTING_SNOW_TREES.include?(current_tileset)
return tile_id unless Settings::SNOW_DAY
return tile_id unless SNOW_SUBSTITUTIONS.include?(tile_id)
return SNOW_SUBSTITUTIONS[tile_id]
end
def check_hoenn_safari_flowers(tile_id)
replacement_tile = EMPTY_TILE
safari_flower_tiles = [987,998]
return tile_id unless Settings::HOENN
return tile_id unless HOENN_SAFARI_MAPS.include?(@current_map_id)
return tile_id if $game_switches[SWITCH_SAFARI_FLOWERS_PLANTED]
return tile_id unless safari_flower_tiles.include?(tile_id)
echoln "deleting flowers!"
return replacement_tile
end
def refresh_tile_bitmap(tile, map, tile_id)
tile.tile_id = tile_id
original_id = tile_id
if tile_id < TILES_PER_AUTOTILE || (Settings::HOENN && tile_id == INVISIBLE_WALL_TILE_ID)
tile.set_bitmap("", tile_id, false, false, 0, nil)
tile.shows_reflection = false
@@ -716,7 +779,6 @@ class TilemapRenderer
# true_tileset_start_id += single_autotile_count
# end
filename = nil
extra_autotile_hash = get_autotile_overrides(map.tileset_id, map.map_id)
if extra_autotile_hash && extra_autotile_hash[tile_id]
@@ -740,6 +802,15 @@ class TilemapRenderer
filename = map.tileset_name
tile.set_bitmap(filename, tile_id, false, false, priority, @tilesets[filename])
end
tile_id = get_snow_tile_id(tile_id,map.tileset_id) #returns the original tile if no snow
tile_id = check_hoenn_safari_flowers(tile_id) #Removes flowers in safari if not unlocked all zones
if tile_id == EMPTY_TILE
tile.set_bitmap("", original_id, false, false, 0, nil)
tile.shows_reflection = false
tile.underwater_tile = false
tile.bridge = false
return
end
tile.shows_reflection = terrain_tag_data&.shows_reflections
tile.underwater_tile = terrain_tag_data&.underwater
@@ -431,7 +431,7 @@ end
def pbDisplayCosmeticsMoneyWindow(msgwindow,x=nil,y=nil)
moneyString = pbGetCosmeticsMoneyString()
goldwindow = Window_AdvancedTextPokemon.new(_INTL("{2}:\n<ar>{1}</ar>", moneyString,COSMETIC_CURRENCY_NAME))
goldwindow = Window_AdvancedTextPokemon.new(_INTL("{2}:\n<ar>{1}</ar>", moneyString, get_cosmetic_currency_name))
goldwindow.setSkin("Graphics/Windowskins/goldskin")
goldwindow.resizeToFit(goldwindow.text, Graphics.width)
goldwindow.width = 160 if goldwindow.width <= 160
@@ -648,6 +648,16 @@ def pbMessageDisplay(msgwindow, message, letterbyletter = true, commandProc = ni
text.gsub!(/\\pog/i, "")
text.gsub!(/\\b/i, "<c3=3050C8,D0D0C8>")
text.gsub!(/\\r/i, "<c3=E00808,D0D0C8>")
text.gsub!("<-","←")
text.gsub!("->","→")
text.gsub!("<arr_left>","←")
text.gsub!("<arr_right>","→")
text.gsub!("<arr_down>","↓")
text.gsub!("<arr_up>","↑")
text.gsub!("<arr_down>","↓")
text.gsub!(/\\mu\[(.*?)\]/i) do
$Trainer && isPlayerMale() ? $1 : ""
end
@@ -948,6 +958,7 @@ def pbMessage(message, commands = nil, cmdIfCancel = 0, skin = nil, defaultCmd =
end
def pbMessageNoSound(message, commands = nil, cmdIfCancel = 0, skin = nil, defaultCmd = 0, &block)
echoln message
ret = 0
msgwindow = pbCreateMessageWindow(nil, skin)
if commands
@@ -264,6 +264,15 @@ GameData::Evolution.register({
}
})
GameData::Evolution.register({
:id => :ReversersLevel,
:parameter => Integer,
:level_up_proc => proc { |pkmn, parameter|
next pkmn.level >= parameter #TODO
}
})
GameData::Evolution.register({
:id => :Happiness,
:minimum_level => 1, # Needs any level up
@@ -22,6 +22,7 @@ module GameData
attr_reader :ignore_passability
attr_reader :acroBike
attr_reader :show_footprints
# oricorio
@@ -43,6 +44,15 @@ module GameData
attr_reader :secretBase_tree
attr_reader :secretBase_cave
attr_reader :secretBase_bush
attr_reader :step_sound
attr_reader :ambient_sound
attr_reader :ambient_sound_priority
attr_reader :shifting_tile_horizontal
attr_reader :shifting_tile_vertical
attr_reader :is_cliff
DATA = {}
@@ -86,6 +96,8 @@ module GameData
@ignore_passability = hash[:ignore_passability] || false
@ignore_passability = hash[:ignore_passability] || false
@show_footprints = hash[:show_footprints] || false
@flowerRed = hash[:flowerRed] || false
@flowerYellow = hash[:flowerYellow] || false
@flowerPink = hash[:flowerPink] || false
@@ -102,6 +114,13 @@ module GameData
@secretBase_tree = hash[:secretBase_tree] || false
@secretBase_cave = hash[:secretBase_cave] || false
@secretBase_bush = hash[:secretBase_bush] || false
@shifting_tile_horizontal = hash[:shifting_tile_horizontal] || false
@shifting_tile_vertical = hash[:shifting_tile_vertical] || false
@step_sound = hash[:step_sound]
@ambient_sound = hash[:ambient_sound]
@ambient_sound_priority = hash[:ambient_sound_priority]
@is_cliff = hash[:is_cliff]
end
@@ -126,7 +145,8 @@ GameData::TerrainTag.register({
GameData::TerrainTag.register({
:id => :Ledge,
:id_number => 1,
:ledge => true
:ledge => true,
:is_cliff => true
})
GameData::TerrainTag.register({
@@ -134,19 +154,21 @@ GameData::TerrainTag.register({
:id_number => 2,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass
:battle_environment => :Grass,
:step_sound => "steps/step_tall_grass"
})
GameData::TerrainTag.register({
:id => :Sand,
:id_number => 3,
:battle_environment => :Sand
:battle_environment => :Sand,
:show_footprints => true,
})
GameData::TerrainTag.register({
:id => :Rock,
:id_number => 15,
:battle_environment => :Rock
:battle_environment => :Rock,
})
GameData::TerrainTag.register({
@@ -179,7 +201,9 @@ GameData::TerrainTag.register({
:id => :Waterfall,
:id_number => 8,
:can_surf => true,
:waterfall => true
:waterfall => true,
:ambient_sound => "ambient/waterfall",
:ambient_sound_priority => 80
})
GameData::TerrainTag.register({
@@ -187,7 +211,9 @@ GameData::TerrainTag.register({
:id_number => 9,
:can_surf => true,
:can_fish => true,
:waterfall_crest => true
:waterfall_crest => true,
:ambient_sound => "ambient/waterfall",
:ambient_sound_priority => 80
})
GameData::TerrainTag.register({
@@ -195,16 +221,17 @@ GameData::TerrainTag.register({
:id_number => 10,
:deep_bush => true,
:land_wild_encounters => true,
:double_wild_encounters => true,
:battle_environment => :TallGrass,
:must_walk => true
:must_walk => true,
:step_sound => "steps/step_tall_grass",
})
GameData::TerrainTag.register({
:id => :UnderwaterGrass,
:id_number => 11,
:underwater => true,
:land_wild_encounters => true
:land_wild_encounters => true,
:step_sound => "steps/step_tall_grass"
})
GameData::TerrainTag.register({
@@ -228,7 +255,8 @@ GameData::TerrainTag.register({
:id_number => 14,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass
:battle_environment => :Grass,
:step_sound => "steps/step_tall_grass"
})
GameData::TerrainTag.register({
@@ -241,7 +269,8 @@ GameData::TerrainTag.register({
:id => :Puddle,
:id_number => 16,
:battle_environment => :Puddle,
:shows_reflections => false
:land_wild_encounters => true,
:shows_reflections => true
})
GameData::TerrainTag.register({
@@ -286,27 +315,30 @@ GameData::TerrainTag.register({
})
GameData::TerrainTag.register({
:id => :Grass_alt1,
:id => :Grass_alt1, #CLOVERS
:id_number => 24,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass
:battle_environment => :Grass,
:step_sound => "steps/step_tall_grass"
})
GameData::TerrainTag.register({
:id => :Grass_alt2,
:id => :Grass_alt2, #DRY GRASS
:id_number => 25,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass
:battle_environment => :Grass,
:step_sound => "steps/step_tall_grass"
})
GameData::TerrainTag.register({
:id => :Grass_alt3,
:id => :Grass_alt3, #FLOWERS
:id_number => 26,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass
:battle_environment => :Grass,
:step_sound => "steps/step_tall_grass"
})
GameData::TerrainTag.register({
@@ -359,4 +391,108 @@ GameData::TerrainTag.register({
:id => :AcroBike,
:id_number => 34,
:acroBike => true,
})
GameData::TerrainTag.register({
:id => :CutGrass,
:id_number => 35,
})
GameData::TerrainTag.register({
:id => :TallGrassTop,
:id_number => 36,
:step_sound => "steps/step_tall_grass",
})
GameData::TerrainTag.register({
:id => :TallGrassMiddle,
:id_number => 37,
:deep_bush => true,
:land_wild_encounters => true,
:double_wild_encounters => true,
:battle_environment => :TallGrass,
:must_walk => true,
:step_sound => "steps/step_tall_grass",
})
GameData::TerrainTag.register({
:id => :DeepSand,
:id_number => 38,
:battle_environment => :Sand,
:land_wild_encounters => true,
:must_walk => true,
:show_footprints => true,
:can_fish => true,
})
GameData::TerrainTag.register({
:id => :SuspendedBridgeVertical,
:id_number => 39,
:shifting_tile_vertical => true,
:step_sound => "steps/wooden_bridge",
:bridge => true
})
GameData::TerrainTag.register({
:id => :SuspendedBridgeHHorizontal,
:id_number => 40,
:shifting_tile_horizontal => true,
:step_sound => "steps/wooden_bridge",
:bridge => true
})
GameData::TerrainTag.register({
:id => :Beach,
:id_number => 41,
:battle_environment => :Sand,
:show_footprints => true,
:ambient_sound => "ambient/ocean",
:ambient_sound_priority => 50,
})
GameData::TerrainTag.register({ #Like normal water, but with a river flowing sound effect
:id => :RiverWater,
:id_number => 42,
:can_surf => true,
:can_fish => true,
:battle_environment => :MovingWater,
:ambient_sound => "ambient/river",
:ambient_sound_priority => 50
})
GameData::TerrainTag.register({
:id => :Lava,
:id_number => 43,
:battle_environment => :Volcano,
:ambient_sound => "ambient/lava",
:ambient_sound_priority => 30,
:can_fish => true,
})
GameData::TerrainTag.register({
:id => :Snow,
:id_number => 44,
:battle_environment => :Snow,
:show_footprints => true,
})
GameData::TerrainTag.register({
:id => :Cliff,
:id_number => 45,
:is_cliff => true,
:battle_environment => :Rock,
})
GameData::TerrainTag.register({
:id => :Mud,
:id_number => 46,
:step_sound => "steps/step_mud",
:show_footprints => true,
})
GameData::TerrainTag.register({
:id => :Grass_alt4, #Additional grass type for maps that need something else aside from grass, clovers, dry grass and flowers
:id_number => 47,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass,
:step_sound => "steps/step_tall_grass"
})
@@ -128,8 +128,8 @@ GameData::Weather.register({
:graphics => [["sandstorm_1", "sandstorm_2", "sandstorm_3", "sandstorm_4"], ["sandstorm_tile"]],
:particle_delta_x => -1200,
:particle_delta_y => 640,
:tile_delta_x => -720,
:tile_delta_y => 360,
:tile_delta_x => -800,
:tile_delta_y => 400,
:tone_proc => proc { |strength|
next Tone.new(strength / 2, 0, -strength / 2, 0)
}
@@ -199,9 +199,11 @@ GameData::Weather.register({
:graphics => [["ash_1", "ash_2", "ash_3"]],
:particle_delta_x => 20,
:particle_delta_y => 100,
:tone_proc => proc { |strength|
next Tone.new(strength / 2, strength / 2, strength / 2, 0)
}
:tone_proc => proc { |strength| next Tone.new(0, 0, 0, 0) }
# :tone_proc => proc { |strength|
# # next Tone.new(strength / 2, strength / 2, strength / 2, 0)
# next Tone.new(0, 0, 0, 0)
# }
})
GameData::Weather.register({ #Used underwater
@@ -209,8 +211,20 @@ GameData::Weather.register({ #Used underwater
:id_number => 13,
:graphics => [["bubble_1", "bubble_2", "bubble_3"]],
:particle_delta_x => 20,
:particle_delta_y => 40,
:particle_delta_y => -40,
:tone_proc => proc { |strength|
next Tone.new(strength / 2, strength / 2, strength / 2, 0)
}
})
})
GameData::Weather.register({
:id => :Crumble,
:id_number => 14,
:category => :Crumble,
:graphics => [[], ["crumble_tile"]],
:tile_delta_x => 0,
:tile_delta_y => 300,
:tone_proc => proc { |strength|
next Tone.new(strength / 2, 0, -strength / 2, 0)
}
})
@@ -55,6 +55,19 @@ GameData::EncounterType.register({
:old_slots => [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
})
GameData::EncounterType.register({
:id => :Land4,
:type => :land,
:trigger_chance => 10,
:old_slots => [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
})
GameData::EncounterType.register({
:id => :Puddle,
:type => :land,
:trigger_chance => 5,
:old_slots => [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
})
GameData::EncounterType.register({
:id => :LandDay,
@@ -96,7 +96,8 @@ GameData::Environment.register({
GameData::Environment.register({
:id => :Snow,
:name => _INTL("Snow")
:name => _INTL("Snow"),
:battle_base => "snow"
})
GameData::Environment.register({
@@ -192,6 +192,9 @@ module GameData
end
# @return [String] the translated name of this species
def name
if getCurrentLanguage == :FRENCH_QC
return @real_name
end
ret = MessageTypes.get(MessageTypes::Species, @id_number)
return (ret && !ret.empty?) ? ret : @real_name
end
@@ -212,7 +212,6 @@ module GameData
end
def generateRandomGymSpecies(old_species)
echoln "GENERATING GYM SPECIES"
gym_index = pbGet(VAR_CURRENT_GYM_TYPE)
return old_species if gym_index == -1
return generateRandomChampionSpecies(old_species) if gym_index == 999
@@ -222,10 +221,12 @@ module GameData
customsList = getCustomSpeciesList()
bst_range = pbGet(VAR_RANDOMIZER_TRAINER_BST)
gym_type = GameData::Type.get(type_id)
echoln "type: #{gym_type.id}"
#echoln "type: #{gym_type.id}"
same_egg_group = $game_switches[SWITCH_RANDOM_GYM_EGG_GROUP]
while true
new_species = $game_switches[SWITCH_RANDOM_GYM_CUSTOMS] ? getSpecies(getNewCustomSpecies(old_species, customsList, bst_range)) : getSpecies(getNewSpecies(old_species, bst_range))
new_species = $game_switches[SWITCH_RANDOM_GYM_CUSTOMS] ? getSpecies(getNewCustomSpecies(old_species, customsList, bst_range, false, true, same_egg_group)) : getSpecies(getNewSpecies(old_species, bst_range, false, PBSpecies.maxValue, true, same_egg_group))
#echoln "#{old_species} - #{new_species.name}> "
return new_species if $game_switches[SWITCH_LEGENDARY_MODE] # new_species = $game_switches[SWITCH_RANDOM_GYM_CUSTOMS] ? getSpecies(getNewCustomSpecies(old_species, customsList, bst_range)) : getSpecies(getNewSpecies(old_species, bst_range))
if new_species.hasType?(gym_type)
return new_species
@@ -301,7 +301,7 @@ class PokeBattle_Battler
end
def pbWeight
ret = (@pokemon) ? @pokemon.weight : 500
ret = (@pokemon) ? @pokemon.species_data.weight : 500
ret += @effects[PBEffects::WeightChange]
ret = 1 if ret < 1
if abilityActive? && !@battle.moldBreaker
@@ -297,6 +297,7 @@ class PokeBattle_Battler
@spatk = @pokemon.spatk
@spdef = @pokemon.spdef
@speed = @pokemon.speed
@attack, @defense = @defense, @attack if @effects[PBEffects::PowerTrick]
if fullChange
@type1 = @pokemon.type1
@type2 = @pokemon.type2
@@ -136,6 +136,11 @@ class PokeBattle_Battler
end
@effects[PBEffects::BurnUp] = false
@effects[PBEffects::Roost] = false
if pbOwnedByPlayer?
@battle.scene.pbRefreshOne(@index) if $PokemonSystem.type_icons_player
else
@battle.scene.pbRefreshOne(@index) if $PokemonSystem.type_icons_opponent
end
end
#=============================================================================
@@ -171,6 +171,7 @@ class PokeBattle_Battler
pbBeginTurn(choice)
# Force the use of certain moves if they're already being used
if usingMultiTurnAttack?
echoln @currentMove
choice[2] = PokeBattle_Move.from_pokemon_move(@battle, Pokemon::Move.new(@currentMove))
specialUsage = true
elsif @effects[PBEffects::Encore] > 0 && choice[1] >= 0 &&
@@ -277,6 +277,14 @@ end
# Confuses the target.
#===============================================================================
class PokeBattle_Move_013 < PokeBattle_ConfuseMove
def pbOnStartUse(user,target)
if user.pokemon.chatter_text
pbCallBubOverBattler(user)
pbMessage(user.pokemon.chatter_text + "!\\wtnp[15]")
end
super(user,target)
end
end
#===============================================================================
@@ -1753,7 +1761,7 @@ class PokeBattle_Move_060 < PokeBattle_Move
end
if !checkedTerrain
case @battle.environment
when :Grass, :TallGrass, :Grass_alt1,:Grass_alt2,:Grass_alt3,
when :Grass, :TallGrass, :Grass_alt1,:Grass_alt2,:Grass_alt3,:Grass_alt4
@newType = :GRASS
when :MovingWater, :StillWater, :Puddle, :Underwater
@newType = :WATER
@@ -2498,8 +2498,14 @@ class PokeBattle_Move_0D6 < PokeBattle_HealingMove
return (user.totalhp/2.0).round
end
def pbEffectAfterAllHits(user,target)
def pbEffectGeneral(user)
user.effects[PBEffects::Roost] = true
if user.pbOwnedByPlayer?
@battle.scene.pbRefreshOne(user.index) if $PokemonSystem.type_icons_player
else
@battle.scene.pbRefreshOne(user.index) if $PokemonSystem.type_icons_opponent
end
super(user)
end
end
@@ -3223,8 +3229,7 @@ class PokeBattle_Move_0F1 < PokeBattle_Move
itemName = target.itemName
user.item = target.item
# Permanently steal the item from wild Pokémon
# removed target.item == target.initialItem, this may cause bugs.
if @battle.wildBattle? && target.opposes? && !user.initialItem
if @battle.wildBattle? && target.opposes? && !user.initialItem && target.item&.id == target.initialItem
user.setInitialItem(target.item)
end
target.pbRemoveItem(false)
@@ -3284,8 +3289,7 @@ class PokeBattle_Move_0F2 < PokeBattle_Move
target.effects[PBEffects::ChoiceBand] = nil
target.effects[PBEffects::Unburden] = (!target.item && oldTargetItem)
# Permanently steal the item from wild Pokémon
if @battle.wildBattle? && target.opposes? &&
target.initialItem==oldTargetItem && !user.initialItem
if @battle.wildBattle? && target.opposes? && target.initialItem==oldTargetItem&.id && !user.initialItem
user.setInitialItem(oldTargetItem)
end
@battle.pbDisplay(_INTL("{1} switched items with its opponent!",user.pbThis))
@@ -3328,8 +3332,7 @@ class PokeBattle_Move_0F3 < PokeBattle_Move
itemName = user.itemName
target.item = user.item
# Permanently steal the item from wild Pokémon
if @battle.wildBattle? && user.opposes? &&
user.initialItem==user.item && !target.initialItem
if @battle.wildBattle? && user.opposes? && user.initialItem==user.item&.id && !target.initialItem
target.setInitialItem(user.item)
user.pbRemoveItem
else
@@ -3534,6 +3537,7 @@ class PokeBattle_Move_0F7 < PokeBattle_Move
@willFail = true if user.item.is_berry? && !user.canConsumeBerry?
return if @willFail
return if user.item.is_mega_stone?
return if user.item.is_berry?
flingableItem = false
@flingPowers.each do |_power, items|
next if !items.include?(user.item_id)
@@ -1352,6 +1352,11 @@ class PokeBattle_Move_142 < PokeBattle_Move
def pbEffectAgainstTarget(user, target)
target.effects[PBEffects::Type3] = :GHOST
if target.pbOwnedByPlayer?
@battle.scene.pbRefreshOne(target.index) if $PokemonSystem.type_icons_player
else
@battle.scene.pbRefreshOne(target.index) if $PokemonSystem.type_icons_opponent
end
typeName = GameData::Type.get(:GHOST).name
@battle.pbDisplay(_INTL("{1} transformed into the {2} type!", target.pbThis, typeName))
end
@@ -1371,6 +1376,11 @@ class PokeBattle_Move_143 < PokeBattle_Move
def pbEffectAgainstTarget(user, target)
target.effects[PBEffects::Type3] = :GRASS
if target.pbOwnedByPlayer?
@battle.scene.pbRefreshOne(target.index) if $PokemonSystem.type_icons_player
else
@battle.scene.pbRefreshOne(target.index) if $PokemonSystem.type_icons_opponent
end
typeName = GameData::Type.get(:GRASS).name
@battle.pbDisplay(_INTL("{1} transformed into the {2} type!", target.pbThis, typeName))
end
@@ -2017,6 +2027,11 @@ class PokeBattle_Move_162 < PokeBattle_Move
def pbEffectAfterAllHits(user, target)
if !user.effects[PBEffects::BurnUp]
user.effects[PBEffects::BurnUp] = true
if user.pbOwnedByPlayer?
@battle.scene.pbRefreshOne(user.index) if $PokemonSystem.type_icons_player
else
@battle.scene.pbRefreshOne(user.index) if $PokemonSystem.type_icons_opponent
end
@battle.pbDisplay(_INTL("{1} burned itself out!", user.pbThis))
end
end
@@ -76,10 +76,11 @@ module PokeBattle_BattleCommon
gave_away_pokemon = promptGiveToPartner(pkmn) if isPartneredWithAnyTrainer()
promptCaughtPokemonAction(pkmn) if !gave_away_pokemon
if $game_switches[AUTOSAVE_CATCH_SWITCH]
Kernel.tryAutosave()
end
#Removed because battle restarts right away after reloading and duplicates the Pokemon.
# if $game_switches[AUTOSAVE_CATCH_SWITCH]
# Kernel.tryAutosave()
# end
end
@caughtPokemon.clear
end
@@ -218,6 +218,16 @@ class PokeBattle_Battle
end
end
def list_all_player_participants
participating = []
pbParty(0).each_with_index do |pkmn, i|
next if !pkmn
if @usedInBattle[0][i] == true
participating.push(pkmn) unless pkmn.fainted?
end
end
return participating
end
def singleBattle?
@@ -83,7 +83,6 @@ class PokeBattle_Battle
@sideSizes[0] -= 1
end
end
PBDebug.log("Trying #{@sideSizes[0]}v#{@sideSizes[1]} battle instead")
if @sideSizes[0] <= 0 || @sideSizes[1] <= 0
raise _INTL("Couldn't reduce battle size any further, battle isn't possible")
@@ -103,6 +102,9 @@ class PokeBattle_Battle
pbClearChoice(idxBattler)
@successStates[idxBattler] = PokeBattle_SuccessState.new
@battlers[idxBattler].pbInitialize(pkmn, idxParty)
side = idxBattler % 2
@usedInBattle[side][idxParty] = true if @usedInBattle && @usedInBattle[side]
end
def pbSetUpSides
@@ -378,7 +380,7 @@ class PokeBattle_Battle
$Trainer.cosmetics_money = 0 unless $Trainer.cosmetics_money
pbPlayer.cosmetics_money += cosmetics_money
if !@moneyGain && cosmetics_money > 0 # message displayed in pbGainMoney if player wins money
pbDisplayPaused(_INTL("You got some {1} for winning!", COSMETIC_CURRENCY_NAME))
pbDisplayPaused(_INTL("You got some {1} for winning!", get_cosmetic_currency_name))
end
return cosmetics_money
end
@@ -395,7 +397,7 @@ class PokeBattle_Battle
if moneyGained > 0
if cosmetics_money > 0
pbDisplayPaused(_INTL("You got ${1} and some {2} for winning!", moneyGained.to_s_formatted, COSMETIC_CURRENCY_NAME))
pbDisplayPaused(_INTL("You got ${1} and some {2} for winning!", moneyGained.to_s_formatted, get_cosmetic_currency_name))
else
pbDisplayPaused(_INTL("You got ${1} for winning!", moneyGained.to_s_formatted))
end
@@ -457,7 +459,15 @@ class PokeBattle_Battle
@opponent.each_with_index do |_t, i|
@scene.pbShowOpponent(i)
msg = (@endSpeeches[i] && @endSpeeches[i] != "") ? @endSpeeches[i] : "..."
pbDisplayPaused(msg.gsub(/\\[Pp][Nn]/, pbPlayer.name))
msg = MessageTypes.getFromMapHash($game_map.map_id, msg)
msg = msg.gsub(/\\[Pp][Nn]/, pbPlayer.name)
msg = msg.gsub(/\\n/, "\n")
if Settings::EXPERIMENTAL_FEATURES
pbCallBubFixed(60, 4, 340, 100, true)
pbMessage(msg)
else
pbDisplayPaused(msg)
end
end
end
# Gain money from winning a trainer battle, and from Pay Day
@@ -499,7 +509,10 @@ class PokeBattle_Battle
@opponent.each_with_index do |_t, i|
@scene.pbShowOpponent(i)
msg = (@endSpeechesWin[i] && @endSpeechesWin[i] != "") ? @endSpeechesWin[i] : "..."
pbDisplayPaused(msg.gsub(/\\[Pp][Nn]/, pbPlayer.name))
msg = MessageTypes.getFromMapHash($game_map.map_id, msg)
msg = msg.gsub(/\\[Pp][Nn]/, pbPlayer.name)
msg = msg.gsub(/\\n/, "\n")
pbDisplayPaused(msg)
end
end
end
@@ -302,7 +302,8 @@ class PokeBattle_Battle
sendOuts.each do |b|
@scene.pbResetMoveIndex(b[0])
pbSetSeen(@battlers[b[0]])
@usedInBattle[b[0] & 1][b[0] / 2] = true
idxParty = @battlers[b[0]].pokemonIndex
@usedInBattle[b[0] & 1][idxParty] = true if idxParty >= 0
end
end
@@ -208,44 +208,7 @@ class PokeBattle_Battle
# Weather
pbEORWeather(priority)
# Future Sight/Doom Desire
@positions.each_with_index do |pos,idxPos|
next if !pos || pos.effects[PBEffects::FutureSightCounter]==0
pos.effects[PBEffects::FutureSightCounter] -= 1
next if pos.effects[PBEffects::FutureSightCounter]>0
next if !@battlers[idxPos] || @battlers[idxPos].fainted? # No target
moveUser = nil
eachBattler do |b|
next if b.opposes?(pos.effects[PBEffects::FutureSightUserIndex])
next if b.pokemonIndex!=pos.effects[PBEffects::FutureSightUserPartyIndex]
moveUser = b
break
end
next if moveUser && moveUser.index==idxPos # Target is the user
if !moveUser # User isn't in battle, get it from the party
party = pbParty(pos.effects[PBEffects::FutureSightUserIndex])
pkmn = party[pos.effects[PBEffects::FutureSightUserPartyIndex]]
if pkmn && pkmn.able?
moveUser = PokeBattle_Battler.new(self,pos.effects[PBEffects::FutureSightUserIndex])
moveUser.pbInitDummyPokemon(pkmn,pos.effects[PBEffects::FutureSightUserPartyIndex])
end
end
next if !moveUser # User is fainted
move = pos.effects[PBEffects::FutureSightMove]
pbDisplay(_INTL("{1} took the {2} attack!",@battlers[idxPos].pbThis,
GameData::Move.get(move).name))
# NOTE: Future Sight failing against the target here doesn't count towards
# Stomping Tantrum.
userLastMoveFailed = moveUser.lastMoveFailed
@futureSight = true
moveUser.pbUseMoveSimple(move,idxPos)
@futureSight = false
moveUser.lastMoveFailed = userLastMoveFailed
@battlers[idxPos].pbFaint if @battlers[idxPos].fainted?
pos.effects[PBEffects::FutureSightCounter] = 0
pos.effects[PBEffects::FutureSightMove] = nil
pos.effects[PBEffects::FutureSightUserIndex] = -1
pos.effects[PBEffects::FutureSightUserPartyIndex] = -1
end
@positions.each_with_index { |pos, idxPos| pbEORUseFutureSight(pos, idxPos) }
# Wish
@positions.each_with_index do |pos,idxPos|
next if !pos || pos.effects[PBEffects::Wish]==0
@@ -261,8 +224,8 @@ class PokeBattle_Battle
for side in 0...2
next if sides[side].effects[PBEffects::SeaOfFire]==0
next if [:Rain, :HeavyRain].include?(curWeather)
@battle.pbCommonAnimation("SeaOfFire") if side==0
@battle.pbCommonAnimation("SeaOfFireOpp") if side==1
pbCommonAnimation("SeaOfFire") if side==0
pbCommonAnimation("SeaOfFireOpp") if side==1
priority.each do |b|
next if b.opposes?(side)
next if !b.takesIndirectDamage? || b.pbHasType?(:FIRE)
@@ -631,7 +594,14 @@ class PokeBattle_Battle
b.effects[PBEffects::PriorityItem] = false
b.effects[PBEffects::Protect] = false
b.effects[PBEffects::RagePowder] = false
b.effects[PBEffects::Roost] = false
if b.effects[PBEffects::Roost]
b.effects[PBEffects::Roost] = false
if b.pbOwnedByPlayer?
@scene.pbRefreshOne(b.index) if $PokemonSystem.type_icons_player
else
@scene.pbRefreshOne(b.index) if $PokemonSystem.type_icons_opponent
end
end
b.effects[PBEffects::Snatch] = 0
b.effects[PBEffects::SpikyShield] = false
b.effects[PBEffects::Spotlight] = 0
@@ -663,4 +633,51 @@ class PokeBattle_Battle
@field.effects[PBEffects::FusionFlare] = false
@endOfRound = false
end
#-----------------------------------------------------------------------------
# End Of Round use delayed moves (Future Sight, Doom Desire).
#-----------------------------------------------------------------------------
def pbEORUseFutureSight(position, position_index)
return if !position || position.effects[PBEffects::FutureSightCounter] == 0
position.effects[PBEffects::FutureSightCounter] -= 1
return if position.effects[PBEffects::FutureSightCounter] > 0
move = position.effects[PBEffects::FutureSightMove]
userIdx = position.effects[PBEffects::FutureSightUserIndex]
partyIdx = position.effects[PBEffects::FutureSightUserPartyIndex]
position.effects[PBEffects::FutureSightCounter] = 0
position.effects[PBEffects::FutureSightMove] = nil
position.effects[PBEffects::FutureSightUserIndex] = -1
position.effects[PBEffects::FutureSightUserPartyIndex] = -1
return if !move # defensive: corrupted/never-set state, bail out safely
return if !@battlers[position_index] || @battlers[position_index].fainted?
moveUser = nil
allBattlers = @battlers.select { |b| b && !b.fainted? }
allBattlers.each do |battler|
next if battler.opposes?(userIdx)
next if battler.pokemonIndex != partyIdx
moveUser = battler
break
end
return if moveUser && moveUser.index == position_index
if !moveUser
party = pbParty(userIdx)
pkmn = (partyIdx >= 0) ? party[partyIdx] : nil
if pkmn&.able?
moveUser = PokeBattle_Battler.new(self, userIdx)
moveUser.pbInitDummyPokemon(pkmn, partyIdx)
end
end
return if !moveUser
pbDisplay(_INTL("{1} took the {2} attack!", @battlers[position_index].pbThis,
GameData::Move.get(move).name))
userLastMoveFailed = moveUser.lastMoveFailed
@futureSight = true
moveUser.pbUseMoveSimple(move, position_index)
@futureSight = false
moveUser.lastMoveFailed = userLastMoveFailed
@battlers[position_index].pbFaint if @battlers[position_index].fainted?
end
end
@@ -183,7 +183,7 @@ BattleHandlers::StatusImmunityAbilityNonIgnorable.add(:COMATOSE,
BattleHandlers::StatusImmunityAbilityNonIgnorable.add(:SHIELDSDOWN,
proc { |ability,battler,status|
next true if battler.isFusionOf(:MINIOR_C) && battler.form<7
next true if battler.isFusionOf(:MINIOR_M) && battler.form<7
}
)
@@ -1453,6 +1453,11 @@ BattleHandlers::TargetAbilityOnHit.add(:ILLUSION,
next if !target.effects[PBEffects::Illusion]
target.effects[PBEffects::Illusion] = nil
battle.scene.pbChangePokemon(target,target.pokemon)
if user.pbOwnedByPlayer?
battle.scene.pbRefreshOne(target.index) if $PokemonSystem.type_icons_player
else
battle.scene.pbRefreshOne(target.index) if $PokemonSystem.type_icons_opponent
end
battle.pbDisplay(_INTL("{1}'s illusion wore off!",target.pbThis))
battle.pbSetSeen(target)
}
@@ -0,0 +1,413 @@
module MoveFunctions
# --- 000-00F: Basic / status conditions ----------------------------------
NO_ADDITIONAL_EFFECT = "000" # Tackle, Slash, Hydro Pump, Megahorn, X-Scissor, etc.
NO_EFFECT = "001" # Splash, Counterfeit
STRUGGLE = "002"
INFLICT_SLEEP = "003" # Spore, Sing, Hypnosis, Sleep Powder, Dark Void, Relic Song...
INFLICT_DROWSY = "004" # Yawn
INFLICT_POISON = "005" # Sludge Bomb, Poison Jab, Gunk Shot, Smog, Poison Gas...
INFLICT_BAD_POISON = "006" # Toxic, Poison Fang
INFLICT_PARALYSIS = "007" # Thunderbolt, Thunder Wave, Body Slam, Glare, Stun Spore...
INFLICT_PARALYSIS_THUNDER = "008" # Thunder (weather affects accuracy)
PARALYZE_OR_FLINCH = "009" # Thunder Fang
INFLICT_BURN = "00A" # Flamethrower, Fire Blast, Will-O-Wisp, Scald, Ember...
BURN_OR_FLINCH = "00B" # Fire Fang
INFLICT_FREEZE = "00C" # Ice Beam, Ice Punch, Powder Snow
INFLICT_FREEZE_BLIZZARD = "00D" # Blizzard (perfect accuracy in hail)
FREEZE_OR_FLINCH = "00E" # Ice Fang
FLINCH = "00F" # Bite, Air Slash, Iron Head, Headbutt, Rock Slide...
# --- 010-01F: Flinch / confusion / misc status ----------------------------
FLINCH_MINIMIZE_BOOST = "010" # Stomp, Steamroller, Dragon Rush
HIT_ONLY_WHILE_ASLEEP = "011" # Snore
FLINCH_FIRST_TURN_ONLY = "012" # Fake Out
INFLICT_CONFUSION = "013" # Psybeam, Confusion, Confuse Ray, Supersonic, Water Pulse...
INFLICT_CONFUSION_CHATTER = "014" # Chatter
INFLICT_CONFUSION_HURRICANE = "015" # Hurricane (weather affects accuracy)
INFLICT_ATTRACT = "016" # Attract
BURN_FREEZE_OR_PARALYZE = "017" # Tri Attack
CURE_USER_STATUS = "018" # Refresh
CURE_PARTY_STATUS = "019" # Aromatherapy, Heal Bell
SAFEGUARD = "01A" # Safeguard
TRANSFER_STATUS = "01B" # Psycho Shift
USER_ATTACK_UP_1 = "01C" # Howl, Sharpen, Meditate, Meteor Mash, Metal Claw, Power-Up Punch
USER_DEFENSE_UP_1 = "01D" # Harden, Withdraw, Steel Wing
USER_DEFENSE_UP_1_CURL = "01E" # Defense Curl
USER_SPEED_UP_1 = "01F" # Flame Charge
# --- 020-02F: User stat boosts ---------------------------------------------
USER_SP_ATK_UP_1 = "020" # Charge Beam, Fiery Dance
USER_SP_DEF_UP_1_CHARGE = "021" # Charge
USER_EVASION_UP_1 = "022" # Double Team
USER_CRIT_RATE_UP = "023" # Focus Energy
USER_ATK_DEF_UP_1 = "024" # Bulk Up
USER_ATK_DEF_ACC_UP_1 = "025" # Coil
USER_ATK_SPEED_UP_1 = "026" # Dragon Dance
USER_ATK_SP_ATK_UP_1 = "027" # Work Up
USER_ATK_SP_ATK_UP_1_SUN = "028" # Growth (doubled in sun)
USER_ATK_ACC_UP_1 = "029" # Hone Claws
USER_DEF_SP_DEF_UP_1 = "02A" # Cosmic Power, Defend Order
USER_SP_ATK_SP_DEF_SPEED_UP_1 = "02B" # Quiver Dance
USER_SP_ATK_SP_DEF_UP_1 = "02C" # Calm Mind
USER_ALL_STATS_UP_1 = "02D" # Ancient Power, Ominous Wind, Silver Wind
USER_ATTACK_UP_2 = "02E" # Swords Dance
USER_DEFENSE_UP_2 = "02F" # Acid Armor, Barrier, Iron Defense
# --- 030-03F: User stat boosts / drops --------------------------------------
USER_SPEED_UP_2 = "030" # Agility, Rock Polish
USER_SPEED_UP_2_LOSE_WEIGHT = "031" # Autotomize
USER_SP_ATK_UP_2 = "032" # Nasty Plot
USER_SP_DEF_UP_2 = "033" # Amnesia
USER_EVASION_UP_2_MINIMIZE = "034" # Minimize
USER_SHELL_SMASH = "035" # Shell Smash
USER_SPEED_UP_2_ATTACK_UP_1 = "036" # Shift Gear
RAISE_RANDOM_STAT_2 = "037" # Acupressure
USER_DEFENSE_UP_3 = "038" # Cotton Guard
USER_SP_ATK_UP_3 = "039" # Tail Glow
USER_BELLY_DRUM = "03A" # Belly Drum
USER_ATK_DEF_DOWN_1 = "03B" # Superpower
USER_DEF_SP_DEF_DOWN_1 = "03C" # Close Combat, Dragon Ascent
USER_DEF_SP_DEF_SPEED_DOWN_1 = "03D" # V-create
USER_SPEED_DOWN_1 = "03E" # Hammer Arm, Ice Hammer
USER_SP_ATK_DOWN_2 = "03F" # Draco Meteor, Overheat, Leaf Storm, Psycho Boost, Fleur Cannon
# --- 040-04F: Target stat changes -------------------------------------------
TARGET_SP_ATK_UP_1_CONFUSE = "040" # Flatter
TARGET_ATTACK_UP_2_CONFUSE = "041" # Swagger
TARGET_ATTACK_DOWN_1 = "042" # Growl, Play Rough, Lunge, Baby-Doll Eyes, Aurora Beam...
TARGET_DEFENSE_DOWN_1 = "043" # Leer, Tail Whip, Crunch, Iron Tail, Rock Smash...
TARGET_SPEED_DOWN_1 = "044" # Icy Wind, Bulldoze, Mud Shot, Rock Tomb, Bubble Beam...
TARGET_SP_ATK_DOWN_1 = "045" # Moonblast, Snarl, Struggle Bug, Mystical Fire, Mist Ball
TARGET_SP_DEF_DOWN_1 = "046" # Psychic, Shadow Ball, Energy Ball, Earth Power, Bug Buzz...
TARGET_ACCURACY_DOWN_1 = "047" # Smokescreen, Sand Attack, Mud-Slap, Flash, Octazooka...
TARGET_EVASION_DOWN = "048" # Sweet Scent
TARGET_EVASION_DOWN_CLEAR_FIELD = "049" # Defog
TARGET_ATK_DEF_DOWN_1 = "04A" # Tickle
TARGET_ATTACK_DOWN_2 = "04B" # Charm, Feather Dance
TARGET_DEFENSE_DOWN_2 = "04C" # Screech
TARGET_SPEED_DOWN_2 = "04D" # String Shot, Cotton Spore, Scary Face
TARGET_SP_ATK_DOWN_2_GENDER = "04E" # Captivate
TARGET_SP_DEF_DOWN_2 = "04F" # Fake Tears, Acid Spray, Seed Flare, Metal Sound
# --- 050-05F: Stat stage manipulation / type & ability changes ----------------
RESET_TARGET_STAT_STAGES = "050" # Clear Smog
RESET_ALL_STAT_STAGES = "051" # Haze
SWAP_ATTACK_STAGES = "052" # Power Swap
SWAP_DEFENSE_STAGES = "053" # Guard Swap
SWAP_ALL_STAGES = "054" # Heart Swap
COPY_TARGET_STAGES = "055" # Psych Up
PREVENT_STAT_DROPS = "056" # Mist
SWAP_USER_ATK_DEF = "057" # Power Trick
AVERAGE_ATTACK_STATS = "058" # Power Split
AVERAGE_DEFENSE_STATS = "059" # Guard Split
AVERAGE_HP = "05A" # Pain Split
TAILWIND = "05B" # Tailwind
MIMIC = "05C" # Mimic
SKETCH = "05D" # Sketch
CHANGE_TYPE_TO_MOVE = "05E" # Conversion
CHANGE_TYPE_TO_RESIST = "05F" # Conversion 2
# --- 060-06F: Type / ability changes, fixed damage ---------------------------
CHANGE_TYPE_BY_ENVIRONMENT = "060" # Camouflage
TARGET_BECOMES_WATER = "061" # Soak
COPY_TARGET_TYPE = "062" # Reflect Type
TARGET_ABILITY_SIMPLE = "063" # Simple Beam
TARGET_ABILITY_INSOMNIA = "064" # Worry Seed
USER_COPY_TARGET_ABILITY = "065" # Role Play
TARGET_COPY_USER_ABILITY = "066" # Entrainment
SWAP_ABILITIES = "067" # Skill Swap
NEGATE_TARGET_ABILITY = "068" # Gastro Acid
TRANSFORM = "069" # Transform
FIXED_DAMAGE_20 = "06A" # Sonic Boom
FIXED_DAMAGE_40 = "06B" # Dragon Rage
FIXED_DAMAGE_HALF_TARGET_HP = "06C" # Super Fang, Nature's Madness
FIXED_DAMAGE_USER_LEVEL = "06D" # Seismic Toss, Night Shade
FIXED_DAMAGE_MATCH_USER_HP = "06E" # Endeavor
FIXED_DAMAGE_RANDOM_LEVEL = "06F" # Psywave
# --- 070-07F: OHKO, counters, conditional power ----------------------------------
ONE_HIT_KO = "070" # Fissure, Sheer Cold, Guillotine, Horn Drill
COUNTER_PHYSICAL = "071" # Counter
COUNTER_SPECIAL = "072" # Mirror Coat
COUNTER_LAST_DAMAGE = "073" # Metal Burst
DAMAGE_TARGET_ALLY = "074" # Flame Burst
DOUBLE_POWER_VS_DIVE = "075" # Surf
DOUBLE_POWER_VS_DIG = "076" # Earthquake
DOUBLE_POWER_VS_FLYING_GUST = "077" # Gust
DOUBLE_POWER_VS_FLYING_TWISTER = "078" # Twister (also flinches)
DOUBLE_POWER_AFTER_FUSION_FLARE = "079" # Fusion Bolt
DOUBLE_POWER_AFTER_FUSION_BOLT = "07A" # Fusion Flare
DOUBLE_POWER_IF_POISONED = "07B" # Venoshock
DOUBLE_POWER_IF_PARALYZED = "07C" # Smelling Salts
DOUBLE_POWER_IF_ASLEEP = "07D" # Wake-Up Slap
DOUBLE_POWER_IF_USER_STATUS = "07E" # Facade
DOUBLE_POWER_IF_TARGET_STATUS = "07F" # Hex
# --- 080-08F: Conditional / variable power ------------------------------------------
DOUBLE_POWER_IF_TARGET_HALF_HP = "080" # Brine
DOUBLE_POWER_IF_USER_HIT = "081" # Revenge, Avalanche
DOUBLE_POWER_IF_TARGET_DAMAGED = "082" # Assurance
ROUND = "083" # Round
DOUBLE_POWER_IF_TARGET_MOVED = "084" # Payback
DOUBLE_POWER_IF_ALLY_FAINTED = "085" # Retaliate
DOUBLE_POWER_IF_NO_ITEM = "086" # Acrobatics
WEATHER_BALL = "087" # Weather Ball
PURSUIT = "088" # Pursuit
POWER_BY_HAPPINESS = "089" # Return
POWER_BY_LOW_HAPPINESS = "08A" # Frustration
POWER_BY_USER_HP = "08B" # Eruption, Water Spout
POWER_BY_TARGET_HP = "08C" # Crush Grip, Wring Out
POWER_BY_SPEED_DIFF_SLOWER = "08D" # Gyro Ball
POWER_BY_USER_STAT_BOOSTS = "08E" # Power Trip, Stored Power
POWER_BY_TARGET_STAT_BOOSTS = "08F" # Punishment
# --- 090-09F: Variable power / field effects ----------------------------------------
HIDDEN_POWER = "090" # Hidden Power
POWER_DOUBLES_CONSECUTIVE = "091" # Fury Cutter
POWER_BY_CONSECUTIVE_TURNS = "092" # Echoed Voice
RAGE = "093" # Rage
PRESENT = "094" # Present
MAGNITUDE = "095" # Magnitude
NATURAL_GIFT = "096" # Natural Gift
POWER_BY_LOW_PP = "097" # Trump Card
POWER_BY_LOW_USER_HP = "098" # Flail, Reversal
POWER_BY_SPEED_DIFF_FASTER = "099" # Electro Ball
POWER_BY_TARGET_WEIGHT = "09A" # Low Kick, Grass Knot
POWER_BY_WEIGHT_DIFF = "09B" # Heat Crash, Heavy Slam
HELPING_HAND = "09C" # Helping Hand
MUD_SPORT = "09D" # Mud Sport
WATER_SPORT = "09E" # Water Sport
TYPE_BY_HELD_ITEM = "09F" # Judgment, Multi-Attack, Techno Blast
# --- 0A0-0AF: Crits, screens, accuracy, protection, move copying ---------------------
ALWAYS_CRITICAL_HIT = "0A0" # Frost Breath, Storm Throw
LUCKY_CHANT = "0A1" # Lucky Chant
REFLECT = "0A2" # Reflect
LIGHT_SCREEN = "0A3" # Light Screen
SECRET_POWER = "0A4" # Secret Power
ALWAYS_HITS = "0A5" # Swift, Aerial Ace, Aura Sphere, Shock Wave, Magical Leaf...
LOCK_ON = "0A6" # Lock-On, Mind Reader
FORESIGHT = "0A7" # Foresight, Odor Sleuth
MIRACLE_EYE = "0A8" # Miracle Eye
IGNORE_DEFENSE_STAGES = "0A9" # Chip Away, Darkest Lariat, Sacred Sword
PROTECT = "0AA" # Protect, Detect
QUICK_GUARD = "0AB" # Quick Guard
WIDE_GUARD = "0AC" # Wide Guard
FEINT = "0AD" # Feint
MIRROR_MOVE = "0AE" # Mirror Move
COPYCAT = "0AF" # Copycat
# --- 0B0-0BF: Move calling, disruption, multi-hit ------------------------------------
ME_FIRST = "0B0" # Me First
MAGIC_COAT = "0B1" # Magic Coat
SNATCH = "0B2" # Snatch
NATURE_POWER = "0B3" # Nature Power
RANDOM_MOVE_WHILE_ASLEEP = "0B4" # Sleep Talk
ASSIST = "0B5" # Assist
METRONOME = "0B6" # Metronome
TORMENT = "0B7" # Torment
IMPRISON = "0B8" # Imprison
DISABLE = "0B9" # Disable
TAUNT = "0BA" # Taunt
HEAL_BLOCK = "0BB" # Heal Block
ENCORE = "0BC" # Encore
HIT_TWICE = "0BD" # Double Kick, Dual Chop, Bonemerang, Double Hit, Gear Grind
HIT_TWICE_POISON = "0BE" # Twineedle
HIT_THREE_TIMES_POWER_UP = "0BF" # Triple Kick
# --- 0C0-0CF: Multi-hit, recharge, two-turn moves --------------------------------------
HIT_2_TO_5_TIMES = "0C0" # Fury Attack, Bullet Seed, Rock Blast, Icicle Spear, Pin Missile...
BEAT_UP = "0C1" # Beat Up
RECHARGE_NEXT_TURN = "0C2" # Hyper Beam, Giga Impact, Blast Burn, Frenzy Plant, Hydro Cannon...
TWO_TURN_RAZOR_WIND = "0C3" # Razor Wind
TWO_TURN_SOLAR_BEAM = "0C4" # Solar Beam, Solar Blade
TWO_TURN_FREEZE_SHOCK = "0C5" # Freeze Shock
TWO_TURN_ICE_BURN = "0C6" # Ice Burn
TWO_TURN_SKY_ATTACK = "0C7" # Sky Attack
TWO_TURN_SKULL_BASH = "0C8" # Skull Bash
TWO_TURN_FLY = "0C9" # Fly
TWO_TURN_DIG = "0CA" # Dig
TWO_TURN_DIVE = "0CB" # Dive
TWO_TURN_BOUNCE = "0CC" # Bounce
TWO_TURN_SHADOW_FORCE = "0CD" # Shadow Force
TWO_TURN_SKY_DROP = "0CE" # Sky Drop
TRAP_TARGET = "0CF" # Bind, Wrap, Clamp, Fire Spin, Magma Storm, Sand Tomb, Infestation
# --- 0D0-0DF: Trapping, rampage, healing / draining ----------------------------------------
TRAP_TARGET_WHIRLPOOL = "0D0" # Whirlpool
UPROAR = "0D1" # Uproar
RAMPAGE_THEN_CONFUSE = "0D2" # Outrage, Petal Dance, Thrash
ROLLOUT = "0D3" # Rollout, Ice Ball
BIDE = "0D4" # Bide
HEAL_USER_HALF = "0D5" # Recover, Slack Off, Soft-Boiled, Milk Drink, Heal Order
HEAL_USER_HALF_ROOST = "0D6" # Roost
WISH = "0D7" # Wish
HEAL_USER_BY_WEATHER = "0D8" # Moonlight, Morning Sun, Synthesis
REST = "0D9" # Rest
AQUA_RING = "0DA" # Aqua Ring
INGRAIN = "0DB" # Ingrain
LEECH_SEED = "0DC" # Leech Seed
DRAIN_HALF_DAMAGE = "0DD" # Absorb, Giga Drain, Drain Punch, Horn Leech, Leech Life...
DREAM_EATER = "0DE" # Dream Eater
HEAL_TARGET_HALF = "0DF" # Heal Pulse
# --- 0E0-0EF: Self-KO, switching, trapping -------------------------------------------------
USER_FAINTS_EXPLODE = "0E0" # Explosion, Self-Destruct
FINAL_GAMBIT = "0E1" # Final Gambit
MEMENTO = "0E2" # Memento
HEALING_WISH = "0E3" # Healing Wish
LUNAR_DANCE = "0E4" # Lunar Dance
PERISH_SONG = "0E5" # Perish Song
GRUDGE = "0E6" # Grudge
DESTINY_BOND = "0E7" # Destiny Bond
ENDURE = "0E8" # Endure
NON_LETHAL_HIT = "0E9" # False Swipe, Hold Back
TELEPORT = "0EA" # Teleport
FORCE_SWITCH_STATUS = "0EB" # Roar, Whirlwind
FORCE_SWITCH_DAMAGE = "0EC" # Dragon Tail, Circle Throw
BATON_PASS = "0ED" # Baton Pass
SWITCH_OUT_AFTER_HIT = "0EE" # U-turn, Volt Switch
PREVENT_ESCAPE = "0EF" # Mean Look, Block, Spider Web, Anchor Shot, Spirit Shackle...
# --- 0F0-0FF: Items, recoil, weather ---------------------------------------------------------
KNOCK_OFF = "0F0" # Knock Off
STEAL_ITEM = "0F1" # Thief, Covet
SWAP_ITEMS = "0F2" # Trick, Switcheroo
BESTOW = "0F3" # Bestow
EAT_TARGET_BERRY = "0F4" # Bug Bite, Pluck
DESTROY_TARGET_BERRY = "0F5" # Incinerate
RECYCLE = "0F6" # Recycle
FLING = "0F7" # Fling
EMBARGO = "0F8" # Embargo
MAGIC_ROOM = "0F9" # Magic Room
RECOIL_QUARTER = "0FA" # Take Down, Submission, Wild Charge, Head Charge
RECOIL_THIRD = "0FB" # Double-Edge, Brave Bird, Wood Hammer
RECOIL_HALF = "0FC" # Head Smash, Light of Ruin
RECOIL_THIRD_PARALYZE = "0FD" # Volt Tackle
RECOIL_THIRD_BURN = "0FE" # Flare Blitz
WEATHER_SUN = "0FF" # Sunny Day
# --- 100-10F: Weather, hazards, misc ----------------------------------------------------------
WEATHER_RAIN = "100" # Rain Dance
WEATHER_SANDSTORM = "101" # Sandstorm
WEATHER_HAIL = "102" # Hail
HAZARD_SPIKES = "103" # Spikes
HAZARD_TOXIC_SPIKES = "104" # Toxic Spikes
HAZARD_STEALTH_ROCK = "105" # Stealth Rock
PLEDGE_GRASS = "106" # Grass Pledge
PLEDGE_FIRE = "107" # Fire Pledge
PLEDGE_WATER = "108" # Water Pledge
PAY_DAY = "109" # Pay Day
BREAK_SCREENS = "10A" # Brick Break, Psychic Fangs
CRASH_DAMAGE_ON_MISS = "10B" # Jump Kick, High Jump Kick
SUBSTITUTE = "10C" # Substitute
CURSE = "10D" # Curse
SPITE = "10E" # Spite
NIGHTMARE = "10F" # Nightmare
# --- 110-11F: Misc, stockpile, redirect, field effects ----------------------------------------
RAPID_SPIN = "110" # Rapid Spin
DELAYED_ATTACK = "111" # Future Sight, Doom Desire
STOCKPILE = "112" # Stockpile
SPIT_UP = "113" # Spit Up
SWALLOW = "114" # Swallow
FAILS_IF_USER_HIT = "115" # Focus Punch
FAILS_IF_TARGET_NOT_ATTACKING = "116" # Sucker Punch
REDIRECT_ATTACKS_TO_USER = "117" # Follow Me, Rage Powder
GRAVITY = "118" # Gravity
MAGNET_RISE = "119" # Magnet Rise
TELEKINESIS = "11A" # Telekinesis
HITS_FLYING_TARGETS = "11B" # Sky Uppercut
GROUND_TARGET = "11C" # Smack Down, Thousand Arrows
AFTER_YOU = "11D" # After You
QUASH = "11E" # Quash
TRICK_ROOM = "11F" # Trick Room
# --- 120-12F: Misc (126-132 are reserved for Shadow moves) --------------------------------------
ALLY_SWITCH = "120" # Ally Switch
USE_TARGET_ATTACK = "121" # Foul Play
USE_TARGET_DEFENSE = "122" # Psyshock, Psystrike, Secret Sword
DAMAGE_SAME_TYPE_ONLY = "123" # Synchronoise
WONDER_ROOM = "124" # Wonder Room
LAST_RESORT = "125" # Last Resort
# 126-132: reserved for Shadow moves (no constants defined)
# --- 133-13F: Gen 6 moves --------------------------------------------------------------------
HOLD_HANDS = "133" # Hold Hands
CELEBRATE = "134" # Celebrate
FREEZE_SUPER_EFFECTIVE_WATER = "135" # Freeze-Dry
USER_DEFENSE_UP_2_DIAMOND_STORM = "136" # Diamond Storm
MAGNETIC_FLUX = "137" # Magnetic Flux
AROMATIC_MIST = "138" # Aromatic Mist
TARGET_ATTACK_DOWN_1_NEVER_MISS = "139" # Play Nice
TARGET_ATK_SP_ATK_DOWN_1 = "13A" # Noble Roar, Tearful Look
HYPERSPACE_FURY = "13B" # Hyperspace Fury
TARGET_SP_ATK_DOWN_1_NEVER_MISS = "13C" # Confide
TARGET_SP_ATK_DOWN_2_PLAIN = "13D" # Eerie Impulse
ROTOTILLER = "13E" # Rototiller
FLOWER_SHIELD = "13F" # Flower Shield
# --- 140-14F ----------------------------------------------------------------------------------
VENOM_DRENCH = "140" # Venom Drench
TOPSY_TURVY = "141" # Topsy-Turvy
ADD_GHOST_TYPE = "142" # Trick-or-Treat
ADD_GRASS_TYPE = "143" # Forest's Curse
FLYING_PRESS = "144" # Flying Press
ELECTRIFY = "145" # Electrify
ION_DELUGE = "146" # Ion Deluge, Plasma Fists
HYPERSPACE_HOLE = "147" # Hyperspace Hole
POWDER = "148" # Powder
MAT_BLOCK = "149" # Mat Block
CRAFTY_SHIELD = "14A" # Crafty Shield
KINGS_SHIELD = "14B" # King's Shield
SPIKY_SHIELD = "14C" # Spiky Shield
TWO_TURN_PHANTOM_FORCE = "14D" # Phantom Force
GEOMANCY = "14E" # Geomancy
DRAIN_THREE_QUARTERS_DAMAGE = "14F" # Draining Kiss, Oblivion Wing
# --- 150-15F ----------------------------------------------------------------------------------
FELL_STINGER = "150" # Fell Stinger
PARTING_SHOT = "151" # Parting Shot
FAIRY_LOCK = "152" # Fairy Lock
HAZARD_STICKY_WEB = "153" # Sticky Web
TERRAIN_ELECTRIC = "154" # Electric Terrain
TERRAIN_GRASSY = "155" # Grassy Terrain
TERRAIN_MISTY = "156" # Misty Terrain
HAPPY_HOUR = "157" # Happy Hour
BELCH = "158" # Belch
TOXIC_THREAD = "159" # Toxic Thread
SPARKLING_ARIA = "15A" # Sparkling Aria
PURIFY = "15B" # Purify
GEAR_UP = "15C" # Gear Up
SPECTRAL_THIEF = "15D" # Spectral Thief
LASER_FOCUS = "15E" # Laser Focus
USER_DEFENSE_DOWN_1 = "15F" # Clanging Scales
# --- 160-16F ----------------------------------------------------------------------------------
STRENGTH_SAP = "160" # Strength Sap
SPEED_SWAP = "161" # Speed Swap
BURN_UP = "162" # Burn Up
IGNORE_ABILITIES = "163" # Moongeist Beam, Sunsteel Strike
PHOTON_GEYSER = "164" # Photon Geyser
CORE_ENFORCER = "165" # Core Enforcer
DOUBLE_POWER_IF_LAST_MOVE_FAILED = "166" # Stomping Tantrum
AURORA_VEIL = "167" # Aurora Veil
BANEFUL_BUNKER = "168" # Baneful Bunker
REVELATION_DANCE = "169" # Revelation Dance
SPOTLIGHT = "16A" # Spotlight
INSTRUCT = "16B" # Instruct
THROAT_CHOP = "16C" # Throat Chop
HEAL_USER_HALF_SANDSTORM_BOOST = "16D" # Shore Up
HEAL_TARGET_HALF_GRASSY_BOOST = "16E" # Floral Healing
POLLEN_PUFF = "16F" # Pollen Puff
# --- 170-175 ----------------------------------------------------------------------------------
MIND_BLOWN = "170" # Mind Blown
SHELL_TRAP = "171" # Shell Trap
BEAK_BLAST = "172" # Beak Blast
TERRAIN_PSYCHIC = "173" # Psychic Terrain
FAILS_AFTER_FIRST_TURN = "174" # First Impression
HIT_TWICE_FLINCH = "175" # Double Iron Bash
# New custom function codes should start at 176 (or high values like 500+).
end
File diff suppressed because it is too large Load Diff
@@ -272,44 +272,49 @@ class PokemonDataBox < SpriteWrapper
end
# Draw type icons (foe Pokémon only)
if @battler.opposes?(0) && $PokemonSystem.type_icons
if @battler.opposes?(0) && $PokemonSystem.type_icons_opponent
drawEnemyTypeIcons(imagePos)
end
if @battler.pbOwnedByPlayer? && $PokemonSystem.type_icons_player
drawPlayerTypeIcons(imagePos)
end
pbDrawImagePositions(self.bitmap, imagePos)
refreshHP
refreshExp
end
def drawEnemyTypeIcons(imagePos)
def drawTypeIcons(imagePos, x_position, first_icon_y_position, wrap_direction)
return if @battler.is_a?(PokeBattle_FakeBattler)
type1_number = GameData::Type.get(@battler.type1).id_number
type2_number = GameData::Type.get(@battler.type2).id_number
vertical_margin = 2
iconHeight = 19
type_icons_x_position = @spriteBaseX + 210
type1_icon_y_position = 16
type2_icon_y_position = type1_icon_y_position + vertical_margin + iconHeight
type1_y_offset = type1_number * iconHeight
type2_y_offset = type2_number * iconHeight
types_icon_path = "Graphics/Pictures/Battle/typesSmall"
y_position = first_icon_y_position
x_offset = 0
types_icon_path = "Graphics/Pictures/Battle/typesSmall"
if type1_number == type2_number
imagePos.push([types_icon_path, type_icons_x_position, type1_icon_y_position,
x_offset, type1_y_offset, -1, iconHeight])
else
imagePos.push([types_icon_path, type_icons_x_position,
type1_icon_y_position,
x_offset,
type1_y_offset, -1, iconHeight]
)
imagePos.push([types_icon_path, type_icons_x_position, type2_icon_y_position,
x_offset,
type2_y_offset, -1, iconHeight])
end
illusion = @battler.effects[PBEffects::Illusion]
types = illusion ? [ illusion.type1, illusion.type2 ] : @battler.pbTypes(true)
types.uniq.each { |type|
type_number = GameData::Type.get(type).id_number
type_y_offset = type_number * iconHeight
imagePos.push([types_icon_path, x_position, y_position,
x_offset, type_y_offset, -1, iconHeight])
y_position += vertical_margin + iconHeight
if y_position + iconHeight > self.bitmap.height
y_position = first_icon_y_position
x_position += (vertical_margin + iconHeight) * wrap_direction
end
}
end
def drawEnemyTypeIcons(imagePos)
drawTypeIcons(imagePos, @spriteBaseX + 210, 16, 1)
end
def drawPlayerTypeIcons(imagePos)
drawTypeIcons(imagePos, @spriteBaseX -20, 16, -1)
end
def refreshHP
@@ -211,14 +211,21 @@ class PokeBattle_Scene
else
x = 200
y = 380
# Partner trainer's sprite
trainerFile = GameData::TrainerType.front_sprite_filename(trainerType)
echoln ""
echoln "-------"
echoln trainerFile
echoln trainerType
if trainerType == :RIVAL1 && Settings::HOENN
trainer_sprite = IconSprite.new(x,y,@viewport)
trainer_sprite.setBitmapDirectly(generate_front_trainer_sprite_bitmap_from_appearance($Trainer.rival_appearance))
else
# Partner trainer's sprite
trainerFile = GameData::TrainerType.front_sprite_filename(trainerType)
echoln ""
echoln "-------"
echoln trainerFile
trainer_sprite = IconSprite.new(x,y,@viewport)
trainer_sprite.setBitmap(trainerFile)
trainer_sprite = IconSprite.new(x,y,@viewport)
trainer_sprite.setBitmap(trainerFile)
end
trainer_sprite.zoom_x=2
trainer_sprite.zoom_y=2
trainer_sprite.z = 30 + idxTrainer
@@ -7,9 +7,10 @@ class PokeBattle_FakeBattler
attr_reader :pokemon
attr_reader :owned
def initialize(battle,index)
def initialize(battle,index,pokemon=nil)
@battle = battle
@pokemon = battle.party2[0]
@pokemon = pokemon
@pokemon = battle.party2[0] unless pokemon
@index = index
end
@@ -25,6 +26,10 @@ class PokeBattle_FakeBattler
def shiny?; return @pokemon.shiny?; end
alias isShiny? shiny?
def pbOwnedByPlayer?
return @battle.pbOwnedByPlayer?(@index)
end
def isSpecies?(check_species)
return @pokemon && @pokemon.isSpecies?(check_species)
end
@@ -348,6 +353,10 @@ class PokeBattle_SafariZone
return 30-@ballCount
end
def pbOwnedByPlayer?(idxBattler)
return
end
def defaultWeather=(value); @weather = value; end
def defaultTerrain=(value); end
@@ -286,6 +286,94 @@ class LightEffect_DayNight < LightEffect
end
end
class LightEffect_PokemonGlow < LightEffect_DayNight
def initialize(event, viewport = nil, map = nil)
return unless event.is_a?(OverworldPokemonEvent)
@event = event
@map = map || $game_map
@disposed = false
glow_sprite_path = "Graphics/Characters/#{event.character_name}_glow"
if pbResolveBitmap(glow_sprite_path)
@glow_bitmap = AnimatedBitmap.new(glow_sprite_path).bitmap
else
@glow_bitmap = AnimatedBitmap.new("Graphics/Pictures/LE_pokemon").bitmap
end
# 4 rows = directions (down, left, right, up), columns = walk frames.
# Frame is assumed square, same as the character's own charset.
@frame_height = @glow_bitmap.height / 4
@frame_width = @frame_height
@num_frames = [@glow_bitmap.width / @frame_width, 1].max
@light = Sprite.new(viewport)
@light.bitmap = Bitmap.new(@frame_width, @frame_height)
@light.z = 1000
@last_direction = nil
@last_pattern = nil
update_frame
end
def dispose
@glow_bitmap&.dispose
super
end
def update
return if !@light || !@event || @disposed
update_frame
@light.update
if $PokemonGlobal&.diving
shade = 0
else
shade = PBDayNight.getShade
end
if shade >= 144
shade = 255
elsif shade <= 64
shade = 0
else
shade = 255 - (255 * (144 - shade) / (144 - 64))
end
@light.opacity = 255 - shade
return if @light.opacity <= 0
@light.ox = @frame_width / 2
@light.oy = @frame_height
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
private
def update_frame
return unless @glow_bitmap
direction = @event.direction
pattern = (@event.pattern rescue 0)
return if direction == @last_direction && pattern == @last_pattern
row = [2, 4, 6, 8].index(direction) || 0
col = pattern.clamp(0, @num_frames - 1)
src_rect = Rect.new(col * @frame_width, row * @frame_height, @frame_width, @frame_height)
@light.bitmap.clear
@light.bitmap.blt(0, 0, @glow_bitmap, src_rect)
@last_direction = direction
@last_pattern = pattern
end
end
Events.onSpritesetCreate += proc { |_sender,e|
@@ -293,16 +381,23 @@ Events.onSpritesetCreate += proc { |_sender,e|
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]
event = map.events[i]
if event.is_a?(OverworldPokemonEvent)
if event.glow_in_the_dark
spriteset.addUserSprite(LightEffect_PokemonGlow.new(event,viewport,map))
end
end
if event.name[/^outdoorlight\((\w+)\)$/i]
filename = $~[1].to_s
spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i],viewport,map,filename))
elsif map.events[i].name[/^outdoorlight$/i]
spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i],viewport,map))
elsif map.events[i].name[/^light\((\w+)\)$/i]
spriteset.addUserSprite(LightEffect_DayNight.new(event,viewport,map,filename))
elsif event.name[/^outdoorlight$/i]
spriteset.addUserSprite(LightEffect_DayNight.new(event,viewport,map))
elsif event.name[/^light\((\w+)\)$/i]
filename = $~[1].to_s
spriteset.addUserSprite(LightEffect_Basic.new(map.events[i],viewport,map,filename))
elsif map.events[i].name[/^light$/i]
spriteset.addUserSprite(LightEffect_Basic.new(map.events[i],viewport,map))
spriteset.addUserSprite(LightEffect_Basic.new(event,viewport,map,filename))
elsif event.name[/^light$/i]
spriteset.addUserSprite(LightEffect_Basic.new(event,viewport,map))
end
end
spriteset.addUserSprite(Particle_Engine.new(viewport,map))
@@ -91,10 +91,20 @@ end
def pbStartOver(gameover = false)
$game_variables[VAR_CURRENT_GYM_TYPE] = -1
$game_switches[SWITCH_LOCK_PLAYER_MOVEMENT] = false
$game_switches[SWITCH_TEAMED_WITH_ERIKA_SEWERS] = false
if $game_switches[SWITCH_WALLY_CATCHING_POKEMON] || $game_switches[SWITCH_WALLY_GAVE_POKEMON]
$game_switches[SWITCH_DIED_WITH_WALLY] = true
end
$game_switches[SWITCH_CANNOT_CATCH_POKEMON] = false
if Settings::HOENN
$game_switches[SWITCH_RIVAL_ON_MT_CHIMNEY] = false
$game_switches[SWITCH_WAILMER_EGGS_QUEST] = false
$game_variables[]
end
pbBridgeOff
$PokemonTemp.enteredSecretBaseController = nil
clear_all_images()
@@ -133,6 +143,8 @@ def pbStartOver(gameover = false)
$game_temp.player_new_x = $PokemonGlobal.pokecenterX
$game_temp.player_new_y = $PokemonGlobal.pokecenterY
$game_temp.player_new_direction = $PokemonGlobal.pokecenterDirection
adjustWarpCoordinatesExceptions()
if $scene.is_a?(Scene_Map)
$scene.transfer_player
$scene.reset_map(false)
@@ -177,3 +189,15 @@ def pbStartOver(gameover = false)
end
pbEraseEscapePoint
end
def adjustWarpCoordinatesExceptions()
switch_azalea_unflooded = 314
if Settings::KANTO
map_azalea_center_unflooded = 279
map_azalea_center_flooded = 339
if $game_temp.player_new_map_id == map_azalea_center_flooded && $game_switches[switch_azalea_unflooded]
$game_temp.player_new_map_id = map_azalea_center_unflooded
end
end
end
+49 -42
View File
@@ -126,54 +126,63 @@ def pbCheckAllFainted
end
end
# Gather soot from soot grass
def playFootstepSound(sound_file)
volume = rand(25..40)
pitch = rand(90..110)
pbSEPlay(sound_file,volume,pitch)
end
#Stuff that happens when stepping on a tile depending on TerrainTags
#
Events.onStepTakenFieldMovement += proc { |_sender, e|
event = e[0] # Get the event affected by field movement
thistile = $MapFactory.getRealTilePos(event.map.map_id, event.x, event.y)
map = $MapFactory.getMap(thistile[0])
event = e[0]
next unless $scene.is_a?(Scene_Map)
map = $MapFactory.getMapNoAdd(event.map.map_id)
next unless map
terrainTagEffectsOnStep(event, map)
}
def terrainTagEffectsOnStep(event, map)
event.each_occupied_tile do |x, y|
terrain_tag = map.terrain_tag(x, y, true)
next unless terrain_tag
next if terrain_tag.bridge && $PokemonGlobal.bridge == 0
playFootstepSound(terrain_tag.step_sound) if terrain_tag.step_sound && event == $game_player
if terrain_tag.shows_grass_rustle && !event.floating
$scene.spriteset.addUserAnimation(Settings::GRASS_ANIMATION_ID, x, y, true, 1)
end
gatherSootGrass(map, x, y, event) if terrain_tag.id == :SootGrass
end
# Player-only effects: waterfall descent / ice / water-current sliding.
return unless event == $game_player
currentTag = $game_player.pbTerrainTag
if isTerrainWaterfall(currentTag)
pbDescendWaterfall
elsif currentTag.ice && !$PokemonGlobal.sliding
pbSlideOnIce
elsif currentTag.waterCurrent && !$PokemonGlobal.sliding
pbSlideOnWater
end
end
# Erases a soot grass tile once walked over, gathering soot if the walker is
# the player and has a Soot Sack.
def gatherSootGrass(map, x, y, event)
for i in [2, 1, 0]
tile_id = map.data[thistile[1], thistile[2], i]
next if tile_id == nil
tile_id = map.data[x, y, i]
next if tile_id.nil?
next if GameData::TerrainTag.try_get(map.terrain_tags[tile_id]).id != :SootGrass
if event == $game_player && GameData::Item.exists?(:SOOTSACK)
$Trainer.soot += 1 if $PokemonBag.pbHasItem?(:SOOTSACK)
end
# map.data[thistile[1], thistile[2], i] = 0
# $scene.createSingleSpriteset(map.map_id)
playAnimation(SOOT_DUST_ANIMATION, x, y)
map.erase_tile(x, y, i)
break
end
}
end
# Show grass rustle animation, and auto-move the player over waterfalls and ice
Events.onStepTakenFieldMovement += proc { |_sender, e|
event = e[0] # Get the event affected by field movement
if $scene.is_a?(Scene_Map)
event.each_occupied_tile do |x, y|
if $MapFactory.getTerrainTag(event.map.map_id, x, y, true).shows_grass_rustle
$scene.spriteset.addUserAnimation(Settings::GRASS_ANIMATION_ID, x, y, true, 1) unless event.floating
end
end
if event == $game_player
currentTag = $game_player.pbTerrainTag
if isTerrainWaterfall(currentTag)
pbDescendWaterfall
elsif currentTag.ice && !$PokemonGlobal.sliding
pbSlideOnIce
elsif currentTag.waterCurrent && !$PokemonGlobal.sliding
pbSlideOnWater
end
end
end
}
# Events.onStepTakenFieldMovement += proc { |_sender, e|
# event = e[0] # Get the event affected by field movement
# return unless event == $game_player
# currentTag = $game_player.pbTerrainTag
# if currentTag.stairs
# $PokemonSystem.runstyle=0
# end
# }
def isTerrainWaterfall(currentTag)
return currentTag.waterfall_crest || currentTag.waterfall
@@ -196,7 +205,6 @@ def pbOnStepTaken(eventTriggered)
repel_active = isRepelActive()
Events.onStepTaken.trigger(nil)
# Events.onStepTakenFieldMovement.trigger(nil,$game_player)
handled = [nil]
Events.onStepTakenTransferPossible.trigger(nil, handled)
return if handled[0]
@@ -410,7 +418,7 @@ Events.onMapSceneChange += proc { |_sender, e|
break if nosignpost
end
mapinfos = pbLoadMapInfos
oldmapname = mapinfos[$PokemonGlobal.mapTrail[1]].name
oldmapname = mapinfos[$PokemonGlobal.mapTrail[1]]&.name
nosignpost = true if $game_map.name == oldmapname
end
nosignpost = true if $game_switches[SWITCH_AQUA_CAMP] #Camp is split between 2 maps. Don't want the window when in.
@@ -723,7 +731,6 @@ def pbLedge(_xOffset, _yOffset)
end
def sitOnChair()
if $game_player.pbFacingTerrainTag.chair
if $PokemonGlobal.bicycle
bump_into_object
@@ -13,6 +13,11 @@ class PokemonTemp
attr_accessor :encounterType
attr_accessor :evolutionLevels
attr_accessor :battle_npc_used_items
attr_accessor :last_battle_participants
def last_participants
return @last_battle_participants
end
def battleRules
@battleRules = {} if !@battleRules
@@ -175,6 +180,9 @@ def pbPrepareBattle(battle)
# Environment
if battleRules["environment"].nil?
battle.environment = pbGetEnvironment
if Settings::SNOW_DAY && battle.environment == :Grass
battle.environment = GameData::Environment.get(:Snow)
end
else
battle.environment = battleRules["environment"]
end
@@ -657,6 +665,7 @@ def pbTrainerBattleCore(*args)
# 2 - Player lost
# 3 - Player or wild Pokémon ran from battle, or player forfeited the match
# 5 - Draw
pbAfterTrainerBattle(decision, battle)
pbSet(outcomeVar, decision)
return decision
end
@@ -708,6 +717,7 @@ def rematchable_trainer_battle(rematchable_trainers = [], default_level = 50, ca
end
}
loseDialog = trainer_data ? trainer_data.rematch_lose_text : "..."
loseDialog = loseDialog.gsub("<PLAYER_NAME>", $Trainer.name)
npc_trainer = NPCTrainer.new(trainer.trainerName, trainer.trainerType, nil, trainer.custom_appearance)
npc_trainer.lose_text = loseDialog
@@ -942,6 +952,7 @@ Events.onEndBattle += proc { |_sender, e|
pickUpTypeItemSetBonus()
nurseOutfitHeal()
qmarkMaskCheck()
when 2, 5 # Lose, draw
if !canLose
$game_system.bgm_unpause
@@ -951,6 +962,17 @@ Events.onEndBattle += proc { |_sender, e|
end
}
#Called after trainer battles only
def pbAfterTrainerBattle(decision, battle)
battle_participants = battle.list_all_player_participants
$PokemonTemp.last_battle_participants = battle_participants
case decision
when 1# Win
checkObtainClothesAfterBattle(battle.list_all_player_participants) if Settings::HOENN
else
end
end
Events.onWildBattleEnd += proc { |_sender, e|
species = e[0]
result = e[2]
@@ -125,7 +125,12 @@ class PokemonEncounters
#Always check encounter if pokeradar is active
return true if $PokemonTemp.pokeradar != nil && !$PokemonSystem.overworld_encounters
# Get base encounter chance and minimum steps grace period
#safari encounters don't get broken up by fights so only spawn hald the time to tone it down a bit
if $PokemonTemp.overworld_safari
return if rand(2) == 0
end
# Get base encounter chance and minimum steps grace period
encounter_chance = @step_chances[enc_type].to_f
min_steps_needed = (8 - encounter_chance / 10).clamp(0, 8).to_f
# Apply modifiers to the encounter chance and the minimum steps amount
@@ -269,7 +274,9 @@ class PokemonEncounters
baseType = :Land1 if terrain_tag == :Grass_alt1
baseType = :Land2 if terrain_tag == :Grass_alt2
baseType = :Land3 if terrain_tag == :Grass_alt3
baseType = :Land4 if terrain_tag == :Grass_alt4
baseType = :TallGrass if terrain_tag == :TallGrass
baseType = :Puddle if terrain_tag == :Puddle
ret = find_valid_encounter_type_for_time(baseType, time) if !ret
end
if !ret && has_cave_encounters?
@@ -497,9 +504,18 @@ end
# Pokémon (or two) for a triggered wild encounter.
def pbEncounter(enc_type)
$PokemonTemp.encounterType = enc_type
encounter1 = $PokemonEncounters.choose_wild_pokemon(enc_type)
pokeblock = scan_for_nearby_pokeblock
if pokeblock
encounter1 = check_feebas_encounter(20,20,25,enc_type,pokeblock)
unless encounter1
encounter1 = $PokemonEncounters.choose_wild_pokemon(enc_type,3) #Higher chance of rare pokemon when you put down a pokeblock near
end
else
encounter1 = $PokemonEncounters.choose_wild_pokemon(enc_type)
end
encounter1 = EncounterModifier.trigger(encounter1)
return false if !encounter1
if $PokemonEncounters.have_double_wild_battle?
encounter2 = $PokemonEncounters.choose_wild_pokemon(enc_type)
encounter2 = EncounterModifier.trigger(encounter2)
@@ -513,3 +529,42 @@ def pbEncounter(enc_type)
EncounterModifier.triggerEncounterEnd
return true
end
#Feebas can only be caught while fishing with a pokeblock in the water
def check_feebas_encounter(feebas_odds,min_level, max_level, enc_type,pokeblock)
return unless [:GoodRod, :SuperRod].include?(enc_type)
return unless [MAP_ROUTE_119_SOUTH,MAP_ROUTE_119_NORTH].include?($game_map.map_id)
return unless pokeblock && pokeblock.is_a?(PokeblockEvent)
return unless pokeblock.floating
feebas_odds *= 20 if isRaining?
feebas_encounter = rand(100) <= feebas_odds
if feebas_encounter
feebas_level = rand(min_level..max_level)
return [:FEEBAS, feebas_level]
end
end
def scan_for_nearby_pokeblock(px = $game_player.x,py = $game_player.y, scan_radius = 3)
map = $MapFactory.getMapNoAdd($game_map.map_id)
return nil if !map
nearest_event = nil
nearest_distance = nil
$game_map.events.each_value do |event|
next unless event.is_a?(PokeblockEvent)
dx = event.x - px
dy = event.y - py
distance = Math.sqrt(dx * dx + dy * dy)
next if distance > scan_radius
next if nearest_distance && nearest_distance <= distance
nearest_event = event
nearest_distance = distance
end
return nil if nearest_event.nil?
return nearest_event
end
@@ -238,7 +238,11 @@ def pbRoamingPokemonBattle(species, level)
setBattleRule("single")
setBattleRule("roamerFlees")
# Perform the battle
decision = pbWildBattleCore($PokemonGlobal.roamPokemon[idxRoamer])
roamPokemon = $PokemonGlobal.roamPokemon[idxRoamer]
if !roamPokemon.able? #Fallback in case the roamer is fainted for some reason (shouldn't happen but does in rare cases)
roamPokemon.hp =1
end
decision = pbWildBattleCore(roamPokemon)
# Update Roaming Pokémon data based on result of battle
if decision==1 || decision==4 # Defeated or caught
$PokemonGlobal.roamPokemon[idxRoamer] = true
@@ -214,6 +214,13 @@ HiddenMoveHandlers::CanUseMove.add(:CUT, proc { |move, pkmn, showmsg|
next false if !pbCheckHiddenMoveBadge(Settings::BADGE_FOR_CUT, showmsg)
facingEvent = $game_player.pbFacingEvent
if !facingEvent || !facingEvent.name[/cuttree/i]
currentTile = $game_player.getTerrainTag
facingTile = $game_player.pbFacingTerrainTag
cuttable_environments = [:Grass]
currentTile.battle_environment
if cuttable_environments.include?(facingTile.battle_environment) || cuttable_environments.include?(currentTile.battle_environment)
next true
end
pbMessage(_INTL("Can't use that here.")) if showmsg
next false
end
@@ -227,10 +234,94 @@ HiddenMoveHandlers::UseMove.add(:CUT, proc { |move, pokemon|
facingEvent = $game_player.pbFacingEvent
if facingEvent
pbSmashEvent(facingEvent)
else
currentTile = $game_player.getTerrainTag
facingTile = $game_player.pbFacingTerrainTag
cuttable_environments = [:Grass]
if cuttable_environments.include?(facingTile.battle_environment) || cuttable_environments.include?(currentTile.battle_environment)
cutTallGrass
next true
end
end
next true
})
def cutTallGrass
return unless Settings::HOENN
#3*2 rectangle in front of the player (including under the player)
# - - -
# x x -
# o x -
# x x -
# - - -
tiles_to_cut = [[$game_map, $game_player.x, $game_player.y]]
case $game_player.direction
when DIRECTION_RIGHT
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y]
tiles_to_cut << [$game_map, $game_player.x, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x, $game_player.y-1]
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y-1]
tiles_to_cut << [$game_map, $game_player.x+2, $game_player.y]
tiles_to_cut << [$game_map, $game_player.x+2, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x+2, $game_player.y-1]
when DIRECTION_LEFT
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y]
tiles_to_cut << [$game_map, $game_player.x, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x, $game_player.y-1]
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y-1]
tiles_to_cut << [$game_map, $game_player.x-2, $game_player.y]
tiles_to_cut << [$game_map, $game_player.x-2, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x-2, $game_player.y-1]
when DIRECTION_UP
tiles_to_cut << [$game_map, $game_player.x, $game_player.y-1]
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y]
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y]
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y-1]
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y-1]
tiles_to_cut << [$game_map, $game_player.x, $game_player.y-2]
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y-2]
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y-2]
when DIRECTION_DOWN
tiles_to_cut << [$game_map, $game_player.x, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y]
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y]
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y+1]
tiles_to_cut << [$game_map, $game_player.x, $game_player.y+2]
tiles_to_cut << [$game_map, $game_player.x+1, $game_player.y+2]
tiles_to_cut << [$game_map, $game_player.x-1, $game_player.y+2]
end
map = $MapFactory.getMap($game_map.map_id)
erased_tiles = []
for tile in tiles_to_cut
for map_layer in [2, 1, 0]
tile_id = map.data[tile[1], tile[2], map_layer]
cut_tile_id = tile_id -8
next if tile_id == nil
tile_tag = GameData::TerrainTag.try_get(map.terrain_tags[tile_id])
next unless tile_tag.battle_environment == :Grass
map.set_tile(tile[1], tile[2], map_layer,cut_tile_id)
erased_tiles << tile
end
end
unless erased_tiles.empty?
pbSEPlay("Cut", 80)
$scene.spriteset.addUserAnimation(Settings::CUT_TREE_ANIMATION_ID, $game_player.x, $game_player.y, false, 1)
end
end
def pbSmashEvent(event)
return if !event
if event.name[/cuttree/i]
@@ -328,6 +419,7 @@ end
# Dive
#===============================================================================
def pbDive
return
return false if $game_player.pbFacingEvent
map_metadata = GameData::MapMetadata.try_get($game_map.map_id)
return false if !map_metadata || !map_metadata.dive_map_id
@@ -534,6 +626,13 @@ HiddenMoveHandlers::UseMove.add(:FLASH, proc { |move, pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!", pokemon.name, GameData::Move.get(move).name))
end
useFlash()
next true
})
def useFlash
darkness = $PokemonTemp.darknessSprite
return if !darkness || darkness.disposed?
$PokemonGlobal.flashUsed = true
radiusDiff = 8 * 20 / Graphics.frame_rate
while darkness.radius < darkness.radiusMax
@@ -543,8 +642,7 @@ HiddenMoveHandlers::UseMove.add(:FLASH, proc { |move, pokemon|
darkness.radius += radiusDiff
darkness.radius = darkness.radiusMax if darkness.radius > darkness.radiusMax
end
next true
})
end
#===============================================================================
# Fly / Teleport
@@ -585,6 +683,9 @@ def pbFly(move, pokemon)
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!", pokemon.name, GameData::Move.get(move).name))
end
$PokemonGlobal.common_map_entrance_id = nil
$PokemonGlobal.common_map_entrance_position = nil
reset_pokemart_variables
pbFadeOutIn {
$game_temp.player_new_map_id = $PokemonTemp.flydata[0]
$game_temp.player_new_x = $PokemonTemp.flydata[1]
@@ -951,6 +1052,13 @@ Events.onAction += proc { |_sender, _e|
pbSurf
}
#Waterfall
Events.onAction += proc { |_sender, _e|
next unless $PokemonGlobal.surfing
next unless $game_player.pbFacingTerrainTag.waterfall
pbWaterfall
}
# Flowers
Events.onAction += proc { |_sender, _e|
next if !$game_player.pbFacingTerrainTag.flower
@@ -1077,9 +1185,10 @@ def pbSweetScent
end
viewport.dispose
enctype = $PokemonEncounters.encounter_type
if enctype || !$PokemonEncounters.encounter_possible_here? ||
!pbEncounter(enctype)
pbMessage(_INTL("There appears to be nothing here..."))
if enctype || !$PokemonEncounters.encounter_possible_here?
unless pbEncounter(enctype)
pbMessage(_INTL("There appears to be nothing here..."))
end
end
end
@@ -1099,6 +1208,28 @@ HiddenMoveHandlers::CanUseMove.add(:RAINDANCE, proc { |move, pkmn, showmsg|
next true if Settings::GAME_ID == :IF_HOENN
})
HiddenMoveHandlers::CanUseMove.add(:HAIL, proc { |move, pkmn, showmsg|
next true if Settings::GAME_ID == :IF_HOENN
})
HiddenMoveHandlers::UseMove.add(:HAIL, proc { |move, pokemon|
next false unless Settings::EXPERIMENTAL_FEATURES
next false if GameWeather::NO_SNOW_MAPS.include?($game_map.map_id)
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!", pokemon.name, GameData::Move.get(move).name))
end
changeCurrentWeather(:Snow, 1)
next true
})
HiddenMoveHandlers::UseMove.add(:SUNNYDAY, proc { |move, pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!", pokemon.name, GameData::Move.get(move).name))
end
changeCurrentWeather(:Sunny, 1)
next true
})
HiddenMoveHandlers::UseMove.add(:RAINDANCE, proc { |move, pokemon|
if !pbHiddenMoveAnimation(pokemon)
pbMessage(_INTL("{1} used {2}!", pokemon.name, GameData::Move.get(move).name))
@@ -1148,6 +1279,28 @@ HiddenMoveHandlers::UseMove.add(:THUNDER, proc { |move, pokemon|
next true
})
HiddenMoveHandlers::CanUseMove.add(:ROAR, proc { |move, pkmn, showmsg|
next true if $PokemonSystem.overworld_encounters
})
HiddenMoveHandlers::UseMove.add(:ROAR, proc { |move, pokemon|
playAnimation(NOISE_ANIMATION_ID,$game_player.x, $game_player.y)
playCry(pokemon.species)
scareOffWildPokemon(5)
next true
})
HiddenMoveHandlers::CanUseMove.add(:CHATTER, proc { |move, pkmn, showmsg|
next true
})
HiddenMoveHandlers::UseMove.add(:CHATTER, proc { |move, pokemon|
text = pokemon.chatter_text
text = "" unless text
pokemon.chatter_text = pbEnterText(_INTL("Teach a phrase!"),0,16, text)
pokemon.chatter_text = nil if pokemon.chatter_text == ""
next true
})
HiddenMoveHandlers::CanUseMove.add(:MAGNETRISE, proc { |move, pkmn, showmsg|
next true unless $PokemonGlobal.surfing
})
@@ -1173,11 +1326,10 @@ HiddenMoveHandlers::UseMove.add(:SPLASH, proc { |move, pokemon|
pbMessage(_INTL("{1} used {2}!", pokemon.name, GameData::Move.get(move).name))
end
pbSEPlay("jump", 80, 100)
$game_player.jump(0,0)
$game_player.jump(0, 0)
next true
})
HiddenMoveHandlers::CanUseMove.add(:MIST, proc { |move, pkmn, showmsg|
next true if Settings::GAME_ID == :IF_HOENN
})
@@ -1327,12 +1479,7 @@ end
# end
# }
def isFacingTempWaterfall()
return if !$game_temp.temp_waterfall
player_coordinates = [$game_player.x, $game_player.y]
echoln $game_temp.temp_waterfall.include?(player_coordinates)
return $game_temp.temp_waterfall.include?(player_coordinates)
end
HiddenMoveHandlers::CanUseMove.add(:WATERFALL, proc { |move, pkmn, showmsg|
next false if !pbCheckHiddenMoveBadge(Settings::BADGE_FOR_WATERFALL, showmsg)
+19 -9
View File
@@ -19,7 +19,7 @@ ItemHandlers::UseText.copy(:BICYCLE, :RACEBIKE)
#===============================================================================
ItemHandlers::UseFromBag.add(:HONEY, proc { |item|
next 4
next 2
})
ItemHandlers::UseFromBag.add(:ESCAPEROPE, proc { |item|
@@ -28,7 +28,7 @@ ItemHandlers::UseFromBag.add(:ESCAPEROPE, proc { |item|
next 0
end
if ($PokemonGlobal.escapePoint rescue false) && $PokemonGlobal.escapePoint.length > 0
next 4 # End screen and consume item
next 2 # End screen and consume item
end
pbMessage(_INTL("Can't use that here."))
next 0
@@ -87,7 +87,13 @@ ItemHandlers::ConfirmUseInField.add(:ESCAPEROPE, proc { |item|
#===============================================================================
def pbRepel(item, steps)
message = $game_switches[SWITCH_USED_AN_INCENSE] ? "But an incense's effect still lingers from earlier." : "But a repellent's effect still lingers from earlier."
message = $game_switches[SWITCH_USED_AN_INCENSE] ?
_INTL("But an incense's effect still lingers from earlier.") :
_INTL("But a repellent's effect still lingers from earlier.")
if $PokemonGlobal.repel > 0
pbMessage(message)
return 0
end
if $PokemonGlobal.repel > 0
pbMessage(_INTL(message))
return 0
@@ -122,7 +128,7 @@ Events.onStepTaken += proc {
isIncense = $game_switches[SWITCH_USED_AN_INCENSE]
$game_switches[SWITCH_FORCE_ALL_WILD_FUSIONS] = false
$game_switches[SWITCH_USED_AN_INCENSE] = false
itemName = isIncense ? "incense" : "repellent"
itemName = isIncense ? _INTL("incense") : _INTL("repellent")
if $PokemonBag.pbHasItem?(:REPEL) ||
$PokemonBag.pbHasItem?(:SUPERREPEL) ||
$PokemonBag.pbHasItem?(:MAXREPEL) ||
@@ -147,8 +153,10 @@ Events.onStepTaken += proc {
ItemHandlers::UseInField.add(:BLACKFLUTE, proc { |item|
pbUseItemMessage(item)
message = $PokemonMap.blackFluteUsed ? "Wild Pokemon will no longer be repelled." : "Wild Pokémon will be repelled."
pbMessage(_INTL(message))
message = $PokemonMap.blackFluteUsed ?
_INTL("Wild Pokemon will no longer be repelled.") :
_INTL("Wild Pokémon will be repelled.")
pbMessage(message)
$PokemonMap.blackFluteUsed = !$PokemonMap.blackFluteUsed
$PokemonMap.whiteFluteUsed = false
next 1
@@ -156,8 +164,10 @@ ItemHandlers::UseInField.add(:BLACKFLUTE, proc { |item|
ItemHandlers::UseInField.add(:WHITEFLUTE, proc { |item|
pbUseItemMessage(item)
message = $PokemonMap.whiteFluteUsed ? "Wild Pokemon will no longer be lured." : "Wild Pokémon will be lured."
pbMessage(_INTL(message))
message = $PokemonMap.whiteFluteUsed ?
_INTL("Wild Pokemon will no longer be lured.") :
_INTL("Wild Pokémon will be lured.")
pbMessage(message)
$PokemonMap.whiteFluteUsed = !$PokemonMap.whiteFluteUsed
$PokemonMap.blackFluteUsed = false
next 1
@@ -1145,4 +1155,4 @@ ItemHandlers::UseOnPokemon.add(:ABILITYCAPSULE, proc { |item, pkmn, scene|
ItemHandlers::UseFromBag.add(:POKERADAR, proc { |item|
next (pbCanUsePokeRadar?) ? 2 : 0
})
})
+1
View File
@@ -117,6 +117,7 @@ class Pokemon
# Another Pokémon which has been fused with this Pokémon (or nil if there is none).
# Currently only used by Kyurem, to record a fused Reshiram or Zekrom.
# @return [Pokemon, nil] the Pokémon fused into this one (nil if there is none)
attr_accessor :chatter_text
attr_accessor :fused
# @return [Integer] this Pokémon's personal ID
attr_accessor :personalID
@@ -13,6 +13,7 @@ class Pokemon
# Creates a new Move object.
# @param move_id [Symbol, String, Integer] move ID
def initialize(move_id)
@id = GameData::Move.get(move_id).id
@ppup = 0
@pp = total_pp
@@ -47,6 +47,7 @@ class Player < Trainer
attr_accessor :birth_day
attr_accessor :birth_month
attr_accessor :birthdays_celebrated
# @return [Array<Boolean>] the player's Gym Badges (true if owned)
@@ -154,6 +154,7 @@ class HallOfFameSimple_Scene < HallOfFame_Scene
rival.friendship_level = 2
$PokemonGlobal.battledTrainers[BATTLED_TRAINER_RIVAL_KEY] = rival
end
return unless wally
if wally.friendship_level == 0
wally.friendship_level = 1
$PokemonGlobal.battledTrainers[BATTLED_TRAINER_WALLY_KEY] = wally
@@ -122,12 +122,12 @@ PokemonInfiniteFusionFR Discord
Coordinated by anthonygourmand
<title>Chinese Translation
翻译、UI:Leon (Leonnovation)
技术支持:白崎时绘 (Shiroe)
文本参考:阿省呦 (Sheng)
标题图像:未蓝啊 (Weilan)
字体支持:狼人小林 (FusionPixel)
其他支持:小鱼转晴 (XploreLight)
翻译、UI:Leon (Leonnovation)
日语支持:Charlotte (Charlotte)
技术支持:白崎时绘 (Shiroe)
中文Logo:未蓝啊 (Weilan)
字体支持:狼人小林 (FusionPixel)
其他支持:阿省呦 (Sheng) 小鱼转晴 (XploreLight)
The following free resources were also used
with their respective authors' consent:
@@ -76,6 +76,14 @@ locpic_
blood.wolf58 (Willi)
ragzzh
<title>Chinese Translation
翻译、UI:Leon (Leonnovation)
日语支持:Charlotte (Charlotte)
内测反馈:晓夜千羽 (Xion) 风伊布 (Breezeon)
技术支持:白崎时绘 (Shiroe)
中文Logo:未蓝啊 (Weilan)
字体支持:狼人小林 (FusionPixel)
<title>The following free resources were also used
<title>with their respective authors' consent:
+13 -5
View File
@@ -105,6 +105,7 @@ class PokemonPauseMenu
ICON_DEBUG = "menuIcons/DEBUG"
ICON_TITLE = "menuIcons/TITLE"
ICON_QUIT_SAFARI = "menuIcons/SAFARI"
ICON_PC = "menuIcons/PC"
def pbStartPokemonMenu
if !$Trainer
@@ -126,6 +127,7 @@ class PokemonPauseMenu
cmdPokegear = -1
cmdDebug = -1
cmdQuit = -1
cmdPC = -1
cmdEndGame = -1
if $Trainer.has_pokedex && $Trainer.pokedex.accessible_dexes.length > 0
commands[cmdPokedex = commands.length] = " <icon=#{ICON_POKEDEX}> " + _INTL("Pokédex")
@@ -136,11 +138,12 @@ class PokemonPauseMenu
commands[cmdTrainer = commands.length] = " <icon=#{ICON_PLAYER}> " + _INTL("{1}", $Trainer.name)
commands[cmdOutfit = commands.length] = " <icon=#{ICON_OUTFIT}> " + _INTL("Outfit") if $Trainer.can_change_outfit
if pbInSafari?
if Settings::SAFARI_STEPS <= 0
if Settings::SAFARI_STEPS > 0
@scene.pbShowInfo(_INTL("Balls: {1}", pbSafariState.ballcount))
else
@scene.pbShowInfo(_INTL("Steps: {1}/{2}\nBalls: {3}",
pbSafariState.steps, Settings::SAFARI_STEPS, pbSafariState.ballcount))
@scene.pbShowInfo(_INTL("Steps: {1}/{2}\nBalls: {3}", pbSafariState.steps, Settings::SAFARI_STEPS, pbSafariState.ballcount))
end
if $PokemonTemp.overworld_safari
commands[cmdPC = commands.length] = " <icon=#{ICON_PC}> " + _INTL("PC")
end
commands[cmdQuit = commands.length] = " <icon=#{ICON_QUIT_SAFARI}> " + _INTL("Quit")
elsif pbInBugContest?
@@ -238,7 +241,12 @@ class PokemonPauseMenu
elsif cmdOutfit && cmdOutfit >= 0 && command == cmdOutfit
@scene.pbHideMenu
pbCommonEvent(COMMON_EVENT_OUTFIT)
elsif cmdPC >= 0 && command == cmdPC
pbFadeOutIn {
scene = PokemonStorageScene.new
screen = PokemonStorageScreen.new(scene, $PokemonStorage)
screen.pbStartScreen(0) # Boot PC in organize mode
}
elsif cmdQuit >= 0 && command == cmdQuit
@scene.pbHideMenu
if pbInSafari?
+1 -1
View File
@@ -1266,7 +1266,7 @@ class PokemonPartyScreen
isSuperSplicer = [:SUPERSPLICERS,:INFINITESPLICERS2].include?(splicerItem)
echoln index
if pbUnfuse(pokemon,@scene,index, nil)
$PokemonBag.pbDeleteItem(splicerItem, 1) unless splicerItem == :INFINITESPLICERS || splicerItem == :INFINITESPLICER2
$PokemonBag.pbDeleteItem(splicerItem, 1) unless splicerItem == :INFINITESPLICERS || splicerItem == :INFINITESPLICERS2
end
end
+8 -2
View File
@@ -23,7 +23,9 @@ class PokemonSystem
attr_accessor :speedup_speed_battles
attr_accessor :max_nb_sprites_download
attr_accessor :on_mobile
attr_accessor :type_icons
attr_accessor :type_icons_opponent
attr_accessor :type_icons_player
attr_accessor :use_generated_dex_entries
attr_accessor :hide_custom_eggs
attr_accessor :include_alt_sprites_in_random
@@ -38,6 +40,8 @@ class PokemonSystem
attr_accessor :no_pokemon_center
attr_accessor :obtained_transfer_box
attr_accessor :selected_reference_sprite_categories
def initialize
@textspeed = 1 # Text speed (0=slow, 1=normal, 2=fast)
@battlescene = 0 # Battle effects (animations) (0=on, 1=off)
@@ -58,7 +62,9 @@ class PokemonSystem
@download_sprites = 0
@max_nb_sprites_download = 5
@on_mobile = false
@type_icons = true
@type_icons_opponent = true
@type_icons_player = true
@use_generated_dex_entries = true
@hide_custom_eggs = true
@include_alt_sprites_in_random = false
+2 -1
View File
@@ -303,7 +303,8 @@ end
def pbUseKeyItem
moves = [:CUT, :DEFOG, :DIG, :DIVE, :FLASH, :FLY, :ROCKCLIMB,
:ROCKSMASH, :SECRETPOWER, :STRENGTH, :SURF, :SWEETSCENT, :TELEPORT,
:WATERFALL, :WHIRLPOOL, :BOUNCE, :SUNNYDAY, :RAINDANCE, :WHIRLWIND]
:WATERFALL, :WHIRLPOOL, :BOUNCE, :SUNNYDAY, :RAINDANCE, :WHIRLWIND,
:THUNDER, :MAGNETRISE, :SPLASH, :ROAR, :MIST, :DEFOG]
real_moves = []
moves.each do |move|
$Trainer.pokemon_party.each_with_index do |pkmn, i|
@@ -299,6 +299,7 @@ def scanLocalMysteryGifts
skipped_filenames = ["configuration.json", "mkxp.json"]
mystery_gifts = []
Dir.glob("*.json").each do |filename|
echoln filename
next if skipped_filenames.include?(filename)
begin
next if !safeExists?(filename)
@@ -0,0 +1,456 @@
class MultiSelectOptionsScene
attr_reader :selected_items
attr_reader :canceled
SWITCH_FOCUS_BUTTONS = [Input::L, Input::R]
CURSOR_X_OFFSET = -4
ARROW_NORMAL = "Graphics/Pictures/selarrow"
ARROW_ACTIVE = "Graphics/Pictures/selarrow_red"
def initialize(items, preselected = [], title = "Select options",
item_name_proc = nil, filter_placeholder = "Shift to search",
item_weight_proc = nil)
@items = items
@item_name_proc = item_name_proc || proc { |item| item.to_s }
@item_weight_proc = item_weight_proc || proc { |_item| 1 }
@selected_items = preselected.dup
@selected_display_items = []
@focus = :full # :full or :selected
@title_text = title
@filter_placeholder = filter_placeholder
@canceled = false
end
def pbStartScene(window_x = 0, window_y = 0)
title_height = 60
filter_height = 60
left_width = Graphics.width / 2
right_x = window_x + left_width
right_width = Graphics.width - left_width
reference_text = @items.map { |i| @item_name_proc.call(i) }.max_by(&:length) || @filter_placeholder
reference_text = @filter_placeholder if @filter_placeholder.length > reference_text.length
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@sprites = {}
@sprites["title"] = Window_UnformattedTextPokemon.newWithSize(
_INTL(@title_text), window_x, window_y, Graphics.width, title_height, @viewport)
@sprites["filter"] = Window_UnformattedTextPokemon.newWithSize(
reference_text, window_x, window_y + title_height, left_width, filter_height, @viewport)
@sprites["filter"].setTextToFit(reference_text)
@sprites["option"] = Window_MultiSelectFilterList.new(
[], window_x, window_y + title_height + filter_height,
left_width, Graphics.height - (window_y + title_height + filter_height),
@viewport
)
@sprites["option"].active = true
pbSetSystemFont(@sprites["option"].contents)
# Right-side panel: selected items + running total
@sprites["selected_title"] = Window_UnformattedTextPokemon.newWithSize(
"", right_x, window_y + title_height, right_width, filter_height, @viewport)
@sprites["selected_list"] = Window_ReadOnlyList.new(
[], right_x, window_y + title_height + filter_height,
right_width, Graphics.height - (window_y + title_height + filter_height),
@viewport
)
@sprites["selected_list"].active = false
@sprites["selected_list"].index = 0
@arrow_paths = {}
@sprites["cursor"] = IconSprite.new(0, 0, @viewport)
@sprites["cursor"].setBitmap(ARROW_ACTIVE)
@arrow_paths[@sprites["cursor"]] = ARROW_ACTIVE
@sprites["cursor"].z = 99999
@sprites["cursor2"] = IconSprite.new(0, 0, @viewport)
@sprites["cursor2"].setBitmap(ARROW_NORMAL)
@arrow_paths[@sprites["cursor2"]] = ARROW_NORMAL
@sprites["cursor2"].z = 99999
@filterText = ""
@filteredItems = []
refreshList
end
# ---------------------------------------------------------------- cursors
def updateCursorPosition
positionArrow(@sprites["cursor"], @sprites["option"], @focus == :full)
positionArrow(@sprites["cursor2"], @sprites["selected_list"], @focus == :selected)
@sprites["cursor2"].visible = false if @selected_items.empty?
end
def positionArrow(arrow, win, focused)
rect = win.itemRect(win.index)
if rect.width == 0 && rect.height == 0 # index out of visible range
arrow.visible = false
return
end
# Red arrow for the active list, normal arrow for the other
path = focused ? ARROW_ACTIVE : ARROW_NORMAL
if @arrow_paths[arrow] != path
arrow.setBitmap(path)
@arrow_paths[arrow] = path
end
arrow_height = arrow.bitmap ? arrow.bitmap.height : 0
y_center_offset = (win.rowHeight - arrow_height) / 2
arrow.x = win.x + win.startX + rect.x + CURSOR_X_OFFSET
arrow.y = win.y + win.startY + rect.y + y_center_offset
arrow.opacity = focused ? 255 : 110
arrow.visible = true
end
# ---------------------------------------------------------------- focus
def setFocus(focus)
focus = :full if focus == :selected && @selected_items.empty?
@focus = focus
@sprites["option"].active = (@focus == :full)
@sprites["selected_list"].active = (@focus == :selected)
syncFullListToSelected if @focus == :selected
updateCursorPosition
end
def toggleFocus
pbSEPlay("GUI naming tab swap start")
setFocus(@focus == :full ? :selected : :full)
end
def focusLatestSelected
@sprites["selected_list"].index = 0
updateCursorPosition
end
def syncFullListToSelected
item = @selected_display_items[@sprites["selected_list"].index]
return if item.nil?
idx = @filteredItems.index(item)
return if idx.nil? # item is hidden by the current search filter
@sprites["option"].index = itemStartIndex + idx
updateCursorPosition
end
def removeFromSelected(list_index)
item = @selected_display_items[list_index]
return if item.nil?
@selected_items.delete(item)
pbSEPlay("GUI naming tab swap end")
keep_index = @sprites["selected_list"].index
refreshList
max_index = [@selected_items.length - 1, 0].max
@sprites["selected_list"].index = [keep_index, max_index].min
setFocus(:full)
idx = @filteredItems.index(item)
@sprites["option"].index = itemStartIndex + idx if idx
updateCursorPosition
end
# ---------------------------------------------------------------- indices
def cancelIndex; return 0; end
def selectAllIndex; return 1; end
def confirmIndex; return 2; end
def itemStartIndex; return 3; end
# ---------------------------------------------------------------- refresh
def refreshList
filtered = @filterText.empty? ? @items.dup : @items.select { |i|
@item_name_proc.call(i).downcase.include?(@filterText.downcase)
}
@filteredItems = filtered
display = []
flags = []
display.push(_INTL("Cancel"))
flags.push(false)
all_selected = filtered.length > 0 && filtered.all? { |i| @selected_items.include?(i) }
display.push(all_selected ? _INTL("Unselect All") : _INTL("Select All"))
flags.push(false)
display.push(_INTL("Confirm"))
flags.push(false)
filtered.each do |i|
display.push(@item_name_proc.call(i))
flags.push(@selected_items.include?(i))
end
old_index = @sprites["option"].index || 0
@sprites["option"].commands = display
@sprites["option"].selected_flags = flags
@sprites["option"].confirm_index = confirmIndex
@sprites["option"].selall_index = selectAllIndex
@sprites["option"].cancel_index = cancelIndex
@sprites["option"].index = [old_index, display.length - 1].min
@sprites["option"].refresh
@sprites["filter"].text = @filterText.empty? ? @filter_placeholder : @filterText
refreshSelectedPanel
updateCursorPosition
end
def refreshSelectedPanel
total_weight = @selected_items.sum { |i| @item_weight_proc.call(i) }
@sprites["selected_title"].text = _INTL("{1} selected sprites", total_weight)
@selected_display_items = @selected_items.reverse
lines = @selected_display_items.map { |i| @item_name_proc.call(i) }
lines = [_INTL("")] if lines.empty?
old_index = @sprites["selected_list"].index || 0
@sprites["selected_list"].commands = lines
@sprites["selected_list"].index = [old_index, lines.length - 1].min
@sprites["selected_list"].refresh
end
def pbUpdate
pbUpdateSpriteHash(@sprites)
end
# ---------------------------------------------------------------- main loop
def pbOptions
loop do
Graphics.update
Input.update
if SWITCH_FOCUS_BUTTONS.any? { |b| Input.trigger?(b) }
toggleFocus
next
end
if Input.trigger?(Input::ACTION)
pbStartSearchEntry
next
end
if Input.trigger?(Input::BACK)
@canceled = true
break
end
if @focus == :selected
old_index = @sprites["selected_list"].index
@sprites["selected_list"].update
syncFullListToSelected if @sprites["selected_list"].index != old_index
updateCursorPosition
if Input.trigger?(Input::USE)
removeFromSelected(@sprites["selected_list"].index)
end
next
end
# ---- full list focused ----
old_index = @sprites["option"].index
@sprites["option"].update
updateCursorPosition if @sprites["option"].index != old_index
if Input.repeat?(Input::RIGHT)
pbSEPlay("GUI party switch")
scroll_amount = 8
last = @sprites["option"].itemCount - 1
if @sprites["option"].index + scroll_amount >= last
@sprites["option"].index = last
else
@sprites["option"].index += scroll_amount
end
updateCursorPosition
next
end
if Input.repeat?(Input::LEFT)
pbSEPlay("GUI party switch")
scroll_amount = -8
if @sprites["option"].index + scroll_amount <= 0
scrollToConfirm
else
@sprites["option"].index += scroll_amount
end
next
end
if Input.trigger?(Input::USE)
index = @sprites["option"].index
if index == cancelIndex
@canceled = true
break
elsif index == selectAllIndex
all_selected = @filteredItems.length > 0 && @filteredItems.all? { |i| @selected_items.include?(i) }
if all_selected
@selected_items -= @filteredItems
else
@filteredItems.each do |item|
@selected_items << item unless @selected_items.include?(item)
end
end
pbSEPlay("GUI naming confirm")
refreshList
focusLatestSelected
elsif index == confirmIndex
break
else
item = @filteredItems[index - itemStartIndex]
if @selected_items.include?(item)
@selected_items.delete(item)
pbSEPlay("GUI naming tab swap end")
else
@selected_items << item
pbSEPlay("GUI naming confirm")
end
refreshList
focusLatestSelected
end
end
end
end
def scrollToConfirm
@sprites["option"].index = confirmIndex
updateCursorPosition
end
def pbStartSearchEntry
if $PokemonSystem.textinput == 1 # keyboard
scene = PokedexTextEntry.new
else
scene = PokemonEntryScene2.new
end
scene.pbStartScene(
_INTL("Search:"),
0, # min length (0 allows clearing the filter)
30, # max length
@filterText
)
query = scene.pbEntry
scene.pbEndScene
if query
@filterText = query
refreshList
syncFullListToSelected if @focus == :selected
end
end
def pbEndScene
pbPlayCloseMenuSE
pbDisposeSpriteHash(@sprites)
@viewport.dispose
end
end
class MultiSelectOptionScreen
def initialize(scene)
@scene = scene
end
def pbStartScreen(window_x = 0, window_y = 0)
@scene.pbStartScene(window_x, window_y)
@scene.pbOptions
@scene.pbEndScene
return nil if @scene.canceled
return @scene.selected_items
end
end
class Window_MultiSelectFilterList < Window_DrawableCommand
attr_accessor :commands
attr_accessor :selected_flags
attr_accessor :confirm_index
attr_accessor :selall_index
attr_accessor :cancel_index
def initialize(commands, x, y, width, height, viewport = nil)
@commands = commands
@selected_flags = []
@confirm_index = nil
@cancel_index = nil
@selall_index = nil
@selBaseColor = Color.new(48, 96, 216)
@selShadowColor = Color.new(32, 32, 32)
@confirmBaseColor = Color.new(64, 200, 96)
@confirmShadowColor = Color.new(24, 96, 40)
@cancelBaseColor = Color.new(216, 64, 64)
@cancelShadowColor = Color.new(96, 24, 24)
super(x, y, width, height, viewport)
end
def itemCount
return @commands.length
end
def drawCursor(index, rect)
return Rect.new(rect.x + 16, rect.y, rect.width - 16, rect.height)
end
def drawItem(index, _count, rect)
rect = drawCursor(index, rect)
text = @commands[index]
if index == @confirm_index
base, shadow = @confirmBaseColor, @confirmShadowColor
elsif index == @selall_index
base, shadow = @selBaseColor, @selShadowColor
elsif index == @cancel_index
base, shadow = @cancelBaseColor, @cancelShadowColor
elsif @selected_flags[index]
base, shadow = @selBaseColor, @selShadowColor
else
base, shadow = self.baseColor, self.shadowColor
end
pbDrawShadowText(self.contents, rect.x, rect.y, rect.width, rect.height, text, base, shadow)
end
def refresh
self.contents.clear if self.contents
super
end
end
# Used for the "Selected" panel.
class Window_ReadOnlyList < Window_DrawableCommand
attr_accessor :commands
def initialize(commands, x, y, width, height, viewport = nil)
@commands = commands
super(x, y, width, height, viewport)
self.active = false
end
def itemCount
return @commands.length
end
def drawCursor(index, rect)
return Rect.new(rect.x + 16, rect.y, rect.width - 16, rect.height)
end
def drawItem(index, _count, rect)
rect = drawCursor(index, rect)
pbDrawShadowText(self.contents, rect.x, rect.y, rect.width, rect.height,
@commands[index], self.baseColor, self.shadowColor)
end
def refresh
self.contents.clear if self.contents
super
end
end
@@ -455,52 +455,52 @@ class PokemonPokedexInfo_Scene
end
# unused
def getAIDexEntry(pokemonID, name)
begin
head_number = get_head_number_from_symbol(pokemonID).to_s
body_number = get_body_number_from_symbol(pokemonID).to_s
# Ensure the file exists, if not, create it
unless File.exist?(Settings::AI_DEX_ENTRIES_PATH)
File.write(Settings::AI_DEX_ENTRIES_PATH, '{}')
end
json_data = File.read(Settings::AI_DEX_ENTRIES_PATH)
data = HTTPLite::JSON.parse(json_data)
# Check if the entry exists
unless data[head_number] && data[head_number][body_number]
# If not, fetch it from the API
url = Settings::AI_ENTRIES_URL + "?head=#{head_number}&body=#{body_number}"
if !requestRateExceeded?(Settings::AI_ENTRIES_RATE_LOG_FILE, Settings::AI_ENTRIES_RATE_TIME_WINDOW, Settings::AI_ENTRIES_RATE_MAX_NB_REQUESTS)
fetched_entry = clean_json_string(pbDownloadToString(url))
else
echoln "API rate exceeded for AI entries"
end
return nil if !fetched_entry || fetched_entry.empty?
# If the fetched entry is valid, update the JSON and save it
unless fetched_entry.empty?
data[head_number] ||= {}
data[head_number][body_number] = fetched_entry
serialized_data = serialize_json(data)
File.write(Settings::AI_DEX_ENTRIES_PATH, serialized_data)
else
echoln "No AI entry found for Pokemon " + pokemonID.to_s
return nil
end
end
entry = data[head_number][body_number]
entry = entry.gsub(Settings::CUSTOM_ENTRIES_NAME_PLACEHOLDER, name)
entry = entry.gsub("\n", "")
# Unescape any escaped quotes before returning the entry
entry = entry.gsub('\\"', '"')
return clean_json_string(entry)
rescue MKXPError
return nil
end
end
# def getAIDexEntry(pokemonID, name)
# begin
# head_number = get_head_number_from_symbol(pokemonID).to_s
# body_number = get_body_number_from_symbol(pokemonID).to_s
#
# # Ensure the file exists, if not, create it
# unless File.exist?(Settings::AI_DEX_ENTRIES_PATH)
# File.write(Settings::AI_DEX_ENTRIES_PATH, '{}')
# end
#
# json_data = File.read(Settings::AI_DEX_ENTRIES_PATH)
# data = HTTPLite::JSON.parse(json_data)
#
# # Check if the entry exists
# unless data[head_number] && data[head_number][body_number]
# # If not, fetch it from the API
# url = Settings::AI_ENTRIES_URL + "?head=#{head_number}&body=#{body_number}"
# if !requestRateExceeded?(Settings::getAIDexEntry, Settings::AI_ENTRIES_RATE_TIME_WINDOW, Settings::AI_ENTRIES_RATE_MAX_NB_REQUESTS)
# fetched_entry = clean_json_string(pbDownloadToString(url))
# else
# echoln "API rate exceeded for AI entries"
# end
# return nil if !fetched_entry || fetched_entry.empty?
# # If the fetched entry is valid, update the JSON and save it
# unless fetched_entry.empty?
# data[head_number] ||= {}
# data[head_number][body_number] = fetched_entry
# serialized_data = serialize_json(data)
# File.write(Settings::AI_DEX_ENTRIES_PATH, serialized_data)
# else
# echoln "No AI entry found for Pokemon " + pokemonID.to_s
# return nil
# end
# end
#
# entry = data[head_number][body_number]
# entry = entry.gsub(Settings::CUSTOM_ENTRIES_NAME_PLACEHOLDER, name)
# entry = entry.gsub("\n", "")
#
# # Unescape any escaped quotes before returning the entry
# entry = entry.gsub('\\"', '"')
# return clean_json_string(entry)
# rescue MKXPError
# return nil
# end
# end
def pbFindEncounter(enc_types, species)
return false if !enc_types
@@ -1,3 +1,11 @@
class Trainer
attr_accessor :safari_record
end
class Game_Temp
attr_accessor :last_safari_stats
end
class SafariState
attr_accessor :ballcount
attr_accessor :decision
@@ -9,6 +17,7 @@ class SafariState
@inProgress = false
@steps = 0
@decision = 0
@caught_pokemon = []
end
def pbReceptionMap
@@ -19,38 +28,119 @@ class SafariState
return @inProgress
end
def recordLastSafari
$game_temp.last_safari_stats = [@caught_pokemon, @steps]
end
def pbGoToStart
start_map = Settings::KANTO ? 472 : MAP_SAFARI_ENTRANCE
start_x = Settings::KANTO ? 28 : 8
start_y = Settings::KANTO ? 11 : 7
start_direction = Settings::KANTO ? DIRECTION_DOWN : DIRECTION_LEFT
if $scene.is_a?(Scene_Map)
pbFadeOutIn {
$game_temp.player_transferring = true
$game_temp.transition_processing = true
$game_temp.player_new_map_id = 472 #@start[0]
$game_temp.player_new_x = 28#@start[1]
$game_temp.player_new_y = 11#@start[2]
$game_temp.player_new_direction = 2
$game_temp.player_new_map_id = start_map #@start[0]
$game_temp.player_new_x = start_x#@start[1]
$game_temp.player_new_y = start_y#@start[2]
$game_temp.player_new_direction = start_direction
$scene.transfer_player
}
end
pbSafariState.pbEnd
end
def pbStart(ballcount)
@start = [$game_map.map_id,$game_player.x,$game_player.y,$game_player.direction]
@ballcount = ballcount
@inProgress = true
@steps = Settings::SAFARI_STEPS
@steps = Settings::SAFARI_STEPS
end
def pbEnd
recordLastSafari
$PokemonGlobal.encounter_version = 0
@start = nil
@ballcount = 0
@inProgress = false
@steps = 0
@decision = 0
$game_map.need_refresh = true
clear_all_images
pbSafariState.caught_pokemon=nil
disposeBallDisplay
end
end
BALL_ICON_SIZE = 28
BALL_MARGIN = 8
def updateBallDisplay
return if !@inProgress
createBallDisplay if !@ball_sprite || @ball_sprite.disposed?
bmp = @ball_sprite.bitmap
bmp.clear
icon = RPG::Cache.picture("Safari/safariball_ui")
bmp.blt(0, 0, icon, Rect.new(0, 0, icon.width, icon.height))
baseColor = pbColor(:LIGHT_TEXT_MAIN_COLOR)
shadowColor = pbColor(:LIGHT_TEXT_SHADOW_COLOR)
pbSetSystemFont(bmp)
text_x = BALL_ICON_SIZE + 4
pbDrawShadowText(bmp, text_x, 0, -1, -1, "x #{@ballcount}", baseColor, shadowColor)
end
def createBallDisplay
disposeBallDisplay
@ball_viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@ball_viewport.z = 99999
@ball_sprite = Sprite.new(@ball_viewport)
@ball_sprite.bitmap = Bitmap.new(120, BALL_ICON_SIZE)
@ball_sprite.x = BALL_MARGIN
@ball_sprite.y = BALL_MARGIN
end
def disposeBallDisplay
if @ball_sprite
@ball_sprite.bitmap.dispose if @ball_sprite.bitmap && !@ball_sprite.bitmap.disposed?
@ball_sprite.dispose if !@ball_sprite.disposed?
@ball_sprite = nil
end
if @ball_viewport
@ball_viewport.dispose if !@ball_viewport.disposed?
@ball_viewport = nil
end
end
def has_caught_some_pokemon?
return false unless $game_temp.last_safari_stats
return false unless $game_temp.last_safari_stats.size >= 2
return false unless $game_temp.last_safari_stats[0]
return false unless $game_temp.last_safari_stats[1]
return true
end
def tellLatestSafariStats(talking_event_id)
pbCallBub(2, talking_event_id)
pbMessage(_INTL("Welcome back! How was your Safari adventure?"))
return unless has_caught_some_pokemon?
nb_caught = $game_temp.last_safari_stats[0].size
nb_steps = $game_temp.last_safari_stats[1].abs
pbCallBub(2, talking_event_id)
pbMessage(_INTL("You took \\C[1]{1}\\C[0] steps and caught \\C[1]{2}\\C[0] Pokémon!",nb_steps,nb_caught))
$Trainer.safari_record = 0 unless $Trainer.safari_record
if nb_caught > $Trainer.safari_record
pbCallBub(2, talking_event_id)
pbMessage(_INTL("Wow! That's a new personal record. Congratulations!"))
$Trainer.safari_record = nb_caught
else
pbCallBub(2, talking_event_id)
pbMessage(_INTL("I hope you had a lot of fun!"))
end
end
Events.onMapChange += proc { |_sender,*args|
pbSafariState.pbEnd if !pbInSafari?
@@ -69,7 +159,8 @@ def pbInSafari?
end
def is_hardcoded_safari_map(map_id)
safari_maps = [445,74,484,75,485,82,486,107,487,715,718,488,717]
safari_maps = [445,74,484,75,485,82,486,107,487,715,718,488,717] if Settings::KANTO
safari_maps = HOENN_SAFARI_MAPS if Settings::HOENN
return safari_maps.include?(map_id)
end
@@ -82,9 +173,9 @@ end
Events.onStepTakenTransferPossible += proc { |_sender,e|
handled = e[0]
next if handled[0]
if pbInSafari? && pbSafariState.decision==0 && Settings::SAFARI_STEPS > 0
if pbInSafari? && pbSafariState.decision==0
pbSafariState.steps -= 1
if pbSafariState.steps<=0
if pbSafariState.steps==0
pbMessage(_INTL("PA: Ding-dong!\1"))
pbMessage(_INTL("PA: Your safari game is over!"))
pbSafariState.decision = 1
@@ -164,6 +164,7 @@ class PokemonTilesetScene
end
def pbStartScene
current_tag = 0
open_screen
loop do
Graphics.update
@@ -182,17 +183,24 @@ class PokemonTilesetScene
update_cursor_position(0, @visible_height)
elsif Input.trigger?(Input::ACTION)
commands = [
_INTL("Go to bottom"),
_INTL("Change tag"),
_INTL("Go to bottom"),
_INTL("Go to top"),
_INTL("Change tileset"),
_INTL("Cancel")
]
case pbShowCommands(nil, commands, -1)
when 0
update_cursor_position(0, 99999)
selected = tile_ID_from_coordinates(@x, @y)
params = ChooseNumberParams.new
params.setRange(0, 99)
params.setDefaultValue(@tileset.terrain_tags[selected])
current_tag = pbMessageChooseNumber(_INTL("Set the terrain tag."),params)
when 1
update_cursor_position(0, -99999)
update_cursor_position(0, 99999)
when 2
update_cursor_position(0, -99999)
when 3
choose_tileset
end
elsif Input.trigger?(Input::BACK)
@@ -207,15 +215,20 @@ class PokemonTilesetScene
$scene.createSpritesets
end
end
pbMessage(_INTL("To ensure that the changes remain, close and reopen RPG Maker XP."))
pbMessage(_INTL("To ensure that the changes remain, close and reopen RPG Maker XP without saving."))
end
break if pbConfirmMessage(_INTL("Exit from the editor?"))
elsif Input.trigger?(Input::USE)
selected = tile_ID_from_coordinates(@x, @y)
params = ChooseNumberParams.new
params.setRange(0, 99)
params.setDefaultValue(@tileset.terrain_tags[selected])
set_terrain_tag_for_tile_ID(selected, pbMessageChooseNumber(_INTL("Set the terrain tag."), params))
#set_terrain_tag_for_tile_ID(selected, pbMessageChooseNumber(_INTL("Set the terrain tag."), params))
selected_tag = @tileset.terrain_tags[selected]
if selected_tag == current_tag
set_terrain_tag_for_tile_ID(selected, 0)
else
set_terrain_tag_for_tile_ID(selected, current_tag)
end
draw_overlay
end
end
@@ -387,7 +387,7 @@ def pbChooseList(commands, default = 0, cancelValue = -1, sortType = 1)
end
def pbChooseListWithFilter(commands, default = 0, cancelValue = -1, sortType = 1,
window_x = 0, window_y = 0, filter_default_text = "",
window_x = 0, window_y = 0, filter_default_text = _INTL("Select an option"),
width_mode = :filter_text)
filter_height = 60
case width_mode
@@ -114,70 +114,43 @@ def pbAnimName(animation,cmdwin)
end
def pbAnimList(animations,canvas,animwin)
commands=[]
for i in 0...animations.length
animations[i]=PBAnimation.new if !animations[i]
commands[commands.length]="#{i} #{animations[i].name}"
end
cmdwin=pbListWindow(commands,320)
cmdwin.height=416
cmdwin.opacity=224
cmdwin.index=animations.selected
cmdwin.viewport=canvas.viewport
helpwindow=Window_UnformattedTextPokemon.newWithSize(
_INTL("Enter: Load/rename an animation\nEsc: Cancel"),
320,0,320,128,canvas.viewport)
maxsizewindow=ControlWindow.new(0,416,320,32*3)
maxsizewindow.addSlider(_INTL("Total Animations:"),1,2000,animations.length)
maxsizewindow.addButton(_INTL("Resize Animation List"))
maxsizewindow.opacity=224
maxsizewindow.viewport=canvas.viewport
loop do
Graphics.update
Input.update
cmdwin.update
maxsizewindow.update
helpwindow.update
if maxsizewindow.changed?(1)
newsize=maxsizewindow.value(0)
animations.resize(newsize)
commands.clear
for i in 0...animations.length
commands[commands.length]= "#{i} #{animations[i].name}"
end
cmdwin.commands=commands
cmdwin.index=animations.selected
next
commands=[]
for i in 0...animations.length
animations[i]=PBAnimation.new if !animations[i]
commands.push([i, "#{i} #{animations[i].name}", i])
end
if Input.trigger?(Input::USE) && animations.length>0
cmd2=pbShowCommands(helpwindow,[
_INTL("Load Animation"),
_INTL("Rename"),
_INTL("Delete")
],-1)
if cmd2==0 # Load Animation
canvas.loadAnimation(animations[cmdwin.index])
animwin.animbitmap=canvas.animbitmap
animations.selected=cmdwin.index
break
elsif cmd2==1 # Rename
pbAnimName(animations[cmdwin.index],cmdwin)
cmdwin.refresh
elsif cmd2==2 # Delete
if pbConfirmMessage(_INTL("Are you sure you want to delete this animation?"))
animations[cmdwin.index]=PBAnimation.new
cmdwin.commands[cmdwin.index]= "#{cmdwin.index} #{animations[cmdwin.index].name}"
cmdwin.refresh
end
end
end
if Input.trigger?(Input::BACK)
index=pbChooseListWithFilter(commands, animations.selected, -1, 2,
0, 0, _INTL("Search animation..."), :longest_value)
break if !index || index<0 # Cancelled
cmd2=pbShowCommands(nil,[
_INTL("Load Animation"),
_INTL("Rename"),
_INTL("Delete"),
_INTL("Resize Animation List")
],-1)
if cmd2==0 # Load Animation
canvas.loadAnimation(animations[index])
animwin.animbitmap=canvas.animbitmap
animations.selected=index
break
elsif cmd2==1 # Rename
dummy=Struct.new(:commands,:index).new([],0)
pbAnimName(animations[index],dummy)
animations.selected=index
elsif cmd2==2 # Delete
if pbConfirmMessage(_INTL("Are you sure you want to delete this animation?"))
animations[index]=PBAnimation.new
end
animations.selected=index
elsif cmd2==3 # Resize
params=ChooseNumberParams.new
params.setRange(1,2000)
params.setInitialValue(animations.length)
animations.resize(pbMessageChooseNumber(_INTL("Total Animations:"),params))
animations.selected=[animations.selected,animations.length-1].min
end
end
helpwindow.dispose
maxsizewindow.dispose
cmdwin.dispose
end
################################################################################
@@ -941,19 +941,19 @@ DebugMenuCommands.register("terraintags", {
})
# DebugMenuCommands.register("positionsprites", {
# "parent" => "editorsmenu",
# "name" => _INTL("Edit Pokémon Sprite Positions"),
# "description" => _INTL("Reposition Pokémon sprites in battle."),
# "always_show" => true,
# "effect" => proc {
# pbFadeOutIn {
# sp = SpritePositioner.new
# sps = SpritePositionerScreen.new(sp)
# sps.pbStart
# }
# }
# })
DebugMenuCommands.register("positionsprites", {
"parent" => "editorsmenu",
"name" => _INTL("Edit Pokémon Sprite Positions"),
"description" => _INTL("Reposition Pokémon sprites in battle."),
"always_show" => true,
"effect" => proc {
pbFadeOutIn {
sp = SpritePositioner.new
sps = SpritePositionerScreen.new(sp)
sps.pbStart
}
}
})
#
# DebugMenuCommands.register("autopositionsprites", {
# "parent" => "editorsmenu",
@@ -0,0 +1,35 @@
class BstIndex
# entries: [bst, species, legendary?] sorted by bst
def initialize(entries)
@bsts = entries.map { |e| e[0] }
@species = entries.map { |e| e[1] }
end
def empty?
@species.empty?
end
def sample_any
@species.sample
end
def sample_in_range(lo, hi)
first = @bsts.bsearch_index { |b| b >= lo }
return nil if first.nil?
last = @bsts.bsearch_index { |b| b > hi } || @bsts.length
return nil if last <= first
@species[first + rand(last - first)]
end
end
class SpeciesPools
attr_reader :all, :legendary, :normal
def initialize(species_list)
entries = species_list.map { |sp| [calcBaseStatsSum(sp), sp, is_legendary(sp)] }
entries.sort_by! { |e| e[0] }
@all = BstIndex.new(entries)
@legendary = BstIndex.new(entries.select { |e| e[2] })
@normal = BstIndex.new(entries.reject { |e| e[2] })
end
end
@@ -0,0 +1,94 @@
#===============================================================================
# Standalone progress bar, reuses the battle Exp bar graphic
#===============================================================================
class ShuffleProgressBar
MIN_WIDTH = 240
HEIGHT = 56
PADDING = 12
def initialize(text=_INTL("Shuffling..."))
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@barBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/overlay_exp")
@bg = Sprite.new(@viewport)
@bg.bitmap = Bitmap.new(@barBitmap.width + 4, @barBitmap.height + 4)
@bg.bitmap.fill_rect(0, 0, @bg.bitmap.width, @bg.bitmap.height, Color.new(0, 0, 0, 160))
@bg.x = (Graphics.width - @barBitmap.width) / 2 - 40
@bg.y = Graphics.height - 48
@bg.z = 998
@sprite = SpriteWrapper.new(@viewport)
@sprite.bitmap = @barBitmap.bitmap
@sprite.src_rect.width = 0
@sprite.x = ((Graphics.width - @barBitmap.width) / 2) - 100
@sprite.y = Graphics.height - 46
@sprite.z = 999
@text = text
@textSprite = Sprite.new(@viewport)
@textSprite.z = 1000
createTextBitmap(MIN_WIDTH)
drawProgressText(0)
end
def createTextBitmap(width)
@textSprite.bitmap.dispose if @textSprite.bitmap
@textSprite.bitmap = Bitmap.new(width, HEIGHT)
pbSetSystemFont(@textSprite.bitmap)
@textSprite.x = @sprite.x
@textSprite.y = @bg.y - HEIGHT
end
# progress: float from 0.0 to 1.0
def progress=(progress)
progress = 0 if progress < 0
progress = 1 if progress > 1
w = progress * @barBitmap.width
w = ((w / 2).round) * 2
@sprite.src_rect.width = w
drawProgressText(progress)
end
def drawProgressText(progress)
return if !@textSprite || @textSprite.disposed?
pct = sprintf("%.0f%%", progress * 100)
bmp = @textSprite.bitmap
textWidth = bmp.text_size(@text).width
pctWidth = bmp.text_size(pct).width
neededWidth = [textWidth, pctWidth].max + PADDING * 2
neededWidth = MIN_WIDTH if neededWidth < MIN_WIDTH
if bmp.width != neededWidth
createTextBitmap(neededWidth)
bmp = @textSprite.bitmap
end
bmp.clear
textPositions = [
[@text, PADDING, 0, :left, Color.new(255, 255, 255), Color.new(0, 0, 0)],
[pct, PADDING, 24, :left, Color.new(255, 255, 255), Color.new(0, 0, 0)]
]
pbDrawTextPositions(bmp, textPositions)
end
def update
Graphics.update
Input.update
end
def dispose
@textSprite.bitmap.dispose
@textSprite.dispose
@sprite.dispose
@bg.bitmap.dispose
@bg.dispose
@barBitmap.dispose
@viewport.dispose
end
def disposed?
@viewport.disposed?
end
end
+120 -10
View File
@@ -10,6 +10,7 @@ class RandomizerOptionsScene < PokemonOption_Scene
@openWildOptions = false
@openGymOptions = false
@openItemOptions = false
@openReferenceMenu = false
$game_switches[SWITCH_RANDOMIZED_AT_LEAST_ONCE] = true
end
@@ -19,6 +20,9 @@ class RandomizerOptionsScene < PokemonOption_Scene
def pbStartScene(inloadscreen = false)
super
@old_wild_pokemon_options = recordCurrentWildPokemonOptions
@old_trainer_options = recordCurrentTrainerOptions
@changedColor = true
@sprites["title"] = Window_UnformattedTextPokemon.newWithSize(
_INTL("Randomizer settings"), 0, 0, Graphics.width, 64, @viewport)
@@ -26,6 +30,50 @@ class RandomizerOptionsScene < PokemonOption_Scene
pbFadeInAndShow(@sprites) { pbUpdate }
end
def pbEndScene
super
new_wild_pokemon_options = recordCurrentWildPokemonOptions
new_trainer_options = recordCurrentTrainerOptions
wild_pokemon_on = $game_switches[SWITCH_RANDOM_WILD]
trainers_on = $game_switches[SWITCH_RANDOM_TRAINERS]
if wild_pokemon_on && new_wild_pokemon_options != @old_wild_pokemon_options
$PokemonTemp.should_reshuffle_pokemon = true
end
if trainers_on && new_trainer_options != @old_trainer_options
$PokemonTemp.should_reshuffle_pokemon = true
end
end
def recordCurrentWildPokemonOptions
is_on = $game_switches[SWITCH_RANDOM_WILD]
randomness_degree = $game_variables[VAR_RANDOMIZER_WILD_POKE_BST]
type_global = $game_switches[RandomizerWildPokemonOptionsScene::RANDOM_WILD_GLOBAL]
type_area = $game_switches[RandomizerWildPokemonOptionsScene::RANDOM_WILD_AREA]
customs_only = $game_switches[SWITCH_RANDOM_WILD_ONLY_CUSTOMS]
legendaries = $game_switches[SWITCH_RANDOM_WILD_LEGENDARIES]
egg_groups = $game_switches[SWITCH_RANDOM_WILD_EGG_GROUP]
starters = $game_switches[SWITCH_RANDOM_STARTERS]
starters_first_stage = $game_switches[SWITCH_RANDOM_STARTER_FIRST_STAGE]
random_static = $game_switches[RandomizerWildPokemonOptionsScene::RANDOM_STATIC]
gift_pokemon = $game_switches[RandomizerWildPokemonOptionsScene::GIFT_POKEMON]
fuse_everything = $game_switches[RandomizerWildPokemonOptionsScene::REGULAR_TO_FUSIONS]
return [is_on, randomness_degree, type_global, type_area, customs_only, legendaries, egg_groups,
starters, starters_first_stage, random_static, gift_pokemon, fuse_everything]
end
def recordCurrentTrainerOptions
is_on = $game_switches[SWITCH_RANDOM_TRAINERS]
randomness_degree = $game_variables[VAR_RANDOMIZER_TRAINER_BST]
customs_only = $game_switches[RandomizerTrainerOptionsScene::RANDOM_TEAMS_CUSTOM_SPRITES]
egg_groups = $game_switches[SWITCH_RANDOM_TRAINER_EGG_GROUP]
references_filter = $game_switches[SWITCH_RANDOM_REFERENCE_SPRITES]
return [is_on, randomness_degree, customs_only, egg_groups, references_filter]
end
def pbGetOptions(inloadscreen = false)
options = [
EnumOption.new(_INTL("Pokémon"), [_INTL("On"), _INTL("Off")],
@@ -127,6 +175,21 @@ class RandomizerTrainerOptionsScene < PokemonOption_Scene
@changedColor = false
end
def pbEndScene
super
if $game_switches[SWITCH_RANDOM_REFERENCE_SPRITES] && !$game_switches[RANDOM_TEAMS_CUSTOM_SPRITES]
pbMessage(_INTL("\"The References Filter\" option needs the \"Custom Sprites Only\" option to be enabled in order to work."))
if pbConfirmMessage(_INTL("Would you like to turn on the \"Custom Sprites Only\" option?"))
$game_switches[RANDOM_TEAMS_CUSTOM_SPRITES] = true
pbMessage(_INTL("The \"Custom Sprites Only\" option was enabled."))
else
$game_switches[SWITCH_RANDOM_REFERENCE_SPRITES] = false
pbMessage(_INTL("The \"References Filter\" option was disabled."))
end
end
$PokemonTemp.should_reshuffle_trainers = true
end
def pbStartScene(inloadscreen = false)
super
@sprites["option"].nameBaseColor = MessageConfig::BLUE_TEXT_MAIN_COLOR
@@ -156,7 +219,7 @@ class RandomizerTrainerOptionsScene < PokemonOption_Scene
$game_variables[VAR_RANDOMIZER_TRAINER_BST] = value
},
_INTL("The higher the number, the more random it is.")
)
)
end
options << EnumOption.new(_INTL("Custom Sprites only"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[RANDOM_TEAMS_CUSTOM_SPRITES] ? 0 : 1 },
@@ -166,15 +229,39 @@ class RandomizerTrainerOptionsScene < PokemonOption_Scene
_INTL("Use only Pokémon that have custom sprites in trainer teams")
)
# options << EnumOption.new("Allow legendaries", ["On", "Off"],
# proc { $game_switches[SWITCH_RANDOM_TRAINER_LEGENDARIES] ? 0 : 1 },
# proc { |value|
# $game_switches[SWITCH_RANDOM_TRAINER_LEGENDARIES] = value == 0
# }, _INTL("Regular Pokémon can also be randomized into legendaries")
# )
if Settings::HOENN
options << EnumOption.new(_INTL("Egg Groups"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[SWITCH_RANDOM_TRAINER_EGG_GROUP] ? 0 : 1 },
proc { |value|
$game_switches[SWITCH_RANDOM_TRAINER_EGG_GROUP] = value == 0
},
_INTL("Limit to the same egg groups for randomization that feels more natural.")
)
end
options << EnumOption.new(_INTL("References Filter"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[SWITCH_RANDOM_REFERENCE_SPRITES] ? 0 : 1 },
proc { |value|
if !$game_switches[SWITCH_RANDOM_REFERENCE_SPRITES] && value == 0
@openReferenceMenu = true
openReferencesMenu()
end
$game_switches[SWITCH_RANDOM_REFERENCE_SPRITES] = value == 0
},
_INTL("All Trainer teams use reference sprites.")
)
return options
end
def openReferencesMenu()
return unless @openReferenceMenu
pbFadeOutIn {
select_randomizer_references(200)
}
@openReferenceMenu = false
end
end
class RandomizerWildPokemonOptionsScene < PokemonOption_Scene
@@ -207,6 +294,7 @@ class RandomizerWildPokemonOptionsScene < PokemonOption_Scene
super
end
# TODO: Move the randomizer settings to $PokemonGlobal instead of living in game switches
def pbGetOptions(inloadscreen = false)
options = []
if !$game_switches[SWITCH_DURING_INTRO]
@@ -252,13 +340,24 @@ class RandomizerWildPokemonOptionsScene < PokemonOption_Scene
proc { $game_switches[SWITCH_RANDOM_WILD_LEGENDARIES] ? 0 : 1 },
proc { |value|
$game_switches[SWITCH_RANDOM_WILD_LEGENDARIES] = value == 0
},
},
[
_INTL("Regular wild Pokémon can also be randomized into legendaries."),
_INTL("Only legendaries can be randomized into legendaries")
]
)
if Settings::HOENN
options << EnumOption.new(_INTL("Egg Groups"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[SWITCH_RANDOM_WILD_EGG_GROUP] ? 0 : 1 },
proc { |value|
$game_switches[SWITCH_RANDOM_WILD_EGG_GROUP] = value == 0
},
_INTL("Limit to the same egg groups for randomization that feels more natural.")
)
end
options << EnumOption.new(_INTL("Starters"), [_INTL("1st Stage"), _INTL("Any"), _INTL("Off")],
proc {
getStarterRandomizerSelectedOption() },
@@ -274,7 +373,7 @@ class RandomizerWildPokemonOptionsScene < PokemonOption_Scene
$game_switches[SWITCH_RANDOM_STARTERS] = false
$game_switches[SWITCH_RANDOM_STARTER_FIRST_STAGE] = false
end
},
},
[
_INTL("The starters will always be a first evolution Pokémon"),
_INTL("The starters can be any Pokémon"),
@@ -370,7 +469,7 @@ class RandomizerGymOptionsScene < PokemonOption_Scene
proc { $game_switches[SWITCH_RANDOM_GYM_CUSTOMS] ? 0 : 1 },
proc { |value|
$game_switches[SWITCH_RANDOM_GYM_CUSTOMS] = value == 0
},
},
[
_INTL("Use only Pokémon that have custom sprites in gym trainers or gym leader teams"),
_INTL("Pick any possible fusion, including auto-generated sprites.")
@@ -398,6 +497,17 @@ class RandomizerGymOptionsScene < PokemonOption_Scene
}, _INTL("Gym trainers and leaders have a new team each try instead of keeping the same one")
)
# if Settings::HOENN
# options << EnumOption.new(_INTL("Egg Groups"), [_INTL("On"), _INTL("Off")],
# proc { $game_switches[SWITCH_RANDOM_GYM_EGG_GROUP] ? 0 : 1 },
# proc { |value|
# $game_switches[SWITCH_RANDOM_GYM_EGG_GROUP] = value == 0
# },
# _INTL("Limit to the same egg groups for randomization that feels more natural.")
#
# )
# end
return options
end
end
@@ -0,0 +1,80 @@
def select_randomizer_references(minimum_allowed = nil)
references_map = map_sprites_by_reference()
label_to_key = {}
non_ref_list = getNonReferenceSprites(nil, references_map)
references_map["Include non-reference"] = non_ref_list
references_list = references_map.keys.sort_by { |k| [-references_map[k].length, k] }.map do |key|
label = format_reference_for_menu(references_map,key)
label_to_key[label] = key
label
end
current_references = $PokemonSystem.selected_reference_sprite_categories
current_references = references_map.keys if current_references.nil?
formatted_current_references = current_references.map do |reference_key|
format_reference_for_menu(references_map, reference_key)
end.compact
scene = MultiSelectOptionsScene.new(
references_list, formatted_current_references,
_INTL("Select all reference sprites to be included"), nil,
_INTL("Press Shift to search"),
proc { |label| references_map[label_to_key[label]].length }
)
screen = MultiSelectOptionScreen.new(scene)
selected_labels = screen.pbStartScreen
return [] if selected_labels.nil?
selected_keys = selected_labels.map { |label| label_to_key[label] }
total_sprites = 0
selected_keys.each do |key|
sprites = references_map[key]
total_sprites += sprites.length
end
if minimum_allowed && total_sprites < minimum_allowed
pbMessage(_INTL("Warning: The categories you selected only have a total of {1} sprites, and so is likely that you will see repeats during your playthrough.", total_sprites))
pbMessage(_INTL("You can still continue but it is recommended to select at least {1} sprites for a new playthrough.", minimum_allowed))
end
write_selected_references_to_file(selected_keys, references_map)
scene.pbEndScene
$PokemonSystem.selected_reference_sprite_categories = selected_keys
return selected_keys
end
#Util method to export a list - not used by the game itself
def print_reference_map_to_file(references_map)
output_path = "reference_map_ids.txt"
File.open(output_path, "w") do |file|
references_map.keys.sort.each do |reference_id|
file.puts(reference_id)
end
end
rescue => e
echoln("Failed to write reference map to #{output_path}: #{e.message}")
end
def format_reference_for_menu(references_map, key)
return nil unless references_map && references_map.key?(key)
label = "#{titleize(key)} (#{references_map[key].length})"
return label
end
def write_selected_references_to_file(selected_keys, references_map)
output_path = Settings::REFERENCES_FILE_PATH
sprite_names = selected_keys.flat_map { |key| references_map[key] }
File.open(output_path, "w") do |file|
sprite_names.each do |spritename|
file.puts(spritename)
end
end
end# frozen_string_literal: true
@@ -9,6 +9,14 @@ def Kernel.randomizeWildPokemonByRoute()
onlyCustoms = $game_switches[SWITCH_RANDOM_WILD_ONLY_CUSTOMS] && randomizeToFusions
customsList = onlyCustoms ? getCustomSpeciesList() : []
maxSpecies = randomizeToFusions ? PBSpecies.maxValue : NB_POKEMON
# Shared across all routes (only needed for custom sprites)
if onlyCustoms
bst_cache = new_bst_cache
egg_group_cache = new_egg_group_cache
legendary_cache = new_legendary_cache
end
GameData::EncounterRandom::DATA.clear
GameData::Encounter.each do |enc_data|
encounters_hash = {}
@@ -19,8 +27,8 @@ def Kernel.randomizeWildPokemonByRoute()
types_hash = {}
enc_data.types.each do |key, value|
pokemonList = value
newType = randomizePokemonList(pokemonList,bstRange,maxSpecies,onlyCustoms,customsList)
types_hash[key]= newType
newType = randomizePokemonList(pokemonList, bstRange, maxSpecies, onlyCustoms, customsList, bst_cache, egg_group_cache, legendary_cache)
types_hash[key] = newType
end
encounters_hash[:types] = types_hash
GameData::EncounterRandom.register(encounters_hash)
@@ -33,17 +41,27 @@ def Kernel.randomizeWildPokemonByRoute()
end
#input: [[60, :TENTACOOL,5,40, [30, :GOLDEEN, 5, 35], etc.]]
def randomizePokemonList(encountersList,bstRange=50,maxSpecies=NB_POKEMON,customOnly=false,customsList=[])
def randomizePokemonList(encountersList, bstRange = 50, maxSpecies = NB_POKEMON, customOnly = false, customsList = [],
bst_cache = nil, egg_group_cache = nil, legendary_cache = nil)
same_egg_group = $game_switches[SWITCH_RANDOM_WILD_EGG_GROUP]
includeLegendaries = $game_switches[SWITCH_RANDOM_WILD_LEGENDARIES]
newList=[]
if customOnly
bst_cache ||= new_bst_cache
egg_group_cache ||= new_egg_group_cache
legendary_cache ||= new_legendary_cache
end
newList = []
for encounter in encountersList
oldPokemon = encounter[1]
if customOnly
newPokemon = getNewCustomSpecies(oldPokemon,customsList,bstRange,false,includeLegendaries)
newPokemon = getNewCustomSpecies(oldPokemon, customsList, bstRange, false, includeLegendaries, same_egg_group,
bst_cache, egg_group_cache, legendary_cache)
else
newPokemon = getNewSpecies(oldPokemon,bstRange,false,maxSpecies,includeLegendaries)
newPokemon = getNewSpecies(oldPokemon, bstRange, false, maxSpecies, includeLegendaries, same_egg_group)
end
newEntry =[]
newEntry = []
newEntry << encounter[0]
newEntry << getSpecies(newPokemon).species
newEntry << encounter[2]
@@ -54,6 +72,7 @@ def randomizePokemonList(encountersList,bstRange=50,maxSpecies=NB_POKEMON,custom
end
#
# def Kernel.randomizeWildPokemonByRouteOld()
# bstRange = $game_variables[VAR_RANDOMIZER_WILD_POKE_BST]
@@ -140,12 +140,39 @@ def legendaryOk(oldspecies,newspecies,includeLegendaries)
end
def egg_group_ok(oldSpecies_id,newSpecies_id)
oldSpecies = GameData::Species.get(oldSpecies_id)
newSpecies = GameData::Species.get(newSpecies_id)
oldEggGroups = Array(oldSpecies.egg_groups)
newEggGroups = Array(newSpecies.egg_groups)
return oldEggGroups.any? { |g| newEggGroups.include?(g) }
end
def bstNotOk(newspecies, oldPokemonSpecies, bst_range = 50)
newBST = calcBaseStatsSum(newspecies)
originalBST = calcBaseStatsSum(oldPokemonSpecies)
return newBST < originalBST - bst_range || newBST > originalBST + bst_range
end
def legendaryOk_cached(oldspecies, newspecies, includeLegendaries, legendary_cache)
old_legendary = legendary_cache[oldspecies]
return legendary_cache[newspecies] if old_legendary
return true if includeLegendaries
return !legendary_cache[newspecies]
end
def egg_group_ok_cached(oldSpecies_id, newSpecies_id, egg_group_cache)
old_groups = egg_group_cache[oldSpecies_id]
new_groups = egg_group_cache[newSpecies_id]
old_groups.any? { |g| new_groups.include?(g) }
end
def bstNotOk_cached(newspecies, oldPokemonSpecies, bst_range, bst_cache)
newBST = bst_cache[newspecies]
originalBST = bst_cache[oldPokemonSpecies]
newBST < originalBST - bst_range || newBST > originalBST + bst_range
end
def gymLeaderOk(newspecies)
return true if $game_variables[VAR_CURRENT_GYM_TYPE] == -1 #not in a gym
leaderType = getLeaderType()
@@ -281,56 +308,99 @@ def Kernel.pbRandomizeTM()
end
end
def getNewSpecies(oldSpecies, bst_range = 50, ignoreRivalPlaceholder = false, maxDexNumber = PBSpecies.maxValue, includeLegendaries=true)
def getNewSpecies(oldSpecies, bst_range = 50, ignoreRivalPlaceholder = false, maxDexNumber = PBSpecies.maxValue, includeLegendaries=true, same_egg_group=false)
oldSpecies_dex = dexNum(oldSpecies)
return oldSpecies_dex if (oldSpecies_dex == Settings::RIVAL_STARTER_PLACEHOLDER_SPECIES && !ignoreRivalPlaceholder)
return oldSpecies_dex if oldSpecies_dex >= Settings::ZAPMOLCUNO_NB
if $game_switches[SWITCH_LEGENDARY_MODE]
new_species= convert_species_to_legendary(oldSpecies)
newspecies_dex = dexNum(new_species)
return newspecies_dex
new_species = convert_species_to_legendary(oldSpecies)
return dexNum(new_species)
end
newspecies_dex = rand(maxDexNumber - 1) + 1
i = 0
while bstNotOk(newspecies_dex, oldSpecies_dex, bst_range) || !(legendaryOk(oldSpecies_dex,newspecies_dex,includeLegendaries))
newspecies_dex = rand(maxDexNumber - 1) + 1
i += 1
if i % 10 == 0
bst_range += 5
validated = false
until validated
is_valid = true
is_valid = false if bstNotOk(newspecies_dex, oldSpecies_dex, bst_range)
is_valid = false unless legendaryOk(oldSpecies_dex, newspecies_dex, includeLegendaries)
is_valid = false if same_egg_group && !egg_group_ok(oldSpecies_dex, newspecies_dex)
validated = is_valid
unless validated
newspecies_dex = rand(maxDexNumber - 1) + 1
i += 1
bst_range += 5 if i % 10 == 0
end
break if i > 200
end
return newspecies_dex
end
def getNewCustomSpecies(oldSpecies, customSpeciesList, bst_range = 50, ignoreRivalPlaceholder = false,includeLegendaries=true)
#Don't use cache past this point
CUSTOM_LIST_THRESHOLD = 5000
def new_bst_cache
Hash.new { |h, sp| h[sp] = calcBaseStatsSum(sp) }
end
def new_egg_group_cache
Hash.new { |h, sp| h[sp] = Array(GameData::Species.get(sp).egg_groups) }
end
def new_legendary_cache
Hash.new { |h, sp| h[sp] = is_legendary_num(sp) }
end
def getNewCustomSpecies(oldSpecies, customSpeciesList, bst_range, ignoreRivalPlaceholder, includeLegendaries, same_egg_group,
bst_cache = nil, egg_group_cache = nil, legendary_cache = nil, fallback_cache = nil)
if $game_switches[SWITCH_LEGENDARY_MODE]
new_species= convert_species_to_legendary(oldSpecies)
echoln "CHOSEN #{get_readable_fusion_name(oldSpecies)} -> #{get_readable_fusion_name(new_species)}"
newspecies_dex = dexNum(new_species)
return newspecies_dex
return dexNum(convert_species_to_legendary(oldSpecies))
end
oldSpecies_dex = dexNum(oldSpecies)
return oldSpecies_dex if (oldSpecies_dex == Settings::RIVAL_STARTER_PLACEHOLDER_SPECIES && !ignoreRivalPlaceholder)
return oldSpecies_dex if oldSpecies_dex >= Settings::ZAPMOLCUNO_NB
i = rand(customSpeciesList.length - 1) + 1
n = 0
newspecies_dex = customSpeciesList[i]
while bstNotOk(newspecies_dex, oldSpecies_dex, bst_range) || !(legendaryOk(oldSpecies_dex,newspecies_dex,includeLegendaries))
i = rand(customSpeciesList.length - 1) #+1
newspecies_dex = customSpeciesList[i]
n += 1
if n % 10 == 0
bst_range += 5
end
#when cache not passed as argument: initialize
bst_cache ||= new_bst_cache
egg_group_cache ||= new_egg_group_cache
legendary_cache ||= new_legendary_cache
fallback_cache ||= {}
ok = lambda do |sp, range|
!bstNotOk_cached(sp, oldSpecies_dex, range, bst_cache) &&
legendaryOk_cached(oldSpecies_dex, sp, includeLegendaries, legendary_cache) &&
(!same_egg_group || egg_group_ok_cached(oldSpecies_dex, sp, egg_group_cache))
end
return newspecies_dex
# Fast path: random picks (works great when the list is big)
range = bst_range
100.times do |n|
sp = customSpeciesList.sample
return sp if ok.call(sp, range)
range += 5 if (n + 1) % 10 == 0
end
# Slow path (rare with big lists, cheap with small ones): full filter, cached per old species
key = [oldSpecies_dex, bst_range, includeLegendaries, same_egg_group]
candidates = fallback_cache[key]
if candidates.nil?
range = bst_range
candidates = []
10.times do
candidates = customSpeciesList.select { |sp| ok.call(sp, range) }
break unless candidates.empty?
range += 5
end
candidates = customSpeciesList if candidates.empty?
fallback_cache[key] = candidates
end
candidates.sample
end
def playShuffleSE(i)
@@ -351,36 +421,56 @@ end
def Kernel.pbShuffleTrainers(bst_range = 50, customsOnly = false, customsList = nil)
bst_range = pbGet(VAR_RANDOMIZER_TRAINER_BST)
if customsOnly && customsList == nil
customsOnly = false
end
customsOnly = false if customsOnly && customsList == nil
randomTrainersHash = Hash.new
# Create the bar BEFORE any heavy work so the screen updates immediately
progress_bar = ShuffleProgressBar.new(_INTL("Shuffling Trainers..."))
update_progress_bar(progress_bar, 0, 1)
trainers_data = getTrainersDataMode.list_all
trainers_data.each do |key, value|
trainer = trainers_data[key]
#echoln "------"
#echoln "Processing [#{trainer.id}#] {trainer.trainer_type} ##{trainer.real_name}"
begin
trainers_data = getTrainersDataMode.list_all
bst_cache = new_bst_cache
egg_group_cache = new_egg_group_cache
legendary_cache = new_legendary_cache
fallback_cache = {}
total = trainers_data.size
i = 0
new_party = []
for poke in trainer.pokemon
old_poke = GameData::Species.get(poke[:species]).id_number
new_poke = customsOnly ? getNewCustomSpecies(old_poke, customsList, bst_range) : getNewSpecies(old_poke, bst_range)
new_party << new_poke
end
randomTrainersHash[trainer.id] = new_party
playShuffleSE(i)
i += 1
if i % 2 == 0
n = (i.to_f / trainers.length) * 100
Kernel.pbMessageNoSound(_INTL("\\ts[]Shuffling trainers...\\n {1}%\\^", sprintf('%.2f', n), PBSpecies.maxValue))
trainers_data.each do |key, value|
trainer = trainers_data[key]
new_party = []
same_egg_group = $game_switches[SWITCH_RANDOM_TRAINERS]
for poke in trainer.pokemon
old_poke = GameData::Species.get(poke[:species]).id_number
new_poke = customsOnly ?
getNewCustomSpecies(old_poke, customsList, bst_range, false, true, same_egg_group, bst_cache, egg_group_cache, legendary_cache, fallback_cache) :
getNewSpecies(old_poke, bst_range, false, PBSpecies.maxValue, true, same_egg_group)
new_party << new_poke
end
randomTrainersHash[trainer.id] = new_party
i += 1
if i % 20 == 0 || i == total
playShuffleSE(i)
update_progress_bar(progress_bar, i, total)
end
end
ensure
progress_bar.dispose
end
$PokemonGlobal.randomTrainersHash = randomTrainersHash
$PokemonTemp.should_reshuffle_trainers = false
end
def update_progress_bar(progress_bar, nb_processed, nb_to_process)
return if !progress_bar || progress_bar.disposed?
progress_bar.progress = nb_processed.to_f / nb_to_process
progress_bar.update
end
# def Kernel.pbShuffleTrainers(bst_range = 50)
# randomTrainersHash = Hash.new
#
@@ -407,16 +497,24 @@ def Kernel.pbShuffleTrainersCustom(bst_range = 50)
bst_range = pbGet(VAR_RANDOMIZER_TRAINER_BST)
Kernel.pbMessage(_INTL("Parsing custom sprites folder...\\wtnp[20]"))
customsList = getCustomSpeciesList(true, true)
reference_sprites = $game_switches[SWITCH_RANDOM_REFERENCE_SPRITES]
if reference_sprites
reference_sprites_list = getSelectedReferenceSprites
$PokemonTemp.selected_reference_sprites = reference_sprites_list
customsList = getSelectedReferenceSpeciesList(reference_sprites_list)
else
customsList = getCustomSpeciesList(true, true)
end
Kernel.pbMessage(_INTL("{1} sprites found. Shuffling...\\wtnp[20]", customsList.length.to_s))
if customsList.length == 0
Kernel.pbMessage(_INTL("To use custom sprites, please place correctly named sprites in the /CustomBattlers folder. See readMe.txt for more information."))
Kernel.pbMessage(_INTL("Trainer Pokémon will include auto-generated sprites."))
return Kernel.pbShuffleTrainers(bst_range)
elsif customsList.length < 200
elsif customsList.length < 100 && ! $game_switches[SWITCH_RANDOM_REFERENCE_SPRITES]
if Kernel.pbConfirmMessage(_INTL("Too few custom sprites were found. This will result in a very low Pokémon variety for trainers. Would you like to disable the Custom Sprites only option?"))
Kernel.pbMessage(_INTL("Trainer Pokémon will include auto-generated sprites."))
Kernel.pbMessage(_INTL("Trainer Pokémon may also include auto-generated sprites."))
return Kernel.pbShuffleTrainers(bst_range) ##use regular shuffle if not enough sprites
end
if Kernel.pbConfirmMessage(_INTL("This will result in a very low Pokémon variety for trainers. Continue anyway?"))
@@ -426,6 +524,7 @@ def Kernel.pbShuffleTrainersCustom(bst_range = 50)
return Kernel.pbShuffleTrainers(bst_range) ##use regular shuffle if not enough sprites
end
end
Kernel.pbShuffleTrainers(bst_range, true, customsList)
end
@@ -493,7 +592,40 @@ def getCustomSpeciesList(allowOnline = true, redownload_file = false)
return speciesList
end
def getNonReferenceSprites(full_list, references_map = nil)
full_list = getCustomSpeciesList(false, false) unless full_list
references_map = map_sprites_by_reference() unless references_map
referenced = {}
references_map.each_value do |sprites|
sprites.each { |sprite| referenced[sprite] = true }
end
full_list.reject { |sprite| referenced.key?(sprite) }
return full_list
end
def getSelectedReferenceSprites
spritesList = []
path = Settings::REFERENCES_FILE_PATH
return spritesList if !File.exist?(path)
File.foreach(path) do |line|
spritename = line.chomp
spritesList << spritename if !spritename.empty?
end
return spritesList
end
def getSelectedReferenceSpeciesList(spriteslist)
species_id_list = []
for file in spriteslist
dexnum = getDexNumFromFilename(file)
species_id_list << dexnum
end
return species_id_list
end
def is_file_alt(file)
filename = file.split(".")[0]
+123 -47
View File
@@ -6,6 +6,15 @@ LEGENDARIES_LIST = [:ARTICUNO, :ZAPDOS, :MOLTRES, :MEWTWO, :MEW,
:GENESECT, :RESHIRAM, :ZEKROM, :KYUREM, :MELOETTA_A,:MELOETTA_P,
:NECROZMA, :U_NECROZMA, :DIANCIE]
class PokemonTemp
attr_accessor :should_reshuffle_trainers
attr_accessor :should_reshuffle_pokemon
attr_accessor :should_reshuffle_items
attr_accessor :should_reshuffle_gyms
end
class PokemonGlobalMetadata
attr_accessor :psuedoHash
attr_accessor :psuedoBSTHash
@@ -42,79 +51,145 @@ end
def get_randomized_bst_hash(poke_list, bst_range, show_progress = true)
bst_hash = Hash.new
msg = ""
progress_bar = ShuffleProgressBar.new(_INTL("Shuffling wild Pokémon...")) if show_progress
for i in 1..NB_POKEMON
show_shuffle_progress(i) if show_progress
show_shuffle_progress(progress_bar, i, NB_POKEMON) if progress_bar
baseStats = getBaseStatsFormattedForRandomizer(i)
statsTotal = getStatsTotal(baseStats)
targetStats_max = statsTotal + bst_range
targetStats_min = statsTotal - bst_range
max_bst_allowed = targetStats_max
min_bst_allowed = targetStats_min
#if a match, add to hash, remove from array, and cycle to next poke in dex
max_bst_allowed = statsTotal + bst_range
min_bst_allowed = statsTotal - bst_range
#only randomize legendaries to legendaries if Allow Legendaries not enabled
#
#
# if !$game_switches[SWITCH_RANDOM_WILD_LEGENDARIES]
# current_species = GameData::Species.get(i).id
# random_poke_species = GameData::Species.get(random_poke).id
# next if !legendaryOk(current_species,random_poke_species,$game_switches[SWITCH_RANDOM_WILD_LEGENDARIES])
#
# if !is_legendary(current_species)
# next if is_legendary(random_poke_species,true)
# else
# next if !is_legendary(random_poke_species,true)
# end
# end
playShuffleSE(i)
random_poke = poke_list.sample
random_poke_bst = getStatsTotal(getBaseStatsFormattedForRandomizer(random_poke))
j = 0
includeLegendaries = $game_switches[SWITCH_RANDOM_WILD_LEGENDARIES]
current_species = GameData::Species.get(i).id
random_poke_species = GameData::Species.get(random_poke).id
while (random_poke_bst <= min_bst_allowed || random_poke_bst >= max_bst_allowed) || !legendaryOk(current_species,random_poke_species,includeLegendaries)
random_poke = poke_list.sample
random_poke_species = GameData::Species.get(random_poke).id
#todo: right now, the main function uses dex numbers, but the legendaryOK check needs the ids.
# This can be a hit on performance to recalculate the ids from the dex numbers.
# The function should be optimized to just use the ids everywhere
same_egg_group = $game_switches[SWITCH_RANDOM_WILD_EGG_GROUP]
current_species_data = GameData::Species.get(i)
current_species = current_species_data.id
current_egg_groups = Array(current_species_data.egg_groups)
j = 0
loop do
random_poke = poke_list.sample
random_poke_species_data = GameData::Species.get(random_poke)
random_poke_species = random_poke_species_data.id
random_poke_bst = getStatsTotal(getBaseStatsFormattedForRandomizer(random_poke))
if same_egg_group
random_poke_egg_groups = Array(random_poke_species_data.egg_groups)
egg_group_ok = random_poke_egg_groups.any? { |g| current_egg_groups.include?(g) }
else
egg_group_ok = true
end
bst_ok = random_poke_bst > min_bst_allowed && random_poke_bst < max_bst_allowed
legendary_ok = legendaryOk(current_species, random_poke_species, includeLegendaries)
j += 1
if j % 5 == 0 #to avoid infinite loops if can't find anything
if j % 5 == 0
min_bst_allowed -= 1
max_bst_allowed += 1
end
if egg_group_ok && bst_ok && legendary_ok
msg += "#{current_species_data.species} (#{current_species_data.egg_groups})-> #{random_poke_species_data.species} (#{random_poke_species_data.egg_groups})\n"
bst_hash[i] = random_poke
break
end
end
bst_hash[i] = random_poke
end
progress_bar.dispose if progress_bar
Input.clipboard = msg if $DEBUG
return bst_hash
end
def is_legendary(dex_num,printInfo=false)
pokemon_id = getPokemon(dex_num).id
is_legendary = is_fusion_of_any(pokemon_id,LEGENDARIES_LIST)
#echoln "#{pokemon_id} is legendary? : #{is_legendary}"
#echoln "{1} ({2}) {3}",dex_num,pokemon_id,is_legendary) if printInfo
return is_legendary
LEGENDARY_LOOKUP = {}
LEGENDARIES_LIST.each { |sp| LEGENDARY_LOOKUP[sp] = true }
def is_legendary(dex_num)
if dex_num.is_a?(Integer)
return is_legendary_num(dex_num)
end
id = getPokemon(dex_num).id
if species_is_fusion(id)
LEGENDARY_LOOKUP.key?(get_body_species_from_symbol(id)) ||
LEGENDARY_LOOKUP.key?(get_head_species_from_symbol(id))
else
LEGENDARY_LOOKUP.key?(id)
end
end
def show_shuffle_progress(i)
if i % 2 == 0
n = (i.to_f / NB_POKEMON) * 100
Kernel.pbMessageNoSound(_INTL("\\ts[]Shuffling wild Pokémon...\\n {1}%\\^", sprintf('%.2f', n), NB_POKEMON))
def legendary_nums
$legendary_nums ||= begin
h = {}
LEGENDARIES_LIST.each { |sym| h[GameData::Species.get(sym).id_number] = true }
h
end
end
def is_legendary_num(dex)
if dex <= NB_POKEMON
legendary_nums.key?(dex)
else
legendary_nums.key?(dex / NB_POKEMON) || legendary_nums.key?(dex % NB_POKEMON)
end
end
def build_species_cache(species_ids)
bst_cache = {}
legendary_cache = {}
egg_group_cache = {}
species_ids.each do |id|
next if bst_cache.key?(id)
bst_cache[id] = calcBaseStatsSum(id)
legendary_cache[id] = is_legendary(id)
sp = GameData::Species.get(id)
egg_group_cache[id] = Array(sp.egg_groups)
end
[bst_cache, legendary_cache, egg_group_cache]
end
def show_shuffle_progress(progress_bar, nb_processed, nb_to_process)
return if !progress_bar || progress_bar.disposed?
progress_bar.progress = nb_processed.to_f / nb_to_process
progress_bar.update
# if i % 2 == 0
# n = (i.to_f / NB_POKEMON) * 100
# Kernel.pbMessageNoSound(_INTL("\\ts[]Shuffling wild Pokémon...\\n {1}%\\^", sprintf('%.2f', n), NB_POKEMON))
# end
end
#equivalent of common event 28 (APPLY randomizer options)
def reshuffleWithCurrentSettings()
if $PokemonTemp.should_reshuffle_pokemon
bst = pbGet(VAR_RANDOMIZER_WILD_POKE_BST)
if $game_switches[SWITCH_RANDOM_WILD_TO_FUSION]
type = 1
else
type = nil
end
Kernel.initRandomTypeArray
Kernel.pbShuffleDex(bst,type, true)
end
if $PokemonTemp.should_reshuffle_trainers
if $game_switches[SWITCH_RANDOM_TRAINERS_CUSTOMS_ONLY]
Kernel.pbShuffleTrainersCustom
else
Kernel.pbShuffleTrainers
end
end
end
##############
# randomizer shuffle
# ##############
def Kernel.pbShuffleDex(range = 50, type = 0)
def Kernel.pbShuffleDex(range = nil, type = nil, force_reshuffle=true)
range = 50 unless range
type = 0 unless type
return if $PokemonGlobal.psuedoBSTHash && !force_reshuffle
$game_switches[SWITCH_RANDOMIZED_AT_LEAST_ONCE] = true
#type 0: BST
@@ -127,7 +202,8 @@ def Kernel.pbShuffleDex(range = 50, type = 0)
if !pokemon_list #when not enough custom sprites
pokemon_list = get_pokemon_list(should_include_fusions)
end
$PokemonGlobal.psuedoBSTHash = get_randomized_bst_hash(pokemon_list, range, should_include_fusions)
$PokemonGlobal.psuedoBSTHash = get_randomized_bst_hash(pokemon_list, range, true)
$PokemonTemp.should_reshuffle_pokemon = false
end
def itemCanBeRandomized(item)
@@ -23,7 +23,7 @@ end
def filter_clothes_only_not_owned(clothes_ids_list)
filtered_list = []
clothes_ids_list.each do|clothe_id|
filtered_list << clothe_id if !$Trainer.unlocked_clothes.include?(clothe_id)
filtered_list << clothe_id unless $Trainer.unlocked_clothes.include?(clothe_id)
end
return filtered_list
end
+1 -1
View File
@@ -30,7 +30,7 @@ CLOTHES_GRASS = "grassexpert"
CLOTHES_ELECTRIC = "urbanelectric"
CLOTHES_PSYCHIC_M = "psyshamanm"
CLOTHES_PSYCHIC_M = "psyshaman"
CLOTHES_PSYCHIC_F = "psyshamanf"
CLOTHES_ICE = "iceoutfit"
+32
View File
@@ -63,6 +63,8 @@ CLOTHES_LADY = "lady"
CLOTHES_PSYSHAMAN_M = "psyshaman"
CLOTHES_PSYSHAMAN_F = "psyshamanf"
CLOTHES_ZUBAT_KID = "zubatkidcostume"
HAT_ZUBAT_KID = "zubatkidmask"
CLOTHES_SWIMMING_M = "BlackSwimTrunks"
CLOTHES_SAILOR = "WingullOutfit"
@@ -98,8 +100,20 @@ HAT_POOCHYENA_MASK = "PoochyenaHead"
HAT_LOTAD_MASK = "LotadHead"
HAT_ZIGZAGOON_MASK = "ZigzagoonHead"
HAT_WURMPLE_MASK = "WurmpleHead"
HAT_SEEDOT_MASK = "SeedotHead"
HAT_TAILLOW_MASK = "TaillowHead"
HAT_TREECKO_MASK = "TreeckoHead"
HAT_MUDKIP_MASK = "MudkipHead"
HAT_PARTY_1 = "partywurmple"
HAT_PARTY_2 = "partygostripes"
HAT_PARTY_3 = "partygopolka"
HAT_PARTY_4 = "partyhatennaspots"
HAT_PARTY_5 = "partysmashstars"
HAT_PARTY_6 = "partyanimestripes"
HAT_PARTY_7 = "partyanimespots"
HAT_DUSKULL_MASK = "duskullmask"
HAT_SLEEPMASK = "sleepmask"
HAT_DITTO_MASK = "creepydittomask"
@@ -128,6 +142,9 @@ HAT_CLOWN = "clownnose"
HAT_WHITE_HAND = "whitehand"
HAT_COFFEE = "cupofcoffee"
HAT_GOGOGGLES = "gogoggles"
HAT_BREEDER_1 = "breedervisor"
HAT_BREEDER_2 = "breederbandana"
HAT_BREEDER_2_2 = "PKMBreeder"
@@ -144,6 +161,9 @@ FUSION_HAT = "fusionnerd"
FUSION_OUTFIT = "fusionnerd"
HAT_ASH = "ash"
CLOTHES_ASH = "ash"
CLOTHES_ASH_2 = "ash_b"
HAT_BIANCA = "bianca"
HAT_CLEFAIRY = "clefairyearheadband"
HAT_FLOWER = "mikufairy"
@@ -167,11 +187,21 @@ HAT_NURSE_BLANK = "nursejoy"
HAT_NURSE = "nursejoyhat"
HAT_TRUMPET = "trumpet"
HAT_CRADILY = "cradiclava"
HAT_BIKE = "Bikingvolthelmet"
CLOTHES_BIKE = "Bikingvolt"
HAT_GYM_REWARD_1 = Settings::KANTO ? "brockpan" : "aronmask"
HAT_GYM_REWARD_2 = Settings::KANTO ? "starmieclip" : "brawlyshades"
HAT_GYM_REWARD_3 = Settings::KANTO ? "surgeglasses" : "magnemitepin"
HAT_GYM_REWARD_4 = Settings::KANTO ? "erikaHeadband" : "flannerybeanie"
HAT_GYM_REWARD_5 = Settings::KANTO ? "kogascarf" : "eeveeears"
HAT_GYM_REWARD_5_HOENN_M = "brendanE"
HAT_GYM_REWARD_5_HOENN_F = "brendanE"
HAT_GYM_REWARD_6 = Settings::KANTO ? "sabrinasballs" : "winona"
HAT_GYM_REWARD_7 = Settings::KANTO ? "blaineGlasses" : "sabrinasballs"
HAT_GYM_REWARD_8 = Settings::KANTO ? "giovannifedora" : "starmieclip"
@@ -237,6 +267,8 @@ HAIR_JASMINE = "jasmine" # does not exist yet
HAIR_ROXANNE = "roxanne"
HAIR_BRAWLY = "brawly"
HAIR_WATTSON = "wattson"
HAIR_FLANNERY = "flannery"
HAIR_NORMAN = "norman"
HAIR_HOOH = "ho-oh"
HAIR_CRESSELIA = "lunarbob"
@@ -2,7 +2,7 @@ class ClothesShopView < PokemonMart_Scene
def initialize(currency_name = _INTL("Money"))
@currency_name = currency_name
@currency_name = COSMETIC_CURRENCY_NAME if Settings::HOENN
@currency_name = get_cosmetic_currency_name if Settings::HOENN
end
def pbStartBuyOrSellScene(buying, stock, adapter)
@@ -50,7 +50,7 @@ class HairMartAdapter < OutfitsMartAdapter
def toggleText()
text = ""
#text << "Color: R, \n"
text << "Toggle Hat: D\n"
text << _INTL("Toggle Hat: D\n")
end
@@ -161,7 +161,7 @@ class HairMartAdapter < OutfitsMartAdapter
def getSpecialItemCaption(specialType)
case specialType
when :SWAP_COLOR
return "Swap Color"
return _INTL("Swap Color")
end
return nil
end
@@ -183,7 +183,7 @@ class HairMartAdapter < OutfitsMartAdapter
end
def getSpecialItemDescription(specialType)
return "Swap to the next base hair color."
return _INTL("Swap to the next base hair color.")
end
def doSpecialItemAction(specialType)
+8 -8
View File
@@ -101,20 +101,20 @@ TYPE_EXPERT_REWARDS = {
:NORMAL => [CLOTHES_NORMAL],
}
TOTAL_NB_TYPE_EXPERTS = 14
TOTAL_NB_TYPE_EXPERTS = 18
def type_expert_battle(type_id)
type = GameData::Type.get(type_id)
pbCallBub(2, @event_id)
pbMessage(_INTL("Ah! Can you feel the energy in here? This place is great for {1}-Pokémon!", type.real_name))
pbMessage(_INTL("Ah! Can you feel the energy in here? This place is great for {1}-Pokémon!", type.name))
pbCallBub(2, @event_id)
pbMessage(_INTL("I'm what you could call an expert on {1}-Pokémon. I've grown with them for all of my life.", type.real_name))
pbMessage(_INTL("I'm what you could call an expert on {1}-Pokémon. I've grown with them for all of my life.", type.name))
pbCallBub(2, @event_id)
pbMessage(_INTL("I'll give you my \\C[5]special outfit\\C[0] if you can defeat my team using only {1}-Pokémon. ", type.real_name))
pbMessage(_INTL("I'll give you my \\C[5]special outfit\\C[0] if you can defeat my team using only {1}-Pokémon. ", type.name))
pbCallBub(2, @event_id)
if pbConfirmMessage(_INTL("Do you think you can handle that?"))
pbCallBub(2, @event_id)
pbMessage(_INTL("Select your team! Remember, only {1}-type Pokémon are allowed!", type.real_name))
pbMessage(_INTL("Select your team! Remember, only {1}-type Pokémon are allowed!", type.name))
gym_randomizer_index = GYM_TYPES_CLASSIC.index(type_id)
echoln gym_randomizer_index
@@ -140,7 +140,7 @@ def type_expert_battle(type_id)
obtainClothes(clothes)
end
pbCallBub(2, @event_id)
pbMessage(_INTL("When you wear it, you can sometimes find {1}-type related items after battles!", type.real_name))
pbMessage(_INTL("When you wear it, you can sometimes find {1}-type related items after battles!", type.name))
show_nb_type_experts_defeated()
PokemonSelection.restore
$game_switches[Settings::OVERRIDE_BATTLE_LEVEL_SWITCH] = false
@@ -150,7 +150,7 @@ def type_expert_battle(type_id)
end
else
pbCallBub(2, @event_id)
pbMessage(_INTL("Remember, you're only allowed to use {1}-type Pokémon!", type.real_name))
pbMessage(_INTL("Remember, you're only allowed to use {1}-type Pokémon!", type.name))
end
end
PokemonSelection.restore
@@ -164,4 +164,4 @@ def show_nb_type_experts_defeated()
pbMEPlay("Register phone")
pbCallBub(3)
Kernel.pbMessage(_INTL("Type experts defeated: {1}/{2}", pbGet(VAR_TYPE_EXPERTS_BEATEN), TOTAL_NB_TYPE_EXPERTS))
end
end
@@ -10,12 +10,17 @@ SPARKLE_ANIMATION=29
PUDDLE_ANIMATION_ID = 31
ANIMATION_SPLASH_SMALL = 21
HEART_ANIMATION_SHORT_ID = 40
EXCLAMATION_ANIMATION_ID = 3
SOOT_DUST_ANIMATION = 36
QUESTION_MARK_ANIMATION_ID = 4
ANGRY_ANIMATION_ID = 24
ANGRY_SHORT_ANIMATION_ID = 34
NOISE_ANIMATION_ID = 12
FUSE_ANIMATION_ID = 33
@@ -117,11 +117,14 @@ VAR_CONSTELLATION_URSARING=310
VAR_CONSTELLATION_LUGIA=311
VAR_CONSTELLATION_HOOH=312
VAR_CONSTELLATION_CELEBI=313
VAR_CONSTELLATION_SLAKING=314
VAR_CONSTELLATION_JIRACHI=315
VAR_CONSTELLATION_TYRANTRUM=316
VAR_CONSTELLATION_SHARPEDO=317
VAR_CONSTELLATION_SHARPEDO=337
VAR_CONSTELLATION_SLAKING=338
VAR_CONSTELLATION_JIRACHI=339
VAR_CONSTELLATION_ARCEUS=318
VAR_CONSTELLATION_TYRANTRUM=316
VAR_LATEST_CONSTELLATION=319
VAR_TRAINER_CARD_BACKGROUND_PRICE=329
@@ -146,4 +149,8 @@ VAR_NB_WILD_FUSING_SEEN = 1036
VAR_TIME_TRIAL_START =1051
VAR_TIME_TRIAL_SECONDS =1052
VAR_CONTEST_CATEGORY = 1048
VAR_CONTEST_CATEGORY = 1048
VAR_HOENN_SAFARI_NB_BALLS = 1049
VAR_HOENN_SAFARI_FEEDER_DISCOUNT = 1050
VAR_SAFARI_POINTS = 1054
@@ -25,9 +25,12 @@ GENDER_MALE=1
MELOETTA_BAND_NAME = _INTL("Miss Melody and the Mystic Musicians")
SUCKY_BAND_NAME = _INTL("MooMoo Milk")
COSMETIC_CURRENCY_NAME = _INTL("Glimmer Coins")
def get_cosmetic_currency_name()
_INTL("Glimmer Coins")
end
NB_POKEMON = Settings::NB_POKEMON#809#420 #351 #aussi CONST_NB_POKE
CONST_NB_POKE = NB_POKEMON
DOSSIERCUSTOMSPRITES = "CustomBattlers"
BATTLERSPATH = "Battlers"
BATTLERSPATH = "Battlers"
@@ -130,14 +130,14 @@ MAP_DEWFORD = 51
MAP_SLATEPORT = 6
MAP_MAUVILLE = 73
MAP_VERDANTURF = 18
MAP_LAVARIDGE = 994 #todo: Temp
MAP_LAVARIDGE = 135
MAP_PETALBURG = 7
MAP_FORTREE = 992 #todo: Temp
MAP_FORTREE = 142
MAP_MOSSDEEP = 990 #todo: Temp
MAP_SOOTOPOLIS = 989 #todo: Temp
MAP_LEAGUE = 988 #todo: Temp
MAP_EVERGRANDE = 988 #todo: Temp
MAP_FALLARBOR = 993 #todo: Temp
MAP_FALLARBOR = 1171
MAP_PACIFIDLOG = 951 #todo: Temp
MAP_MAGMA_CAMP = 11
MAP_AQUA_CAMP = 39
@@ -145,23 +145,48 @@ MAP_AQUA_CAMP = 39
# Routes
MAP_ROUTE_102 = 10
MAP_ROUTE_104 = 20
MAP_ROUTE_104_SOUTH = 12
MAP_ROUTE_105 = 50
MAP_ROUTE_106 = 49
MAP_ROUTE_107 = 37
MAP_ROUTE_108 = 38
MAP_ROUTE_109 = 39
MAP_ROUTE_110 = 71
MAP_ROUTE_111 = 77
MAP_ROUTE_112 = 113
MAP_ROUTE_112_NORTH = 119
MAP_ROUTE_115 = 65
MAP_ROUTE_116 = 31
MAP_ROUTE_113 = 973 #todo: Temp
MAP_ROUTE_119 = 967 #todo: Temp
MAP_ROUTE_120 = 966 #todo: Temp
MAP_ROUTE_121 = 965 #todo: Temp
MAP_ROUTE_113 = 116
MAP_ROUTE_119_SOUTH = 133
MAP_ROUTE_119_NORTH = 137
MAP_ROUTE_120 = 147
MAP_ROUTE_121 = 148
MAP_ROUTE_123 = 144
MAP_ROUTE_124 = 962 #todo: Temp
MAP_ROUTE_128 = 958 #todo: Temp
MAP_SCORCHED_SLAB = 147
MAP_SAFARI_ENTRANCE = 155
MAP_SAFARI_1 = 149
MAP_SAFARI_2 = 150
MAP_SAFARI_3 = 151
MAP_SAFARI_4 = 152
MAP_SAFARI_5 = 153
MAP_SAFARI_6 = 154
# Dungeons/Areas
MAP_PETALBURG_WOODS = 30
MAP_RUSTURF_TUNNEL = 0
MAP_MT_CHIMNEY = 983
MAP_DESERT = 555 #todo: Temp
MAP_MT_CHIMNEY = 126
MAP_DESERT = 124
MAP_GRANITE_CAVE = 32
MAP_SHOAL_CAVE = 444 #todo: Temp
MAP_MT_PYRE = 964 #todo: Temp
MAP_METEOR_FALLS = 985 #todo: Temp
MAP_METEOR_FALLS = 129
MAP_DESERT_UNDERPASS = 19
MAP_JAGGED_PASS = 132
@@ -102,6 +102,8 @@ SWITCH_CAUGHT_MELOETTA = 750
SWITCH_FINISHED_ROCKET_QUESTS_CERULEAN = 1116
SWITCH_FINISHED_ROCKET_QUESTS_CELADON = 1106
SWITCH_NO_REPEL = 1147
##Randomizer & System
SWITCH_RANDOM_WILD_TO_FUSION=953
SWITCH_RANDOMIZED_AT_LEAST_ONCE = 855
@@ -111,9 +113,14 @@ SWITCH_RANDOM_WILD = 778
SWITCH_RANDOM_WILD_AREA = 777
SWITCH_RANDOM_TRAINERS = 987
SWITCH_RANDOM_TRAINERS_CUSTOMS_ONLY = 600
SWITCH_RANDOM_STARTERS = 954
SWITCH_RANDOM_STARTER_FIRST_STAGE = 771
SWITCH_RANDOM_REFERENCE_SPRITES = 1187
SWITCH_RANDOM_ITEMS_GENERAL=759
SWITCH_RANDOM_ITEMS=751
SWITCH_RANDOM_FOUND_ITEMS=755
@@ -144,6 +151,10 @@ SWITCH_RANDOM_WILD_LEGENDARIES=1031
SWITCH_RANDOM_TRAINER_LEGENDARIES=1032
SWITCH_RANDOM_GYM_LEGENDARIES=1033
SWITCH_DONT_RANDOMIZE=890
SWITCH_RANDOM_WILD_EGG_GROUP = 1150
SWITCH_RANDOM_TRAINER_EGG_GROUP = 1148
SWITCH_RANDOM_GYM_EGG_GROUP = 1149
#Other switches
SWITCH_RACE_BIKE = 984
@@ -207,5 +218,10 @@ SWITCH_AQUA_CAMP = 2114
SWITCH_WILD_FUSION_QUEST = 2159
SWITCH_TIME_TRIAL = 2196
SWITCH_WAILMER_EGGS_QUEST = 2167
SWITCH_SAFARI_FLOWERS_PLANTED = 2258
SWITCH_UNLOCKED_WALLPAPER_LOTTERY = 1995
SWITCH_UNLOCKED_TRANSFER_BOX = 1994
SWITCH_UNLOCKED_TRANSFER_BOX = 1994
SWITCH_ENCOUNTERED_A_POKEMON = 2209 #Used for challenge where you need to get through a place without enountering wild POkemon
@@ -9,4 +9,6 @@ COMMON_EVENT_OUTFIT = 80
COMMON_EVENT_FIX_GAME = 16
COMMON_EVENT_IDLE_HAT = 100
COMMON_EVENT_PINKAN_WHISTLE = 106
COMMON_EVENT_PINKAN_BACK_TO_BEGIN = 103
COMMON_EVENT_PINKAN_BACK_TO_BEGIN = 103
COMMON_EVENT_RESHUFFLE = 28
@@ -13,12 +13,35 @@ def map_sprites_by_artist
return creditsMap
end
def titleize(str)
str.split(/ |\_/).map(&:capitalize).join(" ")
end
def map_sprites_by_reference
creditsMap = Hash.new { |hash, key| hash[key] = [] }
File.foreach(Settings::CREDITS_FILE_PATH) do |line|
row = line.split(',')
spritename = row[0]
next unless row[3]
tags = row[3].chomp.split(';')
next unless tags[0] == 'reference'
tags[1..-1].each do |reference|
creditsMap[reference] << spritename
end
end
return creditsMap
end
SPRITER_CREDITS_BLACKLIST = ["Game Freak", "Anonymous"]
def get_top_artists(nb_names = 100)
filename = Settings::CREDITS_FILE_PATH
name_counts = Hash.new(0)
File.readlines(filename).each do |line|
name = line.strip.split(',')[1]
next if name.nil? || SPRITER_CREDITS_BLACKLIST.include?(name)
name_counts[name] += 1
end
@@ -37,7 +37,7 @@ module GameData
@base_exp = calculate_base_exp()
@growth_rate = calculate_growth_rate()
@gender_ratio = calculate_gender() #todo
@gender_ratio = calculate_gender()
@catch_rate = calculate_catch_rate()
@happiness = calculate_base_happiness()
@@ -285,7 +285,7 @@ module GameData
def get_split_names
case getCurrentLanguage
when :ENGLISH
when :ENGLISH, :FRENCH_CANADA
return GameData::SPLIT_NAMES
when :FRENCH
return GameData::SPLIT_NAMES_FRENCH
@@ -393,11 +393,12 @@ module GameData
return :Medium
end
#todo
def calculate_gender
head_ratio = @head_pokemon.gender_ratio
body_ratio = @body_pokemon.gender_ratio
return :Genderless if head_ratio == :Genderless || body_ratio == :Genderless
return :Female50Percent
return @body_pokemon.gender_ratio
end
@@ -1137,6 +1137,7 @@ end
def drawSpriteCredits(pif_sprite, viewport)
@credits_overlay = BitmapSprite.new(Graphics.width, Graphics.height, @viewport).bitmap
pbSetSystemFont(@credits_overlay)
return if pif_sprite.type == :AUTOGEN
return if pif_sprite.local_path
x = Graphics.width / 2
@@ -71,7 +71,7 @@ module GameData
["Ma", "champ"],
["Bell", "sprout"],
["Weepin", "bell"],
["Victree", "bell"],
["Victree", "bel"],
["Tenta", "cool"],
["Tenta", "cruel"],
["Geo", "dude"],
@@ -511,12 +511,12 @@ module GameData
["Stout", "land"],
["Purr", "loin"],
["Lie", "pard"],
["Pans", "ansage"],
["Sim", "misage"],
["Panse", "ansear"],
["Simis", "misear"],
["Panp", "pour"],
["Simip", "mipour"],
["Pan", "sage"],
["Simi", "sage"],
["Pans", "sear"],
["Simi", "sear"],
["Pan", "pour"],
["Simi", "pour"],
["Mun", "na"],
["Mush", "sharna"],
["Pido", "dove"],
@@ -314,14 +314,14 @@ end
def get_body_number_from_symbol(id)
dexNum = getDexNumberForSpecies(id)
return dexNum if !isFusion(dexNum)
id.to_s.match(/\d+/)[0]
return id.to_s.match(/\d+/)[0].to_i
dexNum -= get_head_number_from_symbol(id)
return dexNum / Settings::NB_POKEMON
end
def get_head_number_from_symbol(id)
dexNum = getDexNumberForSpecies(id)
return dexNum if !isFusion(dexNum)
return id.to_s.match(/(?<=H)\d+/)[0].to_i
return dexNum % Settings::NB_POKEMON
end
def get_fusion_symbol(head_id, body_id)
@@ -440,7 +440,7 @@ end
def getSpeciesRealName(species_symbol)
return nil if !species_symbol
species = GameData::Species.get(species_symbol)
return species.real_name
return species.name
end
def playerHasFusedPokemonInTeam()
@@ -522,6 +522,14 @@ def get_triple_fusion_components(species_id)
return [480,483,486]
when Settings::ZAPMOLCUNO_NB + 30
return [481,484,487]
when Settings::ZAPMOLCUNO_NB + 31 #Telemauv
return [000]
when Settings::ZAPMOLCUNO_NB + 32 #Solrock/minior/lunatone
return [498,544,545]
when Settings::ZAPMOLCUNO_NB + 33 #Solrock/minior_core/lunatone
return [499,544,545]
when Settings::ZAPMOLCUNO_NB + 34 #stunfisk/bruxish/luvdisc
return [420,469,501]
else
return [000]
end
@@ -91,7 +91,7 @@ class BattleSpriteLoader
def obtain_fusion_pif_sprite(head_id,body_id)
substitution_id = get_sprite_substitution_id_for_fusion(head_id, body_id)
pif_sprite = $PokemonSystem.alt_sprite_substitutions[substitution_id] if $PokemonGlobal
#pif_sprite.dump_info if pif_sprite
if !pif_sprite || $PokemonSystem.random_sprites
pif_sprite = select_new_pif_fusion_sprite(head_id, body_id)
local_path = check_for_local_sprite(pif_sprite)
@@ -124,6 +124,11 @@ class BattleSpriteLoader
pif_sprite = $PokemonSystem.alt_sprite_substitutions[substitution_id] if $PokemonGlobal
if !pif_sprite || $PokemonSystem.random_sprites
pif_sprite = select_new_pif_base_sprite(dex_number)
local_path = check_for_local_sprite(pif_sprite)
if local_path
pif_sprite.local_path = local_path
end
$PokemonSystem.alt_sprite_substitutions[substitution_id] = pif_sprite if $PokemonGlobal && !$PokemonSystem.random_sprites
end
if pif_sprite.local_path
@@ -181,6 +186,7 @@ class BattleSpriteLoader
return pif_sprite.local_path if pif_sprite.local_path
if pif_sprite.type == :BASE
sprite_path = "#{Settings::CUSTOM_BASE_SPRITES_FOLDER}#{pif_sprite.head_id}#{pif_sprite.alt_letter}.png"
echoln sprite_path
else
sprite_path = "#{Settings::CUSTOM_BATTLERS_FOLDER_INDEXED}#{pif_sprite.head_id}/#{pif_sprite.head_id}.#{pif_sprite.body_id}#{pif_sprite.alt_letter}.png"
end
@@ -228,13 +234,46 @@ class BattleSpriteLoader
if $PokemonTemp.forced_alt_sprites && $PokemonTemp.forced_alt_sprites.include?(spritename)
alt_letter = $PokemonTemp.forced_alt_sprites[spritename]
end
if $game_switches && $game_switches[SWITCH_RANDOM_REFERENCE_SPRITES]
unless $PokemonTemp.selected_reference_sprites
$PokemonTemp.selected_reference_sprites = getSelectedReferenceSprites()
end
unless $PokemonTemp.reference_sprite_index
$PokemonTemp.reference_sprite_index = build_reference_sprite_index($PokemonTemp.selected_reference_sprites)
end
matching_alts = $PokemonTemp.reference_sprite_index[spritename]
if matching_alts && !matching_alts.empty?
alt_letter = matching_alts.sample
type = :CUSTOM
end
end
return PIFSprite.new(type, head_id, body_id, alt_letter)
end
def build_reference_sprite_index(list)
index = Hash.new { |h, k| h[k] = [] }
list.each do |entry|
# spritename portion is digits/dots only; alt suffix is trailing lowercase letters
if entry =~ /\A([\d.]+)([a-z]*)\z/
index[$1] << $2
end
end
index
end
def select_new_pif_base_sprite(dex_number)
random_alt = get_random_alt_letter_for_unfused(dex_number, true) #nil if no main
random_alt = "" if !random_alt
return PIFSprite.new(:BASE, dex_number, nil, random_alt)
pif_sprite = PIFSprite.new(:BASE, dex_number, nil, random_alt)
local_path = check_for_local_sprite(pif_sprite)
if local_path
pif_sprite.local_path = local_path
pif_sprite.type = :CUSTOM
end
return pif_sprite
end
#todo refactor by using get_triple_fusion_components()
@@ -295,6 +295,9 @@ end
#
class PokemonTemp
attr_accessor :forced_alt_sprites
attr_accessor :selected_reference_sprites
attr_accessor :reference_sprite_index
end
# todo:
@@ -23,7 +23,7 @@ end
def Kernel.getRoamingMap(roamingArrayPos)
curmap = $PokemonGlobal.roamPosition[roamingArrayPos]
mapinfos = $RPGVX ? load_data("Data/MapInfos.rvdata") : load_data("Data/MapInfos.rxdata")
text = mapinfos[curmap].name #,(curmap==$game_map.map_id) ? _INTL("(this map)") : "")
text = pbGetMessage(MessageTypes::MapNames, curmap) #,(curmap==$game_map.map_id) ? _INTL("(this map)") : "")
return text
end
@@ -63,4 +63,4 @@ end
def setForcedAltSprites(forcedSprites_map)
$PokemonTemp.forced_alt_sprites = forcedSprites_map
end
end
@@ -82,9 +82,9 @@ def pbReceiveCosmeticsMoney(amount, showMessage=true, msgwindow=nil, goldwindow=
if showMessage
if amount >= 0
pbMessage(_INTL("{1} received {2} {3}!", $Trainer.name, amount.to_s_formatted, COSMETIC_CURRENCY_NAME))
pbMessage(_INTL("{1} received {2} {3}!", $Trainer.name, amount.to_s_formatted, get_cosmetic_currency_name))
else
pbMessage(_INTL("{1} spent {2} {3}!", $Trainer.name, amount.abs.to_s_formatted, COSMETIC_CURRENCY_NAME))
pbMessage(_INTL("{1} spent {2} {3}!", $Trainer.name, amount.abs.to_s_formatted, get_cosmetic_currency_name))
end
end
@@ -111,7 +111,7 @@ def pbReceiveCosmeticsMoney(amount, showMessage=true, msgwindow=nil, goldwindow=
sign = amount >= 0 ? "+" : "-"
goldwindow.text = _INTL(
"{1}:\n<ar>{2}</ar>\n<ar><c3={3}>{4} {5}</c3></ar>",
COSMETIC_CURRENCY_NAME,
get_cosmetic_currency_name,
current.to_s_formatted,
color,
sign,
@@ -131,7 +131,7 @@ def pbReceiveCosmeticsMoney(amount, showMessage=true, msgwindow=nil, goldwindow=
# Final display text
goldwindow.text = _INTL(
"{1}:\n<ar>{2}</ar>",
COSMETIC_CURRENCY_NAME,
get_cosmetic_currency_name,
targetMoney.to_s_formatted
)

Some files were not shown because too many files have changed in this diff Show More