6.4 update (minus sprites)

This commit is contained in:
infinitefusion
2024-12-21 09:43:11 -05:00
parent f70c2cfde4
commit 1e325366d2
1717 changed files with 140299 additions and 27845 deletions

View File

@@ -0,0 +1,133 @@
AUTOSAVE_ENABLED_SWITCH = 48
AUTOSAVE_HEALING_VAR = 24
AUTOSAVE_CATCH_SWITCH = 782
AUTOSAVE_WIN_SWITCH = 783
AUTOSAVE_STEPS_SWITCH = 784
AUTOSAVE_STEPS_VAR = 236
DEFAULT_AUTOSAVE_STEPS = 500
def pbSetPokemonCenter
$PokemonGlobal.pokecenterMapId = $game_map.map_id
$PokemonGlobal.pokecenterX = $game_player.x
$PokemonGlobal.pokecenterY = $game_player.y
$PokemonGlobal.pokecenterDirection = $game_player.direction
if $game_variables[AUTOSAVE_HEALING_VAR]==0
pbSEPlay("save",100,100)
Kernel.tryAutosave()
end
end
def Kernel.Autosave
#Game.auto_save
#showSaveIcon()
pbSave(false)
# #hideSaveIcon()
end
def Kernel.tryAutosave()
return if !$Trainer.save_slot
Kernel.Autosave if $game_switches[AUTOSAVE_ENABLED_SWITCH]
end
Events.onMapUpdate += proc { |sender, e|
next if !$game_switches
next if !$game_switches[AUTOSAVE_STEPS_SWITCH]
stepsNum = pbGet(AUTOSAVE_STEPS_VAR)
if stepsNum > 0 && !$PokemonGlobal.sliding
next if $PokemonGlobal.stepcount < 100
if $PokemonGlobal.stepcount % stepsNum == 0
$PokemonGlobal.stepcount += 1
Kernel.tryAutosave()
end
end
}
class AutosaveOptionsScene < PokemonOption_Scene
def initialize
@changedColor = false
end
def pbStartScene(inloadscreen = false)
super
@sprites["option"].nameBaseColor = Color.new(35, 130, 200)
@sprites["option"].nameShadowColor = Color.new(20, 75, 115)
@changedColor = true
for i in 0...@PokemonOptions.length
@sprites["option"][i] = (@PokemonOptions[i].get || 0)
end
@sprites["title"]=Window_UnformattedTextPokemon.newWithSize(
_INTL("Autosave settings"),0,0,Graphics.width,64,@viewport)
@sprites["textbox"].text=_INTL("Customize the autosave settings")
pbFadeInAndShow(@sprites) { pbUpdate }
end
def pbFadeInAndShow(sprites, visiblesprites = nil)
return if !@changedColor
super
end
def pbGetOptions(inloadscreen = false)
options = [
EnumOption.new(_INTL("When healing"), [_INTL("On"), _INTL("Off")],
proc { $game_variables[AUTOSAVE_HEALING_VAR]},
proc { |value|
$game_variables[AUTOSAVE_HEALING_VAR]=value
},
"Autosave when healing at a Pokémon Center"
),
EnumOption.new(_INTL("When catching Pokémon"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[AUTOSAVE_CATCH_SWITCH] ? 0 : 1 },
proc { |value|
$game_switches[AUTOSAVE_CATCH_SWITCH] = value == 0
},
"Autosave everytime a new Pokémon is caught"
),
EnumOption.new(_INTL("After trainer battles"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[AUTOSAVE_WIN_SWITCH] ? 0 : 1 },
proc { |value|
$game_switches[AUTOSAVE_WIN_SWITCH] = value == 0
},
"Autosave after each trainer battle"
),
EnumOption.new(_INTL("Every x steps"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[AUTOSAVE_STEPS_SWITCH] ? 0 : 1 },
proc { |value|
if !$game_switches[AUTOSAVE_STEPS_SWITCH] && value == 0
@set_steps = true
selectAutosaveSteps()
end
$game_switches[AUTOSAVE_STEPS_SWITCH] = value == 0
}, "Autosave after a defined amount of steps"
)
]
return options
end
def selectAutosaveSteps()
if pbGet(AUTOSAVE_STEPS_VAR) == 0
pbSet(AUTOSAVE_STEPS_VAR,DEFAULT_AUTOSAVE_STEPS)
end
params=ChooseNumberParams.new
params.setRange(20,999999)
params.setInitialValue(pbGet(AUTOSAVE_STEPS_VAR))
params.setCancelValue(0)
val = Kernel.pbMessageChooseNumber(_INTL("Autosave every how many steps?"),params)
if val < 200
Kernel.pbMessage("Warning: Choosing a low number of steps may decrease performance.")
end
if val == 0
val = 1
end
pbSet(AUTOSAVE_STEPS_VAR,val)
end
end

View File

@@ -0,0 +1,232 @@
def get_opponent_level
return $Trainer.highest_level_pokemon_in_party
end
def get_egg_group_from_id(id)
case id
when 0;
return nil
when 1;
return :Monster
when 2;
return :Water1
when 3;
return :Bug
when 4;
return :Flying
when 5;
return :Field
when 6;
return :Fairy
when 7;
return :Grass
when 8;
return :Humanlike
when 9;
return :Water3
when 10;
return :Mineral
when 11;
return :Amorphous
when 12;
return :Water2
when 13;
return :Ditto
when 14;
return :Dragon
when 15;
return :Undiscovered
end
end
def get_egg_group_name(id)
case id
when 0;
return nil
when 1;
return "Monster Pokémon"
when 2;
return :"Aquatic Pokémon"
when 3;
return :"Bug Pokémon"
when 4;
return :"Bird Pokémon"
when 5;
return :"Land Pokémon"
when 6;
return :"Cute Pokémon"
when 7;
return :"Plant Pokémon"
when 8;
return :"Human-like Pokémon"
when 9;
return :"Aquatic Pokémon"
when 10;
return :"Mineral Pokémon"
when 11;
return :"Blob Pokémon"
when 12;
return :"Fish Pokémon"
when 13;
return :"Ditto"
when 14;
return :"Dragon Pokémon"
when 15;
return :"Legendary Pokémon"
end
end
def get_random_trainer_name(trainer_class)
#0: male, 1: female
gender = GameData::TrainerType.get(trainer_class).gender
if (gender == 0)
return RandTrainerNames_male[rand(RandTrainerNames_male.length)]
else
return RandTrainerNames_female[rand(RandTrainerNames_female.length)]
end
end
def get_random_battle_lounge_egg_group
_DISABLED_EGG_GROUPS = [0, 13, 15]
group = 0
while _DISABLED_EGG_GROUPS.include?(group)
group = rand(0, 15)
end
return group
end
GENERIC_PRIZES_MULTI = [:HEARTSCALE, :HEARTSCALE,:HEARTSCALE,:HEARTSCALE,:HEARTSCALE,
:LEMONADE, :PERFECTBALL, :TRADEBALL,
:GENDERBALL, :ABILITYBALL, :VIRUSBALL, :SHINYBALL]
GENERIC_PRIZES_SINGLE = [:RARECANDY, :RARECANDY,:RARECANDY, :PPUP, :EJECTBUTTON, :FOCUSBAND, :FOCUSSASH,
:RESETURGE, :ABILITYURGE, :ITEMURGE, :ITEMDROP, :HPUP, :INCUBATOR, :LUCKYEGG]
MONSTER_PRIZES = [:RAREBONE, :LAGGINGTAIL, :RAZORFANG, :RAZORCLAW, :GRIPCLAW, :MANKEYPAW]
WATER_PRIZES = [:MYSTICWATER, :BIGPEARL, :SHELLBELL]
BUG_PRIZES = [:SILVERPOWDER, :SHEDSHELL, :EVIOLITE]
FLYING_PRIZES = [:AIRBALLOON, :FLOATSTONE, :COMETSHARD]
FIELD_PRIZES = [:MOOMOOMILK, :IRONBALL, :RAREBONE, :MANKEYPAW, :FLAMEORB]
FAIRY_PRIZES = [:STARPIECE, :DESTINYKNOT, :MAXELIXIR, :LIFEORB]
HUMAN_PRIZES = [:BLACKBELT, :RINGTARGET, :EXPERTBELT, :GOLDRING, :AMULETCOIN]
GRASS_PRIZES = [:REVIVALHERB, :POWERHERB, :HEALPOWDER, :ABSORBBULB, :BIGMUSHROOM]
MINERAL_PRIZES = [:CELLBATTERY, :SHINYSTONE, :BIGNUGGET, :RELICCOPPER, :RELICGOLD, :RELICSILVER, :DIAMOND, :ROCKYHELMET]
AMORPHOUS_PRIZES = [:SPELLTAG, :WIDELENS, :ZOOMLENS, :SCOPELENS, :TOXICORB]
DRAGON_PRIZES = [:DRAGONSCALE, :DRAGONFANG, :RARECANDY, :GOLDRING]
UNDISCOVERED_PRIZES = [:MASTERBALL, :SACREDASH]
#todo: prizes related to the group (ex: dragon fang for dragon types, TMs, etc. )
# todo: if heartscale, give a random amount from 10-20
def get_random_battle_lounge_prize(group_type)
generic_prizes = [GENERIC_PRIZES_MULTI, GENERIC_PRIZES_SINGLE]
is_generic_prize = rand(3) == 1
if is_generic_prize
type = generic_prizes.sample
return type.sample
else
case get_egg_group_from_id(group_type)
when :Monster;
return MONSTER_PRIZES.sample
when :Water1, :Water2, :Water3;
return WATER_PRIZES.sample
when :Bug;
return BUG_PRIZES.sample
when :Flying;
return FLYING_PRIZES.sample
when :Field;
return FIELD_PRIZES.sample
when :Fairy;
return FAIRY_PRIZES.sample
when :Grass;
return GRASS_PRIZES.sample
when :Mineral;
return MINERAL_PRIZES.sample
when :Humanlike;
return HUMAN_PRIZES.sample
when :Amorphous;
return AMORPHOUS_PRIZES.sample
when :Dragon;
return DRAGON_PRIZES.sample
when :Undiscovered;
return UNDISCOVERED_PRIZES.sample
end
end
end
def generateSameEggGroupFusionsTeam(eggGroup_id)
eggGroup = get_egg_group_from_id(eggGroup_id)
teamComplete = false
generatedTeam = []
while !teamComplete
foundFusionPartner = false
species1 = rand(Settings::NB_POKEMON) + 1
if getPokemonEggGroups(species1).include?(eggGroup)
foundFusionPartner = false
while !foundFusionPartner
species2 = rand(Settings::NB_POKEMON) + 1
if getPokemonEggGroups(species2).include?(eggGroup)
generatedTeam << getFusionSpeciesSymbol(species1, species2)
foundFusionPartner = true
end
end
end
teamComplete = generatedTeam.length == 3
end
return generatedTeam
end
def listLegendaryPokemonIds()
return [144, 145, 146, 150, 151, 245, 243, 244, 245, 249, 250, 251, 315, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 378, 379, 380, 381]
end
def pokemonIsPartLegendary(species)
head = getBasePokemonID(species, false)
body = getBasePokemonID(species, true)
return listLegendaryPokemonIds().include?(head) || listLegendaryPokemonIds().include?(body)
end
def generateRandomFusionFromPokemon(dexNum, onlyCustomSprites = false, allowLegendaries=true)
excluded = allowLegendaries ? [] : listLegendaryPokemonIds()
customsList = getCustomSpeciesList(downloadAllowed?())
i=0
while i < customsList.length
comparedPoke = customsList.sample
next if excluded.include?(comparedPoke)
if Kernel.isPartPokemon(comparedPoke, dexNum)
return comparedPoke
end
i+=1
end
return 1
end
def getRandomBasePokemon(includeLegendaries = false,maxNb=NB_POKEMON)
legendaries =listLegendaryPokemonIds()
poke = rand(maxNb + 1)
return poke if includeLegendaries
while legendaries.include?(poke)
poke = rand(maxNb + 1)
end
return poke
end
def getAllPokemonWithBase(dexNum)
#todo Unimplemented
return [25]
end
def getCustomSpeciesListForPokemon(dexNum,allowLegendaries=true)
excluded = allowLegendaries ? [] : listLegendaryPokemonIds()
customsList = getCustomSpeciesList(downloadAllowed?())
speciesList = []
for comparedPoke in customsList
next if excluded.include?(comparedPoke)
if Kernel.isPartPokemon(comparedPoke, dexNum)
speciesList << comparedPoke
end
end
if speciesList.length == 0
speciesList << dexNum
end
return speciesList
end

View File

@@ -0,0 +1,972 @@
#==============================================================================#
# Better Region Map #
# By Marin, with edits by Boonzeet #
#==============================================================================#
# This region map is smoother and allows you to use region maps larger than #
# 480x320. #
# #
# This resource also comes with a new townmapgen.html to support for the #
# larger images. #
#==============================================================================#
# This region map now supports hidden islands (e.g. Berth or Faraday). #
#==============================================================================#
# Please give credit when using this. #
#==============================================================================#
#
# PluginManager.register({
# :name => "Better Region Map",
# :version => "1.2",
# :credits => ["Marin", "Boonzeet"],
# :dependencies => "Marin's Scripting Utilities",
# :link => "https://reliccastle.com/resources/174/"
# })
def pbBetterRegionMap(region = -1, show_player = true, can_fly = false, wallmap = false, species = nil, fly_anywhere = false)
scene = BetterRegionMap.new(-1, show_player, can_fly, wallmap, species, fly_anywhere)
return scene.flydata
end
class PokemonGlobalMetadata
attr_writer :regionMapSel
attr_writer :region
def regionMapSel
@regionMapSel ||= [0, 0]
return @regionMapSel
end
def region
@region ||= 0
return @region
end
end
class BetterRegionMap
KANTO_DEFAULT_POS = [37, 7]
CursorAnimateDelay = 12.0
CursorMoveSpeed = 2.0
TileWidth = 16.0
TileHeight = 16.0
FlyPointAnimateDelay = 20.0
attr_reader :flydata
def initialize(region = -1, show_player = true, can_fly = false, wallmap = false, species = nil, fly_anywhere = false)
region = 0
showBlk
map_metadata = GameData::MapMetadata.try_get($game_map.map_id)
if map_metadata
playerpos = $game_map ? map_metadata.town_map_position : nil #pbGetMetadata($game_map.map_id, MetadataMapPosition) : nil
end
if playerpos == nil
playerpos = [0, 0]
end
@fly_anywhere = fly_anywhere
@region = 0 #(region < 0) ? playerpos[0] : region
@species = species
@show_player = show_player #(show_player && playerpos[0] == @region)
@can_fly = can_fly
@data = load_data("Data/town_map.dat")[@region]
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@mapdata = pbLoadTownMapData
@mapvp = Viewport.new(16, 32, 480, 320)
@mapvp.z = 100000
@mapoverlayvp = Viewport.new(16, 32, 480, 320)
@mapoverlayvp.z = 100001
@viewport2 = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport2.z = 100001
@sprites = SpriteHash.new
@sprites["bg"] = Sprite.new(@viewport)
@sprites["bg"].bmp("Graphics/Pictures/mapbg")
@window = SpriteHash.new
@window["map"] = Sprite.new(@mapvp)
mapFilename = isPostgame?() ? "map_postgame" : "map"
# @window["map"].bmp("Graphics/Pictures/#{@data[1]}")
@window["map"].bmp("Graphics/Pictures/map/#{mapFilename}")
# for hidden in REGION_MAP_EXTRAS
# if hidden[0] == @region && ((wallmap && hidden[5]) || # always show if looking at wall map, irrespective of switch
# (!wallmap && hidden[1] > 0 && $game_switches[hidden[1]]))
# if !@window["map2"]
# @window["map2"] = BitmapSprite.new(480,320,@mapoverlayvp)
# end
# pbDrawImagePositions(@window["map2"].bitmap, [
# ["Graphics/Pictures/#{hidden[4]}", hidden[2] * TileWidth, hidden[3] * TileHeight, 0, 0, -1, -1],
# ])
# end
# end
@window["player"] = Sprite.new(@mapoverlayvp)
if @show_player
if map_metadata
player = map_metadata.town_map_position
if true #player && player[0] == @region #only use 1 region
$PokemonGlobal.regionMapSel = [0, 0]
gender = $Trainer.gender.to_digits(3)
# @window["player"].bmp("Graphics/Pictures/map/Player#{gender}")
@window["player"].bmp("Graphics/Pictures/map/location_icon")
@window["player"].x = TileWidth * player[1] + (TileWidth / 2.0) if player
@window["player"].y = TileHeight * player[2] + (TileHeight / 2.0) if player
@window["player"].center_origins
end
else
end
end
@window["areahighlight"] = BitmapSprite.new(@window["map"].bitmap.width, @window["map"].bitmap.height, @mapoverlayvp)
@window["areahighlight"].y = -8
# pokedex highlights
# if @species != nil
# @window["areahighlight"].bitmap.clear
# # Fill the array "points" with all squares of the region map in which the
# # species can be found
#
# mapwidth = @window["map"].bitmap.width / BetterRegionMap::TileWidth
# data = calculatePointsAndCenter(mapwidth)
#
# points = data[0]
# minxy = data[1]
# maxxy = data[2]
#
# # Draw coloured squares on each square of the region map with a nest
# pointcolor = Color.new(0, 248, 248)
# pointcolorhl = Color.new(192, 248, 248)
#
# sqwidth = TileWidth.round
# sqheight = TileHeight.round
#
# for j in 0...points.length
# if points[j]
# x = (j % mapwidth) * sqwidth
# y = (j / mapwidth) * sqheight
# @window["areahighlight"].bitmap.fill_rect(x, y, sqwidth, sqheight, pointcolor)
# if j - mapwidth < 0 || !points[j - mapwidth]
# @window["areahighlight"].bitmap.fill_rect(x, y - 2, sqwidth, 2, pointcolorhl)
# end
# if j + mapwidth >= points.length || !points[j + mapwidth]
# @window["areahighlight"].bitmap.fill_rect(x, y + sqheight, sqwidth, 2, pointcolorhl)
# end
# if j % mapwidth == 0 || !points[j - 1]
# @window["areahighlight"].bitmap.fill_rect(x - 2, y, 2, sqheight, pointcolorhl)
# end
# if (j + 1) % mapwidth == 0 || !points[j + 1]
# @window["areahighlight"].bitmap.fill_rect(x + sqwidth, y, 2, sqheight, pointcolorhl)
# end
# end
# end
# end
@sprites["cursor"] = Sprite.new(@viewport2)
@sprites["cursor"].bmp("Graphics/Pictures/mapCursor")
@sprites["cursor"].src_rect.width = @sprites["cursor"].bmp.height
if !$PokemonGlobal.regionMapSel
$PokemonGlobal.regionMapSel = [0, 0]
end
if @species != nil && minxy[0] != nil && maxxy[1] != nil
$PokemonGlobal.regionMapSel[0] = ((minxy[0] + maxxy[0]) / 2).round
$PokemonGlobal.regionMapSel[1] = ((minxy[1] + maxxy[1]) / 2).round
end
@sprites["cursor"].z = 11
# Center the window on the cursor
# windowminx = -1 * (@window["map"].bmp.width - Settings::SCREEN_WIDTH)
# windowminx = 0 if windowminx > 0
# windowminy = -1 * (@window["map"].bmp.height - Settings::SCREEN_HEIGHT)
# windowminy = 0 if windowminy > 0
#
# if @sprites["cursor"].x > (Settings::SCREEN_WIDTH / 2)
# @window.x = (Settings::SCREEN_WIDTH / 2 ) - @sprites["cursor"].x
# if (@window.x < windowminx)
# @window.x = windowminx
# end
# @sprites["cursor"].x += @window.x
# end
# if @sprites["cursor"].y > (Settings::SCREEN_HEIGHT / 2)
# @window.y = (Settings::SCREEN_HEIGHT / 2 ) - @sprites["cursor"].y
# if @window.y < windowminy
# @window.y = windowminy
# end
# @sprites["cursor"].y += @window.y
# end
@sprites["cursor"].ox = (@sprites["cursor"].bmp.height - TileWidth) / 2.0
@sprites["cursor"].oy = @sprites["cursor"].ox
@sprites["txt"] = TextSprite.new(@viewport)
@sprites["arrowLeft"] = Sprite.new(@viewport2)
@sprites["arrowLeft"].bmp("Graphics/Pictures/mapArrowRight")
@sprites["arrowLeft"].mirror = true
@sprites["arrowLeft"].center_origins
@sprites["arrowLeft"].xyz = 12, Graphics.height / 2
@sprites["arrowRight"] = Sprite.new(@viewport2)
@sprites["arrowRight"].bmp("Graphics/Pictures/mapArrowRight")
@sprites["arrowRight"].center_origins
@sprites["arrowRight"].xyz = Graphics.width - 12, Graphics.height / 2
@sprites["arrowUp"] = Sprite.new(@viewport2)
@sprites["arrowUp"].bmp("Graphics/Pictures/mapArrowDown")
@sprites["arrowUp"].angle = 180
@sprites["arrowUp"].center_origins
@sprites["arrowUp"].xyz = Graphics.width / 2, 24
@sprites["arrowDown"] = Sprite.new(@viewport2)
@sprites["arrowDown"].bmp("Graphics/Pictures/mapArrowDown")
@sprites["arrowDown"].center_origins
@sprites["arrowDown"].xyz = Graphics.width / 2, Graphics.height - 24
update_text
@dirs = []
@mdirs = []
@i = 0
if can_fly
@spots = {}
n = 0
for x in 0...(@window["map"].bmp.width / TileWidth)
for y in 0...(@window["map"].bmp.height / TileHeight)
healspot = pbGetHealingSpot(x, y)
if can_fly_to_location(healspot)
@window["point#{n}"] = Sprite.new(@mapvp)
@window["point#{n}"].bmp("Graphics/Pictures/map/mapFly")
@window["point#{n}"].src_rect.width = @window["point#{n}"].bmp.height
@window["point#{n}"].x = TileWidth * x + (TileWidth / 2)
@window["point#{n}"].y = TileHeight * y + (TileHeight / 2)
@window["point#{n}"].oy = @window["point#{n}"].bmp.height / 2.0
@window["point#{n}"].ox = @window["point#{n}"].oy
@spots[[x, y]] = healspot
n += 1
end
end
end
end
initial_position = calculate_initial_position(player)
init_cursor_position(initial_position[0], initial_position[1])
center_window()
hideBlk { update(false) }
main
end
def calculate_initial_position(player)
if player
x_pos = player[1] if player[1]
y_pos = player[2] if player[2]
return [x_pos, y_pos]
end
return KANTO_DEFAULT_POS
end
def findNearbyHealingSpot(current_x, current_y)
range = 5 # Area around each healing spot to check
closest_spot = nil
min_distance = Float::INFINITY
for new_x in current_x - range..current_x + range
for new_y in current_y - range..current_y + range
if can_fly_to_location(pbGetHealingSpot(new_x, new_y))
distance = Math.sqrt((new_x - current_x)**2 + (new_y - current_y)**2)
if distance < min_distance && !(new_x == current_x && new_y == current_y)
min_distance = distance
closest_spot = [new_x, new_y]
end
end
end
end
echoln "Closest spot: #{closest_spot.inspect}" if closest_spot
return closest_spot
end
def synchronize_cursor
# Sync logical position to visual cursor position
x = (($sprites["cursor"].x - 16) / TileWidth).round
y = (($sprites["cursor"].y - 32) / TileHeight).round
$PokemonGlobal.regionMapSel[0] = x
$PokemonGlobal.regionMapSel[1] = y
# Ensure the window is in the correct position
visual_cursor_x = 16 + TileWidth * x
visual_cursor_y = 32 + TileHeight * y
@sprites["cursor"].x = visual_cursor_x + @window.x
@sprites["cursor"].y = visual_cursor_y + @window.y
end
def move_cursor_to(x, y)
# Update the logical position
$PokemonGlobal.regionMapSel[0] = x
$PokemonGlobal.regionMapSel[1] = y
# Calculate the visual position of the cursor based on the logical position
visual_cursor_x = 16 + TileWidth * x
visual_cursor_y = 32 + TileHeight * y
# Ensure the map window scrolls to keep the cursor centered when needed
# Calculate bounds for the map window
window_min_x = -1 * (@window["map"].bmp.width - Settings::SCREEN_WIDTH)
window_min_x = 0 if window_min_x > 0
window_min_y = -1 * (@window["map"].bmp.height - Settings::SCREEN_HEIGHT)
window_min_y = 0 if window_min_y > 0
# Adjust the map window X-axis to center the cursor
if visual_cursor_x < 16 # Too far left
@window.x = [@window.x + (16 - visual_cursor_x), 0].min
elsif visual_cursor_x > Settings::SCREEN_WIDTH - 16 # Too far right
@window.x = [@window.x - (visual_cursor_x - (Settings::SCREEN_WIDTH - 16)), window_min_x].max
end
# Adjust the map window Y-axis to center the cursor
if visual_cursor_y < 32 # Too far up
@window.y = [@window.y + (32 - visual_cursor_y), 0].min
elsif visual_cursor_y > Settings::SCREEN_HEIGHT - 32 # Too far down
@window.y = [@window.y - (visual_cursor_y - (Settings::SCREEN_HEIGHT - 32)), window_min_y].max
end
# After adjusting the window, re-calculate the cursor position
# Ensure it's visually accurate relative to the adjusted map window
@sprites["cursor"].x = visual_cursor_x + @window.x
@sprites["cursor"].y = visual_cursor_y + @window.y
adjust_window_if_not_visited_regions
end
def init_cursor_position(x, y)
$PokemonGlobal.regionMapSel[0] = x
$PokemonGlobal.regionMapSel[1] = y
@sprites["cursor"].x = 16 + TileWidth * $PokemonGlobal.regionMapSel[0]
@sprites["cursor"].y = 32 + TileHeight * $PokemonGlobal.regionMapSel[1]
# @sprites["cursor"].x = x + TileWidth * $PokemonGlobal.regionMapSel[0]
# @sprites["cursor"].y = y + TileHeight * $PokemonGlobal.regionMapSel[1]
#
# @window["player"].x = TileWidth * player[1] + (TileWidth / 2.0)
# @window["player"].y = TileHeight * player[2] + (TileHeight / 2.0)
end
def been_to_johto()
first_visited_map = 248 #goldenrod train station
return $PokemonGlobal.visitedMaps[first_visited_map]
end
def been_to_sevii()
offshore_road_map = 762 #offshore road
knot_island_map = 526
return $PokemonGlobal.visitedMaps[offshore_road_map] || $PokemonGlobal.visitedMaps[knot_island_map]
end
def center_window()
# Center the window on the cursor
windowminx = -1 * (@window["map"].bmp.width - Settings::SCREEN_WIDTH)
windowminx = 0 if windowminx > 0
windowminy = -1 * (@window["map"].bmp.height - Settings::SCREEN_HEIGHT)
windowminy = 0 if windowminy > 0
if @sprites["cursor"].x > (Settings::SCREEN_WIDTH / 2)
@window.x = (Settings::SCREEN_WIDTH / 2) - @sprites["cursor"].x
if (@window.x < windowminx)
@window.x = windowminx
end
@sprites["cursor"].x += @window.x
end
if @sprites["cursor"].y > (Settings::SCREEN_HEIGHT / 2)
@window.y = (Settings::SCREEN_HEIGHT / 2) - @sprites["cursor"].y
if @window.y < windowminy
@window.y = windowminy
end
@sprites["cursor"].y += @window.y
end
adjust_window_if_not_visited_regions()
end
def adjust_window_if_not_visited_regions()
if !been_to_johto()
baseline = -352
if @window.x >= baseline
old_window_x = @window.x
@window.x = baseline
difference = baseline - old_window_x
@sprites["cursor"].x += difference
end
end
if !been_to_sevii()
baseline = 0
if @window.y < baseline
old_window_y = @window.y
@window.y = baseline
difference = baseline - old_window_y
@sprites["cursor"].y += difference
end
end
end
def can_fly_to_location(healspot)
return true if healspot && @fly_anywhere
return healspot && $PokemonGlobal.visitedMaps[healspot[0]]
end
def pbGetHealingSpot(x, y)
return nil if !@data[2]
for loc in @data[2]
if loc[0] == x && loc[1] == y
if !loc[4] || !loc[5] || !loc[6]
return nil
else
return [loc[4], loc[5], loc[6]]
end
end
end
return nil
end
def main
loop do
update
if Input.press?(Input::RIGHT) && ![4, 6].any? { |e| @dirs.include?(e) || @mdirs.include?(e) }
if @sprites["cursor"].x < 480
$PokemonGlobal.regionMapSel[0] += 1
@sx = @sprites["cursor"].x
@dirs << DIRECTION_RIGHT
elsif @window.x > -1 * (@window["map"].bmp.width - 480)
$PokemonGlobal.regionMapSel[0] += 1
@mx = @window.x
@mdirs << DIRECTION_RIGHT
end
end
if Input.press?(Input::LEFT) && ![4, 6].any? { |e| @dirs.include?(e) || @mdirs.include?(e) }
if @sprites["cursor"].x > 16
$PokemonGlobal.regionMapSel[0] -= 1
@sx = @sprites["cursor"].x
@dirs << DIRECTION_LEFT
elsif @window.x < 0 && been_to_johto()
$PokemonGlobal.regionMapSel[0] -= 1
@mx = @window.x
@mdirs << DIRECTION_LEFT
end
end
if Input.press?(Input::DOWN) && ![DIRECTION_DOWN, DIRECTION_UP].any? { |e| @dirs.include?(e) || @mdirs.include?(e) }
if @sprites["cursor"].y <= 320
$PokemonGlobal.regionMapSel[1] += 1
@sy = @sprites["cursor"].y
@dirs << DIRECTION_DOWN
elsif @window.y > -1 * (@window["map"].bmp.height - 320) && been_to_sevii()
$PokemonGlobal.regionMapSel[1] += 1
@my = @window.y
@mdirs << DIRECTION_DOWN
end
end
if Input.press?(Input::UP) && ![2, 8].any? { |e| @dirs.include?(e) || @mdirs.include?(e) }
if @sprites["cursor"].y > 32
$PokemonGlobal.regionMapSel[1] -= 1
@sy = @sprites["cursor"].y
@dirs << DIRECTION_UP
elsif @window.y < 0
$PokemonGlobal.regionMapSel[1] -= 1
@my = @window.y
@mdirs << DIRECTION_UP
end
end
if Input.trigger?(Input::AUX1)
print_current_position()
end
if Input.trigger?(Input::C) && @dirs.empty?
x, y = $PokemonGlobal.regionMapSel
if @spots && @spots[[x, y]]
@flydata = @spots[[x, y]]
break
else
stickToPositions = findNearbyHealingSpot(x, y)
if stickToPositions
@sy = @sprites["cursor"].y
@sx = @sprites["cursor"].x
@my = @window.y
@mx = @window.x
move_cursor_to(stickToPositions[0], stickToPositions[1])
update_text
# synchronize_cursor # Force sync
end
end
end
break if Input.trigger?(Input::B)
end
dispose
end
def update(update_gfx = true)
@sprites["arrowLeft"].visible = @window.x < 0 && been_to_johto()
@sprites["arrowRight"].visible = @window.x > -1 * (@window["map"].bmp.width - 480)
@sprites["arrowUp"].visible = @window.y < 0
@sprites["arrowDown"].visible = @window.y > -1 * (@window["map"].bmp.height - 320) && been_to_sevii()
if update_gfx
Graphics.update
Input.update
end
intensity = (Graphics.frame_count % 40) * 12
intensity = 480 - intensity if intensity > 240
@window["areahighlight"].opacity = intensity
@i += 1
if @i % CursorAnimateDelay == 0
@sprites["cursor"].src_rect.x += @sprites["cursor"].src_rect.width
@sprites["cursor"].src_rect.x = 0 if @sprites["cursor"].src_rect.x >= @sprites["cursor"].bmp.width
end
if @i % FlyPointAnimateDelay == 0
@window.keys.each do |e|
next unless e.to_s.start_with?("point")
@window[e].src_rect.x += @window[e].src_rect.width
@window[e].src_rect.x = 0 if @window[e].src_rect.x >= @window[e].bmp.width
end
end
if @i % 2 == 0
case @i % 32
when 0...8
@sprites["arrowLeft"].x -= 1
@sprites["arrowRight"].x += 1
@sprites["arrowUp"].y -= 1
@sprites["arrowDown"].y += 1
when 8...24
@sprites["arrowLeft"].x += 1
@sprites["arrowRight"].x -= 1
@sprites["arrowUp"].y += 1
@sprites["arrowDown"].y -= 1
when 24...32
@sprites["arrowLeft"].x -= 1
@sprites["arrowRight"].x += 1
@sprites["arrowUp"].y -= 1
@sprites["arrowDown"].y += 1
end
end
# Cursor movement
if @dirs.include?(DIRECTION_RIGHT)
@hor_count ||= 0
@hor_count += 1
update_text if @hor_count == (CursorMoveSpeed / 2.0).round
@sprites["cursor"].x = @sx + (TileWidth / CursorMoveSpeed.to_f) * @hor_count
if @hor_count == CursorMoveSpeed
@dirs.delete(6)
@hor_count = nil
@sx = nil
end
#print_current_position()
end
if @dirs.include?(DIRECTION_LEFT)
@hor_count ||= 0
@hor_count += 1
update_text if @hor_count == (CursorMoveSpeed / 2.0).round
@sprites["cursor"].x = @sx - (TileWidth / CursorMoveSpeed.to_f) * @hor_count
if @hor_count == CursorMoveSpeed
@dirs.delete(4)
@hor_count = nil
@sx = nil
end
#print_current_position()
end
if @dirs.include?(DIRECTION_UP)
@ver_count ||= 0
@ver_count += 1
update_text if @ver_count == (CursorMoveSpeed / 2.0).round
@sprites["cursor"].y = @sy - (TileHeight / CursorMoveSpeed.to_f) * @ver_count
if @ver_count == CursorMoveSpeed
@dirs.delete(8)
@ver_count = nil
@sy = nil
end
#print_current_position()
end
if @dirs.include?(DIRECTION_DOWN)
@ver_count ||= 0
@ver_count += 1
update_text if @ver_count == (CursorMoveSpeed / 2.0).round
@sprites["cursor"].y = @sy + (TileHeight / CursorMoveSpeed.to_f) * @ver_count
if @ver_count == CursorMoveSpeed
@dirs.delete(2)
@ver_count = nil
@sy = nil
end
#print_current_position()
end
# Map movement
if @mdirs.include?(DIRECTION_RIGHT)
@hor_count ||= 0
@hor_count += 1
update_text if @hor_count == (CursorMoveSpeed / 2.0).round
@window.x = @mx - (TileWidth / CursorMoveSpeed.to_f) * @hor_count
if @hor_count == CursorMoveSpeed
@mdirs.delete(6)
@hor_count = nil
@mx = nil
end
end
if @mdirs.include?(DIRECTION_LEFT)
@hor_count ||= 0
@hor_count += 1
update_text if @hor_count == (CursorMoveSpeed / 2.0).round
@window.x = @mx + (TileWidth / CursorMoveSpeed.to_f) * @hor_count
if @hor_count == CursorMoveSpeed
@mdirs.delete(4)
@hor_count = nil
@mx = nil
end
end
if @mdirs.include?(DIRECTION_UP)
@ver_count ||= 0
@ver_count += 1
update_text if @ver_count == (CursorMoveSpeed / 2.0).round
@window.y = @my + (TileHeight / CursorMoveSpeed.to_f) * @ver_count
if @ver_count == CursorMoveSpeed
@mdirs.delete(8)
@ver_count = nil
@my = nil
end
end
if @mdirs.include?(DIRECTION_DOWN)
@ver_count ||= 0
@ver_count += 1
update_text if @ver_count == (CursorMoveSpeed / 2.0).round
@window.y = @my - (TileHeight / CursorMoveSpeed.to_f) * @ver_count
if @ver_count == CursorMoveSpeed
@mdirs.delete(2)
@ver_count = nil
@my = nil
end
end
end
def print_current_position()
echoln _INTL("({1}, {2})", $PokemonGlobal.regionMapSel[0], $PokemonGlobal.regionMapSel[1])
end
def update_text
location = @data[2].find do |e|
e[0] == $PokemonGlobal.regionMapSel[0] &&
e[1] == $PokemonGlobal.regionMapSel[1]
end
text = ""
text = location[2] if location
poi = ""
poi = location[3] if location && location[3]
@sprites["txt"].draw([
[pbGetMessage(MessageTypes::RegionNames, @region), 16, 0, 0,
Color.new(255, 255, 255), Color.new(0, 0, 0)],
[text, 16, 354, 0, Color.new(255, 255, 255), Color.new(0, 0, 0)],
[poi, 496, 354, 1, Color.new(255, 255, 255), Color.new(0, 0, 0)],
], true)
end
def dispose
showBlk { update(false) }
@sprites.dispose
@window.dispose
@viewport.dispose
@viewport2.dispose
@mapvp.dispose
hideBlk
Input.update
end
end
#==============================================================================#
# Overwrites some old methods to use the new region map #
#==============================================================================#
ItemHandlers::UseInField.add(:TOWNMAP, proc { |item|
pbBetterRegionMap
next 1
})
def pbShowMap(region = -1, wallmap = true)
# pokegear
pbBetterRegionMap(region, true, false, wallmap)
end
def calculatePointsAndCenter(mapwidth)
# Fill the array "points" with all squares of the region map in which the
# species can be found
points = []
encdata = pbLoadEncountersData
minxy = [nil, nil] # top-leftmost tile
maxxy = [nil, nil] # bottom-rightmost tile
for enc in encdata.keys
enctypes = encdata[enc][1]
if pbFindEncounter(enctypes, @species)
mappos = GameData::MapMetadata.get(enc).town_map_position
if true #mappos && mappos[0] == @region #only use 1 region heheh
showpoint = true
for loc in @mapdata[@region][2]
showpoint = false if loc[0] == mappos[1] && loc[1] == mappos[2] &&
loc[7] && !$game_switches[loc[7]]
end
if showpoint
#mapsize = pbGetMetadata(enc, MetadataMapSize)
mapsize = GameData::MapMetadata.get(enc).town_map_size
if mapsize && mapsize[0] && mapsize[0] > 0
sqwidth = mapsize[0]
sqheight = (mapsize[1].length * 1.0 / mapsize[0]).ceil
for i in 0...sqwidth
for j in 0...sqheight
if mapsize[1][i + j * sqwidth, 1].to_i > 0
# work out the upper-leftmost and lower-rightmost tiles
minxy[0] = (minxy[0] == nil || minxy[0] > mappos[1] + i) ? mappos[1] + i : minxy[0]
minxy[1] = (minxy[1] == nil || minxy[1] > mappos[2] + j) ? mappos[2] + j : minxy[1]
maxxy[0] = (maxxy[0] == nil || maxxy[0] < mappos[1] + i) ? mappos[1] + i : maxxy[0]
maxxy[1] = (maxxy[1] == nil || maxxy[1] < mappos[2] + j) ? mappos[2] + j : maxxy[1]
points[mappos[1] + i + (mappos[2] + j) * mapwidth] = true
end
end
end
else
# work out the upper-leftmost and lower-rightmost tiles
minxy[0] = (minxy[0] == nil || minxy[0] > mappos[1]) ? mappos[1] : minxy[0]
minxy[1] = minxy[1] == nil || minxy[1] > mappos[2] ? mappos[2] : minxy[1]
maxxy[0] = (maxxy[0] == nil || maxxy[0] < mappos[1]) ? mappos[1] : maxxy[0]
maxxy[1] = (maxxy[1] == nil || maxxy[1] < mappos[2]) ? mappos[2] : maxxy[1]
points[mappos[1] + mappos[2] * mapwidth] = true
end
end
end
end
end
return [points, minxy, maxxy]
end
class PokemonReadyMenu
def pbStartReadyMenu(moves, items)
commands = [[], []] # Moves, items
for i in moves
commands[0].push([i[0], GameData::Move.get(i[0]).name, true, i[1]])
end
commands[0].sort! { |a, b| a[1] <=> b[1] }
for i in items
commands[1].push([i, GameData::Item.get(i).name, false])
end
commands[1].sort! { |a, b| a[1] <=> b[1] }
@scene.pbStartScene(commands)
loop do
command = @scene.pbShowCommands
break if command == -1
if command[0] == 0 # Use a move
move = commands[0][command[1]][0]
user = $Trainer.party[commands[0][command[1]][3]]
if move == :FLY || move == :TELEPORT
###############################################
pbHideMenu
ret = pbBetterRegionMap(-1, true, true)
pbShowMenu unless ret
###############################################
if ret
$PokemonTemp.flydata = ret
$game_temp.in_menu = false
Kernel.pbUseHiddenMove(user, move)
break
end
else
pbHideMenu
if pbConfirmUseHiddenMove(user, move)
$game_temp.in_menu = false
pbUseHiddenMove(user, move)
break
else
pbShowMenu
end
end
else
# Use an item
item = commands[1][command[1]][0]
pbHideMenu
if ItemHandlers.triggerConfirmUseInField(item)
$game_temp.in_menu = false
break if pbUseKeyItemInField(item)
$game_temp.in_menu = true
end
end
pbShowMenu
end
@scene.pbEndScene
end
end
#
# class PokemonPokedexInfo_Scene
# def drawPageArea
# @sprites["background"].setBitmap(_INTL("Graphics/Pictures/Pokedex/bg_area"))
# overlay = @sprites["overlay"].bitmap
# base = Color.new(88,88,80)
# shadow = Color.new(168,184,184)
# @sprites["areahighlight"].bitmap.clear
#
# mapwidth = @sprites["areamap"].bitmap.width/BetterRegionMap::TileWidth
# data = calculatePointsAndCenter(mapwidth)
#
# points = data[0]
# minxy = data[1]
# maxxy = data[2]
#
# # Draw coloured squares on each square of the region map with a nest
# pointcolor = Color.new(0,248,248)
# pointcolorhl = Color.new(192,248,248)
# sqwidth = PokemonRegionMap_Scene::SQUAREWIDTH
# sqheight = PokemonRegionMap_Scene::SQUAREHEIGHT
#
#
# # Center the window on the center of visible areas
# if minxy[0] != nil && maxxy[0] != nil
# center_x = ((minxy[0]+maxxy[0])/2).round * sqwidth
# center_y = ((minxy[1]+maxxy[1])/2).round * sqheight - 40
# else
# center_x = Settings::SCREEN_WIDTH/2
# center_y = Settings::SCREEN_HEIGHT/2 - 40
# end
#
# windowminx = -1 * (@sprites["areamap"].bmp.width - Settings::SCREEN_WIDTH + 16)
# windowminy = -1 * (@sprites["areamap"].bmp.height - Settings::SCREEN_HEIGHT + 16)
#
# if center_x > (Settings::SCREEN_WIDTH / 2)
# @sprites["areamap"].x = (480 / 2 ) - center_x
# if (@sprites["areamap"].x < windowminx)
# @sprites["areamap"].x = windowminx
# end
# else
# @sprites["areamap"].x = windowminx
# end
# if center_y > (Settings::SCREEN_HEIGHT / 2)
# @sprites["areamap"].y = (320 / 2 ) - center_y
# if @sprites["areamap"].y < windowminy
# @sprites["areamap"].y = windowminy
# end
# else
# @sprites["areamap"].y = windowminy
# end
#
# for j in 0...points.length
# if points[j]
# x = (j%mapwidth)*sqwidth
# x += @sprites["areamap"].x
# y = (j/mapwidth)*sqheight
# y += @sprites["areamap"].y - 8
# @sprites["areahighlight"].bitmap.fill_rect(x,y,sqwidth,sqheight,pointcolor)
# if j-mapwidth<0 || !points[j-mapwidth]
# @sprites["areahighlight"].bitmap.fill_rect(x,y-2,sqwidth,2,pointcolorhl)
# end
# if j+mapwidth>=points.length || !points[j+mapwidth]
# @sprites["areahighlight"].bitmap.fill_rect(x,y+sqheight,sqwidth,2,pointcolorhl)
# end
# if j%mapwidth==0 || !points[j-1]
# @sprites["areahighlight"].bitmap.fill_rect(x-2,y,2,sqheight,pointcolorhl)
# end
# if (j+1)%mapwidth==0 || !points[j+1]
# @sprites["areahighlight"].bitmap.fill_rect(x+sqwidth,y,2,sqheight,pointcolorhl)
# end
# end
# end
#
# # Set the text
# textpos = []
# if points.length==0
# pbDrawImagePositions(overlay,[
# [sprintf("Graphics/Pictures/Pokedex/overlay_areanone"),108,188]
# ])
# textpos.push([_INTL("Area unknown"),Graphics.width/2,Graphics.height/2,2,base,shadow])
# end
# textpos.push([pbGetMessage(MessageTypes::RegionNames,@region),414,44,2,base,shadow])
# textpos.push([_INTL("{1}'s area",PBSpecies.getName(@species)),
# Graphics.width/2,352,2,base,shadow])
#
# textpos.push([_INTL("Full view"),Graphics.width/2,306,2,base,shadow])
# pbDrawTextPositions(overlay,textpos)
# end
# end
#
# class PokemonPokedexInfo_Scene
# def pbScene
# pbPlayCrySpecies(@species,@form)
# loop do
# Graphics.update
# Input.update
# pbUpdate
# dorefresh = false
# if Input.trigger?(Input::A)
# pbSEStop
# pbPlayCrySpecies(@species,@form) if @page==1
# elsif Input.trigger?(Input::B)
# pbPlayCloseMenuSE
# break
# elsif Input.trigger?(Input::C)
# if @page==2 # Area
# pbBetterRegionMap(@region,false,false,false,@species)
# elsif @page==3 # Forms
# if @available.length>1
# pbPlayDecisionSE
# pbChooseForm
# dorefresh = true
# end
# end
# elsif Input.trigger?(Input::UP)
# oldindex = @index
# pbGoToPrevious
# if @index!=oldindex
# pbUpdateDummyPokemon
# @available = pbGetAvailableForms
# pbSEStop
# (@page==1) ? pbPlayCrySpecies(@species,@form) : pbPlayCursorSE
# dorefresh = true
# end
# elsif Input.trigger?(Input::DOWN)
# oldindex = @index
# pbGoToNext
# if @index!=oldindex
# pbUpdateDummyPokemon
# @available = pbGetAvailableForms
# pbSEStop
# (@page==1) ? pbPlayCrySpecies(@species,@form) : pbPlayCursorSE
# dorefresh = true
# end
# elsif Input.trigger?(Input::LEFT)
# oldpage = @page
# @page -= 1
# @page = 1 if @page<1
# @page = 3 if @page>3
# if @page!=oldpage
# pbPlayCursorSE
# dorefresh = true
# end
# elsif Input.trigger?(Input::RIGHT)
# oldpage = @page
# @page += 1
# @page = 1 if @page<1
# @page = 3 if @page>3
# if @page!=oldpage
# pbPlayCursorSE
# dorefresh = true
# end
# end
# if dorefresh
# drawPage(@page)
# end
# end
# return @index
# end
# end

View File

@@ -0,0 +1,232 @@
# # ------------------------------------------------------------------------------
# # Written by Stochastic, except for customTrainerBattle method which is a
# # modified version of pbTrainerBattle method.
# # ------------------------------------------------------------------------------
#
# BR_DRAW = 5
# BR_LOSS = 2
# BR_WIN = 1
#
# # ------------------------------------------------------------------------------
# # species - Name of the species, e.g. "PIKACHU"
# # level - Level
# # moveset - Optional. Array of moves, e.g. [:MUDSLAP, :THUNDERBOLT, :VINEWHIP]
# # If not specified, pokemon will be created with moves learned by leveling.
# # The pokemon doesn't need to be able to learn the given moves, they can be
# # arbitary.
# # ------------------------------------------------------------------------------
# def createPokemon(species, level, helditem=nil, moveset=nil, ability=nil, form=nil, nature=nil, hpev=nil, atkev=nil, defev=nil, speev=nil, spaev=nil, spdev=nil)
# begin
# poke = Pokemon.new(species, level)
# poke.item=(helditem) if helditem
# poke.moves = convertMoves(moveset) if moveset
# poke.ability=(ability) if ability
# poke.form = form if form
# poke.shiny = false
# poke.nature =(nature) if nature
# poke.happiness=0
# poke.iv[0]=hpev
# poke.iv[1]=atkev
# poke.iv[2]=defev
# poke.iv[3]=speev
# poke.iv[4]=spaev
# poke.iv[5]=spdev
#
# poke.calc_stats
# return poke
# end
# end
#
# def convertMoves(moves)
# moves.map! {|m| PBMove.new(getMoveID(m))}
# return moves
# end
#
# # provide move like this; :TACKLE
# def getMoveID(move)
# return getConst(PBMoves,move)
# end
#
# # ------------------------------------------------------------------------------
# # Creates a trainer with specified id, name, party, and optionally, items.
# # Does not depend on defined trainers, only on trainer types
# # ------------------------------------------------------------------------------
# def createTrainer(trainerid,trainername,party,items=[])
#
# name = pbGetMessageFromHash(MessageTypes::TrainerNames, trainername)
#
# trainer_hash = {
# :id_number => 999,
# :trainer_type => trainerid,
# :name => name,
# :version => 0,
# :pokemon => party,
# :items => items
# }
# opponent = GameData::Trainer.new(trainer_hash)
# #opponent.setForeignID($Trainer) if $Trainer
# # opponent.party = party
# return [opponent.to_trainer,items,party]
# end
#
# def init_trainer(trainer_data)
# return (trainer_data) ? trainer_data.to_trainer : nil
# end
#
# # ------------------------------------------------------------------------------
# # Initiates trainer battle. This is a modified pbTrainerBattle method.
# #
# # trainer - custom PokeBattle_Trainer provided by the user
# # endspeech - what the trainer says in-battle when defeated
# # doublebattle - Optional. Set it to true if you want a double battle
# # canlose - Optional. Set it to true if you want your party to be healed after battle,and if you don't want to be sent to a pokemon center if you lose
# # ------------------------------------------------------------------------------
#
# def customTrainerBattle(trainer,endSpeech,doubleBattle=false,canLose=false,outcomeVar=1)
# # If there is another NPC trainer who spotted the player at the same time, and
# # it is possible to have a double battle (the player has 2+ able Pokémon or
# # has a partner trainer), then record this first NPC trainer into
# # $PokemonTemp.waitingTrainer and end this method. That second NPC event will
# # then trigger and cause the battle to happen against this first trainer and
# # themselves.
# if !$PokemonTemp.waitingTrainer && pbMapInterpreterRunning? &&
# ($Trainer.able_pokemon_count > 1 ||
# ($Trainer.able_pokemon_count > 0 && $PokemonGlobal.partner))
# thisEvent = pbMapInterpreter.get_character(0)
# # Find all other triggered trainer events
# triggeredEvents = $game_player.pbTriggeredTrainerEvents([2],false)
# otherEvent = []
# for i in triggeredEvents
# next if i.id==thisEvent.id
# next if $game_self_switches[[$game_map.map_id,i.id,"A"]]
# otherEvent.push(i)
# end
# return false if !trainer
# Events.onTrainerPartyLoad.trigger(nil,trainer)
# # If there is exactly 1 other triggered trainer event, and this trainer has
# # 6 or fewer Pokémon, record this trainer for a double battle caused by the
# # other triggered trainer event
# if otherEvent.length == 1 && trainer.party.length <= Settings::MAX_PARTY_SIZE
# trainer.lose_text = endSpeech if endSpeech && !endSpeech.empty?
# $PokemonTemp.waitingTrainer = [trainer, thisEvent.id]
# return false
# end
# end
# # Set some battle rules
# setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
# setBattleRule("canLose") if canLose
# setBattleRule("double") if doubleBattle || $PokemonTemp.waitingTrainer
# # Perform the battle
# if $PokemonTemp.waitingTrainer
# decision = pbTrainerBattleCore($PokemonTemp.waitingTrainer[0],
# [trainer[0].trainer_type,trainer[0].name,endSpeech]
# )
# else
# decision = pbTrainerCustomBattleCore(trainer,[trainer[0].trainer_type,trainer[0].name,endSpeech]) #trainerPartyID
# end
# # Finish off the recorded waiting trainer, because they have now been battled
# if decision==1 && $PokemonTemp.waitingTrainer # Win
# pbMapInterpreter.pbSetSelfSwitch($PokemonTemp.waitingTrainer[1], "A", true)
# end
# $PokemonTemp.waitingTrainer = nil
# # Return true if the player won the battle, and false if any other result
# return (decision==1)
# end
#
#
# def pbTrainerCustomBattleCore(trainer,*args)
# outcomeVar = $PokemonTemp.battleRules["outcomeVar"] || 1
# canLose = $PokemonTemp.battleRules["canLose"] || false
# # Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode
# if $Trainer.able_pokemon_count == 0 || ($DEBUG && Input.press?(Input::CTRL))
# pbMessage(_INTL("SKIPPING BATTLE...")) if $DEBUG
# pbMessage(_INTL("AFTER WINNING...")) if $DEBUG && $Trainer.able_pokemon_count > 0
# pbSet(outcomeVar,($Trainer.able_pokemon_count == 0) ? 0 : 1) # Treat it as undecided/a win
# $PokemonTemp.clearBattleRules
# $PokemonGlobal.nextBattleBGM = nil
# $PokemonGlobal.nextBattleME = nil
# $PokemonGlobal.nextBattleCaptureME = nil
# $PokemonGlobal.nextBattleBack = nil
# pbMEStop
# return ($Trainer.able_pokemon_count == 0) ? 0 : 1 # Treat it as undecided/a win
# end
# # Record information about party Pokémon to be used at the end of battle (e.g.
# # comparing levels for an evolution check)
# Events.onStartBattle.trigger(nil)
# # Generate trainers and their parties based on the arguments given
# foeTrainers = []
# foeItems = []
# foeEndSpeeches = []
# foeParty = []
# foePartyStarts = []
# for arg in args
# if arg.is_a?(NPCTrainer)
# foeTrainers.push(arg)
# foePartyStarts.push(foeParty.length)
# arg.party.each { |pkmn| foeParty.push(pkmn) }
# foeEndSpeeches.push(arg.lose_text)
# foeItems.push(arg.items)
# elsif arg.is_a?(Array) # [trainer type, trainer name, ID, speech (optional)]
# pbMissingTrainer(arg[0],arg[1],arg[2]) if !trainer
# return 0 if !trainer
# Events.onTrainerPartyLoad.trigger(nil,trainer)
# foeTrainers.push(trainer)
# foePartyStarts.push(foeParty.length)
# trainer.party.each { |pkmn| foeParty.push(pkmn) }
# foeEndSpeeches.push(arg[3] || trainer.lose_text)
# foeItems.push(trainer.items)
# else
# raise _INTL("Expected NPCTrainer or array of trainer data, got {1}.", arg)
# end
# end
# # Calculate who the player trainer(s) and their party are
# playerTrainers = [$Trainer]
# playerParty = $Trainer.party
# playerPartyStarts = [0]
# room_for_partner = (foeParty.length > 1)
# if !room_for_partner && $PokemonTemp.battleRules["size"] &&
# !["single", "1v1", "1v2", "1v3"].include?($PokemonTemp.battleRules["size"])
# room_for_partner = true
# end
# if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && room_for_partner
# ally = NPCTrainer.new($PokemonGlobal.partner[1], $PokemonGlobal.partner[0])
# ally.id = $PokemonGlobal.partner[2]
# ally.party = $PokemonGlobal.partner[3]
# playerTrainers.push(ally)
# playerParty = []
# $Trainer.party.each { |pkmn| playerParty.push(pkmn) }
# playerPartyStarts.push(playerParty.length)
# ally.party.each { |pkmn| playerParty.push(pkmn) }
# setBattleRule("double") if !$PokemonTemp.battleRules["size"]
# end
# # Create the battle scene (the visual side of it)
# scene = pbNewBattleScene
# # Create the battle class (the mechanics side of it)
# battle = PokeBattle_Battle.new(scene,playerParty,foeParty,playerTrainers,foeTrainers)
# battle.party1starts = playerPartyStarts
# battle.party2starts = foePartyStarts
# battle.items = foeItems
# battle.endSpeeches = foeEndSpeeches
# # Set various other properties in the battle class
# pbPrepareBattle(battle)
# $PokemonTemp.clearBattleRules
# # End the trainer intro music
# Audio.me_stop
# # Perform the battle itself
# decision = 0
# pbBattleAnimation(pbGetTrainerBattleBGM(foeTrainers),(battle.singleBattle?) ? 1 : 3,foeTrainers) {
# pbSceneStandby {
# decision = battle.pbStartBattle
# }
# pbAfterBattle(decision,canLose)
# }
# Input.update
# # Save the result of the battle in a Game Variable (1 by default)
# # 0 - Undecided or aborted
# # 1 - Player won
# # 2 - Player lost
# # 3 - Player or wild Pokémon ran from battle, or player forfeited the match
# # 5 - Draw
# pbSet(outcomeVar,decision)
# return decision
# end

View File

@@ -0,0 +1,118 @@
module SwitchFinder
def self.search_switch_trigger(switch_id)
results = []
mapinfos = $RPGVX ? load_data("Data/MapInfos.rvdata") : load_data("Data/MapInfos.rxdata")
mapinfos.each_key do |map_id|
map = load_data(sprintf("Data/Map%03d.rxdata", map_id))
map.events.each_value do |event|
event.pages.each do |page,index|
# Check conditions for each page
if page.condition.switch1_id == switch_id || page.condition.switch2_id == switch_id
results.push("Map #{map_id}, Event #{event.id} (#{event.x},#{event.y}), Trigger for page #{index}")
end
# Check commands for switch control
page.list.each do |command|
if command.code == 122 && command.parameters[0] == switch_id
results.push("Map #{map_id}, Event #{event.id} (#{event.x},#{event.y}), Command #{command.code}")
end
end
end
end
end
echoln "Switch #{switch_id} found:" + results.to_s
end
def self.search_switch_anyUse(switch_id)
results = []
# Load map info based on RPG Maker version
mapinfos = $RPGVX ? load_data("Data/MapInfos.rvdata") : load_data("Data/MapInfos.rxdata")
# Iterate over each map
mapinfos.each_key do |map_id|
map = load_data(sprintf("Data/Map%03d.rxdata", map_id))
mapinfo = mapinfos[map_id]
# Iterate over each event in the map
map.events.each_value do |event|
# Iterate over each page in the event
event.pages.each_with_index do |page, page_index|
# Check conditions for each page
if page.condition.switch1_id == switch_id || page.condition.switch2_id == switch_id
results.push("Map #{map_id}: #{mapinfo.name}, Event #{event.id} (#{event.x},#{event.y}), Trigger for page #{page_index + 1}")
end
# Iterate over each command in the page
page.list.each_with_index do |command, command_index|
# Check commands for switch control
if command.code == 121
# Command 121 is Control Switches
range_start = command.parameters[0]
range_end = command.parameters[1]
value = command.parameters[2]
# Check if the switch is within the specified range
if range_start <= switch_id && switch_id <= range_end
action = value == 0 ? "ON" : "OFF"
results.push("Map #{map_id}: #{mapinfo.name}, Event #{event.id} (#{event.x},#{event.y}), Command #{command_index + 1}: Set Switch to #{action}")
end
# Check script calls for switch control
elsif command.code == 355
# Command 355 is Call Script
script_text = command.parameters[0]
# Collect multi-line scripts
next_command_index = command_index + 1
while page.list[next_command_index]&.code == 655
script_text += page.list[next_command_index].parameters[0]
next_command_index += 1
end
# Use a regular expression to find switch manipulations
if script_text.match?(/\$game_switches\[\s*#{switch_id}\s*\]/)
results.push("Map #{map_id}: #{mapinfo.name}, Event #{event.id} (#{event.x},#{event.y}), Command #{command_index + 1}: Script Manipulation")
end
end
end
end
end
end
# Output the results
results = "Switch #{switch_id} found:\n" + results.join("\n")
echoln results
return results
end
def self.find_unused_switches(total_switches)
unused_switches = []
# Check each switch from 1 to total_switches
(1..total_switches).each do |switch_id|
results = search_switch_anyUse(switch_id)
report = "Switch #{switch_id}:\n#{results}"
unused_switches << report
end
# Export to a text file
File.open("unused_switches.txt", "w") do |file|
file.puts "Unused Switches:"
unused_switches.each do |switch_id|
file.puts "\n\n#{switch_id}"
end
end
echoln "#{unused_switches.length} unused switches found. Exported to unused_switches.txt."
end
end
# Example usage: Replace 100 with the switch ID you want to search
# SwitchFinder.search_switch(100)

View File

@@ -0,0 +1,51 @@
def Kernel.pbDisplayText(message,xposition,yposition,z=nil, baseColor=nil, shadowColor=nil)
if @hud==nil
@hud = []
end
# Draw the text
baseColor= baseColor ? baseColor : Color.new(72,72,72)
shadowColor= shadowColor ? shadowColor : Color.new(160,160,160)
sprite = BitmapSprite.new(Graphics.width,Graphics.height,@viewport1)
if z != nil
sprite.z=z
end
@hud.push(sprite)
text1=_INTL(message)
textPosition=[
[text1,xposition,yposition,2,baseColor,shadowColor],
]
pbSetSystemFont(@hud[-1].bitmap)
pbDrawTextPositions(@hud[0].bitmap,textPosition)
end
def Kernel.pbDisplayNumber(number,xposition,yposition)
@numT = []
# Draw the text
baseColor=Color.new(72,72,72)
shadowColor=Color.new(160,160,160)
@numT.push(BitmapSprite.new(Graphics.width,Graphics.height,@viewport1))
text1=_INTL(number.to_s)
textPosition=[
[text1,xposition,yposition,2,baseColor,shadowColor],
]
pbSetSystemFont(@numT[-1].bitmap)
pbDrawTextPositions(@numT[0].bitmap,textPosition)
end
def Kernel.pbClearNumber()
if @numT != nil then
for sprite in @numT
sprite.dispose
end
@numT.clear
end
end
def Kernel.pbClearText()
if @hud != nil then
for sprite in @hud
sprite.dispose
end
@hud.clear
end
end

View File

@@ -0,0 +1,259 @@
class PokeBattle_Battler
attr_accessor :ability_id
attr_accessor :ability2_id
#Primary ability utility methods for battlers class
def ability
return GameData::Ability.try_get(@ability_id)
end
def ability=(value)
new_ability = GameData::Ability.try_get(value)
@ability_id = (new_ability) ? new_ability.id : nil
end
def abilityName
abil = self.ability
return (abil) ? abil.name : ""
end
#Secondary ability utility methods for battlers class
def ability2
return nil if !$game_switches[SWITCH_DOUBLE_ABILITIES]
return GameData::Ability.try_get(@ability2_id)
end
def ability2=(value)
return if !$game_switches[SWITCH_DOUBLE_ABILITIES]
new_ability = GameData::Ability.try_get(value)
@ability2_id = (new_ability) ? new_ability.id : nil
end
def ability2Name
abil = self.ability2
return (abil) ? abil.name : ""
end
#Ability logic overrides
def hasActiveAbility?(check_ability, ignore_fainted = false)
return hasActiveAbilityDouble?(check_ability, ignore_fainted) if $game_switches[SWITCH_DOUBLE_ABILITIES]
return false if !abilityActive?(ignore_fainted)
return check_ability.include?(@ability_id) if check_ability.is_a?(Array)
return self.ability == check_ability
end
def hasActiveAbilityDouble?(check_ability, ignore_fainted = false)
return false if !$game_switches[SWITCH_DOUBLE_ABILITIES]
return false if !abilityActive?(ignore_fainted)
if check_ability.is_a?(Array)
return check_ability.include?(@ability_id) || check_ability.include?(@ability2_id)
end
return self.ability == check_ability || self.ability2 == check_ability
end
def triggerAbilityEffectsOnHit(move, user, target)
# Target's ability
if target.abilityActive?(true)
oldHP = user.hp
BattleHandlers.triggerTargetAbilityOnHit(target.ability, user, target, move, @battle)
BattleHandlers.triggerTargetAbilityOnHit(target.ability2, user, target, move, @battle) if $game_switches[SWITCH_DOUBLE_ABILITIES] && target.ability2
user.pbItemHPHealCheck if user.hp < oldHP
end
# User's ability
if user.abilityActive?(true)
BattleHandlers.triggerUserAbilityOnHit(user.ability, user, target, move, @battle)
BattleHandlers.triggerUserAbilityOnHit(user.ability2, user, target, move, @battle) if $game_switches[SWITCH_DOUBLE_ABILITIES] && user.ability2
user.pbItemHPHealCheck
end
end
def pbCheckDamageAbsorption(user, target)
# Substitute will take the damage
if target.effects[PBEffects::Substitute] > 0 && !ignoresSubstitute?(user) &&
(!user || user.index != target.index)
target.damageState.substitute = true
return
end
# Disguise will take the damage
if !@battle.moldBreaker && target.isFusionOf(:MIMIKYU) &&
target.form == 0 && (target.ability == :DISGUISE || target.ability2 == :DISGUISE)
target.damageState.disguise = true
return
end
end
# Called when a Pokémon (self) enters battle, at the end of each move used,
# and at the end of each round.
def pbContinualAbilityChecks(onSwitchIn = false)
# Check for end of primordial weather
@battle.pbEndPrimordialWeather
# Trace
if $game_switches[SWITCH_DOUBLE_ABILITIES] && onSwitchIn
displayOpponentDoubleAbilities()
else
if hasActiveAbility?(:TRACE)
# NOTE: In Gen 5 only, Trace only triggers upon the Trace bearer switching
# in and not at any later times, even if a traceable ability turns
# up later. Essentials ignores this, and allows Trace to trigger
# whenever it can even in the old battle mechanics.
choices = []
@battle.eachOtherSideBattler(@index) do |b|
next if b.ungainableAbility? ||
[:POWEROFALCHEMY, :RECEIVER, :TRACE].include?(b.ability_id)
choices.push(b)
end
if choices.length > 0
choice = choices[@battle.pbRandom(choices.length)]
@battle.pbShowAbilitySplash(self)
self.ability = choice.ability
@battle.pbDisplay(_INTL("{1} traced {2}'s {3}!", pbThis, choice.pbThis(true), choice.abilityName))
@battle.pbHideAbilitySplash(self)
if !onSwitchIn && (unstoppableAbility? || abilityActive?)
BattleHandlers.triggerAbilityOnSwitchIn(self.ability, self, @battle)
end
end
end
end
end
def displayOpponentDoubleAbilities()
@battle.eachOtherSideBattler(@index) do |battler|
@battle.pbShowPrimaryAbilitySplash(battler,true)
@battle.pbShowSecondaryAbilitySplash(battler,true) if battler.isFusion?()
@battle.pbHideAbilitySplash(battler)
end
end
end
class Pokemon
attr_writer :ability_index
attr_writer :ability2_index
#Primary ability utility methods for pokemon class
def ability_index
@ability_index = (@personalID & 1) if !@ability_index
return @ability_index
end
def ability
return GameData::Ability.try_get(ability_id())
end
def ability=(value)
return if value && !GameData::Ability.exists?(value)
@ability = (value) ? GameData::Ability.get(value).id : value
end
#Secondary ability utility methods for pokemon class
def ability2_index
return nil if !$game_switches[SWITCH_DOUBLE_ABILITIES]
@ability2_index = (@personalID & 1) if !@ability2_index
return @ability2_index
end
def ability2
return nil if !$game_switches[SWITCH_DOUBLE_ABILITIES]
return GameData::Ability.try_get(ability2_id())
end
def ability2=(value)
return if !$game_switches[SWITCH_DOUBLE_ABILITIES]
return if value && !GameData::Ability.exists?(value)
@ability2 = (value) ? GameData::Ability.get(value).id : value
end
def ability_id
if !@ability
sp_data = species_data
abil_index = ability_index
#echoln abil_index
if abil_index >= 2 # Hidden ability
@ability = sp_data.hidden_abilities[abil_index - 2]
abil_index = (@personalID & 1) if !@ability
end
if !@ability # Natural ability or no hidden ability defined
if $game_switches[SWITCH_NO_LEVELS_MODE]
@ability = sp_data.abilities[0] || sp_data.abilities[0]
@ability2 = sp_data.abilities[1] || sp_data.abilities[0]
else
@ability = sp_data.abilities[abil_index] || sp_data.abilities[0]
end
end
end
return @ability
end
def ability2_id
return nil if !$game_switches[SWITCH_DOUBLE_ABILITIES]
if !@ability2
sp_data = species_data
abil_index = ability_index
if abil_index >= 2 # Hidden ability
@ability2 = sp_data.hidden_abilities[abil_index - 2]
abil_index = (@personalID & 1) if !@ability2
end
if !@ability2 # Natural ability or no hidden ability defined
@ability2 = sp_data.abilities[abil_index] || sp_data.abilities[0]
end
end
return @ability2
end
def adjustHPForWonderGuard(stats)
return self.ability == :WONDERGUARD ? 1 : stats[:HP] || ($game_switches[SWITCH_DOUBLE_ABILITIES] && self.ability2 == :WONDERGUARD)
end
end
class PokemonFusionScene
def pbChooseAbility(ability1Id,ability2Id)
ability1 = GameData::Ability.get(ability1Id)
ability2 = GameData::Ability.get(ability2Id)
availableNatures = []
availableNatures << @pokemon1.nature
availableNatures << @pokemon2.nature
setAbilityAndNatureAndNickname([ability1,ability2], availableNatures)
end
def setAbilityAndNatureAndNickname(abilitiesList, naturesList)
clearUIForMoves
if $game_switches[SWITCH_DOUBLE_ABILITIES]
scene = FusionSelectOptionsScene.new(nil, naturesList, @pokemon1, @pokemon2)
screen = PokemonOptionScreen.new(scene)
screen.pbStartScreen
@pokemon1.ability = abilitiesList[0]
@pokemon1.ability2 = abilitiesList[1]
else
scene = FusionSelectOptionsScene.new(abilitiesList, naturesList, @pokemon1, @pokemon2)
screen = PokemonOptionScreen.new(scene)
screen.pbStartScreen
selectedAbility = scene.selectedAbility
@pokemon1.body_original_ability_index = @pokemon1.ability_index
@pokemon1.head_original_ability_index = @pokemon2.ability_index
@pokemon1.ability = selectedAbility
@pokemon1.ability_index = getAbilityIndexFromID(selectedAbility.id,@pokemon1)
end
@pokemon1.nature = scene.selectedNature
if scene.hasNickname
@pokemon1.name = scene.nickname
end
end
end

View File

@@ -0,0 +1,389 @@
#
# module BattleHandlers
# #
# # Speed calculation
# #
#
# def self.triggerSpeedCalcAbility(ability, battler, mult)
# ability1 = ability
# ability2 = battler.ability2
# calculateAbilitySpeedMultiplier(ability1, battler, mult)
# if $game_switches[SWITCH_DOUBLE_ABILITIES]
# calculateAbilitySpeedMultiplier(ability2, battler, mult)
# end
# return mult
# end
#
# def self.calculateAbilitySpeedMultiplier(ability, battler, mult)
# ability1 = ability
# ability2 = battler.ability2
# ret = SpeedCalcAbility.trigger(ability1, battler, mult) || SpeedCalcAbility.trigger(ability2, battler, mult)
# return (ret != nil) ? ret : mult
# end
#
# def self.triggerWeightCalcAbility(ability,battler,w)
# ability1 = ability
# ability2 = battler.ability2
# ret = WeightCalcAbility.trigger(ability1,battler,w) || WeightCalcAbility.trigger(ability2,battler,w)
# return (ret!=nil) ? ret : w
# end
#
#
#
#
# def self.triggerEOREffectAbility(ability,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
#
# EOREffectAbility.trigger(ability1,battler,battle)
# EOREffectAbility.trigger(ability2,battler,battle)
# end
#
# def self.triggerEORGainItemAbility(ability,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
#
# EORGainItemAbility.trigger(ability1,battler,battle)
# EORGainItemAbility.trigger(ability2,battler,battle)
# end
#
# def self.triggerCertainSwitchingUserAbility(ability,switcher,battle)
# ability1 = ability
# ability2 = switcher.ability2
#
# ret = CertainSwitchingUserAbility.trigger(ability1,switcher,battle) || CertainSwitchingUserAbility.trigger(ability2,switcher,battle)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerCertainSwitchingUserAbility(ability,switcher,battle)
# ability1 = ability
# ability2 = switcher.ability2
#
# ret = CertainSwitchingUserAbility.trigger(ability1,switcher,battle) || CertainSwitchingUserAbility.trigger(ability2,switcher,battle)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerTrappingTargetAbility(ability,switcher,bearer,battle)
# ability1 = ability
# ability2 = switcher.ability2
# ret = TrappingTargetAbility.trigger(ability1,switcher,bearer,battle) || TrappingTargetAbility.trigger(ability2,switcher,bearer,battle)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerAbilityOnSwitchIn(ability,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
# AbilityOnSwitchIn.trigger(ability1,battler,battle)
# AbilityOnSwitchIn.trigger(ability2,battler,battle)
# end
#
# def self.triggerAbilityOnSwitchOut(ability,battler,endOfBattle)
# ability1 = ability
# ability2 = battler.ability2
# AbilityOnSwitchOut.trigger(ability1,battler,endOfBattle)
# AbilityOnSwitchOut.trigger(ability2,battler,endOfBattle)
# end
#
# def self.triggerAbilityChangeOnBattlerFainting(ability,battler,fainted,battle)
# ability1 = ability
# ability2 = battler.ability2
# AbilityChangeOnBattlerFainting.trigger(ability1,battler,fainted,battle)
# AbilityChangeOnBattlerFainting.trigger(ability2,battler,fainted,battle)
#
# end
#
# def self.triggerAbilityOnBattlerFainting(ability,battler,fainted,battle)
# ability1 = ability
# ability2 = battler.ability2
# AbilityOnBattlerFainting.trigger(ability1,battler,fainted,battle)
# AbilityOnBattlerFainting.trigger(ability2,battler,fainted,battle)
# end
#
#
# def self.triggerRunFromBattleAbility(ability,battler)
# ability1 = ability
# ability2 = battler.ability2
# ret = RunFromBattleAbility.trigger(ability1,battler) || RunFromBattleAbility.trigger(ability2,battler)
# return (ret!=nil) ? ret : false
# end
# ########
# # FROM HERE
# #
#
# def self.triggerAbilityOnHPDroppedBelowHalf(ability,user,battle)
# ability1 = ability
# ability2 = user.ability2
# ret = AbilityOnHPDroppedBelowHalf.trigger(ability1,user,battle) || AbilityOnHPDroppedBelowHalf.trigger(ability2,user,battle)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerStatusCheckAbilityNonIgnorable(ability,battler,status)
# ability1 = ability
# ability2 = battler.ability2
# ret = StatusCheckAbilityNonIgnorable.trigger(ability1,battler,status) || StatusCheckAbilityNonIgnorable.trigger(ability2,battler,status)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerStatusImmunityAbility(ability,battler,status)
# ability1 = ability
# ability2 = battler.ability2
# ret = StatusImmunityAbility.trigger(ability1,battler,status) || StatusImmunityAbility.trigger(ability2,battler,status)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerStatusImmunityAbilityNonIgnorable(ability,battler,status)
# ability1 = ability
# ability2 = battler.ability2
# ret = StatusImmunityAbilityNonIgnorable.trigger(ability1,battler,status) || StatusImmunityAbilityNonIgnorable.trigger(ability2,battler,status)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerStatusImmunityAllyAbility(ability,battler,status)
# ability1 = ability
# ability2 = battler.ability2
# ret = StatusImmunityAllyAbility.trigger(ability1,battler,status) || StatusImmunityAllyAbility.trigger(ability2,battler,status)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerAbilityOnStatusInflicted(ability,battler,user,status)
# ability1 = ability
# ability2 = battler.ability2
# AbilityOnStatusInflicted.trigger(ability1,battler,user,status)
# AbilityOnStatusInflicted.trigger(ability2,battler,user,status)
# end
#
# def self.triggerStatusCureAbility(ability,battler)
# ability1 = ability
# ability2 = battler.ability2
# ret = StatusCureAbility.trigger(ability1,battler) || StatusCureAbility.trigger(ability2,battler)
# return (ret!=nil) ? ret : false
# end
#
#
# def self.triggerStatLossImmunityAbility(ability,battler,stat,battle,showMessages)
# ability1 = ability
# ability2 = battler.ability2
# ret = StatLossImmunityAbility.trigger(ability1,battler,stat,battle,showMessages) || StatLossImmunityAbility.trigger(ability2,battler,stat,battle,showMessages)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerStatLossImmunityAbilityNonIgnorable(ability,battler,stat,battle,showMessages)
# ability1 = ability
# ability2 = battler.ability2
# ret = StatLossImmunityAbilityNonIgnorable.trigger(ability1,battler,stat,battle,showMessages) || StatLossImmunityAbilityNonIgnorable.trigger(ability2,battler,stat,battle,showMessages)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerStatLossImmunityAllyAbility(ability,bearer,battler,stat,battle,showMessages)
# ability1 = ability
# ability2 = battler.ability2
# ret = StatLossImmunityAllyAbility.trigger(ability1,bearer,battler,stat,battle,showMessages) || StatLossImmunityAllyAbility.trigger(ability2,bearer,battler,stat,battle,showMessages)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerAbilityOnStatGain(ability,battler,stat,user)
# ability1 = ability
# ability2 = battler.ability2
# AbilityOnStatGain.trigger(ability1,battler,stat,user)
# AbilityOnStatGain.trigger(ability2,battler,stat,user)
# end
#
# def self.triggerAbilityOnStatLoss(ability,battler,stat,user)
# ability1 = ability
# ability2 = battler.ability2
# AbilityOnStatLoss.trigger(ability1,battler,stat,user)
# AbilityOnStatLoss.trigger(ability2,battler,stat,user)
# end
#
# #=============================================================================
#
#
# def self.triggerPriorityChangeAbility(ability,battler,move,pri)
# ability1 = ability
# ability2 = battler.ability2
# ret = PriorityChangeAbility.trigger(ability1,battler,move,pri) || PriorityChangeAbility.trigger(ability2,battler,move,pri)
# return (ret!=nil) ? ret : pri
# end
#
# def self.triggerPriorityBracketChangeAbility(ability,battler,subPri,battle)
# ability1 = ability
# ability2 = battler.ability2
# ret = PriorityBracketChangeAbility.trigger(ability1,battler,subPri,battle) || PriorityBracketChangeAbility.trigger(ability2,battler,subPri,battle)
# return (ret!=nil) ? ret : subPri
# end
#
# def self.triggerPriorityBracketUseAbility(ability,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
# PriorityBracketUseAbility.trigger(ability1,battler,battle)
# PriorityBracketUseAbility.trigger(ability2,battler,battle)
# end
#
# #=============================================================================
#
# def self.triggerAbilityOnFlinch(ability,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
# AbilityOnFlinch.trigger(ability1,battler,battle)
# AbilityOnFlinch.trigger(ability2,battler,battle)
# end
#
# def self.triggerMoveBlockingAbility(ability,bearer,user,targets,move,battle)
# ability1 = ability
# ability2 = bearer.ability2
# ret = MoveBlockingAbility.trigger(ability1,bearer,user,targets,move,battle) || MoveBlockingAbility.trigger(ability2,bearer,user,targets,move,battle)
# return (ret!=nil) ? ret : false
# end
#
# def self.triggerMoveImmunityTargetAbility(ability,user,target,move,type,battle)
# ability1 = ability
# ability2 = user.ability2
# ret = MoveImmunityTargetAbility.trigger(ability1,user,target,move,type,battle) || MoveImmunityTargetAbility.trigger(ability2,user,target,move,type,battle)
# return (ret!=nil) ? ret : false
# end
#
# #=============================================================================
#
# def self.triggerMoveBaseTypeModifierAbility(ability,user,move,type)
# ability1 = ability
# ability2 = user.ability2
# ret = MoveBaseTypeModifierAbility.trigger(ability1,user,move,type) || MoveBaseTypeModifierAbility.trigger(ability2,user,move,type)
# return (ret!=nil) ? ret : type
# end
#
# #=============================================================================
#
# def self.triggerAccuracyCalcUserAbility(ability,mods,user,target,move,type)
# ability1 = ability
# ability2 = user.ability2
# AccuracyCalcUserAbility.trigger(ability1,mods,user,target,move,type)
# AccuracyCalcUserAbility.trigger(ability2,mods,user,target,move,type)
# end
#
# def self.triggerAccuracyCalcUserAllyAbility(ability,mods,user,target,move,type)
# ability1 = ability
# ability2 = user.ability2
# AccuracyCalcUserAllyAbility.trigger(ability1,mods,user,target,move,type)
# AccuracyCalcUserAllyAbility.trigger(ability2,mods,user,target,move,type)
# end
#
# def self.triggerAccuracyCalcTargetAbility(ability,mods,user,target,move,type)
# ability1 = ability
# ability2 = user.ability2
# AccuracyCalcTargetAbility.trigger(ability1,mods,user,target,move,type)
# AccuracyCalcTargetAbility.trigger(ability2,mods,user,target,move,type)
# end
# #=============================================================================
#
# def self.triggerDamageCalcUserAbility(ability,user,target,move,mults,baseDmg,type)
# ability1 = ability
# ability2 = user.ability2
# DamageCalcUserAbility.trigger(ability1,user,target,move,mults,baseDmg,type)
# DamageCalcUserAbility.trigger(ability2,user,target,move,mults,baseDmg,type)
# end
#
# def self.triggerDamageCalcUserAllyAbility(ability,user,target,move,mults,baseDmg,type)
# ability1 = ability
# ability2 = target.ability2
# DamageCalcUserAllyAbility.trigger(ability1,user,target,move,mults,baseDmg,type)
# DamageCalcUserAllyAbility.trigger(ability2,user,target,move,mults,baseDmg,type)
# end
#
# def self.triggerDamageCalcTargetAbility(ability,user,target,move,mults,baseDmg,type)
# ability1 = ability
# ability2 = target.ability2
# DamageCalcTargetAbility.trigger(ability1,user,target,move,mults,baseDmg,type)
# DamageCalcTargetAbility.trigger(ability2,user,target,move,mults,baseDmg,type)
# end
#
# def self.triggerDamageCalcTargetAbilityNonIgnorable(ability,user,target,move,mults,baseDmg,type)
# ability1 = ability
# ability2 = target.ability2
# DamageCalcTargetAbilityNonIgnorable.trigger(ability1,user,target,move,mults,baseDmg,type)
# DamageCalcTargetAbilityNonIgnorable.trigger(ability2,user,target,move,mults,baseDmg,type)
# end
#
# def self.triggerDamageCalcTargetAllyAbility(ability,user,target,move,mults,baseDmg,type)
# ability1 = ability
# ability2 = target.ability2
# DamageCalcTargetAllyAbility.trigger(ability1,user,target,move,mults,baseDmg,type)
# DamageCalcTargetAllyAbility.trigger(ability2,user,target,move,mults,baseDmg,type)
# end
#
# #=============================================================================
#
# def self.triggerCriticalCalcUserAbility(ability,user,target,c)
# ability1 = ability
# ability2 = user.ability2
# ret = CriticalCalcUserAbility.trigger(ability1,user,target,c) || CriticalCalcUserAbility.trigger(ability2,user,target,c)
# return (ret!=nil) ? ret : c
# end
#
# def self.triggerCriticalCalcTargetAbility(ability,user,target,c)
# ability1 = ability
# ability2 = target.ability2
# ret = CriticalCalcTargetAbility.trigger(ability1,user,target,c) || CriticalCalcTargetAbility.trigger(ability2,user,target,c)
# return (ret!=nil) ? ret : c
# end
# #=============================================================================
#
# def self.triggerTargetAbilityOnHit(ability,user,target,move,battle)
# ability1 = ability
# ability2 = target.ability2
# TargetAbilityOnHit.trigger(ability1,user,target,move,battle)
# TargetAbilityOnHit.trigger(ability2,user,target,move,battle)
# end
#
# def self.triggerUserAbilityOnHit(ability,user,target,move,battle)
# ability1 = ability
# ability2 = user.ability2
# UserAbilityOnHit.trigger(ability1,user,target,move,battle)
# UserAbilityOnHit.trigger(ability2,user,target,move,battle)
# end
# #=============================================================================
#
# def self.triggerUserAbilityEndOfMove(ability,user,targets,move,battle)
# ability1 = ability
# ability2 = user.ability2
# UserAbilityEndOfMove.trigger(ability1,user,targets,move,battle)
# UserAbilityEndOfMove.trigger(ability2,user,targets,move,battle)
# end
#
# def self.triggerTargetAbilityAfterMoveUse(ability,target,user,move,switched,battle)
# ability1 = ability
# ability2 = target.ability2
# TargetAbilityAfterMoveUse.trigger(ability1,target,user,move,switched,battle)
# TargetAbilityAfterMoveUse.trigger(ability2,target,user,move,switched,battle)
# end
#
# #=============================================================================
#
# def self.triggerEORWeatherAbility(ability,weather,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
# EORWeatherAbility.trigger(ability1,weather,battler,battle)
# EORWeatherAbility.trigger(ability2,weather,battler,battle)
# end
#
# def self.triggerEORHealingAbility(ability,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
# EORHealingAbility.trigger(ability1,battler,battle)
# EORHealingAbility.trigger(ability2,battler,battle)
# end
#
# def self.triggerEOREffectAbility(ability,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
# EOREffectAbility.trigger(ability1,battler,battle)
# EOREffectAbility.trigger(ability2,battler,battle)
# end
#
# def self.triggerEORGainItemAbility(ability,battler,battle)
# ability1 = ability
# ability2 = battler.ability2
# EORGainItemAbility.trigger(ability1,battler,battle)
# EORGainItemAbility.trigger(ability2,battler,battle)
# end
#
# end

View File

@@ -0,0 +1,130 @@
#
# class AbilitySplashBar < SpriteWrapper
# def refresh
# self.bitmap.clear
# return if !@battler
# textPos = []
# textX = (@side==0) ? 10 : self.bitmap.width-8
# # Draw Pokémon's name
# textPos.push([_INTL("{1}'s",@battler.name),textX,-4,@side==1,
# TEXT_BASE_COLOR,TEXT_SHADOW_COLOR,true])
# # Draw Pokémon's ability
# textPos.push([@battler.abilityName,textX,26,@side==1,
# TEXT_BASE_COLOR,TEXT_SHADOW_COLOR,true])
# pbDrawTextPositions(self.bitmap,textPos)
#
# #2nd ability
# if $game_switches[SWITCH_DOUBLE_ABILITIES]
# textPos.push([@battler.ability2Name,textX,26,@side==1,
# TEXT_BASE_COLOR,TEXT_SHADOW_COLOR,true])
# pbDrawTextPositions(self.bitmap,textPos)
# end
# end
# end
class AbilitySplashDisappearAnimation < PokeBattle_Animation
def initialize(sprites,viewport,side)
@side = side
super(sprites,viewport)
end
def createProcesses
return if !@sprites["abilityBar_#{@side}"]
bar = addSprite(@sprites["abilityBar_#{@side}"])
bar2 = addSprite(@sprites["ability2Bar_#{@side}"]) if @sprites["ability2Bar_#{@side}"]
dir = (@side==0) ? -1 : 1
bar.moveDelta(0,8,dir*Graphics.width/2,0)
bar2.moveDelta(0,8,dir*Graphics.width/2,0) if bar2
bar.setVisible(8,false)
bar2.setVisible(8,false) if bar2
end
end
class PokeBattle_Scene
def pbShowAbilitySplash(battler,secondAbility=false, abilityName=nil)
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
side = battler.index%2
if secondAbility
pbHideAbilitySplash(battler) if @sprites["ability2Bar_#{side}"].visible
else
pbHideAbilitySplash(battler) if @sprites["abilityBar_#{side}"].visible
end
if abilityName
@sprites["abilityBar_#{side}"].ability_name = abilityName if !secondAbility
@sprites["ability2Bar_#{side}"].ability_name = abilityName if secondAbility
end
@sprites["abilityBar_#{side}"].battler = battler
@sprites["ability2Bar_#{side}"].battler = battler if @sprites["ability2Bar_#{side}"]
abilitySplashAnim = AbilitySplashAppearAnimation.new(@sprites,@viewport,side,secondAbility)
loop do
abilitySplashAnim.update
pbUpdate
break if abilitySplashAnim.animDone?
end
abilitySplashAnim.dispose
end
end
class PokeBattle_Battle
def pbShowSecondaryAbilitySplash(battler,delay=false,logTrigger=true)
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
@scene.pbShowAbilitySplash(battler,true)
if delay
Graphics.frame_rate.times { @scene.pbUpdate } # 1 second
end
end
def pbShowPrimaryAbilitySplash(battler,delay=false,logTrigger=true)
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
@scene.pbShowAbilitySplash(battler,false)
if delay
Graphics.frame_rate.times { @scene.pbUpdate } # 1 second
end
end
end
class FusionSelectOptionsScene < PokemonOption_Scene
def pbGetOptions(inloadscreen = false)
options = []
if shouldSelectNickname
options << EnumOption.new(_INTL("Nickname"), [_INTL(@pokemon1.name), _INTL(@pokemon2.name)],
proc { 0 },
proc { |value|
if value ==0
@nickname = @pokemon1.name
else
@nickname = @pokemon2.name
end
}, "Select the Pokémon's nickname")
end
if @abilityList != nil
options << EnumOption.new(_INTL("Ability"), [_INTL(getAbilityName(@abilityList[0])), _INTL(getAbilityName(@abilityList[1]))],
proc { 0 },
proc { |value|
@selectedAbility=@abilityList[value]
}, [getAbilityDescription(@abilityList[0]), getAbilityDescription(@abilityList[1])]
)
end
options << EnumOption.new(_INTL("Nature"), [_INTL(getNatureName(@natureList[0])), _INTL(getNatureName(@natureList[1]))],
proc { 0 },
proc { |value|
@selectedNature=@natureList[value]
}, [getNatureDescription(@natureList[0]), getNatureDescription(@natureList[1])]
)
return options
end
end

View File

@@ -0,0 +1,32 @@
def pbRelearnEggMoveScreen(pkmn)
retval = true
pbFadeOutIn {
scene = MoveRelearner_Scene.new
screen = MoveRelearnerScreen.new(scene)
retval = screen.pbStartScreenEgg(pkmn)
}
return retval
end
class MoveRelearnerScreen
def pbStartScreenEgg(pkmn)
baby = pbGetBabySpecies(pkmn.species)
moves = pbGetSpeciesEggMoves(baby)
@scene.pbStartScene(pkmn, moves)
loop do
move = @scene.pbChooseMove
if move
if @scene.pbConfirm(_INTL("Teach {1}?", GameData::Move.get(move).name))
if pbLearnMove(pkmn, move)
@scene.pbEndScene
return true
end
end
elsif @scene.pbConfirm(_INTL("Give up trying to teach a new move to {1}?", pkmn.name))
@scene.pbEndScene
return false
end
end
end
end

View File

@@ -0,0 +1,72 @@
module OptionTypes
WILD_POKE = 0
TRAINER_POKE = 1
end
class ExperimentalOptionsScene < PokemonOption_Scene
def initialize
super
@openTrainerOptions = false
@openWildOptions = false
@openGymOptions = false
@openItemOptions = false
$game_switches[SWITCH_RANDOMIZED_AT_LEAST_ONCE] = true
end
def getDefaultDescription
return _INTL("Set the randomizer settings")
end
def pbStartScene(inloadscreen = false)
super
@changedColor = true
@sprites["title"] = Window_UnformattedTextPokemon.newWithSize(
_INTL("Experimental options"), 0, 0, Graphics.width, 64, @viewport)
@sprites["textbox"].text = getDefaultDescription
pbFadeInAndShow(@sprites) { pbUpdate }
end
def pbGetOptions(inloadscreen = false)
options = [
EnumOption.new(_INTL("Expert mode (beta)"), [_INTL("On"), _INTL("Off")],
proc {
$game_switches[SWITCH_EXPERT_MODE] ? 0 : 1
},
proc { |value|
$game_switches[SWITCH_EXPERT_MODE] = value == 0
}, "Changes all of the trainer teams to make them as challenging as possible!"
),
EnumOption.new(_INTL("No levels mode"), [_INTL("On"), _INTL("Off")],
proc {
$game_switches[SWITCH_NO_LEVELS_MODE] ? 0 : 1
},
proc { |value|
$game_switches[SWITCH_NO_LEVELS_MODE] = value == 0
}, "All Pokémon use their base stats, regardless of levels."
),
EnumOption.new(_INTL("Reversed mode"), [_INTL("On"), _INTL("Off")],
proc {
$game_switches[SWITCH_REVERSED_MODE] ? 0 : 1
},
proc { |value|
$game_switches[SWITCH_REVERSED_MODE] = value == 0
}, "Inverts the fusions of all the trainers in the game."
)
#,
# EnumOption.new(_INTL("Double abilities"), [_INTL("On"), _INTL("Off")],
# proc {
# $game_switches[SWITCH_DOUBLE_ABILITIES] ? 0 : 1
# },
# proc { |value|
# $game_switches[SWITCH_DOUBLE_ABILITIES] = value == 0
# }, "Fused Pokémon have two abilities at the same time"
#)
]
return options
end
end

View File

@@ -0,0 +1,38 @@
def export_music_use_map()
music_hash = Hash.new
for map_id in 1..796
mapInfos = load_data(sprintf("Data/Map%03d.rxdata", map_id))
bgm_name = mapInfos.bgm.name
map_name = Kernel.getMapName(map_id)
formatted_value = map_name + " [" + map_id.to_s + "]"
if music_hash.has_key?(bgm_name)
music_hash[bgm_name] << formatted_value
else
music_hash[bgm_name] = Array.new(1, formatted_value)
end
end
export_hash_to_csv(music_hash,"music_export.csv")
end
def export_hash_to_csv(hash, file_path)
# Open the file for writing
file = File.open(file_path, "w")
# Write the CSV header
file.puts "Key,Value"
# Write each key-value pair as a new line in the CSV file
hash.each do |key, values|
if key == ""
key = "(No value)"
end
# Join the values into a single string with newline characters
values_str = values.join("\n,")
file.puts "#{key},#{values_str}"
end
# Close the file
file.close
end

View File

@@ -0,0 +1,225 @@
#===============================================================================
# Klein Footprints / WolfPP for Pokémon Essentials
# Give credits if you're using this!
# http://kleinstudio.deviantart.com
#
# bo4p5687 update (v.19)
#===============================================================================
# Fix event comment
def pbEventCommentInput(*args)
parameters = []
list = *args[0].list # Event or event page
elements = *args[1] # Number of elements
trigger = *args[2] # Trigger
return nil if list == nil
return nil unless list.is_a?(Array)
for item in list
next unless item.code == 108 || item.code == 408
if item.parameters[0] == trigger[0]
start = list.index(item) + 1
finish = start + elements[0]
for id in start...finish
next if !list[id]
parameters.push(list[id].parameters[0])
end
return parameters
end
end
return nil
end
module FootprintVariables
# If you set pokemon here, they doesn't have footprints
FOLLOWING_DONT_WALK = [
# Example:
# 12,15,17
]
# Set here the terrain tag for footprints, 3 is sand
TERRAIN_FOOT = 3
# Initial opacity for footprints
FOOT_OPACITY = 62
# Delay velocity
FOOT_DELAY = 1.1
def self.get_new_id
newId = 1
while !$game_map.events[newId].nil? do
break if $game_map.events[newId].erased
newId += 1
end
return newId
end
def self.show(event, position)
if event != $game_player
return if event.character_name == "" || event.character_name == "nil" || event.name.include?("/nofoot/")
return if pbEventCommentInput(event, 0, "NoFoot")
if $Trainer.party.length > 0
return if (!($game_map.events[event] && $game_map.events[event].name == "Dependent") &&
(FOLLOWING_DONT_WALK.include?($Trainer.party[0].species) || $PokemonGlobal.bicycle))
end
end
character_sprites = $scene.spriteset.character_sprites
viewport = $scene.spriteset.viewport1
footsprites = $scene.spriteset.footsprites
nid = self.get_new_id
rpgEvent = RPG::Event.new(position[0], position[1])
rpgEvent.id = nid
fev = Game_Event.new($game_map.map_id, rpgEvent, $game_map)
eventsprite = Sprite_Character.new(viewport, fev)
character_sprites.push(eventsprite)
footsprites.push(Footsprite.new(eventsprite, fev, viewport, $game_map, position[2], nid, character_sprites, (event==$game_player)))
end
end
class Game_Event < Game_Character
attr_reader :erased
end
class Sprite_Character
alias old_initialize_foot initialize
def initialize(viewport, character=nil)
old_initialize_foot(viewport, character)
@disposed = false
end
alias old_update_foot update
def update
return if @disposed
old_update_foot
end
alias old_dispose_foot dispose
def dispose
old_dispose_foot
@disposed = true
end
end
class Spriteset_Map
attr_accessor :character_sprites
attr_accessor :footsprites
alias old_initialize initialize
def initialize(map=nil)
old_initialize(map)
@footsprites = []
end
def viewport1
return @@viewport1
end
def putFootprint(event, pos)
return FootprintVariables.show(event, pos)
end
alias old_dispose dispose
def dispose
old_dispose
@footsprites.each { |sprite| sprite.dispose } if !@footsprites.nil?
@footsprites.clear
end
alias old_update update
def update
old_update
return if @footsprites.nil?
@footsprites.each { |sprite| sprite.update }
end
end
class Scene_Map
def spriteset?
return !@spritesets.nil?
end
end
class Game_Character
def get_last_pos
case direction
when 2 then return [@x, @y-1, direction] # Move down
when 4 then return [@x+1, @y, direction] # Move left
when 6 then return [@x-1, @y, direction] # Move right
when 8 then return [@x, @y+1, direction] # Move up
end
return false
end
def foot_prints?
return $game_map.terrain_tag(get_last_pos[0], get_last_pos[1]) == FootprintVariables::TERRAIN_FOOT && $scene.is_a?(Scene_Map) && $scene.spriteset?
end
alias leave_tile_footprints triggerLeaveTile
def triggerLeaveTile
leave_tile_footprints
$scene.spriteset.putFootprint(self, get_last_pos) if foot_prints?
end
end
class Footsprite
def initialize(sprite,event,viewport,map,direction,nid,chardata,player)
@rsprite = sprite
# Sprite
@sprite = Sprite.new(viewport)
file = player && $PokemonGlobal.bicycle ? "footsetbike.png" : "footset.png"
@sprite.bitmap = RPG::Cache.load_bitmap("Graphics/Pictures/", file)
# Set position
@realwidth = @sprite.bitmap.width/4
@sprite.src_rect.width = @realwidth
@opacity = FootprintVariables::FOOT_OPACITY
setFootset(direction)
# Values
@map = map
@event = event
@disposed = false
@eventid = nid
@viewport = viewport
@chardata = chardata
update
end
def setFootset(direction)
@sprite.src_rect.x =
case direction
when 2 then 0 # Move down
when 4 then @realwidth * 3 # Move left
when 6 then @realwidth * 2 # Move right
when 8 then @realwidth # Move up
end
@sprite.opacity = @opacity
end
def dispose
return if @disposed
@disposed = true
@event.erase
(0...@chardata.length).each { |i| @chardata.delete_at(i) if @chardata[i] == @rsprite }
@rsprite.dispose
@sprite.dispose
@sprite = nil
end
def update
return if @disposed
x = @rsprite.x - @rsprite.ox
y = @rsprite.y - @rsprite.oy
width = @rsprite.src_rect.width
height = @rsprite.src_rect.height
@sprite.x = x + width / 2
@sprite.y = y + height
@sprite.ox = @realwidth / 2
@sprite.oy = @sprite.bitmap.height
@sprite.z = @rsprite.z - 2
@opacity -= FootprintVariables::FOOT_DELAY
@sprite.opacity = @opacity
dispose if @sprite.opacity <= 0
end
end

View File

@@ -0,0 +1,205 @@
def pbSpecialTutor(pokemon,legendaries=false)
retval = true
tutorUtil = FusionTutorService.new(pokemon)
pbFadeOutIn {
scene = MoveRelearner_Scene.new
screen = MoveRelearnerScreen.new(scene)
moves = tutorUtil.getCompatibleMoves(legendaries)
if !moves.empty?
retval = screen.pbStartScreen(pokemon, moves)
else
return false
end
}
return retval
end
def pbShowRareTutorFullList(includeLegendaries = false)
tutorUtil = FusionTutorService.new(nil)
tutorUtil.setShowList(true)
pbFadeOutIn {
scene = MoveRelearner_Scene.new
screen = MoveRelearnerScreen.new(scene)
moves = tutorUtil.getCompatibleMoves(includeLegendaries)
screen.pbStartScreen(nil, moves)
}
return false
end
def pbCheckRareTutorCompatibleMoves(pokemon, includeLeshgendaries)
tutorUtil = FusionTutorService.new(pokemon)
return tutorUtil.has_compatible_move(includeLeshgendaries)
end
def showRandomRareMoveConditionExample(legendary = false)
example = legendary ? getlegendaryConditionExample : getRegularConditionExample
text = "For example, " + example
pbMessage(text)
end
def getRegularConditionExample()
list = [
"a Sandslash fusion which has the electric type will be able to learn the move Zing Zap.",
"any Pokémon that is both Flying and Fighting type will be able to learn the move Flying Press.",
"the move Shadow Bone can only be learned by ghost-type Marowak fusions.",
"any Pokémon that is both Ghost and Grass type will be able to learn the move Trick or Treat.",
"the move Forest's Curse can only be learned by Ghost/Grass typed Pokémon.",
"a grass-type fusion of a spiky Pokémon such as Jolteon will be able to learn the move Spiky Shield.",
"only a ground-type fusion of Grimer or Muk will be able to learn the move Shore Up.",
"any ice-type fusion that can already learn the move Crabhammer will also be able to learn the move Ice Hammer.",
"only water-type fusions of a ninja-like Pokémon such as Ninjask or Zoroark will be able to learn the move Water Shuriken.",
]
return list.sample
end
def getlegendaryConditionExample()
list = [
"any Rotom fusion that can already learn the move Thunder Punch can also be taught the move Plasma Fists.",
"only an Electric-type fusion of a legendary Ice-type Pokémon will be able to learn the move Freeze Shock.",
"only a Fire-type fusion of a legendary Ice-type Pokémon will be able to learn the move Ice Burn.",
"any Pokémon that is both Flying and Dark type will be able to learn the move Oblivion Wing.",
"a ground-type fusion of a spiky Pokémon such as Ferrothorn will be able to learn the move Thousand Arrows.",
"any steel-type Pokémon that can already learn the move Double Slap will be able to learn Double Iron Bash.",
"any Pokémon that is both Fairy and Rock type will be able to learn the move Diamond Storm.",
"any water-type Pokémon that can already learn the move Eruption can also be taught the move Steam Eruption",
]
return list.sample
end
class FusionTutorService
def has_compatible_move(include_legendaries = false)
return !getCompatibleMoves(include_legendaries).empty?
end
def initialize(pokemon)
@pokemon = pokemon
@show_full_list = false
end
def setShowList(value)
@show_full_list = value
end
#todo: these moves
# DRAGONHAMMER
# FIRELASH
# BEAKBLAST
# CHATTER
# LEAFAGE
# HEADCHARGE
# HYPERSPACEHOLE
# HOLDBACK
# CELEBRATE
# HEARTSWAP
def getCompatibleMoves(includeLegendaries = false)
compatibleMoves = []
#normal moves
if !includeLegendaries
compatibleMoves << :ATTACKORDER if is_fusion_of([:BEEDRILL])
# compatibleMoves << :FIRSTIMPRESSION if is_fusion_of([:SCYTHER, :SCIZOR, :PINSIR, :FARFETCHD, :TRAPINCH, :VIBRAVA, :FLYGON, :KABUTOPS, :ARMALDO])
compatibleMoves << :POLLENPUFF if is_fusion_of([:BUTTERFREE, :CELEBI, :VILEPLUME, :PARASECT, :BRELOOM])
compatibleMoves << :LUNGE if is_fusion_of([:SPINARAK, :ARIADOS, :JOLTIK, :GALVANTULA, :VENOMOTH, :VOLCARONA, :PINSIR, :PARASECT, :LEDIAN, :DODUO, :DODRIO, :STANTLER])
compatibleMoves << :DEFENDORDER if is_fusion_of([:BEEDRILL])
compatibleMoves << :HEALORDER if is_fusion_of([:BEEDRILL])
compatibleMoves << :POWDER if is_fusion_of([:BUTTERFREE, :VENOMOTH, :VOLCARONA, :PARASECT, :BRELOOM])
compatibleMoves << :TAILGLOW if is_fusion_of([:MAREEP, :FLAAFFY, :AMPHAROS, :LANTURN, :ZEKROM, :RESHIRAM])
compatibleMoves << :DARKESTLARIAT if is_fusion_of([:SNORLAX, :REGIGIGAS, :POLIWRATH, :MACHAMP, :ELECTIVIRE, :DUSKNOIR, :SWAMPERT, :KROOKODILE, :GOLURK])
compatibleMoves << :PARTINGSHOT if is_fusion_of([:MEOWTH, :PERSIAN, :SANDILE, :KROKOROK, :KROOKODILE, :UMBREON])
compatibleMoves << :TOPSYTURVY if is_fusion_of([:HITMONTOP, :WOBBUFFET])
# compatibleMoves << :CLANGINGSCALES if is_fusion_of([:EKANS, :ARBOK, :GARCHOMP, :FLYGON, :HAXORUS])
compatibleMoves << :ZINGZAP if is_fusion_of([:PICHU, :PIKACHU, :RAICHU, :VOLTORB, :ELECTRODE]) || (is_fusion_of([:SANDSLASH, :GOLEM]) && hasType(:ELECTRIC))
compatibleMoves << :PARABOLICCHARGE if is_fusion_of([:PICHU, :PIKACHU, :RAICHU, :MAGNEMITE, :MAGNETON, :MAGNEZONE, :MAREEP, :FLAAFFY, :AMPHAROS, :ELEKID, :ELECTABUZZ, :ELECTIVIRE, :ZAPDOS, :CHINCHOU, :LANTURN, :RAIKOU, :KLINK, :KLANG, :KLINKLANG, :ROTOM, :STUNFISK])
compatibleMoves << :ELECTRIFY if is_fusion_of([:KLINK, :KLANG, :KLINKLANG]) || hasType(:ELECTRIC)
compatibleMoves << :AROMATICMIST if is_fusion_of([:WEEZING, :BULBASAUR, :IVYSAUR, :VENUSAUR, :CHIKORITA, :BAYLEEF, :MEGANIUM, :GLOOM, :VILEPLUME, :BELLOSSOM, :ROSELIA, :ROSERADE])
compatibleMoves << :FLORALHEALING if is_fusion_of([:SUNFLORA, :BELLOSSOM, :ROSELIA, :ROSERADE])
#compatibleMoves << :FLYINGPRESS if is_fusion_of([:TORCHIC, :COMBUSKEN, :BLAZIKEN, :FARFETCHD, :HERACROSS]) || (hasType(:FLYING) && hasType(:FIGHTING))
compatibleMoves << :MATBLOCK if is_fusion_of([:MACHOP, :MACHOKE, :MACHAMP, :TYROGUE, :HITMONLEE, :HITMONCHAN, :HITMONTOP])
compatibleMoves << :MINDBLOWN if is_fusion_of([:VOLTORB, :ELECTRODE, :EXEGGUTOR])
compatibleMoves << :SHELLTRAP if is_fusion_of([:MAGCARGO, :FORRETRESS])
compatibleMoves << :HEATCRASH if is_fusion_of([:BLAZIKEN, :RESHIRAM, :GROUDON, :CHARIZARD, :GOLURK, :REGIGIGAS, :RHYDON, :RHYPERIOR, :SNORLAX])
compatibleMoves << :SHADOWBONE if is_fusion_of([:MAROWAK]) && hasType(:GHOST)
compatibleMoves << :SPIRITSHACKLE if is_fusion_of([:BANETTE, :SPIRITOMB, :DUSKNOIR, :SHEDINJA, :COFAGRIGUS])
compatibleMoves << :TRICKORTREAT if (hasType(:GRASS) && hasType(:GHOST)) || is_fusion_of([:GASTLY, :HAUNTER, :GENGAR, :MIMIKYU, :ZORUA, :ZOROARK])
compatibleMoves << :TROPKICK if is_fusion_of([:HITMONLEE, :HITMONTOP, :ROSERADE]) || (hasType(:GRASS) && hasType(:FIGHTING))
#compatibleMoves << :NEEDLEARM if is_fusion_of([:FERROTHORN])
#compatibleMoves << :FORESTSCURSE if (hasType(:GRASS) && hasType(:GHOST))
#compatibleMoves << :SPIKYSHIELD if is_fusion_of([:FERROSEED, :FERROTHORN]) || (is_fusion_of([:SANDSLASH, :JOLTEON, :CLOYSTER]) && hasType(:GRASS))
compatibleMoves << :STRENGTHSAP if is_fusion_of([:ODDISH, :GLOOM, :VILEPLUME, :BELLOSSOM, :HOPPIP, :SKIPLOOM, :JUMPLUFF, :BELLSPROUT, :WEEPINBELL, :VICTREEBEL, :PARAS, :PARASECT, :DRIFBLIM, :BRELOOM])
#compatibleMoves << :SHOREUP if is_fusion_of([:GRIMER, :MUK]) && hasType(:GROUND)
compatibleMoves << :ICEHAMMER if (canLearnMove(:CRABHAMMER) || canLearnMove(:GRASSHAMMER) || canLearnMove(:HAMMERARM)) && hasType(:ICE)
compatibleMoves << :MULTIATTACK if is_fusion_of([:ARCEUS, :MEW, :GENESECT])
# compatibleMoves << :REVELATIONDANCE if is_fusion_of([:KECLEON, :BELLOSSOM, :CLEFAIRY, :CLEFABLE, :CLEFFA])
#compatibleMoves << :BANEFULBUNKER if is_fusion_of([:TENTACOOL, :TENTACRUEL, :NIDORINA, :NIDORINO, :NIDOQUEEN, :NIDOKING, :GRIMER, :MUK, :QWILFISH])
compatibleMoves << :INSTRUCT if is_fusion_of([:CHIMCHAR, :MONFERNO, :INFERNAPE, :KADABRA, :ALAKAZAM, :SLOWKING])
compatibleMoves << :PSYCHICTERRAIN if hasType(:PSYCHIC)
#compatibleMoves << :GRASSYTERRAIN if hasType(:GRASS)
compatibleMoves << :MISTYTERRAIN if hasType(:FAIRY)
compatibleMoves << :SPEEDSWAP if is_fusion_of([:PIKACHU, :RAICHU, :ABRA, :KADABRA, :ALAKAZAM, :PORYGON, :PORYGON2, :PORYGONZ, :MEWTWO, :MEW, :JOLTIK, :GALVANTULA])
#compatibleMoves << :ACCELEROCK if is_fusion_of([:AERODACTYL, :KABUTOPS, :ANORITH, :ARMALDO])
#compatibleMoves << :ANCHORSHOT if (is_fusion_of([:EMPOLEON, :STEELIX, :BELDUM, :METANG, :METAGROSS, :KLINK, :KLINKLANG, :KLANG, :ARON, :LAIRON, :AGGRON]) && hasType(:WATER)) || (is_fusion_of([:LAPRAS, :WAILORD, :KYOGRE]) && hasType(:STEEL))
compatibleMoves << :SPARKLINGARIA if (is_fusion_of([:JYNX, :JIGGLYPUFF, :WIGGLYTUFF]) && hasType(:WATER)) || is_fusion_of([:LAPRAS])
#compatibleMoves << :WATERSHURIKEN if is_fusion_of([:NINJASK, :LUCARIO, :ZOROARK, :BISHARP]) && hasType(:WATER)
end
if includeLegendaries
#legendary moves (only available after a certain trigger, maybe a different npc)
compatibleMoves << :HYPERSPACEFURY if is_fusion_of([:GIRATINA, :PALKIA, :DIALGA, :ARCEUS])
compatibleMoves << :COREENFORCER if is_fusion_of([:GIRATINA, :PALKIA, :DIALGA, :RAYQUAZA])
compatibleMoves << :PLASMAFISTS if is_fusion_of([:ELECTABUZZ, :ELECTIVIRE, :ZEKROM]) || (is_fusion_of([:ROTOM]) && canLearnMove(:THUNDERPUNCH))
compatibleMoves << :LIGHTOFRUIN if is_fusion_of([:ARCEUS, :MEW, :CELEBI, :JIRACHI])
compatibleMoves << :FLEURCANNON if is_fusion_of([:GARDEVOIR, :GALLADE, :SYLVEON, :WIGGLYTUFF])
compatibleMoves << :NATURESMADNESS if is_fusion_of([:CELEBI, :KYOGRE, :GROUDON, :ABSOL])
compatibleMoves << :GEOMANCY if is_fusion_of([:CELEBI])
compatibleMoves << :VCREATE if is_fusion_of([:ENTEI, :HOOH, :TYPHLOSION])
compatibleMoves << :MAGMASTORM if is_fusion_of([:MAGCARGO, :TYPHLOSION, :MAGMORTAR, :MAGMAR, :ENTEI, :GROUDON]) || canLearnMove(:ERUPTION)
compatibleMoves << :SEARINGSHOT if is_fusion_of([:MAGMORTAR])
compatibleMoves << :OBLIVIONWING if is_fusion_of([:MURKROW, :HONCHKROW]) || (hasType(:DARK) && hasType(:FLYING))
compatibleMoves << :MOONGEISTBEAM if (is_fusion_of([:CLEFFA, :CLEFAIRY, :CLEFABLE]) && hasType(:DARK)) || is_fusion_of([:DARKRAI, :MISDREAVUS, :MISMAGIUS])
compatibleMoves << :SPECTRALTHIEF if is_fusion_of([:HAUNTER, :GENGAR, :BANETTE, :GIRATINA, :HONEDGE, :DOUBLADE, :AEGISLASH])
compatibleMoves << :SEEDFLARE if is_fusion_of([:JUMPLUFF, :SUNFLORA])
compatibleMoves << :LANDSWRATH if is_fusion_of([:GROUDON])
compatibleMoves << :THOUSANDARROWS if is_fusion_of([:SANDSLASH, :JOLTEON, :FERROTHORN]) && hasType(:GROUND)
compatibleMoves << :THOUSANDWAVES if is_fusion_of([:STUNFISK, :QUAGSIRE, :SWAMPERT])
compatibleMoves << :FREEZESHOCK if is_fusion_of([:KYUREM, :ARTICUNO]) && hasType(:ELECTRIC)
compatibleMoves << :ICEBURN if is_fusion_of([:KYUREM, :ARTICUNO]) && hasType(:FIRE)
#compatibleMoves << :RELICSONG if is_fusion_of([:JYNX, :LAPRAS, :JIGGLYPUFF, :WIGGLYTUFF, :MISDREAVUS, :MISMAGIUS])
compatibleMoves << :HAPPYHOUR if is_fusion_of([:MEOWTH, :JIRACHI, :DELIBIRD, :MUNCHLAX, :SNORLAX, :PIKACHU, :RAICHU])
compatibleMoves << :HOLDHANDS if is_fusion_of([:CHARMANDER, :BULBASAUR, :SQUIRTLE, :PIKACHU, :TOGEPI])
#compatibleMoves << :PRISMATICLASER if is_fusion_of([:LANTURN, :AMPHAROS, :HOOH, :DEOXYS, :MEWTWO, :MEW]) && hasType(:PSYCHIC)
#compatibleMoves << :PHOTONGEYSER if is_fusion_of([:LANTURN, :AMPHAROS, :HOOH, :MEW, :MEWTWO, :DEOXYS]) && hasType(:PSYCHIC)
# compatibleMoves << :LUNARDANCE if is_fusion_of([:CLEFAIRY, :CLEFABLE, :STARYU, :STARMIE])
#compatibleMoves << :DIAMONDSTORM if ((hasType(:FAIRY) && hasType(:ROCK)) || (hasType(:ROCK) && hasType(:STEEL))) || is_fusion_of([:DIALGA, :STEELIX])
compatibleMoves << :SUNSTEELSTRIKE if is_fusion_of([:CHARIZARD, :VOLCARONA, :FLAREON, :NINETALES, :ENTEI, :HOOH, :RAPIDASH]) && hasType(:STEEL)
compatibleMoves << :DOUBLEIRONBASH if canLearnMove(:DOUBLESLAP) && hasType(:STEEL)
compatibleMoves << :STEAMERUPTION if canLearnMove(:ERUPTION) && hasType(:WATER)
compatibleMoves << :SECRETSWORD if is_fusion_of([:HONEDGE, :DOUBLADE, :AEGISLASH, :GALLADE, :FARFETCHD, :ABSOL, :BISHARP])
end
return compatibleMoves
end
def is_fusion_of(pokemonList)
return true if @show_full_list
is_species = false
for fusionPokemon in pokemonList
if @pokemon.isFusionOf(fusionPokemon)
is_species = true
end
end
return is_species
end
def hasType(type)
return true if @show_full_list
return @pokemon.hasType?(type)
end
def canLearnMove(move)
return true if @show_full_list
return @pokemon.compatible_with_move?(move)
end
end

View File

@@ -0,0 +1,402 @@
module GameData
class Species
def self.sprite_bitmap_from_pokemon(pkmn, back = false, species = nil)
species = pkmn.species if !species
species = GameData::Species.get(species).id_number # Just to be sure it's a number
return self.egg_sprite_bitmap(species, pkmn.form) if pkmn.egg?
if back
ret = self.back_sprite_bitmap(species, pkmn.shiny?, pkmn.bodyShiny?, pkmn.headShiny?)
else
ret = self.front_sprite_bitmap(species, pkmn.shiny?, pkmn.bodyShiny?, pkmn.headShiny?)
end
ret.scale_bitmap(pkmn.sprite_scale) #for pokemon with size differences
return ret
end
def self.sprite_bitmap_from_pokemon_id(id, back = false, shiny = false, bodyShiny = false, headShiny = false)
if back
ret = self.back_sprite_bitmap(id, shiny, bodyShiny, headShiny)
else
ret = self.front_sprite_bitmap(id, shiny, bodyShiny, headShiny)
end
return ret
end
MAX_SHIFT_VALUE = 360
MINIMUM_OFFSET = 40
ADDITIONAL_OFFSET_WHEN_TOO_CLOSE = 40
MINIMUM_DEX_DIF = 20
def self.calculateShinyHueOffset(dex_number, isBodyShiny = false, isHeadShiny = false)
if dex_number <= NB_POKEMON
if SHINY_COLOR_OFFSETS[dex_number]
return SHINY_COLOR_OFFSETS[dex_number]
end
body_number = dex_number
head_number = dex_number
else
body_number = getBodyID(dex_number)
head_number = getHeadID(dex_number, body_number)
end
if isBodyShiny && isHeadShiny && SHINY_COLOR_OFFSETS[body_number] && SHINY_COLOR_OFFSETS[head_number]
offset = SHINY_COLOR_OFFSETS[body_number] + SHINY_COLOR_OFFSETS[head_number]
elsif isHeadShiny && SHINY_COLOR_OFFSETS[head_number]
offset = SHINY_COLOR_OFFSETS[head_number]
elsif isBodyShiny && SHINY_COLOR_OFFSETS[body_number]
offset = SHINY_COLOR_OFFSETS[body_number]
else
offset = calculateShinyHueOffsetDefaultMethod(body_number, head_number, dex_number, isBodyShiny, isHeadShiny)
end
return offset
end
def self.calculateShinyHueOffsetDefaultMethod(body_number, head_number, dex_number, isBodyShiny = false, isHeadShiny = false)
dex_offset = dex_number
#body_number = getBodyID(dex_number)
#head_number=getHeadID(dex_number,body_number)
dex_diff = (body_number - head_number).abs
if isBodyShiny && isHeadShiny
dex_offset = dex_number
elsif isHeadShiny
dex_offset = head_number
elsif isBodyShiny
dex_offset = dex_diff > MINIMUM_DEX_DIF ? body_number : body_number + ADDITIONAL_OFFSET_WHEN_TOO_CLOSE
end
offset = dex_offset + Settings::SHINY_HUE_OFFSET
offset /= MAX_SHIFT_VALUE if offset > NB_POKEMON
offset = MINIMUM_OFFSET if offset < MINIMUM_OFFSET
offset = MINIMUM_OFFSET if (MAX_SHIFT_VALUE - offset).abs < MINIMUM_OFFSET
offset += pbGet(VAR_SHINY_HUE_OFFSET) #for testing - always 0 during normal gameplay
return offset
end
def self.getAutogenSprite(head_id, body_id)
end
# species can be either a number, a Species objet of a symbol
def self.front_sprite_bitmap(species, isShiny = false, bodyShiny = false, headShiny = false)
dex_number = getDexNumberForSpecies(species)
if species.is_a?(Species)
dex_number = species.id_number
end
spriteLoader = BattleSpriteLoader.new
if isFusion(dex_number)
body_id = getBodyID(dex_number)
head_id = getHeadID(dex_number, body_id)
sprite = spriteLoader.load_fusion_sprite(head_id,body_id)
else
if isTripleFusion?(dex_number)
sprite = spriteLoader.load_triple_fusion_sprite(dex_number)
else
sprite = spriteLoader.load_base_sprite(dex_number)
end
end
if isShiny
sprite.shiftColors(self.calculateShinyHueOffset(dex_number, bodyShiny, headShiny))
end
return sprite
end
# def self.front_sprite_bitmap(dex_number, isShiny = false, bodyShiny = false, headShiny = false)
# # body_id = getBodyID(dex_number)
# # head_id = getHeadID(dex_number, body_id)
# # return getAutogenSprite(head_id,body_id)
#
# #la méthode est utilisé ailleurs avec d'autres arguments (gender, form, etc.) mais on les veut pas
# if dex_number.is_a?(Symbol)
# dex_number = GameData::Species.get(dex_number).id_number
# end
# filename = self.sprite_filename(dex_number)
# sprite = (filename) ? AnimatedBitmap.new(filename) : nil
# if isShiny
# sprite.shiftColors(self.calculateShinyHueOffset(dex_number, bodyShiny, headShiny))
# end
# return sprite
# end
def self.back_sprite_bitmap(dex_number, isShiny = false, bodyShiny = false, headShiny = false)
# filename = self.sprite_filename(dex_number)
# sprite = (filename) ? AnimatedBitmap.new(filename) : nil
# if isShiny
# sprite.shiftColors(self.calculateShinyHueOffset(dex_number, bodyShiny, headShiny))
# end
# return sprite
sprite = self.front_sprite_bitmap(dex_number,isShiny,bodyShiny,headShiny)
return sprite#.mirror
end
def self.egg_sprite_bitmap(dex_number, form = nil)
filename = self.egg_sprite_filename(dex_number, form)
return (filename) ? AnimatedBitmap.new(filename) : nil
end
end
end
# def self.sprite_filename(dex_number)
# #dex_number = GameData::NAT_DEX_MAPPING[dex_number] ? GameData::NAT_DEX_MAPPING[dex_number] : dex_number
# if dex_number.is_a?(GameData::Species)
# dex_number = dex_number.id_number
# end
# if dex_number.is_a?(Symbol)
# dex_number = getDexNumberForSpecies(dex_number)
# end
# return nil if dex_number == nil
# if dex_number <= Settings::NB_POKEMON
# return get_unfused_sprite_path(dex_number)
# else
# if dex_number >= Settings::ZAPMOLCUNO_NB
# specialPath = getSpecialSpriteName(dex_number)
# return pbResolveBitmap(specialPath)
# head_id = nil
# else
# body_id = getBodyID(dex_number)
# head_id = getHeadID(dex_number, body_id)
# return get_fusion_sprite_path(head_id, body_id)
# # folder = head_id.to_s
# # filename = sprintf("%s.%s.png", head_id, body_id)
# end
# end
# # customPath = pbResolveBitmap(Settings::CUSTOM_BATTLERS_FOLDER_INDEXED + "/" + head_id.to_s + "/" +filename)
# # customPath = download_custom_sprite(head_id,body_id)
# #
# # species = getSpecies(dex_number)
# # use_custom = customPath && !species.always_use_generated
# # if use_custom
# # return customPath
# # end
# # #return Settings::BATTLERS_FOLDER + folder + "/" + filename
# # return download_autogen_sprite(head_id,body_id)
# end
# def get_unfused_sprite_path(dex_number_id, localOnly = false)
# dex_number = dex_number_id.to_s
# folder = dex_number.to_s
# substitution_id = _INTL("{1}", dex_number)
#
# if alt_sprites_substitutions_available && $PokemonGlobal.alt_sprite_substitutions.keys.include?(substitution_id)
# substitutionPath = $PokemonGlobal.alt_sprite_substitutions[substitution_id]
# return substitutionPath if pbResolveBitmap(substitutionPath)
# end
# random_alt = get_random_alt_letter_for_unfused(dex_number, true) #nil if no main
# random_alt = "" if !random_alt || localOnly
#
#
# filename = _INTL("{1}{2}.png", dex_number,random_alt)
#
# path = Settings::CUSTOM_BASE_SPRITES_FOLDER + filename
# if pbResolveBitmap(path)
# record_sprite_substitution(substitution_id,path)
# return path
# end
# echoln "downloading main sprite #{filename}"
# downloaded_path = download_unfused_main_sprite(dex_number, random_alt) if !localOnly
# if pbResolveBitmap(downloaded_path)
# record_sprite_substitution(substitution_id,downloaded_path)
# return downloaded_path
# end
# return path
# end
def alt_sprites_substitutions_available
return $PokemonGlobal && $PokemonGlobal.alt_sprite_substitutions
end
def print_stack_trace
stack_trace = caller
stack_trace.each_with_index do |call, index|
echo("#{index + 1}: #{call}")
end
end
# def record_sprite_substitution(substitution_id, sprite_name)
# return if !$PokemonGlobal
# return if !$PokemonGlobal.alt_sprite_substitutions
# $PokemonGlobal.alt_sprite_substitutions[substitution_id] = sprite_name
# end
def add_to_autogen_cache(pokemon_id, sprite_name)
return if !$PokemonGlobal
return if !$PokemonGlobal.autogen_sprites_cache
$PokemonGlobal.autogen_sprites_cache[pokemon_id]=sprite_name
end
class PokemonGlobalMetadata
attr_accessor :autogen_sprites_cache
end
#To force a specific sprites before a battle
#
# ex:
# $PokemonTemp.forced_alt_sprites={"20.25" => "20.25a"}
#
class PokemonTemp
attr_accessor :forced_alt_sprites
end
#todo:
# DO NOT USE ANYMORE
# Replace by BattleSpriteLoader
# def get_fusion_sprite_path(head_id, body_id, localOnly=false)
# $PokemonGlobal.autogen_sprites_cache = {} if $PokemonGlobal && !$PokemonGlobal.autogen_sprites_cache
# #Todo: ça va chier si on fusionne une forme d'un pokemon avec une autre forme, mais pas un problème pour tout de suite
# form_suffix = ""
#
# #Swap path if alt is selected for this pokemon
# dex_num = getSpeciesIdForFusion(head_id, body_id)
# substitution_id = dex_num.to_s + form_suffix
#
# if alt_sprites_substitutions_available && $PokemonGlobal.alt_sprite_substitutions.keys.include?(substitution_id)
# substitutionPath= $PokemonGlobal.alt_sprite_substitutions[substitution_id]
# return substitutionPath if pbResolveBitmap(substitutionPath)
# end
#
#
# pokemon_name = _INTL("{1}.{2}",head_id, body_id)
#
# #get altSprite letter
# random_alt = get_random_alt_letter_for_custom(head_id, body_id) #nil if no main
# random_alt = "" if !random_alt
# forcingSprite=false
# if $PokemonTemp.forced_alt_sprites && $PokemonTemp.forced_alt_sprites.key?(pokemon_name)
# random_alt = $PokemonTemp.forced_alt_sprites[pokemon_name]
# forcingSprite=true
# end
#
#
# filename = _INTL("{1}{2}.png", pokemon_name, random_alt)
# #Try local custom sprite
# local_custom_path = Settings::CUSTOM_BATTLERS_FOLDER_INDEXED + head_id.to_s + "/" + filename
# if pbResolveBitmap(local_custom_path)
# record_sprite_substitution(substitution_id, local_custom_path) if !forcingSprite
# return local_custom_path
# end
# #if the game has loaded an autogen earlier, no point in trying to redownload, so load that instead
# return $PokemonGlobal.autogen_sprites_cache[substitution_id] if $PokemonGlobal && $PokemonGlobal.autogen_sprites_cache[substitution_id]
#
# #Try to download custom sprite if none found locally
# downloaded_custom = download_custom_sprite(head_id, body_id, random_alt) if !localOnly
# if downloaded_custom
# record_sprite_substitution(substitution_id, downloaded_custom) if !forcingSprite
# return downloaded_custom
# end
#
# #Try local generated sprite
# local_generated_path = Settings::BATTLERS_FOLDER + head_id.to_s + "/" + filename
# if pbResolveBitmap(local_generated_path)
# add_to_autogen_cache(substitution_id,local_generated_path)
# return local_generated_path
# end
#
# #Download generated sprite if nothing else found
# autogen_path = download_autogen_sprite(head_id, body_id) if !localOnly
# if pbResolveBitmap(autogen_path)
# add_to_autogen_cache(substitution_id,autogen_path)
# return autogen_path
# end
#
# return Settings::DEFAULT_SPRITE_PATH
# end
def get_random_alt_letter_for_custom(head_id, body_id, onlyMain = true)
spriteName = _INTL("{1}.{2}", head_id, body_id)
if onlyMain
alts_list = list_main_sprites_letters(spriteName)
return nil if alts_list.empty?
return alts_list.sample
else
alts_list = list_all_sprites_letters(spriteName)
return nil if alts_list.empty?
return alts_list.sample
end
end
def get_random_alt_letter_for_unfused(dex_num, onlyMain = true)
spriteName = _INTL("{1}", dex_num)
if onlyMain
letters_list= list_main_sprites_letters(spriteName)
else
letters_list= list_all_sprites_letters(spriteName)
end
letters_list << "" #add main sprite
return letters_list.sample
end
def list_main_sprites_letters(spriteName)
all_sprites = map_alt_sprite_letters_for_pokemon(spriteName)
main_sprites = []
all_sprites.each do |key, value|
main_sprites << key if value == "main"
end
#add temp sprites if no main sprites found
if main_sprites.empty?
all_sprites.each do |key, value|
main_sprites << key if value == "temp"
end
end
return main_sprites
end
def list_all_sprites_letters_head_body(head_id,body_id)
spriteName = _INTL("{1}.{2}", head_id, body_id)
all_sprites_map = map_alt_sprite_letters_for_pokemon(spriteName)
letters = []
all_sprites_map.each do |key, value|
letters << key
end
return letters
end
def list_all_sprites_letters(spriteName)
all_sprites_map = map_alt_sprite_letters_for_pokemon(spriteName)
letters = []
all_sprites_map.each do |key, value|
letters << key
end
return letters
end
def list_alt_sprite_letters(spriteName)
all_sprites = map_alt_sprite_letters_for_pokemon(spriteName)
alt_sprites = []
all_sprites.each do |key, value|
alt_sprites << key if value == "alt"
end
end
#ex: "1" -> "main"
# "1a" -> "alt"
def map_alt_sprite_letters_for_pokemon(spriteName)
alt_sprites = {}
File.foreach(Settings::CREDITS_FILE_PATH) do |line|
row = line.split(',')
sprite_name = row[0]
if sprite_name.start_with?(spriteName)
if sprite_name.length > spriteName.length #alt letter
letter = sprite_name[spriteName.length]
if letter.match?(/[a-zA-Z]/)
main_or_alt = row[2] ? row[2] : nil
alt_sprites[letter] = main_or_alt
end
else #letterless
main_or_alt = row[2] ? row[2] : nil
alt_sprites[""] = main_or_alt
end
end
end
return alt_sprites
end

View File

@@ -0,0 +1,333 @@
def is_fusion_of_any(species_id, pokemonList)
is_species = false
for fusionPokemon in pokemonList
if is_fusion_of(species_id, fusionPokemon)
is_species = true
end
end
return is_species
end
def is_fusion_of(checked_species, checked_against)
return species_has_body_of(checked_species, checked_against) || species_has_head_of(checked_species, checked_against)
end
def is_species(checked_species, checked_against)
return checked_species == checked_against
end
def species_has_body_of(checked_species, checked_against)
if !species_is_fusion(checked_species)
return is_species(checked_species, checked_against)
end
bodySpecies = get_body_species_from_symbol(checked_species)
ret = bodySpecies == checked_against
#echoln _INTL("{1} HAS BODY OF {2} : {3} (body is {4})",checked_species,checked_against,ret,bodySpecies)
return ret
end
def species_has_head_of(checked_species, checked_against)
if !species_is_fusion(checked_species)
return is_species(checked_species, checked_against)
end
headSpecies = get_head_species_from_symbol(checked_species)
ret = headSpecies == checked_against
#echoln _INTL("{1} HAS HEAD OF {2} : {3}",checked_species,checked_against,ret)
return ret
end
def species_is_fusion(species_id)
dex_number = get_dex_number(species_id)
return dex_number > NB_POKEMON && dex_number < Settings::ZAPMOLCUNO_NB
end
def get_dex_number(species_id)
return GameData::Species.get(species_id).id_number
end
def getBodyID(species, nb_pokemon = NB_POKEMON)
if species.is_a?(Integer)
dexNum = species
else
dexNum = getDexNumberForSpecies(species)
end
if dexNum % nb_pokemon == 0
return (dexNum / nb_pokemon) - 1
end
return (dexNum / nb_pokemon).round
end
def getHeadID(species, bodyId = nil, nb_pokemon = NB_POKEMON)
if species.is_a?(Integer)
fused_dexNum = species
else
fused_dexNum = getDexNumberForSpecies(species)
end
if bodyId == nil
bodyId = getBodyID(species)
end
body_dexNum = getDexNumberForSpecies(bodyId)
calculated_number = (fused_dexNum - (body_dexNum * nb_pokemon)).round
return calculated_number == 0 ? nb_pokemon : calculated_number
end
def get_fusion_id(head_number, body_number)
return "B#{body_number}H#{head_number}".to_sym
end
def get_body_id_from_symbol(id)
split_id = id.to_s.match(/\d+/)
if !split_id #non-fusion
return GameData::Species.get(id).id_number
end
return split_id[0].to_i
end
def get_head_id_from_symbol(id)
split_id = id.to_s.match(/(?<=H)\d+/)
if !split_id #non-fusion
return GameData::Species.get(id).id_number
end
return split_id[0].to_i
end
def obtainPokemonSpritePath(id, includeCustoms = true)
head = getBasePokemonID(param.to_i, false)
body = getBasePokemonID(param.to_i, true)
return obtainPokemonSpritePath(body, head, includeCustoms)
end
def obtainPokemonSpritePath(bodyId, headId, include_customs = true)
#download_pokemon_sprite_if_missing(bodyId, headId)
picturePath = _INTL("Graphics/Battlers/{1}/{1}.{2}.png", headId, bodyId)
if include_customs && customSpriteExistsBodyHead(bodyId, headId)
pathCustom = getCustomSpritePath(bodyId, headId)
if (pbResolveBitmap(pathCustom))
picturePath = pathCustom
end
end
return picturePath
end
def getCustomSpritePath(body, head)
return _INTL("#{Settings::CUSTOM_BATTLERS_FOLDER_INDEXED}{1}/{1}.{2}.png", head, body)
end
def customSpriteExistsForm(species, form_id_head = nil, form_id_body = nil)
head = getBasePokemonID(species, false)
body = getBasePokemonID(species, true)
folder = head.to_s
folder += "_" + form_id_head.to_s if form_id_head
spritename = head.to_s
spritename += "_" + form_id_head.to_s if form_id_head
spritename += "." + body.to_s
spritename += "_" + form_id_body.to_s if form_id_body
pathCustom = _INTL("Graphics/.CustomBattlers/indexed/{1}/{2}.png", folder, spritename)
return true if pbResolveBitmap(pathCustom) != nil
return download_custom_sprite(head, body) != nil
end
def get_fusion_spritename(head_id, body_id, alt_letter = "")
return "#{head_id}.#{body_id}#{alt_letter}"
end
def customSpriteExistsSpecies(species)
head = getBasePokemonID(species, false)
body = getBasePokemonID(species, true)
return customSpriteExists(body, head)
# pathCustom = getCustomSpritePath(body, head)
#
# return true if pbResolveBitmap(pathCustom) != nil
# return download_custom_sprite(head, body) != nil
end
def getRandomCustomFusion(returnRandomPokemonIfNoneFound = true, customPokeList = [], maxPoke = -1, recursionLimit = 3)
if customPokeList.length == 0
customPokeList = getCustomSpeciesList(false)
end
randPoke = []
if customPokeList.length >= 5000
chosen = false
i = 0 #loop pas plus que 3 fois pour pas lag
while chosen == false
fusedPoke = customPokeList[rand(customPokeList.length)]
poke1 = getBasePokemonID(fusedPoke, false)
poke2 = getBasePokemonID(fusedPoke, true)
if ((poke1 <= maxPoke && poke2 <= maxPoke) || i >= recursionLimit) || maxPoke == -1
randPoke << getBasePokemonID(fusedPoke, false)
randPoke << getBasePokemonID(fusedPoke, true)
chosen = true
end
end
else
if returnRandomPokemonIfNoneFound
randPoke << rand(maxPoke) + 1
randPoke << rand(maxPoke) + 1
end
end
return randPoke
end
def checkIfCustomSpriteExistsByPath(path)
return true if pbResolveBitmap(path) != nil
end
def customSpriteExistsBodyHead(body, head)
pathCustom = getCustomSpritePath(body, head)
return true if pbResolveBitmap(pathCustom) != nil
return download_custom_sprite(head, body) != nil
end
def customSpriteExistsSpecies(species)
body_id = getBodyID(species)
head_id = getHeadID(species, body_id)
fusion_id = get_fusion_symbol(head_id, body_id)
return $game_temp.custom_sprites_list.include?(fusion_id)
end
def customSpriteExists(body, head)
fusion_id = get_fusion_symbol(head, body)
return $game_temp.custom_sprites_list.include?(fusion_id)
end
#shortcut for using in game events because of script characters limit
def dexNum(species)
return getDexNumberForSpecies(species)
end
def isTripleFusion?(num)
return num >= Settings::ZAPMOLCUNO_NB
end
def isFusion(num)
return num > Settings::NB_POKEMON && !isTripleFusion?(num)
end
def isSpeciesFusion(species)
num = getDexNumberForSpecies(species)
return isFusion(num)
end
def getRandomLocalFusion()
spritesList = []
$PokemonGlobal.alt_sprite_substitutions.each_value do |value|
if value.is_a?(PIFSprite)
spritesList << value
end
end
return spritesList.sample
end
def getRandomFusionForIntro()
random_pokemon = $game_temp.custom_sprites_list.keys.sample || :PIKACHU
alt_letter = $game_temp.custom_sprites_list[random_pokemon]
body_id = get_body_number_from_symbol(random_pokemon)
head_id = get_head_number_from_symbol(random_pokemon)
return PIFSprite.new(:CUSTOM, head_id, body_id, alt_letter)
end
def getSpeciesIdForFusion(head_number, body_number)
return (body_number) * Settings::NB_POKEMON + head_number
end
def get_body_species_from_symbol(fused_id)
body_num = get_body_number_from_symbol(fused_id)
return GameData::Species.get(body_num).species
end
def get_head_species_from_symbol(fused_id)
head_num = get_head_number_from_symbol(fused_id)
return GameData::Species.get(head_num).species
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
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
end
def get_fusion_symbol(head_id, body_id)
return "B#{body_id}H#{head_id}".to_sym
end
def getFusionSpecies(body, head)
body_num = getDexNumberForSpecies(body)
head_num = getDexNumberForSpecies(head)
id = body_num * Settings::NB_POKEMON + head_num
return GameData::Species.get(id)
end
def getDexNumberForSpecies(species)
return species if species.is_a?(Integer)
if species.is_a?(Symbol)
dexNum = GameData::Species.get(species).id_number
elsif species.is_a?(Pokemon)
dexNum = GameData::Species.get(species.species).id_number
elsif species.is_a?(GameData::Species)
return species.id_number
else
dexNum = species
end
return dexNum
end
def getFusedPokemonIdFromDexNum(body_dex, head_dex)
return ("B" + body_dex.to_s + "H" + head_dex.to_s).to_sym
end
def getFusedPokemonIdFromSymbols(body_dex, head_dex)
bodyDexNum = GameData::Species.get(body_dex).id_number
headDexNum = GameData::Species.get(head_dex).id_number
return getFusedPokemonIdFromDexNum(body_dex, head_dex)
end
def generateFusionIcon(dexNum, path)
begin
IO.copy_stream(dexNum, path)
return true
rescue
return false
end
end
def ensureFusionIconExists
directory_name = "Graphics/Pokemon/FusionIcons"
Dir.mkdir(directory_name) unless File.exists?(directory_name)
end
def addNewTripleFusion(pokemon1, pokemon2, pokemon3, level = 1)
return if !pokemon1
return if !pokemon2
return if !pokemon3
if pbBoxesFull?
pbMessage(_INTL("There's no more room for Pokémon!\1"))
pbMessage(_INTL("The Pokémon Boxes are full and can't accept any more!"))
return false
end
pokemon = TripleFusion.new(pokemon1, pokemon2, pokemon3, level)
pokemon.calc_stats
pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[80]\1", $Trainer.name, pokemon.name))
pbNicknameAndStore(pokemon)
#$Trainer.pokedex.register(pokemon)
return true
end

View File

@@ -0,0 +1,226 @@
class PokemonGameOption_Scene < PokemonOption_Scene
def pbGetOptions(inloadscreen = false)
options = []
options << SliderOption.new(_INTL("Music Volume"), 0, 100, 5,
proc { $PokemonSystem.bgmvolume },
proc { |value|
if $PokemonSystem.bgmvolume != value
$PokemonSystem.bgmvolume = value
if $game_system.playing_bgm != nil && !inloadscreen
playingBGM = $game_system.getPlayingBGM
$game_system.bgm_pause
$game_system.bgm_resume(playingBGM)
end
end
}, "Sets the volume for background music"
)
options << SliderOption.new(_INTL("SE Volume"), 0, 100, 5,
proc { $PokemonSystem.sevolume },
proc { |value|
if $PokemonSystem.sevolume != value
$PokemonSystem.sevolume = value
if $game_system.playing_bgs != nil
$game_system.playing_bgs.volume = value
playingBGS = $game_system.getPlayingBGS
$game_system.bgs_pause
$game_system.bgs_resume(playingBGS)
end
pbPlayCursorSE
end
}, "Sets the volume for sound effects"
)
options << EnumOption.new(_INTL("Default Movement"), [_INTL("Walking"), _INTL("Running")],
proc { $PokemonSystem.runstyle },
proc { |value| $PokemonSystem.runstyle = value },
["Default to walking when not holding the Run key",
"Default to running when not holding the Run key"]
)
options << EnumOption.new(_INTL("Text Speed"), [_INTL("Normal"), _INTL("Fast")],
proc { $PokemonSystem.textspeed },
proc { |value|
$PokemonSystem.textspeed = value
MessageConfig.pbSetTextSpeed(MessageConfig.pbSettingToTextSpeed(value))
}, "Sets the speed at which the text is displayed"
)
if $game_switches
options << EnumOption.new(_INTL("Difficulty"), [_INTL("Easy"), _INTL("Normal"), _INTL("Hard")],
proc { $Trainer.selected_difficulty },
proc { |value|
setDifficulty(value)
@manually_changed_difficulty=true
}, ["All Pokémon in the team gain experience. Otherwise the same as Normal difficulty.",
"The default experience. Levels are similar to the official games.",
"Higher levels and smarter AI. All trainers have access to healing items."]
)
end
if $game_switches
options <<
EnumOption.new(_INTL("Autosave"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[AUTOSAVE_ENABLED_SWITCH] ? 0 : 1 },
proc { |value|
if !$game_switches[AUTOSAVE_ENABLED_SWITCH] && value == 0
@autosave_menu = true
openAutosaveMenu()
end
$game_switches[AUTOSAVE_ENABLED_SWITCH] = value == 0
},
"Automatically saves when healing at Pokémon centers"
)
end
options << EnumOption.new(_INTL("Speed-up type"), [_INTL("Hold"), _INTL("Toggle")],
proc { $PokemonSystem.speedup },
proc { |value|
$PokemonSystem.speedup = value
}, "Pick how you want speed-up to be enabled"
)
options << SliderOption.new(_INTL("Speed-up speed"), 1, 10, 1,
proc { $PokemonSystem.speedup_speed },
proc { |value|
$PokemonSystem.speedup_speed = value
}, "Sets by how much to speed up the game when holding the speed up button (Default: 3x)"
)
# if $game_switches && ($game_switches[SWITCH_NEW_GAME_PLUS] || $game_switches[SWITCH_BEAT_THE_LEAGUE]) #beat the league
# options << EnumOption.new(_INTL("Text Speed"), [_INTL("Normal"), _INTL("Fast"), _INTL("Instant")],
# proc { $PokemonSystem.textspeed },
# proc { |value|
# $PokemonSystem.textspeed = value
# MessageConfig.pbSetTextSpeed(MessageConfig.pbSettingToTextSpeed(value))
# }, "Sets the speed at which the text is displayed"
# )
# else
# options << EnumOption.new(_INTL("Text Speed"), [_INTL("Normal"), _INTL("Fast")],
# proc { $PokemonSystem.textspeed },
# proc { |value|
# $PokemonSystem.textspeed = value
# MessageConfig.pbSetTextSpeed(MessageConfig.pbSettingToTextSpeed(value))
# }, "Sets the speed at which the text is displayed"
# )
# end
options <<
EnumOption.new(_INTL("Download data"), [_INTL("On"), _INTL("Off")],
proc { $PokemonSystem.download_sprites },
proc { |value|
$PokemonSystem.download_sprites = value
},
"Automatically download missing custom sprites and Pokédex entries from the internet"
)
if $game_switches && ($game_switches[SWITCH_NEW_GAME_PLUS] || $game_switches[SWITCH_BEAT_THE_LEAGUE]) #beat the league
options <<
EnumOption.new(_INTL("Battle type"), [_INTL("1v1"), _INTL("2v2"), _INTL("3v3")],
proc { $PokemonSystem.battle_type },
proc { |value|
if value == 0
$game_variables[VAR_DEFAULT_BATTLE_TYPE] = [1, 1]
elsif value == 1
$game_variables[VAR_DEFAULT_BATTLE_TYPE] = [2, 2]
elsif value == 2
$game_variables[VAR_DEFAULT_BATTLE_TYPE] = [3, 3]
else
$game_variables[VAR_DEFAULT_BATTLE_TYPE] = [1, 1]
end
$PokemonSystem.battle_type = value
}, "Sets the number of Pokémon sent out in battles (when possible)"
)
end
options << EnumOption.new(_INTL("Battle Effects"), [_INTL("On"), _INTL("Off")],
proc { $PokemonSystem.battlescene },
proc { |value| $PokemonSystem.battlescene = value },
"Display move animations in battles"
)
options << EnumOption.new(_INTL("Battle Style"), [_INTL("Switch"), _INTL("Set")],
proc { $PokemonSystem.battlestyle },
proc { |value| $PokemonSystem.battlestyle = value },
["Prompts to switch Pokémon before the opponent sends out the next one",
"No prompt to switch Pokémon before the opponent sends the next one"]
)
options << NumberOption.new(_INTL("Speech Frame"), 1, Settings::SPEECH_WINDOWSKINS.length,
proc { $PokemonSystem.textskin },
proc { |value|
$PokemonSystem.textskin = value
MessageConfig.pbSetSpeechFrame("Graphics/Windowskins/" + Settings::SPEECH_WINDOWSKINS[value])
}
)
# NumberOption.new(_INTL("Menu Frame"),1,Settings::MENU_WINDOWSKINS.length,
# proc { $PokemonSystem.frame },
# proc { |value|
# $PokemonSystem.frame = value
# MessageConfig.pbSetSystemFrame("Graphics/Windowskins/" + Settings::MENU_WINDOWSKINS[value])
# }
# ),
options << EnumOption.new(_INTL("Text Entry"), [_INTL("Cursor"), _INTL("Keyboard")],
proc { $PokemonSystem.textinput },
proc { |value| $PokemonSystem.textinput = value },
["Enter text by selecting letters on the screen",
"Enter text by typing on the keyboard"]
)
if $game_variables
options << EnumOption.new(_INTL("Fusion Icons"), [_INTL("Combined"), _INTL("DNA")],
proc { $game_variables[VAR_FUSION_ICON_STYLE] },
proc { |value| $game_variables[VAR_FUSION_ICON_STYLE] = value },
["Combines both Pokémon's party icons",
"Uses the same party icon for all fusions"]
)
battle_type_icon_option_selected=$PokemonSystem.type_icons ? 1 : 0
options << EnumOption.new(_INTL("Battle Type Icons"), [_INTL("Off"), _INTL("On")],
proc { battle_type_icon_option_selected },
proc { |value| $PokemonSystem.type_icons = value == 1 },
"Display the enemy Pokémon type in battles."
)
end
options << EnumOption.new(_INTL("Screen Size"), [_INTL("S"), _INTL("M"), _INTL("L"), _INTL("XL"), _INTL("Full")],
proc { [$PokemonSystem.screensize, 4].min },
proc { |value|
if $PokemonSystem.screensize != value
$PokemonSystem.screensize = value
pbSetResizeFactor($PokemonSystem.screensize)
echoln $PokemonSystem.screensize
end
}, "Sets the size of the screen"
)
options << EnumOption.new(_INTL("Quick Surf"), [_INTL("Off"), _INTL("On")],
proc { $PokemonSystem.quicksurf },
proc { |value| $PokemonSystem.quicksurf = value },
"Start surfing automatically when interacting with water"
)
options << EnumOption.new(_INTL("Level caps"), [_INTL("Off"), _INTL("On")],
proc { $PokemonSystem.level_caps },
proc { |value| $PokemonSystem.level_caps = value },
"Prevents leveling above the next gym leader's highest leveled Pokemon"
)
options << EnumOption.new(_INTL("Device"), [_INTL("PC"), _INTL("Mobile")],
proc { $PokemonSystem.on_mobile },
proc { |value| $PokemonSystem.on_mobile = value == 1 },
["The intended device on which to play the game.",
"Disables some options that aren't supported when playing on mobile."]
)
return options
end
def pbEndScene
echoln "Selected Difficulty: #{$Trainer.selected_difficulty}, lowest difficutly: #{$Trainer.lowest_difficulty}" if $Trainer
if $Trainer && $Trainer.selected_difficulty < $Trainer.lowest_difficulty
$Trainer.lowest_difficulty = $Trainer.selected_difficulty
echoln "lowered difficulty (#{$Trainer.selected_difficulty})"
if @manually_changed_difficulty
pbMessage(_INTL("The savefile's lowest selected difficulty was changed to #{getDisplayDifficulty()}."))
@manually_changed_difficulty = false
end
end
super
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,301 @@
#IMPORTANT
#La méthode def pbCheckEvolution(pokemon,item=0)
#dans PokemonFusion (class PokemonFusionScene)
#a été modifiée et pour une raison ou une autre ca marche
#pas quand on la copie ici.
#Donc NE PAS OUBLIER DE LE COPIER AVEC
############################
# MODIFIED CODE SECTION #
###########################
#
# require PokeBattle_Scene_edited2
# PokemonFusion
#
NB_POKEMON = Settings::NB_POKEMON#809#420 #351 #aussi CONST_NB_POKE
CONST_NB_POKE = NB_POKEMON
def pbPokemonBitmapFile(species)
# Used by the Pokédex
# Load normal bitmap
#get body and head num
isFused = species > NB_POKEMON
if isFused
if species >= ZAPMOLCUNO_NB
path = getSpecialSpriteName(species) + ".png"
else
poke1 = getBodyID(species) #getBasePokemonID(species,true)
poke2 = getHeadID(species, poke1) #getBasePokemonID(species,false)
path = GetSpritePath(poke1, poke2, isFused)
end
else
path = GetSpritePath(species, species, false)
end
ret = sprintf(path) rescue nil
if !pbResolveBitmap(ret)
ret = "Graphics/Battlers/000.png"
end
return ret
end
def pbLoadPokemonBitmap(pokemon, species, back = false)
#species est utilisé par elitebattle mais ca sert a rien
return pbLoadPokemonBitmapSpecies(pokemon, pokemon.species, back)
end
def getEggBitmapPath(pokemon)
bitmapFileName = sprintf("Graphics/Battlers/Eggs/%s", getConstantName(PBSpecies, pokemon.species)) rescue nil
if !pbResolveBitmap(bitmapFileName)
if pokemon.species >= NUM_ZAPMOLCUNO
bitmapFileName = "Graphics/Battlers/Eggs/egg_base"
else
bitmapFileName = sprintf("Graphics/Battlers/Eggs/%03d", pokemon.species)
if !pbResolveBitmap(bitmapFileName)
bitmapFileName = sprintf("Graphics/Battlers/Eggs/000")
end
end
end
return bitmapFileName
end
def pbLoadPokemonBitmapSpecies(pokemon, species, back = false, scale = POKEMONSPRITESCALE)
ret = nil
pokemon = pokemon.pokemon if pokemon.respond_to?(:pokemon)
if pokemon.isEgg?
bitmapFileName = getEggBitmapPath(pokemon)
bitmapFileName = pbResolveBitmap(bitmapFileName)
elsif pokemon.species >= ZAPMOLCUNO_NB #zapmolcuno
bitmapFileName = getSpecialSpriteName(pokemon.species) #sprintf("Graphics/Battlers/special/144.145.146")
bitmapFileName = pbResolveBitmap(bitmapFileName)
else
#edited here
isFusion = species > NB_POKEMON
if isFusion
poke1 = getBodyID(species)
poke2 = getHeadID(species, poke1)
else
poke1 = species
poke2 = species
end
bitmapFileName = GetSpritePath(poke1, poke2, isFusion)
# Alter bitmap if supported
alterBitmap = (MultipleForms.getFunction(species, "alterBitmap") rescue nil)
end
if bitmapFileName && alterBitmap
animatedBitmap = AnimatedBitmap.new(bitmapFileName)
copiedBitmap = animatedBitmap.copy
animatedBitmap.dispose
copiedBitmap.each { |bitmap| alterBitmap.call(pokemon, bitmap) }
ret = copiedBitmap
elsif bitmapFileName
ret = AnimatedBitmap.new(bitmapFileName)
end
return ret
end
#######################
# NEW CODE SECTION #
#######################
DOSSIERCUSTOMSPRITES = "CustomBattlers"
BATTLERSPATH = "Battlers"
def GetSpritePath(poke1, poke2, isFused)
#Check if custom exists
spritename = GetSpriteName(poke1, poke2, isFused)
pathCustom = sprintf("Graphics/%s/indexed/%s/%s.png", DOSSIERCUSTOMSPRITES,poke2, spritename)
pathReg = sprintf("Graphics/%s/%s/%s.png", BATTLERSPATH, poke2, spritename)
path = pbResolveBitmap(pathCustom) && $game_variables[196] == 0 ? pathCustom : pathReg
return path
end
def GetSpritePathForced(poke1, poke2, isFused)
#Check if custom exists
spritename = GetSpriteName(poke1, poke2, isFused)
pathCustom = sprintf("Graphics/%s/indexed/%s/%s.png", DOSSIERCUSTOMSPRITES, poke2, spritename)
pathReg = sprintf("Graphics/%s/%s/%s.png", BATTLERSPATH, poke2, spritename)
path = pbResolveBitmap(pathCustom) ? pathCustom : pathReg
return path
end
def GetSpriteName(poke1, poke2, isFused)
ret = isFused ? sprintf("%d.%d", poke2, poke1) : sprintf("%d", poke2) rescue nil
return ret
end
#in: pokemon number
def Kernel.isPartPokemon(src, target)
src = getDexNumberForSpecies(src)
target = getDexNumberForSpecies(target)
return true if src == target
return false if src <= NB_POKEMON
bod = getBasePokemonID(src, true)
head = getBasePokemonID(src, false)
return bod == target || head == target
end
##EDITED HERE
#Retourne le pokemon de base
#param1 = int
#param2 = true pour body, false pour head
#return int du pokemon de base
def getBasePokemonID(pokemon, body = true)
if pokemon.is_a?(Symbol)
dex_number = GameData::Species.get(pokemon).id_number
pokemon = dex_number
end
return nil if pokemon <= 0
return nil if pokemon >= Settings::ZAPMOLCUNO_NB
# cname = getConstantName(PBSpecies, pokemon) rescue nil
cname = GameData::Species.get(pokemon).id.to_s
return pokemon if pokemon <= NB_POKEMON
return pokemon if cname == nil
arr = cname.split(/[B,H]/)
bod = arr[1]
head = arr[2]
return bod.to_i if body
return head.to_i
end
###################
## CONVERTER #
###################
def convertAllPokemon()
Kernel.pbMessage(_INTL("The game has detected that your previous savefile was from an earlier build of the game."))
Kernel.pbMessage(_INTL("In order to play this version, your Pokémon need to be converted to their new Pokédex numbers. "))
Kernel.pbMessage(_INTL("If you were playing Randomized mode, the trainers and wild Pokémon will also need to be reshuffled."))
if (Kernel.pbConfirmMessage(_INTL("Convert your Pokémon?")))
#get previous version
msgwindow = Kernel.pbCreateMessageWindow(nil)
msgwindow.text = "What is the last version of the game you played?"
choice = Kernel.pbShowCommands(msgwindow, [
"4.7 (September 2020)",
"4.5-4.6.2 (2019-2020)",
"4.2-4.4 (2019)",
"4.0-4.1 (2018-2019)",
"3.x or earlier (2015-2018)"], -1)
case choice
when 0
prev_total = 381
when 1
prev_total = 351
when 2
prev_total = 315
when 3
prev_total = 275
when 4
prev_total = 151
else
prev_total = 381
end
Kernel.pbDisposeMessageWindow(msgwindow)
pbEachPokemon { |poke, box|
if poke.species >= NB_POKEMON
pf = poke.species
pBody = (pf / prev_total).round
pHead = pf - (prev_total * pBody)
# Kernel.pbMessage(_INTL("pbod {1} pHead {2}, species: {3})",pBody,pHead,pf))
prev_max_value = (prev_total * prev_total) + prev_total
if pf >= prev_max_value
newSpecies = convertTripleFusion(pf, prev_max_value)
if newSpecies == nil
boxname = box == -1 ? "Party" : box
Kernel.pbMessage(_INTL("Invalid Pokémon detected in box {1}:\n num. {2}, {3} (lv. {4})", boxname, pf, poke.name, poke.level))
if (Kernel.pbConfirmMessage(_INTL("Delete Pokémon and continue?")))
poke = nil
next
else
Kernel.pbMessage(_INTL("Conversion cancelled. Please restart the game."))
Graphics.freeze
end
end
end
newSpecies = pBody * NB_POKEMON + pHead
poke.species = newSpecies
end
}
Kernel.initRandomTypeArray()
if $game_switches[SWITCH_RANDOM_TRAINERS] #randomized trainers
Kernel.pbShuffleTrainers()
end
if $game_switches[956] #randomized pokemon
range = pbGet(197) == nil ? 25 : pbGet(197)
Kernel.pbShuffleDex(range, 1)
end
end
end
def convertTripleFusion(species, prev_max_value)
if prev_max_value == (351 * 351) + 351
case species
when 123553
return 145543
when 123554
return 145544
when 123555
return 145545
when 123556
return 145546
when 123557
return 145547
when 123558
return 145548
else
return nil
end
end
return nil
end
def convertTrainers()
if ($game_switches[SWITCH_RANDOM_TRAINERS])
Kernel.pbShuffleTrainers()
end
end
def convertAllPokemonManually()
if (Kernel.pbConfirmMessage(_INTL("When you last played the game, where there any gen 2 Pokémon?")))
#4.0
prev_total = 315
else
#3.0
prev_total = 151
end
convertPokemon(prev_total)
end
def convertPokemon(prev_total = 275)
pbEachPokemon { |poke, box|
if poke.species >= NB_POKEMON
pf = poke.species
pBody = (pf / prev_total).round
pHead = pf - (prev_total * pBody)
newSpecies = pBody * NB_POKEMON + pHead
poke.species = newSpecies
end
}
end

View File

@@ -0,0 +1,510 @@
def pbAddPokemonID(pokemon, level = nil, seeform = true, dontRandomize = false)
return if !pokemon || !$Trainer
dontRandomize = true if $game_switches[SWITCH_CHOOSING_STARTER] #when choosing starters
if pbBoxesFull?
Kernel.pbMessage(_INTL("There's no more room for Pokémon!\1"))
Kernel.pbMessage(_INTL("The Pokémon Boxes are full and can't accept any more!"))
return false
end
if pokemon.is_a?(Integer) && level.is_a?(Integer)
pokemon = Pokemon.new(pokemon, level, $Trainer)
end
#random species if randomized gift pokemon & wild poke
if $game_switches[SWITCH_RANDOM_GIFT_POKEMON] && $game_switches[SWITCH_RANDOM_WILD] && !dontRandomize
tryRandomizeGiftPokemon(pokemon, dontRandomize)
end
speciesname = PBSpecies.getName(pokemon.species)
Kernel.pbMessage(_INTL("{1} obtained {2}!\\se[itemlevel]\1", $Trainer.name, speciesname))
pbNicknameAndStore(pokemon)
pbSeenForm(pokemon) if seeform
return true
end
def pbAddPokemonID(pokemon_id, level = 1, see_form = true, skip_randomize = false)
return false if !pokemon_id
skip_randomize = true if $game_switches[SWITCH_CHOOSING_STARTER] #when choosing starters
if pbBoxesFull?
pbMessage(_INTL("There's no more room for Pokémon!\1"))
pbMessage(_INTL("The Pokémon Boxes are full and can't accept any more!"))
return false
end
if pokemon_id.is_a?(Integer) && level.is_a?(Integer)
pokemon = Pokemon.new(pokemon_id, level)
species_name = pokemon.speciesName
end
#random species if randomized gift pokemon & wild poke
if $game_switches[SWITCH_RANDOM_GIFT_POKEMON] && $game_switches[SWITCH_RANDOM_WILD] && !skip_randomize
tryRandomizeGiftPokemon(pokemon, skip_randomize)
end
pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[80]\1", $Trainer.name, species_name))
pbNicknameAndStore(pokemon)
$Trainer.pokedex.register(pokemon) if see_form
return true
end
def pbHasSpecies?(species)
if species.is_a?(String) || species.is_a?(Symbol)
id = getID(PBSpecies, species)
elsif species.is_a?(Pokemon)
id = species.dexNum
end
for pokemon in $Trainer.party
next if pokemon.isEgg?
return true if pokemon.dexNum == id
end
return false
end
#ancienne methode qui est encore callée un peu partout dans les vieux scripts
def getID(pbspecies_unused, species)
if species.is_a?(String)
return nil
elsif species.is_a?(Symbol)
return GameData::Species.get(species).id_number
elsif species.is_a?(Pokemon)
id = species.dexNum
end
end
#Check if the Pokemon can learn a TM
def CanLearnMove(pokemon, move)
species = getID(PBSpecies, pokemon)
return false if species <= 0
data = load_data("Data/tm.dat")
return false if !data[move]
return data[move].any? { |item| item == species }
end
def pbPokemonIconFile(pokemon)
bitmapFileName = pbCheckPokemonIconFiles(pokemon.species, pokemon.isEgg?)
return bitmapFileName
end
def pbCheckPokemonIconFiles(speciesID, egg = false, dna = false)
if egg
bitmapFileName = sprintf("Graphics/Icons/iconEgg")
return pbResolveBitmap(bitmapFileName)
else
bitmapFileName = _INTL("Graphics/Pokemon/Icons/{1}", speciesID)
ret = pbResolveBitmap(bitmapFileName)
return ret if ret
end
ret = pbResolveBitmap("Graphics/Icons/iconDNA.png")
return ret if ret
return pbResolveBitmap("Graphics/Icons/iconDNA.png")
end
def getPokemon(dexNum)
if dexNum.is_a?(Integer)
if dexNum > NB_POKEMON
body_id = getBodyID(dexNum)
head_id = getHeadID(dexNum, body_id)
pokemon_id = getFusedPokemonIdFromDexNum(body_id, head_id)
else
pokemon_id = dexNum
end
else
pokemon_id = dexNum
end
return GameData::Species.get(pokemon_id)
end
def getSpecies(dexnum)
return getPokemon(dexnum.species) if dexnum.is_a?(Pokemon)
return getPokemon(dexnum)
end
def getAbilityIndexFromID(abilityID, fusedPokemon)
abilityList = fusedPokemon.getAbilityList
for abilityArray in abilityList #ex: [:CHLOROPHYLL, 0]
ability = abilityArray[0]
index = abilityArray[1]
return index if ability == abilityID
end
return 0
end
# dir_path = Settings::CUSTOM_BATTLERS_FOLDER_INDEXED
# indexFolders = Dir.entries(dir_path).select do |entry|
# entry_number = entry.to_i
# File.directory?(File.join(dir_path, entry)) && entry_number.between?(1, NB_POKEMON)
# end
# return nil if indexFolders.empty?
# # Loop until a non-empty folder is found
# selectedIndex = nil
# spritesList = []
# until selectedIndex && !spritesList.empty?
# selectedIndex = indexFolders.sample
# spritesList = Dir.entries(File.join(dir_path, selectedIndex)).select do |file|
# File.file?(File.join(dir_path, selectedIndex, file))
# end
# end
# selectedSprite = spritesList.sample
# return getPokemonSpeciesFromSprite(selectedSprite)
#end
def addShinyStarsToGraphicsArray(imageArray, xPos, yPos, shinyBody, shinyHead, debugShiny, srcx = nil, srcy = nil, width = nil, height = nil,
showSecondStarUnder = false, showSecondStarAbove = false)
color = debugShiny ? Color.new(0, 0, 0, 255) : nil
imageArray.push(["Graphics/Pictures/shiny", xPos, yPos, srcx, srcy, width, height, color])
if shinyBody && shinyHead
if showSecondStarUnder
yPos += 15
elsif showSecondStarAbove
yPos -= 15
else
xPos -= 15
end
imageArray.push(["Graphics/Pictures/shiny", xPos, yPos, srcx, srcy, width, height, color])
end
# if onlyOutline
# imageArray.push(["Graphics/Pictures/shiny_black",xPos,yPos,srcx,srcy,width,height,color])
# end
end
# def getRandomCustomFusion(returnRandomPokemonIfNoneFound = true, customPokeList = [], maxPoke = -1, recursionLimit = 3, maxBST = 300)
# if customPokeList.length == 0
# customPokeList = getCustomSpeciesList()
# end
# randPoke = []
# if customPokeList.length >= 5000
# chosen = false
# i = 0 #loop pas plus que 3 fois pour pas lag
# while chosen == false
# fusedPoke = customPokeList[rand(customPokeList.length)]
# if (i >= recursionLimit) || maxPoke == -1
# return fusedPoke
# end
# end
# else
# if returnRandomPokemonIfNoneFound
# return rand(maxPoke) + 1
# end
# end
#
# return randPoke
# end
def getAllNonLegendaryPokemon()
list = []
for i in 1..143
list.push(i)
end
for i in 147..149
list.push(i)
end
for i in 152..242
list.push(i)
end
list.push(246)
list.push(247)
list.push(248)
for i in 252..314
list.push(i)
end
for i in 316..339
list.push(i)
end
for i in 352..377
list.push(i)
end
for i in 382..420
list.push(i)
end
return list
end
def getPokemonEggGroups(species)
return GameData::Species.get(species).egg_groups
end
def generateEggGroupTeam(eggGroup)
teamComplete = false
generatedTeam = []
while !teamComplete
species = rand(PBSpecies.maxValue)
if getPokemonEggGroups(species).include?(eggGroup)
generatedTeam << species
end
teamComplete = generatedTeam.length == 3
end
return generatedTeam
end
def pbGetSelfSwitch(eventId, switch)
return $game_self_switches[[@map_id, eventId, switch]]
end
def getAllNonLegendaryPokemon()
list = []
for i in 1..143
list.push(i)
end
for i in 147..149
list.push(i)
end
for i in 152..242
list.push(i)
end
list.push(246)
list.push(247)
list.push(248)
for i in 252..314
list.push(i)
end
for i in 316..339
list.push(i)
end
for i in 352..377
list.push(i)
end
for i in 382..420
list.push(i)
end
return list
end
def generateSimpleTrainerParty(teamSpecies, level)
team = []
for species in teamSpecies
poke = Pokemon.new(species, level)
team << poke
end
return team
end
def isInKantoGeneration(dexNumber)
return dexNumber <= 151
end
def isKantoPokemon(species)
dexNum = getDexNumberForSpecies(species)
poke = getPokemon(species)
head_dex = getDexNumberForSpecies(poke.get_head_species())
body_dex = getDexNumberForSpecies(poke.get_body_species())
return isInKantoGeneration(dexNum) || isInKantoGeneration(head_dex) || isInKantoGeneration(body_dex)
end
def isInJohtoGeneration(dexNumber)
return dexNumber > 151 && dexNumber <= 251
end
def isJohtoPokemon(species)
dexNum = getDexNumberForSpecies(species)
poke = getPokemon(species)
head_dex = getDexNumberForSpecies(poke.get_head_species())
body_dex = getDexNumberForSpecies(poke.get_body_species())
return isInJohtoGeneration(dexNum) || isInJohtoGeneration(head_dex) || isInJohtoGeneration(body_dex)
end
def isAlolaPokemon(species)
dexNum = getDexNumberForSpecies(species)
poke = getPokemon(species)
head_dex = getDexNumberForSpecies(poke.get_head_species())
body_dex = getDexNumberForSpecies(poke.get_body_species())
list = [
370, 373, 430, 431, 432, 433, 450, 451, 452,
453, 454, 455, 459, 460, 463, 464, 465, 469, 470,
471, 472, 473, 474, 475, 476, 477, 498, 499,
]
return list.include?(dexNum) || list.include?(head_dex) || list.include?(body_dex)
end
def isKalosPokemon(species)
dexNum = getDexNumberForSpecies(species)
poke = getPokemon(species)
head_dex = getDexNumberForSpecies(poke.get_head_species())
body_dex = getDexNumberForSpecies(poke.get_body_species())
list =
[327, 328, 329, 339, 371, 372, 417, 418,
425, 426, 438, 439, 440, 441, 444, 445, 446,
456, 461, 462, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487,
489, 490, 491, 492, 500,
]
return list.include?(dexNum) || list.include?(head_dex) || list.include?(body_dex)
end
def isUnovaPokemon(species)
dexNum = getDexNumberForSpecies(species)
poke = getPokemon(species)
head_dex = getDexNumberForSpecies(poke.get_head_species())
body_dex = getDexNumberForSpecies(poke.get_body_species())
list =
[
330, 331, 337, 338, 348, 349, 350, 351, 359, 360, 361,
362, 363, 364, 365, 366, 367, 368, 369, 374, 375, 376, 377,
397, 398, 399, 406, 407, 408, 409, 410, 411, 412, 413, 414,
415, 416, 419, 420,
422, 423, 424, 434, 345,
466, 467, 494, 493,
]
return list.include?(dexNum) || list.include?(head_dex) || list.include?(body_dex)
end
def isSinnohPokemon(species)
dexNum = getDexNumberForSpecies(species)
poke = getPokemon(species)
head_dex = getDexNumberForSpecies(poke.get_head_species())
body_dex = getDexNumberForSpecies(poke.get_body_species())
list =
[254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 288, 294,
295, 296, 297, 298, 299, 305, 306, 307, 308, 315, 316, 317,
318, 319, 320, 321, 322, 323, 324, 326, 332, 343, 344, 345,
346, 347, 352, 353, 354, 358, 383, 384, 388, 389, 400, 402,
403, 429, 468]
return list.include?(dexNum) || list.include?(head_dex) || list.include?(body_dex)
end
def isHoennPokemon(species)
dexNum = getDexNumberForSpecies(species)
poke = getPokemon(species)
head_dex = getDexNumberForSpecies(poke.get_head_species())
body_dex = getDexNumberForSpecies(poke.get_body_species())
list = [252, 253, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 289, 290, 291, 292, 293, 300, 301, 302, 303,
304, 309, 310, 311, 312, 313, 314, 333, 334, 335, 336, 340,
341, 342, 355, 356, 357, 378, 379, 380, 381, 382, 385, 386, 387, 390,
391, 392, 393, 394, 395, 396, 401, 404, 405, 421, 427, 428, 436,
437, 442, 443, 447, 448, 449, 457, 458, 488, 495, 496, 497, 501]
return list.include?(dexNum) || list.include?(head_dex) || list.include?(body_dex)
end
def pbBitmap(path)
if !pbResolveBitmap(path).nil?
bmp = RPG::Cache.load_bitmap_path(path)
bmp.storedPath = path
else
p "Image located at '#{path}' was not found!" if $DEBUG
bmp = Bitmap.new(1, 1)
end
return bmp
end
def reverseFusionSpecies(species)
dexId = getDexNumberForSpecies(species)
return species if dexId <= NB_POKEMON
return species if dexId > (NB_POKEMON * NB_POKEMON) + NB_POKEMON
body = getBasePokemonID(dexId, true)
head = getBasePokemonID(dexId, false)
newspecies = (head) * NB_POKEMON + body
return getPokemon(newspecies)
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)") : "")
return text
end
def Kernel.getItemNamesAsString(list)
strList = ""
for i in 0..list.length - 1
id = list[i]
name = PBItems.getName(id)
strList += name
if i != list.length - 1 && list.length > 1
strList += ","
end
end
return strList
end
def get_default_moves_at_level(species, level)
moveset = GameData::Species.get(species).moves
knowable_moves = []
moveset.each { |m| knowable_moves.push(m[1]) if m[0] <= level }
# Remove duplicates (retaining the latest copy of each move)
knowable_moves = knowable_moves.reverse
knowable_moves |= []
knowable_moves = knowable_moves.reverse
# Add all moves
moves = []
first_move_index = knowable_moves.length - MAX_MOVES
first_move_index = 0 if first_move_index < 0
for i in first_move_index...knowable_moves.length
#moves.push(Pokemon::Move.new(knowable_moves[i]))
moves << knowable_moves[i]
end
return moves
end
def find_newer_available_version
latest_Version = fetch_latest_game_version
return nil if !latest_Version
return nil if is_higher_version(Settings::GAME_VERSION_NUMBER, latest_Version)
return latest_Version
end
def is_higher_version(gameVersion, latestVersion)
gameVersion_parts = gameVersion.split('.').map(&:to_i)
latestVersion_parts = latestVersion.split('.').map(&:to_i)
# Compare each part of the version numbers from left to right
gameVersion_parts.each_with_index do |part, i|
return true if (latestVersion_parts[i].nil? || part > latestVersion_parts[i])
return false if part < latestVersion_parts[i]
end
return latestVersion_parts.length <= gameVersion_parts.length
end
def get_current_game_difficulty
return :EASY if $game_switches[SWITCH_GAME_DIFFICULTY_EASY]
return :HARD if $game_switches[SWITCH_GAME_DIFFICULTY_HARD]
return :NORMAL
end
def get_difficulty_text
if $game_switches[SWITCH_GAME_DIFFICULTY_EASY]
return "Easy"
elsif $game_switches[SWITCH_GAME_DIFFICULTY_HARD]
return "Hard"
else
return "Normal"
end
end
def pokemonExceedsLevelCap(pokemon)
return false if $Trainer.badge_count >= Settings::NB_BADGES
current_max_level = Settings::LEVEL_CAPS[$Trainer.badge_count]
current_max_level *= Settings::HARD_MODE_LEVEL_MODIFIER if $game_switches[SWITCH_GAME_DIFFICULTY_HARD]
return pokemon.level >= current_max_level
end
def listPokemonIDs()
for id in 0..NB_POKEMON
pokemon = GameData::Species.get(id).species
echoln id.to_s + ": " + "\"" + pokemon.to_s + "\"" + ", "
end
end
def getLatestSpritepackDate()
return Time.new(Settings::NEWEST_SPRITEPACK_YEAR, Settings::NEWEST_SPRITEPACK_MONTH)
end
def new_spritepack_was_released()
current_spritepack_date = $PokemonGlobal.current_spritepack_date
latest_spritepack_date = getLatestSpritepackDate()
if !current_spritepack_date || (current_spritepack_date < latest_spritepack_date)
$PokemonGlobal.current_spritepack_date = latest_spritepack_date
return true
end
return false
end

View File

@@ -0,0 +1,309 @@
class FusionQuiz
#
# Possible difficulties:
#
# :REGULAR -> 4 options choice
#
# :ADVANCED -> List of all pokemon
#
def initialize(difficulty = :REGULAR)
@sprites = {}
@previewwindow = nil
@difficulty = difficulty
@customs_list = getCustomSpeciesList(true, false)
@selected_pokemon = nil
@head_id = nil
@body_id = nil
@choices = []
@abandonned = false
@score = 0
@current_streak = 0
@streak_multiplier = 0.15
end
def start_quiz(nb_rounds = 3)
nb_games_played= pbGet(VAR_STAT_FUSION_QUIZ_NB_TIMES)
pbSet(VAR_STAT_FUSION_QUIZ_NB_TIMES,nb_games_played+1)
round_multiplier = 1
round_multiplier_increase = 0.1
for i in 1..nb_rounds
if i == nb_rounds
pbMessage(_INTL("Get ready! Here comes the final round!"))
elsif i == 1
pbMessage(_INTL("Get ready! Here comes the first round!"))
else
pbMessage(_INTL("Get ready! Here comes round {1}!", i))
end
start_quiz_new_round(round_multiplier)
rounds_left = nb_rounds - i
if rounds_left > 0
pbMessage(_INTL("That's it for round {1}. You've cumulated {2} points so far.", i, @score))
prompt_next_round = pbMessage(_INTL("Are you ready to move on to the next round?", i), ["Yes", "No"])
if prompt_next_round != 0
prompt_quit = pbMessage(_INTL("You still have {1} rounds to go. You'll only keep your points if you finish all {2} rounds. Do you really want to quit now?", rounds_left, nb_rounds), ["Yes", "No"])
if prompt_quit
@abandonned = true
break
end
end
round_multiplier += round_multiplier_increase
else
pbMessage(_INTL("This concludes our quiz! You've cumulated {1} points in total.", @score))
pbMessage("Thanks for playing with us today!")
end
end
end_quiz()
end
def end_quiz()
hide_fusion_picture
Kernel.pbClearText()
previous_highest = pbGet(VAR_STAT_FUSION_QUIZ_HIGHEST_SCORE)
pbSet(VAR_STAT_FUSION_QUIZ_HIGHEST_SCORE,@score) if @score > previous_highest
previous_total = pbGet(VAR_STAT_FUSION_QUIZ_TOTAL_PTS)
pbSet(VAR_STAT_FUSION_QUIZ_TOTAL_PTS,previous_total+@score)
dispose
end
def start_quiz_new_round(round_multiplier = 1)
if @difficulty == :ADVANCED
base_points_q1 = 500
base_points_q1_redemption = 200
base_points_q2 = 600
base_points_q2_redemption = 200
perfect_round_points = 100
else
base_points_q1 = 300
base_points_q1_redemption = 100
base_points_q2 = 400
base_points_q2_redemption = 100
perfect_round_points = 50
end
pick_random_pokemon()
show_fusion_picture(true)
correct_answers = []
#OBSCURED
correct_answers << new_question(calculate_points_awarded(base_points_q1, round_multiplier), "Which Pokémon is this fusion's body?", @body_id, true, true)
pbMessage("Next question!")
correct_answers << new_question(calculate_points_awarded(base_points_q2, round_multiplier), "Which Pokémon is this fusion's head?", @head_id, true, true)
#NON-OBSCURED
if !correct_answers[0] || !correct_answers[1]
show_fusion_picture(false)
pbMessage("Okay, now's your chance to make up for the points you missed!")
if !correct_answers[0] #1st question redemption
new_question(calculate_points_awarded(base_points_q1_redemption, round_multiplier), "Which Pokémon is this fusion's body?", @body_id, true, false)
if !correct_answers[1]
pbMessage("Next question!")
end
end
if !correct_answers[1] #2nd question redemption
new_question(calculate_points_awarded(base_points_q2_redemption, round_multiplier), "Which Pokémon is this fusion's head?", @head_id, true, false)
end
else
pbSEPlay("Applause", 80)
pbMessage(_INTL("Wow! A perfect round! You get {1} more points!", perfect_round_points))
show_fusion_picture(false, 100)
pbMessage("Let's see what this Pokémon looked like!")
end
current_streak_dialog()
hide_fusion_picture()
end
def calculate_points_awarded(base_points, round_multiplier)
points = base_points * round_multiplier
if @current_streak > 0
current_streak_multiplier = (@current_streak * @streak_multiplier) - @streak_multiplier
points += points * current_streak_multiplier
#p (base_points * round_multiplier)
#p (points * current_streak_multiplier)
end
return points
end
def new_question(points_value, question, answer_id, should_generate_new_choices, other_chance_later)
points_value = points_value.to_i
answer_name = getPokemon(answer_id).real_name
answered_correctly = give_answer(question, answer_id, should_generate_new_choices)
award_points(points_value) if answered_correctly
question_answer_followup_dialog(answered_correctly, answer_name, points_value, other_chance_later)
return answered_correctly
end
def increase_streak
@current_streak += 1
refresh_streak_ui()
end
def break_streak
@current_streak = 0
refresh_streak_ui()
end
def refresh_streak_ui()
shadow_color = Color.new(160,160,160)
base_color_low_streak = Color.new(72,72,72)
base_color_medium_streak = Color.new(213,254,205)
base_color_high_streak = Color.new(100,232,96)
streak_color= base_color_low_streak
streak_color = base_color_medium_streak if @current_streak >= 2
streak_color = base_color_high_streak if @current_streak >= 4
message = _INTL("Streak: {1}",@current_streak)
Kernel.pbClearText()
Kernel.pbDisplayText(message,420,340,nil,streak_color)
end
def award_points(nb_points)
@score += nb_points
end
def question_answer_followup_dialog(answered_correctly, correct_answer, points_awarded_if_win, other_chance_later = false)
if !other_chance_later
pbMessage("And the correct answer was...")
pbMessage("...")
pbMessage(_INTL("{1}!", correct_answer))
end
if answered_correctly
pbSEPlay("itemlevel", 80)
increase_streak
pbMessage("That's a correct answer!")
pbMessage(_INTL("You're awarded {1} points for your answer. Your current score is {2}", points_awarded_if_win, @score.to_s))
else
pbSEPlay("buzzer", 80)
break_streak
pbMessage("Unfortunately, that was a wrong answer.")
pbMessage("But you'll get another chance at it!") if other_chance_later
end
end
def current_streak_dialog()
return if @current_streak ==0
streak_base_worth= @difficulty == :REGULAR ? 25 : 100
if @current_streak % 4 == 0
extra_points = (@current_streak/4)*streak_base_worth
if @current_streak >= 8
pbMessage(_INTL("That's {1} correct answers in a row. You're on a roll!", @current_streak))
else
pbMessage(_INTL("That's {1} correct answers in a row. You're doing great!", @current_streak))
end
pbMessage(_INTL("Here's {1} extra points for maintaining a streak!",extra_points))
award_points(extra_points)
end
end
def show_fusion_picture(obscured = false, x = nil, y = nil)
hide_fusion_picture()
spriteLoader = BattleSpriteLoader.new
bitmap = spriteLoader.load_fusion_sprite(@head_id, @body_id)
bitmap.scale_bitmap(Settings::FRONTSPRITE_SCALE)
@previewwindow = PictureWindow.new(bitmap)
@previewwindow.y = y ? y : 30
@previewwindow.x = x ? x : (@difficulty == :ADVANCED ? 275 : 100)
@previewwindow.z = 100000
if obscured
@previewwindow.picture.pbSetColor(255, 255, 255, 200)
end
end
def hide_fusion_picture()
@previewwindow.dispose if @previewwindow
end
def pick_random_pokemon(save_in_variable = 1)
random_pokemon = getRandomCustomFusion(true, @customs_list)
@head_id = random_pokemon[0]
@body_id = random_pokemon[1]
@selected_pokemon = getSpeciesIdForFusion(@head_id, @body_id)
pbSet(save_in_variable, @selected_pokemon)
end
def give_answer(prompt_message, answer_id, should_generate_new_choices)
question_answered = false
answer_pokemon_name = getPokemon(answer_id).real_name
while !question_answered
if @difficulty == :ADVANCED
player_answer = prompt_pick_answer_advanced(prompt_message, answer_id)
else
player_answer = prompt_pick_answer_regular(prompt_message, answer_id, should_generate_new_choices)
end
confirmed = pbMessage("Is this your final answer?", ["Yes", "No"])
if confirmed == 0
question_answered = true
else
should_generate_new_choices = false
end
end
return player_answer == answer_pokemon_name
end
def get_random_pokemon_from_same_egg_group(pokemon, previous_choices)
egg_groups = getPokemonEggGroups(pokemon)
while true
new_pokemon = rand(1, NB_POKEMON) + 1
new_pokemon_egg_groups = getPokemonEggGroups(new_pokemon)
if (egg_groups & new_pokemon_egg_groups).any? && !previous_choices.include?(new_pokemon)
return new_pokemon
end
end
end
def prompt_pick_answer_regular(prompt_message, real_answer, should_new_choices)
commands = should_new_choices ? generate_new_choices(real_answer) : @choices.shuffle
chosen = pbMessage(prompt_message, commands)
return commands[chosen]
end
def generate_new_choices(real_answer)
choices = []
choices << real_answer
choices << get_random_pokemon_from_same_egg_group(real_answer, choices)
choices << get_random_pokemon_from_same_egg_group(real_answer, choices)
choices << get_random_pokemon_from_same_egg_group(real_answer, choices)
commands = []
choices.each do |dex_num, i|
species = getPokemon(dex_num)
commands.push(species.real_name)
end
@choices = commands
return commands.shuffle
end
def prompt_pick_answer_advanced(prompt_message, answer)
commands = []
for dex_num in 1..NB_POKEMON
species = getPokemon(dex_num)
commands.push([dex_num - 1, species.real_name, species.real_name])
end
pbMessage(prompt_message)
return pbChooseList(commands, 0, nil, 1)
end
def get_score
return @score
end
def player_abandonned
return @abandonned
end
def dispose
@previewwindow.dispose
end
end

View File

@@ -0,0 +1,46 @@
HIDDEN_MAPS_STEPS = 1500
HIDDEN_MAP_ALWAYS = [178,655,570,356]
RANDOM_HIDDEN_MAP_LIST = [8,109,431,446,402,403,467,468,10,23,167,16,19,78,185,86,
491,90,40,342,490,102,103,104,105,106,1,12,413,445,484,485,486,140,350,146,
149,304,356,307,409,351,495,154,349,322,323,544,198,144,155,444,58,59,229,52,53,54,
55,98,173,174,181,187,95,159,162,437,440,438,57,171,172,528,265,288,364,329,
335,254,261,262,266,230,145,147,258,284,283,267,586,285,286,287,300,311,47,580,529,
635,638,646,560,559,526,600,564,594,566,562,619,563,603,561,597,633,640,641,621,312,
670,692,643,523,698,
602,642,623,569,588,573,362,645,651,376,762
]
Events.onMapUpdate+=proc {|sender,e|
#next if !$game_switches[HIDDENMAPSWITCH]
if $PokemonGlobal.stepcount % HIDDEN_MAPS_STEPS == 0
changeHiddenMap()
end
}
def changeHiddenMap()
i = rand(RANDOM_HIDDEN_MAP_LIST.length-1)
pbSet(VAR_CURRENT_HIDDEN_MAP,RANDOM_HIDDEN_MAP_LIST[i])
end
Events.onWildPokemonCreate+=proc {|sender,e|
if player_on_hidden_ability_map || isAlwaysHiddenAbilityMap($game_map.map_id)
pokemon=e[0]
chosenAbility = pokemon.getAbilityList.sample #format: [[:ABILITY, index],...]
pokemon.ability = chosenAbility[0]
pokemon.ability_index = chosenAbility[1]
end
}
def isAlwaysHiddenAbilityMap(mapId)
return HIDDEN_MAP_ALWAYS.include? mapId
end
def player_on_hidden_ability_map
return $game_map.map_id== pbGet(226)
end
def Kernel.getMapName(id)
mapinfos = pbLoadMapInfos
return mapinfos[id].name
end

View File

@@ -0,0 +1,439 @@
def test_http_get
url = "http://localhost:8080"
response = HTTPLite.get(url)
if response[:status] == 200
p response[:body]
end
end
def updateHttpSettingsFile
return if !downloadAllowed?()
download_file(Settings::HTTP_CONFIGS_FILE_URL, Settings::HTTP_CONFIGS_FILE_PATH,)
end
def updateCreditsFile
return if !downloadAllowed?()
download_file(Settings::CREDITS_FILE_URL, Settings::CREDITS_FILE_PATH,)
end
def updateCustomDexFile
return if !downloadAllowed?()
download_file(Settings::CUSTOM_DEX_FILE_URL, Settings::CUSTOM_DEX_ENTRIES_PATH,)
end
def createCustomSpriteFolders()
if !Dir.exist?(Settings::CUSTOM_BATTLERS_FOLDER)
Dir.mkdir(Settings::CUSTOM_BATTLERS_FOLDER)
end
if !Dir.exist?(Settings::CUSTOM_BATTLERS_FOLDER_INDEXED)
Dir.mkdir(Settings::CUSTOM_BATTLERS_FOLDER_INDEXED)
end
end
def download_file(url, saveLocation)
echoln url
begin
response = HTTPLite.get(url)
if response[:status] == 200
File.open(saveLocation, "wb") do |file|
file.write(response[:body])
end
echoln _INTL("\nDownloaded file {1} to {2}", url, saveLocation)
return saveLocation
else
echoln _INTL("Tried to download file {1}", url)
end
return nil
rescue MKXPError, Errno::ENOENT => error
echo error
return nil
end
end
#Returns:
# A file was downloaded ->true
# A file was not downloaded -> false
# #
#TODO:
# This method bypasses the client-side rate limiting
# MAKE SURE TO ALWAYS CHECK requestRateExceeded? BEFORE CALLING THIS METHOD
# #
def fetch_sprite_from_web(url, destinationPath)
return false if !downloadAllowed?()
begin
response = HTTPLite.get(url)
if response[:status] == 200
File.open(destinationPath, "wb") do |file|
file.write(response[:body])
end
echoln "Downloaded #{url} to #{destinationPath}"
return true
end
echoln "Failed to download #{url}"
return false
rescue MKXPError => e
echoln "MKXPError: #{e.message}"
return false
rescue Errno::ENOENT => e
echoln "File Error: #{e.message}"
return false
rescue Exception => e
echoln "Error: #{e.message}"
end
end
def download_spritesheet(pif_sprite, dest)
#return nil if requestRateExceeded?(Settings::CUSTOMSPRITES_RATE_LOG_FILE,Settings::CUSTOMSPRITES_ENTRIES_RATE_TIME_WINDOW,Settings::CUSTOMSPRITES_RATE_MAX_NB_REQUESTS)
return nil if requestRateExceeded?(Settings::CUSTOMSPRITES_RATE_LOG_FILE, 60, 15)
case pif_sprite.type
when :AUTOGEN
return
when :CUSTOM
url = Settings::CUSTOM_FUSIONS_SPRITESHEET_URL + "#{pif_sprite.head_id}/#{pif_sprite.head_id}#{pif_sprite.alt_letter}.png"
when :BASE
url = Settings::BASE_POKEMON_SPRITESHEET_URL + "#{pif_sprite.head_id}.png"
end
folder = File.dirname(dest)
ensure_folder_exists(folder)
fetchedFromWeb = fetch_sprite_from_web(url, dest)
return fetchedFromWeb
end
def ensure_folder_exists(folder)
# Recursively create directories if they don't exist
unless Dir.exist?(folder)
parent = File.dirname(folder)
ensure_folder_exists(parent) unless Dir.exist?(parent)
Dir.mkdir(folder)
end
end
#Returns: The local path of the downloaded sprite
# def download_sprite(base_path, head_id, body_id, saveLocation = "Graphics/temp", alt_letter = "")
# return nil if requestRateExceeded?(Settings::CUSTOMSPRITES_RATE_LOG_FILE,Settings::CUSTOMSPRITES_ENTRIES_RATE_TIME_WINDOW,Settings::CUSTOMSPRITES_RATE_MAX_NB_REQUESTS)
# filename = "#{head_id}.#{body_id}#{alt_letter}.png"
# filename = "#{head_id}#{alt_letter}.png" if !body_id #unfused
#
# #check if it's in the Custom sprites list if it's a fusion
# if head_id && body_id
# return nil if !custom_exists(filename)
# end
#
# begin
# head_id = head_id.to_s
# body_id = body_id.to_s
#
# downloaded_file_name = _INTL("{1}/{2}.{3}{4}.png", saveLocation, head_id, body_id, alt_letter)
# if !body_id || body_id == ""
# downloaded_file_name = _INTL("{1}{2}{3}.png", saveLocation, head_id, alt_letter)
# end
#
# return downloaded_file_name if pbResolveBitmap(downloaded_file_name)
#
# url = _INTL(base_path, head_id, body_id)
# if !body_id
# url = _INTL(base_path, head_id)
# end
# if fetch_sprite_from_web(url,downloaded_file_name)
# return downloaded_file_name
# end
# return nil
# rescue MKXPError => e
# echoln "MKXPError: #{e.message}"
# return nil
# rescue Errno::ENOENT => e
# echoln "File Error: #{e.message}"
# return nil
# end
# end
def custom_exists(target_file)
file_path = Settings::CUSTOM_SPRITES_FILE_PATH
# Read the file and store its lines in an array, removing newlines
file_list = File.readlines(file_path, chomp: true)
# Perform binary search
low = 0
high = file_list.length - 1
while low <= high
mid = (low + high) / 2
case file_list[mid] <=> target_file
when 0
return true # Found the target file
when -1
low = mid + 1 # Target is in the upper half
when 1
high = mid - 1 # Target is in the lower half
end
end
return false # Target file not found
end
#
# Autogens are no longer downloaded from the web. Instead, the game comes with spritesheets, from which
# it extracts the sprites and puts them in individual files (for faster loading)
#
def download_autogen_sprite(head_id, body_id)
#return nil if !downloadAllowed?()
#template_url = Settings::AUTOGEN_SPRITES_REPO_URL + "{1}/{1}.{2}.png"
destPath = _INTL("{1}{2}", Settings::BATTLERS_FOLDER, head_id)
autogenExtracter = AutogenExtracter.new
return autogenExtracter.extract_bitmap_to_file(PIFSprite.new(:AUTOGEN, head_id, body_id), destPath)
# url = _INTL(template_url, head_id, body_id)
# sprite = download_sprite(url, head_id, body_id, destPath)
# return sprite if sprite
# return nil
end
def download_custom_sprite(head_id, body_id, alt_letter = "")
return nil unless downloadAllowed?()
#url = getDownloadableCustomSpritesUrl() + "{1}.{2}{3}.png"
destPath = _INTL("{1}{2}", Settings::CUSTOM_BATTLERS_FOLDER_INDEXED, head_id)
spriteExtracter = CustomSpriteExtracter.new
sprite_path = spriteExtracter.extract_bitmap_to_file(head_id, body_id, alt_letter, destPath)
echoln sprite_path
return sprite_path
# if !Dir.exist?(destPath)
# Dir.mkdir(destPath)
# end
# sprite = download_sprite(_INTL(url, head_id, body_id,alt_letter), head_id, body_id, destPath, alt_letter)
# return sprite if sprite
# return nil
end
# def download_custom_sprite(head_id, body_id, spriteformBody_suffix = "", spriteformHead_suffix = "", alt_letter="")
# head_id = (head_id.to_s) + spriteformHead_suffix.to_s
# body_id = (body_id.to_s) + spriteformBody_suffix.to_s
# return nil if !downloadAllowed?()
# url = getDownloadableCustomSpritesUrl() + "{1}.{2}{3}.png"
# destPath = _INTL("{1}{2}", Settings::CUSTOM_BATTLERS_FOLDER_INDEXED, head_id)
# if !Dir.exist?(destPath)
# Dir.mkdir(destPath)
# end
# sprite = download_sprite(_INTL(url, head_id, body_id,alt_letter), head_id, body_id, destPath, alt_letter)
# return sprite if sprite
# return nil
# end
# def download_custom_sprite_filename(filename)
# head_id = (head_id.to_s) + spriteformHead_suffix.to_s
# body_id = (body_id.to_s) + spriteformBody_suffix.to_s
# return nil if !downloadAllowed?()
# url = getDownloadableCustomSpritesUrl() + "{1}.{2}{3}.png"
# destPath = _INTL("{1}{2}", Settings::CUSTOM_BATTLERS_FOLDER_INDEXED, head_id)
# if !Dir.exist?(destPath)
# Dir.mkdir(destPath)
# end
# sprite = download_sprite(_INTL(url, head_id, body_id,alt_letter), head_id, body_id, destPath, alt_letter)
# return sprite if sprite
# return nil
# end
# #todo refactor & put custom base sprites in same folder as fusion sprites
# def download_unfused_main_sprite(dex_num, alt_letter="")
# base_url = alt_letter == "" ? Settings::BASE_POKEMON_SPRITES_REPO_URL : getDownloadableBaseSpritesUrl()
# filename = _INTL("{1}{2}.png",dex_num,alt_letter)
# url = base_url + filename
#
# echoln url
# destPath = Settings::CUSTOM_BASE_SPRITES_FOLDER
# sprite = download_sprite(url, dex_num, nil, destPath,alt_letter)
#
# return sprite if sprite
# return nil
# end
# def download_all_unfused_alt_sprites(dex_num)
# base_url = getDownloadableBaseSpritesUrl() + "{1}"
# extension = ".png"
# destPath = _INTL("{1}", Settings::CUSTOM_BASE_SPRITES_FOLDER)
# if !Dir.exist?(destPath)
# Dir.mkdir(destPath)
# end
# alt_url = _INTL(base_url, dex_num) + extension
# download_sprite(alt_url, dex_num, nil, destPath)
# alphabet = ('a'..'z').to_a + ('aa'..'az').to_a
# alphabet.each do |letter|
# alt_url = _INTL(base_url, dex_num) + letter + extension
# sprite = download_sprite(alt_url, dex_num, nil, destPath, letter)
# return if !sprite
# end
# end
# def download_all_unfused_alt_sprites(dex_num)
# template_url = getDownloadableBaseSpritesUrl()
# baseUrl = _INTL(template_url,dex_num)
# destDirectory = _INTL("{1}", Settings::CUSTOM_BASE_SPRITES_FOLDER)
# if !Dir.exist?(destDirectory)
# Dir.mkdir(destDirectory)
# end
# sprites_alt_map = map_alt_sprite_letters_for_pokemon(dex_num.to_s)
# # Sorting the sprite keys by their status in order of priority: "main", "temp", "alt"
# sprite_letters_to_download = sprites_alt_map.keys.sort_by do |key|
# case sprites_alt_map[key]
# when "main" then 0
# when "temp" then 1
# when "alt" then 2
# else 3 # Catch-all for any undefined statuses, if any
# end
# end
#
# nb_sprites_downloaded = 0
# sprites_processed=0
#
# sprite_letters_to_download.each do |letter|
# sprites_processed+=1
# echoln sprites_processed
# echoln nb_sprites_downloaded
#
# break if nb_sprites_downloaded > Settings::MAX_NB_SPRITES_TO_DOWNLOAD_AT_ONCE
#
# filename = "#{dex_num}#{letter}.png"
# url = baseUrl + filename
# destPath = destDirectory + "/" + filename
# next if pbResolveBitmap(destPath)
# downloaded_new_sprite= fetch_sprite_from_web(url,destPath)
# if downloaded_new_sprite
# nb_sprites_downloaded += 1
# break if requestRateExceeded?(Settings::CUSTOMSPRITES_RATE_LOG_FILE,Settings::CUSTOMSPRITES_ENTRIES_RATE_TIME_WINDOW,Settings::CUSTOMSPRITES_RATE_MAX_NB_REQUESTS)
# end
#
# end
# end
# def download_all_alt_sprites(head_id, body_id)
# base_url = "#{getDownloadableCustomSpritesUrl()}{1}.{2}"
# extension = ".png"
# destPath = _INTL("{1}{2}", Settings::CUSTOM_BATTLERS_FOLDER_INDEXED, head_id)
# if !Dir.exist?(destPath)
# Dir.mkdir(destPath)
# end
# sprite_letters_to_download = list_all_sprites_letters_head_body(head_id,body_id)
# sprite_letters_to_download.each do |letter|
# alt_url = base_url + letter + extension
# download_sprite(alt_url, head_id, body_id, destPath, letter)
# end
# end
#format: [1.1.png, 1.2.png, etc.]
# https://api.github.com/repos/infinitefusion/contents/sprites/CustomBattlers
# repo = "Aegide/custom-fusion-sprites"
# folder = "CustomBattlers"
#
# def fetch_online_custom_sprites
# page_start =1
# page_end =2
#
# repo = "infinitefusion/sprites"
# folder = "CustomBattlers"
# api_url = "https://api.github.com/repos/#{repo}/contents/#{folder}"
#
# files = []
# page = page_start
#
# File.open(Settings::CUSTOM_SPRITES_FILE_PATH, "wb") do |csv|
# loop do
# break if page > page_end
# response = HTTPLite.get(api_url, {'page' => page.to_s})
# response_files = HTTPLite::JSON.parse(response[:body])
# break if response_files.empty?
# response_files.each do |file|
# csv << [file['name']].to_s
# csv << "\n"
# end
# page += 1
# end
# end
#
#
# write_custom_sprites_csv(files)
# end
# Too many file to get everything without getting
# rate limited by github, so instead we're getting the
# files list from a csv file that will be manually updated
# with each new spritepack
def updateOnlineCustomSpritesFile
return if !downloadAllowed?()
download_file(Settings::SPRITES_FILE_URL, Settings::CUSTOM_SPRITES_FILE_PATH)
download_file(Settings::BASE_SPRITES_FILE_URL, Settings::BASE_SPRITES_FILE_PATH)
end
def list_online_custom_sprites(updateList = false)
sprites_list = []
File.foreach(Settings::CUSTOM_SPRITES_FILE_PATH) do |line|
sprites_list << line
end
return sprites_list
end
GAME_VERSION_FORMAT_REGEX = /\A\d+(\.\d+)*\z/
def fetch_latest_game_version
begin
# download_file(Settings::VERSION_FILE_URL, Settings::VERSION_FILE_PATH)
# version_file = File.open(Settings::VERSION_FILE_PATH, "r")
# version = version_file.first
# version_file.close
version = Settings::LATEST_GAME_RELEASE
version_format_valid = version.match(GAME_VERSION_FORMAT_REGEX)
return version if version_format_valid
return nil
rescue MKXPError, Errno::ENOENT => error
echo error
return nil
end
end
# update_log_file: keep to true when trying to make an actual request
# set to false if just checking
def requestRateExceeded?(logFile, timeWindow, maxRequests, update_log_file = true)
# Read or initialize the request log
if File.exist?(logFile)
log_data = File.read(logFile).split("\n")
request_timestamps = log_data.map(&:to_i)
else
request_timestamps = []
end
current_time = Time.now.to_i
# Remove old timestamps that are outside the time window
request_timestamps.reject! { |timestamp| (current_time - timestamp) > timeWindow }
# Update the log with the current request
request_timestamps << current_time
# Write the updated log back to the file
if update_log_file
File.write(logFile, request_timestamps.join("\n"))
echoln "Rate limiting: Current: #{request_timestamps.size}, Max: #{maxRequests}"
end
rateLimitExceeded = request_timestamps.size > maxRequests
return rateLimitExceeded
end
# def getDownloadableCustomSpritesUrl()
# if Settings::USE_NEW_URL_FOR_CUSTOM_SPRITES
# return Settings::CUSTOM_SPRITES_NEW_URL
# end
# return Settings::CUSTOM_SPRITES_REPO_URL
# end
# def getDownloadableBaseSpritesUrl()
# if Settings::USE_NEW_URL_FOR_BASE_SPRITES
# return Settings::BASE_POKEMON_ALT_SPRITES_NEW_URL
# end
# return Settings::BASE_POKEMON_ALT_SPRITES_REPO_URL
# end

View File

@@ -0,0 +1,489 @@
#===============================================================================
# New animated Title Screens for Pokemon Essentials
# by Luka S.J.
#
# Adds new visual styles to the Pokemon Essentials title screen, and animates
# depending on the style selected
#===============================================================================
###SCRIPTEDIT1
# Config value for selecting title screen style
SCREENSTYLE = 1
# 1 - FR/LG
# 2 - R/S/E
class Scene_Intro
alias main_old main
def playIntroCinematic
intro_frames_path = "Graphics\\Pictures\\Intro\\INTRO-%03d"
intro_bgm = "INTRO_music_cries"
intro_movie = Movie.new(intro_frames_path,intro_bgm,230,true)
intro_movie.playInViewPort(@viewport)
end
def main
Graphics.transition(0)
# Cycles through the intro pictures
@skip = false
playIntroCinematic
# Selects title screen style
@screen = GenOneStyle.new
# Plays the title screen intro (is skippable)
@screen.intro
# Creates/updates the main title screen loop
self.update
Graphics.freeze
end
def update
ret = 0
loop do
@screen.update
Graphics.update
Input.update
if continueKeyPressed?
ret = 2
break
end
end
case ret
when 1
closeSplashDelete(scene, args)
when 2
closeTitle
end
end
def closeTitle
# Play Pokemon cry
pbSEPlay("Absorb2", 100, 100)
# Fade out
pbBGMStop(1.0)
# disposes current title screen
disposeTitle
#clearTempFolder
# initializes load screen
sscene = PokemonLoad_Scene.new
sscreen = PokemonLoadScreen.new(sscene)
sscreen.pbStartLoadScreen
end
def closeTitleDelete
pbBGMStop(1.0)
# disposes current title screen
disposeTitle
# initializes delete screen
sscene = PokemonLoadScene.new
sscreen = PokemonLoad.new(sscene)
sscreen.pbStartDeleteScreen
end
# def cyclePics(pics)
# sprite=Sprite.new
# sprite.opacity=0
# for i in 0...pics.length
# bitmap=pbBitmap("Graphics/Titles/#{pics[i]}")
# sprite.bitmap=bitmap
# 15.times do
# sprite.opacity+=17
# pbWait(1)
# end
# wait(32)
# 15.times do
# sprite.opacity-=17
# pbWait(1)
# end
# end
# sprite.dispose
# end
def disposeTitle
@screen.dispose
end
def wait(frames)
return if @skip
frames.times do
Graphics.update
Input.update
@skip = true if continueKeyPressed?()
end
end
end
def continueKeyPressed?()
return Input.trigger?(Input::USE) ||
Input.trigger?(Input::ACTION) ||
Input.trigger?(Input::BACK) ||
Input.trigger?(Input::SPECIAL)
end
#===============================================================================
# Styled to look like the FRLG games
#===============================================================================
class GenOneStyle
def initialize
#Kernel.pbDisplayText("Keybindings: F1", 80, 0, 99999)
#Kernel.pbDisplayText("Version " + Settings::GAME_VERSION_NUMBER, 254, 308, 99999)
@maxPoke = 140 #1st gen, pas de legend la premiere fois, graduellement plus de poke
@customPokeList = getCustomSpeciesList(false)
#Get random Pokemon (1st gen orandPokenly, pas de legend la prmeiere fois)
random_fusion = getRandomFusionForIntro()
random_fusion_body = random_fusion.body_id
random_fusion_head = random_fusion.head_id
# if randpoke_body && randpoke_head
# path_s1 = get_unfused_sprite_path(randpoke_body,true)
# path_s2 = get_unfused_sprite_path(randpoke_head,true)
# path_f = get_fusion_sprite_path(randpoke_body, randpoke_head,true)
@prevPoke1 = random_fusion_body
@prevPoke2 = random_fusion_head
#end
@spriteLoader = BattleSpriteLoader.new
@selector_pos = 0 #1: left, 0:right
# sound file for playing the title screen BGM
bgm = "Pokemon Red-Blue Opening"
@skip = false
# speed of the effect movement
@speed = 16
@opacity = 17
@disposed = false
@currentFrame = 0
# calculates after how many frames the game will reset
#@totalFrames=getPlayTime("Audio/BGM/#{bgm}")*Graphics.frame_rate
@totalFrames = 10 * Graphics.frame_rate
pbBGMPlay(bgm)
# creates all the necessary graphics
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99998
@sprites = {}
@sprites["bars"] = Sprite.new(@viewport)
@sprites["bars"].bitmap = pbBitmap("Graphics/Titles/gen1_bars")
@sprites["bars"].x = Graphics.width
@sprites["bg"] = Sprite.new(@viewport)
@sprites["bg"].bitmap = pbBitmap("Graphics/Titles/gen1_bg")
@sprites["bg"].x = -Graphics.width
@sprites["logo"] = Sprite.new(@viewport)
@sprites["logo"].bitmap = pbBitmap("Graphics/Titles/PokemonInfiniteFusionLogo_Main_25")
@sprites["logo"].tone = Tone.new(255, 255, 255, 255)
@sprites["logo"].x = (Graphics.width/2)-125
@sprites["logo"].y = 0
@sprites["logo"].opacity = 0
@sprites["logo"].z = 9999
@sprites["logo_bg"] = Sprite.new(@viewport)
@sprites["logo_bg"].bitmap = pbBitmap("Graphics/Titles/PokemonInfiniteFusionLogo_Back_25")
@sprites["logo_bg"].tone = Tone.new(255, 255, 255, 255)
@sprites["logo_bg"].x = (Graphics.width/2)-125
@sprites["logo_bg"].y = 0
@sprites["logo_bg"].opacity = 0
#@sprites["bg2"]=Sprite.new(@viewport)
#@sprites["bg2"].bitmap=pbBitmap("Graphics/Titles/gen1_bg_litup")
#@sprites["bg2"].opacity=0
@sprites["start"]=Sprite.new(@viewport)
@sprites["start"].bitmap=pbBitmap("Graphics/Titles/intro_pressKey2")
@sprites["start"].x=125
@sprites["start"].y=350
@sprites["start"].opacity=0
@sprites["effect"] = AnimatedPlane.new(@viewport)
@sprites["effect"].bitmap = pbBitmap("Graphics/Titles/gen1_effect")
@sprites["effect"].opacity = 155
@sprites["effect"].visible = false
@sprites["selector"] = Sprite.new(@viewport)
@sprites["selector"].bitmap = pbBitmap("Graphics/Titles/selector")
@sprites["selector"].x = 0
@sprites["selector"].y = 200
@sprites["selector"].opacity = 0
@sprites["poke"] = Sprite.new(@viewport)
@sprites["poke"].bitmap = @spriteLoader.load_base_sprite(random_fusion_body).bitmap
@sprites["poke"].x = 400
@sprites["poke"].y = 100
@sprites["2poke"] = Sprite.new(@viewport)
@sprites["2poke"].bitmap = @spriteLoader.load_base_sprite(random_fusion_head).bitmap
@sprites["2poke"].x = -150
@sprites["2poke"].y = 100
@sprites["fpoke"] = Sprite.new(@viewport)
@sprites["fpoke"].bitmap = @spriteLoader.load_pif_sprite(random_fusion).bitmap
@sprites["fpoke"].x = 125
@sprites["fpoke"].y = 100
@sprites["fpoke"].z = 999
@sprites["fpoke"].opacity = 0
@sprites["fpoke"].z = 999
@sprites["poke"].tone = Tone.new(0, 0, 0, 255)
@sprites["poke"].opacity = 0
@sprites["poke2"] = Sprite.new(@viewport)
# @sprites["poke2"].bitmap = pbBitmap("Graphics/Battlers/21364")
@sprites["poke2"].tone = Tone.new(255, 255, 255, 255)
@sprites["poke2"].src_rect.set(0, Graphics.height, Graphics.width, 48)
@sprites["poke2"].y = Graphics.height
@sprites["poke2"].y = 125
@sprites["poke2"].z = 999
@sprites["2poke"].tone = Tone.new(0, 0, 0, 255)
@sprites["2poke"].opacity = 0
@sprites["2poke2"] = Sprite.new(@viewport)
@sprites["2poke2"].bitmap = pbBitmap("Graphics/Battlers/special/000")
@sprites["2poke2"].tone = Tone.new(255, 255, 255, 255)
@sprites["2poke2"].src_rect.set(0, Graphics.height, Graphics.width, 48)
@sprites["2poke2"].y = Graphics.height
@sprites["2poke2"].y = 125
@sprites["2poke2"].z = 999
@sprites["star"] = Sprite.new(@viewport)
@sprites["star"].bitmap = pbBitmap("Graphics/Pictures/darkness")
@sprites["star"].opacity = 0
@sprites["star"].x = -50
@sprites["star"].y = 0
end
def intro
wait(16)
16.times do
end
wait(32)
64.times do
@sprites["2poke"].opacity += 4
@sprites["poke"].opacity += 4
wait(1)
end
8.times do
@sprites["bg"].x += 64
wait(1)
end
wait(8)
8.times do
@sprites["bars"].x -= 64
wait(1)
end
wait(8)
showUIElements()
@sprites["poke"].tone = Tone.new(0, 0, 0, 0)
@sprites["2poke"].tone = Tone.new(0, 0, 0, 0)
@sprites["effect"].visible = false
c = 255.0
16.times do
@sprites["poke2"].opacity -= 255.0 / 16
@sprites["2poke2"].opacity -= 255.0 / 16
c -= 255.0 / 16
@sprites["logo"].tone = Tone.new(c, c, c)
@sprites["logo_bg"].tone = Tone.new(c, c, c)
@sprites["effect"].ox += @speed
wait(1)
end
end
def showUIElements()
@sprites["logo"].opacity = 255
@sprites["logo_bg"].opacity = 255
@sprites["poke2"].opacity = 255
@sprites["2poke2"].opacity = 255
@sprites["start"].opacity = 200
Kernel.pbDisplayText("v." + Settings::GAME_VERSION_NUMBER, 455, 5, 99999,pbColor(:WHITE),pbColor(:INVISIBLE))
end
TONE_INCR = 15
def makeShineEffect()
newColor = @sprites["poke"].tone.red + TONE_INCR
newTone = Tone.new(newColor, newColor, newColor, 0)
@sprites["poke"].tone = newTone
@sprites["2poke"].tone = newTone
end
def introloop
@sprites["star"].opacity = 0
@sprites["poke"].opacity = 255
@sprites["2poke"].opacity = 255
@sprites["fpoke"].opacity = 0
@sprites["poke"].x = @sprites["poke"].x - 1
@sprites["2poke"].x = @sprites["2poke"].x + 1
end
def update_selector_position()
if Input.press?(Input::RIGHT) || Input.press?(Input::LEFT)
if Input.press?(Input::RIGHT)
@selector_pos = 0
@sprites["selector"].opacity = 100
elsif Input.press?(Input::LEFT)
@selector_pos = 1
@sprites["selector"].opacity = 100
end
else
@sprites["selector"].opacity=0
end
if @selector_pos == 0
@sprites["selector"].x = @sprites["poke"].x
else
@sprites["selector"].x = @sprites["2poke"].x
end
end
def update
@sprites["effect"].ox += @speed
@currentFrame += 1
@skip = false
if @sprites["poke"].x < 175 #150
makeShineEffect()
end
#update_selector_position()
if @sprites["poke"].x > @sprites["2poke"].x
@sprites["poke"].x = @sprites["poke"].x - 1
@sprites["2poke"].x = @sprites["2poke"].x + 1
#@sprites["effect"].opacity-=1
#@sprites["bg"].opacity-=1
#@sprites["bg2"].opacity+=3
end
if @sprites["poke"].x <= @sprites["2poke"].x
@sprites["poke"].opacity = 0
@sprites["2poke"].opacity = 0
#16.times do
@sprites["fpoke"].opacity = 255
@sprites["selector"].opacity = 0
#wait(1)
#end
@sprites["poke"].x = 400
@sprites["poke"].tone = Tone.new(0, 0, 0, 0)
@sprites["2poke"].x = -150
@sprites["2poke"].tone = Tone.new(0, 0, 0, 0)
if @maxPoke < NB_POKEMON - 1
@maxPoke += 5 #-1 pour que ca arrive pile. tant pis pour kyurem
end
random_fusion = getRandomFusionForIntro()
random_fusion_body = random_fusion.body_id
random_fusion_head = random_fusion.head_id
@prevPoke1 = random_fusion_body
@prevPoke2 = random_fusion_head
@sprites["poke"].bitmap = @spriteLoader.load_base_sprite(random_fusion_body).bitmap
@sprites["2poke"].bitmap = @spriteLoader.load_base_sprite(random_fusion_head).bitmap
wait(150)
@sprites["fpoke"].bitmap = @spriteLoader.load_pif_sprite(random_fusion).bitmap
end
@sprites["fpoke"].opacity -= 10
@sprites["effect"].ox += @speed
updatePressStartAnimation(@currentFrame)
if @currentFrame >= @totalFrames
introloop
end
end
PRESS_START_OPACITY_DIFF=2
PRESS_START_ANIMATION_TIME=60
def updatePressStartAnimation(currentFrame)
return if @sprites["start"].opacity==0
@start_opacity_diff=PRESS_START_OPACITY_DIFF if !@start_opacity_diff
@sprites["start"].opacity += @start_opacity_diff
@sprites["logo_bg"].opacity -= @start_opacity_diff
if currentFrame % PRESS_START_ANIMATION_TIME == 0
if @start_opacity_diff <0
@start_opacity_diff = PRESS_START_OPACITY_DIFF
else
@start_opacity_diff = 0 - PRESS_START_OPACITY_DIFF
end
end
end
#new version
# def getFusedPath(randpoke1, randpoke2)
# # path = rand(2) == 0 ? get_fusion_sprite_path(randpoke_body, randpoke_head,true) : get_fusion_sprite_path(randpoke_head, randpoke_body,true)
# path = get_fusion_sprite_path(randpoke2, randpoke1,true)
#
# #allow download here because intentional
# if Input.press?(Input::RIGHT)
# path = get_fusion_sprite_path(randpoke2, randpoke1)
# elsif Input.press?(Input::LEFT)
# path = get_fusion_sprite_path(randpoke1, randpoke2)
# end
# return path
# end
end
# def getFusedPatho(randpoke1s, randpoke2s)
# path = rand(2) == 0 ? "Graphics/Battlers/" + randpoke1s + "/" + randpoke1s + "." + randpoke2s : "Graphics/Battlers/" + randpoke2s + "/" + randpoke2s + "." + randpoke1s
# if Input.press?(Input::RIGHT)
# path = "Graphics/Battlers/" + randpoke2s + "/" + randpoke2s + "." + randpoke1s
# elsif Input.press?(Input::LEFT)
# path = "Graphics/Battlers/" + randpoke1s + "/" + randpoke1s + "." + randpoke2s
# end
# return path
# end
def dispose
Kernel.pbClearText()
pbFadeOutAndHide(@sprites)
pbDisposeSpriteHash(@sprites)
@viewport.dispose
@disposed = true
end
def disposed?
return @disposed
end
def wait(frames)
return if @skip
frames.times do
@currentFrame += 1
updatePressStartAnimation(@currentFrame)
@sprites["effect"].ox += @speed
Graphics.update
Input.update
if continueKeyPressed?
@skip = true
return
end
end
end

View File

@@ -0,0 +1,189 @@
# #==============================================================================#
# # Map Exporter #
# # by Marin #
# #==============================================================================#
# # Manually export a map using `pbExportMap(id)`, or go into the Debug menu and #
# # choose the `Export a Map` option that is now in there. #
# # #
# # `pbExportMap(id, options)`, where `options` is an array that can contain: #
# # - :events -> This will alsoEXPORTED_FILENAME = "export/"
# #
# # def exportAllMaps
# # options = [:events]
# # for id in 1..768
# # pbExportMap(id, options)
# # end
# # end export all events present on the map #
# # - :player -> This will also export the player if they're on that map #
# # `id` can be nil, which case it will use the current map the player is on. #
# #==============================================================================#
# # Please give credit when using this. #
# #==============================================================================#
#
# # This is where the map will be exported to once it has been created.
# # If this file already exists, it is overwritten.
# ExportedMapFilename = "export/"
#
# def exportAllMaps
# options = [:events]
# for id in 1..768
# begin
# pbExportMap(id,options)
# rescue
# echo "error in " +(id.to_s) +"\n"
# end
# end
# end
#
#
# def pbExportMap(id = nil, options = [])
# MarinMapExporter.new(id, options)
# end
#
# def pbExportAMap
# vp = Viewport.new(0, 0, Graphics.width, Graphics.height)
# vp.z = 99999
# s = Sprite.new(vp)
# s.bitmap = Bitmap.new(Graphics.width, Graphics.height)
# s.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0,0,0))
# mapid = pbListScreen(_INTL("Export Map"),MapLister.new(pbDefaultMap))
# if mapid > 0
# player = $game_map.map_id == mapid
# if player
# cmds = ["Export", "[ ] Events", "[ ] Player", "Cancel"]
# else
# cmds = ["Export", "[ ] Events", "Cancel"]
# end
# cmd = 0
# loop do
# cmd = pbShowCommands(nil,cmds,-1,cmd)
# if cmd == 0
# Graphics.update
# options = []
# options << :events if cmds[1].split("")[1] == "X"
# options << :player if player && cmds[2].split("")[1] == "X"
# msgwindow = Window_AdvancedTextPokemon.newWithSize(
# _INTL("Saving... Please be patient."),
# 0, Graphics.height - 96, Graphics.width, 96, vp
# )
# msgwindow.setSkin(MessageConfig.pbGetSpeechFrame)
# Graphics.update
# pbExportMap(mapid, options)
# msgwindow.setText(_INTL("Successfully exported the map."))
# 60.times { Graphics.update; Input.update }
# pbDisposeMessageWindow(msgwindow)
# break
# elsif cmd == 1
# if cmds[1].split("")[1] == " "
# cmds[1] = "[X] Events"
# else
# cmds[1] = "[ ] Events"
# end
# elsif cmd == 2 && player
# if cmds[2].split("")[1] == " "
# cmds[2] = "[X] Player"
# else
# cmds[2] = "[ ] Player"
# end
# elsif cmd == 3 || cmd == 2 && !player || cmd == -1
# break
# end
# end
# end
# s.bitmap.dispose
# s.dispose
# vp.dispose
# end
#
# DebugMenuCommands.register("exportmap", {
# "parent" => "fieldmenu",
# "name" => _INTL("Export a Map"),
# "description" => _INTL("Choose a map to export it to a PNG."),
# "effect" => proc { |sprites, viewport|
# pbExportAMap
# }
# })
#
# class MarinMapExporter
# def initialize(id = nil, options = [])
# mapinfos = load_data("Data/MapInfos.rxdata")
# filename = id.to_s + "_" + mapinfos[id].name
#
#
#
# @id = id || $game_map.map_id
# @options = options
# @data = load_data("Data/Map#{@id.to_digits}.rxdata")
# @tiles = @data.data
# @result = Bitmap.new(32 * @tiles.xsize, 32 * @tiles.ysize)
# @tilesetdata = load_data("Data/Tilesets.rxdata")
# tilesetname = @tilesetdata[@data.tileset_id].tileset_name
# @tileset = Bitmap.new("Graphics/Tilesets/#{tilesetname}")
# @autotiles = @tilesetdata[@data.tileset_id].autotile_names
# .filter { |e| e && e.size > 0 }
# .map { |e| Bitmap.new("Graphics/Autotiles/#{e}") }
# for z in 0..2
# for y in 0...@tiles.ysize
# for x in 0...@tiles.xsize
# id = @tiles[x, y, z]
# next if id == 0
# if id < 384 # Autotile
# build_autotile(@result, x * 32, y * 32, id)
# else # Normal tile
# @result.blt(x * 32, y * 32, @tileset,
# Rect.new(32 * ((id - 384) % 8),32 * ((id - 384) / 8).floor,32,32))
# end
# end
# end
# end
# if @options.include?(:events)
# keys = @data.events.keys.sort { |a, b| @data.events[a].y <=> @data.events[b].y }
# keys.each do |id|
# event = @data.events[id]
# page = pbGetActiveEventPage(event, @id)
# if page && page.graphic && page.graphic.character_name && page.graphic.character_name.size > 0
# bmp = Bitmap.new("Graphics/Characters/#{page.graphic.character_name}")
# if bmp
# bmp = bmp.clone
# bmp.hue_change(page.graphic.character_hue) unless page.graphic.character_hue == 0
# ex = bmp.width / 4 * page.graphic.pattern
# ey = bmp.height / 4 * (page.graphic.direction / 2 - 1)
# @result.blt(event.x * 32 + 16 - bmp.width / 8, (event.y + 1) * 32 - bmp.height / 4, bmp,
# Rect.new(ex, ey, bmp.width / 4, bmp.height / 4))
# end
# bmp = nil
# end
# end
# end
# if @options.include?(:player) && $game_map.map_id == @id && $game_player.character_name &&
# $game_player.character_name.size > 0
# bmp = Bitmap.new("Graphics/Characters/#{$game_player.character_name}")
# dir = $game_player.direction
# @result.blt($game_player.x * 32 + 16 - bmp.width / 8, ($game_player.y + 1) * 32 - bmp.height / 4,
# bmp, Rect.new(0, bmp.height / 4 * (dir / 2 - 1), bmp.width / 4, bmp.height / 4))
# end
# @result.save_to_png(ExportedMapFilename + filename + ".png")
# echo (id.to_s) +"\n"
# Input.update
# end
#
# def build_autotile(bitmap, x, y, id)
# autotile = @autotiles[id / 48 - 1]
# return unless autotile
# if autotile.height == 32
# bitmap.blt(x,y,autotile,Rect.new(0,0,32,32))
# else
# id %= 48
# tiles = CustomTilemap::Autotiles[id >> 3][id & 7]
# src = Rect.new(0,0,0,0)
# halfTileWidth = halfTileHeight = halfTileSrcWidth = halfTileSrcHeight = 32 >> 1
# for i in 0...4
# tile_position = tiles[i] - 1
# src.set((tile_position % 6) * halfTileSrcWidth,
# (tile_position / 6) * halfTileSrcHeight, halfTileSrcWidth, halfTileSrcHeight)
# bitmap.blt(i % 2 * halfTileWidth + x, i / 2 * halfTileHeight + y,
# autotile, src)
# end
# end
# end
# end

View File

@@ -0,0 +1,79 @@
class Movie
attr_reader :finished
def initialize(framesPath, bgm, maxFrame = 1000, canStopEarly=false)
@currentFrame = 1
@initialTime = nil
@timeElapsed = nil
@maxFrame = maxFrame
@framesPath = framesPath
@bgm = bgm
@canStopEarly = canStopEarly
@finished=false
end
def play(imageNumber = 12)
@finished=false
@currentFrame = 1
@initialTime = Time.now
@timeElapsed = Time.now
pbBGMPlay(@bgm)
while (@currentFrame <= @maxFrame)# && !(@canStopEarly && Input::ACTION))
if Input.trigger?(Input::C)
end
frame = sprintf(@framesPath, @currentFrame)
picture = Game_Picture.new(imageNumber)
picture.show(frame, 0, 0, 0, 100, 100, 255, 0)
pbWait(Graphics.frame_rate / 20)
picture.erase
@currentFrame += 1
end
@finished=true
pbBGMStop
end
def playInViewPort(viewport)
@finished=false
@currentFrame = 1
@initialTime = Time.now
@timeElapsed = Time.now
pbBGMPlay(@bgm)
while (@currentFrame <= @maxFrame)# && !(@canStopEarly && Input::ACTION))
break if Input.trigger?(Input::C) && @canStopEarly
frame = sprintf(@framesPath, @currentFrame)
picture = Sprite.new(viewport)
picture.bitmap = pbBitmap(frame)
picture.visible=true
pbWait(Graphics.frame_rate / 20)
picture.dispose
@currentFrame += 1
end
@finished=true
pbBGMStop
end
# not really necessary I think
# def pbAutoregulador()
# hora_inicio = $game_variables[VARIABLE_TIME_INITIAL]
# hora_actual = Time.now
# diferencia = (hora_actual - hora_inicio) * 20 #20 frames corresponde a 1 seg
# #Redondeo
# diferencia_entera = diferencia.to_i
#
# diferencia_entera = diferencia_entera.to_f
#
# if diferencia - diferencia_entera >= 0.5
# diferencia_entera = diferencia_entera + 1
# end
#
# $game_variables[VARIABLE_CURRENT_FRAME] = diferencia_entera.to_int
#
# $game_variables[VARIABLE_TIME_ELAPSED] = Time.now
#
# return $game_variables[VARIABLE_CURRENT_FRAME]
# end
end

View File

@@ -0,0 +1,898 @@
# Auto Multi Save by http404error
# For Pokemon Essentials v19.1
# Description:
# Adds multiple save slots and the abliity to auto-save.
# Included is code to autosave every 30 overworld steps. Feel free to edit or delete it (it's right at the top).
# On the Load screen you can use the left and right buttons while "Continue" is selected to cycle through files.
# When saving, you can quickly save to the same slot you loaded from, or pick another slot.
# Battle Challenges are NOT supported.
# Customization:
# I recommend altering your pause menu to quit to the title screen or load screen instead of exiting entirely.
# -> For instance, just change the menu text to "Quit to Title" and change `$scene = nil` to `$scene = pbCallTitle`.
# Call Game.auto_save whenever you want.
# -> Autosaving during an event script will correctly resume event execution when you load the game.
# -> I haven't investigated if it might be possible to autosave on closing the window with the X or Alt-F4 yet.
# You can rename the slots to your liking, or change how many there are.
# In some cases, you might want to remove the option to save to a different slot than the one you loaded from.
# Notes:
# On the first Load, the old Game.rxdata will be copied to the first slot in MANUAL_SLOTS. It won't have a known save time though.
# The interface to `Game.save` has been changed.
# Due to the slots, alters the save backup system in the case of save corruption/crashes - backups will be named Backup000.rxdata and so on.
# Heavily modifies the SaveData module and Save and Load screens. This may cause incompatibility with some other plugins or custom game code.
# Not everything here has been tested extensively, only what applies to normal usage of my game. Please let me know if you run into any problems.
# Future development ideas:
# There isn't currently support for unlimited slots but it wouldn't be too hard.
# Letting the user name their slots seems cool.
# It would be nice if there was a sliding animation for switching files on that load screen. :)
# It would be nice if the file select arrows used nicer animated graphics, kind of like the Bag.
# Maybe auto-save slots should act like a queue instead of cycling around.
# Autosave every 30 steps
# Events.onStepTaken += proc {
# $Trainer.autosave_steps = 0 if !$Trainer.autosave_steps
# $Trainer.autosave_steps += 1
# if $Trainer.autosave_steps >= 30
# echo("Autosaving...")
# $Trainer.autosave_steps = 0
# Game.auto_save
# echoln("done.")
# end
# }
def onLoadExistingGame()
migrateOldSavesToCharacterCustomization()
clear_all_images()
end
def onStartingNewGame() end
def migrateOldSavesToCharacterCustomization()
if !$Trainer.unlocked_clothes
$Trainer.unlocked_clothes = [DEFAULT_OUTFIT_MALE,
DEFAULT_OUTFIT_FEMALE,
STARTING_OUTFIT]
end
if !$Trainer.unlocked_hats
$Trainer.unlocked_hats = [DEFAULT_OUTFIT_MALE, DEFAULT_OUTFIT_FEMALE]
end
if !$Trainer.unlocked_hairstyles
$Trainer.unlocked_hairstyles = [DEFAULT_OUTFIT_MALE, DEFAULT_OUTFIT_FEMALE]
end
if !$Trainer.clothes || !$Trainer.hair #|| !$Trainer.hat
setupStartingOutfit()
end
end
#===============================================================================
#
#===============================================================================
module SaveData
# You can rename these slots or change the amount of them
# They change the actual save file names though, so it would take some extra work to use the translation system on them.
AUTO_SLOTS = [
'Auto 1',
'Auto 2'
]
MANUAL_SLOTS = [
'File A',
'File B',
'File C',
'File D',
'File E',
'File F',
'File G',
'File H'
]
# For compatibility with games saved without this plugin
OLD_SAVE_SLOT = 'Game'
SAVE_DIR = if File.directory?(System.data_directory)
System.data_directory
else
'.'
end
def self.each_slot
(AUTO_SLOTS + MANUAL_SLOTS).each { |f| yield f }
end
def self.get_full_path(file)
return "#{SAVE_DIR}/#{file}.rxdata"
end
def self.get_backup_file_path
backup_file = "Backup000"
while File.file?(self.get_full_path(backup_file))
backup_file.next!
end
return self.get_full_path(backup_file)
end
# Given a list of save file names and a file name in it, return the next file after it which exists
# If no other file exists, will just return the same file again
def self.get_next_slot(file_list, file)
old_index = file_list.find_index(file)
ordered_list = file_list.rotate(old_index + 1)
ordered_list.each do |f|
return f if File.file?(self.get_full_path(f))
end
# should never reach here since the original file should always exist
return file
end
# See self.get_next_slot
def self.get_prev_slot(file_list, file)
return self.get_next_slot(file_list.reverse, file)
end
# Returns nil if there are no saves
# Returns the first save if there's a tie for newest
# Old saves from previous version don't store their saved time, so are treated as very old
def self.get_newest_save_slot
newest_time = Time.at(0) # the Epoch
newest_slot = nil
self.each_slot do |file_slot|
full_path = self.get_full_path(file_slot)
next if !File.file?(full_path)
begin
temp_save_data = self.read_from_file(full_path)
rescue
next
end
save_time = temp_save_data[:player].last_time_saved || Time.at(1)
if save_time > newest_time
newest_time = save_time
newest_slot = file_slot
end
end
# Port old save
if newest_slot.nil? && File.file?(self.get_full_path(OLD_SAVE_SLOT))
file_copy(self.get_full_path(OLD_SAVE_SLOT), self.get_full_path(MANUAL_SLOTS[0]))
return MANUAL_SLOTS[0]
end
return newest_slot
end
# @return [Boolean] whether any save file exists
def self.exists?
self.each_slot do |slot|
full_path = SaveData.get_full_path(slot)
return true if File.file?(full_path)
end
return false
end
# This is used in a hidden function (ctrl+down+cancel on title screen) or if the save file is corrupt
# Pass nil to delete everything, or a file path to just delete that one
# @raise [Error::ENOENT]
def self.delete_file(file_path = nil)
if file_path
File.delete(file_path) if File.file?(file_path)
else
self.each_slot do |slot|
full_path = self.get_full_path(slot)
File.delete(full_path) if File.file?(full_path)
end
end
end
# Moves a save file from the old Saved Games folder to the new
# location specified by {MANUAL_SLOTS[0]}. Does nothing if a save file
# already exists in {MANUAL_SLOTS[0]}.
def self.move_old_windows_save
return if self.exists?
game_title = System.game_title.gsub(/[^\w ]/, '_')
home = ENV['HOME'] || ENV['HOMEPATH']
return if home.nil?
old_location = File.join(home, 'Saved Games', game_title)
return unless File.directory?(old_location)
old_file = File.join(old_location, 'Game.rxdata')
return unless File.file?(old_file)
File.move(old_file, MANUAL_SLOTS[0])
end
# Runs all possible conversions on the given save data.
# Saves a backup before running conversions.
# @param save_data [Hash] save data to run conversions on
# @return [Boolean] whether conversions were run
def self.run_conversions(save_data)
validate save_data => Hash
conversions_to_run = self.get_conversions(save_data)
return false if conversions_to_run.none?
File.open(SaveData.get_backup_file_path, 'wb') { |f| Marshal.dump(save_data, f) }
echoln "Backed up save to #{SaveData.get_backup_file_path}"
echoln "Running #{conversions_to_run.length} conversions..."
conversions_to_run.each do |conversion|
echo "#{conversion.title}..."
conversion.run(save_data)
echoln ' done.'
end
echoln '' if conversions_to_run.length > 0
save_data[:essentials_version] = Essentials::VERSION
save_data[:game_version] = Settings::GAME_VERSION
return true
end
end
#===============================================================================
#
#===============================================================================
class PokemonLoad_Scene
def pbChoose(commands, continue_idx)
@sprites["cmdwindow"].commands = commands
loop do
Graphics.update
Input.update
pbUpdate
if Input.trigger?(Input::USE)
return @sprites["cmdwindow"].index
elsif @sprites["cmdwindow"].index == continue_idx
@sprites["leftarrow"].visible = true
@sprites["rightarrow"].visible = true
if Input.trigger?(Input::LEFT)
return -3
elsif Input.trigger?(Input::RIGHT)
return -2
end
else
@sprites["leftarrow"].visible = false
@sprites["rightarrow"].visible = false
end
end
end
def pbStartScene(commands, show_continue, trainer, frame_count, map_id)
@commands = commands
@sprites = {}
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99998
addBackgroundOrColoredPlane(@sprites, "background", "loadbg", Color.new(248, 248, 248), @viewport)
@sprites["leftarrow"] = AnimatedSprite.new("Graphics/Pictures/leftarrow", 8, 40, 28, 2, @viewport)
@sprites["leftarrow"].x = 10
@sprites["leftarrow"].y = 140
@sprites["leftarrow"].play
#@sprites["leftarrow"].visible=true
@sprites["rightarrow"] = AnimatedSprite.new("Graphics/Pictures/rightarrow", 8, 40, 28, 2, @viewport)
@sprites["rightarrow"].x = 460
@sprites["rightarrow"].y = 140
@sprites["rightarrow"].play
#@sprites["rightarrow"].visible=true
y = 16 * 2
for i in 0...commands.length
@sprites["panel#{i}"] = PokemonLoadPanel.new(i, commands[i],
(show_continue) ? (i == 0) : false, trainer, frame_count, map_id, @viewport)
@sprites["panel#{i}"].x = 24 * 2
@sprites["panel#{i}"].y = y
@sprites["panel#{i}"].pbRefresh
y += (show_continue && i == 0) ? 112 * 2 : 24 * 2
end
@sprites["cmdwindow"] = Window_CommandPokemon.new([])
@sprites["cmdwindow"].viewport = @viewport
@sprites["cmdwindow"].visible = false
end
end
#===============================================================================
#
#===============================================================================
class PokemonLoadScreen
def initialize(scene)
@scene = scene
@selected_file = SaveData.get_newest_save_slot
end
# @param file_path [String] file to load save data from
# @return [Hash] save data
def load_save_file(file_path)
begin
save_data = SaveData.read_from_file(file_path)
rescue
save_data = try_load_backup(file_path)
end
unless SaveData.valid?(save_data)
save_data = try_load_backup(file_path)
end
return save_data
end
def try_load_backup(file_path)
if File.file?(file_path + ".bak")
pbMessage(_INTL("The save file is corrupt. A backup will be loaded."))
save_data = load_save_file(file_path + ".bak")
else
self.prompt_save_deletion(file_path)
return {}
end
return save_data
end
# Called if save file is invalid.
# Prompts the player to delete the save files.
def prompt_save_deletion(file_path)
pbMessage(_INTL("A save file is corrupt, or is incompatible with this game."))
self.delete_save_data(file_path) if pbConfirmMessageSerious(
_INTL("Do you want to delete that save file? The game will exit afterwards either way.")
)
exit
end
# nil deletes all, otherwise just the given file
def delete_save_data(file_path = nil)
begin
SaveData.delete_file(file_path)
pbMessage(_INTL("The save data was deleted."))
rescue SystemCallError
pbMessage(_INTL("The save data could not be deleted."))
end
end
def checkEnableSpritesDownload
if $PokemonSystem.download_sprites && $PokemonSystem.download_sprites != 0
customSprites = getCustomSpeciesList
if !customSprites
promptEnableSpritesDownload
else
if customSprites.length < 1000
promptEnableSpritesDownload
end
end
end
end
#So that the options menu is set on the correct difficulty on older saves
def ensureCorrectDifficulty()
$Trainer.selected_difficulty = 1 #normal
$Trainer.selected_difficulty = 0 if $game_switches[SWITCH_GAME_DIFFICULTY_EASY]
$Trainer.selected_difficulty = 2 if $game_switches[SWITCH_GAME_DIFFICULTY_HARD]
$Trainer.lowest_difficulty = $Trainer.selected_difficulty if !$Trainer.lowest_difficulty
end
def setGameMode()
$Trainer.game_mode = 0 #classic
$Trainer.game_mode = 2 if $game_switches[SWITCH_MODERN_MODE]
$Trainer.game_mode = 3 if $game_switches[SWITCH_EXPERT_MODE]
$Trainer.game_mode = 4 if $game_switches[SWITCH_SINGLE_POKEMON_MODE]
$Trainer.game_mode = 1 if $game_switches[SWITCH_RANDOMIZED_AT_LEAST_ONCE]
$Trainer.game_mode = 5 if $game_switches[ENABLED_DEBUG_MODE_AT_LEAST_ONCE]
end
def promptEnableSpritesDownload
message = "Some sprites appear to be missing from your game. \nWould you like the game to download sprites automatically while playing? (this requires an internet connection)"
if pbConfirmMessage(message)
$PokemonSystem.download_sprites = 0
end
end
def check_for_spritepack_update()
$updated_spritesheets = [] if !$updated_spritesheets
echoln new_spritepack_was_released()
if new_spritepack_was_released()
$updated_spritesheets = []
end
end
def preload_party(trainer)
spriteLoader = BattleSpriteLoader.new
for pokemon in trainer.party
spriteLoader.preload_sprite_from_pokemon(pokemon)
end
end
#unused - too slow, & multithreading not possible
# def preload_party_and_boxes(storage, trainer)
# echoln "Loading boxes and party into cache in the background"
# start_time = Time.now
# spriterLoader = BattleSpriteLoader.new
# for box in storage.boxes
# for pokemon in box.pokemon
# if pokemon != nil
# if !pokemon.egg?
# spriterLoader.preload_sprite_from_pokemon(pokemon)
# end
# end
# end
# end
# for pokemon in trainer.party
# spriterLoader.preload_sprite_from_pokemon(pokemon)
# end
# end_time = Time.now
# echoln "Finished in #{end_time - start_time} seconds"
# end
def pbStartLoadScreen
updateHttpSettingsFile
updateCreditsFile
updateCustomDexFile
newer_version = find_newer_available_version
if newer_version
pbMessage(_INTL("Version {1} is now available! Please use the game's installer to download the newest version. Check the Discord for more information.", newer_version))
end
if Settings::STARTUP_MESSAGES != ""
pbMessage(_INTL(Settings::STARTUP_MESSAGES))
end
if ($game_temp.unimportedSprites && $game_temp.unimportedSprites.size > 0)
handleReplaceExistingSprites()
end
if ($game_temp.nb_imported_sprites && $game_temp.nb_imported_sprites > 0)
pbMessage(_INTL("{1} new custom sprites were imported into the game", $game_temp.nb_imported_sprites.to_s))
end
checkEnableSpritesDownload
$game_temp.nb_imported_sprites = nil
copyKeybindings()
save_file_list = SaveData::AUTO_SLOTS + SaveData::MANUAL_SLOTS
first_time = true
loop do
# Outer loop is used for switching save files
if @selected_file
@save_data = load_save_file(SaveData.get_full_path(@selected_file))
else
@save_data = {}
end
commands = []
cmd_continue = -1
cmd_new_game = -1
cmd_options = -1
cmd_language = -1
cmd_mystery_gift = -1
cmd_debug = -1
cmd_quit = -1
show_continue = !@save_data.empty?
new_game_plus = show_continue && (@save_data[:player].new_game_plus_unlocked || $DEBUG)
if show_continue
commands[cmd_continue = commands.length] = "#{@selected_file}"
if @save_data[:player].mystery_gift_unlocked
commands[cmd_mystery_gift = commands.length] = _INTL('Mystery Gift') # Honestly I have no idea how to make Mystery Gift work well with this.
end
end
commands[cmd_new_game = commands.length] = _INTL('New Game')
if new_game_plus
commands[cmd_new_game_plus = commands.length] = _INTL('New Game +')
end
commands[cmd_options = commands.length] = _INTL('Options')
commands[cmd_language = commands.length] = _INTL('Language') if Settings::LANGUAGES.length >= 2
commands[cmd_discord = commands.length] = _INTL('Discord')
commands[cmd_wiki = commands.length] = _INTL('Wiki')
commands[cmd_debug = commands.length] = _INTL('Debug') if $DEBUG
commands[cmd_quit = commands.length] = _INTL('Quit Game')
cmd_left = -3
cmd_right = -2
map_id = show_continue ? @save_data[:map_factory].map.map_id : 0
@scene.pbStartScene(commands, show_continue, @save_data[:player],
@save_data[:frame_count] || 0, map_id)
@scene.pbSetParty(@save_data[:player]) if show_continue
if first_time
@scene.pbStartScene2
first_time = false
else
@scene.pbUpdate
end
loop do
# Inner loop is used for going to other menus and back and stuff (vanilla)
command = @scene.pbChoose(commands, cmd_continue)
pbPlayDecisionSE if command != cmd_quit
case command
when cmd_continue
@scene.pbEndScene
Game.load(@save_data)
$game_switches[SWITCH_V5_1] = true
ensureCorrectDifficulty()
setGameMode()
initialize_alt_sprite_substitutions()
$PokemonGlobal.autogen_sprites_cache = {}
check_for_spritepack_update()
preload_party(@save_data[:player])
return
when cmd_new_game
@scene.pbEndScene
Game.start_new
initialize_alt_sprite_substitutions()
return
when cmd_new_game_plus
@scene.pbEndScene
Game.start_new(@save_data[:bag], @save_data[:storage_system], @save_data[:player])
initialize_alt_sprite_substitutions()
@save_data[:player].new_game_plus_unlocked = true
return
when cmd_discord
openUrlInBrowser(Settings::DISCORD_URL)
when cmd_wiki
openUrlInBrowser(Settings::WIKI_URL)
when cmd_mystery_gift
pbFadeOutIn { pbDownloadMysteryGift(@save_data[:player]) }
when cmd_options
pbFadeOutIn do
scene = PokemonGameOption_Scene.new
screen = PokemonOptionScreen.new(scene)
screen.pbStartScreen(true)
end
when cmd_language
@scene.pbEndScene
$PokemonSystem.language = pbChooseLanguage
pbLoadMessages('Data/' + Settings::LANGUAGES[$PokemonSystem.language][1])
if show_continue
@save_data[:pokemon_system] = $PokemonSystem
File.open(SaveData.get_full_path(@selected_file), 'wb') { |file| Marshal.dump(@save_data, file) }
end
$scene = pbCallTitle
return
when cmd_debug
pbFadeOutIn { pbDebugMenu(false) }
when cmd_quit
pbPlayCloseMenuSE
@scene.pbEndScene
$scene = nil
return
when cmd_left
@scene.pbCloseScene
@selected_file = SaveData.get_prev_slot(save_file_list, @selected_file)
break # to outer loop
when cmd_right
@scene.pbCloseScene
@selected_file = SaveData.get_next_slot(save_file_list, @selected_file)
break # to outer loop
else
pbPlayBuzzerSE
end
end
end
end
end
#===============================================================================
#
#===============================================================================
class PokemonSave_Scene
def pbUpdateSlotInfo(slottext)
pbDisposeSprite(@sprites, "slotinfo")
@sprites["slotinfo"] = Window_AdvancedTextPokemon.new(slottext)
@sprites["slotinfo"].viewport = @viewport
@sprites["slotinfo"].x = 0
@sprites["slotinfo"].y = 160
@sprites["slotinfo"].width = 228 if @sprites["slotinfo"].width < 228
@sprites["slotinfo"].visible = true
end
end
#===============================================================================
#
#===============================================================================
class PokemonSaveScreen
def doSave(slot)
if Game.save(slot)
pbMessage(_INTL("\\se[]{1} saved the game.\\me[GUI save game]\\wtnp[30]", $Trainer.name))
return true
else
pbMessage(_INTL("\\se[]Save failed.\\wtnp[30]"))
return false
end
end
# Return true if pause menu should close after this is done (if the game was saved successfully)
def pbSaveScreen
ret = false
@scene.pbStartScreen
if !$Trainer.save_slot
# New Game - must select slot
ret = slotSelect
else
choices = [
_INTL("Save to #{$Trainer.save_slot}"),
_INTL("Save to another slot"),
_INTL("Don't save")
]
opt = pbMessage(_INTL('Would you like to save the game?'), choices, 3)
if opt == 0
pbSEPlay('GUI save choice')
ret = doSave($Trainer.save_slot)
elsif opt == 1
pbPlayDecisionSE
ret = slotSelect
else
pbPlayCancelSE
end
end
@scene.pbEndScreen
return ret
end
# Call this to open the slot select screen
# Returns true if the game was saved, otherwise false
def slotSelect
ret = false
choices = SaveData::MANUAL_SLOTS
choice_info = SaveData::MANUAL_SLOTS.map { |s| getSaveInfoBoxContents(s) }
index = slotSelectCommands(choices, choice_info)
if index >= 0
slot = SaveData::MANUAL_SLOTS[index]
# Confirm if slot not empty
if !File.file?(SaveData.get_full_path(slot)) ||
pbConfirmMessageSerious(_INTL("Are you sure you want to overwrite the save in #{slot}?")) # If the slot names were changed this grammar might need adjustment.
pbSEPlay('GUI save choice')
ret = doSave(slot)
end
end
pbPlayCloseMenuSE if !ret
return ret
end
# Handles the UI for the save slot select screen. Returns the index of the chosen slot, or -1.
# Based on pbShowCommands
def slotSelectCommands(choices, choice_info, defaultCmd = 0)
msgwindow = Window_AdvancedTextPokemon.new(_INTL("Which slot to save in?"))
msgwindow.z = 99999
msgwindow.visible = true
msgwindow.letterbyletter = true
msgwindow.back_opacity = MessageConfig::WINDOW_OPACITY
pbBottomLeftLines(msgwindow, 2)
$game_temp.message_window_showing = true if $game_temp
msgwindow.setSkin(MessageConfig.pbGetSpeechFrame)
cmdwindow = Window_CommandPokemonEx.new(choices)
cmdwindow.z = 99999
cmdwindow.visible = true
cmdwindow.resizeToFit(cmdwindow.commands)
pbPositionNearMsgWindow(cmdwindow, msgwindow, :right)
cmdwindow.index = defaultCmd
command = 0
loop do
@scene.pbUpdateSlotInfo(choice_info[cmdwindow.index])
Graphics.update
Input.update
cmdwindow.update
msgwindow.update if msgwindow
if Input.trigger?(Input::BACK)
command = -1
break
end
if Input.trigger?(Input::USE)
command = cmdwindow.index
break
end
pbUpdateSceneMap
end
ret = command
cmdwindow.dispose
msgwindow.dispose
$game_temp.message_window_showing = false if $game_temp
Input.update
return ret
end
# Show the player some data about their currently selected save slot for quick identification
# This doesn't use player gender for coloring, unlike the default save window
def getSaveInfoBoxContents(slot)
full_path = SaveData.get_full_path(slot)
if !File.file?(full_path)
return _INTL("<ac><c3=3050C8,D0D0C8>(empty)</c3></ac>")
end
temp_save_data = SaveData.read_from_file(full_path)
# Last save time
time = temp_save_data[:player].last_time_saved
if time
date_str = time.strftime("%x")
time_str = time.strftime(_INTL("%I:%M%p"))
datetime_str = "#{date_str}<r>#{time_str}<br>"
else
datetime_str = _INTL("<ac>(old save)</ac>")
end
# Map name
map_str = pbGetMapNameFromId(temp_save_data[:map_factory].map.map_id)
# Elapsed time
totalsec = (temp_save_data[:frame_count] || 0) / Graphics.frame_rate
hour = totalsec / 60 / 60
min = totalsec / 60 % 60
if hour > 0
elapsed_str = _INTL("Time<r>{1}h {2}m<br>", hour, min)
else
elapsed_str = _INTL("Time<r>{1}m<br>", min)
end
return "<c3=3050C8,D0D0C8>#{datetime_str}</c3>" + # blue
"<ac><c3=209808,90F090>#{map_str}</c3></ac>" + # green
"#{elapsed_str}"
end
end
#===============================================================================
#
#===============================================================================
module Game
# Fix New Game bug (if you saved during an event script)
# This fix is from Essentials v20.1 Hotfixes 1.0.5
def self.start_new(ngp_bag = nil, ngp_storage = nil, ngp_trainer = nil)
if $game_map && $game_map.events
$game_map.events.each_value { |event| event.clear_starting }
end
$game_temp.common_event_id = 0 if $game_temp
$PokemonTemp.begunNewGame = true
pbMapInterpreter&.clear
pbMapInterpreter&.setup(nil, 0, 0)
$scene = Scene_Map.new
SaveData.load_new_game_values
$MapFactory = PokemonMapFactory.new($data_system.start_map_id)
$game_player.moveto($data_system.start_x, $data_system.start_y)
$game_player.refresh
$PokemonEncounters = PokemonEncounters.new
$PokemonEncounters.setup($game_map.map_id)
$game_map.autoplay
$game_map.update
#
# if ngp_bag != nil
# $PokemonBag = ngp_clean_item_data(ngp_bag)
# end
if ngp_storage != nil
$PokemonStorage = ngp_clean_pc_data(ngp_storage, ngp_trainer.party)
end
if ngp_trainer
$Trainer.unlocked_hats = ngp_trainer.unlocked_hats
$Trainer.unlocked_clothes = ngp_trainer.unlocked_clothes
end
end
# Loads bootup data from save file (if it exists) or creates bootup data (if
# it doesn't).
def self.set_up_system
SaveData.move_old_windows_save if System.platform[/Windows/]
save_slot = SaveData.get_newest_save_slot
if save_slot
save_data = SaveData.read_from_file(SaveData.get_full_path(save_slot))
else
save_data = {}
end
if save_data.empty?
SaveData.initialize_bootup_values
else
SaveData.load_bootup_values(save_data)
end
# Set resize factor
pbSetResizeFactor([$PokemonSystem.screensize, 4].min)
# Set language (and choose language if there is no save file)
if Settings::LANGUAGES.length >= 2
$PokemonSystem.language = pbChooseLanguage if save_data.empty?
pbLoadMessages('Data/' + Settings::LANGUAGES[$PokemonSystem.language][1])
end
end
def self.backup_savefile(save_path, slot)
backup_dir = File.join(File.dirname(save_path), "backups")
Dir.mkdir(backup_dir) if !Dir.exist?(backup_dir)
backup_slot_dir = File.join(File.dirname(save_path), "backups/#{slot}")
Dir.mkdir(backup_slot_dir) if !Dir.exist?(backup_slot_dir)
# Manage rolling backups
if File.exist?(save_path)
# Generate a timestamped backup name
timestamp = Time.now.strftime("%Y%m%d%H%M%S")
backup_file = File.join(backup_slot_dir, "#{slot}_#{timestamp}.rxdata")
# Copy the save file manually
File.open(save_path, 'rb') do |source|
File.open(backup_file, 'wb') do |dest|
dest.write(source.read)
end
end
# Clean up old backups
backups = Dir.get(backup_slot_dir, "*.rxdata")
# Keep only the latest N backups
if backups.length > Settings::SAVEFILE_NB_BACKUPS
excess_backups = backups[0...(backups.length - Settings::SAVEFILE_NB_BACKUPS)]
echoln excess_backups
excess_backups.each { |old_backup| File.delete(old_backup) }
end
end
end
# Saves the game. Returns whether the operation was successful.
# @param save_file [String] the save file path
# @param safe [Boolean] whether $PokemonGlobal.safesave should be set to true
# @return [Boolean] whether the operation was successful
# @raise [SaveData::InvalidValueError] if an invalid value is being saved
def self.save(slot = nil, auto = false, safe: false)
slot = $Trainer.save_slot if slot.nil?
return false if slot.nil?
file_path = SaveData.get_full_path(slot)
self.backup_savefile(file_path, slot)
$PokemonGlobal.safesave = safe
$game_system.save_count += 1
$game_system.magic_number = $data_system.magic_number
$Trainer.save_slot = slot unless auto
$Trainer.last_time_saved = Time.now
begin
SaveData.save_to_file(file_path)
Graphics.frame_reset
rescue IOError, SystemCallError
$game_system.save_count -= 1
return false
end
return true
end
# Overwrites the first empty autosave slot, otherwise the oldest existing autosave
def self.auto_save
oldest_time = nil
oldest_slot = nil
SaveData::AUTO_SLOTS.each do |slot|
full_path = SaveData.get_full_path(slot)
if !File.file?(full_path)
oldest_slot = slot
break
end
temp_save_data = SaveData.read_from_file(full_path)
save_time = temp_save_data[:player].last_time_saved || Time.at(1)
if oldest_time.nil? || save_time < oldest_time
oldest_time = save_time
oldest_slot = slot
end
end
self.save(oldest_slot, true)
end
end
#===============================================================================
#
#===============================================================================
# Lol who needs the FileUtils gem?
# This is the implementation from the original pbEmergencySave.
def file_copy(src, dst)
File.open(src, 'rb') do |r|
File.open(dst, 'wb') do |w|
while s = r.read(4096)
w.write s
end
end
end
end
# When I needed extra data fields in the save file I put them in Player because it seemed easier than figuring out
# how to make a save file conversion, and I prefer to maintain backwards compatibility.
class Player
attr_accessor :last_time_saved
attr_accessor :save_slot
attr_accessor :autosave_steps
end
def pbEmergencySave
oldscene = $scene
$scene = nil
pbMessage(_INTL("The script is taking too long. The game will restart."))
return if !$Trainer
return if !$Trainer.save_slot
current_file = SaveData.get_full_path($Trainer.save_slot)
backup_file = SaveData.get_backup_file_path
file_copy(current_file, backup_file)
if Game.save
pbMessage(_INTL("\\se[]The game was saved.\\me[GUI save game] The previous save file has been backed up.\\wtnp[30]"))
else
pbMessage(_INTL("\\se[]Save failed.\\wtnp[30]"))
end
$scene = oldscene
end

View File

@@ -0,0 +1,128 @@
###################
## NEW POKEBALLS #
###################
#GENDER BALL (24) - switch le gender du pokemon
#catch rate: pokeball
BallHandlers::OnCatch.add(:GENDERBALL,proc{|ball,battle,pokemon|
if pokemon.gender == 0
pokemon.makeFemale
elsif pokemon.gender == 1
pokemon.makeMale
end
})
#BOOST BALL 25 - rend le pokemon traded
#catch rate: 80% pokeball
BallHandlers::ModifyCatchRate.add(:TRADEBALL,proc{|ball,catchRate,battle,pokemon|
catchRate=(catchRate*0.8).floor(1)
next catchRate
})
BallHandlers::OnCatch.add(:TRADEBALL,proc{|ball,battle,pokemon|
pokemon.obtain_method = 2
})
#ABILITY BALL 26 - change l'ability
#catch rate: 60% pokeball
BallHandlers::ModifyCatchRate.add(:ABILITYBALL,proc{|ball,catchRate,battle,pokemon|
catchRate=(catchRate*0.6).floor(1)
next catchRate
})
BallHandlers::OnCatch.add(:ABILITYBALL,proc{|ball,battle,pokemon|
species = getSpecies(dexNum(pokemon))
ability = species.hidden_abilities[-1]
pokemon.ability = ability
pokemon.ability_index= getAbilityIndexFromID(ability,pokemon)
})
#VIRUS BALL 27 - give pokerus
#catch rate: 40% pokeball
BallHandlers::ModifyCatchRate.add(:VIRUSBALL,proc{|ball,catchRate,battle,pokemon|
catchRate=(catchRate*0.4).floor(1)
next catchRate
})
BallHandlers::OnCatch.add(:VIRUSBALL,proc{|ball,battle,pokemon|
pokemon.givePokerus
})
#SHINY BALL 28 - rend shiny
#catchrate: 20% pokeball
BallHandlers::ModifyCatchRate.add(:SHINYBALL,proc{|ball,catchRate,battle,pokemon|
catchRate=(catchRate*0.2).floor(1)
next catchRate
})
BallHandlers::OnCatch.add(:SHINYBALL,proc{|ball,battle,pokemon|
pokemon.glitter=true
})
#PERFECTBALL 29
#catch rate: 10% pokeball
BallHandlers::ModifyCatchRate.add(:PERFECTBALL,proc{|ball,catchRate,battle,pokemon|
catchRate=(catchRate*0.1).floor(1)
next catchRate
})
BallHandlers::OnCatch.add(:PERFECTBALL,proc{|ball,battle,pokemon|
stats = [:ATTACK, :SPECIAL_ATTACK, :SPECIAL_DEFENSE, :SPEED, :DEFENSE, :HP]
first = rand(stats.length)
second = rand(stats.length)
pokemon.iv[stats[first]] = 31
pokemon.iv[stats[second]] = 31
})
#DREAMBALL - endormi
BallHandlers::ModifyCatchRate.add(:DREAMBALL,proc{|ball,catchRate,battle,battler|
battler.status = :SLEEP
next catchRate
})
#TOXICBALL - empoisonné
BallHandlers::ModifyCatchRate.add(:TOXICBALL,proc{|ball,catchRate,battle,battler|
battler.status = :POISON
next catchRate
})
#SCORCHBALL - brulé
BallHandlers::ModifyCatchRate.add(:SCORCHBALL,proc{|ball,catchRate,battle,battler|
battler.status = :BURN
next catchRate
})
#FROSTBALL - frozen
BallHandlers::ModifyCatchRate.add(:FROSTBALL,proc{|ball,catchRate,battle,battler|
battler.status = :FROZEN
next catchRate
})
#SPARKBALL - paralizé
BallHandlers::ModifyCatchRate.add(:SPARKBALL,proc{|ball,catchRate,battle,battler|
battler.status = :PARALYSIS
next catchRate
})
#PUREBALL - marche mieux quand pas de status
BallHandlers::ModifyCatchRate.add(:PUREBALL,proc{|ball,catchRate,battle,battler|
catchRate=(catchRate*7/2).floor if battler.status ==0
next catchRate
})
#STATUSBALL - marche mieux quand any status
BallHandlers::ModifyCatchRate.add(:STATUSBALL,proc{|ball,catchRate,battle,battler|
catchRate=(catchRate*5/2).floor if battler.status !=0
next catchRate
})
#FUSIONBALL - marche mieux quand fusedr
BallHandlers::ModifyCatchRate.add(:FUSIONBALL,proc{|ball,catchRate,battle,battler|
catchRate*=3 if GameData::Species.get(battler.species).id_number > Settings::NB_POKEMON
next catchRate
})
#CANDY BALL - +5 level
#catchrate: 80% pokeball
BallHandlers::ModifyCatchRate.add(:CANDYBALL,proc{|ball,catchRate,battle,pokemon|
catchRate=(catchRate*0.8).floor
next catchRate
})
BallHandlers::OnCatch.add(:CANDYBALL,proc{|ball,battle,pokemon|
pokemon.level = pokemon.level+5
})
#FIRECRACKER
BallHandlers::ModifyCatchRate.add(:FIRECRACKER,proc{|ball,catchRate,battle,battler|
battler.hp -= 10
next 0
})

View File

@@ -0,0 +1,141 @@
#===============================================================================
# Rock Smash
#===============================================================================
def pbRockSmashRandomEncounter
if rand(100)<30
if pbEncounter(:RockSmash)
return
else
pbDefaultRockSmashEncounter(5,15)
end
else
rockSmashItem(false)
end
end
def pbDefaultRockSmashEncounter(minLevel,maxLevel)
level =rand((maxLevel-minLevel).abs)+minLevel
pbWildBattle(:GEODUDE,level)
return true
end
#FOR ROCK TUNNEL AND CERULEAN CAVE (+diamond)
def pbRockSmashRandomEncounterSpecial
if rand(100)<35
pbEncounter(:RockSmash)
else
rockSmashItem(true)
end
end
def getRockSmashItemList(inclRareItems)
basicItems = [:ROCKGEM, :GROUNDGEM,:STEELGEM,
:HARDSTONE,:HARDSTONE,:HARDSTONE,:ROCKGEM,
:SMOOTHROCK,:STARDUST,:HEARTSCALE,:HEARTSCALE,
:HEARTSCALE,:SOFTSAND,:HEARTSCALE,:RAREBONE]
rareItems = [:RAREBONE,:STARDUST,:ETHER,
:REVIVE,:NUGGET,:DIAMOND]
fossilItems = [:ROOTFOSSIL,:CLAWFOSSIL,:DOMEFOSSIL,:HELIXFOSSIL,
:SKULLFOSSIL,:ARMORFOSSIL,:JAWFOSSIL,:SAILFOSSIL]
# Kernel.pbMessage(inclRareItems.to_s)
itemsList = inclRareItems ? basicItems + basicItems + rareItems : basicItems
#beaten league
if $game_switches[12]
itemsList += fossilItems
end
return itemsList
end
def rockSmashItem(isDark=false)
chance = 50
if rand(100)< chance
if rand(5) == 0 && !hatUnlocked?(HAT_AERODACTYL)
obtainHat(HAT_AERODACTYL)
else
itemsList = getRockSmashItemList(isDark)
i = rand(itemsList.length)
Kernel.pbItemBall(itemsList[i],1,nil,false)
end
end
end
#Used in underwater maps
def pbRockSmashRandomEncounterDive
if rand(100)<25
pbEncounter(:RockSmash)
else
if rand(100)<20
itemsList = [:WATERGEM,:STEELGEM,
:HEARTSCALE,:HEARTSCALE,:HARDSTONE,:ROCKGEM,
:SMOOTHROCK,:WATERSTONE,:PEARL,:HEARTSCALE,
:HEARTSCALE,:HEARTSCALE,:SHOALSHELL,:BIGPEARL]
i = rand(itemsList.length)
Kernel.pbItemBall(itemsList[i],1,nil,false)
end
end
end
############### MORNING SUN / MOONLIGHT
HiddenMoveHandlers::CanUseMove.add(:MORNINGSUN,proc{|move,pkmn|
mapMetadata = GameData::MapMetadata.try_get($game_map.map_id)
if !mapMetadata || !mapMetadata.outdoor_map
Kernel.pbMessage(_INTL("Can't use that here."))
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:MORNINGSUN,proc{|move,pokemon|
Kernel.pbMessage(_INTL("{1} used {2}!",pokemon.name,GameData::Move.get(move).name))
pbHiddenMoveAnimation(pokemon)
pbFadeOutIn(99999){
pbSkipTime(9)
newTime = pbGetTimeNow.strftime("%I:%M %p")
Kernel.pbMessage(_INTL("{1} waited until morning...",$Trainer.name))
Kernel.pbMessage(_INTL("The time is now {1}",newTime))
$game_screen.weather(:None,0,0)
$game_map.refresh
}
next true
})
HiddenMoveHandlers::CanUseMove.add(:MOONLIGHT,proc{|move,pkmn|
mapMetadata = GameData::MapMetadata.try_get($game_map.map_id)
if !mapMetadata || !mapMetadata.outdoor_map
Kernel.pbMessage(_INTL("Can't use that here."))
next false
end
next true
})
HiddenMoveHandlers::UseMove.add(:MOONLIGHT,proc{|move,pokemon|
Kernel.pbMessage(_INTL("{1} used {2}!",pokemon.name,GameData::Move.get(move).name))
pbHiddenMoveAnimation(pokemon)
pbFadeOutIn(99999){
pbSkipTime(21)
newTime = pbGetTimeNow.strftime("%I:%M %p")
Kernel.pbMessage(_INTL("{1} waited until night...",$Trainer.name))
Kernel.pbMessage(_INTL("The time is now {1}",newTime))
$game_screen.weather(:None,0,0)
$game_map.refresh
}
next true
})
def pbSkipTime(newTime)
currentTime = pbGetTimeNow.hour
hoursToAdd = newTime - currentTime
$game_variables[UnrealTime::EXTRA_SECONDS] += hoursToAdd*3600
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
class VariableCurrencyMartAdapter < PokemonMartAdapter
def initialize(currency)
@currency_variable = currency
end
def getMoney
return pbGet(@currency_variable).to_i
end
def getMoneyString
return pbGet(@currency_variable).to_s
end
def setMoney(value)
pbSet(@currency_variable,value)
end
end
def pbVariablePokemonMart(stock,currencyVariable,currency_name="Points",speech=nil,cantsell=true)
for i in 0...stock.length
stock[i] = GameData::Item.get(stock[i]).id
stock[i] = nil if GameData::Item.get(stock[i]).is_important? && $PokemonBag.pbHasItem?(stock[i])
end
stock.compact!
commands = []
cmdBuy = -1
cmdSell = -1
cmdQuit = -1
commands[cmdBuy = commands.length] = _INTL("Buy")
commands[cmdSell = commands.length] = _INTL("Sell") if !cantsell
commands[cmdQuit = commands.length] = _INTL("Quit")
cmd = pbMessage(
speech ? speech : _INTL("Welcome! How may I serve you?"),
commands,cmdQuit+1)
loop do
if cmdBuy>=0 && cmd==cmdBuy
adapter = VariableCurrencyMartAdapter.new(currencyVariable)
scene = PokemonMart_Scene.new(currency_name)
screen = PokemonMartScreen.new(scene,stock,adapter)
screen.pbBuyScreen
elsif cmdSell>=0 && cmd==cmdSell #NOT IMPLEMENTED
scene = PokemonMart_Scene.new(currency_name)
screen = PokemonMartScreen.new(scene,stock,adapter)
screen.pbSellScreen
else
pbMessage(_INTL("Please come again!"))
break
end
cmd = pbMessage(_INTL("Is there anything else I can help you with?"),
commands,cmdQuit+1)
end
$game_temp.clear_mart_prices
end

View File

@@ -0,0 +1,91 @@
class OnlineWondertrade
def pbWonderTrade()
givenPokemon = selectPokemonToGive
return if givenPokemon == nil
queryBody = buildWondertradeQueryJson(givenPokemon)
begin
response = HTTPLite.post_body(Settings::WONDERTRADE_BASE_URL + "/wondertrade", queryBody, "application/json")
if response[:status] == 200
body = HTTPLite::JSON.parse(response[:body])
doTrade(body)
else
pbMessage("Could not find a trading partner...")
end
rescue MKXPError
pbMessage("There was an error while sending your Pokémon...")
end
end
def doTrade(receivedData)
receivedPokemonSpecies = receivedData["pokemon_species"].to_sym
receivedPokemonLevel = receivedData["level"].to_i
receivedPokemonName = receivedData["nickname"]
receivedPokemonOT = receivedData["original_trainer_name"]
receivedPokemonTrainerId = receivedData["trainer_id"]
receivedPokemonTrainerName = receivedData["trainer_name"]
receivedPokemonTrainerGender = receivedData["trainer_gender"].to_i
is_head_shiny = receivedData["head_shiny"]
is_body_shiny = receivedData["body_shiny"]
is_debug_shiny = receivedData["debug_shiny"]
newpoke = pbStartTrade(pbGet(1), receivedPokemonSpecies, receivedPokemonName, receivedPokemonTrainerName, receivedPokemonTrainerGender, true) # Starts the trade
newpoke.owner=Pokemon::Owner.new(receivedPokemonTrainerId.to_i,receivedPokemonOT,2,2)
newpoke.level=receivedPokemonLevel
if is_head_shiny || is_body_shiny
newpoke.shiny=true
newpoke.head_shiny=is_head_shiny
newpoke.body_shiny = is_body_shiny
if is_debug_shiny
newpoke.debug_shiny=false
newpoke.natural_shiny=true
else
newpoke.debug_shiny=true
newpoke.natural_shiny=false
end
end
newpoke.calc_stats
end
def selectPokemonToGive
pbChoosePokemon(1, 2, # Choose eligable pokemon
proc {
|poke| !poke.egg? &&
!(poke.isShadow?) &&
poke.isFusion? &&
customSpriteExistsSpecies(poke.species) #&&
# !poke.debug_shiny
})
poke = $Trainer.party[pbGet(1)]
if pbConfirmMessage(_INTL("Trade {1} away?", poke.name))
return poke
end
return nil
end
# @param [Pokemon] givenPokemon
def buildWondertradeQueryJson(givenPokemon)
isDebugShiny = givenPokemon.debug_shiny || !givenPokemon.natural_shiny
postData = {
"trainer_name" => $Trainer.name,
"trainer_gender" => $Trainer.gender,
"trainer_id" => $Trainer.id.to_s,
"nb_badges" => $Trainer.badge_count,
"given_pokemon" => givenPokemon.species.to_s,
"level" => givenPokemon.level,
"nickname" => givenPokemon.name,
"original_trainer_name" => givenPokemon.owner.name,
"original_trainer_id" => givenPokemon.owner.id.to_s,
"body_shiny" => givenPokemon.body_shiny == nil ? false : givenPokemon.body_shiny,
"head_shiny" => givenPokemon.head_shiny == nil ? false : givenPokemon.head_shiny,
"debug_shiny" => isDebugShiny,
"original_trainer_id" => givenPokemon.owner.id.to_s,
}
return HTTPLite::JSON.stringify(postData)
end
end

View File

@@ -0,0 +1,3 @@
def pbGetCurrentRegion(defaultRegion = -1)
return -1
end

View File

@@ -0,0 +1,302 @@
#==============================================================================#
# Overworld Shadows #
# by Marin #
#==============================================================================#
# Info #
# #
# You'll have likely heard of KleinStudios' Overworld Shadows script; many #
# fangames use it, after all. It was not compatible with Essentials v17+ #
# though, so after getting the suggestion I thought it would be cool if I #
# could make something of my own that would work with v16, as well as v17. #
#==============================================================================#
# Features: #
# - Blacklisting events from receiving shadows #
# - Whitelisting events to always receive shadows #
# - A scaling animation when an event jumps #
#==============================================================================#
# Usage #
# #
# Shadow_Path is the path to the shadow graphic. You can change this #
# sprite, though you may need to fiddle with positioning of the sprite in #
# relation to the event after, though. That's done in "def position_shadow". #
# #
# As the name literally says, if an event's name includes any of the strings #
# in "No_Shadow_If_Event_Name_Has", it won't get a shadow, UNLESS the event's #
# name also includes any of the strings in #
# "Always_Give_Shadow_If_Event_Name_Has". This is essentially "overriding". #
# #
# Case_Sensitive is either true or false. It's used when determing if an #
# event's name includes a string in the "No_Shadow" and "Always_Give" arrays. #
# If true, it must match all strings with capitals exactly as well. #
# If false, capitals don't need to match up. #
#==============================================================================#
# Please give credit when using this. #
#==============================================================================#
SHADOW_IMG_FOLDER = "Graphics/Characters/"
SHADOW_IMG_NAME = "shadow"
# Whether or not the event names below need to match in capitals as well.
Case_Sensitive = false
No_Shadow_If_Event_Name_Has = [
# I like to use "extensions" like these. Up to you though.
".shadowless",
".noshadow",
".sl",
"Door",
"Stairs"
]
# Events that have this in their event name will always receive a shadow.
# Does take "Case_Sensitive" into account.
Always_Give_Shadow_If_Event_Name_Has = [
"Trainer", "npc"
]
# Determines whether or not an event should be given a shadow.
def pbShouldGetShadow?(event)
return true if event.is_a?(Game_Player) # The player will always have a shadow
page = pbGetActiveEventPage(event)
return false unless page
comments = page.list.select { |e| e.code == 108 || e.code == 408 }.map do |e|
e.parameters.join
end
Always_Give_Shadow_If_Event_Name_Has.each do |e|
name = event.name.clone
unless Case_Sensitive
e.downcase!
name.downcase!
end
return true if name.include?(e) || comments.any? { |c| c.include?(e) }
end
No_Shadow_If_Event_Name_Has.each do |e|
name = event.name.clone
unless Case_Sensitive
e.downcase!
name.downcase!
end
return false if name.include?(e) || comments.any? { |c| c.include?(e) }
end
return true
end
# Extending so we can access some private instance variables.
class Game_Character
attr_reader :jump_count
end
unless Spriteset_Map.respond_to?(:viewport)
class Spriteset_Map
def viewport
return @viewport1
end
def self.viewport
return $scene.spriteset.viewport rescue nil
end
end
end
# Following Pokémon compatibility
def pbToggleFollowingPokemon
return if $Trainer.party[0].hp <= 0 || $Trainer.party[0].isEgg?
if $game_switches[Following_Activated_Switch]
if $game_switches[Toggle_Following_Switch]
$game_switches[Toggle_Following_Switch] = false
$PokemonTemp.dependentEvents.remove_sprite(true)
$scene.spriteset.usersprites.select do |e|
e.is_a?(DependentEventSprites)
end.each do |des|
des.sprites.each do |e|
if e && e.shadow
e.shadow.dispose
e.shadow = nil
end
end
end
pbWait(1)
else
$game_switches[Toggle_Following_Switch] = true
$PokemonTemp.dependentEvents.refresh_sprite
$scene.spriteset.usersprites.select do |e|
e.is_a?(DependentEventSprites)
end.each do |des|
des.sprites.each do |e|
e.make_shadow if e.respond_to?(:make_shadow)
end
end
pbWait(1)
end
end
end
class DependentEventSprites
def refresh
for sprite in @sprites
sprite.dispose
end
@sprites.clear
$PokemonTemp.dependentEvents.eachEvent do |event, data|
if data[2] == @map.map_id # Check current map
spr = Sprite_Character.new(@viewport,event,true)
@sprites.push(spr)
end
end
end
end
unless defined?(pbGetActiveEventPage)
def pbGetActiveEventPage(event, mapid = nil)
mapid ||= event.map.map_id if event.respond_to?(:map)
pages = (event.is_a?(RPG::Event) ? event.pages : event.instance_eval { @event.pages })
for i in 0...pages.size
c = pages[pages.size - 1 - i].condition
ss = !(c.self_switch_valid && !$game_self_switches[[mapid,
event.id,c.self_switch_ch]])
sw1 = !(c.switch1_valid && !$game_switches[c.switch1_id])
sw2 = !(c.switch2_valid && !$game_switches[c.switch2_id])
var = true
if c.variable_valid
if !c.variable_value || !$game_variables[c.variable_id].is_a?(Numeric) ||
$game_variables[c.variable_id] < c.variable_value
var = false
end
end
if ss && sw1 && sw2 && var # All conditions are met
return pages[pages.size - 1 - i]
end
end
return nil
end
end
class Spriteset_Map
attr_accessor :usersprites
end
class Sprite_Character
attr_accessor :shadow
alias ow_shadow_init initialize
def initialize(viewport, character = nil, is_follower = false)
@viewport = viewport
@is_follower = is_follower
ow_shadow_init(@viewport, character)
return unless pbShouldGetShadow?(character)
return if @is_follower && defined?(Toggle_Following_Switch) &&
!$game_switches[Toggle_Following_Switch]
return if @is_follower && defined?(Following_Activated_Switch) &&
!$game_switches[Following_Activated_Switch]
@character = character
if @character.is_a?(Game_Event)
page = pbGetActiveEventPage(@character)
return if !page || !page.graphic || page.graphic.character_name == ""
end
make_shadow
end
def make_shadow
@shadow.dispose if @shadow
@shadow = nil
@shadow = Sprite.new(@viewport)
@shadow.bitmap = RPG::Cache.load_bitmap(SHADOW_IMG_FOLDER,SHADOW_IMG_NAME)
# Center the shadow by halving the origin points
@shadow.ox = @shadow.bitmap.width / 2.0
@shadow.oy = @shadow.bitmap.height / 2.0
# Positioning the shadow
position_shadow
end
def position_shadow
return unless @shadow
# x = @character.screen_x
# y = @character.screen_y
# if @character.jumping?
# @totaljump = @character.jump_count if !@totaljump
# case @character.jump_count
# when 1..(@totaljump / 3)
# @shadow.zoom_x += 0.1
# @shadow.zoom_y += 0.1
# when (@totaljump / 3 + 1)..(@totaljump / 3 + 2)
# @shadow.zoom_x += 0.05
# @shadow.zoom_y += 0.05
# when (@totaljump / 3 * 2 - 1)..(@totaljump / 3 * 2)
# @shadow.zoom_x -= 0.05
# @shadow.zoom_y -= 0.05
# when (@totaljump / 3 * 2 + 1)..(@totaljump)
# @shadow.zoom_x -= 0.1
# @shadow.zoom_y -= 0.1
# end
# if @character.jump_count == 1
# @shadow.zoom_x = 1.0
# @shadow.zoom_y = 1.0
# @totaljump = nil
# end
# end
@shadow.x = x
@shadow.y = y - 6
@shadow.z = self.z - 1
if @shadow
if @charbitmap.disposed? || @character.instance_eval { @erased }
@shadow.dispose
@shadow = nil
end
end
end
alias ow_shadow_visible visible=
def visible=(value)
ow_shadow_visible(value)
@shadow.visible = value if @shadow
end
alias ow_shadow_dispose dispose
def dispose
ow_shadow_dispose
@shadow.dispose if @shadow
@shadow = nil
end
alias ow_shadow_update update
def update
ow_shadow_update
position_shadow
if @character.is_a?(Game_Event)
page = pbGetActiveEventPage(@character)
if @old_page != page
@shadow.dispose if @shadow
@shadow = nil
if page && page.graphic && page.graphic.character_name != "" &&
pbShouldGetShadow?(@character)
unless @is_follower && defined?(Toggle_Following_Switch) &&
!$game_switches[Toggle_Following_Switch]
unless @is_follower && defined?(Following_Activated_Switch) &&
!$game_switches[Following_Activated_Switch]
make_shadow
end
end
end
end
end
@old_page = (@character.is_a?(Game_Event) ? pbGetActiveEventPage(@character) : nil)
bushdepth = @character.bush_depth
if @shadow
@shadow.opacity = self.opacity
@shadow.visible = (bushdepth == 0)
if !self.visible || (@is_follower || @character == $game_player) &&
($PokemonGlobal.surfing || $PokemonGlobal.diving)
@shadow.visible = false
end
end
end
end

View File

@@ -0,0 +1,89 @@
def getDirection(x_incr,y_incr)
return DIRECTION_RIGHT if x_incr>0
return DIRECTION_LEFT if x_incr<0
return DIRECTION_DOWN if y_incr>0
return DIRECTION_UP if y_incr<0
return 0
end
def get_direction_forward_x(directionId)
return 1 if directionId == DIRECTION_RIGHT
return -1 if directionId == DIRECTION_LEFT
return 0
end
def get_direction_forward_y(directionId)
return 1 if directionId == DIRECTION_DOWN
return -1 if directionId == DIRECTION_UP
return 0
end
#Basic pathfinding to move an event towards a certain general direction while avoiding obstacles
def pathFindingGetDirection(current_x,current_y,goal_direction,pathfindingRange=4)
goal_direction_is_horizontal = goal_direction == DIRECTION_RIGHT || goal_direction == DIRECTION_LEFT
direction_forward_x = get_direction_forward_x(goal_direction)
direction_forward_y = get_direction_forward_y(goal_direction)
#echoln "Goal direction :#{goal_direction}. ForwardX: #{direction_forward_x}. ForwardY: #{direction_forward_y}"
if(eventCanPassThrough(current_x+direction_forward_x,current_y+direction_forward_y,goal_direction))
return goal_direction
else
if goal_direction_is_horizontal
alternate_direction_x=direction_forward_x
alternate_direction_y=1
else
alternate_direction_x=1
alternate_direction_y=direction_forward_y
end
echoln "########### CURRENT_POSITION: #{current_x},#{current_y}"
direction_polarities = [1,-1]
for i in 1..pathfindingRange
for polarity in direction_polarities
new_x = goal_direction_is_horizontal ? current_x+ direction_forward_x : current_x+((i*alternate_direction_x)*polarity)
new_y = !goal_direction_is_horizontal ? current_y + direction_forward_y : current_y+((i*alternate_direction_y)*polarity)
echoln "Checking for #{new_x}, #{new_y}"
if eventCanPassThrough(new_x,new_y,goal_direction)
if goal_direction_is_horizontal
new_direction = getDirection(0,(i*alternate_direction_y)*polarity)
echoln "found a gap! new direction x: #{0}, new direction y: #{(i*alternate_direction_y)*polarity}"
if eventCanPassThrough(current_x,current_y+polarity,goal_direction)
return new_direction
else
echoln "...but cannot go in that direction (#{current_x},#{current_y+new_direction} blocked)"
end
else
new_direction = getDirection((i*alternate_direction_x)*polarity,0)
if eventCanPassThrough(current_x+polarity,current_y,goal_direction)
return new_direction
else
echoln "...but cannot go in that direction"
end
end
end
end
end
end
return 0
end
def eventCanPassThrough(x, y, direction)
if x == $game_player.x && y == $game_player.y
echoln "cannot pass because of player"
return false
end
$PokemonTemp.dependentEvents.realEvents.each { |dependantEvent|
if x == dependantEvent.x && y == dependantEvent.y
echoln "cannot pass because of dependant event #{dependantEvent.name}(#{dependantEvent.x},#{dependantEvent.y})"
return false
end
}
return $game_player.passable?(x, y, direction)
end

View File

@@ -0,0 +1,92 @@
class PokedexUtils
# POSSIBLE_ALTS = ["", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
# "r", "s", "t", "u", "v", "w", "x", "y", "z", "aa", "ab", "ac", "ad", "ae", "af", "ag", "ah",
# "ai", "aj", "ak", "al", "am", "an", "ao", "ap", "aq", "ar", "as", "at", "au", "av", "aw", "ax",
# "ay", "az"]
def getAltLettersList()
return ('a'..'z').to_a + ('aa'..'az').to_a
end
def getBaseSpritesAlts(dex_number)
return $game_temp.base_sprites_list[dex_number]
end
def getFusionSpriteAlts(head_id, body_id)
sprite_id = get_fusion_symbol(head_id,body_id)
return $game_temp.custom_sprites_list[sprite_id]
# available_alts = []
# species_id = get_fusion_id(head_id,body_id).to_s
# for pokemon_id in $game_temp.custom_sprites_list
# available_alts << pokemon_id if pokemon_id.to_s.start_with?(species_id)
# end
# echoln available_alts
# return available_alts
end
def pbGetAvailableAlts(species, includeAutogens=false)
dex_number = getDexNumberForSpecies(species)
if isFusion(dex_number)
body_id = getBodyID(dex_number)
head_id = getHeadID(dex_number,body_id)
available_alts = getFusionSpriteAlts(head_id,body_id)
else
available_alts= getBaseSpritesAlts(dex_number)
end
available_alts = [] if !available_alts
available_alts << "autogen" if includeAutogens
return available_alts
# ret = []
# return ret if !species
# dexNum = getDexNumberForSpecies(species)
# isFusion = dexNum > NB_POKEMON
# if !isFusion
# altLetters = getAltLettersList()
# altLetters << ""
# altLetters.each { |alt_letter|
# altFilePath = Settings::CUSTOM_BASE_SPRITES_FOLDER + dexNum.to_s + alt_letter + ".png"
# if pbResolveBitmap(altFilePath)
# ret << altFilePath
# end
# }
# return ret
# end
# body_id = getBodyID(species)
# head_id = getHeadID(species, body_id)
#
# baseFilename = head_id.to_s + "." + body_id.to_s
# baseFilePath = Settings::CUSTOM_BATTLERS_FOLDER_INDEXED + head_id.to_s + "/" + baseFilename + ".png"
# if pbResolveBitmap(baseFilePath)
# ret << baseFilePath
# end
# getAltLettersList().each { |alt_letter|
# if alt_letter != "" #empty is included in alt letters because unfused sprites can be alts and not have a letter
# altFilePath = Settings::CUSTOM_BATTLERS_FOLDER_INDEXED + head_id.to_s + "/" + baseFilename + alt_letter + ".png"
# if pbResolveBitmap(altFilePath)
# ret << altFilePath
# end
# end
# }
# ret << Settings::BATTLERS_FOLDER + head_id.to_s + "/" + baseFilename + ".png"
# return ret
end
#todo: return array for split evolution lines that have multiple final evos
def getFinalEvolution(species)
#ex: [[B3H4,Level 32],[B2H5, Level 35]]
evolution_line = species.get_evolutions
return species if evolution_line.empty?
finalEvoId = evolution_line[0][0]
return evolution_line[]
for evolution in evolution_line
evoSpecies = evolution[0]
p GameData::Species.get(evoSpecies).get_evolutions
isFinalEvo = GameData::Species.get(evoSpecies).get_evolutions.empty?
return evoSpecies if isFinalEvo
end
return nil
end
end

View File

@@ -0,0 +1,137 @@
#===============================================================================
# * Pokémon Selection - by FL (Credits will be apreciated)
#===============================================================================
#
# This script is for Pokémon Essentials. It makes a pokémon selection system
# similar to Stadium/Battle Tower, where you can choose a certain number and
# order of pokémon.
#
#===============================================================================
#
# To this script works, put it above main and use in script command
# 'PokemonSelection.choose(min, max, canCancel, acceptFainted)' where min and
# max are the minimum and maximum pokémon number selection (default values are
# 1 and 6), canCancel when true the player can cancel the selection (default
# is false) and acceptFainted that when true the player can choose fainted
# pokémon and eggs (default is false). This method return if a party is choosen.
#
# To restore the previous party, use 'PokemonSelection.restore'. This do nothing
# is there's no party to restore. Ths method returns if the party is restored.
#
# Between the two commands, don't allow the player to caught or deposit/withdraw
# any pokémon or the pokémon will be lost! However, you pokémon can gain
# exp/level, evolve, change hold item/moves normally. If you try to choose a
# new party before restore the old one, the game raises an error. This won't
# occurs if the previous selection is only an order change. ONLY in Debug mode
# you get the phrase "Generate Pokemon teams for this challenge?", always
# choose "No".
#
# 'PokemonSelection.hasValidTeam?(min, max, canCancel, acceptFainted)' returns
# if your team is valid. If you try to use a invalid team (like putting the
# minimum pokémon number as 3, but only having 2 pokémon), the selection is
# treats as canceled. If the canCancel=false, the game goes in an infinite loop.
#
# Example: To make a 3vs3 battle, use 'PokemonSelection.choose(3,3)' and, after
# the battle (regardless of result) use 'PokemonSelection.restore'. Only allows
# the player to go in the battle if 'PokemonSelection.hasValidTeam?(3,3)' is
# true, or set the minimum as 1.
#
# To perform only an order change, use
# 'PokemonSelection.choose($Trainer,party.size,$Trainer,party.size,true,true)'.
#
# If you take a look in PokemonChallengeRules applications in scripts you can
# customize some others choice conditions like have a certain level or ban
# certain pokémon.
#
#===============================================================================
module PokemonSelection
def self.rules(min=1, max=6, canCancel=false, acceptFainted=false)
ret=PokemonChallengeRules.new
# ret.setLevelAdjustment(OpenLevelAdjustment.new(PBExperience::MAXLEVEL))
ret.addPokemonRule(AblePokemonRestriction.new) if !acceptFainted
ret.ruleset.setNumberRange(min,max)
return ret
end
def self.hasValidTeam?(min=1, max=6, canCancel=false, acceptFainted=false)
pbBattleChallenge.set("pokemonSelectionRules",7,self.rules(min,max))
ret=pbHasEligible?
pbBattleChallenge.pbCancel
return ret
end
def self.choose(min=1, max=6, canCancel=false, acceptFainted=false, ableproc=nil)
if $PokemonGlobal.pokemonSelectionOriginalParty
PokemonSelection.restore
echoln "Can't choose a new party until restore the old one"
end
validPartyChosen=false
pbBattleChallenge.set("pokemonSelectionRules",7,self.rules(min,max))
loop do
pbEntryScreen(ableproc)
validPartyChosen=(pbBattleChallenge.getParty!=nil)
break if(canCancel || validPartyChosen)
Kernel.pbMessage(_INTL("Choose a Pokémon."))
end
if validPartyChosen
# If the party size is the same, it is only an order change
if($Trainer.party.size != pbBattleChallenge.getParty.size)
$PokemonGlobal.pokemonSelectionOriginalParty=$Trainer.party
end
$Trainer.party=pbBattleChallenge.getParty
end
pbBattleChallenge.pbCancel
return validPartyChosen
end
def self.saveParty()
$PokemonGlobal.pokemonSelectionOriginalParty=$Trainer.party
end
def self.restore(*args)
hasSavedTeam=($PokemonGlobal.pokemonSelectionOriginalParty!=nil)
if hasSavedTeam
$Trainer.party=$PokemonGlobal.pokemonSelectionOriginalParty
$PokemonGlobal.pokemonSelectionOriginalParty=nil
end
return hasSavedTeam
end
end
class PokemonRuleSet # Redefined to fix a bug
def hasValidTeam?(team)
if !team || team.length<self.minTeamLength
return false
end
teamNumber=[self.maxLength,team.length].min
validPokemon=[]
for pokemon in team
if isPokemonValid?(pokemon)
validPokemon.push(pokemon)
end
end
#if validPokemon.length<teamNumber # original
if validPokemon.length<self.minLength # fixed
return false
end
if @teamRules.length>0
pbEachCombination(team,teamNumber){|comb|
if isValid?(comb)
return true
end
}
return false
end
return true
end
end
class BattleChallenge; def getParty; return @bc.party; end; end
class PokemonGlobalMetadata
attr_accessor :pokemonSelectionOriginalParty
attr_accessor :pokemonSelectionOriginalBag
end

View File

@@ -0,0 +1,8 @@
def getBlackMarketOriginalTrainer
randomTrainer = GameData::Trainer.list_all.values.sample
return randomTrainer
# trainer = NPCTrainer.new("", randomTrainer.id)
# return trainer
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
#Eevee quest
Events.onStepTaken+=proc {|sender,e|
next if !$game_switches[173]
next if !$game_switches[179] #If not outside of building
$game_variables[102]+=1
if $game_variables[102] % 100 == 0 then
$game_variables[101]+=1
end
if $game_variables[102] >= 400 then
if $game_variables[102] % 100 == 0 then
Kernel.pbMessage(_INTL("Eevee is getting tired. You should head back soon!"))
cry=pbResolveAudioSE(pbCryFile(133))
pbSEPlay(cry,100,100)
end
end
}

View File

@@ -0,0 +1,422 @@
SHINY_COLOR_OFFSETS = {
1 => -30,
2 => -85,
3 => -50,
4 => 40,
5 => 60,
6 => 130,
7 => 25,
8 => 15,
9 => 50,
10 => -50,
11 => -80,
12 => 95,
#13 => -1,
#14 => -1,
#15 => -1,
#16 => -1,
#17 => -1,
#18 => -1,
#19 => -1,
#20 => -1,
#21 => -1,
#22 => -1,
#23 => -1,
#24 => -1,
#25 => -1,
#26 => -1,
#27 => -1,
#28 => -1,
#29 => -1,
#30 => -1,
#31 => -1,
#32 => -1,
#33 => -1,
#34 => -1,
#35 => -1,
#36 => -1,
#37 => -1,
#38 => -1,
#39 => -1,
#40 => -1,
#41 => -1,
#42 => -1,
#43 => -1,
#44 => -1,
#45 => -1,
#46 => -1,
#47 => -1,
#48 => -1,
#49 => -1,
#50 => -1,
#51 => -1,
#52 => -1,
#53 => -1,
#54 => -1,
#55 => -1,
#56 => -1,
#57 => -1,
#58 => -1,
#59 => -1,
#60 => -1,
#61 => -1,
#62 => -1,
#63 => -1,
#64 => -1,
#65 => -1,
#66 => -1,
#67 => -1,
#68 => -1,
#69 => -1,
#70 => -1,
#71 => -1,
#72 => -1,
#73 => -1,
#74 => -1,
#75 => -1,
#76 => -1,
#77 => -1,
#78 => -1,
#79 => -1,
#80 => -1,
#81 => -1,
#82 => -1,
#83 => -1,
#84 => -1,
#85 => -1,
#86 => -1,
#87 => -1,
#88 => -1,
#89 => -1,
#90 => -1,
#91 => -1,
#92 => -1,
#93 => -1,
#94 => -1,
#95 => -1,
#96 => -1,
#97 => -1,
#98 => -1,
#99 => -1,
#100 => -1,
#101 => -1,
#102 => -1,
#103 => -1,
#104 => -1,
#105 => -1,
#106 => -1,
#107 => -1,
#108 => -1,
#109 => -1,
#110 => -1,
#111 => -1,
#112 => -1,
#113 => -1,
#114 => -1,
#115 => -1,
#116 => -1,
#117 => -1,
#118 => -1,
#119 => -1,
#120 => -1,
#121 => -1,
#122 => -1,
#123 => -1,
#124 => -1,
#125 => -1,
#126 => -1,
#127 => -1,
#128 => -1,
129 => 36,
130 => 150,
#131 => -1,
#132 => -1,
#133 => -1,
#134 => -1,
#135 => -1,
#136 => -1,
#137 => -1,
#138 => -1,
#139 => -1,
#140 => -1,
#141 => -1,
#142 => -1,
#143 => -1,
#144 => -1,
#145 => -1,
#146 => -1,
#147 => -1,
#148 => -1,
#149 => -1,
#150 => -1,
#151 => -1,
#152 => -1,
#153 => -1,
#154 => -1,
#155 => -1,
#156 => -1,
#157 => -1,
#158 => -1,
#159 => -1,
#160 => -1,
#161 => -1,
#162 => -1,
#163 => -1,
#164 => -1,
#165 => -1,
#166 => -1,
#167 => -1,
#168 => -1,
#169 => -1,
#170 => -1,
#171 => -1,
#172 => -1,
#173 => -1,
#174 => -1,
#175 => -1,
#176 => -1,
#177 => -1,
#178 => -1,
#179 => -1,
#180 => -1,
#181 => -1,
#182 => -1,
#183 => -1,
#184 => -1,
#185 => -1,
#186 => -1,
#187 => -1,
#188 => -1,
#189 => -1,
#190 => -1,
#191 => -1,
#192 => -1,
#193 => -1,
#194 => -1,
#195 => -1,
#196 => -1,
#197 => -1,
#198 => -1,
#199 => -1,
#200 => -1,
#201 => -1,
#202 => -1,
#203 => -1,
#204 => -1,
#205 => -1,
#206 => -1,
#207 => -1,
#208 => -1,
#209 => -1,
#210 => -1,
#211 => -1,
#212 => -1,
#213 => -1,
#214 => -1,
#215 => -1,
#216 => -1,
#217 => -1,
#218 => -1,
#219 => -1,
#220 => -1,
#221 => -1,
#222 => -1,
#223 => -1,
#224 => -1,
#225 => -1,
#226 => -1,
#227 => -1,
#228 => -1,
#229 => -1,
#230 => -1,
#231 => -1,
#232 => -1,
#233 => -1,
#234 => -1,
#235 => -1,
#236 => -1,
#237 => -1,
#238 => -1,
#239 => -1,
#240 => -1,
#241 => -1,
#242 => -1,
#243 => -1,
#244 => -1,
#245 => -1,
#246 => -1,
#247 => -1,
#248 => -1,
#249 => -1,
#250 => -1,
#251 => -1,
#252 => -1,
#253 => -1,
#254 => -1,
#255 => -1,
#256 => -1,
#257 => -1,
#258 => -1,
#259 => -1,
#260 => -1,
#261 => -1,
#262 => -1,
#263 => -1,
#264 => -1,
#265 => -1,
#266 => -1,
#267 => -1,
#268 => -1,
#269 => -1,
#270 => -1,
#271 => -1,
#272 => -1,
#273 => -1,
#274 => -1,
#275 => -1,
#276 => -1,
#277 => -1,
#278 => -1,
#279 => -1,
#280 => -1,
#281 => -1,
#282 => -1,
#283 => -1,
#284 => -1,
#285 => -1,
#286 => -1,
#287 => -1,
#288 => -1,
#289 => -1,
#290 => -1,
#291 => -1,
#292 => -1,
#293 => -1,
#294 => -1,
#295 => -1,
#296 => -1,
#297 => -1,
#298 => -1,
#299 => -1,
#300 => -1,
#301 => -1,
#302 => -1,
#303 => -1,
#304 => -1,
#305 => -1,
#306 => -1,
#307 => -1,
#308 => -1,
#309 => -1,
#310 => -1,
#311 => -1,
#312 => -1,
#313 => -1,
#314 => -1,
#315 => -1,
#316 => -1,
#317 => -1,
#318 => -1,
#319 => -1,
#320 => -1,
#321 => -1,
#322 => -1,
#323 => -1,
#324 => -1,
#325 => -1,
#326 => -1,
#327 => -1,
#328 => -1,
#329 => -1,
#330 => -1,
#331 => -1,
332 => 140,
#333 => -1,
#334 => -1,
#335 => -1,
#336 => -1,
#337 => -1,
#338 => -1,
#339 => -1,
#340 => -1,
#341 => -1,
342 => 50,
#343 => -1,
#344 => -1,
#345 => -1,
#346 => -1,
#347 => -1,
#348 => -1,
#349 => -1,
#350 => -1,
#351 => -1,
#352 => -1,
#353 => -1,
#354 => -1,
#355 => -1,
#356 => -1,
#357 => -1,
#358 => -1,
#359 => -1,
#360 => -1,
#361 => -1,
#362 => -1,
#363 => -1,
#364 => -1,
#365 => -1,
#366 => -1,
#367 => -1,
#368 => -1,
#369 => -1,
#370 => -1,
#371 => -1,
#372 => -1,
#373 => -1,
#374 => -1,
#375 => -1,
#376 => -1,
#377 => -1,
#378 => -1,
#379 => -1,
#380 => -1,
#381 => -1,
#382 => -1,
#383 => -1,
#384 => -1,
#385 => -1,
#386 => -1,
#387 => -1,
388 => 160,
389 => 136,
#390 => -1,
#391 => -1,
#392 => -1,
#393 => -1,
#394 => -1,
#395 => -1,
#396 => -1,
#397 => -1,
#398 => -1,
#399 => -1,
#400 => -1,
#401 => -1,
#402 => -1,
#403 => -1,
#404 => -1,
#405 => -1,
#406 => -1,
#407 => -1,
#408 => -1,
#409 => -1,
#410 => -1,
#411 => -1,
#412 => -1,
#413 => -1,
#414 => -1,
#415 => -1,
#416 => -1,
#417 => -1,
#418 => -1,
#419 => -1,
#420 => -1,
}

View File

@@ -0,0 +1,147 @@
class PokemonTemp
def pbClearSilhouetteEvents()
echoln @tempEvents
@tempEvents.keys.each {|map_id|
map = $MapFactory.getMap(map_id,false)
@tempEvents[map_id].each { |event|
#this deletes the event after a small fadeout
$game_self_switches[[map_id, event.id, "B"]] = true if map.events[event.id]
}
}
@tempEvents={}
@silhouetteDirection=nil
end
end
def isNightmareEffect()
return $game_switches[SWITCH_NIGHTMARE_EFFECT] && PBDayNight.isNight?
end
# def playNightmareEffect()
# frame=1
# while true
# frame +=1
# frame = 1 if frame >4
# filename = "nightmare"+frame.to_s
# picture = Game_Picture.new(40)
# picture.show(filename, 0, 0, 0, 200, 200, 255, 0)
# pbWait(3)
# picture.erase
# end
#
# end
Events.onStepTaken += proc { |sender, e|
next if !$PokemonTemp.silhouetteDirection
if $PokemonTemp.silhouetteDirection && $PokemonTemp.silhouetteDirection == $game_player.direction
$PokemonTemp.pbClearSilhouetteEvents
$PokemonTemp.silhouetteDirection = nil
end
}
Events.onStepTaken += proc { |sender, e|
next if !$scene.is_a?(Scene_Map)
next if !isNightmareEffect()
steps_constant_offset = 40
steps_chance=100
minimum_steps=10
steps_nb = rand(steps_chance)+pbGet(VAR_KARMA)+steps_constant_offset
steps_nb = minimum_steps if steps_nb<minimum_steps
next if $PokemonGlobal.stepcount % steps_nb != 0
next if !isOutdoor()
$PokemonTemp.pbClearSilhouetteEvents
spawnSilhouette()
}
Events.onMapChange += proc { |sender, e|
next if $PokemonTemp.tempEvents.empty?
$PokemonTemp.pbClearTempEvents()
}
def getRandomPositionOnPerimeter(width, height, center_x, center_y, variance=0,edge=nil)
half_width = width / 2.0
half_height = height / 2.0
# Randomly select one of the four edges of the rectangle
edge = rand(4) if !edge
case edge
when 0 # Top edge
random_x = center_x + rand(-half_width..half_width)
random_y = center_y - half_height
when 1 # Bottom edge
random_x = center_x + rand(-half_width..half_width)
random_y = center_y + half_height
when 2 # Left edge
random_x = center_x - half_width
random_y = center_y + rand(-half_height..half_height)
when 3 # Right edge
random_x = center_x + half_width
random_y = center_y + rand(-half_height..half_height)
end
return random_x.round, random_y.round
end
# def launchSilhouetteCommonEvent(event)
# $scene.spriteset.addUserAnimation(VIRUS_ANIMATION_ID, event.x, event.y, true)
# $PokemonTemp.pbClearTempEvents
# $PokemonTemp.silhouetteDirection = nil
# pbCommonEvent(COMMON_EVENT_SILHOUETTE)
# end
#
# Faces the same way as player
# Disappears as soon as player takes a step in same direction as event
# -> when talk to it:
# ghost animation
# Message:
# A voice echoed from somewhere...
# [NEXT HINT] (ex: The house in Vermillion City...)
#
def generate_silhouette_event(id)
$game_self_switches[[MAP_TEMPLATE_EVENTS, TEMPLATE_EVENT_SILHOUETTE, "A"]] = false
$game_self_switches[[MAP_TEMPLATE_EVENTS, TEMPLATE_EVENT_SILHOUETTE, "B"]] = false
template_event = $MapFactory.getMap(MAP_TEMPLATE_EVENTS,false).events[TEMPLATE_EVENT_SILHOUETTE]
new_event= template_event.event.dup
new_event.name = "temp_silhouette"
new_event.id = id
return new_event
end
def spawnSilhouette()
found_available_position = false
max_tries = 10
current_try = 0
while !found_available_position
x, y = getRandomPositionOnPerimeter(15, 11, $game_player.x, $game_player.y, 2)
found_available_position = true if $game_map.passable?(x, y, $game_player.direction)
current_try += 1
return if current_try > max_tries
end
key_id = ($game_map.events.keys.max || -1) + 1
rpgEvent = generate_silhouette_event(key_id)
#rpgEvent = RPG::Event.new(x,y)
gameEvent = Game_Event.new($game_map.map_id, rpgEvent, $game_map)
direction = $game_player.direction #[2,4,6,8].sample
gameEvent.direction = direction
$PokemonTemp.silhouetteDirection = direction
$game_map.events[key_id] = gameEvent
gameEvent.moveto(x, y)
#-------------------------------------------------------------------------
#updating the sprites
sprite = Sprite_Character.new(Spriteset_Map.viewport, $game_map.events[key_id])
$scene.spritesets[$game_map.map_id] = Spriteset_Map.new($game_map) if $scene.spritesets[$game_map.map_id] == nil
$scene.spritesets[$game_map.map_id].character_sprites.push(sprite)
#$PokemonTemp.addTempEvent($game_map.map_id, gameEvent)
end

View File

@@ -0,0 +1,217 @@
PluginManager.register({
:name => "Carmaniac's Speech Bubbles",
:version => "1.1",
:credits => ["Carmaniac","Avery","Boonzeet"],
:link => "https://reliccastle.com/resources/461/"
})
#-------------------------------------------------------------------------------
# Carmaniac's Speech Bubbles for v18
# Updated by Avery
#-------------------------------------------------------------------------------
# To use, call pbCallBub(type, eventID)
#
# Where type is either 1 or 2:
# 1 - floating bubble
# 2 - speech bubble with arrow
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Class modifiers
#-------------------------------------------------------------------------------
class PokemonTemp
attr_accessor :speechbubble_bubble
attr_accessor :speechbubble_vp
attr_accessor :speechbubble_arrow
attr_accessor :speechbubble_outofrange
attr_accessor :speechbubble_talking
attr_accessor :speechbubble_alwaysDown
attr_accessor :speechbubble_alwaysUp
end
module MessageConfig
BUBBLETEXTBASE = Color.new(22,22,22)
BUBBLETEXTSHADOW = Color.new(166,160,151)
WindowOpacity = 255
end
#-------------------------------------------------------------------------------
# Function modifiers
#-------------------------------------------------------------------------------
class Window_AdvancedTextPokemon
def text=(value)
if value != nil && value != "" && $PokemonTemp.speechbubble_bubble && $PokemonTemp.speechbubble_bubble > 0
if $PokemonTemp.speechbubble_bubble == 1
$PokemonTemp.speechbubble_bubble = 0
resizeToFit2(value,400,100)
@x = $game_map.events[$PokemonTemp.speechbubble_talking].screen_x
@y = $game_map.events[$PokemonTemp.speechbubble_talking].screen_y - (32 + @height)
if @y>(Graphics.height-@height-2)
@y = (Graphics.height-@height)
elsif @y<2
@y=2
end
if @x>(Graphics.width-@width-2)
@x = ($game_map.events[$PokemonTemp.speechbubble_talking].screen_x-@width)
elsif @x<2
@x=2
end
elsif $PokemonTemp.speechbubble_bubble == 3
@x=$game_player.x+32
@y=$game_player.y+36
else
$PokemonTemp.speechbubble_bubble = 0
end
end
setText(value)
end
end
def pbRepositionMessageWindow(msgwindow, linecount=2)
msgwindow.height=32*linecount+msgwindow.borderY
msgwindow.y=(Graphics.height)-(msgwindow.height)
if $game_temp && $game_temp.in_battle && !$scene.respond_to?("update_basic")
msgwindow.y=0
elsif $game_system && $game_system.respond_to?("message_position")
case $game_system.message_position
when 0 # up
msgwindow.y=0
when 1 # middle
msgwindow.y=(Graphics.height/2)-(msgwindow.height/2)
when 2
if $PokemonTemp.speechbubble_bubble == 1 || $PokemonTemp.speechbubble_bubble == 3
msgwindow.setSkin("Graphics/windowskins/frlgtextskin")
msgwindow.height = 100
msgwindow.width = 400
elsif $PokemonTemp.speechbubble_bubble==2
msgwindow.setSkin("Graphics/windowskins/frlgtextskin")
msgwindow.height = 102
msgwindow.width = Graphics.width
if ($game_player.direction==8 && !$PokemonTemp.speechbubble_alwaysDown) || $PokemonTemp.speechbubble_alwaysUp
$PokemonTemp.speechbubble_vp = Viewport.new(0, 0, Graphics.width, 280)
msgwindow.y = 6
else
$PokemonTemp.speechbubble_vp = Viewport.new(0, 6 + msgwindow.height, Graphics.width, 280)
msgwindow.y = (Graphics.height - msgwindow.height) - 6
if $PokemonTemp.speechbubble_outofrange==true
msgwindow.y = 6
end
end
else
msgwindow.height = 102
msgwindow.y = Graphics.height - msgwindow.height - 6
end
end
end
if $game_system && $game_system.respond_to?("message_frame")
if $game_system.message_frame != 0
msgwindow.opacity = 0
end
end
if $game_message
case $game_message.background
when 1 # dim
msgwindow.opacity=0
when 2 # transparent
msgwindow.opacity=0
end
end
end
def pbCreateMessageWindow(viewport=nil,skin=nil)
arrow = nil
if $PokemonTemp.speechbubble_bubble==2 && $game_map.events[$PokemonTemp.speechbubble_talking] != nil # Message window set to floating bubble.
if ($game_player.direction==8 && !$PokemonTemp.speechbubble_alwaysDown) || $PokemonTemp.speechbubble_alwaysUp# Player facing up, message window top.
$PokemonTemp.speechbubble_vp = Viewport.new(0, 104, Graphics.width, 280)
$PokemonTemp.speechbubble_vp.z = 999999
arrow = Sprite.new($PokemonTemp.speechbubble_vp)
arrow.x = $game_map.events[$PokemonTemp.speechbubble_talking].screen_x - Graphics.width
arrow.y = ($game_map.events[$PokemonTemp.speechbubble_talking].screen_y - Graphics.height) - 136
arrow.z = 999999
arrow.bitmap = RPG::Cache.load_bitmap_path("Graphics/Pictures/Arrow4")
arrow.zoom_x = 2
arrow.zoom_y = 2
if arrow.x<-230
arrow.x = $game_map.events[$PokemonTemp.speechbubble_talking].screen_x
arrow.bitmap = RPG::Cache.load_bitmap_path("Graphics/Pictures/Arrow3")
end
else # Player facing left, down, right, message window bottom.
$PokemonTemp.speechbubble_vp = Viewport.new(0, 0, Graphics.width, 280)
$PokemonTemp.speechbubble_vp.z = 999999
arrow = Sprite.new($PokemonTemp.speechbubble_vp)
arrow.x = $game_map.events[$PokemonTemp.speechbubble_talking].screen_x
arrow.y = $game_map.events[$PokemonTemp.speechbubble_talking].screen_y
arrow.z = 999999
arrow.bitmap = RPG::Cache.load_bitmap_path("Graphics/Pictures/Arrow1")
if arrow.y>=Graphics.height-120 # Change arrow direction.
$PokemonTemp.speechbubble_outofrange=true
$PokemonTemp.speechbubble_vp.rect.y+=104
arrow.x = $game_map.events[$PokemonTemp.speechbubble_talking].screen_x - Graphics.width
arrow.bitmap = RPG::Cache.load_bitmap_path("Graphics/Pictures/Arrow4")
arrow.y = ($game_map.events[$PokemonTemp.speechbubble_talking].screen_y - Graphics.height) - 136
if arrow.x<-250
arrow.x = $game_map.events[$PokemonTemp.speechbubble_talking].screen_x
arrow.bitmap = RPG::Cache.load_bitmap_path("Graphics/Pictures/Arrow3")
end
if arrow.x>=256
arrow.x-=15# = $game_map.events[$PokemonTemp.speechbubble_talking].screen_x-Graphics.width
arrow.bitmap = RPG::Cache.load_bitmap_path("Graphics/Pictures/Arrow3")
end
else
$PokemonTemp.speechbubble_outofrange=false
end
arrow.zoom_x = 2
arrow.zoom_y = 2
end
end
$PokemonTemp.speechbubble_arrow = arrow
msgwindow=Window_AdvancedTextPokemon.new("")
if !viewport
msgwindow.z=99999
else
msgwindow.viewport=viewport
end
msgwindow.visible=true
msgwindow.letterbyletter=true
msgwindow.back_opacity=MessageConfig::WindowOpacity
pbBottomLeftLines(msgwindow,2)
$game_temp.message_window_showing=true if $game_temp
$game_message.visible=true if $game_message
skin=MessageConfig.pbGetSpeechFrame() if !skin
msgwindow.setSkin(skin)
return msgwindow
end
def pbDisposeMessageWindow(msgwindow)
$game_temp.message_window_showing=false if $game_temp
$game_message.visible=false if $game_message
msgwindow.dispose
$PokemonTemp.speechbubble_arrow.dispose if $PokemonTemp.speechbubble_arrow
$PokemonTemp.speechbubble_vp.dispose if $PokemonTemp.speechbubble_vp
$PokemonTemp.speechbubble_bubble=nil
end
def pbCallBubUp(status=0,value=0)
pbCallBub(status,value,false,true)
end
def pbCallBubDown(status=0,value=0)
pbCallBub(status,value,true,false)
end
#always_down, always_up is not ideal but used everywhere in game so too late to change
def pbCallBub(status=0,value=0,always_down=false, always_up=false)
begin
$PokemonTemp.speechbubble_talking=get_character(value).id
$PokemonTemp.speechbubble_bubble=status
$PokemonTemp.speechbubble_alwaysDown=always_down
$PokemonTemp.speechbubble_alwaysUp=always_up
rescue
return #Let's not crash the game if error
end
end

View File

@@ -0,0 +1,71 @@
#==============================================================================#
# Better Fast-forward Mode #
# v1.0 #
# #
# by Marin #
#==============================================================================#
# Usage #
# #
# SPEEDUP_STAGES are the speed stages the game will pick from. If you click F, #
# it'll choose the next number in that array. It goes back to the first number #
# afterward. #
# #
# $GameSpeed is the current index in the speed up array. #
# Should you want to change that manually, you can do, say, $GameSpeed = 0 #
# #
# If you don't want the user to be able to speed up at certain points, you can #
# use "pbDisallowSpeedup" and "pbAllowSpeedup". #
#==============================================================================#
# Please give credit when using this. #
#==============================================================================#
PluginManager.register({
:name => "Better Fast-forward Mode",
:version => "1.1",
:credits => "Marin",
:link => "https://reliccastle.com/resources/151/"
})
# When the user clicks F, it'll pick the next number in this array.
SPEEDUP_STAGES = [1,2,3]
def pbAllowSpeedup
$CanToggle = true
end
def pbDisallowSpeedup
$CanToggle = false
end
# Default game speed.
$GameSpeed = 0
$frame = 0
$CanToggle = true
module Graphics
class << Graphics
alias fast_forward_update update
end
def self.update
if $CanToggle && Input.trigger?(Input::AUX1)
$GameSpeed += 1
$GameSpeed = 0 if $GameSpeed >= SPEEDUP_STAGES.size
end
$frame += 1
if $PokemonSystem && $PokemonSystem.speedup == 1
speedStage = SPEEDUP_STAGES[$GameSpeed]
else
speedStage = 1
if Input.press?(Input::AUX1) && $CanToggle
$PokemonSystem.speedup_speed = Settings::DEFAULT_SPEED_UP_SPEED if !$PokemonSystem.speedup_speed || $PokemonSystem.speedup_speed==0
speedStage=$PokemonSystem.speedup_speed+1
end
end
return unless $frame % speedStage == 0
fast_forward_update
$frame = 0
end
end

View File

@@ -0,0 +1,493 @@
def map_sprites_by_artist
creditsMap = Hash.new
File.foreach(Settings::CREDITS_FILE_PATH) do |line|
row = line.split(',')
spritename = row[0]
if row[1]
artist = row[1].chomp
sprites = creditsMap.key?(artist) ? creditsMap[artist] : []
sprites << spritename
creditsMap[artist] = sprites
end
end
return creditsMap
end
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]
name_counts[name] += 1
end
name_counts.sort_by { |name, count| -count }.to_h
.first(nb_names)
.to_h
end
def analyzeSpritesList(spritesList, mostPopularCallbackVariable = 1)
pokemon_map = Hash.new
for spritename in spritesList
splitName = spritename.split(".")
headNum = splitName[0].to_i
bodyNum = splitName[1].to_i
if pokemon_map.key?(headNum)
pokemon_map[headNum] += 1
else
pokemon_map[headNum] = 1
end
if pokemon_map.key?(bodyNum)
pokemon_map[bodyNum] += 1
else
pokemon_map[bodyNum] = 1
end
end
most_popular = pokemon_map.max_by { |key, value| value }
most_popular_poke = most_popular[0]
most_popular_nb = most_popular[1]
pbSet(mostPopularCallbackVariable, most_popular_nb)
species = getSpecies(most_popular_poke)
return species
end
def getPokemonSpeciesFromPifSprite(pif_sprite)
if pif_sprite.type == :BASE
return getSpecies(pif_sprite.head_id)
else
return getFusionSpecies(pif_sprite.body_id, pif_sprite.head_id)
end
end
# def getPokemonSpeciesFromSprite(spritename)
# return nil if !spritename
# spritename.gsub('.png', '')
# splitName = spritename.split(".")
# headNum = splitName[0].to_i
# bodyNum = splitName[1].to_i
#
# #call this to make sure that the sprite is downloaded
# get_fusion_sprite_path(headNum, bodyNum)
#
# species = getFusionSpecies(bodyNum, headNum)
# return species
# end
def doesCurrentExhibitionFeaturePokemon(displayedSprites, pokemon)
for sprite in displayedSprites
headNum = sprite.head_id
bodyNum = sprite.body_id
return true if headNum == pokemon.id_number || bodyNum == pokemon.id_number
end
return false
end
def select_spriter(minNbSprites = 10, save_in_var = 1)
spriters_list = list_all_spriters_with_min_nb_of_sprites(minNbSprites)
commands = []
spriters_list.each do |name, i|
if name
commands.push([i, name, name])
end
end
chosen = pbChooseList(commands, 0, nil, 1)
return nil if !chosen
return chosen
end
def list_all_spriters_with_min_nb_of_sprites(minNbSprites)
return list_all_spriters() if !minNbSprites
filename = Settings::CREDITS_FILE_PATH
spriters_hash = Hash.new(0)
File.readlines(filename).each do |line|
name = line.strip.split(',')[1]
if name
spriters_hash[name] += 1
end
end
spriters_list = []
for spriter_name in spriters_hash.keys
if spriters_hash[spriter_name] >= minNbSprites
spriters_list << spriter_name
end
end
return spriters_list
end
def list_all_spriters()
filename = Settings::CREDITS_FILE_PATH
names_list = []
File.readlines(filename).each do |line|
name = line.strip.split(',')[1]
if !names_list.include?(name)
names_list << name
end
end
return names_list
end
def generateCurrentGalleryBattle(level = nil, number_of_pokemon = 3)
spriter_name = pbGet(259)
#set highest level in party if nil
if !level
level = $Trainer.highest_level_pokemon_in_party
end
possible_battlers = []
for i in 0..5
pif_sprite = pbGet(VAR_GALLERY_FEATURED_SPRITES)[i]
species = getPokemonSpeciesFromPifSprite(pif_sprite)
possible_battlers << species if species
end
selected_battlers_idx = possible_battlers.sample(number_of_pokemon)
party = []
selected_battlers_idx.each { |species| 00
party << Pokemon.new(species, level)
}
customTrainerBattle(spriter_name,
:PAINTER,
party,
level,
pick_spriter_losing_dialog(spriter_name),
pick_trainer_sprite(spriter_name)
)
end
def generateArtGallery(nbSpritesDisplayed = 6, saveArtistNameInVariable = 1, saveSpritesInVariable = 2, saveAllArtistSpritesInVariable = 3, artistName = nil)
artistName = nil if artistName == 0
creditsMap = map_sprites_by_artist
select_daily_team_flags()
featuredArtist = artistName ? artistName : getRandomSpriteArtist(creditsMap, nbSpritesDisplayed)
if featuredArtist
if !creditsMap[featuredArtist] #try again if issue
artistName = getRandomSpriteArtist(creditsMap, nbSpritesDisplayed)
return generateArtGallery(nbSpritesDisplayed, saveSpritesInVariable, saveSpritesInVariable, saveSpritesInVariable, artistName)
end
featuredSprites_files = creditsMap[featuredArtist].shuffle.take(nbSpritesDisplayed)
echoln featuredSprites_files
featuredSprites = []
for sprite_name in featuredSprites_files
featuredSprites << pif_sprite_from_spritename(sprite_name)
end
echoln featuredSprites
pbSet(saveArtistNameInVariable, File.basename(featuredArtist, '#*'))
pbSet(saveSpritesInVariable, featuredSprites)
pbSet(saveAllArtistSpritesInVariable, creditsMap[featuredArtist])
return featuredSprites
end
return nil
end
FLAGS_PATH = "Graphics/Pictures/Trainer Card/backgrounds/flags/"
def select_daily_team_flags()
eligible_flags = []
all_flags = Dir.entries(FLAGS_PATH)
.select { |file| file.end_with?('_FLAG.png') }
.map { |file| file.sub('_FLAG.png', '') }
for flag in all_flags
if GameData::Species.get(flag.to_sym)
eligible_flags << flag
end
end
selectedFlags = eligible_flags.sample(4)
echoln selectedFlags
pbSet(VAR_GALLERY_TEAM_FLAGS, selectedFlags)
end
def displayTeamFlag(frame)
selected_flags = pbGet(VAR_GALLERY_TEAM_FLAGS)
flag_image_id = 10
frame_image_id = 9
flag = selected_flags[frame]
species = GameData::Species.get(flag.to_sym)
flag_path = "Trainer Card/backgrounds/flags/#{flag}_FLAG"
x_position = 150
y_position = 50
$game_screen.pictures[flag_image_id].show(flag_path, 0, x_position, y_position, 50, 50)
$game_screen.pictures[frame_image_id].show("teamFlagFrame", 0, x_position, y_position, 50, 50)
name = species.real_name
pbMessage("\"Team #{name} Flag\"")
display_team_flag_statistics(species)
# species_sprites = list_all_sprite_credits_for_pokemon(species)
# unique_sprites = species_sprites.reject { |sprite_name, _| sprite_name.match(/[a-zA-Z]$/) }
# percent = (unique_sprites.keys.length.to_f / (NB_POKEMON * 2)) * 100
# pbMessage("Team #{name} completion: \\C[1]#{sprintf('%.2f', percent)}%")
#
# top_contributors = get_top_contributors_for_pokemon(species_sprites, 5)
# echoln top_contributors
#
#
# contributors_string = ""
# top_contributors.keys.each_with_index do |spriter, index|
# contributors_string += "\\C[1]#{spriter}\\C[0]"
# contributors_string += " (#{top_contributors[spriter]} sprites)"
# contributors_string += "<br>" unless index == top_contributors.length - 1
# end
# pbMessage("Top contributors:<br>#{contributors_string}")
flag_id = "flags/#{species.id.to_s}_FLAG"
flag_name = "Team #{species.real_name}"
prompt_flag_purchase(flag_id, flag_name, 5000)
$game_screen.pictures[flag_image_id].erase
$game_screen.pictures[frame_image_id].erase
end
def display_specific_pokemon_statistics()
species_id = select_any_pokemon()
species = GameData::Species.get(species_id)
species_sprites = list_all_sprite_credits_for_pokemon(species)
unique_sprites = filter_unique_sprites_nb_for_pokemon(species_sprites)
percent = (unique_sprites.length.to_f / (NB_POKEMON * 2)) * 100
pbMessage "#{species.real_name} completion: \\C[1]#{sprintf('%.2f', percent)}%\\C[0]"
contributors_string = ""
top_contributors = get_top_contributors_for_pokemon(species_sprites, 5)
top_contributors.keys.each_with_index do |spriter, index|
contributors_string += "\\C[1]#{spriter}\\C[0]"
contributors_string += " (#{top_contributors[spriter]} sprites)"
contributors_string += "<br>" unless index == top_contributors.length - 1
end
pbMessage("#{species.real_name} top contributors:<br>#{contributors_string}")
end
def display_team_flag_statistics(species)
evolution_line = species.get_related_species
flag_pokemon_name = species.name
echoln evolution_line
if evolution_line.length > 1
pbMessage("This flag stands as a tribute to the artists who have devoted their talents to portraying \\C[1]#{flag_pokemon_name}\\C[0] and its evolution line in all its forms.")
else
pbMessage("This flag stands as a tribute to the artists who have devoted their talents to portraying \\C[1]#{flag_pokemon_name}\\C[0] in all its forms.")
end
all_sprites = []
family_unique_sprites_nb = []
for pokemon_id in evolution_line
species = GameData::Species.get(pokemon_id)
species_sprites = list_all_sprite_credits_for_pokemon(species)
unique_sprites = filter_unique_sprites_nb_for_pokemon(species_sprites)
all_sprites << species_sprites
unique_sprites_nb = unique_sprites.length.to_f
family_unique_sprites_nb << unique_sprites_nb
percent = (unique_sprites.length.to_f / (NB_POKEMON * 2)) * 100
pbMessage "#{species.real_name} completion: \\C[1]#{sprintf('%.2f', percent)}%\\C[0]" if evolution_line.length > 1
end
overall_total = 0
family_unique_sprites_nb.each { |nb|
overall_total += nb
}
overall_percent = (overall_total / ((NB_POKEMON * 2)*family_unique_sprites_nb.length))*100
pbMessage "Team #{flag_pokemon_name} overall completion: \\C[3]#{sprintf('%.2f', overall_percent)}%\\C[0]"
family_line_sprites = {}
for pokemon_sprites in all_sprites
family_line_sprites = family_line_sprites.merge(pokemon_sprites)
end
contributors_string = ""
top_contributors = get_top_contributors_for_pokemon(family_line_sprites, 5)
top_contributors.keys.each_with_index do |spriter, index|
contributors_string += "\\C[1]#{spriter}\\C[0]"
contributors_string += " (#{top_contributors[spriter]} sprites)"
contributors_string += "<br>" unless index == top_contributors.length - 1
end
pbMessage("Team #{flag_pokemon_name} top contributors:<br>#{contributors_string}")
end
def filter_unique_sprites_nb_for_pokemon(species_sprites)
unique_sprites = species_sprites.reject { |sprite_name, _| sprite_name.match(/[a-zA-Z]$/) }
return unique_sprites
end
def display_special_banner()
flag_id = "500000"
flag_name = "Team 500,000"
price = 10000
banner_title = "Half-million Milestone Banner"
flag_path = "Trainer Card/backgrounds/#{flag_id}"
flag_image_id = 10
frame_image_id = 9
x_position = 150
y_position = 50
$game_screen.pictures[flag_image_id].show(flag_path, 0, x_position, y_position, 50, 50)
$game_screen.pictures[frame_image_id].show("teamFlagFrame", 0, x_position, y_position, 50, 50)
pbMessage("\"#{banner_title}\"")
pbMessage("A banner honoring the 500,000 members of the community who have come together to inspire countless others.")
pbWait(10)
percent = get_total_completion_percent()
pbMessage("All Pokémon completion: \\C[1]#{sprintf('%.2f', percent)}%")
prompt_flag_purchase(flag_id, flag_name, price)
$game_screen.pictures[flag_image_id].erase
$game_screen.pictures[frame_image_id].erase
end
def prompt_flag_purchase(flag_id, flag_name, price)
$Trainer.unlocked_card_backgrounds = [] if ! $Trainer.unlocked_card_backgrounds
if !$Trainer.unlocked_card_backgrounds.include?(flag_id) && $Trainer.money >= price
pbWait(20)
if pbConfirmMessage("\\GWould you to purchase the \\C[1]#{flag_name}\\C[0] flag as a background for your \\C[1]Trainer Card\\C[0] for $#{price}?")
pbSEPlay("Mart buy item")
$Trainer.money -= price
unlock_card_background(flag_id)
pbMessage("\\GYou purchased the \\C[1]#{flag_name}\\C[0] Trainer Card background!")
if pbConfirmMessage("Swap your current Trainer Card for the newly purchased one?")
pbSEPlay("GUI trainer card open")
$Trainer.card_background = flag_id
else
pbMessage("You can swap the background at anytime when viewing your Trainer Card.")
end
end
end
end
def get_total_completion_percent()
customSpritesList = $game_temp.custom_sprites_list.keys
total_nb_pokemon = (NB_POKEMON * NB_POKEMON) + NB_POKEMON
sprited_pokemon = customSpritesList.length
return (sprited_pokemon.to_f / total_nb_pokemon) * 100
end
def get_top_contributors_for_pokemon(species_sprites, top_x)
frequency = Hash.new(0)
species_sprites.values.each { |str| frequency[str] += 1 }
frequency.sort_by { |_, count| -count }.first(top_x).to_h
end
def list_all_sprite_credits_for_pokemon(species)
dex_num = species.id_number
sprites = {}
filename = Settings::CREDITS_FILE_PATH
File.readlines(filename).each do |line|
split_line = line.strip.split(',')
sprite = split_line[0]
match = sprite.match(/(\d+)\.(\d+)/)
next unless match # Skip if no match is found
head_id = match[1].to_i
tail_id = match[2].to_i
artist = split_line[1]
sprites[sprite] = artist if head_id == dex_num || tail_id == dex_num
end
return sprites
end
def displayGalleryFrame(frame)
frame_image_id = 10
bg_image_id = 9
pif_sprite = pbGet(VAR_GALLERY_FEATURED_SPRITES)[frame]
if !pif_sprite.is_a?(PIFSprite)
pbMessage("The frame is empty...")
return
end
species = getPokemonSpeciesFromPifSprite(pif_sprite)
$game_screen.pictures[frame_image_id].show("pictureFrame_bg", 0, 0, 0)
$game_screen.pictures[bg_image_id].show("pictureFrame", 0, 0, 0)
name = species.real_name
author = pbGet(259)
message = "\"#{name}\"\nBy #{author}"
displaySpriteWindowWithMessage(pif_sprite, message, 90, -10, 201)
$game_screen.pictures[frame_image_id].erase
$game_screen.pictures[bg_image_id].erase
end
def format_artist_name(full_name)
return File.basename(full_name, '#*')
end
def getRandomSpriteArtist(creditsMap = nil, minimumNumberOfSprites = 10, giveUpAfterX = 50)
creditsMap = map_sprites_by_artist if !creditsMap
i = 0
while i < giveUpAfterX
artist = creditsMap.keys.sample
return artist if creditsMap[artist].length >= minimumNumberOfSprites
end
return nil
end
def getSpriteCredits(spriteName)
File.foreach(Settings::CREDITS_FILE_PATH) do |line|
row = line.split(',')
if row[0] == (spriteName)
return row[1]
end
end
return nil
end
def formatList(list, separator)
formatted = ""
i = 0
for element in list
formatted << element
formatted << separator if i < list.length
i += 1
end
end
def format_names_for_game_credits()
spriters_map = get_top_artists(100)
formatted = ""
i = 1
for spriter in spriters_map.keys
formatted << spriter
if i % 2 == 0
formatted << "\n"
else
formatted << "<s>"
end
i += 1
end
return formatted
end
def get_spritename_from_path(file_path, includeExtension = false)
filename_with_extension = File.basename(file_path)
filename_without_extension = File.basename(filename_with_extension, ".*")
return filename_with_extension if includeExtension
return filename_without_extension
end
def getSpriterCreditForDexNumber(species_sym)
#download sprite to make sure it's in the substitutions map
body_id = getBodyID(species_sym)
head_id = getHeadID(species_sym, body_id)
spritename = "#{head_id}.#{body_id}"
return getSpriteCredits(spritename)
end
#
# def getSpriterCreditForPokemon(species_sym)
# p species_sym
# #download sprite to make sure it's in the substitutions map
# head_id = get_head_id_from_symbol(species_sym)
# body_id = get_body_id_from_symbol(species_sym)
#
# echoln head_id
# echoln body_id
# spritename = get_fusion_sprite_path(head_id,body_id)
# p spritename
# p getSpriteCredits(spritename)
# return getSpriteCredits(spritename)
# end

View File

@@ -0,0 +1,362 @@
def isWearingTeamRocketOutfit()
return false if !$game_switches[SWITCH_JOINED_TEAM_ROCKET]
return (isWearingClothes(CLOTHES_TEAM_ROCKET_MALE) || isWearingClothes(CLOTHES_TEAM_ROCKET_FEMALE)) && isWearingHat(HAT_TEAM_ROCKET)
end
def obtainRocketOutfit()
Kernel.pbReceiveItem(:ROCKETUNIFORM)
gender = pbGet(VAR_TRAINER_GENDER)
if gender == GENDER_MALE
obtainClothes(CLOTHES_TEAM_ROCKET_MALE)
obtainHat(HAT_TEAM_ROCKET)
$Trainer.unlocked_clothes << CLOTHES_TEAM_ROCKET_FEMALE
else
obtainClothes(CLOTHES_TEAM_ROCKET_FEMALE)
obtainHat(HAT_TEAM_ROCKET)
$Trainer.unlocked_clothes << CLOTHES_TEAM_ROCKET_MALE
end
#$PokemonBag.pbStoreItem(:ROCKETUNIFORM,1)
end
def acceptTRQuest(id, show_description = true)
return if isQuestAlreadyAccepted?(id)
title = TR_QUESTS[id].name
description = TR_QUESTS[id].desc
showNewTRMissionMessage(title, description, show_description)
addRocketQuest(id)
end
def addRocketQuest(id)
echoln $Trainer.quests.length
$Trainer.quests = [] if $Trainer.quests.class == NilClass
quest = TR_QUESTS[id]
$Trainer.quests << quest if quest
echoln $Trainer.quests.length
end
def showNewTRMissionMessage(title, description, show_description)
titleColor = 2
textColor = 2
pbMEPlay("rocketQuest", 80, 110)
pbCallBub(3)
Kernel.pbMessage("\\C[#{titleColor}]NEW MISSION: " + title)
if show_description
pbCallBub(3)
Kernel.pbMessage("\\C[#{textColor}]" + description)
end
end
#status = :SUCCESS, :FAILURE
def finishTRQuest(id, status, silent = false)
return if pbCompletedQuest?(id)
pbMEPlay("Register phone") if status == :SUCCESS && !silent
pbMEPlay("Voltorb Flip Game Over") if status == :FAILURE && !silent
Kernel.pbMessage("\\C[2]Mission completed!") if status == :SUCCESS && !silent
Kernel.pbMessage("\\C[2]Mission Failed...") if status == :FAILURE && !silent
$game_variables[VAR_KARMA] -= 5 # karma
$game_variables[VAR_NB_ROCKET_MISSIONS] += 1 #nb. quests completed
pbSetQuest(id, true)
end
TR_QUESTS = {
"tr_cerulean_1" => Quest.new(0, "Creepy Crawlies", "The Team Rocket Captain has tasked you with clearing the bug infestation in the temporary Rocket HQ in Cerulean City", QuestBranchRocket, "rocket_petrel", "Cerulean City", TRQuestColor),
"tr_cerulean_2" => Quest.new(0, "No Fishing Zone", "Intimidate the fishermen at Nugget Bridge until they leave the area.", QuestBranchRocket, "rocket_petrel", "Cerulean City", TRQuestColor),
"tr_cerulean_3" => Quest.new(0, "Disobedient Pokémon", "Bring back the Pokémon given by the Team Rocket Captain fainted to teach it a lesson.", QuestBranchRocket, "rocket_petrel", "Cerulean City", TRQuestColor),
"tr_cerulean_4" => Quest.new(0, "Gran Theft Pokémon!", "Follow Petrel and go steal a rare Pokémon from a young girl.", QuestBranchRocket, "rocket_petrel", "Cerulean City", TRQuestColor),
"tr_celadon_1" => Quest.new(0, "Supplying the new grunts", "Catch 4 Pokémon with Rocket Balls in the outskirts of Celadon City.", QuestBranchRocket, "rocket_archer", "Celadon City", TRQuestColor),
"tr_celadon_2" => Quest.new(0, "Interception!", "Intercept the TMs shipment to the Celadon Store and pose as the delivery person to deliver fake TMs.", QuestBranchRocket, "rocket_archer", "Celadon City", TRQuestColor),
"tr_celadon_3" => Quest.new(0, "Pokémon Collector", "Go meet a Pokémon collector on Route 22, near Viridian City and get his rare Pokémon.", QuestBranchRocket, "rocket_archer", "Celadon City", TRQuestColor),
"tr_celadon_4" => Quest.new(0, "Operation Shutdown", "The Team Rocket HQ is being raided! Regroup with the rest of the grunts in Goldenrod Tunnel!", QuestBranchRocket, "rocket_archer", "Goldenrod City", TRQuestColor),
"tr_pinkan" => Quest.new(0, "Pinkan Island!", "Help Team Rocket with a heist on a Pokémon nature preserve!", QuestBranchRocket, "rocket_archer", "Goldenrod City", TRQuestColor),
}
def calculateSuspicionLevel(answersSoFar, uncertain_answers)
echoln answersSoFar
believable_answers = [
[:BIRD, :ICE, :CINNABAR, :DAWN], #articuno
[:BIRD, :ELECTRIC, :LAVENDER, :AFTERNOON], #zapdos
[:BIRD, :FIRE, :CINNABAR, :SUNSET], #moltres
[:BEAST, :ELECTRIC, :CERULEAN, :NIGHT], #raikou
[:BEAST, :ELECTRIC, :LAVENDER, :NIGHT], #raikou
[:BEAST, :FIRE, :VIRIDIAN, :NOON], #entei
[:BEAST, :FIRE, :VIRIDIAN, :SUNSET], #entei
[:BEAST, :WATER, :CERULEAN, :DAWN], #suicune
[:BEAST, :WATER, :CERULEAN, :NIGHT], #suicune
[:FISH, :WATER, :CERULEAN, :NIGHT], #suicune
[:FISH, :WATER, :CERULEAN, :DAWN] #suicune
]
min_suspicion_score = Float::INFINITY
# Iterate over each believable answer
believable_answers.each do |believable_answer|
suspicion_score = 0
length_to_check = [answersSoFar.length, believable_answer.length].min
# Compare answersSoFar with believable_answer up to the current length
length_to_check.times do |i|
suspicion_score += 1 unless answersSoFar[i] == believable_answer[i]
end
# Track the minimum suspicion score found
min_suspicion_score = [min_suspicion_score, suspicion_score].min
end
min_suspicion_score += min_suspicion_score if uncertain_answers > 1
echoln "suspicion score: #{min_suspicion_score}"
return min_suspicion_score
end
##### Gameplay stuff
def legendaryQuestioning()
uncertain_answers = 0
answers_so_far = []
#question 1
pbCallBub(2, @event_id)
pbMessage("First off what does the legendary Pokémon look like?")
bodyTypes = { :BIRD => "A flying creature", :BEAST => "A large beast", :FISH => "An aquatic creature", :UNKNOWN => "I don't know..." }
chosen_bodyType = optionsMenu(bodyTypes.values)
answers_so_far << bodyTypes.keys[chosen_bodyType]
if chosen_bodyType == bodyTypes.length - 1
pbCallBub(2, @event_id)
pbMessage("You don't know? Have you even seen that Pokémon?")
pbCallBub(2, @event_id)
pbMessage("Hmm... You better have some more information.")
uncertain_answers += 1
else
pbCallBub(2, @event_id)
pbMessage("#{bodyTypes.values[chosen_bodyType]} that's also a legendary Pokémon? That sounds incredible! You have my attention.")
end
#question 2
pbCallBub(2, @event_id)
pbMessage("Okay... What about its type?")
types = { :ELECTRIC => "Electric-type", :FIRE => "Fire-type", :WATER => "Water-Type", :ICE => "Ice-type", :UNKNOWN => "I don't know..." }
chosen_type = optionsMenu(types.values)
answers_so_far << types.keys[chosen_type]
if chosen_type == types.length - 1
pbCallBub(2, @event_id)
pbMessage("So you don't know its type... Hmm...")
uncertain_answers += 1
else
if chosen_bodyType == bodyTypes.length - 1
pbCallBub(2, @event_id)
pbMessage("Hmm... So it's an unknown creature that's #{types.values[chosen_type]}...")
else
pbCallBub(2, @event_id)
pbMessage("Hmm... #{bodyTypes.values[chosen_bodyType]} that's #{types.values[chosen_type]}.")
end
susMeter = calculateSuspicionLevel(answers_so_far, uncertain_answers)
if susMeter == 0
pbCallBub(2, @event_id)
pbMessage("That sounds pretty exciting!")
else
pbCallBub(2, @event_id)
pbMessage("I've never heard of such a creature, but keep going.")
end
end
#question 3
pbCallBub(2, @event_id)
pbMessage("So... Where was this legendary Pokémon sighted?")
locations = { :VIRIDIAN => "Near Viridian City", :LAVENDER => "Near Lavender Town", :CERULEAN => "Near Cerulean City", :CINNABAR => "Near Cinnabar Island", :UNKNOWN => "I don't know" }
chosen_location = optionsMenu(locations.values)
if chosen_location == locations.length - 1
uncertain_answers += 1
if uncertain_answers == 3
pbCallBub(2, @event_id)
pbMessage("Do you even know anything? This has been such a waste of time!")
return 100
else
pbCallBub(2, @event_id)
pbMessage("How can you not know where it was sighted? Do you know how unhelpful this is to me?")
uncertain_answers += 1
end
else
answers_so_far << locations.keys[chosen_location]
susMeter = calculateSuspicionLevel(answers_so_far, uncertain_answers)
if susMeter == 0
pbCallBub(2, @event_id)
pbMessage("#{locations.values[chosen_location]}, huh? Ah yes, that would make a lot of sense... How did I not think of this before?")
else
pbCallBub(2, @event_id)
pbMessage("Hmmm... #{locations.values[chosen_location]}, really? That sounds pretty surprising to me.")
end
end
#question 4
locations_formatted = { :VIRIDIAN => "Viridian City", :LAVENDER => "Lavender Town", :CERULEAN => "Cerulean City", :CINNABAR => "Cinnabar Island", :UNKNOWN => "that unknown location" }
pbCallBub(2, @event_id)
pbMessage("And at what time of the day was that legendary Pokémon seen near #{locations_formatted.values[chosen_location]} exactly?")
time_of_day = { :DAWN => "At dawn", :NOON => "At noon", :AFTERNOON => "In the afternoon", :SUNSET => "At sunset", :NIGHT => "At night" }
chosen_time = optionsMenu(time_of_day.values)
pbCallBub(2, @event_id)
pbMessage("So it was seen near #{locations_formatted.values[chosen_location]} #{time_of_day.values[chosen_time].downcase}...")
answers_so_far << time_of_day.keys[chosen_time]
return calculateSuspicionLevel(answers_so_far, uncertain_answers)
end
def sellPokemon(event_id)
if $Trainer.party.length <= 1
pbCallBub(2, event_id)
pbMessage("... Wait, I can't take your only Pokémon!")
return false
end
pbChoosePokemon(1, 2,
proc { |poke|
!poke.egg?
})
chosenIndex = pbGet(1)
chosenPokemon = $Trainer.party[chosenIndex]
exotic_pokemon_id = pbGet(VAR_EXOTIC_POKEMON_ID)
if chosenPokemon.personalID == exotic_pokemon_id
pbCallBub(2, event_id)
pbMessage("Oh, this is the Pokémon you got from the collector, right?")
pbCallBub(2, event_id)
pbMessage("Yeah, I can't take that one. The collector blabbed to the police so it's too risky.")
return false
end
speciesName = GameData::Species.get(chosenPokemon.species).real_name
pbCallBub(2, event_id)
if pbConfirmMessageSerious("You wanna sell me this #{speciesName}, is that right?")
pbCallBub(2, event_id)
pbMessage("Hmm... Let's see...")
pbWait(10)
value = calculate_pokemon_value(chosenPokemon)
pbCallBub(2, event_id)
if pbConfirmMessageSerious("\\GI could give you $#{value.to_s} for it. Do we have a deal?")
payout = (value * 0.7).to_i
pbCallBub(2, event_id)
pbMessage("\\GExcellent. And of course, 30% goes to Team Rocket. So you get $#{payout}.")
$Trainer.money += payout
$Trainer.remove_pokemon_at_index(pbGet(1))
pbSEPlay("Mart buy item")
pbCallBub(2, event_id)
pbMessage("\\GPleasure doing business with you.")
return true
else
pbCallBub(2, event_id)
pbMessage("Stop wasting my time!")
end
else
pbCallBub(2, event_id)
pbMessage("Stop wasting my time!")
end
return false
end
def calculate_pokemon_value(pokemon)
# Attribute weights adjusted further for lower-level Pokémon
catch_rate_weight = 0.5
level_weight = 0.2
stats_weight = 0.3
# Constants for the price range
min_price = 100
max_price = 20000
foreign_pokemon_bonus = 3000
fused_bonus = 1000
# Baseline minimum values for scaling
min_catch_rate = 3 # Legendary catch rate
min_level = 1 # Minimum level for a Pokémon
min_base_stats = 180 # Approximate minimum total stats (e.g., Sunkern)
# Attribute maximums
max_catch_rate = 255 # Easy catch rate Pokémon like Magikarp
max_level = 100
max_base_stats = 720 # Maximum base stat total (e.g., Arceus)
# Normalize values based on actual ranges
normalized_catch_rate = (max_catch_rate - pokemon.species_data.catch_rate).to_f / (max_catch_rate - min_catch_rate)
normalized_level = (pokemon.level - min_level).to_f / (max_level - min_level)
normalized_stats = (calcBaseStatsSum(pokemon.species) - min_base_stats).to_f / (max_base_stats - min_base_stats)
# Apply weights to each component
weighted_catch_rate = normalized_catch_rate * catch_rate_weight
weighted_level = normalized_level * level_weight
weighted_stats = normalized_stats * stats_weight
# Calculate the total score and scale to price range with a reduced scaling factor
total_score = weighted_catch_rate + weighted_level + weighted_stats
price = min_price + (total_score * (max_price - min_price) * 0.4) # Lower scaling factor
# Add foreign Pokémon bonus if applicable
is_foreign = !(isKantoPokemon(pokemon.species) || isJohtoPokemon(pokemon.species))
price += foreign_pokemon_bonus if is_foreign
price += fused_bonus if isSpeciesFusion(pokemon.species)
price.to_i # Convert to an integer value
end
def updatePinkanBerryDisplay()
return if !isOnPinkanIsland()
berry_image_width=25
clear_all_images()
pbSEPlay("GUI storage pick up", 80, 100)
nbPinkanBerries = $PokemonBag.pbQuantity(:PINKANBERRY)
for i in 1..nbPinkanBerries
x_pos=i*berry_image_width
y_pos=0
$game_screen.pictures[i].show("pinkanberryui",0,x_pos,y_pos)
end
end
PINKAN_ISLAND_MAP = 51
PINKAN_ISLAND_START_ROCKET = [11,25]
PINKAN_ISLAND_START_POLICE = [20,55]
def pinkanIslandWarpToStart()
$game_temp.player_new_map_id = PINKAN_ISLAND_MAP
if $game_switches[SWITCH_PINKAN_SIDE_ROCKET]
$game_temp.player_new_x = PINKAN_ISLAND_START_ROCKET[0]
$game_temp.player_new_y = PINKAN_ISLAND_START_ROCKET[1]
else
$game_temp.player_new_x = PINKAN_ISLAND_START_POLICE[0]
$game_temp.player_new_y = PINKAN_ISLAND_START_POLICE[1]
end
$scene.transfer_player if $scene.is_a?(Scene_Map)
$game_map.refresh
$game_switches[Settings::STARTING_OVER_SWITCH] = true
$scene.reset_map(true)
end
def isOnPinkanIsland()
return Settings::PINKAN_ISLAND_MAPS.include?($game_map.map_id)
end
def pinkanAddAllCaughtPinkanPokemon()
for pokemon in $Trainer.party
pbStorePokemon(pokemon)
end
end
def resetPinkanIsland()
$game_switches[SWITCH_BLOCK_PINKAN_WHISTLE]=false
$game_switches[SWITCH_LEAVING_PINKAN_ISLAND]=false
$game_switches[SWITCH_PINKAN_SIDE_POLICE]=false
$game_switches[SWITCH_PINKAN_SIDE_ROCKET]=false
for map_id in Settings::PINKAN_ISLAND_MAPS
map = $MapFactory.getMap(map_id,false)
for event in map.events.values
$game_self_switches[[map_id, event.id, "A"]] = false
$game_self_switches[[map_id, event.id, "B"]] = false
$game_self_switches[[map_id, event.id, "C"]] = false
$game_self_switches[[map_id, event.id, "D"]] = false
end
end
end

View File

@@ -0,0 +1,18 @@
def fill_flags_room()
#read info from json,
#
# line ID
# frameType
# image
end
#x_pos, y_pos will be taken from an predefined map
def build_flag_event(flag_id,frame_type,x_pos,y_pos)
rpgEvent = RPG::Event.new(x_pos,y_pos)
gameEvent = Game_Event.new($game_map.map_id, rpgEvent, $game_map)
end

View File

@@ -0,0 +1,34 @@
class PokemonTemp
attr_accessor :tempEvents
attr_accessor :silhouetteDirection
def tempEvents
@tempEvents = {} if !@tempEvents
return @tempEvents
end
def pbClearTempEvents()
@tempEvents.keys.each {|map_id|
map = $MapFactory.getMap(map_id)
@tempEvents[map_id].each { |event|
map.events[event.id].erase if map.events[event.id]
}
}
@tempEvents={}
@silhouetteDirection=nil
end
def addTempEvent(map,event)
@tempEvents = {} if !@tempEvents
mapEvents = @tempEvents.has_key?(map) ? @tempEvents[map] : []
mapEvents.push(event)
@tempEvents[map] = mapEvents
end
end

View File

@@ -0,0 +1,196 @@
#Purchasable from pokemart.
CARD_BACKGROUND_DEFAULT_PURCHASABLE = [
"BLUE",
"PLAIN_BLUE",
"GREEN",
"PLAIN_GREEN",
"RED",
"PURPLE",
"BLACK",
"BRONZE",
"SILVER",
"GOLD",
]
#Purchasable, but not from pokemart.
# a special npc somewhere.
CARD_BACKGROUND_CITY_EXCLUSIVES = {
"GRAYPOLY" => :PEWTER,
"EEVEELUTION" => :CELADON,
"GALAXYMAIL" => :SAFFRON,
"HEARTMAIL" => :CERULEAN,
"PIKACHU" => :VERMILLION,
"RAINBOWMAIL" => :CELADON,
}
#purchasable from pokemart after unlocking a
# certain switch
#flag => switch to unlock
CARD_BACKGROUND_UNLOCKABLES = {
"BLASTOISE" => SWITCH_BEAT_THE_LEAGUE,
"CHARIZARD" => SWITCH_BEAT_THE_LEAGUE,
"VENUSAUR" => SWITCH_BEAT_THE_LEAGUE,
"GROUDON" => SWITCH_HOENN_HAIR_COLLECTION,
"KYOGRE" => SWITCH_HOENN_HAIR_COLLECTION,
"RAYQUAZA" => SWITCH_HOENN_HAIR_COLLECTION,
"RESHIRAM" => SWITCH_UNOVA_HAIR_COLLECTION,
"ZEKROM" => SWITCH_UNOVA_HAIR_COLLECTION,
"BOULDERBADGE" => SWITCH_GOT_BADGE_1,
"CASCADEBADGE" => SWITCH_GOT_BADGE_2,
"THUNDERBADGE" => SWITCH_GOT_BADGE_3,
"RAINBOWBADGE" => SWITCH_GOT_BADGE_4,
"SOULBADGE" => SWITCH_GOT_BADGE_5,
"MARSHBADGE" => SWITCH_GOT_BADGE_6,
"VOLCANOBADGE" => SWITCH_GOT_BADGE_7,
"EARTHBADGE" => SWITCH_GOT_BADGE_8,
"PLAINBADGE" => SWITCH_GOT_BADGE_9,
"HIVEBADGE" => SWITCH_GOT_BADGE_10,
"ZEPHYRBADGE" => SWITCH_GOT_BADGE_11,
"RISINGBADGE" => SWITCH_GOT_BADGE_12,
"FOGBADGE" => SWITCH_GOT_BADGE_13,
"GLACIERBADGE" => SWITCH_GOT_BADGE_14,
"STORMBADGE" => SWITCH_GOT_BADGE_15,
"MINERALBADGE" => SWITCH_GOT_BADGE_16,
}
def unlock_card_background(id)
$Trainer.unlocked_card_backgrounds = [] if !$Trainer.unlocked_card_backgrounds
$Trainer.unlocked_card_backgrounds << id
end
def getDisplayedName(card_id)
return card_id.downcase.gsub('_', ' ').gsub('flags/', 'Team ').split.map(&:capitalize).join(' ')
end
def purchaseCardBackground(price = 1000)
$Trainer.unlocked_card_backgrounds = [] if ! $Trainer.unlocked_card_backgrounds
purchasable_cards = []
current_city = pbGet(VAR_CURRENT_MART)
current_city = :PEWTER if !current_city.is_a?(Symbol)
for card in CARD_BACKGROUND_DEFAULT_PURCHASABLE
purchasable_cards << card if !$Trainer.unlocked_card_backgrounds.include?(card)
end
for card in CARD_BACKGROUND_UNLOCKABLES.keys
purchasable_cards << card if $game_switches[CARD_BACKGROUND_UNLOCKABLES[card]] && !$Trainer.unlocked_card_backgrounds.include?(card)
end
for card in CARD_BACKGROUND_CITY_EXCLUSIVES.keys
purchasable_cards << card if current_city == CARD_BACKGROUND_CITY_EXCLUSIVES[card]
end
if purchasable_cards.length <= 0
pbMessage("There are no more Trainer Card backgrounds available for purchase!")
return
end
commands = []
index = 0
for card in purchasable_cards
index += 1
name = getDisplayedName(card)
commands.push([index, name, card])
end
pbMessage("\\GWhich background would you like to purchase?")
chosen = pbListScreen("Trainer card", TrainerCardBackgroundLister.new(purchasable_cards))
echoln chosen
if chosen != nil
name = getDisplayedName(chosen)
if pbConfirmMessage("\\GPurchase the \\C[1]#{name} Trainer Card background\\C[0] for $#{price.to_s}?")
if $Trainer.money < price
pbSEPlay("GUI sel buzzer", 80)
pbMessage("\\G\\C[2]Insufficient funds")
return false
end
pbSEPlay("Mart buy item")
$Trainer.money -= price
unlock_card_background(chosen)
pbSEPlay("Item get")
pbMessage("\\GYou purchased the #{name} Trainer Card background!")
if pbConfirmMessage("Would you like to swap your current Trainer Card for the newly purchased one?")
pbSEPlay("GUI trainer card open")
$Trainer.card_background = chosen
else
pbMessage("You can swap the background at anytime when viewing your Trainer Card.")
end
echoln $Trainer.unlocked_card_backgrounds
return true
end
else
pbSEPlay("computerclose")
end
end
class TrainerCardBackgroundLister
BASE_TRAINER_CARD_PATH = "Graphics/Pictures/Trainer Card/backgrounds"
def initialize(cardsList)
@sprite = SpriteWrapper.new
@sprite.bitmap = nil
@sprite.x = 250
@sprite.y = 100
@sprite.z = -2
@sprite.zoom_x = 0.5
@sprite.zoom_y = 0.5
@frame = SpriteWrapper.new
@frame.bitmap = AnimatedBitmap.new("Graphics/Pictures/Trainer Card/overlay").bitmap
@frame.x = 250
@frame.y = 100
@frame.z = -2
@frame.zoom_x = 0.5
@frame.zoom_y = 0.5
@commands = []
@cardsList = cardsList
@index = 0
end
def dispose
@sprite.bitmap.dispose if @sprite.bitmap
@sprite.dispose
@frame.bitmap.dispose if @sprite.bitmap
@frame.dispose
end
def setViewport(viewport)
@sprite.viewport = viewport
@frame.viewport = viewport
end
def startIndex
return @index
end
def commands
@commands.clear
for i in 0...@cardsList.length
card_id = @cardsList[i]
card_name = getDisplayedName(@cardsList[i])
@commands.push(card_name)
end
@commands << "Cancel"
return @commands
end
def value(index)
return nil if index < 0
return nil if index == @commands.length
return @cardsList[index]
end
def refresh(index)
return if index >= @cardsList.length
return if index < 0
@sprite.bitmap.dispose if @sprite.bitmap
card_id = @cardsList[index]
trainer_card_path = "#{BASE_TRAINER_CARD_PATH}/#{card_id}"
echoln index
echoln @cardsList.length
@sprite.bitmap = AnimatedBitmap.new(trainer_card_path).bitmap
#sprite.ox = @sprite.bitmap.width/2 if @sprite.bitmap
#@sprite.oy = @sprite.bitmap.height/2 if @sprite
end
end

View File

@@ -0,0 +1,36 @@
def pick_trainer_sprite(spriter_name)
possible_types = "abcd"
trainer_type_index = select_number_from_seed(spriter_name,0,3)
path = _INTL("Graphics/Trainers/trainer116{1}",possible_types[trainer_type_index].to_s)
return path
end
def select_number_from_seed(seed, min_value, max_value)
hash = 137
seed.each_byte do |byte|
hash = ((hash << 5) + hash) + byte
end
srand(hash)
selected_number = rand(min_value..max_value)
selected_number
end
def pick_spriter_losing_dialog(spriter_name)
possible_dialogs = [
"Oh... I lost...",
"I did my best!",
"You're too strong!",
"You win!",
"What a fight!",
"That was fun!",
"Ohh, that's too bad",
"I should've sprited some stronger Pokémon!",
"So much for that!",
"Should've seen that coming!",
"I can't believe it!",
"What a surprise!"
]
index = select_number_from_seed(spriter_name,0,possible_dialogs.size-1)
return possible_dialogs[index]
end

View File

@@ -0,0 +1,295 @@
#
#
#
class RematchTrainer
attr_reader :id
attr_reader :nbTimesRematched
def initialize(id)
@id = id
@nbTimesRematched = 0
end
def incrementNbTimes()
@nbTimesRematched += 1
end
def removeNbTimes()
@nbTimesRematched -= 1
end
end
#Methods called from elsewhere in the code
#
# called from pbEndOfBattle
#
def incrNbRematches(trainerId)
$PokemonGlobal.rematchedTrainers.each do |key, trainer|
if (trainer.id == trainerId)
trainer.incrementNbTimes()
end
end
end
# called from Trainer.to_trainer
def getNumberRematch(trainerId)
if $PokemonGlobal.rematchedTrainers == nil
$PokemonGlobal.rematchedTrainers = Hash.new
addNewTrainerRematch(trainerId)
end
trainer = $PokemonGlobal.rematchedTrainers[trainerId.to_sym]
if trainer == nil
addNewTrainerRematch(trainerId)
return 0
end
return (trainer.nbTimesRematched)
end
#
#
#
# #garder un list de cette classe en mem. globale
#
# #quand lance un combat: check si le switch pour rematch est actif.
# #si oui, check dans l'array globale si on trouve le trainer id.
# #si oui on maj, si non on l'ajoute
#
# #overload la classe qui lance les combats et ajuste les niveaux
# #selon le nb. de fois rematched
#
#
# # levelCap = originalLevel + (nbBadges*2) +2
#
# # on incremente le level a chaque x (jusqu'au levelcap)
# # nb = (level/10).ceil
#
#
def addNewTrainerRematch(trainerId)
#$PokemonGlobal.rematchedTrainers[:trainerId]
newTrainer = RematchTrainer.new(trainerId)
$PokemonGlobal.rematchedTrainers[trainerId.to_sym] = newTrainer
end
def getNumberRematchOld(trainerId)
if $PokemonGlobal.rematchedTrainers == nil
$PokemonGlobal.rematchedTrainers = Hash.new
addNewTrainerRematch(trainerId)
end
$PokemonGlobal.rematchedTrainers.each do |key, trainer|
if (trainer.id == trainerId)
return (trainer.nbTimesRematched)
end
end
addNewTrainerRematch(trainerId)
return 0
end
def getRematchLevel(originalLevel, nbRematch)
levelCap = getLevelCap(originalLevel, $Trainer.numbadges)
expRate = getLevelRate(originalLevel)
levelIncr = 0
for i in 0..nbRematch
if i % expRate == 0
levelIncr += 1
end
end
newLevel = originalLevel + levelIncr
#printDebugRematchInfo(nbRematch,expRate,newLevel,levelCap,originalLevel)
return (newLevel < levelCap) ? newLevel : levelCap
end
def getLevelRate(originalLevel)
return 2 + (originalLevel / 20).ceil
end
def getLevelCap(originalLevel, nbBadges)
return 100 if $game_switches[599] #no cap in battle arena
cap = originalLevel + nbBadges + 2
return cap < 100 ? cap : 100
end
def decreaseRematchNumber(trainerId)
$PokemonGlobal.rematchedTrainers.each do |key, trainer|
if (trainer.id == trainerId)
trainer.removeNbTimes()
return
end
end
end
# def evolveRematchPokemon(nbRematch, speciesSymbol)
# species = getDexNumberForSpecies(speciesSymbol)
# if (nbRematch >= 10 && $Trainer.numbadges >= 3)
# evospecies = getEvolution(species)
# return species if evospecies == -1
# if (nbRematch >= 20 && $Trainer.numbadges >= 8)
# secondEvoSpecies = getEvolution(evospecies)
# return secondEvoSpecies == -1 ? evospecies : secondEvoSpecies
# end
# return evospecies
# end
# return species
# end
def evolveRematchPokemon(nbRematch, speciesSymbol)
species = getDexNumberForSpecies(speciesSymbol)
if (nbRematch >= 30 && $Trainer.numbadges >= 6)
species = getEvolution(species,:HEAD)
species = getEvolution(species,:BODY)
species = getEvolution(species,:HEAD)
species = getEvolution(species,:BODY)
elsif (nbRematch >= 20 && $Trainer.numbadges >= 3)
species = getEvolution(species,:HEAD)
species = getEvolution(species,:BODY)
species = getEvolution(species,:HEAD)
elsif (nbRematch >= 10 && $Trainer.numbadges >= 3)
species = getEvolution(species,:HEAD)
species = getEvolution(species,:BODY)
elsif (nbRematch >= 5)
species = getEvolution(species,:HEAD)
end
return species
end
def getEvolution(speciesParam, halfToEvolve=nil)
species = dexNum(speciesParam)
begin
prioritizeHead = halfToEvolve == :HEAD
prioritizeBody = halfToEvolve == :BODY
if species >= Settings::NB_POKEMON
body = getBasePokemonID(species)
head = getBasePokemonID(species, false)
bodyPossibleEvolutions = GameData::Species.get(body).get_evolutions(true)
headPossibleEvolutions = GameData::Species.get(head).get_evolutions(true)
bodyCanEvolve = !bodyPossibleEvolutions.empty?
headCanEvolve = !headPossibleEvolutions.empty?
evoBodySpecies = bodyCanEvolve ? bodyPossibleEvolutions[rand(bodyPossibleEvolutions.length - 1)][0] : nil
evoHeadSpecies = headCanEvolve ? headPossibleEvolutions[rand(headPossibleEvolutions.length - 1)][0] : nil
if evoBodySpecies != nil
evoBody = getDexNumberForSpecies(evoBodySpecies)
end
if evoHeadSpecies != nil
evoHead = getDexNumberForSpecies(evoHeadSpecies)
end
return species if evoBody == nil && evoHead == nil
if prioritizeBody
if evoBody == nil
return body * Settings::NB_POKEMON + evoHead #only head evolves
else
return evoBody * Settings::NB_POKEMON + head #only body evolves
end
end
if prioritizeHead
if evoHead == nil
return evoBody * Settings::NB_POKEMON + head #only body evolves
else
return body * Settings::NB_POKEMON + evoHead #only head evolves
end
end
return body * Settings::NB_POKEMON + evoHead if evoBody == nil #only head evolves
return evoBody * Settings::NB_POKEMON + head if evoHead == nil #only body evolves
return evoBody * Settings::NB_POKEMON + evoHead #both evolve
else
evo = pbGetEvolvedFormData(species)
newSpecies = evo[rand(evo.length - 1)][0]
return evo.any? ? getDexNumberForSpecies(newSpecies) : species
end
rescue
return species
end
end
def getFusionSpeciesSymbol(body, head)
body_num = dexNum(body)
head_num = dexNum(head)
nb_pokemon = Settings::NB_POKEMON
id = body_num * nb_pokemon + head_num
if id > (nb_pokemon*nb_pokemon)+nb_pokemon
displayRandomizerErrorMessage()
return body
end
return GameData::Species.get(id).species
end
#
def evolveHead(species)
species_id = getDexNumberForSpecies(species)
if species_id <= Settings::NB_POKEMON
evo = getEvolution(species_id)
return evo == -1 ? species_id : evo
end
head = getBasePokemonID(species_id, false)
body = getBasePokemonID(species_id)
headEvo = getEvolution(head)
return headEvo == -1 ? species_id : getFusionSpeciesSymbol(body, headEvo)
end
def evolveBody(species)
species_id = getDexNumberForSpecies(species)
if species_id <= Settings::NB_POKEMON
evo = getEvolution(species_id)
return evo == -1 ? species_id : evo
end
head = getBasePokemonID(species_id, false)
body = getBasePokemonID(species_id)
bodyEvo = getEvolution(body)
return bodyEvo == -1 ? species_id : getFusionSpeciesSymbol(bodyEvo, head)
end
def getCorrectEvolvedSpecies(pokemon)
if pokemon.species >= Settings::NB_POKEMON
body = getBasePokemonID(pokemon.species)
head = getBasePokemonID(pokemon.species, false)
ret1 = -1; ret2 = -1
for form in pbGetEvolvedFormData(body)
retB = yield pokemon, form[0], form[1], form[2]
break if retB > 0
end
for form in pbGetEvolvedFormData(head)
retH = yield pokemon, form[0], form[1], form[2]
break if retH > 0
end
return ret if ret == retB && ret == retH
return fixEvolutionOverflow(retB, retH, pokemon.species)
else
for form in pbGetEvolvedFormData(pokemon.species)
newspecies = form[2]
end
return newspecies;
end
end
def printDebugRematchInfo(nbRematch, expRate, newLevel, levelCap, originalLevel)
info = ""
info << "total rematched trainers: " + $PokemonGlobal.rematchedTrainers.length.to_s + "\n"
info << "nb times: " + nbRematch.to_s + "\n"
info << "lvl up every " + expRate.to_s + " times" + "\n"
info << "original level: " << originalLevel.to_s + "\n"
info << "new level: " + newLevel.to_s + "\n"
info << "level cap: " + levelCap.to_s
print info
end
#
#
#
# class PokeBattle_Trainer
# attr_accessor(:name)
# def name()
# return @name
# end
# end

View File

@@ -0,0 +1,90 @@
class TripleFusion < Pokemon
attr_reader :species1
attr_reader :species2
attr_reader :species3
def initialize(species1, species2,species3, level, owner = $Trainer, withMoves = true, recheck_form = true)
@species1=species1
@species2=species2
@species3=species3
@species1_data = GameData::Species.get(@species1)
@species2_data = GameData::Species.get(@species2)
@species3_data = GameData::Species.get(@species3)
@species_name = generate_triple_fusion_name()
super(:ZAPMOLTICUNO,level,owner,withMoves,recheck_form)
end
def types
return [@species1_data.type1, @species2_data.type1,@species3_data.type1]
end
def baseStats
ret = {}
GameData::Stat.each_main do |s|
stat1 = @species1_data.base_stats[s.id]
stat2 = @species2_data.base_stats[s.id]
stat3 = @species3_data.base_stats[s.id]
ret[s.id] = (stat1 + stat2 + stat3) / 3
end
return ret
end
def name
return (nicknamed?) ? @name : @species_name
end
def speciesName
return @species_name
end
def generate_triple_fusion_name()
part1 = split_string_with_syllables(@species1_data.name)[0]
part2 = split_string_with_syllables(@species2_data.name)[1]
part3 = split_string_with_syllables(@species3_data.name)[2]
return _INTL("{1}{2}{3}",part1,part2,part3).capitalize!
end
def split_string_with_syllables(name)
syllable_pattern = /[bcdfghjklmnpqrstvwxyz]*[aeiou]+[bcdfghjklmnpqrstvwxyz]*/
syllables = name.downcase.scan(syllable_pattern)
first_syllable= syllables.first
last_syllable = syllables.last
if syllables.length > 1
middle_syllable = syllables[1]
else
middle_syllable = first_syllable.downcase
end
last_syllable.nil? ? first_syllable : last_syllable
return [first_syllable,middle_syllable,last_syllable]
end
def ability_id
if !@ability
abil_index = ability_index
if !@ability # Natural ability or no hidden ability defined
chosen_poke_for_ability= rand(1..3)
if chosen_poke_for_ability == 1
@ability = @species1_data.abilities[abil_index] || @species1_data.abilities[0]
elsif chosen_poke_for_ability == 2
@ability = @species2_data.abilities[abil_index] || @species2_data.abilities[0]
else
@ability = @species3_data.abilities[abil_index] || @species3_data.abilities[0]
end
end
end
return @ability
end
end

View File

@@ -0,0 +1,423 @@
class PokemonPokedexInfo_Scene
#todo add indicator to show which one is the main sprite -
# also maybe add an indicator in main list for when a sprite has available alts
Y_POSITION_SMALL = 40 #90
Y_POSITION_BIG = 60
X_POSITION_PREVIOUS = -30 #20
X_POSITION_SELECTED = 105
X_POSITION_NEXT = 340 #380
Y_POSITION_BG_SMALL = 70
Y_POSITION_BG_BIG = 93
X_POSITION_BG_PREVIOUS = -1
X_POSITION_BG_SELECTED = 145
X_POSITION_BG_NEXT = 363
def drawPageForms()
#@selected_index=0
@sprites["background"].setBitmap(_INTL("Graphics/Pictures/Pokedex/bg_forms"))
overlay = @sprites["overlay"].bitmap
base = Color.new(88, 88, 80)
shadow = Color.new(168, 184, 184)
#alts_list= pbGetAvailableAlts
@selected_index = 0 if !@selected_index
update_displayed
end
def init_selected_bg
@sprites["bgSelected_previous"] = IconSprite.new(0, 0, @viewport)
@sprites["bgSelected_previous"].x = X_POSITION_BG_PREVIOUS
@sprites["bgSelected_previous"].y = Y_POSITION_BG_SMALL
@sprites["bgSelected_previous"].setBitmap(_INTL("Graphics/Pictures/Pokedex/bg_forms_selected_small"))
@sprites["bgSelected_previous"].visible = false
@sprites["bgSelected_center"] = IconSprite.new(0, 0, @viewport)
@sprites["bgSelected_center"].x = X_POSITION_BG_SELECTED
@sprites["bgSelected_center"].y = Y_POSITION_BG_BIG
@sprites["bgSelected_center"].setBitmap(_INTL("Graphics/Pictures/Pokedex/bg_forms_selected_large"))
@sprites["bgSelected_center"].visible = false
@sprites["bgSelected_next"] = IconSprite.new(0, 0, @viewport)
@sprites["bgSelected_next"].x = X_POSITION_BG_NEXT
@sprites["bgSelected_next"].y = Y_POSITION_BG_SMALL
@sprites["bgSelected_next"].setBitmap(_INTL("Graphics/Pictures/Pokedex/bg_forms_selected_small"))
@sprites["bgSelected_next"].visible = false
@creditsOverlay = BitmapSprite.new(Graphics.width, Graphics.height, @viewport).bitmap
end
def initializeSpritesPage(altsList)
@forms_list = list_pokemon_forms()
@formIndex = 0
init_selected_bg
@speciesData = getSpecies(@species)
@selected_index = 0
set_displayed_to_current_alt(altsList)
@sprites["selectedSprite"] = IconSprite.new(0, 0, @viewport)
@sprites["selectedSprite"].x = X_POSITION_SELECTED
@sprites["selectedSprite"].y = Y_POSITION_BIG
@sprites["selectedSprite"].z = 999999
@sprites["selectedSprite"].visible = false
@sprites["selectedSprite"].zoom_x = 1
@sprites["selectedSprite"].zoom_y = 1
@sprites["previousSprite"] = IconSprite.new(0, 0, @viewport)
@sprites["previousSprite"].x = X_POSITION_PREVIOUS
@sprites["previousSprite"].y = Y_POSITION_SMALL
@sprites["previousSprite"].visible = false
@sprites["previousSprite"].zoom_x = Settings::FRONTSPRITE_SCALE #/2
@sprites["previousSprite"].zoom_y = Settings::FRONTSPRITE_SCALE #/2
@sprites["nextSprite"] = IconSprite.new(0, 0, @viewport)
@sprites["nextSprite"].x = X_POSITION_NEXT
@sprites["nextSprite"].y = Y_POSITION_SMALL
@sprites["nextSprite"].visible = false
@sprites["nextSprite"].zoom_x = Settings::FRONTSPRITE_SCALE #/2
@sprites["nextSprite"].zoom_y = Settings::FRONTSPRITE_SCALE #/2
@sprites["selectedSprite"].z = 9999999
@sprites["previousSprite"].z = 9999999
@sprites["nextSprite"].z = 9999999
@selected_pif_sprite = get_pif_sprite(@available[@selected_index])
@previous_pif_sprite = get_pif_sprite(@available[@selected_index - 1])
@next_pif_sprite = get_pif_sprite(@available[@selected_index + 1])
@sprites["selectedSprite"].bitmap = load_pif_sprite(@selected_pif_sprite)
if altsList.size >= 2
@sprites["nextSprite"].bitmap = load_pif_sprite(@next_pif_sprite)
@sprites["nextSprite"].visible = true
end
if altsList.size >= 3
animated_bitmap =
@sprites["previousSprite"].bitmap = load_pif_sprite(@previous_pif_sprite)
@sprites["previousSprite"].visible = true
end
end
def load_pif_sprite(pif_sprite)
animated_bitmap = @spritesLoader.load_pif_sprite_directly(pif_sprite)
return animated_bitmap.bitmap if animated_bitmap
return nil
end
# def get_currently_selected_sprite()
# species_dex = getDexNumberForSpecies(@species).to_s
# initialize_alt_sprite_substitutions()
# substitution_id = getSpritesSubstutionFromSpecies(species_dex)
# return $PokemonGlobal.alt_sprite_substitutions[substitution_id]
# end
def get_substitution_id(dex_number)
if isFusion(dex_number)
body_id = getBodyID(dex_number)
head_id = getHeadID(dex_number, body_id)
species_id = [head_id, body_id]
else
species_id = dex_number
end
return species_id
end
def set_displayed_to_current_alt(altsList)
dex_number= getDexNumberForSpecies(@species)
species_id= get_substitution_id(dex_number)
initialize_alt_sprite_substitutions()
return if !$PokemonGlobal.alt_sprite_substitutions[species_id]
current_sprite = $PokemonGlobal.alt_sprite_substitutions[species_id]
index = @selected_index
for alt in altsList
if alt == current_sprite.alt_letter
@selected_index = index
return
end
index += 1
end
end
def pbGetAvailableForms(species = nil)
chosen_species = species != nil ? species : @species
dex_num = getDexNumberForSpecies(chosen_species)
includeAutogens = isFusion(dex_num)
return PokedexUtils.new.pbGetAvailableAlts(chosen_species, includeAutogens)
end
def hide_all_selected_windows
@sprites["bgSelected_previous"].visible = false if @sprites["bgSelected_previous"]
@sprites["bgSelected_center"].visible = false if @sprites["bgSelected_center"]
@sprites["bgSelected_next"].visible = false if @sprites["bgSelected_next"]
end
def update_selected
hide_all_selected_windows
previous_index = @selected_index == 0 ? @available.size - 1 : @selected_index - 1
next_index = @selected_index == @available.size - 1 ? 0 : @selected_index + 1
@sprites["bgSelected_previous"].visible = true if is_main_sprite(previous_index) && @available.size > 2
@sprites["bgSelected_center"].visible = true if is_main_sprite(@selected_index)
@sprites["bgSelected_next"].visible = true if is_main_sprite(next_index) && @available.size > 1
end
def get_pif_sprite(alt_letter)
dex_number = getDexNumberForSpecies(@species) #@species is a symbol when called from the summary screen and an int from the pokedex... Would be nice to refactor
if isFusion(dex_number)
body_id = getBodyID(dex_number)
head_id = getHeadID(dex_number, body_id)
if alt_letter == "autogen"
pif_sprite = PIFSprite.new(:AUTOGEN, head_id, body_id)
else
pif_sprite = PIFSprite.new(:CUSTOM, head_id, body_id, alt_letter)
end
else
pif_sprite = PIFSprite.new(:BASE, dex_number, nil, alt_letter)
end
return pif_sprite
end
def isBaseSpritePath(path)
filename = File.basename(path).downcase
return filename.match?(/\A\d+\.png\Z/)
end
def update_displayed
nextIndex = @selected_index + 1
previousIndex = @selected_index - 1
if nextIndex > @available.size - 1
nextIndex = 0
end
if previousIndex < 0
previousIndex = @available.size - 1
end
# @sprites["previousSprite"].visible = @available.size > 2
# @sprites["nextSprite"].visible = @available.size > 1
@selected_pif_sprite = get_pif_sprite(@available[@selected_index])
@previous_pif_sprite = get_pif_sprite(@available[previousIndex])
@next_pif_sprite = get_pif_sprite(@available[nextIndex])
@sprites["previousSprite"].bitmap = load_pif_sprite(@previous_pif_sprite) if previousIndex != nextIndex
@sprites["selectedSprite"].bitmap = load_pif_sprite(@selected_pif_sprite)
@sprites["nextSprite"].bitmap = load_pif_sprite(@next_pif_sprite)
#selected_bitmap = @sprites["selectedSprite"].getBitmap
# sprite_path = selected_bitmap.path
#isBaseSprite = isBaseSpritePath(@available[@selected_index])
is_generated = @selected_pif_sprite.type == :AUTOGEN
spritename = @selected_pif_sprite.to_filename()
showSpriteCredits(spritename, is_generated)
update_selected
end
def showSpriteCredits(filename, generated_sprite = false)
@creditsOverlay.dispose
x = Graphics.width / 2 - 75
y = Graphics.height - 60
spritename = File.basename(filename, '.*')
if !generated_sprite
discord_name = getSpriteCredits(spritename)
discord_name = "Unknown artist" if !discord_name
else
#todo give credits to Japeal - need to differenciate unfused sprites
discord_name = "" #"Japeal\n(Generated)"
end
author_name = File.basename(discord_name, '#*')
label_base_color = Color.new(248, 248, 248)
label_shadow_color = Color.new(104, 104, 104)
@creditsOverlay = BitmapSprite.new(Graphics.width, Graphics.height, @viewport).bitmap
textpos = [[author_name, x, y, 0, label_base_color, label_shadow_color]]
pbDrawTextPositions(@creditsOverlay, textpos)
end
def list_pokemon_forms
dexNum = dexNum(@species)
if dexNum > NB_POKEMON
body_id = getBodyID(dexNum)
else
if @species.is_a?(Symbol)
body_id = get_body_number_from_symbol(@species)
else
body_id = dexNum
end
end
forms_list = []
found_last_form = false
form_index = 0
while !found_last_form
form_index += 1
form_path = Settings::BATTLERS_FOLDER + body_id.to_s + "_" + form_index.to_s
if File.directory?(form_path)
forms_list << form_index
else
found_last_form = true
end
end
return forms_list
end
def pbChooseAlt(brief = false)
loop do
@sprites["rightarrow"].visible = true
@sprites["leftarrow"].visible = true
if @forms_list.length >= 1
@sprites["uparrow"].visible = true
@sprites["downarrow"].visible = true
end
multiple_forms = @forms_list.length > 0
Graphics.update
Input.update
pbUpdate
if Input.trigger?(Input::LEFT)
pbPlayCursorSE
@selected_index -= 1 #(index+@available.length-1)%@available.length
if @selected_index < 0
@selected_index = @available.size - 1
end
update_displayed
elsif Input.trigger?(Input::RIGHT)
pbPlayCursorSE
@selected_index += 1
if @selected_index > @available.size - 1
@selected_index = 0
end
update_displayed
elsif Input.trigger?(Input::BACK)
pbPlayCancelSE
break
elsif Input.trigger?(Input::USE)
pbPlayDecisionSE
if select_sprite(brief)
@endscene = true
break
end
end
end
@sprites["uparrow"].visible = false
@sprites["downarrow"].visible = false
end
# def is_main_sprite(index = nil)
# return false if !@available
# if index == nil
# index = @selected_index
# end
# return true if @available.size <= 1
# if @speciesData.always_use_generated
# selected_sprite = @available[index]
# return selected_sprite.start_with?(Settings::BATTLERS_FOLDER)
# end
# return index == 0
# end
def is_main_sprite(index = nil)
dex_number= getDexNumberForSpecies(@species)
if !index
index = @selected_index
end
selected_sprite = @available[index]
species_id = get_substitution_id(dex_number)
if $PokemonGlobal.alt_sprite_substitutions[species_id]
return $PokemonGlobal.alt_sprite_substitutions[species_id].alt_letter == selected_sprite
end
end
def sprite_is_alt(sprite_path)
spritename = File.basename(sprite_path, '.*')
return spritename.match?(/[a-zA-Z]/)
end
def select_sprite(brief = false)
if @available.length > 1
if is_main_sprite
if brief
pbMessage("This sprite will remain the displayed sprite")
return true
else
pbMessage("This sprite is already the displayed sprite")
end
else
message = 'Would you like to use this sprite instead of the current sprite?'
if pbConfirmMessage(_INTL(message))
swap_main_sprite()
return true
end
end
else
pbMessage("This is the only sprite available for this Pokémon!")
end
return false
end
def swap_main_sprite
old_main_sprite = @available[0]
new_alt_letter = @available[@selected_index]
species_number = dexNum(@species)
substitution_id = get_substitution_id(species_number)
$PokemonGlobal.alt_sprite_substitutions[substitution_id] = @selected_pif_sprite
end
# def swap_main_sprite
# begin
# old_main_sprite = @available[0]
# new_main_sprite = @available[@selected_index]
#
# if main_sprite_is_non_custom()
# @speciesData.set_always_use_generated_sprite(false)
# return
# # new_name_without_ext = File.basename(old_main_sprite, ".png")
# # new_name_without_letter=new_name_without_ext.chop
# # File.rename(new_main_sprite, Settings::CUSTOM_BATTLERS_FOLDER+new_name_without_letter + ".png")
# end
#
# if new_main_sprite.start_with?(Settings::BATTLERS_FOLDER)
# @speciesData.set_always_use_generated_sprite(true)
# return
# # new_name_without_ext = File.basename(old_main_sprite, ".png")
# # File.rename(old_main_sprite, Settings::CUSTOM_BATTLERS_FOLDER+new_name_without_ext+"x" + ".png")x
# # return
# end
# File.rename(new_main_sprite, new_main_sprite + "temp")
# File.rename(old_main_sprite, new_main_sprite)
# File.rename(new_main_sprite + "temp", old_main_sprite)
# rescue
# pbMessage("There was an error while swapping the sprites. Please save and restart the game as soon as possible.")
# end
# end
# def main_sprite_is_non_custom()
# speciesData = getSpecies(@species)
# return speciesData.always_use_generated || @available.size <= 1
# end
end
class PokemonGlobalMetadata
attr_accessor :alt_sprite_substitutions
end
# def set_alt_sprite_substitution(original_sprite_name, selected_alt, formIndex = 0)
# if !$PokemonGlobal.alt_sprite_substitutions
# initialize_alt_sprite_substitutions()
# end
# if formIndex
# form_suffix = formIndex != 0 ? "_" + formIndex.to_s : ""
# else
# form_suffix = ""
# end
# $PokemonGlobal.alt_sprite_substitutions[original_sprite_name.to_s + form_suffix] = selected_alt
# end

View File

@@ -0,0 +1,293 @@
# #===============================================================================
# # * Unreal Time System - by FL (Credits will be apreciated)
# #===============================================================================
# #
# # This script is for Pokémon Essentials. It makes the time in game uses its
# # own clock that only pass when you are in game instead of using real time
# # (like Minecraft and Zelda: Ocarina of Time).
# #
# #== INSTALLATION ===============================================================
# #
# # To this script works, put it above main OR convert into a plugin.
# #
# #== HOW TO USE =================================================================
# #
# # This script automatic works after installed.
# #
# # If you wish to add/reduce time, there are 3 ways:
# #
# # 1. EXTRA_SECONDS/EXTRA_DAYS are variables numbers that hold time passage;
# # The time in these variable isn't affected by PROPORTION.
# # Example: When the player sleeps you wish to the time in game advance
# # 8 hours, so put in EXTRA_SECONDS a game variable number and sum
# # 28800 (60*60*8) in this variable every time that the players sleeps.
# #
# # 2. 'UnrealTime.add_seconds(seconds)' and 'UnrealTime.add_days(days)' does the
# # same thing, in fact, EXTRA_SECONDS/EXTRA_DAYS call these methods.
# #
# # 3. 'UnrealTime.advance_to(16,17,18)' advance the time to a fixed time of day,
# # 16:17:18 on this example.
# #
# #== NOTES ======================================================================
# #
# # If you wish to some parts still use real time like the Trainer Card start time
# # and Pokémon Trainer Memo, just change 'pbGetTimeNow' to 'Time.now' in their
# # scripts.
# #
# # This script uses the Ruby Time class. Before Essentials version 19 (who came
# # with 64-bit ruby) it can only have 1901-2038 range.
# #
# # Some time methods:
# # 'pbGetTimeNow.year', 'pbGetTimeNow.mon' (the numbers from 1-12),
# # 'pbGetTimeNow.day','pbGetTimeNow.hour', 'pbGetTimeNow.min',
# # 'pbGetTimeNow.sec', 'pbGetAbbrevMonthName(pbGetTimeNow.mon)',
# # 'pbGetTimeNow.strftime("%A")' (displays weekday name),
# # 'pbGetTimeNow.strftime("%I:%M %p")' (displays Hours:Minutes pm/am)
# #
# #===============================================================================
#
# if defined?(PluginManager) && !PluginManager.installed?("Unreal Time System")
# PluginManager.register({
# :name => "Unreal Time System",
# :version => "1.1",
# :link => "https://www.pokecommunity.com/showthread.php?t=285831",
# :credits => "FL"
# })
# end
#
module UnrealTime
# Set false to disable this system (returns Time.now)
ENABLED = true
# Time proportion here.
# So if it is 100, one second in real time will be 100 seconds in game.
# If it is 60, one second in real time will be one minute in game.
PROPORTION = 60
# Starting on Essentials v17, the map tone only try to refresh tone each 30
# real time seconds.
# If this variable number isn't -1, the game use this number instead of 30.
# When time is changed with advance_to or add_seconds, the tone refreshes.
TONE_CHECK_INTERVAL = 10.0
# Make this true to time only pass at field (Scene_Map)
# A note to scripters: To make time pass on other scenes, put line
# '$PokemonGlobal.addNewFrameCount' near to line 'Graphics.update'
TIME_STOPS = true
# Make this true to time pass in battle, during turns and command selection.
# This won't affect the Pokémon and Bag submenus.
# Only works if TIME_STOPS=true.
BATTLE_PASS = true
# Make this true to time pass when the Dialog box or the main menu are open.
# This won't affect the submenus like Pokémon and Bag.
# Only works if TIME_STOPS=true.
TALK_PASS = true
# Choose switch number that when true the time won't pass (or -1 to cancel).
# Only works if TIME_STOPS=true.
SWITCH_STOPS = -1
# Choose variable(s) number(s) that can hold time passage (or -1 to cancel).
# Look at description for more details.
EXTRA_SECONDS = 79
EXTRA_DAYS = -1
WEEK_DAY_VARIABLE = 280
WEEK_DAYS = [:MONDAY,:TUESDAY,:WEDNESDAY,:THURSDAY,:FRIDAY,:SATURDAY,:SUNDAY]
# Initial date. In sequence: Year, month, day, hour and minutes.
# Method UnrealTime.reset resets time back to this time.
def self.initial_date
return Time.local(2000, 1, 1, 4, 0)
end
# Advance to next time. If time already passed, advance
# into the time on the next day.
# Hour is 0..23
def self.advance_to(hour, min = 0, sec = 0)
if hour < 0 || hour > 23
raise RangeError, "hour is #{hour}, should be 0..23"
end
day_seconds = 60 * 60 * 24
seconds_now = pbGetTimeNow.hour * 60 * 60 + pbGetTimeNow.min * 60 + pbGetTimeNow.sec
target_seconds = hour * 60 * 60 + min * 60 + sec
seconds_added = target_seconds - seconds_now
seconds_added += day_seconds if seconds_added < 0
$PokemonGlobal.newFrameCount += seconds_added
PBDayNight.sheduleToneRefresh
end
# Resets time to initial_date.
def self.reset
raise "Method doesn't work when TIME_STOPS is false!" if !TIME_STOPS
$game_variables[EXTRA_SECONDS] = 0 if EXTRA_DAYS > 0
$game_variables[EXTRA_DAYS] = 0 if EXTRA_DAYS > 0
$PokemonGlobal.newFrameCount = 0
$PokemonGlobal.extraYears = 0
PBDayNight.sheduleToneRefresh
end
# Does the same thing as EXTRA_SECONDS variable.
def self.add_seconds(seconds)
raise "Method doesn't work when TIME_STOPS is false!" if !TIME_STOPS
$PokemonGlobal.newFrameCount += (seconds * Graphics.frame_rate) / PROPORTION.to_f
PBDayNight.sheduleToneRefresh
end
def self.add_days(days)
add_seconds(60 * 60 * 24 * days)
end
NEED_32_BIT_FIX = [''].pack('p').size <= 4
end
# Essentials V18 and lower compatibility
module Settings
TIME_SHADING = defined?(ENABLESHADING) ? ENABLESHADING : ::TIME_SHADING
end if defined?(TIME_SHADING) || defined?(ENABLESHADING)
module PBDayNight
class << self
if method_defined?(:getTone) && UnrealTime::TONE_CHECK_INTERVAL > 0
def getTone
@cachedTone = Tone.new(0, 0, 0) if !@cachedTone
return @cachedTone if !Settings::TIME_SHADING
toneNeedUpdate = (!@dayNightToneLastUpdate ||
Graphics.frame_count - @dayNightToneLastUpdate >=
Graphics.frame_rate * UnrealTime::TONE_CHECK_INTERVAL
)
if toneNeedUpdate
getToneInternal
@dayNightToneLastUpdate = Graphics.frame_count
end
return @cachedTone
end
end
# Shedule a tone refresh on the next try (probably next frame)
def sheduleToneRefresh
@dayNightToneLastUpdate = nil
end
end
end
def getDayOfTheWeek()
day_of_week = (pbGetTimeNow.day % UnrealTime::WEEK_DAYS.length).to_i
return UnrealTime::WEEK_DAYS[day_of_week]
end
def isDayOfTheWeek(day)
return day == getDayOfTheWeek()
end
def pbGetTimeNow
return Time.now if !$PokemonGlobal || !UnrealTime::ENABLED
day_seconds = 60 * 60 * 24
if UnrealTime::TIME_STOPS
# Sum the extra values to newFrameCount
if UnrealTime::EXTRA_SECONDS > 0
UnrealTime.add_seconds(pbGet(UnrealTime::EXTRA_SECONDS))
$game_variables[UnrealTime::EXTRA_SECONDS] = 0
end
if UnrealTime::EXTRA_DAYS > 0
UnrealTime.add_seconds(day_seconds * pbGet(UnrealTime::EXTRA_DAYS))
$game_variables[UnrealTime::EXTRA_DAYS] = 0
end
elsif UnrealTime::EXTRA_SECONDS > 0 && UnrealTime::EXTRA_DAYS > 0
# Checks to regulate the max/min values at UnrealTime::EXTRA_SECONDS
while pbGet(UnrealTime::EXTRA_SECONDS) >= day_seconds
$game_variables[UnrealTime::EXTRA_SECONDS] -= day_seconds
$game_variables[UnrealTime::EXTRA_DAYS] += 1
end
while pbGet(UnrealTime::EXTRA_SECONDS) <= -day_seconds
$game_variables[UnrealTime::EXTRA_SECONDS] += day_seconds
$game_variables[UnrealTime::EXTRA_DAYS] -= 1
end
end
start_time = UnrealTime.initial_date
if UnrealTime::TIME_STOPS
time_played = $PokemonGlobal.newFrameCount
else
time_played = Graphics.frame_count
end
time_played = (time_played * UnrealTime::PROPORTION) / Graphics.frame_rate
time_jumped = 0
if UnrealTime::EXTRA_SECONDS > -1
time_jumped += pbGet(UnrealTime::EXTRA_SECONDS)
end
if UnrealTime::EXTRA_DAYS > -1
time_jumped += pbGet(UnrealTime::EXTRA_DAYS) * day_seconds
end
time_ret = 0
# Before Essentials V19, there is a year limit. To prevent crashes due to this
# limit, every time that you reach in year 2036 the system will subtract 6
# years (to works with leap year) from your date and sum in
# $PokemonGlobal.extraYears. You can sum your actual year with this extraYears
# when displaying years.
loop do
time_fix = 0
if $PokemonGlobal.extraYears != 0
time_fix = $PokemonGlobal.extraYears * day_seconds * (365 * 6 + 1) / 6
end
time_ret = start_time + (time_played + time_jumped - time_fix)
break if !UnrealTime::NEED_32_BIT_FIX || time_ret.year < 2036
$PokemonGlobal.extraYears += 6
end
return time_ret
end
if UnrealTime::ENABLED
class PokemonGlobalMetadata
attr_accessor :newFrameCount # Became float when using extra values
attr_accessor :extraYears
def addNewFrameCount
return if (UnrealTime::SWITCH_STOPS > 0 &&
$game_switches[UnrealTime::SWITCH_STOPS])
self.newFrameCount += 1
end
def newFrameCount
@newFrameCount = 0 if !@newFrameCount
return @newFrameCount
end
def extraYears
@extraYears = 0 if !@extraYears
return @extraYears
end
end
if UnrealTime::TIME_STOPS
class Scene_Map
alias :updateold :update
def update
$PokemonGlobal.addNewFrameCount
updateold
end
if UnrealTime::TALK_PASS
alias :miniupdateold :miniupdate
def miniupdate
$PokemonGlobal.addNewFrameCount
miniupdateold
end
end
end
if UnrealTime::BATTLE_PASS
class PokeBattle_Scene
alias :pbGraphicsUpdateold :pbGraphicsUpdate
def pbGraphicsUpdate
$PokemonGlobal.addNewFrameCount
pbGraphicsUpdateold
end
end
end
end
end

View File

@@ -0,0 +1,23 @@
PUDDLE_ANIMATION_ID = 22
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|
mapTerrainTag = $MapFactory.getTerrainTag(event.map.map_id, x, y, false)
if $PokemonGlobal.surfing
if isWaterTerrain?(mapTerrainTag) #&& $PokemonGlobal.stepcount % 2 ==0
$scene.spriteset.addUserAnimation(PUDDLE_ANIMATION_ID, event.x, event.y, true, 0)
end
else
if mapTerrainTag == 16 #puddle
pbSEPlay("puddle", 100) if event == $game_player && !$PokemonGlobal.surfing #only play sound effect in puddle
$scene.spriteset.addUserAnimation(PUDDLE_ANIMATION_ID, event.x, event.y, true, 0)
end
end
end
end
}
def isWaterTerrain?(tag)
return [5, 6, 17, 7, 9, 16].include?(tag)
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
=begin
*** Wonder Trade Script by Black Eternity ***
This script is to mimic Wonder Trade from an offline perspective.
THERE IS NO ONLINE CAPABILITIES OF THIS SCRIPT,
ALL CALCULATIONS ARE DONE INTERNALLY.
To call the script like normal and have ALL Pokemon trade-able, use the following.
pbWondertrade(1,[],[])
Black listed Pokemon are to be added to the Exceptions arrays.
Except is the list of pokemon the player is forbidden to trade.
Here the player cannot trade any of the following.
pbWonderTrade(1,[:PIKACHU,:SQUIRTLE,:CHARMANDER,;BULBASAUR],[])
Except2 is the list of pokemon the player is forbidden to receive.
Here the player cannot receive any of the following.
pbWonderTrade(1,[],[:MEWTWO,;MEW,;DEOXYS])
The first parameter is the minimum allowed Level of the Pokemon to be traded.
For example, you can not trade a Pokemon through Wonder Trade unless its level
is greater than or equal to specified level.
pbWonderTrade(40,[:SQUIRTLE,:CHARMANDER,:BULBASAUR],[:MEWTWO,:MEW,:DEOXYS])
*** Only pokemon over level 40 can be traded, you cannot trade starters.
*** You cannot receive these legendaries.
The fourth parameter, which has recently replaced mej71's "hardobtain"
is called "rare", this parameter developed also by mej71, will use
the Pokemon's rareness and filter the results depending on its values.
** Rareness is turned on by default, if you wish to disable it, call the
function accordingly.
pbWonderTrade(10,[:SQUIRTLE],[:CHARMANDER,:BULBASAUR],false)
** Only Pokemon over level 10, cannot trade Squirtle, cannot
** recieve Charmander or Bulbasaur, Rareness disabled.
It is up to you to use it how you wish, credits will be appreciated.
=end
# List of Randomly selected Trainer Names
# These are just names taken from a generator, add custom or change to
# whatever you desire.
def pbWonderTrade(lvl, except = [], except2 = [], premiumWonderTrade = true)
# for i in 0...except.length # Gets ID of pokemon in exception array
# except[i]=getID(PBSpecies,except[i]) if !except[i].is_a?(Integer)
# end
# for i in 0...except2.length # Gets ID of pokemon in exception array
# except2[i]=getID(PBSpecies,except2[i]) if !except2[i].is_a?(Integer)
# end
# ignoreExcept = rand(100) == 0 #tiny chance to include legendaries
#
# except+=[]
rare = premiumWonderTrade
chosen = pbChoosePokemon(1, 2, # Choose eligable pokemon
proc {
|poke| !poke.egg? && !(poke.isShadow?) && # No Eggs, No Shadow Pokemon
(poke.level >= lvl) && !(except.include?(poke.species)) # None under "lvl", no exceptions.
})
poke = $Trainer.party[pbGet(1)]
if !pbConfirmMessage(_INTL("Trade {1} away?",poke.name))
return
end
# $PokemonBag.pbStoreItem(poke.item, 1) if poke.item != nil
myPoke = poke.species
chosenBST = calcBaseStatsSum(myPoke)
# The following excecption fields are for hardcoding the blacklisted pokemon
# without adding them in the events.
#except+=[]
except2 += [:ARCEUS, :MEW, :CELEBI, :LUGIA, :HOOH, :MEWTWO]
if pbGet(1) >= 0
species = 0
luck = rand(5) + 1
rarecap = (rand(155 + poke.level) / (1 + rand(5))) / luck
bonus = 0
while (species == 0) # Loop Start
bonus += 5 #+ de chance de pogner un bon poke a chaque loop (permet d'eviter infinite loop)
species = rand(PBSpecies.maxValue) + 1
bst = calcBaseStatsSum(species)
# Redo the loop if pokemon is too evolved for its level
#species=0 if lvl < pbGetMinimumLevel(species)# && pbGetPreviousForm(species) != species # && pbGetPreviousForm(species)!=species
# Redo the loop if the species is an exception.
species = 0 if checkifBlacklisted(species, except2) && !ignoreExcept #except2.include?(species)
#Redo loop if above BST
bstLimit = chosenBST + bonus# + $game_variables[120]
if !premiumWonderTrade
bstLimit-=50
end
species = 0 if bst > bstLimit
if species > 0 && premiumWonderTrade
species = 0 if !customSpriteExistsSpecies(species)
end
if species > 0
skipLegendaryCheck = premiumWonderTrade && rand(100) < luck
species = 0 if pokemonIsPartLegendary(species) && !$game_switches[SWITCH_BEAT_THE_LEAGUE] && !skipLegendaryCheck
end
#Redo loop if below BST - 200
species = 0 if bst < (chosenBST - 200)
# raise _INTL("{1}'s bst ist {2}, new ist {3}",myPoke,chosenBST,bst)
# species=0 if (except.include?(species) && except2.include?(species))
# use this above line instead if you wish to neither receive pokemon that YOU
# cannot trade.
if rare == true #turn on rareness
if species > 0
rareness = GameData::Species.get(species).catch_rate
species = 0 if rarecap >= rareness
end
end
end
randTrainerNames = RandTrainerNames_male + RandTrainerNames_female + RandTrainerNames_others
#tname = randTrainerNames[rand(randTrainerNames.size)] # Randomizes Trainer Names
pname = RandPokeNick[rand(RandPokeNick.size)] # Randomizes Pokemon Nicknames
#num of Wondertrade - 1
if premiumWonderTrade
$game_variables[VAR_PREMIUM_WONDERTRADE_LEFT] -= 1
else
$game_variables[VAR_STANDARD_WONDERTRADE_LEFT] -= 1
end
tname = getSpriterCreditForDexNumber(species)
tname = randTrainerNames[rand(randTrainerNames.size)] if ! tname
newpoke = pbStartTrade(pbGet(1), species, pname, tname, 0, true) # Starts the trade
#lower level by 1 to prevent abuse
if poke.level > 25
newpoke.level = poke.level - 1
end
else
return -1
end
end
def pbGRS(minBST, chosenBST, luck, rare, except2)
#pbGenerateRandomSpecies (le nom doit etre short pour etre callé dans events)
# The following excecption fields are for hardcoding the blacklisted pokemon
# without adding them in the events.
#except+=[]
except2 += []
species = 0
#luck = rand(5)+1
rarecap = (rand(rare) / (1 + rand(5))) / luck
bonus = 0
while (species == 0) # Loop Start
bonus += 5 #+ de chance de pogner un bon poke a chaque loop (permet d'eviter infinite loop)
species = rand(PBSpecies.maxValue) + 1
bst = calcBaseStatsSum(species)
# Redo the loop if pokemon is too evolved for its level
#species=0 if lvl < pbGetMinimumLevel(species)# && pbGetPreviousForm(species) != species # && pbGetPreviousForm(species)!=species
# Redo the loop if the species is an exception.
species = 0 if checkifBlacklisted(species, except2) #except2.include?(species)
#Redo loop if above BST
species = 0 if bst > chosenBST + $game_variables[120] + bonus
#Redo loop if below BST - 200
species = 0 if bst < (chosenBST - 200)
# raise _INTL("{1}'s bst ist {2}, new ist {3}",myPoke,chosenBST,bst)
# species=0 if (except.include?(species) && except2.include?(species))
# use this above line instead if you wish to neither receive pokemon that YOU
# cannot trade.
if rare == true #turn on rareness
rareness = GameData::Species.get(species).catch_rate
species = 0 if rarecap >= rareness
end
end
return species
end
#utilisé dans des events - ne pas renommer
def calcBaseStats(species)
return calcBaseStatsSum(species)
end
def calcBaseStatsSum(species)
stats = GameData::Species.get(species).base_stats
sum = 0
sum += stats[:HP]
sum += stats[:ATTACK]
sum += stats[:DEFENSE]
sum += stats[:SPECIAL_ATTACK]
sum += stats[:SPECIAL_DEFENSE]
sum += stats[:SPEED]
return sum
#
# basestatsum = $pkmn_dex[species][5][0] # HP
# basestatsum +=$pkmn_dex[species][5][1] # Attack
# basestatsum +=$pkmn_dex[species][5][2] # Defense
# basestatsum +=$pkmn_dex[species][5][3] # Speed
# basestatsum +=$pkmn_dex[species][5][4] # Special Attack
# basestatsum +=$pkmn_dex[species][5][5] # Special Defense
# return basestatsum
end
def checkifBlacklisted(species, blacklist)
return true if blacklist.include?(getBasePokemonID(species, true))
return true if blacklist.include?(getBasePokemonID(species, false))
return false
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,533 @@
EXPORT_EXCEPT_MAP_IDS= [768,722,723,724,720,809,816]
def exportAllMaps
for id in 817..830
begin
MapExporter.export(id, [:Events]) if !EXPORT_EXCEPT_MAP_IDS.include?(id)
rescue
echo "error in " +(id.to_s) +"\n"
end
end
end
def exportSpecificMaps(maps_to_export)
for id in maps_to_export
begin
MapExporter.export(id, [:Events])
rescue
echo "error in " +(id.to_s) +"\n"
end
end
end
module MapExporter
@@map = nil
@@bitmap = nil
@@helper = nil
module_function
def export(map_id, options)
map_name = pbGetMapNameFromId(map_id)
begin
@@map = $MapFactory.getMapForExport(map_id)
rescue
error("Map #{map_id} (#{map_name}) could not be loaded.")
end
@@bitmap = Bitmap.new(@@map.width * Game_Map::TILE_HEIGHT, @@map.height * Game_Map::TILE_WIDTH)
@@helper = TileDrawingHelper.fromTileset($data_tilesets[@@map.tileset_id])
set_map_options(options)
if options.include?(:Panorama)
if !nil_or_empty?(@@map.panorama_name)
draw_panorama
else
echoln "Map #{map_id} (#{map_name}) doesn't have a Panorama."
end
end
draw_reflective_tiles
draw_all_reflections(options)
draw_regular_tiles
if !draw_all_events(options)
draw_low_priority_tiles
end
draw_high_priority_tiles
draw_all_top_events(options)
if options.include?(:Fog)
if nil_or_empty?(@@map.fog_name)
echoln "Map #{map_id} (#{map_name}) doesn't have a Fog."
else
draw_fog
end
end
draw_watermark(options)
save_map_image
end
def draw_all_events(options)
include_player = options.include?(:Player) && $game_map.map_id == @@map.map_id
include_dep = options.include?(:DependentEvents) && $game_map.map_id == @@map.map_id
include_event = true#options.include?(:Events)
return false if !(include_player || include_dep || include_event)
for y in 0...@@map.height
for x in 0...@@map.width
event = nil
if include_event
event_hash = @@map.events.select {|_,e| e.x == x && e.y == y && !e.always_on_top }
event = event_hash.values.first if !event_hash.empty?
end
event = $game_player if !event && include_player && $game_player.x == x && $game_player.y == y && !$game_player.always_on_top
if include_dep
$PokemonTemp.dependentEvents.realEvents.each do |e|
next if !e || e.x != x || e.y != y
event = e
break
end
end
if event
deep_bush = @@map.bush?(x, y)
draw_event_bitmap(event, deep_bush)
end
for z in 0..2
tile_id = @@map.data[x, y, z] || 0
priority = @@map.priorities[tile_id]
next if priority == nil
next if priority != 1
tag_data = GameData::TerrainTag.try_get(@@map.terrain_tags[tile_id])
next if !tag_data || tag_data.shows_reflections
@@helper.bltTile(@@bitmap, x * Game_Map::TILE_WIDTH, y * Game_Map::TILE_HEIGHT, tile_id)
end
end
end
return true
end
def draw_all_top_events(options)
include_player = options.include?(:Player) && $game_map.map_id == @@map.map_id
include_event = options.include?(:Events)
return false if !(include_player || include_event)
for y in 0...@@map.height
for x in 0...@@map.width
event = nil
if include_event
event_hash = @@map.events.select {|_,e| e.x == x && e.y == y && e.always_on_top }
event = event_hash.values.first if !event_hash.empty?
end
event = $game_player if !event && include_player && $game_player.x == x && $game_player.y == y && $game_player.always_on_top
if event
deep_bush = @@map.bush?(x, y)
draw_event_bitmap(event, deep_bush)
end
end
end
return true
end
def draw_all_reflections(options)
include_player = options.include?(:Player) && $game_map.map_id == @@map.map_id
include_dep = options.include?(:DependentEvents) && $game_map.map_id == @@map.map_id
include_event = options.include?(:Events)
return false if !(include_player || include_dep || include_event)
for y in 0...@@map.height
for x in 0...@@map.width
dep = false
event = nil
if include_event
event_hash = @@map.events.select {|_,e| e.x == x && e.y == y }
event = event_hash.values.first if !event_hash.empty?
end
event = $game_player if !event && include_player && $game_player.x == x && $game_player.y == y
if include_dep && !event
$PokemonTemp.dependentEvents.realEvents.each do |e|
next if !e || e.x != x || e.y != y
event = e
dep = true
break
end
end
draw_event_reflection(event, dep) if event
end
end
return true
end
def draw_reflective_tiles
for y in 0...@@map.height
for x in 0...@@map.width
for z in 0..2
tile_id = @@map.data[x, y, z] || 0
tag_data = GameData::TerrainTag.try_get(@@map.terrain_tags[tile_id])
next if !tag_data || !tag_data.shows_reflections
@@helper.bltTile(@@bitmap, x * Game_Map::TILE_WIDTH, y * Game_Map::TILE_HEIGHT, tile_id)
end
end
end
end
def draw_regular_tiles
for y in 0...@@map.height
for x in 0...@@map.width
for z in 0..2
tile_id = @@map.data[x, y, z] || 0
priority = @@map.priorities[tile_id]
next if priority == nil
next if priority >= 1
tag_data = GameData::TerrainTag.try_get(@@map.terrain_tags[tile_id])
next if !tag_data || tag_data.shows_reflections
@@helper.bltTile(@@bitmap, x * Game_Map::TILE_WIDTH, y * Game_Map::TILE_HEIGHT, tile_id)
end
end
end
end
def draw_low_priority_tiles
for y in 0...@@map.height
for x in 0...@@map.width
for z in 0..2
tile_id = @@map.data[x, y, z] || 0
priority = @@map.priorities[tile_id]
next unless priority == 1
tag_data = GameData::TerrainTag.try_get(@@map.terrain_tags[tile_id])
next if !tag_data || tag_data.shows_reflections
@@helper.bltTile(@@bitmap, x * Game_Map::TILE_WIDTH, y * Game_Map::TILE_HEIGHT, tile_id)
end
end
end
end
def draw_high_priority_tiles
for y in 0...@@map.height
for x in 0...@@map.width
for z in 0..2
tile_id = @@map.data[x, y, z] || 0
priority = @@map.priorities[tile_id]
next if priority == nil
next if priority < 2
tag_data = GameData::TerrainTag.try_get(@@map.terrain_tags[tile_id])
next if !tag_data || tag_data.shows_reflections
@@helper.bltTile(@@bitmap, x * Game_Map::TILE_WIDTH, y * Game_Map::TILE_HEIGHT, tile_id)
end
end
end
end
def draw_event_bitmap(event, deep_bush)
hued = false
tile_bmp = false
if event.tile_id >= 384
bmp = pbGetTileBitmap(@@map.tileset_name, event.tile_id, event.character_hue, event.width, event.height)
hued = true
tile_bmp = true
elsif deep_bush
event.calculate_bush_depth
temp_bmp = AnimatedBitmap.new("Graphics/Characters/" + "#{event.character_name}", event.character_hue)
bushmap = BushBitmap.new(temp_bmp, false, event.bush_depth)
bmp = bushmap.bitmap.clone
bushmap.dispose
temp_bmp.dispose
hued = true
else
bmp = RPG::Cache.load_bitmap("Graphics/Characters/", "#{event.character_name}") rescue Bitmap.new(32,32)
end
if bmp
bmp = bmp.clone
bmp.hue_change(event.character_hue) if event.character_hue != 0 && !hued
final_x = (event.x * Game_Map::TILE_WIDTH) + ((event.width * Game_Map::TILE_WIDTH)/2) - bmp.width / 8
final_y = (event.y + 1) * Game_Map::TILE_HEIGHT - bmp.height / 4 + (event.bob_height)
final_y += 16 if event.character_name[/offset/i]
draw_event_shadow(event) if defined?(OWShadowSettings)
draw_surf_base(event) if event == $game_player
if !tile_bmp
ex = (bmp.width/4) * event.pattern
ey = (bmp.height/4) * (event.direction/2 - 1)
rect = Rect.new(ex, ey, bmp.width / 4, bmp.height / 4)
else
final_x += (bmp.width/8 - ((event.width * Game_Map::TILE_WIDTH)/2))
final_y += (bmp.height/4) - (Game_Map::TILE_HEIGHT * event.height)
rect = Rect.new(0, 0, bmp.width, bmp.height)
end
@@bitmap.blt(final_x, final_y, bmp, rect, event.opacity)
bmp.dispose
end
bmp = nil
end
def draw_event_shadow(event)
if OWShadowSettings::CASE_SENSITIVE_BLACKLISTS
remove = true if OWShadowSettings::SHADOWLESS_CHARACTER_NAME.any?{|e| event.character_name[/#{e}/]}
remove = true if event != $game_player && OWShadowSettings::SHADOWLESS_EVENT_NAME.any? {|e| event.name[/#{e}/]}
else
remove = true if OWShadowSettings::SHADOWLESS_CHARACTER_NAME.any?{|e| event.character_name[/#{e}/i]}
remove = true if event != $game_player && OWShadowSettings::SHADOWLESS_EVENT_NAME.any? {|e| event.name[/#{e}/i]}
end
terrain = @@map.terrain_tag(event.x, event.y)
remove = true if OWShadowSettings::SHADOWLESS_TERRAIN_NAME.any? {|e| terrain == e} if terrain
if !(nil_or_empty?(event.character_name) || event.transparent || remove)
if event == $game_player
shadow_name = OWShadowSettings::PLAYER_SHADOW_FILENAME
else
shadow_name = $~[1] if event.name[/shdw\((.*?)\)/]
end
shadow_name = OWShadowSettings::DEFAULT_SHADOW_FILENAME if nil_or_empty?(shadow_name)
shadow_bmp = RPG::Cache.load_bitmap("Graphics/Characters/Shadows/", "#{shadow_name}")
shadow_x = (event.x * Game_Map::TILE_WIDTH) + ((event.width * Game_Map::TILE_WIDTH)/2) - shadow_bmp.width/2
shadow_y = (event.y + 1) * Game_Map::TILE_HEIGHT - shadow_bmp.height + 2
@@bitmap.blt(shadow_x, shadow_y, shadow_bmp, Rect.new(0, 0, shadow_bmp.width, shadow_bmp.height), event.opacity)
shadow_bmp.dispose
end
end
def draw_event_reflection(event, forced = true)
tile_bmp = false
if event.tile_id >= 384
bmp = pbGetTileBitmap(@@map.tileset_name, event.tile_id, event.character_hue, event.width, event.height)
tile_bmp = true
else
bmp = RPG::Cache.load_bitmap("Graphics/Characters/", "#{event.character_name}") rescue Bitmap.new(32,32)
end
if bmp
bmp = bmp.clone
bmp.hue_change(event.character_hue) if event.character_hue != 0 && !tile_bmp
height = nil
fixed = false
if event == $game_player || forced
height = $PokemonGlobal.bridge
elsif event.name[/reflection/i]
height = 0
if event.name[/reflection\((\d+)\)/i]
height = $~[1].to_i || 0
else
height = $PokemonGlobal.bridge
end
end
if height
final_x = (event.x * Game_Map::TILE_WIDTH) + ((event.width * Game_Map::TILE_WIDTH)/2) - bmp.width/8
final_y = (event.y + 1) * Game_Map::TILE_HEIGHT - 3 - (event.bob_height)
final_y -= 32 if event.character_name[/offset/i]
if !tile_bmp
ex = (bmp.width/4) * event.pattern
ey = (bmp.height/4) * (event.direction/2 - 1)
rect = Rect.new(ex, ey, bmp.width/4, bmp.height/4)
else
final_x += (bmp.width/8 - ((event.width * Game_Map::TILE_WIDTH)/2))
rect = Rect.new(0, 0, bmp.width, bmp.height)
end
if height > 0
new_bmp = colorize_and_flip_bitmap(bmp, Color.new(48,96,160), 255, rect)
opacity = event.opacity
else
new_bmp = colorize_and_flip_bitmap(bmp, Color.new(224,224,224), 96, rect)
opacity = event.opacity*3/4
end
offset = [1.0, 0.95, 1.0, 1.05][(Graphics.frame_count%40)/10]
@@bitmap.stretch_blt(Rect.new(final_x, final_y, (new_bmp.width * offset), new_bmp.height), new_bmp, Rect.new(0, 0, new_bmp.width, new_bmp.height), opacity)
new_bmp.dispose
end
bmp.dispose
end
bmp = nil
end
def draw_surf_base(event)
return if !$PokemonGlobal.surfing && !$PokemonGlobal.diving
bmp = nil
if $PokemonGlobal.surfing
bmp = RPG::Cache.load_bitmap("Graphics/Characters/", "base_surf") rescue Bitmap.new(32,32)
elsif $PokemonGlobal.diving
bmp = RPG::Cache.load_bitmap("Graphics/Characters/", "base_dive") rescue Bitmap.new(32,32)
end
return if !bmp
sx = event.pattern_surf * bmp.width/4
sy = ((event.direction - 2)/2) * bmp.height/4
final_x = (event.x * Game_Map::TILE_WIDTH) + ((event.width * Game_Map::TILE_WIDTH)/2) - bmp.width/8
final_y = (event.y + 1) * Game_Map::TILE_HEIGHT - bmp.height / 4 + 16 + (event.bob_height)
@@bitmap.blt(final_x, final_y, bmp, Rect.new(sx,sy, bmp.width/4, bmp.height/4), event.opacity)
end
def draw_fog
fog_bmp = create_tiled_bitmap("Graphics/Fogs/#{@@map.fog_name}", @@map.fog_hue, @@map.fog_zoom/100.0)
@@bitmap.blt(0, 0, fog_bmp, Rect.new(0, 0, fog_bmp.width, fog_bmp.height), @@map.fog_opacity)
fog_bmp.dispose
end
def draw_panorama
pan_bmp = create_tiled_bitmap("Graphics/Panoramas/#{@@map.panorama_name}", @@map.panorama_hue)
@@bitmap.blt(0, 0, pan_bmp, Rect.new(0, 0, pan_bmp.width, pan_bmp.height))
pan_bmp.dispose
end
def draw_watermark(options)
return if !options.include?(:GameName) && !options.include?(:MapName)
map_name = nil_or_empty?(@@map.name)? pbGetMapNameFromId(@@map.map_id) : @@map.name
game_name = System.game_title
base_color = Color.new(248, 248, 248)
shadow_color = Color.new(64, 64, 64)
new_bmp = Bitmap.new(@@bitmap.width, @@bitmap.height)
if options.include?(:GameName)
if options.include?(:MapName)
pbSetSmallFont(new_bmp)
else
pbSetSystemFont(new_bmp)
end
pbDrawTextPositions(new_bmp, [[game_name, new_bmp.width - 8, new_bmp.height - 32, 1, base_color, shadow_color, true]])
new_font = (@@bitmap.text_size(map_name).height + 6)
else
new_font = 0
end
if options.include?(:MapName)
pbSetSystemFont(new_bmp)
pbDrawTextPositions(new_bmp, [[map_name, new_bmp.width - 8, new_bmp.height - new_font - 38, 1, base_color, shadow_color, true]])
end
scale_factor = get_name_scale
x = @@bitmap.width - (new_bmp.width * scale_factor) - (8 * (scale_factor - 1))
y = @@bitmap.height - (new_bmp.height * scale_factor) - (8 * (scale_factor - 1))
rect = Rect.new(x, y, (new_bmp.width * scale_factor), (new_bmp.height * scale_factor))
@@bitmap.stretch_blt(rect, new_bmp, Rect.new(0, 0, new_bmp.width, new_bmp.height))
new_bmp.dispose
end
def save_map_image
Dir.mkdir("Exported Maps/") if !safeExists?("Exported Maps/")
filestart = Time.now.strftime("[%Y-%m-%d %H-%M]")
map_name = nil_or_empty?(@@map.name)? pbGetMapNameFromId(@@map.map_id) : @@map.name
filename = sprintf("%03d - #{map_name} #{filestart}", @@map.map_id)
min_exists = 0
if safeExists?("Exported Maps/" + filename + ".png")
min_exists = 1
loop do
break if !safeExists?("Exported Maps/" + "#{filename}(#{min_exists})" + ".png")
min_exists += 1
end
end
filename = "#{filename}(#{min_exists})" if min_exists > 0
@@bitmap.to_file("Exported Maps/" + filename + ".png")
@@bitmap.dispose
@@bitmap = nil
@@map = nil
@@helper = nil
end
def create_tiled_bitmap(filename, hue, zoom = 1.0)
begin
bmp = RPG::Cache.load_bitmap("", filename)
rescue
error("Could not load image file at #{filename}")
end
new_bmp = Bitmap.new(@@map.width * Game_Map::TILE_HEIGHT, @@map.height * Game_Map::TILE_WIDTH)
i = 0
while i <= new_bmp.width
j = 0
while j <= new_bmp.height
new_bmp.stretch_blt(Rect.new(i, j, (bmp.width * zoom), (bmp.height * zoom)), bmp, Rect.new(0, 0, bmp.width, bmp.height))
j += (bmp.height * zoom)
end
i += (bmp.width * zoom)
end
bmp.dispose
new_bmp.hue_change(hue)
return new_bmp
end
def get_name_scale
scale = @@map.width/3
d = [0, -1 , -2, 2, 1, 0, -1, -2, 2, 1][scale%10]
scale = (scale + d)/10.0
return (scale < 1.0) ? 1.0 : scale
end
def colorize_and_flip_bitmap(bitmap, color, alpha = 255, rect = nil)
blankcolor = bitmap.get_pixel(0,0)
new_bmp = Bitmap.new(rect.width, rect.height)
temp_bmp = Bitmap.new(rect.width, rect.height)
temp_bmp.blt(0, 0, bitmap, rect)
for x in 0...temp_bmp.width
for y2 in 0...temp_bmp.height
y = temp_bmp.height - y2
newcolor = temp_bmp.get_pixel(x, y2)
new_bmp.set_pixel(x, y, newcolor) if newcolor
end
end
temp_bmp.dispose
shadowcolor = (color ? color : blankcolor)
colorlayer = Bitmap.new(new_bmp.width, new_bmp.height)
colorlayer.fill_rect(colorlayer.rect, shadowcolor)
new_bmp.blt(0, 0, colorlayer, colorlayer.rect, alpha)
shadowcolor = new_bmp.get_pixel(0,0)
for x in 0...new_bmp.width
for y in 0...new_bmp.height
if new_bmp.get_pixel(x,y) == shadowcolor
new_bmp.set_pixel(x, y, blankcolor)
end
end
end
colorlayer.dispose
return new_bmp
end
def set_map_options(options)
return if !options.include?(:Panorama) && !options.include?(:Fog)
@@map.events.each do |key, event|
for page in event.event.pages.reverse
c = page.condition
next if c.switch1_valid && !event.switchIsOn?(c.switch1_id)
next if c.switch2_valid && !event.switchIsOn?(c.switch2_id)
next if c.variable_valid && $game_variables[c.variable_id] < c.variable_value
if c.self_switch_valid
key = [event.map_id, event.id, c.self_switch_ch]
next if $game_self_switches[key] != true
end
page.list.each do |command|
if command.code == 204
case command.parameters[0]
when 0
next if !options.include?(:Panorama)
@@map.panorama_name = command.parameters[1] if !nil_or_empty?(@@map.panorama_name)
@@map.panorama_hue = command.parameters[2] if @@map.panorama_hue <= 0
when 1
next if !options.include?(:Fog)
@@map.fog_name = command.parameters[1] if nil_or_empty?(@@map.fog_name)
@@map.fog_hue = command.parameters[2] if @@map.fog_hue <= 0
@@map.fog_opacity = command.parameters[3] if @@map.fog_opacity < command.parameters[3]
@@map.fog_zoom = command.parameters[5]
end
elsif command.code == 205
next if !options.include?(:Fog)
@@map.fog_tone = command.parameters[0]
elsif command.code == 206
next if !options.include?(:Fog)
@@map.fog_opacity = command.parameters[0] if command.parameters[0] != 0
end
end
break
end
end
end
def error(message)
emessage = "Map Exporter EX Error:\n\n" + message
print(_INTL(emessage))
exit!
end
end
class Game_Map
def tileset_id; return @map.tileset_id; end
end
class DependentEvents
attr_accessor :realEvents
end
class Game_Character
attr_reader :event
attr_reader :always_on_top
end
class PokemonMapFactory
def getMapForExport(id)
map = Game_Map.new
map.setup(id)
return map
end
end

View File

@@ -0,0 +1,74 @@
#
# DebugMenuCommands.register("exportmap", {
# "parent" => "fieldmenu",
# "name" => _INTL("Export Map Image"),
# "description" => _INTL("Select a map and save its image as a png."),
# "effect" => proc {
# pbExportMapSelection
# }
# })
#
# def pbExportMapSelection
# loop do
# map_id = pbListScreen(_INTL("Export Map"), MapLister.new(pbDefaultMap))
# break if map_id <= 0
# commands = ["Events", "Player", "Dependent Events", "Fog", "Panorama", "Map Name", "Game Name"]
# if $game_map.map_id != map_id
# commands.delete("Player")
# commands.delete("Dependent Events")
# end
# options = pbShowMapExportOptions(commands)
# if !options.include?(:Cancel)
# ret = MapExporter.export(map_id, options)
# mapname = pbGetMapNameFromId(map_id)
# pbMessage(_INTL("Sucessfully exported map image of Map {1} ({2}) to the Exported Maps folder in the games's root.", map_id, mapname))
# return
# end
# end
# end
#
# def pbShowMapExportOptions(commands)
# sel_commands = []
# sym_commands = [:MapName, :GameName]
# cmdwindow = Window_CommandPokemonEx.new([])
# cmdwindow.z = 99999
# cmdwindow.visible = true
# cmdwindow.index = 0
# need_refresh = true
# loop do
# if need_refresh
# sel_commands = []
# commands.each_with_index do |s, i|
# cmd_sym = s.gsub(/\s+/, "").to_sym
# x = sym_commands.include?(cmd_sym) ? "[x]" : "[ ]"
# sel_commands.push(_INTL("{1} {2}",x, s))
# end
# sel_commands.push("Export Map...")
# cmdwindow.commands = sel_commands
# cmdwindow.resizeToFit(cmdwindow.commands)
# need_refresh = false
# end
# Graphics.update
# Input.update
# cmdwindow.update
# yield if block_given?
# if Input.trigger?(Input::USE)
# break if cmdwindow.index == sel_commands.length - 1
# cmd_sym = commands[cmdwindow.index].gsub(/\s+/, "").to_sym
# if sym_commands.include?(cmd_sym)
# sym_commands.delete(cmd_sym)
# else
# sym_commands.push(cmd_sym)
# end
# sym_commands.uniq!
# need_refresh = true
# elsif Input.trigger?(Input::BACK)
# sym_commands = [:Cancel]
# break
# end
# pbUpdateSceneMap
# end
# cmdwindow.dispose
# Input.update
# return sym_commands
# end

View File

@@ -0,0 +1,251 @@
#
# # ▼▲▼ XRXS50. Action-Maps XC. ▼▲▼ built 033010
# # by 桜雅 在土
#
# #======================================================
# # □ Customization points
# #======================================================
# class XRXS50
# #
# # Action-Maps - ID maps actives
# #
#
# ENABLE_FULL_ACTY_MAPS = [404,547,548,549,550,217,614,615,656]
#
# #
# # Slide descent (diagonal drop)
# #
# ENABLE_SLIDE_DESCENT = true
# #
# # true: Jump in the direction facing orientation: Jump
# # false : Jump to the direction in which the key is pressed.
# #
# JUMP_AS_KEY = true
# end
# #======================================================
# # ■ Game_Player
# #======================================================
# class Game_Player < Game_Character
# #------------------------------------------------------
# # Public Variable
# #------------------------------------------------------
# # Existing
# attr_writer :direction_fix
# attr_accessor :walk_anime
# # New
# attr_accessor :now_jumps
# attr_writer :xrxs50_direction_sidefix
# #------------------------------------------------------
# # ○Maximum jump number
# #------------------------------------------------------
# def max_jumps
# return $game_switches[890] ? 5 : 2
# end
# #------------------------------------------------------
# # ● Vers la gauche
# #------------------------------------------------------
# alias xrxs50_turn_left turn_left
# def turn_left
# if @xrxs50_direction_sidefix
# @direction = 4
# else
# turn_generic(4)
#
#
# end
# end
#
# #------------------------------------------------------
# # ● Vers la droite
# #------------------------------------------------------
# alias xrxs50_turn_right turn_right
# def turn_right
# if @xrxs50_direction_sidefix
# @direction = 6
# else
# turn_generic(6)
# end
# end
# #------------------------------------------------------
# # ● Vers le haut et le bas
# #------------------------------------------------------
# alias xrxs50_turn_up turn_up
# def turn_up
# if @xrxs50_direction_sidefix and Input.press?(Input::UP)
# return if $game_switches[890]
# @direction = 8
# xrxs50_turn_up
# else
# turn_generic(8)
# end
# end
#
# alias xrxs50_turn_down turn_down
# def turn_down
# if @xrxs50_direction_sidefix and Input.press?(Input::DOWN)
# xrxs50_turn_right
# else
# turn_generic(2)
# end
# end
#
# end
#
#
#
#
# #======================================================
# # ■ Scene_Map
# #======================================================
# class Scene_Map
# #------------------------------------------------------
# # ● Main processing
# #------------------------------------------------------
# alias xrxs50_main main
# def main
# # Check
# xrxs50_enable_check
# # Recall
# xrxs50_main
# end
# #------------------------------------------------------
# # ● Frame update
# #------------------------------------------------------
# alias xrxs50_update update
# def update
# # Recall
# xrxs50_update
# # Frame update (coordinate system update)
# if @xrxs50_enable
# update_coordinates
# end
# end
# #------------------------------------------------------
# # ○ Frame update (coordinate system update)
# #------------------------------------------------------
# def update_coordinates
# if $game_player.passable?($game_player.x,$game_player.y,2) #2
# unless $game_player.moving?
#
# if XRXS50::ENABLE_SLIDE_DESCENT and
# Input.press?(Input::RIGHT) and
# $game_player.passable?($game_player.x,$game_player.y+1,6) #1,6
# $game_player.move_lower_right
# $game_player.turn_right
# elsif XRXS50::ENABLE_SLIDE_DESCENT and
# Input.press?(Input::LEFT) and
# $game_player.passable?($game_player.x,$game_player.y+1,4)
# $game_player.move_lower_left
# $game_player.turn_left
# else
# $game_player.move_down
# end
# end
# else
# if Input.trigger?(Input::UP) && !$game_switches[890]
# @direction =8 #8
# end
# $game_player.move_down
# $game_player.walk_anime = true unless $game_player.walk_anime
# $game_player.now_jumps = 0
#
#
# end
#
# input = $game_switches[890] ? Input::UP : Input::X
# if Input.trigger?(input) and $game_player.now_jumps < $game_player.max_jumps
# if XRXS50::JUMP_AS_KEY
# direction = $game_player.direction == 4 ? -1 : 1
# #si pas jump as key
# else
# if Input.press?(Input::RIGHT)
# direction = 1
# elsif Input.press?(Input::LEFT)
# direction = -1
# else
# direction = 0
# end
# end
#
# #if $game_switches[31] == true
# # @direction =8 #8# Jump Height
# #else
# $game_player.jump(direction, -2)# Jump Height
# pbSEPlay("Jump",100)
# #end
# $game_player.now_jumps += 1 #1
# $game_player.walk_anime = false
# end
# end
#
# #------------------------------------------------------
# # ● Location movement of player
# #------------------------------------------------------
# #alias xrxs50_transfer_player transfer_player
# #def transfer_player(cancelVehicles=false)
# # #Recall
# #xrxs50_transfer_player
# # #Check
# #xrxs50_enable_check
# #end
#
# def transfer_player(cancelVehicles=true)
# $game_temp.player_transferring = false
# if cancelVehicles
# Kernel.pbCancelVehicles($game_temp.player_new_map_id)
# end
# autofade($game_temp.player_new_map_id)
# pbBridgeOff
# if $game_map.map_id != $game_temp.player_new_map_id
# $MapFactory.setup($game_temp.player_new_map_id)
# end
# $game_player.moveto($game_temp.player_new_x, $game_temp.player_new_y)
# case $game_temp.player_new_direction
# when 2
# $game_player.turn_down
# when 4
# $game_player.turn_left
# when 6
# $game_player.turn_right
# when 8
# $game_player.turn_up
# end
#
# xrxs50_enable_check
# $game_player.straighten
# $game_map.update
# disposeSpritesets
# GC.start
# createSpritesets
# if $game_temp.transition_processing
# $game_temp.transition_processing = false
# Graphics.transition(20)
# end
# $game_map.autoplay
# Graphics.frame_reset
# Input.update
# end
#
#
#
# #------------------------------------------------------
# # ○ XRXS50 Decision whether to run
# #------------------------------------------------------
# def xrxs50_enable_check
# if XRXS50::ENABLE_FULL_ACTY_MAPS.include?($game_map.map_id)
#
# $game_player.now_jumps = 0 if $game_player.now_jumps.nil?
# @xrxs50_enable = true #Gravité
# $game_player.direction_fix =true
# $game_player.xrxs50_direction_sidefix = true
#
# else
# @xrxs50_enable = false
# $game_player.direction_fix = false
# $game_player.xrxs50_direction_sidefix = false
# end
# end
# end
#
#
#