Merge branch 'dev'

This commit is contained in:
Maruno17
2022-05-19 23:23:50 +01:00
406 changed files with 234045 additions and 104268 deletions

1
.gitignore vendored
View File

@@ -17,6 +17,7 @@ RGSS*.dll
.vscode/ .vscode/
*.code-workspace *.code-workspace
.idea/ .idea/
*.mkproj
# Operating system generated files & folders # Operating system generated files & folders
.DS_Store .DS_Store

160
.rubocop.yml Normal file
View File

@@ -0,0 +1,160 @@
AllCops:
TargetRubyVersion: "3.0"
NewCops: enable
#===============================================================================
# Layout
#===============================================================================
# We don't need empty lines in methods to separate "return if"s from later code.
Layout/EmptyLineAfterGuardClause:
Enabled: false
# Extra whitespace often helps to make code more presentable.
Layout/ExtraSpacing:
AllowForAlignment: true
AllowBeforeTrailingComments: true
# In a hash with multiple values (one per line), prefer the => to be lined up
# and text to otherwise be left-aligned.
Layout/HashAlignment:
EnforcedHashRocketStyle: table
EnforcedColonStyle: table
# This means hashes and arrays are written the same way, rather than hashes
# needing to be written like { foo => bar } while arrays are like [foo, bar].
Layout/SpaceInsideHashLiteralBraces:
EnforcedStyle: no_space
#===============================================================================
# Lint
#===============================================================================
# Some methods and blocks will have unused arguments. That's fine.
Lint/UnusedBlockArgument:
Enabled: false
Lint/UnusedMethodArgument:
Enabled: false
#===============================================================================
# Metrics
#===============================================================================
# Yes, Essentials has classes/modules/methods that are too big and complex.
# That's just how it is.
Metrics:
Enabled: false
#===============================================================================
# Naming
#===============================================================================
# This cop forbids class/module names with underscores in them. Having
# underscores isn't the end of the world.
Naming/ClassAndModuleCamelCase:
Enabled: false
# Script files are given names that look reasonable in the list of script
# sections in RMXP, and are all numbered. They won't be camel_case.
Naming/FileName:
Enabled: false
#===============================================================================
# Security
#===============================================================================
# Script event conditions and script switches are eval'd, amongst other things.
Security/Eval:
Enabled: false
# Plenty of things are loaded via Marshal.
Security/MarshalLoad:
Enabled: false
#===============================================================================
# Style
#===============================================================================
# List the attr_reader/writer/accessor variables however you want.
Style/AccessorGrouping:
Enabled: false
# The assign_to_condition style looks awful, indenting loads of lines and
# increasing the separation between variable and value being assigned to it.
Style/ConditionalAssignment:
EnforcedStyle: assign_inside_condition
# Check with yard instead.
Style/Documentation:
Enabled: false
# It's a choice between format and sprintf. We already make use of sprintf and
# the translatable _ISPRINTF, so...
Style/FormatString:
EnforcedStyle: sprintf
# String literals are not frozen by default, which makes this comment a
# pointless bit of boilerplate that we neither need nor want.
Style/FrozenStringLiteralComment:
Enabled: false
# RMXP and Essentials use lots of global variables.
Style/GlobalVars:
Enabled: false
# Mixing the styles within a hash just looks silly.
Style/HashSyntax:
EnforcedStyle: no_mixed_keys
# unless just adds mental gymnastics trying to figure out what it actually
# means. I much prefer if !something.
Style/NegatedIf:
Enabled: false
# .zero?, .positive? and .negative? are more wordy than == 0, > 0 and < 0. They
# also aren't consistent with other value comparisons, e.g. x > 42.
Style/NumericPredicate:
EnforcedStyle: comparison
# Following this just means that calls to an affected method need to know what
# that method calls its parameters, which is ridiculous. Keep things short and
# simple.
Style/OptionalBooleanParameter:
Enabled: false
# has_key? and has_value? are far more readable than key? and value?
Style/PreferredHashMethods:
Enabled: false
# Explicit returns help to show whether a method returns a value.
Style/RedundantReturn:
Enabled: false
# Enforcing the names of variables? To single letter ones? Just no.
Style/SingleLineBlockParams:
Enabled: false
# Single line methods use up less space, and they're easier to list next to each
# other and see that they behave similarly.
Style/SingleLineMethods:
Enabled: false
# Single quotes being faster is hardly measurable and only affects parse time.
# Enforcing double quotes reduces the times where you need to change them
# when introducing an interpolation or an apostrophe. Use single quotes only if
# their semantics are needed.
Style/StringLiterals:
EnforcedStyle: double_quotes
# This cop requires arrays of symbols/text to be written like %i[a b c]. We
# don't need that nonsense. ["a", "b", "c"] is clearer and introduces no
# additional syntax to confuse people.
Style/SymbolArray:
EnforcedStyle: brackets
Style/WordArray:
EnforcedStyle: brackets
# Patentheses around the condition in a ternary operator helps to differentiate
# it from the true/false results.
Style/TernaryParentheses:
EnforcedStyle: require_parentheses

View File

@@ -1,12 +1,12 @@
#==============================================================================# #==============================================================================#
# Pokémon Essentials # # Pokémon Essentials #
# Version 19.1.dev # # Version 20 #
# https://github.com/Maruno17/pokemon-essentials # # https://github.com/Maruno17/pokemon-essentials #
#==============================================================================# #==============================================================================#
module Settings module Settings
# The version of your game. It has to adhere to the MAJOR.MINOR.PATCH format. # The version of your game. It has to adhere to the MAJOR.MINOR.PATCH format.
GAME_VERSION = '1.0.0' GAME_VERSION = "1.0.0"
# The generation that the battle system follows. Used throughout the battle # The generation that the battle system follows. Used throughout the battle
# scripts, and also by some other settings which are used in and out of battle # scripts, and also by some other settings which are used in and out of battle
@@ -14,38 +14,10 @@ module Settings
# Note that this isn't perfect. Essentials doesn't accurately replicate every # Note that this isn't perfect. Essentials doesn't accurately replicate every
# single generation's mechanics. It's considered to be good enough. Only # single generation's mechanics. It's considered to be good enough. Only
# generations 5 and later are reasonably supported. # generations 5 and later are reasonably supported.
MECHANICS_GENERATION = 7 MECHANICS_GENERATION = 8
#============================================================================= #=============================================================================
# The default screen width (at a scale of 1.0).
SCREEN_WIDTH = 512
# The default screen height (at a scale of 1.0).
SCREEN_HEIGHT = 384
# The default screen scale factor. Possible values are 0.5, 1.0, 1.5 and 2.0.
SCREEN_SCALE = 1.0
#=============================================================================
# The maximum level Pokémon can reach.
MAXIMUM_LEVEL = 100
# The level of newly hatched Pokémon.
EGG_LEVEL = 1
# The odds of a newly generated Pokémon being shiny (out of 65536).
SHINY_POKEMON_CHANCE = (MECHANICS_GENERATION >= 6) ? 16 : 8
# The odds of a wild Pokémon/bred egg having Pokérus (out of 65536).
POKERUS_CHANCE = 3
# Whether a bred baby Pokémon can inherit any TM/HM moves from its father. It
# can never inherit TM/HM moves from its mother.
BREEDING_CAN_INHERIT_MACHINE_MOVES = (MECHANICS_GENERATION <= 5)
# Whether a bred baby Pokémon can inherit egg moves from its mother. It can
# always inherit egg moves from its father.
BREEDING_CAN_INHERIT_EGG_MOVES_FROM_MOTHER = (MECHANICS_GENERATION >= 6)
#=============================================================================
# The amount of money the player starts the game with.
INITIAL_MONEY = 3000
# The maximum amount of money the player can have. # The maximum amount of money the player can have.
MAX_MONEY = 999_999 MAX_MONEY = 999_999
# The maximum number of Game Corner coins the player can have. # The maximum number of Game Corner coins the player can have.
@@ -58,25 +30,21 @@ module Settings
MAX_PLAYER_NAME_SIZE = 10 MAX_PLAYER_NAME_SIZE = 10
# The maximum number of Pokémon that can be in the party. # The maximum number of Pokémon that can be in the party.
MAX_PARTY_SIZE = 6 MAX_PARTY_SIZE = 6
# The maximum level Pokémon can reach.
#============================================================================= MAXIMUM_LEVEL = 100
# The level of newly hatched Pokémon.
# A set of arrays each containing a trainer type followed by a Global Variable EGG_LEVEL = 1
# number. If the variable isn't set to 0, then all trainers with the # The odds of a newly generated Pokémon being shiny (out of 65536).
# associated trainer type will be named as whatever is in that variable. SHINY_POKEMON_CHANCE = (MECHANICS_GENERATION >= 6) ? 16 : 8
RIVAL_NAMES = [ # Whether super shininess is enabled (uses a different shiny animation).
[:RIVAL1, 12], SUPER_SHINY = (MECHANICS_GENERATION >= 8)
[:RIVAL2, 12], # The odds of a wild Pokémon/bred egg having Pokérus (out of 65536).
[:CHAMPION, 12] POKERUS_CHANCE = 3
]
#============================================================================= #=============================================================================
# Whether outdoor maps should be shaded according to the time of day. # Whether outdoor maps should be shaded according to the time of day.
TIME_SHADING = true TIME_SHADING = true
#=============================================================================
# Whether poisoned Pokémon will lose HP while walking around in the field. # Whether poisoned Pokémon will lose HP while walking around in the field.
POISON_IN_FIELD = (MECHANICS_GENERATION <= 4) POISON_IN_FIELD = (MECHANICS_GENERATION <= 4)
# Whether poisoned Pokémon will faint while walking around in the field # Whether poisoned Pokémon will faint while walking around in the field
@@ -94,9 +62,26 @@ module Settings
# The ID of the common event that runs when the player stops fishing (runs # The ID of the common event that runs when the player stops fishing (runs
# instead of showing the reeling in animation). # instead of showing the reeling in animation).
FISHING_END_COMMON_EVENT = -1 FISHING_END_COMMON_EVENT = -1
# Whether Pokémon in the Day Care gain Exp for each step the player takes.
#============================================================================= # This is true for the Day Care and false for the Pokémon Nursery, both of
# which use the same code in Essentials.
DAY_CARE_POKEMON_GAIN_EXP_FROM_WALKING = (MECHANICS_GENERATION <= 6)
# Whether two Pokémon in the Day Care can learn egg moves from each other if
# they are the same species.
DAY_CARE_POKEMON_CAN_SHARE_EGG_MOVES = (MECHANICS_GENERATION >= 8)
# Whether a bred baby Pokémon can inherit any TM/TR/HM moves from its father.
# It can never inherit TM/TR/HM moves from its mother.
BREEDING_CAN_INHERIT_MACHINE_MOVES = (MECHANICS_GENERATION <= 5)
# Whether a bred baby Pokémon can inherit egg moves from its mother. It can
# always inherit egg moves from its father.
BREEDING_CAN_INHERIT_EGG_MOVES_FROM_MOTHER = (MECHANICS_GENERATION >= 6)
# Whether the Pokédex entry of a newly owned species will be shown after it
# hatches from an egg, after it evolves and after obtaining it from a trade,
# in addition to after catching it in battle.
SHOW_NEW_SPECIES_POKEDEX_ENTRY_MORE_OFTEN = (MECHANICS_GENERATION >= 7)
# Whether you get 1 Premier Ball for every 10 of any kind of Poké Ball bought
# at once (true), or 1 Premier Ball for buying 10+ Poké Balls (false).
MORE_BONUS_PREMIER_BALLS = (MECHANICS_GENERATION >= 8)
# The number of steps allowed before a Safari Zone game is over (0=infinite). # The number of steps allowed before a Safari Zone game is over (0=infinite).
SAFARI_STEPS = 600 SAFARI_STEPS = 600
# The number of seconds a Bug Catching Contest lasts for (0=infinite). # The number of seconds a Bug Catching Contest lasts for (0=infinite).
@@ -104,13 +89,60 @@ module Settings
#============================================================================= #=============================================================================
# Pairs of map IDs, where the location signpost isn't shown when moving from # If a move taught by a TM/HM/TR replaces another move, this setting is
# one of the maps in a pair to the other (and vice versa). Useful for single # whether the machine's move retains the replaced move's PP (true), or whether
# long routes/towns that are spread over multiple maps. # the machine's move has full PP (false).
# e.g. [4,5,16,17,42,43] will be map pairs 4,5 and 16,17 and 42,43. TAUGHT_MACHINES_KEEP_OLD_PP = (MECHANICS_GENERATION == 5)
# Moving between two maps that have the exact same name won't show the # Whether the Move Relearner can also teach egg moves that the Pokémon knew
# location signpost anyway, so you don't need to list those maps here. # when it hatched and moves that the Pokémon was once taught by a TR. Moves
NO_SIGNPOSTS = [] # from the Pokémon's level-up moveset of the same or a lower level than the
# Pokémon can always be relearned.
MOVE_RELEARNER_CAN_TEACH_MORE_MOVES = (MECHANICS_GENERATION >= 6)
# Whether various HP-healing items heal the amounts they do in Gen 7+ (true)
# or in earlier Generations (false).
REBALANCED_HEALING_ITEM_AMOUNTS = (MECHANICS_GENERATION >= 7)
# Whether Rage Candy Bar acts as a Full Heal (true) or a Potion (false).
RAGE_CANDY_BAR_CURES_STATUS_PROBLEMS = (MECHANICS_GENERATION >= 7)
# Whether vitamins can add EVs no matter how many that stat already has in it
# (true), or whether they can't make that stat's EVs greater than 100 (false).
NO_VITAMIN_EV_CAP = (MECHANICS_GENERATION >= 8)
# Whether Rare Candy can be used on a Pokémon that is already at its maximum
# level if it is able to evolve by level-up (if so, triggers that evolution).
RARE_CANDY_USABLE_AT_MAX_LEVEL = (MECHANICS_GENERATION >= 8)
# Whether the player can choose how many of an item to use at once on a
# Pokémon. This applies to Exp-changing items (Rare Candy, Exp Candies) and
# EV-changing items (vitamins, feathers, EV-lowering berries).
USE_MULTIPLE_STAT_ITEMS_AT_ONCE = (MECHANICS_GENERATION >= 8)
#=============================================================================
# Whether Repel uses the level of the first Pokémon in the party regardless of
# its HP (true), or it uses the level of the first unfainted Pokémon (false).
REPEL_COUNTS_FAINTED_POKEMON = (MECHANICS_GENERATION >= 6)
# Whether more abilities affect whether wild Pokémon appear, which Pokémon
# they are, etc.
MORE_ABILITIES_AFFECT_WILD_ENCOUNTERS = (MECHANICS_GENERATION >= 8)
# Whether the Black/White Flutes will raise/lower the levels of wild Pokémon
# respectively (true), or will lower/raise the wild encounter rate
# respectively (false).
FLUTES_CHANGE_WILD_ENCOUNTER_LEVELS = (MECHANICS_GENERATION >= 6)
# Whether shiny wild Pokémon are more likely to appear if the player has
# previously defeated/caught lots of other Pokémon of the same species.
HIGHER_SHINY_CHANCES_WITH_NUMBER_BATTLED = (MECHANICS_GENERATION >= 8)
# Whether overworld weather can set the default terrain effect in battle.
# Storm weather sets Electric Terrain, and fog weather sets Misty Terrain.
OVERWORLD_WEATHER_SETS_BATTLE_TERRAIN = (MECHANICS_GENERATION >= 8)
#=============================================================================
# A set of arrays each containing a trainer type followed by a Game Variable
# number. If the Variable isn't set to 0, then all trainers with the
# associated trainer type will be named as whatever is in that Variable.
RIVAL_NAMES = [
[:RIVAL1, 12],
[:RIVAL2, 12],
[:CHAMPION, 12]
]
#============================================================================= #=============================================================================
@@ -135,34 +167,9 @@ module Settings
#============================================================================= #=============================================================================
# If a move taught by a TM/HM/TR replaces another move, this setting is # The names of each pocket of the Bag.
# whether the machine's move retains the replaced move's PP (true), or whether
# the machine's move has full PP (false).
TAUGHT_MACHINES_KEEP_OLD_PP = (MECHANICS_GENERATION == 5)
# Whether the Black/White Flutes will raise/lower the levels of wild Pokémon
# respectively (true), or will lower/raise the wild encounter rate
# respectively (false).
FLUTES_CHANGE_WILD_ENCOUNTER_LEVELS = (MECHANICS_GENERATION >= 6)
# Whether Repel uses the level of the first Pokémon in the party regardless of
# its HP (true), or it uses the level of the first unfainted Pokémon (false).
REPEL_COUNTS_FAINTED_POKEMON = (MECHANICS_GENERATION >= 6)
# Whether Rage Candy Bar acts as a Full Heal (true) or a Potion (false).
RAGE_CANDY_BAR_CURES_STATUS_PROBLEMS = (MECHANICS_GENERATION >= 7)
#=============================================================================
# The name of the person who created the Pokémon storage system.
def self.storage_creator_name
return _INTL("Bill")
end
# The number of boxes in Pokémon storage.
NUM_STORAGE_BOXES = 30
#=============================================================================
# The names of each pocket of the Bag. Ignore the first entry ("").
def self.bag_pocket_names def self.bag_pocket_names
return ["", return [
_INTL("Items"), _INTL("Items"),
_INTL("Medicine"), _INTL("Medicine"),
_INTL("Poké Balls"), _INTL("Poké Balls"),
@@ -173,14 +180,20 @@ module Settings
_INTL("Key Items") _INTL("Key Items")
] ]
end end
# The maximum number of slots per pocket (-1 means infinite number). Ignore # The maximum number of slots per pocket (-1 means infinite number).
# the first number (0). BAG_MAX_POCKET_SIZE = [-1, -1, -1, -1, -1, -1, -1, -1]
BAG_MAX_POCKET_SIZE = [0, -1, -1, -1, -1, -1, -1, -1, -1] # Whether each pocket in turn auto-sorts itself by item ID number.
BAG_POCKET_AUTO_SORT = [false, false, false, true, true, false, false, false]
# The maximum number of items each slot in the Bag can hold. # The maximum number of items each slot in the Bag can hold.
BAG_MAX_PER_SLOT = 999 BAG_MAX_PER_SLOT = 999
# Whether each pocket in turn auto-sorts itself by item ID number. Ignore the
# first entry (the 0). #=============================================================================
BAG_POCKET_AUTO_SORT = [0, false, false, false, true, true, false, false, false]
# The number of boxes in Pokémon storage.
NUM_STORAGE_BOXES = 40
# Whether putting a Pokémon into Pokémon storage will heal it. IF false, they
# are healed by the Recover All: Entire Party event command (at Poké Centers).
HEAL_STORED_POKEMON = (MECHANICS_GENERATION >= 8)
#============================================================================= #=============================================================================
@@ -189,16 +202,16 @@ module Settings
# Dex list to view if more than one is available (false). # Dex list to view if more than one is available (false).
USE_CURRENT_REGION_DEX = false USE_CURRENT_REGION_DEX = false
# The names of the Pokédex lists, in the order they are defined in the PBS # The names of the Pokédex lists, in the order they are defined in the PBS
# file "regionaldexes.txt". The last name is for the National Dex and is added # file "regional_dexes.txt". The last name is for the National Dex and is
# onto the end of this array (remember that you don't need to use it). This # added onto the end of this array (remember that you don't need to use it).
# array's order is also the order of $Trainer.pokedex.unlocked_dexes, which # This array's order is also the order of $player.pokedex.unlocked_dexes,
# records which Dexes have been unlocked (the first is unlocked by default). # which records which Dexes have been unlocked (the first is unlocked by
# If an entry is just a name, then the region map shown in the Area page while # default). If an entry is just a name, then the region map shown in the Area
# viewing that Dex list will be the region map of the region the player is # page while viewing that Dex list will be the region map of the region the
# currently in. The National Dex entry should always behave like this. # player is currently in. The National Dex entry should always behave like
# If an entry is of the form [name, number], then the number is a region # this. If an entry is of the form [name, number], then the number is a region
# number. That region's map will appear in the Area page while viewing that # number, and that region's map will appear in the Area page while viewing
# Dex list, no matter which region the player is currently in. # that Dex list, no matter which region the player is currently in.
def self.pokedex_names def self.pokedex_names
return [ return [
[_INTL("Kanto Pokédex"), 0], [_INTL("Kanto Pokédex"), 0],
@@ -231,6 +244,20 @@ module Settings
[0, 52, 20, 14, "mapHiddenFaraday", false] [0, 52, 20, 14, "mapHiddenFaraday", false]
] ]
# Whether the player can use Fly while looking at the Town Map. This is only
# allowed if the player can use Fly normally.
CAN_FLY_FROM_TOWN_MAP = true
#=============================================================================
# Pairs of map IDs, where the location signpost isn't shown when moving from
# one of the maps in a pair to the other (and vice versa). Useful for single
# long routes/towns that are spread over multiple maps.
# e.g. [4,5,16,17,42,43] will be map pairs 4,5 and 16,17 and 42,43.
# Moving between two maps that have the exact same name won't show the
# location signpost anyway, so you don't need to list those maps here.
NO_SIGNPOSTS = []
#============================================================================= #=============================================================================
# A list of maps used by roaming Pokémon. Each map has an array of other maps # A list of maps used by roaming Pokémon. Each map has an array of other maps
@@ -297,6 +324,10 @@ module Settings
# The Game Switch which, while ON, makes all Pokémon created considered to be # The Game Switch which, while ON, makes all Pokémon created considered to be
# met via a fateful encounter. # met via a fateful encounter.
FATEFUL_ENCOUNTER_SWITCH = 32 FATEFUL_ENCOUNTER_SWITCH = 32
# The Game Switch which, while ON, disables the effect of the Pokémon Box Link
# and prevents the player from accessing Pokémon storage via the party screen
# with it.
DISABLE_BOX_LINK_SWITCH = 35
#============================================================================= #=============================================================================
@@ -323,6 +354,15 @@ module Settings
#============================================================================= #=============================================================================
# The default screen width (at a scale of 1.0).
SCREEN_WIDTH = 512
# The default screen height (at a scale of 1.0).
SCREEN_HEIGHT = 384
# The default screen scale factor. Possible values are 0.5, 1.0, 1.5 and 2.0.
SCREEN_SCALE = 1.0
#=============================================================================
# An array of available languages in the game, and their corresponding message # An array of available languages in the game, and their corresponding message
# file in the Data folder. Edit only if you have 2 or more languages to choose # file in the Data folder. Edit only if you have 2 or more languages to choose
# from. # from.
@@ -393,6 +433,6 @@ end
# DO NOT EDIT THESE! # DO NOT EDIT THESE!
module Essentials module Essentials
VERSION = "19.1.dev" VERSION = "20"
ERROR_TEXT = "" ERROR_TEXT = ""
end end

View File

@@ -7,18 +7,16 @@ module PBDebug
rescue rescue
PBDebug.log("") PBDebug.log("")
PBDebug.log("**Exception: #{$!.message}") PBDebug.log("**Exception: #{$!.message}")
PBDebug.log("#{$!.backtrace.inspect}") PBDebug.log($!.backtrace.inspect.to_s)
PBDebug.log("") PBDebug.log("")
# if $INTERNAL pbPrintException($!) # if $INTERNAL
pbPrintException($!)
# end
PBDebug.flush PBDebug.flush
end end
end end
def self.flush def self.flush
if $DEBUG && $INTERNAL && @@log.length > 0 if $DEBUG && $INTERNAL && @@log.length > 0
File.open("Data/debuglog.txt", "a+b") { |f| f.write("#{@@log}") } File.open("Data/debuglog.txt", "a+b") { |f| f.write(@@log.to_s) }
end end
@@log.clear @@log.clear
end end
@@ -26,9 +24,7 @@ module PBDebug
def self.log(msg) def self.log(msg)
if $DEBUG && $INTERNAL if $DEBUG && $INTERNAL
@@log.push("#{msg}\r\n") @@log.push("#{msg}\r\n")
# if @@log.length>1024 PBDebug.flush # if @@log.length > 1024
PBDebug.flush
# end
end end
end end

View File

@@ -1,26 +1,23 @@
# To use the console, use the executable explicitly built # To use the console, use the executable explicitly built with the console
# with the console enabled on Windows. On Linux and macOS, # enabled on Windows. On Linux and macOS, just launch the executable directly
# just launch the executable directly from a terminal. # from a terminal.
module Console module Console
def self.setup_console def self.setup_console
return unless $DEBUG return unless $DEBUG
echoln "GPU Cache Max: #{Bitmap.max_size}" echoln "GPU Cache Max: #{Bitmap.max_size}"
echoln "--------------------------------" echoln "-------------------------------------------------------------------------------"
echoln "#{System.game_title} Output Window" echoln "#{System.game_title} Output Window"
echoln "--------------------------------" echoln "-------------------------------------------------------------------------------"
echoln "If you are seeing this window, you are running" echoln "If you can see this window, you are running the game in Debug Mode. This means"
echoln "#{System.game_title} in Debug Mode. This means" echoln "that you're either playing a debug version of the game, or you're playing from"
echoln "that you're either playing a Debug Version, or" echoln "within RPG Maker XP."
echoln "you are playing from within RPG Maker XP."
echoln "" echoln ""
echoln "Closing this window will close the game. If" echoln "Closing this window will close the game. If you want to get rid of this window,"
echoln "you want to get rid of this window, run the" echoln "run the program from the Shell, or download a release version of the game."
echoln "program from the Shell, or download a Release"
echoln "version."
echoln "" echoln ""
echoln "--------------------------------" echoln "-------------------------------------------------------------------------------"
echoln "Debug Output:" echoln "Debug Output:"
echoln "--------------------------------" echoln "-------------------------------------------------------------------------------"
echoln "" echoln ""
end end
@@ -44,9 +41,187 @@ module Kernel
end end
def echoln(string) def echoln(string)
echo(string) echo string
echo("\r\n") echo "\r\n"
end end
end end
Console.setup_console Console.setup_console
#===============================================================================
# Console message formatting
#===============================================================================
module Console
module_function
#-----------------------------------------------------------------------------
# echo string into console (example shorthand for common options)
#-----------------------------------------------------------------------------
# heading 1
def echo_h1(msg)
echoln markup_style("*** #{msg} ***", text: :brown)
echoln ""
end
# heading 2
def echo_h2(msg, **options)
echoln markup_style(msg, **options)
echoln ""
end
# heading 3
def echo_h3(msg)
echoln markup(msg)
echoln ""
end
# list item
def echo_li(msg, pad = 0, color = :brown)
echo markup_style(" -> ", text: color)
pad = (pad - msg.length) > 0 ? "." * (pad - msg.length) : ""
echo markup(msg + pad)
end
# list item with line break after
def echoln_li(msg, pad = 0, color = :brown)
self.echo_li(msg, pad, color)
echoln ""
end
# paragraph with markup
def echo_p(msg)
echoln markup(msg)
end
# warning message
def echo_warn(msg)
echoln markup_style("WARNING: #{msg}", text: :yellow)
end
# error message
def echo_error(msg)
echoln markup_style("ERROR: #{msg}", text: :light_red)
end
# status output
def echo_status(status)
if status
echoln markup_style("OK", text: :green)
else
echoln markup_style("FAIL", text: :red)
end
end
# completion output
def echo_done(status)
if status
echoln markup_style("done", text: :green)
else
echoln markup_style("error", text: :red)
end
end
#-----------------------------------------------------------------------------
# Markup options
#-----------------------------------------------------------------------------
def string_colors
{
default: "38", black: "30", red: "31", green: "32", brown: "33",
blue: "34", purple: "35", cyan: "36", gray: "37",
dark_gray: "1;30", light_red: "1;31", light_green: "1;32", yellow: "1;33",
light_blue: "1;34", light_purple: "1;35", light_cyan: "1;36", white: "1;37"
}
end
def background_colors
{
default: "0", black: "40", red: "41", green: "42", brown: "43",
blue: "44", purple: "45", cyan: "46", gray: "47",
dark_gray: "100", light_red: "101", light_green: "102", yellow: "103",
light_blue: "104", light_purple: "105", light_cyan: "106", white: "107"
}
end
def font_options
{
bold: "1", dim: "2", italic: "3", underline: "4", reverse: "7",
hidden: "8"
}
end
# Text markup that turns text between them a certain color
def markup_colors
{
"`" => :cyan, '"' => :purple, "'" => :purple, "$" => :green, "~" => :red
}
end
def markup_options
{
"__" => :underline, "*" => :bold, "|" => :italic
}
end
# apply console coloring
def markup_style(string, text: :default, bg: :default, **options)
# get colors
code_text = string_colors[text]
code_bg = background_colors[bg]
# get options
options_pool = options.select { |key, val| font_options.key?(key) && val }
markup_pool = options_pool.keys.map { |opt| font_options[opt] }.join(";").squeeze
# return formatted string
"\e[#{code_bg};#{markup_pool};#{code_text}m#{string}\e[0m".squeeze(";")
end
#-----------------------------------------------------------------------------
# Perform markup on text
#-----------------------------------------------------------------------------
def markup_all_options
@markup_all_options ||= markup_colors.merge(markup_options)
end
def markup_component(string, component, key, options)
# trim inner markup content
l = key.length
trimmed = component[l...-l]
# merge markup options
options[trimmed] = {} unless options[trimmed]
options[trimmed].deep_merge!({}.tap do |new_opt|
new_opt[:text] = markup_colors[key] if markup_colors.key?(key)
new_opt[markup_options[key]] = true if markup_options.key?(key)
end)
# remove markup from input string
string.gsub!(component, trimmed)
# return output
return string, options
end
def markup_breakdown(string, options = {})
# iterate through all options
markup_all_options.each_key do |key|
# ensure escape
key_char = key.chars.map { |c| "\\#{c}" }.join
# define regex
regex = "#{key_char}.*?#{key_char}"
# go through matches
string.scan(/#{regex}/).each do |component|
return *markup_breakdown(*markup_component(string, component, key, options))
end
end
# return output
return string, options
end
def markup(string)
# get a breakdown of all markup options
string, options = markup_breakdown(string)
# iterate through each option and apply
options.each do |key, opt|
string.gsub!(key, markup_style(key, **opt))
end
# return string
return string
end
end

View File

@@ -4,12 +4,23 @@
class Reset < Exception class Reset < Exception
end end
class EventScriptError < Exception
attr_accessor :event_message
def initialize(message)
super(nil)
@event_message = message
end
end
def pbGetExceptionMessage(e, _script = "") def pbGetExceptionMessage(e, _script = "")
return e.event_message.dup if e.is_a?(EventScriptError) # Message with map/event ID generated elsewhere
emessage = e.message.dup emessage = e.message.dup
emessage.force_encoding(Encoding::UTF_8) emessage.force_encoding(Encoding::UTF_8)
if e.is_a?(Hangup) case e
when Hangup
emessage = "The script is taking too long. The game will restart." emessage = "The script is taking too long. The game will restart."
elsif e.is_a?(Errno::ENOENT) when Errno::ENOENT
filename = emessage.sub("No such file or directory - ", "") filename = emessage.sub("No such file or directory - ", "")
emessage = "File #{filename} not found." emessage = "File #{filename} not found."
end end
@@ -18,27 +29,26 @@ def pbGetExceptionMessage(e,_script="")
end end
def pbPrintException(e) def pbPrintException(e)
emessage = ""
if $EVENTHANGUPMSG && $EVENTHANGUPMSG!=""
emessage = $EVENTHANGUPMSG # Message with map/event ID generated elsewhere
$EVENTHANGUPMSG = nil
else
emessage = pbGetExceptionMessage(e) emessage = pbGetExceptionMessage(e)
end
# begin message formatting # begin message formatting
message = "[Pokémon Essentials version #{Essentials::VERSION}]\r\n" message = "[Pokémon Essentials version #{Essentials::VERSION}]\r\n"
message += "#{Essentials::ERROR_TEXT}\r\n" # For third party scripts to add to message += "#{Essentials::ERROR_TEXT}\r\n" # For third party scripts to add to
if !e.is_a?(EventScriptError)
message += "Exception: #{e.class}\r\n" message += "Exception: #{e.class}\r\n"
message += "Message: #{emessage}\r\n" message += "Message: "
end
message += emessage
# show last 10/25 lines of backtrace # show last 10/25 lines of backtrace
message += "\r\nBacktrace:\r\n" if !e.is_a?(EventScriptError)
btrace = "" message += "\r\n\r\nBacktrace:\r\n"
backtrace_text = ""
if e.backtrace if e.backtrace
maxlength = ($INTERNAL) ? 25 : 10 maxlength = ($INTERNAL) ? 25 : 10
e.backtrace[0, maxlength].each { |i| btrace += "#{i}\r\n" } e.backtrace[0, maxlength].each { |i| backtrace_text += "#{i}\r\n" }
end
backtrace_text.gsub!(/Section(\d+)/) { $RGSS_SCRIPTS[$1.to_i][1] } rescue nil
message += backtrace_text
end end
btrace.gsub!(/Section(\d+)/) { $RGSS_SCRIPTS[$1.to_i][1] } rescue nil
message += btrace
# output to log # output to log
errorlog = "errorlog.txt" errorlog = "errorlog.txt"
errorlog = RTP.getSaveFileName("errorlog.txt") if (Object.const_defined?(:RTP) rescue false) errorlog = RTP.getSaveFileName("errorlog.txt") if (Object.const_defined?(:RTP) rescue false)
@@ -55,7 +65,7 @@ def pbPrintException(e)
print("#{message}\r\nThis exception was logged in #{errorlogline}.\r\nHold Ctrl when closing this message to copy it to the clipboard.") print("#{message}\r\nThis exception was logged in #{errorlogline}.\r\nHold Ctrl when closing this message to copy it to the clipboard.")
# Give a ~500ms coyote time to start holding Control # Give a ~500ms coyote time to start holding Control
t = System.delta t = System.delta
until (System.delta - t) >= 500000 until (System.delta - t) >= 500_000
Input.update Input.update
if Input.press?(Input::CTRL) if Input.press?(Input::CTRL)
Input.clipboard = message Input.clipboard = message

View File

@@ -8,15 +8,14 @@ module Deprecation
# @param removal_version [String] version the method is removed in # @param removal_version [String] version the method is removed in
# @param alternative [String] preferred alternative method # @param alternative [String] preferred alternative method
def warn_method(method_name, removal_version = nil, alternative = nil) def warn_method(method_name, removal_version = nil, alternative = nil)
text = _INTL('WARN: usage of deprecated method "{1}" or its alias.', method_name) text = _INTL('Usage of deprecated method "{1}" or its alias.', method_name)
unless removal_version.nil? unless removal_version.nil?
text += _INTL("\nThe method is slated to be"\ text += "\r\n" + _INTL("The method is slated to be removed in Essentials {1}.", removal_version)
" removed in Essentials {1}.", removal_version)
end end
unless alternative.nil? unless alternative.nil?
text += _INTL("\nUse \"{1}\" instead.", alternative) text += "\r\n" + _INTL("Use \"{1}\" instead.", alternative)
end end
echoln text Console.echo_warn text
end end
end end
@@ -41,11 +40,11 @@ class Module
raise ArgumentError, "#{class_name} does not have method #{aliased_method} defined" raise ArgumentError, "#{class_name} does not have method #{aliased_method} defined"
end end
delimiter = class_method ? '.' : '#' delimiter = class_method ? "." : "#"
target.define_method(name) do |*args, **kvargs| target.define_method(name) do |*args, **kvargs|
alias_name = format('%s%s%s', class_name, delimiter, name) alias_name = sprintf("%s%s%s", class_name, delimiter, name)
aliased_method_name = format('%s%s%s', class_name, delimiter, aliased_method) aliased_method_name = sprintf("%s%s%s", class_name, delimiter, aliased_method)
Deprecation.warn_method(alias_name, removal_in, aliased_method_name) Deprecation.warn_method(alias_name, removal_in, aliased_method_name)
method(aliased_method).call(*args, **kvargs) method(aliased_method).call(*args, **kvargs)
end end

View File

@@ -1,20 +1,31 @@
# Using mkxp-z v2.2.0 - https://gitlab.com/mkxp-z/mkxp-z/-/releases/v2.2.0 # Using mkxp-z v2.3.1 - https://gitlab.com/mkxp-z/mkxp-z/-/releases/v2.3.1
$VERBOSE = nil $VERBOSE = nil
Font.default_shadow = false if Font.respond_to?(:default_shadow) Font.default_shadow = false if Font.respond_to?(:default_shadow)
Graphics.frame_rate = 40 Graphics.frame_rate = 40
Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::UTF_8
def pbSetWindowText(string) def pbSetWindowText(string)
System.set_window_title(string || System.game_title) System.set_window_title(string || System.game_title)
end end
class Bitmap class Bitmap
attr_accessor :text_offset_y
alias mkxp_draw_text draw_text unless method_defined?(:mkxp_draw_text) alias mkxp_draw_text draw_text unless method_defined?(:mkxp_draw_text)
def draw_text(x, y, width, height, text, align = 0) def draw_text(x, y, width, height = nil, text = "", align = 0)
if x.is_a?(Rect)
x.y -= (@text_offset_y || 0)
# rect, string & alignment
mkxp_draw_text(x, y, width)
else
y -= (@text_offset_y || 0)
height = text_size(text).height height = text_size(text).height
mkxp_draw_text(x, y, width, height, text, align) mkxp_draw_text(x, y, width, height, text, align)
end end
end end
end
module Graphics module Graphics
def self.delta_s def self.delta_s

View File

@@ -9,7 +9,7 @@ class Dir
files = [] files = []
filters = [filters] if !filters.is_a?(Array) filters = [filters] if !filters.is_a?(Array)
self.chdir(dir) do self.chdir(dir) do
for filter in filters filters.each do |filter|
self.glob(filter) { |f| files.push(full ? (dir + "/" + f) : f) } self.glob(filter) { |f| files.push(full ? (dir + "/" + f) : f) }
end end
end end
@@ -22,7 +22,7 @@ class Dir
# sets variables for starting # sets variables for starting
files = [] files = []
subfolders = [] subfolders = []
for file in self.get(dir, filters, full) self.get(dir, filters, full).each do |file|
# engages in recursion to read the entire file tree # engages in recursion to read the entire file tree
if self.safe?(file) # Is a directory if self.safe?(file) # Is a directory
subfolders += self.all(file, filters, full) subfolders += self.all(file, filters, full)
@@ -43,6 +43,42 @@ class Dir
return ret return ret
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# Creates all the required directories for filename path
#-----------------------------------------------------------------------------
def self.create(path)
path.gsub!("\\", "/") # Windows compatibility
# get path tree
dirs = path.split("/")
full = ""
for dir in dirs
full += dir + "/"
# creates directories
self.mkdir(full) if !self.safe?(full)
end
end
#-----------------------------------------------------------------------------
# Generates entire folder tree from a certain directory
#-----------------------------------------------------------------------------
def self.all_dirs(dir)
# sets variables for starting
dirs = []
for file in self.get(dir, "*", true)
# engages in recursion to read the entire folder tree
dirs += self.all_dirs(file) if self.safe?(file)
end
# returns all found directories
return dirs.length > 0 ? (dirs + [dir]) : [dir]
end
#-----------------------------------------------------------------------------
# Deletes all the files in a directory and all the sub directories (allows for non-empty dirs)
#-----------------------------------------------------------------------------
def self.delete_all(dir)
# delete all files in dir
self.all(dir).each { |f| File.delete(f) }
# delete all dirs in dir
self.all_dirs(dir).each { |f| Dir.delete(f) }
end
#-----------------------------------------------------------------------------
end end
@@ -56,7 +92,15 @@ class File
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def self.safe?(file) def self.safe?(file)
ret = false ret = false
self.open(file, 'rb') { ret = true } rescue nil self.open(file, "rb") { ret = true } rescue nil
return ret
end
#-----------------------------------------------------------------------------
# Checks for existing .rxdata file
#-----------------------------------------------------------------------------
def self.safeData?(file)
ret = false
ret = (load_data(file) ? true : false) rescue false
return ret return ret
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@@ -108,8 +152,8 @@ end
def pbResolveAudioSE(file) def pbResolveAudioSE(file)
return nil if !file return nil if !file
if RTP.exists?("Audio/SE/"+file,["",".wav",".mp3",".ogg"]) if RTP.exists?("Audio/SE/" + file, ["", ".wav", ".ogg"]) # ".mp3"
return RTP.getPath("Audio/SE/"+file,["",".wav",".mp3",".ogg"]) return RTP.getPath("Audio/SE/" + file, ["", ".wav", ".ogg"]) # ".mp3"
end end
return nil return nil
end end
@@ -157,7 +201,7 @@ def canonicalize(c)
pos = -1 pos = -1
ret = [] ret = []
retstr = "" retstr = ""
for x in csplit csplit.each do |x|
if x == ".." if x == ".."
if pos >= 0 if pos >= 0
ret.delete_at(pos) ret.delete_at(pos)
@@ -168,7 +212,7 @@ def canonicalize(c)
pos += 1 pos += 1
end end
end end
for i in 0...ret.length ret.length.times do |i|
retstr += "/" if i > 0 retstr += "/" if i > 0
retstr += ret[i] retstr += ret[i]
end end
@@ -184,7 +228,7 @@ module RTP
return false if nil_or_empty?(filename) return false if nil_or_empty?(filename)
eachPathFor(filename) { |path| eachPathFor(filename) { |path|
return true if safeExists?(path) return true if safeExists?(path)
for ext in extensions extensions.each do |ext|
return true if safeExists?(path + ext) return true if safeExists?(path + ext)
end end
} }
@@ -196,14 +240,14 @@ module RTP
end end
def self.getAudioPath(filename) def self.getAudioPath(filename)
return self.getPath(filename,["",".mp3",".wav",".wma",".mid",".ogg",".midi"]) return self.getPath(filename, ["", ".wav", ".wma", ".mid", ".ogg", ".midi"]) # ".mp3"
end end
def self.getPath(filename, extensions = []) def self.getPath(filename, extensions = [])
return filename if nil_or_empty?(filename) return filename if nil_or_empty?(filename)
eachPathFor(filename) { |path| eachPathFor(filename) { |path|
return path if safeExists?(path) return path if safeExists?(path)
for ext in extensions extensions.each do |ext|
file = path + ext file = path + ext
return file if safeExists?(file) return file if safeExists?(file)
end end
@@ -240,8 +284,6 @@ module RTP
yield ".".gsub(/[\/\\]/, "/").gsub(/[\/\\]$/, "") + "/" yield ".".gsub(/[\/\\]/, "/").gsub(/[\/\\]$/, "") + "/"
end end
private
def self.getSaveFileName(fileName) def self.getSaveFileName(fileName)
File.join(getSaveFolder, fileName) File.join(getSaveFolder, fileName)
end end
@@ -260,15 +302,15 @@ end
module FileTest module FileTest
Image_ext = ['.png', '.gif'] # '.jpg', '.jpeg', '.bmp', IMAGE_EXTENSIONS = [".png", ".gif"] # ".jpg", ".jpeg", ".bmp",
Audio_ext = ['.mp3', '.mid', '.midi', '.ogg', '.wav', '.wma'] AUDIO_EXTENSIONS = [".mid", ".midi", ".ogg", ".wav", ".wma"] # ".mp3"
def self.audio_exist?(filename) def self.audio_exist?(filename)
return RTP.exists?(filename,Audio_ext) return RTP.exists?(filename, AUDIO_EXTENSIONS)
end end
def self.image_exist?(filename) def self.image_exist?(filename)
return RTP.exists?(filename,Image_ext) return RTP.exists?(filename, IMAGE_EXTENSIONS)
end end
end end
@@ -277,7 +319,7 @@ end
# Used to determine whether a data file exists (rather than a graphics or # Used to determine whether a data file exists (rather than a graphics or
# audio file). Doesn't check RTP, but does check encrypted archives. # audio file). Doesn't check RTP, but does check encrypted archives.
# Note: pbGetFileChar checks anything added in MKXP's RTP setting, # NOTE: pbGetFileChar checks anything added in MKXP's RTP setting,
# and matching mount points added through System.mount # and matching mount points added through System.mount
def pbRgssExists?(filename) def pbRgssExists?(filename)
if safeExists?("./Game.rgssad") if safeExists?("./Game.rgssad")
@@ -291,7 +333,7 @@ end
# Opens an IO, even if the file is in an encrypted archive. # Opens an IO, even if the file is in an encrypted archive.
# Doesn't check RTP for the file. # Doesn't check RTP for the file.
# Note: load_data checks anything added in MKXP's RTP setting, # NOTE: load_data checks anything added in MKXP's RTP setting,
# and matching mount points added through System.mount # and matching mount points added through System.mount
def pbRgssOpen(file, mode = nil) def pbRgssOpen(file, mode = nil)
# File.open("debug.txt","ab") { |fw| fw.write([file,mode,Time.now.to_f].inspect+"\r\n") } # File.open("debug.txt","ab") { |fw| fw.write([file,mode,Time.now.to_f].inspect+"\r\n") }
@@ -320,7 +362,7 @@ def pbGetFileChar(file)
canon_file = canonicalize(file) canon_file = canonicalize(file)
if !safeExists?("./Game.rgssad") if !safeExists?("./Game.rgssad")
return nil if !safeExists?(canon_file) return nil if !safeExists?(canon_file)
return nil if file.last == '/' # Is a directory return nil if file.last == "/" # Is a directory
begin begin
File.open(canon_file, "rb") { |f| return f.read(1) } # read one byte File.open(canon_file, "rb") { |f| return f.read(1) } # read one byte
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES, Errno::EISDIR rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES, Errno::EISDIR
@@ -338,13 +380,13 @@ end
def pbTryString(x) def pbTryString(x)
ret = pbGetFileChar(x) ret = pbGetFileChar(x)
return (ret!=nil && ret!="") ? x : nil return nil_or_empty?(ret) ? nil : x
end end
# Gets the contents of a file. Doesn't check RTP, but does check # Gets the contents of a file. Doesn't check RTP, but does check
# encrypted archives. # encrypted archives.
# Note: load_data will check anything added in MKXP's RTP setting, # NOTE: load_data will check anything added in MKXP's RTP setting,
# and matching mount points added through System.mount # and matching mount points added through System.mount
def pbGetFileString(file) def pbGetFileString(file)
file = canonicalize(file) file = canonicalize(file)
@@ -380,7 +422,7 @@ class StringInput
f = super f = super
yield f yield f
ensure ensure
f.close if f f&.close
end end
else else
super super
@@ -403,7 +445,7 @@ class StringInput
end end
def close def close
raise IOError, 'closed stream' if @closed raise IOError, "closed stream" if @closed
@pos = nil @pos = nil
@closed = true @closed = true
end end
@@ -411,7 +453,7 @@ class StringInput
def closed?; @closed; end def closed?; @closed; end
def pos def pos
raise IOError, 'closed stream' if @closed raise IOError, "closed stream" if @closed
[@pos, @string.size].min [@pos, @string.size].min
end end
@@ -422,7 +464,7 @@ class StringInput
def pos=(value); seek(value); end def pos=(value); seek(value); end
def seek(offset, whence = IO::SEEK_SET) def seek(offset, whence = IO::SEEK_SET)
raise IOError, 'closed stream' if @closed raise IOError, "closed stream" if @closed
case whence case whence
when IO::SEEK_SET then @pos = offset when IO::SEEK_SET then @pos = offset
when IO::SEEK_CUR then @pos += offset when IO::SEEK_CUR then @pos += offset
@@ -436,12 +478,12 @@ class StringInput
end end
def eof? def eof?
raise IOError, 'closed stream' if @closed raise IOError, "closed stream" if @closed
@pos > @string.size @pos > @string.size
end end
def each(&block) def each(&block)
raise IOError, 'closed stream' if @closed raise IOError, "closed stream" if @closed
begin begin
@string.each(&block) @string.each(&block)
ensure ensure
@@ -450,8 +492,9 @@ class StringInput
end end
def gets def gets
raise IOError, 'closed stream' if @closed raise IOError, "closed stream" if @closed
if idx = @string.index(?\n, @pos) idx = @string.index("\n", @pos)
if idx
idx += 1 # "\n".size idx += 1 # "\n".size
line = @string[@pos...idx] line = @string[@pos...idx]
@pos = idx @pos = idx
@@ -465,7 +508,7 @@ class StringInput
end end
def getc def getc
raise IOError, 'closed stream' if @closed raise IOError, "closed stream" if @closed
ch = @string[@pos] ch = @string[@pos]
@pos += 1 @pos += 1
@pos += 1 if @pos == @string.size @pos += 1 if @pos == @string.size
@@ -473,7 +516,7 @@ class StringInput
end end
def read(len = nil) def read(len = nil)
raise IOError, 'closed stream' if @closed raise IOError, "closed stream" if @closed
if !len if !len
return nil if eof? return nil if eof?
rest = @string[@pos...@string.size] rest = @string[@pos...@string.size]
@@ -485,8 +528,6 @@ class StringInput
@pos += 1 if @pos == @string.size @pos += 1 if @pos == @string.size
str str
end end
alias read_all read
def read_all; read(); end
alias sysread read alias sysread read
end end

View File

@@ -67,7 +67,7 @@ module FileInputMixin
self.pos = 0 self.pos = 0
offset = fgetdw >> 3 offset = fgetdw >> 3
return 0 if index >= offset return 0 if index >= offset
self.pos = index * 8 + 4 self.pos = (index * 8) + 4
return fgetdw return fgetdw
end end
@@ -137,7 +137,7 @@ class StringInput
end end
def each_byte def each_byte
while !eof? until eof?
yield getc yield getc
end end
end end

View File

@@ -6,16 +6,16 @@
def pbPostData(url, postdata, filename = nil, depth = 0) def pbPostData(url, postdata, filename = nil, depth = 0)
if url[/^http:\/\/([^\/]+)(.*)$/] if url[/^http:\/\/([^\/]+)(.*)$/]
host = $1 host = $1
path = $2 # path = $2
path = "/" if path.length==0 # path = "/" if path.length == 0
userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.14) Gecko/2009082707 Firefox/3.0.14" userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.14) Gecko/2009082707 Firefox/3.0.14"
body = postdata.map { |key, value| body = postdata.map { |key, value|
keyString = key.to_s keyString = key.to_s
valueString = value.to_s valueString = value.to_s
keyString.gsub!(/[^a-zA-Z0-9_\.\-]/n) { |s| sprintf('%%%02x', s[0]) } keyString.gsub!(/[^a-zA-Z0-9_\.\-]/n) { |s| sprintf("%%%02x", s[0]) }
valueString.gsub!(/[^a-zA-Z0-9_\.\-]/n) { |s| sprintf('%%%02x', s[0]) } valueString.gsub!(/[^a-zA-Z0-9_\.\-]/n) { |s| sprintf("%%%02x", s[0]) }
next "#{keyString}=#{valueString}" next "#{keyString}=#{valueString}"
}.join('&') }.join("&")
ret = HTTPLite.post_body( ret = HTTPLite.post_body(
url, url,
body, body,

View File

@@ -2,7 +2,7 @@
# class Object # class Object
#=============================================================================== #===============================================================================
class Object class Object
alias full_inspect inspect alias full_inspect inspect unless method_defined?(:full_inspect)
def inspect def inspect
return "#<#{self.class}>" return "#<#{self.class}>"
@@ -23,32 +23,21 @@ end
#=============================================================================== #===============================================================================
class String class String
def starts_with_vowel? def starts_with_vowel?
return ['a', 'e', 'i', 'o', 'u'].include?(self[0, 1].downcase) return ["a", "e", "i", "o", "u"].include?(self[0, 1].downcase)
end end
def first(n = 1) def first(n = 1); return self[0...n]; end
return self[0...n]
end
def last(n = 1) def last(n = 1); return self[-n..-1] || self; end
return self[-n..-1] || self
end
def blank? def blank?; return self.strip.empty?; end
blank = true
s = self.scan(/./)
for l in s
blank = false if l != ""
end
return blank
end
def cut(bitmap, width) def cut(bitmap, width)
string = self string = self
width -= bitmap.text_size("...").width width -= bitmap.text_size("...").width
string_width = 0 string_width = 0
text = [] text = []
for char in string.scan(/./) string.scan(/./).each do |char|
wdh = bitmap.text_size(char).width wdh = bitmap.text_size(char).width
next if (wdh + string_width) > width next if (wdh + string_width) > width
string_width += wdh string_width += wdh
@@ -56,11 +45,15 @@ class String
end end
text.push("...") if text.length < string.length text.push("...") if text.length < string.length
new_string = "" new_string = ""
for char in text text.each do |char|
new_string += char new_string += char
end end
return new_string return new_string
end end
def numeric?
return !self[/^[+-]?([0-9]+)(?:\.[0-9]+)?$/].nil?
end
end end
#=============================================================================== #===============================================================================
@@ -100,6 +93,29 @@ class Array
end end
end end
#===============================================================================
# class Hash
#===============================================================================
class Hash
def deep_merge(hash)
merged_hash = self.clone
merged_hash.deep_merge!(hash) if hash.is_a?(Hash)
return merged_hash
end
def deep_merge!(hash)
# failsafe
return unless hash.is_a?(Hash)
hash.each do |key, val|
if self[key].is_a?(Hash)
self[key].deep_merge!(val)
else
self[key] = val
end
end
end
end
#=============================================================================== #===============================================================================
# module Enumerable # module Enumerable
#=============================================================================== #===============================================================================
@@ -111,6 +127,144 @@ module Enumerable
end end
end end
#===============================================================================
# class File
#===============================================================================
class File
# Copies the source file to the destination path.
def self.copy(source, destination)
data = ""
t = Time.now
File.open(source, "rb") do |f|
loop do
r = f.read(4096)
break if !r
if Time.now - t > 1
Graphics.update
t = Time.now
end
data += r
end
end
File.delete(destination) if File.file?(destination)
f = File.new(destination, "wb")
f.write data
f.close
end
# Copies the source to the destination and deletes the source.
def self.move(source, destination)
File.copy(source, destination)
File.delete(source)
end
end
#===============================================================================
# class Color
#===============================================================================
class Color
# alias for old constructor
alias init_original initialize unless self.private_method_defined?(:init_original)
# New constructor, accepts RGB values as well as a hex number or string value.
def initialize(*args)
pbPrintException("Wrong number of arguments! At least 1 is needed!") if args.length < 1
if args.length == 1
if args.first.is_a?(Fixnum)
hex = args.first.to_s(16)
elsif args.first.is_a?(String)
try_rgb_format = args.first.split(",")
return init_original(*try_rgb_format.map(&:to_i)) if try_rgb_format.length.between?(3, 4)
hex = args.first.delete("#")
end
pbPrintException("Wrong type of argument given!") if !hex
r = hex[0...2].to_i(16)
g = hex[2...4].to_i(16)
b = hex[4...6].to_i(16)
elsif args.length == 3
r, g, b = *args
end
return init_original(r, g, b) if r && g && b
return init_original(*args)
end
# Returns this color as a hex string like "#RRGGBB".
def to_hex
r = sprintf("%02X", self.red)
g = sprintf("%02X", self.green)
b = sprintf("%02X", self.blue)
return ("#" + r + g + b).upcase
end
# Returns this color as a 24-bit color integer.
def to_i
return self.to_hex.delete("#").to_i(16)
end
# Converts the provided hex string/24-bit integer to RGB values.
def self.hex_to_rgb(hex)
hex = hex.delete("#") if hex.is_a?(String)
hex = hex.to_s(16) if hex.is_a?(Numeric)
r = hex[0...2].to_i(16)
g = hex[2...4].to_i(16)
b = hex[4...6].to_i(16)
return r, g, b
end
# Parses the input as a Color and returns a Color object made from it.
def self.parse(color)
case color
when Color
return color
when String, Numeric
return Color.new(color)
end
# returns nothing if wrong input
return nil
end
# Returns color object for some commonly used colors
def self.red; return Color.new(255, 0, 0); end
def self.green; return Color.new( 0, 255, 0); end
def self.blue; return Color.new( 0, 0, 255); end
def self.black; return Color.new( 0, 0, 0); end
def self.white; return Color.new(255, 255, 255); end
def self.yellow; return Color.new(255, 255, 0); end
def self.magenta; return Color.new(255, 0, 255); end
def self.teal; return Color.new( 0, 255, 255); end
def self.orange; return Color.new(255, 155, 0); end
def self.purple; return Color.new(155, 0, 255); end
def self.brown; return Color.new(112, 72, 32); end
end
#===============================================================================
# Wrap code blocks in a class which passes data accessible as instance variables
# within the code block.
#
# wrapper = CallbackWrapper.new { puts @test }
# wrapper.set(test: "Hi")
# wrapper.execute #=> "Hi"
#===============================================================================
class CallbackWrapper
@params = {}
def initialize(&block)
@code_block = block
end
def execute(given_block = nil, *args)
execute_block = given_block || @code_block
@params.each do |key, value|
args.instance_variable_set("@#{key.to_s}", value)
end
args.instance_eval(&execute_block)
end
def set(params = {})
@params = params
end
end
#=============================================================================== #===============================================================================
# Kernel methods # Kernel methods
#=============================================================================== #===============================================================================

View File

@@ -24,7 +24,7 @@ def pbSetTextMessages
begin begin
t = Time.now.to_i t = Time.now.to_i
texts = [] texts = []
for script in $RGSS_SCRIPTS $RGSS_SCRIPTS.each do |script|
if Time.now.to_i - t >= 5 if Time.now.to_i - t >= 5
t = Time.now.to_i t = Time.now.to_i
Graphics.update Graphics.update
@@ -34,8 +34,8 @@ def pbSetTextMessages
end end
if safeExists?("Data/PluginScripts.rxdata") if safeExists?("Data/PluginScripts.rxdata")
plugin_scripts = load_data("Data/PluginScripts.rxdata") plugin_scripts = load_data("Data/PluginScripts.rxdata")
for plugin in plugin_scripts plugin_scripts.each do |plugin|
for script in plugin[2] plugin[2].each do |script|
if Time.now.to_i - t >= 5 if Time.now.to_i - t >= 5
t = Time.now.to_i t = Time.now.to_i
Graphics.update Graphics.update
@@ -50,7 +50,7 @@ def pbSetTextMessages
commonevents = load_data("Data/CommonEvents.rxdata") commonevents = load_data("Data/CommonEvents.rxdata")
items = [] items = []
choices = [] choices = []
for event in commonevents.compact commonevents.compact.each do |event|
if Time.now.to_i - t >= 5 if Time.now.to_i - t >= 5
t = Time.now.to_i t = Time.now.to_i
Graphics.update Graphics.update
@@ -58,7 +58,7 @@ def pbSetTextMessages
begin begin
neednewline = false neednewline = false
lastitem = "" lastitem = ""
for j in 0...event.list.size event.list.size.times do |j|
list = event.list[j] list = event.list[j]
if neednewline && list.code != 401 if neednewline && list.code != 401
if lastitem != "" if lastitem != ""
@@ -69,16 +69,16 @@ def pbSetTextMessages
neednewline = false neednewline = false
end end
if list.code == 101 if list.code == 101
lastitem+="#{list.parameters[0]}" lastitem += list.parameters[0].to_s
neednewline = true neednewline = true
elsif list.code == 102 elsif list.code == 102
for k in 0...list.parameters[0].length list.parameters[0].length.times do |k|
choices.push(list.parameters[0][k]) choices.push(list.parameters[0][k])
end end
neednewline = false neednewline = false
elsif list.code == 401 elsif list.code == 401
lastitem += " " if lastitem != "" lastitem += " " if lastitem != ""
lastitem+="#{list.parameters[0]}" lastitem += list.parameters[0].to_s
neednewline = true neednewline = true
elsif list.code == 355 || list.code == 655 elsif list.code == 355 || list.code == 655
pbAddScriptTexts(items, list.parameters[0]) pbAddScriptTexts(items, list.parameters[0])
@@ -86,21 +86,19 @@ def pbSetTextMessages
pbAddScriptTexts(items, list.parameters[1]) pbAddScriptTexts(items, list.parameters[1])
elsif list.code == 209 elsif list.code == 209
route = list.parameters[1] route = list.parameters[1]
for k in 0...route.list.size route.list.size.times do |k|
if route.list[k].code == 45 if route.list[k].code == 45
pbAddScriptTexts(items, route.list[k].parameters[0]) pbAddScriptTexts(items, route.list[k].parameters[0])
end end
end end
end end
end end
if neednewline if neednewline && lastitem != ""
if lastitem!=""
items.push(lastitem) items.push(lastitem)
lastitem = "" lastitem = ""
end end
end end
end end
end
if Time.now.to_i - t >= 5 if Time.now.to_i - t >= 5
t = Time.now.to_i t = Time.now.to_i
Graphics.update Graphics.update
@@ -110,12 +108,7 @@ def pbSetTextMessages
items.concat(choices) items.concat(choices)
MessageTypes.setMapMessagesAsHash(0, items) MessageTypes.setMapMessagesAsHash(0, items)
mapinfos = pbLoadMapInfos mapinfos = pbLoadMapInfos
mapnames=[] mapinfos.each_key do |id|
for id in mapinfos.keys
mapnames[id]=mapinfos[id].name
end
MessageTypes.setMessages(MessageTypes::MapNames,mapnames)
for id in mapinfos.keys
if Time.now.to_i - t >= 5 if Time.now.to_i - t >= 5
t = Time.now.to_i t = Time.now.to_i
Graphics.update Graphics.update
@@ -125,16 +118,16 @@ def pbSetTextMessages
map = load_data(filename) map = load_data(filename)
items = [] items = []
choices = [] choices = []
for event in map.events.values map.events.each_value do |event|
if Time.now.to_i - t >= 5 if Time.now.to_i - t >= 5
t = Time.now.to_i t = Time.now.to_i
Graphics.update Graphics.update
end end
begin begin
for i in 0...event.pages.size event.pages.size.times do |i|
neednewline = false neednewline = false
lastitem = "" lastitem = ""
for j in 0...event.pages[i].list.size event.pages[i].list.size.times do |j|
list = event.pages[i].list[j] list = event.pages[i].list[j]
if neednewline && list.code != 401 if neednewline && list.code != 401
if lastitem != "" if lastitem != ""
@@ -145,16 +138,16 @@ def pbSetTextMessages
neednewline = false neednewline = false
end end
if list.code == 101 if list.code == 101
lastitem+="#{list.parameters[0]}" lastitem += list.parameters[0].to_s
neednewline = true neednewline = true
elsif list.code == 102 elsif list.code == 102
for k in 0...list.parameters[0].length list.parameters[0].length.times do |k|
choices.push(list.parameters[0][k]) choices.push(list.parameters[0][k])
end end
neednewline = false neednewline = false
elsif list.code == 401 elsif list.code == 401
lastitem += " " if lastitem != "" lastitem += " " if lastitem != ""
lastitem+="#{list.parameters[0]}" lastitem += list.parameters[0].to_s
neednewline = true neednewline = true
elsif list.code == 355 || list.code == 655 elsif list.code == 355 || list.code == 655
pbAddScriptTexts(items, list.parameters[0]) pbAddScriptTexts(items, list.parameters[0])
@@ -162,22 +155,20 @@ def pbSetTextMessages
pbAddScriptTexts(items, list.parameters[1]) pbAddScriptTexts(items, list.parameters[1])
elsif list.code == 209 elsif list.code == 209
route = list.parameters[1] route = list.parameters[1]
for k in 0...route.list.size route.list.size.times do |k|
if route.list[k].code == 45 if route.list[k].code == 45
pbAddScriptTexts(items, route.list[k].parameters[0]) pbAddScriptTexts(items, route.list[k].parameters[0])
end end
end end
end end
end end
if neednewline if neednewline && lastitem != ""
if lastitem!=""
items.push(lastitem) items.push(lastitem)
lastitem = "" lastitem = ""
end end
end end
end end
end end
end
if Time.now.to_i - t >= 5 if Time.now.to_i - t >= 5
t = Time.now.to_i t = Time.now.to_i
Graphics.update Graphics.update
@@ -215,7 +206,7 @@ def pbEachIntlSection(file)
sectionname = $~[1] sectionname = $~[1]
havesection = true havesection = true
else else
if sectionname==nil if sectionname.nil?
raise _INTL("Expected a section at the beginning of the file (line {1})", lineno) raise _INTL("Expected a section at the beginning of the file (line {1})", lineno)
end end
lastsection.push(line.gsub(/\s+$/, "")) lastsection.push(line.gsub(/\s+$/, ""))
@@ -259,12 +250,13 @@ def pbGetText(infile)
else else
intlhash = OrderedHash.new intlhash = OrderedHash.new
itemlength = 2 itemlength = 2
if section.length%2!=0 if section.length.odd?
raise _INTL("Section {1} has an odd number of entries (section was recognized as a hash because its first line is not a number)", name) raise _INTL("Section {1} has an odd number of entries (section was recognized as a hash because its first line is not a number)", name)
end end
end end
i = 0 i = 0
loop do break unless i<section.length loop do
break unless i < section.length
if itemlength == 3 if itemlength == 3
if !section[i][/^\d+$/] if !section[i][/^\d+$/]
raise _INTL("Expected a number in section {1}, got {2} instead", name, section[i]) raise _INTL("Expected a number in section {1}, got {2} instead", name, section[i])
@@ -316,7 +308,7 @@ class OrderedHash < Hash
def inspect def inspect
str = "{" str = "{"
for i in 0...@keys.length @keys.length.times do |i|
str += ", " if i > 0 str += ", " if i > 0
str += @keys[i].inspect + "=>" + self[@keys[i]].inspect str += @keys[i].inspect + "=>" + self[@keys[i]].inspect
end end
@@ -324,7 +316,7 @@ class OrderedHash < Hash
return str return str
end end
alias :to_s :inspect alias to_s inspect
def []=(key, value) def []=(key, value)
oldvalue = self[key] oldvalue = self[key]
@@ -334,7 +326,7 @@ class OrderedHash < Hash
@keys |= [] @keys |= []
@keys -= [key] @keys -= [key]
end end
return super(key,value) super(key, value)
end end
def self._load(string) def self._load(string)
@@ -342,7 +334,7 @@ class OrderedHash < Hash
keysvalues = Marshal.load(string) keysvalues = Marshal.load(string)
keys = keysvalues[0] keys = keysvalues[0]
values = keysvalues[1] values = keysvalues[1]
for i in 0...keys.length keys.length.times do |i|
ret[keys[i]] = values[i] ret[keys[i]] = values[i]
end end
return ret return ret
@@ -350,7 +342,7 @@ class OrderedHash < Hash
def _dump(_depth = 100) def _dump(_depth = 100)
values = [] values = []
for key in @keys @keys.each do |key|
values.push(self[key]) values.push(self[key])
end end
return Marshal.dump([@keys, values]) return Marshal.dump([@keys, values])
@@ -416,9 +408,10 @@ class Messages
def self.writeObject(f, msgs, secname, origMessages = nil) def self.writeObject(f, msgs, secname, origMessages = nil)
return if !msgs return if !msgs
if msgs.is_a?(Array) case msgs
when Array
f.write("[#{secname}]\r\n") f.write("[#{secname}]\r\n")
for j in 0...msgs.length msgs.length.times do |j|
next if nil_or_empty?(msgs[j]) next if nil_or_empty?(msgs[j])
value = Messages.normalizeValue(msgs[j]) value = Messages.normalizeValue(msgs[j])
origValue = "" origValue = ""
@@ -431,10 +424,10 @@ class Messages
f.write(origValue + "\r\n") f.write(origValue + "\r\n")
f.write(value + "\r\n") f.write(value + "\r\n")
end end
elsif msgs.is_a?(OrderedHash) when OrderedHash
f.write("[#{secname}]\r\n") f.write("[#{secname}]\r\n")
keys = msgs.keys keys = msgs.keys
for key in keys keys.each do |key|
next if nil_or_empty?(msgs[key]) next if nil_or_empty?(msgs[key])
value = Messages.normalizeValue(msgs[key]) value = Messages.normalizeValue(msgs[key])
valkey = Messages.normalizeValue(key) valkey = Messages.normalizeValue(key)
@@ -459,12 +452,12 @@ class Messages
f.write("# To localize this text for a particular language, please\r\n") f.write("# To localize this text for a particular language, please\r\n")
f.write("# translate every second line of this file.\r\n") f.write("# translate every second line of this file.\r\n")
if origMessages.messages[0] if origMessages.messages[0]
for i in 0...origMessages.messages[0].length origMessages.messages[0].length.times do |i|
msgs = origMessages.messages[0][i] msgs = origMessages.messages[0][i]
Messages.writeObject(f, msgs, "Map#{i}", origMessages) Messages.writeObject(f, msgs, "Map#{i}", origMessages)
end end
end end
for i in 1...origMessages.messages.length (1...origMessages.messages.length).each do |i|
msgs = origMessages.messages[i] msgs = origMessages.messages[i]
Messages.writeObject(f, msgs, i, origMessages) Messages.writeObject(f, msgs, i, origMessages)
end end
@@ -474,7 +467,7 @@ class Messages
def setMessages(type, array) def setMessages(type, array)
@messages = [] if !@messages @messages = [] if !@messages
arr = [] arr = []
for i in 0...array.length array.length.times do |i|
arr[i] = (array[i]) ? array[i] : "" arr[i] = (array[i]) ? array[i] : ""
end end
@messages[type] = arr @messages[type] = arr
@@ -483,7 +476,7 @@ class Messages
def addMessages(type, array) def addMessages(type, array)
@messages = [] if !@messages @messages = [] if !@messages
arr = (@messages[type]) ? @messages[type] : [] arr = (@messages[type]) ? @messages[type] : []
for i in 0...array.length array.length.times do |i|
arr[i] = (array[i]) ? array[i] : (arr[i]) ? arr[i] : "" arr[i] = (array[i]) ? array[i] : (arr[i]) ? arr[i] : ""
end end
@messages[type] = arr @messages[type] = arr
@@ -491,7 +484,7 @@ class Messages
def self.createHash(_type, array) def self.createHash(_type, array)
arr = OrderedHash.new arr = OrderedHash.new
for i in 0...array.length array.length.times do |i|
if array[i] if array[i]
key = Messages.stringToKey(array[i]) key = Messages.stringToKey(array[i])
arr[key] = array[i] arr[key] = array[i]
@@ -502,7 +495,7 @@ class Messages
def self.addToHash(_type, array, hash) def self.addToHash(_type, array, hash)
hash = OrderedHash.new if !hash hash = OrderedHash.new if !hash
for i in 0...array.length array.length.times do |i|
if array[i] if array[i]
key = Messages.stringToKey(array[i]) key = Messages.stringToKey(array[i])
hash[key] = array[i] hash[key] = array[i]
@@ -627,6 +620,7 @@ module MessageTypes
ScriptTexts = 24 ScriptTexts = 24
RibbonNames = 25 RibbonNames = 25
RibbonDescriptions = 26 RibbonDescriptions = 26
StorageCreator = 27
@@messages = Messages.new @@messages = Messages.new
@@messagesFallback = Messages.new("Data/messages.dat", true) @@messagesFallback = Messages.new("Data/messages.dat", true)
@@ -740,8 +734,8 @@ def _INTL(*arg)
string = arg[0] string = arg[0]
end end
string = string.clone string = string.clone
for i in 1...arg.length (1...arg.length).each do |i|
string.gsub!(/\{#{i}\}/,"#{arg[i]}") string.gsub!(/\{#{i}\}/, arg[i].to_s)
end end
return string return string
end end
@@ -756,7 +750,7 @@ def _ISPRINTF(*arg)
string = arg[0] string = arg[0]
end end
string = string.clone string = string.clone
for i in 1...arg.length (1...arg.length).each do |i|
string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m| string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m|
next sprintf("%" + $1, arg[i]) next sprintf("%" + $1, arg[i])
} }
@@ -764,15 +758,15 @@ def _ISPRINTF(*arg)
return string return string
end end
def _I(str) def _I(str, *arg)
return _MAPINTL($game_map.map_id,str) return _MAPINTL($game_map.map_id, str, *arg)
end end
def _MAPINTL(mapid, *arg) def _MAPINTL(mapid, *arg)
string = MessageTypes.getFromMapHash(mapid, arg[0]) string = MessageTypes.getFromMapHash(mapid, arg[0])
string = string.clone string = string.clone
for i in 1...arg.length (1...arg.length).each do |i|
string.gsub!(/\{#{i}\}/,"#{arg[i]}") string.gsub!(/\{#{i}\}/, arg[i].to_s)
end end
return string return string
end end
@@ -780,7 +774,7 @@ end
def _MAPISPRINTF(mapid, *arg) def _MAPISPRINTF(mapid, *arg)
string = MessageTypes.getFromMapHash(mapid, arg[0]) string = MessageTypes.getFromMapHash(mapid, arg[0])
string = string.clone string = string.clone
for i in 1...arg.length (1...arg.length).each do |i|
string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m| string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m|
next sprintf("%" + $1, arg[i]) next sprintf("%" + $1, arg[i])
} }

View File

@@ -1,8 +1,8 @@
#==============================================================================# #==============================================================================#
# Plugin Manager # # Plugin Manager #
# by Marin # # by Marin #
# support for external plugin scripts by Luka S.J. # # Support for external plugin scripts by Luka S.J. #
# tweaked by Maruno # # Tweaked by Maruno #
#------------------------------------------------------------------------------# #------------------------------------------------------------------------------#
# Provides a simple interface that allows plugins to require dependencies # # Provides a simple interface that allows plugins to require dependencies #
# at specific versions, and to specify incompatibilities between plugins. # # at specific versions, and to specify incompatibilities between plugins. #
@@ -12,152 +12,92 @@
#------------------------------------------------------------------------------# #------------------------------------------------------------------------------#
# Usage: # # Usage: #
# # # #
# A Pokémon Essentials plugin should register itself using the PluginManager. # # Each plugin should have its own folder in the "Plugins" folder found in the #
# The simplest way to do so, for a plugin without dependencies, is as follows: # # main directory. The "Plugins" folder is similar in concept to the "PBS" #
# folder, in that its contents are compiled and recorded as existing. The #
# plugin's script file(s) are placed in its folder - they must be .rb files. #
# #
# A plugin's folder must also contain a "meta.txt" file. This file is what #
# makes Essentials recognise that the plugin exists, and contains important #
# information about the plugin; if this file does not exist, the folder's #
# contents are ignored. Each line in this file is a property. #
# #
# Required lines: #
# #
# Name = Simple Extension The plugin's name #
# Version = 1.0 The plugin's version #
# Essentials = 19.1,20 Compatible version(s) of Essentials #
# Link = https://reliccastle.com/link-to-the-plugin/ #
# Credits = Luka S.J.,Maruno,Marin One or more names #
# #
# A plugin's version should be in the format X or X.Y or X.Y.Z, where X/Y/Z #
# are numbers. You can also use Xa, Xb, Xc, Ya, etc. What matters is that you #
# use version numbers consistently for your plugin. A later version will be #
# alphanumerically higher than an older version. #
# #
# Plugins can interact with each other in several ways, such as requiring #
# another one to exist or by clashing with each other. These interactions are #
# known as dependencies and conflicts. The lines below are all optional, and #
# go in "meta.txt" to define how your plugin works (or doesn't work) with #
# others. You can have multiples of each of these lines. #
# #
# Requires = Basic Plugin Must have this plugin (any version) #
# Requires = Useful Utils,1.1 Must have this plugin/min. version #
# Exact = Scene Tweaks,2 Must have this plugin/version #
# Optional = Extended Windows,1.2 If this plugin exists, load it first #
# Conflicts = Complex Extension Incompatible plugin #
# #
# A plugin that depends on another one ("Requires"/"Exact"/"Optional") will #
# make that other plugin be loaded first. The "Optional" line is for a plugin #
# which isn't necessary, but if it does exist in the same project, it must be #
# at the given version or higher. #
# #
# When plugins are compiled, their scripts are stored in the file #
# "PluginScripts.rxdata" in the "Data" folder. Dependencies defined above will #
# ensure that they are loaded in a suitable order. Scripts within a plugin are #
# loaded alphanumerically, going through subfolders depth-first. #
# #
# The "Plugins" folder should be deleted when the game is released. Scripts in #
# there are compiled, but any other files used by a plugin (graphics/audio) #
# should go into other folders and not the plugin's folder. #
# #
#------------------------------------------------------------------------------#
# The code behind plugins: #
# #
# When a plugin's "meta.txt" file is read, its contents are registered in the #
# PluginManager. A simple example of registering a plugin is as follows: #
# # # #
# PluginManager.register({ # # PluginManager.register({ #
# :name => "Basic Plugin", # # :name => "Basic Plugin", #
# :version => "1.0", # # :version => "1.0", #
# :essentials => "20", #
# :link => "https://reliccastle.com/link-to-the-plugin/", # # :link => "https://reliccastle.com/link-to-the-plugin/", #
# :credits => "Marin" # # :credits => ["Marin"] #
# }) # # }) #
# # # #
# The link portion here is optional, but recommended. This will be shown in # # The :link value is optional, but recommended. This will be shown in the #
# the error message if the PluginManager detects that this plugin needs to be # # message if the PluginManager detects that this plugin needs to be updated. #
# updated. #
# # # #
# A plugin's version should be in the format X.Y.Z, but the number of digits # # Here is the same example but also with dependencies and conflicts: #
# you use does not matter. You can also use Xa, Xb, Xc, Ya, etc. #
# What matters is that you use it consistently, so that it can be compared. #
# #
# IF there are multiple people to credit, their names should be in an array. #
# If there is only one credit, it does not need an array: #
# #
# :credits => "Marin" #
# :credits => ["Marin", "Maruno"], #
# #
# #
# #
# Dependency: #
# #
# A plugin can require another plugin to be installed in order to work. For #
# example, the "Simple Extension" plugin depends on the above "Basic Plugin" #
# like so: #
# # # #
# PluginManager.register({ # # PluginManager.register({ #
# :name => "Simple Extension", # # :name => "Basic Plugin", #
# :version => "1.0", # # :version => "1.0", #
# :essentials => "20", #
# :link => "https://reliccastle.com/link-to-the-plugin/", # # :link => "https://reliccastle.com/link-to-the-plugin/", #
# :credits => ["Marin", "Maruno"], # # :credits => ["Marin"], #
# :dependencies => ["Basic Plugin"] # # :dependencies => ["Basic Plugin", #
# ["Useful Utils", "1.1"], #
# [:exact, "Scene Tweaks", "2"], #
# [:optional, "Extended Windows", "1.2"], #
# ], #
# :incompatibilities => ["Simple Extension"] #
# }) # # }) #
# # # #
# If there are multiple dependencies, they should be listed in an array. If # # The example dependencies/conflict are the same as the examples shown above #
# there is only one dependency, it does not need an array: # # for lines in "meta.txt". :optional_exact is a combination of :exact and #
# # # :optional, and there is no way to make use of its combined functionality via #
# :dependencies => "Basic Plugin" # # "meta.txt". #
# #
# To require a minimum version of a dependency plugin, you should turn the #
# dependency's name into an array which contains the name and the version #
# (both as strings). For example, to require "Basic Plugin" version 1.2 or #
# higher, you would write: #
# #
# :dependencies => [ #
# ["Basic Plugin", "1.2"] #
# ] #
# #
# To require a specific version (no higher and no lower) of a dependency #
# plugin, you should add the :exact flag as the first thing in the array for #
# that dependency: #
# #
# :dependencies => [ #
# [:exact, "Basic Plugin", "1.2"] #
# ] #
# #
# If your plugin can work without another plugin, but it is incompatible with #
# an old version of that other plugin, you should list it as an optional #
# dependency. If that other plugin is present in a game, then this optional #
# dependency will check whether it meets the minimum version required for your #
# plugin. Write it in the same way as any other dependency as described above, #
# but use the :optional flag instead. #
# #
# :dependencies => [ #
# [:optional, "QoL Improvements", "1.1"] #
# ] #
# #
# The :optional_exact flag is a combination of :optional and :exact. #
# #
# #
# #
# Incompatibility: #
# #
# If your plugin is known to be incompatible with another plugin, you should #
# list that other plugin as such. Only one of the two plugins needs to list #
# that it is incompatible with the other. #
# #
# PluginManager.register({ #
# :name => "QoL Improvements", #
# :version => "1.0", #
# :link => "https://reliccastle.com/link-to-the-plugin/", #
# :credits => "Marin", #
# :incompatibilities => [ #
# "Simple Extension" #
# ] #
# }) #
# #
#------------------------------------------------------------------------------#
# Plugin folder: #
# #
# The Plugin folder is treated like the PBS folder, but for script files for #
# plugins. Each plugin has its own folder within the Plugin folder. Each #
# plugin must have a meta.txt file in its folder, which contains information #
# about that plugin. Folders without this meta.txt file are ignored. #
# #
# Scripts must be in .rb files. You should not put any other files into a #
# plugin's folder except for script files and meta.txt. #
# #
# When the game is compiled, scripts in these folders are read and converted #
# into a usable format, and saved in the file Data/PluginScripts.rxdata. #
# Script files are loaded in order of their name and subfolder, so it is wise #
# to name script files "001_first script.rb", "002_second script.rb", etc. to #
# ensure they are loaded in the correct order. #
# #
# When the game is compressed for distribution, the Plugin folder and all its #
# contents should be deleted (like the PBS folder), because its contents will #
# be unused (they will have been compiled into the PluginScripts.rxdata file). #
# #
# The contents of meta.txt are as follows: #
# #
# Name = Simple Extension #
# Version = 1.0 #
# Requires = Basic Plugin #
# Requires = Useful Utilities,1.1 #
# Conflicts = Complex Extension #
# Conflicts = Extended Windows #
# Link = https://reliccastle.com/link-to-the-plugin/ #
# Credits = Luka S.J.,Maruno,Marin #
# #
# These lines are related to what is described above. You can have multiple #
# "Requires" and "Conflicts" lines, each listing a single other plugin that is #
# either a dependency or a conflict respectively. #
# #
# Examples of the "Requires" line: #
# #
# Requires = Basic Plugin #
# Requires = Basic Plugin,1.1 #
# Requires = Basic Plugin,1.1,exact #
# Requires = Basic Plugin,1.1,optional #
# Exact = Basic Plugin,1.1 #
# Optional = Basic Plugin,1.1 #
# #
# The "Exact" and "Optional" lines are equivalent to the "Requires" lines #
# that contain those keywords. #
# #
# There is also a "Scripts" line, which lists one or more script files that #
# should be loaded first. You can have multiple "Scripts" lines. However, you #
# can achieve the same effect by simply naming your script files in #
# alphanumeric order to make them load in a particular order, so the "Scripts" #
# line should not be necessary. #
# # # #
#------------------------------------------------------------------------------# #------------------------------------------------------------------------------#
# Please give credit when using this. # # Please give credit when using this. #
@@ -172,21 +112,20 @@ module PluginManager
def self.register(options) def self.register(options)
name = nil name = nil
version = nil version = nil
essentials = nil
link = nil link = nil
dependencies = nil dependencies = nil
incompats = nil incompats = nil
credits = [] credits = []
order = [:name, :version, :link, :dependencies, :incompatibilities, :credits] order = [:name, :version, :essentials, :link, :dependencies, :incompatibilities, :credits]
# Ensure it first reads the plugin's name, which is used in error reporting, # Ensure it first reads the plugin's name, which is used in error reporting,
# by sorting the keys # by sorting the keys
keys = options.keys.sort do |a, b| keys = options.keys.sort do |a, b|
idx_a = order.index(a) idx_a = order.index(a) || order.size
idx_a = order.size if idx_a == -1 idx_b = order.index(b) || order.size
idx_b = order.index(b)
idx_b = order.size if idx_b == -1
next idx_a <=> idx_b next idx_a <=> idx_b
end end
for key in keys keys.each do |key|
value = options[key] value = options[key]
case key case key
when :name # Plugin name when :name # Plugin name
@@ -202,6 +141,8 @@ module PluginManager
self.error("Plugin version must be a string.") self.error("Plugin version must be a string.")
end end
version = value version = value
when :essentials
essentials = value
when :link # Plugin website when :link # Plugin website
if nil_or_empty?(value) if nil_or_empty?(value)
self.error("Plugin link must be a non-empty string.") self.error("Plugin link must be a non-empty string.")
@@ -210,12 +151,13 @@ module PluginManager
when :dependencies # Plugin dependencies when :dependencies # Plugin dependencies
dependencies = value dependencies = value
dependencies = [dependencies] if !dependencies.is_a?(Array) || !dependencies[0].is_a?(Array) dependencies = [dependencies] if !dependencies.is_a?(Array) || !dependencies[0].is_a?(Array)
for dep in value value.each do |dep|
if dep.is_a?(String) # "plugin name" case dep
when String # "plugin name"
if !self.installed?(dep) if !self.installed?(dep)
self.error("Plugin '#{name}' requires plugin '#{dep}' to be installed above it.") self.error("Plugin '#{name}' requires plugin '#{dep}' to be installed above it.")
end end
elsif dep.is_a?(Array) when Array
case dep.size case dep.size
when 1 # ["plugin name"] when 1 # ["plugin name"]
if dep[0].is_a?(String) if dep[0].is_a?(String)
@@ -236,7 +178,8 @@ module PluginManager
if self.installed?(dep_name) # Have plugin but lower version if self.installed?(dep_name) # Have plugin but lower version
msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} or higher, " + msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} or higher, " +
"but the installed version is #{self.version(dep_name)}." "but the installed version is #{self.version(dep_name)}."
if dep_link = self.link(dep_name) dep_link = self.link(dep_name)
if dep_link
msg += "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'." msg += "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'."
end end
self.error(msg) self.error(msg)
@@ -278,7 +221,8 @@ module PluginManager
msg = "Plugin '#{name}' requires plugin '#{dep_name}', if installed, to be version #{dep_version}" msg = "Plugin '#{name}' requires plugin '#{dep_name}', if installed, to be version #{dep_version}"
msg << " or higher" if !exact msg << " or higher" if !exact
msg << ", but the installed version was #{self.version(dep_name)}." msg << ", but the installed version was #{self.version(dep_name)}."
if dep_link = self.link(dep_name) dep_link = self.link(dep_name)
if dep_link
msg << "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'." msg << "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'."
end end
self.error(msg) self.error(msg)
@@ -288,16 +232,16 @@ module PluginManager
msg = "Plugin '#{name}' requires plugin '#{dep_name}' to be version #{dep_version}" msg = "Plugin '#{name}' requires plugin '#{dep_name}' to be version #{dep_version}"
msg << " or later" if !exact msg << " or later" if !exact
msg << ", but the installed version was #{self.version(dep_name)}." msg << ", but the installed version was #{self.version(dep_name)}."
if dep_link = self.link(dep_name) dep_link = self.link(dep_name)
if dep_link
msg << "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'." msg << "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'."
end end
self.error(msg)
else # Don't have plugin else # Don't have plugin
msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} " msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} "
msg << "or later " if !exact msg << "or later " if !exact
msg << "to be installed above it." msg << "to be installed above it."
self.error(msg)
end end
self.error(msg)
end end
end end
end end
@@ -305,7 +249,7 @@ module PluginManager
when :incompatibilities # Plugin incompatibilities when :incompatibilities # Plugin incompatibilities
incompats = value incompats = value
incompats = [incompats] if !incompats.is_a?(Array) incompats = [incompats] if !incompats.is_a?(Array)
for incompat in incompats incompats.each do |incompat|
if self.installed?(incompat) if self.installed?(incompat)
self.error("Plugin '#{name}' is incompatible with '#{incompat}'. " + self.error("Plugin '#{name}' is incompatible with '#{incompat}'. " +
"They cannot both be used at the same time.") "They cannot both be used at the same time.")
@@ -314,11 +258,11 @@ module PluginManager
when :credits # Plugin credits when :credits # Plugin credits
value = [value] if value.is_a?(String) value = [value] if value.is_a?(String)
if value.is_a?(Array) if value.is_a?(Array)
for entry in value value.each do |entry|
if !entry.is_a?(String) if entry.is_a?(String)
self.error("Plugin '#{name}'s credits array contains a non-string value.")
else
credits << entry credits << entry
else
self.error("Plugin '#{name}'s credits array contains a non-string value.")
end end
end end
else else
@@ -328,8 +272,8 @@ module PluginManager
self.error("Invalid plugin registry key '#{key}'.") self.error("Invalid plugin registry key '#{key}'.")
end end
end end
for plugin in @@Plugins.values @@Plugins.each_value do |plugin|
if plugin[:incompatibilities] && plugin[:incompatibilities].include?(name) if plugin[:incompatibilities]&.include?(name)
self.error("Plugin '#{plugin[:name]}' is incompatible with '#{name}'. " + self.error("Plugin '#{plugin[:name]}' is incompatible with '#{name}'. " +
"They cannot both be used at the same time.") "They cannot both be used at the same time.")
end end
@@ -338,6 +282,7 @@ module PluginManager
@@Plugins[name] = { @@Plugins[name] = {
:name => name, :name => name,
:version => version, :version => version,
:essentials => essentials,
:link => link, :link => link,
:dependencies => dependencies, :dependencies => dependencies,
:incompatibilities => incompats, :incompatibilities => incompats,
@@ -350,8 +295,8 @@ module PluginManager
def self.error(msg) def self.error(msg)
Graphics.update Graphics.update
t = Thread.new do t = Thread.new do
echoln "Plugin Error:\r\n#{msg}" Console.echo_error "Plugin Error:\r\n#{msg}"
p "Plugin Error: #{msg}" print("Plugin Error:\r\n#{msg}")
Thread.exit Thread.exit
end end
while t.status while t.status
@@ -408,21 +353,25 @@ module PluginManager
# -1 if v1 is lower than v2 # -1 if v1 is lower than v2
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def self.compare_versions(v1, v2) def self.compare_versions(v1, v2)
d1 = v1.split("") d1 = v1.chars
d1.insert(0, "0") if d1[0] == "." # Turn ".123" into "0.123" d1.insert(0, "0") if d1[0] == "." # Turn ".123" into "0.123"
while d1[-1] == "."; d1 = d1[0..-2]; end # Turn "123." into "123" while d1[-1] == "." # Turn "123." into "123"
d2 = v2.split("") d1 = d1[0..-2]
end
d2 = v2.chars
d2.insert(0, "0") if d2[0] == "." # Turn ".123" into "0.123" d2.insert(0, "0") if d2[0] == "." # Turn ".123" into "0.123"
while d2[-1] == "."; d2 = d2[0..-2]; end # Turn "123." into "123" while d2[-1] == "." # Turn "123." into "123"
for i in 0...[d1.size, d2.size].max # Compare each digit in turn d2 = d2[0..-2]
end
[d1.size, d2.size].max.times do |i| # Compare each digit in turn
c1 = d1[i] c1 = d1[i]
c2 = d2[i] c2 = d2[i]
if c1 if c1
return 1 if !c2 return 1 if !c2
return 1 if c1.to_i(16) > c2.to_i(16) return 1 if c1.to_i(16) > c2.to_i(16)
return -1 if c1.to_i(16) < c2.to_i(16) return -1 if c1.to_i(16) < c2.to_i(16)
else elsif c2
return -1 if c2 return -1
end end
end end
return 0 return 0
@@ -431,25 +380,17 @@ module PluginManager
# formats the error message # formats the error message
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def self.pluginErrorMsg(name, script) def self.pluginErrorMsg(name, script)
e = $!
# begin message formatting # begin message formatting
message = "[Pokémon Essentials version #{Essentials::VERSION}]\r\n" message = "[Pokémon Essentials version #{Essentials::VERSION}]\r\n"
message += "#{Essentials::ERROR_TEXT}\r\n" # For third party scripts to add to message += "#{Essentials::ERROR_TEXT}\r\n" # For third party scripts to add to
message += "Error in Plugin [#{name}]:\r\n" message += "Error in Plugin: [#{name}]\r\n"
message += "#{$!.class} occurred.\r\n" message += "Exception: #{e.class}\r\n"
# go through message content message += "Message: "
for line in $!.message.split("\r\n") message += e.message
next if nil_or_empty?(line)
n = line[/\d+/]
err = line.split(":")[-1].strip
lms = line.split(":")[0].strip
err.gsub!(n, "") if n
err = err.capitalize if err.is_a?(String) && !err.empty?
linum = n ? "Line #{n}: " : ""
message += "#{linum}#{err}: #{lms}\r\n"
end
# show last 10 lines of backtrace # show last 10 lines of backtrace
message += "\r\nBacktrace:\r\n" message += "\r\n\r\nBacktrace:\r\n"
$!.backtrace[0, 10].each { |i| message += "#{i}\r\n" } e.backtrace[0, 10].each { |i| message += "#{i}\r\n" }
# output to log # output to log
errorlog = "errorlog.txt" errorlog = "errorlog.txt"
errorlog = RTP.getSaveFileName("errorlog.txt") if (Object.const_defined?(:RTP) rescue false) errorlog = RTP.getSaveFileName("errorlog.txt") if (Object.const_defined?(:RTP) rescue false)
@@ -466,7 +407,7 @@ module PluginManager
print("#{message}\r\nThis exception was logged in #{errorlogline}.\r\nHold Ctrl when closing this message to copy it to the clipboard.") print("#{message}\r\nThis exception was logged in #{errorlogline}.\r\nHold Ctrl when closing this message to copy it to the clipboard.")
# Give a ~500ms coyote time to start holding Control # Give a ~500ms coyote time to start holding Control
t = System.delta t = System.delta
until (System.delta - t) >= 500000 until (System.delta - t) >= 500_000
Input.update Input.update
if Input.press?(Input::CTRL) if Input.press?(Input::CTRL)
Input.clipboard = message Input.clipboard = message
@@ -487,11 +428,14 @@ module PluginManager
raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}", FileLineData.linereport) raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}", FileLineData.linereport)
end end
property = $~[1].upcase property = $~[1].upcase
data = $~[2].split(',') data = $~[2].split(",")
data.each_with_index { |value, i| data[i] = value.strip } data.each_with_index { |value, i| data[i] = value.strip }
# begin formatting data hash # begin formatting data hash
case property case property
when 'REQUIRES' when "ESSENTIALS"
meta[:essentials] = [] if !meta[:essentials]
data.each { |ver| meta[:essentials].push(ver) }
when "REQUIRES"
meta[:dependencies] = [] if !meta[:dependencies] meta[:dependencies] = [] if !meta[:dependencies]
if data.length < 2 # No version given, just push name of plugin dependency if data.length < 2 # No version given, just push name of plugin dependency
meta[:dependencies].push(data[0]) meta[:dependencies].push(data[0])
@@ -501,23 +445,23 @@ module PluginManager
else # Push dependency type, name and version of plugin dependency else # Push dependency type, name and version of plugin dependency
meta[:dependencies].push([data[2].downcase.to_sym, data[0], data[1]]) meta[:dependencies].push([data[2].downcase.to_sym, data[0], data[1]])
end end
when 'EXACT' when "EXACT"
next if data.length < 2 # Exact dependencies must have a version given; ignore if not next if data.length < 2 # Exact dependencies must have a version given; ignore if not
meta[:dependencies] = [] if !meta[:dependencies] meta[:dependencies] = [] if !meta[:dependencies]
meta[:dependencies].push([:exact, data[0], data[1]]) meta[:dependencies].push([:exact, data[0], data[1]])
when 'OPTIONAL' when "OPTIONAL"
next if data.length < 2 # Optional dependencies must have a version given; ignore if not next if data.length < 2 # Optional dependencies must have a version given; ignore if not
meta[:dependencies] = [] if !meta[:dependencies] meta[:dependencies] = [] if !meta[:dependencies]
meta[:dependencies].push([:optional, data[0], data[1]]) meta[:dependencies].push([:optional, data[0], data[1]])
when 'CONFLICTS' when "CONFLICTS"
meta[:incompatibilities] = [] if !meta[:incompatibilities] meta[:incompatibilities] = [] if !meta[:incompatibilities]
data.each { |value| meta[:incompatibilities].push(value) if value && !value.empty? } data.each { |value| meta[:incompatibilities].push(value) if value && !value.empty? }
when 'SCRIPTS' when "SCRIPTS"
meta[:scripts] = [] if !meta[:scripts] meta[:scripts] = [] if !meta[:scripts]
data.each { |scr| meta[:scripts].push(scr) } data.each { |scr| meta[:scripts].push(scr) }
when 'CREDITS' when "CREDITS"
meta[:credits] = data meta[:credits] = data
when 'LINK', 'WEBSITE' when "LINK", "WEBSITE"
meta[:link] = data[0] meta[:link] = data[0]
else else
meta[property.downcase.to_sym] = data[0] meta[property.downcase.to_sym] = data[0]
@@ -527,7 +471,7 @@ module PluginManager
# be loaded (files listed in the meta file are loaded first) # be loaded (files listed in the meta file are loaded first)
meta[:scripts] = [] if !meta[:scripts] meta[:scripts] = [] if !meta[:scripts]
# get all script files from plugin Dir # get all script files from plugin Dir
for fl in Dir.all(dir) Dir.all(dir).each do |fl|
next if !fl.include?(".rb") next if !fl.include?(".rb")
meta[:scripts].push(fl.gsub("#{dir}/", "")) meta[:scripts].push(fl.gsub("#{dir}/", ""))
end end
@@ -555,7 +499,7 @@ module PluginManager
return nil if !meta[name] || !meta[name][:dependencies] return nil if !meta[name] || !meta[name][:dependencies]
og = [name] if !og og = [name] if !og
# go through all dependencies # go through all dependencies
for dname in meta[name][:dependencies] meta[name][:dependencies].each do |dname|
# clean the name to a simple string # clean the name to a simple string
dname = dname[0] if dname.is_a?(Array) && dname.length == 2 dname = dname[0] if dname.is_a?(Array) && dname.length == 2
dname = dname[1] if dname.is_a?(Array) && dname.length == 3 dname = dname[1] if dname.is_a?(Array) && dname.length == 3
@@ -572,10 +516,10 @@ module PluginManager
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def self.sortLoadOrder(order, plugins) def self.sortLoadOrder(order, plugins)
# go through the load order # go through the load order
for o in order order.each do |o|
next if !plugins[o] || !plugins[o][:dependencies] next if !plugins[o] || !plugins[o][:dependencies]
# go through all dependencies # go through all dependencies
for dname in plugins[o][:dependencies] plugins[o][:dependencies].each do |dname|
optional = false optional = false
# clean the name to a simple string # clean the name to a simple string
if dname.is_a?(Array) if dname.is_a?(Array)
@@ -604,7 +548,7 @@ module PluginManager
order = [] order = []
# Find all plugin folders that have a meta.txt and add them to the list of # Find all plugin folders that have a meta.txt and add them to the list of
# plugins. # plugins.
for dir in self.listAll self.listAll.each do |dir|
# skip if there is no meta file # skip if there is no meta file
next if !safeExists?(dir + "/meta.txt") next if !safeExists?(dir + "/meta.txt")
ndx = order.length ndx = order.length
@@ -632,14 +576,14 @@ module PluginManager
return false if !$DEBUG || safeExists?("Game.rgssad") return false if !$DEBUG || safeExists?("Game.rgssad")
return true if !safeExists?("Data/PluginScripts.rxdata") return true if !safeExists?("Data/PluginScripts.rxdata")
Input.update Input.update
return true if Input.press?(Input::CTRL) return true if Input.press?(Input::SHIFT) || Input.press?(Input::CTRL)
# analyze whether or not to push recompile # analyze whether or not to push recompile
mtime = File.mtime("Data/PluginScripts.rxdata") mtime = File.mtime("Data/PluginScripts.rxdata")
for o in order order.each do |o|
# go through all the registered plugin scripts # go through all the registered plugin scripts
scr = plugins[o][:scripts] scr = plugins[o][:scripts]
dir = plugins[o][:dir] dir = plugins[o][:dir]
for sc in scr scr.each do |sc|
return true if File.mtime("#{dir}/#{sc}") > mtime return true if File.mtime("#{dir}/#{sc}") > mtime
end end
return true if File.mtime("#{dir}/meta.txt") > mtime return true if File.mtime("#{dir}/meta.txt") > mtime
@@ -650,18 +594,18 @@ module PluginManager
# Check if plugins need compiling # Check if plugins need compiling
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def self.compilePlugins(order, plugins) def self.compilePlugins(order, plugins)
echo 'Compiling plugin scripts...' Console.echo_li "Compiling plugin scripts..."
scripts = [] scripts = []
# go through the entire order one by one # go through the entire order one by one
for o in order order.each do |o|
# save name, metadata and scripts array # save name, metadata and scripts array
meta = plugins[o].clone meta = plugins[o].clone
meta.delete(:scripts) meta.delete(:scripts)
meta.delete(:dir) meta.delete(:dir)
dat = [o, meta, []] dat = [o, meta, []]
# iterate through each file to deflate # iterate through each file to deflate
for file in plugins[o][:scripts] plugins[o][:scripts].each do |file|
File.open("#{plugins[o][:dir]}/#{file}", 'rb') do |f| File.open("#{plugins[o][:dir]}/#{file}", "rb") do |f|
dat[2].push([file, Zlib::Deflate.deflate(f.read)]) dat[2].push([file, Zlib::Deflate.deflate(f.read)])
end end
end end
@@ -669,16 +613,17 @@ module PluginManager
scripts.push(dat) scripts.push(dat)
end end
# save to main `PluginScripts.rxdata` file # save to main `PluginScripts.rxdata` file
File.open("Data/PluginScripts.rxdata", 'wb') { |f| Marshal.dump(scripts, f) } File.open("Data/PluginScripts.rxdata", "wb") { |f| Marshal.dump(scripts, f) }
# collect garbage # collect garbage
GC.start GC.start
echoln ' done.' Console.echo_done(true)
echoln '' echoln "" if scripts.length == 0
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# Check if plugins need compiling # Check if plugins need compiling
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def self.runPlugins def self.runPlugins
Console.echo_h1 "Checking plugins"
# get the order of plugins to interpret # get the order of plugins to interpret
order, plugins = self.getPluginOrder order, plugins = self.getPluginOrder
# compile if necessary # compile if necessary
@@ -686,13 +631,16 @@ module PluginManager
# load plugins # load plugins
scripts = load_data("Data/PluginScripts.rxdata") scripts = load_data("Data/PluginScripts.rxdata")
echoed_plugins = [] echoed_plugins = []
for plugin in scripts scripts.each do |plugin|
# get the required data # get the required data
name, meta, script = plugin name, meta, script = plugin
if !meta[:essentials] || !meta[:essentials].include?(Essentials::VERSION)
Console.echo_warn "Plugin '#{name}' may not be compatible with Essentials v#{Essentials::VERSION}. Trying to load anyway."
end
# register plugin # register plugin
self.register(meta) self.register(meta)
# go through each script and interpret # go through each script and interpret
for scr in script script.each do |scr|
# turn code into plaintext # turn code into plaintext
code = Zlib::Inflate.inflate(scr[1]).force_encoding(Encoding::UTF_8) code = Zlib::Inflate.inflate(scr[1]).force_encoding(Encoding::UTF_8)
# get rid of tabs # get rid of tabs
@@ -703,7 +651,7 @@ module PluginManager
# try to run the code # try to run the code
begin begin
eval(code, TOPLEVEL_BINDING, fname) eval(code, TOPLEVEL_BINDING, fname)
echoln "Loaded plugin: #{name}" if !echoed_plugins.include?(name) Console.echoln_li "Loaded plugin: '#{name}' (ver. #{meta[:version]})" if !echoed_plugins.include?(name)
echoed_plugins.push(name) echoed_plugins.push(name)
rescue Exception # format error message to display rescue Exception # format error message to display
self.pluginErrorMsg(name, sname) self.pluginErrorMsg(name, sname)
@@ -711,7 +659,27 @@ module PluginManager
end end
end end
end end
echoln '' if !echoed_plugins.empty? if scripts.length > 0
echoln ""
Console.echo_h2("Successfully loaded #{scripts.length} plugin(s)", text: :green)
else
Console.echo_h2("No plugins found", text: :green)
end
end
#-----------------------------------------------------------------------------
# Get plugin dir from name based on meta entries
#-----------------------------------------------------------------------------
def self.findDirectory(name)
# go through the plugins folder
Dir.get("Plugins").each do |dir|
next if !Dir.safe?(dir)
next if !safeExists?(dir + "/meta.txt")
# read meta
meta = self.readMeta(dir, "meta.txt")
return dir if meta[:name] == name
end
# return nil if no plugin dir found
return nil
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
end end

View File

@@ -6,14 +6,12 @@ class SpriteAnimation
@sprite = sprite @sprite = sprite
end end
%w[ ["x", "y", "ox", "oy", "viewport", "flash", "src_rect", "opacity", "tone"].each do |def_name|
x y ox oy viewport flash src_rect opacity tone
].each_with_index do |s, _i|
eval <<-__END__ eval <<-__END__
def #{s}(*arg) def #{def_name}(*arg) # def x(*arg)
@sprite.#{s}(*arg) @sprite.#{def_name}(*arg) # @sprite.x(*arg)
end end # end
__END__ __END__
end end
@@ -30,7 +28,7 @@ class SpriteAnimation
def animation(animation, hit, height = 3) def animation(animation, hit, height = 3)
dispose_animation dispose_animation
@_animation = animation @_animation = animation
return if @_animation == nil return if @_animation.nil?
@_animation_hit = hit @_animation_hit = hit
@_animation_height = height @_animation_height = height
@_animation_duration = @_animation.frame_max @_animation_duration = @_animation.frame_max
@@ -66,7 +64,7 @@ class SpriteAnimation
return if animation == @_loop_animation return if animation == @_loop_animation
dispose_loop_animation dispose_loop_animation
@_loop_animation = animation @_loop_animation = animation
return if @_loop_animation == nil return if @_loop_animation.nil?
@_loop_animation_index = 0 @_loop_animation_index = 0
fr = 20 fr = 20
if @_animation.name[/\[\s*(\d+?)\s*\]\s*$/] if @_animation.name[/\[\s*(\d+?)\s*\]\s*$/]
@@ -92,15 +90,15 @@ class SpriteAnimation
end end
def dispose_animation def dispose_animation
return if @_animation_sprites == nil return if @_animation_sprites.nil?
sprite = @_animation_sprites[0] sprite = @_animation_sprites[0]
if sprite != nil if sprite
@@_reference_count[sprite.bitmap] -= 1 @@_reference_count[sprite.bitmap] -= 1
if @@_reference_count[sprite.bitmap] == 0 if @@_reference_count[sprite.bitmap] == 0
sprite.bitmap.dispose sprite.bitmap.dispose
end end
end end
for sprite in @_animation_sprites @_animation_sprites.each do |sprite|
sprite.dispose sprite.dispose
end end
@_animation_sprites = nil @_animation_sprites = nil
@@ -108,15 +106,15 @@ class SpriteAnimation
end end
def dispose_loop_animation def dispose_loop_animation
return if @_loop_animation_sprites == nil return if @_loop_animation_sprites.nil?
sprite = @_loop_animation_sprites[0] sprite = @_loop_animation_sprites[0]
if sprite != nil if sprite
@@_reference_count[sprite.bitmap] -= 1 @@_reference_count[sprite.bitmap] -= 1
if @@_reference_count[sprite.bitmap] == 0 if @@_reference_count[sprite.bitmap] == 0
sprite.bitmap.dispose sprite.bitmap.dispose
end end
end end
for sprite in @_loop_animation_sprites @_loop_animation_sprites.each do |sprite|
sprite.dispose sprite.dispose
end end
@_loop_animation_sprites = nil @_loop_animation_sprites = nil
@@ -124,7 +122,7 @@ class SpriteAnimation
end end
def active? def active?
return @_loop_animation_sprites != nil || @_animation_sprites != nil return @_loop_animation_sprites || @_animation_sprites
end end
def effect? def effect?
@@ -132,7 +130,7 @@ class SpriteAnimation
end end
def update def update
if @_animation != nil if @_animation
quick_update = true quick_update = true
if Graphics.frame_count % @_animation_frame_skip == 0 if Graphics.frame_count % @_animation_frame_skip == 0
@_animation_duration -= 1 @_animation_duration -= 1
@@ -140,7 +138,7 @@ class SpriteAnimation
end end
update_animation(quick_update) update_animation(quick_update)
end end
if @_loop_animation != nil if @_loop_animation
quick_update = (Graphics.frame_count % @_loop_animation_frame_skip != 0) quick_update = (Graphics.frame_count % @_loop_animation_frame_skip != 0)
update_loop_animation(quick_update) update_loop_animation(quick_update)
if !quick_update if !quick_update
@@ -160,7 +158,7 @@ class SpriteAnimation
position = @_animation.position position = @_animation.position
animation_set_sprites(@_animation_sprites, cell_data, position, quick_update) animation_set_sprites(@_animation_sprites, cell_data, position, quick_update)
return if quick_update return if quick_update
for timing in @_animation.timings @_animation.timings.each do |timing|
next if timing.frame != frame_index next if timing.frame != frame_index
animation_process_timing(timing, @_animation_hit) animation_process_timing(timing, @_animation_hit)
end end
@@ -172,7 +170,7 @@ class SpriteAnimation
position = @_loop_animation.position position = @_loop_animation.position
animation_set_sprites(@_loop_animation_sprites, cell_data, position, quick_update) animation_set_sprites(@_loop_animation_sprites, cell_data, position, quick_update)
return if quick_update return if quick_update
for timing in @_loop_animation.timings @_loop_animation.timings.each do |timing|
next if timing.frame != frame_index next if timing.frame != frame_index
animation_process_timing(timing, true) animation_process_timing(timing, true)
end end
@@ -182,21 +180,21 @@ class SpriteAnimation
sprite_x = 320 sprite_x = 320
sprite_y = 240 sprite_y = 240
if position == 3 if position == 3
if self.viewport != nil if self.viewport
sprite_x = self.viewport.rect.width / 2 sprite_x = self.viewport.rect.width / 2
sprite_y = self.viewport.rect.height - 160 sprite_y = self.viewport.rect.height - 160
end end
else else
sprite_x = self.x - self.ox + self.src_rect.width / 2 sprite_x = self.x - self.ox + (self.src_rect.width / 2)
sprite_y = self.y - self.oy sprite_y = self.y - self.oy
sprite_y += self.src_rect.height / 2 if position == 1 sprite_y += self.src_rect.height / 2 if position == 1
sprite_y += self.src_rect.height if position == 2 sprite_y += self.src_rect.height if position == 2
end end
for i in 0..15 16.times do |i|
sprite = sprites[i] sprite = sprites[i]
pattern = cell_data[i, 0] pattern = cell_data[i, 0]
if sprite == nil || pattern == nil || pattern == -1 if sprite.nil? || pattern.nil? || pattern == -1
sprite.visible = false if sprite != nil sprite.visible = false if sprite
next next
end end
sprite.x = sprite_x + cell_data[i, 1] sprite.x = sprite_x + cell_data[i, 1]
@@ -206,8 +204,8 @@ class SpriteAnimation
sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192) sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192)
case @_animation_height case @_animation_height
when 0 then sprite.z = 1 when 0 then sprite.z = 1
when 1 then sprite.z = sprite.y+32+15 when 1 then sprite.z = sprite.y + (Game_Map::TILE_HEIGHT * 3 / 2) + 1
when 2 then sprite.z = sprite.y+32+32+17 when 2 then sprite.z = sprite.y + (Game_Map::TILE_HEIGHT * 3) + 1
else sprite.z = 2000 else sprite.z = 2000
end end
sprite.ox = 96 sprite.ox = 96
@@ -234,9 +232,7 @@ class SpriteAnimation
when 1 when 1
self.flash(timing.flash_color, timing.flash_duration * 2) self.flash(timing.flash_color, timing.flash_duration * 2)
when 2 when 2
if self.viewport != nil self.viewport.flash(timing.flash_color, timing.flash_duration * 2) if self.viewport
self.viewport.flash(timing.flash_color, timing.flash_duration * 2)
end
when 3 when 3
self.flash(nil, timing.flash_duration * 2) self.flash(nil, timing.flash_duration * 2)
end end
@@ -246,30 +242,22 @@ class SpriteAnimation
def x=(x) def x=(x)
sx = x - self.x sx = x - self.x
return if sx == 0 return if sx == 0
if @_animation_sprites != nil if @_animation_sprites
for i in 0..15 16.times { |i| @_animation_sprites[i].x += sx }
@_animation_sprites[i].x += sx
end
end
if @_loop_animation_sprites != nil
for i in 0..15
@_loop_animation_sprites[i].x += sx
end end
if @_loop_animation_sprites
16.times { |i| @_loop_animation_sprites[i].x += sx }
end end
end end
def y=(y) def y=(y)
sy = y - self.y sy = y - self.y
return if sy == 0 return if sy == 0
if @_animation_sprites != nil if @_animation_sprites
for i in 0..15 16.times { |i| @_animation_sprites[i].y += sy }
@_animation_sprites[i].y += sy
end
end
if @_loop_animation_sprites != nil
for i in 0..15
@_loop_animation_sprites[i].y += sy
end end
if @_loop_animation_sprites
16.times { |i| @_loop_animation_sprites[i].y += sy }
end end
end end
end end
@@ -370,14 +358,14 @@ module RPG
@_damage_sprite.ox = 80 @_damage_sprite.ox = 80
@_damage_sprite.oy = 20 @_damage_sprite.oy = 20
@_damage_sprite.x = self.x @_damage_sprite.x = self.x
@_damage_sprite.y = self.y - self.oy / 2 @_damage_sprite.y = self.y - (self.oy / 2)
@_damage_sprite.z = 3000 @_damage_sprite.z = 3000
@_damage_duration = 40 @_damage_duration = 40
end end
def pushAnimation(array, anim) def pushAnimation(array, anim)
for i in 0...array.length array.length.times do |i|
next if array[i] && array[i].active? next if array[i]&.active?
array[i] = anim array[i] = anim
return return
end end
@@ -397,7 +385,7 @@ module RPG
end end
def dispose_damage def dispose_damage
return if @_damage_sprite == nil return if @_damage_sprite.nil?
@_damage_sprite.bitmap.dispose @_damage_sprite.bitmap.dispose
@_damage_sprite.dispose @_damage_sprite.dispose
@_damage_sprite = nil @_damage_sprite = nil
@@ -405,15 +393,15 @@ module RPG
end end
def dispose_animation def dispose_animation
for a in @animations @animations.each do |a|
a.dispose_animation if a a&.dispose_animation
end end
@animations.clear @animations.clear
end end
def dispose_loop_animation def dispose_loop_animation
for a in @loopAnimations @loopAnimations.each do |a|
a.dispose_loop_animation if a a&.dispose_loop_animation
end end
@loopAnimations.clear @loopAnimations.clear
end end
@@ -440,7 +428,7 @@ module RPG
return true if @_escape_duration > 0 return true if @_escape_duration > 0
return true if @_collapse_duration > 0 return true if @_collapse_duration > 0
return true if @_damage_duration > 0 return true if @_damage_duration > 0
for a in @animations @animations.each do |a|
return true if a.effect? return true if a.effect?
end end
return false return false
@@ -450,7 +438,7 @@ module RPG
super super
if @_whiten_duration > 0 if @_whiten_duration > 0
@_whiten_duration -= 1 @_whiten_duration -= 1
self.color.alpha = 128 - (16 - @_whiten_duration) * 10 self.color.alpha = 128 - ((16 - @_whiten_duration) * 10)
end end
if @_appear_duration > 0 if @_appear_duration > 0
@_appear_duration -= 1 @_appear_duration -= 1
@@ -458,11 +446,11 @@ module RPG
end end
if @_escape_duration > 0 if @_escape_duration > 0
@_escape_duration -= 1 @_escape_duration -= 1
self.opacity = 256 - (32 - @_escape_duration) * 10 self.opacity = 256 - ((32 - @_escape_duration) * 10)
end end
if @_collapse_duration > 0 if @_collapse_duration > 0
@_collapse_duration -= 1 @_collapse_duration -= 1
self.opacity = 256 - (48 - @_collapse_duration) * 6 self.opacity = 256 - ((48 - @_collapse_duration) * 6)
end end
if @_damage_duration > 0 if @_damage_duration > 0
@_damage_duration -= 1 @_damage_duration -= 1
@@ -476,15 +464,15 @@ module RPG
when 28..33 when 28..33
@_damage_sprite.y += 4 @_damage_sprite.y += 4
end end
@_damage_sprite.opacity = 256 - (12 - @_damage_duration) * 32 @_damage_sprite.opacity = 256 - ((12 - @_damage_duration) * 32)
if @_damage_duration == 0 if @_damage_duration == 0
dispose_damage dispose_damage
end end
end end
for a in @animations @animations.each do |a|
a.update a.update
end end
for a in @loopAnimations @loopAnimations.each do |a|
a.update a.update
end end
if @_blink if @_blink
@@ -500,32 +488,32 @@ module RPG
end end
def update_animation def update_animation
for a in @animations @animations.each do |a|
a.update_animation if a && a.active? a.update_animation if a&.active?
end end
end end
def update_loop_animation def update_loop_animation
for a in @loopAnimations @loopAnimations.each do |a|
a.update_loop_animation if a && a.active? a.update_loop_animation if a&.active?
end end
end end
def x=(x) def x=(x)
for a in @animations @animations.each do |a|
a.x = x if a a.x = x if a
end end
for a in @loopAnimations @loopAnimations.each do |a|
a.x = x if a a.x = x if a
end end
super super
end end
def y=(y) def y=(y)
for a in @animations @animations.each do |a|
a.y = y if a a.y = y if a
end end
for a in @loopAnimations @loopAnimations.each do |a|
a.y = y if a a.y = y if a
end end
super super

View File

@@ -1,15 +1,25 @@
module Settings module Settings
# Whether a move's physical/special category depends on the move itself as in
# newer Gens (true), or on its type as in older Gens (false).
MOVE_CATEGORY_PER_MOVE = (MECHANICS_GENERATION >= 4)
# Whether turn order is recalculated after a Pokémon Mega Evolves. # Whether turn order is recalculated after a Pokémon Mega Evolves.
RECALCULATE_TURN_ORDER_AFTER_MEGA_EVOLUTION = (MECHANICS_GENERATION >= 7) RECALCULATE_TURN_ORDER_AFTER_MEGA_EVOLUTION = (MECHANICS_GENERATION >= 7)
# Whether turn order is recalculated after a Pokémon's Speed stat changes. # Whether turn order is recalculated after a Pokémon's Speed stat changes.
RECALCULATE_TURN_ORDER_AFTER_SPEED_CHANGES = (MECHANICS_GENERATION >= 8) RECALCULATE_TURN_ORDER_AFTER_SPEED_CHANGES = (MECHANICS_GENERATION >= 8)
# Whether any Pokémon (originally owned by the player or foreign) can disobey
# the player's commands if the Pokémon is too high a level compared to the
# number of Gym Badges the player has.
ANY_HIGH_LEVEL_POKEMON_CAN_DISOBEY = false
# Whether foreign Pokémon can disobey the player's commands if the Pokémon is
# too high a level compared to the number of Gym Badges the player has.
FOREIGN_HIGH_LEVEL_POKEMON_CAN_DISOBEY = true
# Whether a move's physical/special category depends on the move itself as in
# newer Gens (true), or on its type as in older Gens (false).
MOVE_CATEGORY_PER_MOVE = (MECHANICS_GENERATION >= 4)
# Whether critical hits do 1.5x damage and have 4 stages (true), or they do 2x # Whether critical hits do 1.5x damage and have 4 stages (true), or they do 2x
# damage and have 5 stages as in Gen 5 (false). Also determines whether # damage and have 5 stages as in Gen 5 (false). Also determines whether
# critical hit rate can be copied by Transform/Psych Up. # critical hit rate can be copied by Transform/Psych Up.
NEW_CRITICAL_HIT_RATE_MECHANICS = (MECHANICS_GENERATION >= 6) NEW_CRITICAL_HIT_RATE_MECHANICS = (MECHANICS_GENERATION >= 6)
#=============================================================================
# Whether several effects apply relating to a Pokémon's type: # Whether several effects apply relating to a Pokémon's type:
# * Electric-type immunity to paralysis # * Electric-type immunity to paralysis
# * Ghost-type immunity to being trapped # * Ghost-type immunity to being trapped
@@ -18,9 +28,6 @@ module Settings
MORE_TYPE_EFFECTS = (MECHANICS_GENERATION >= 6) MORE_TYPE_EFFECTS = (MECHANICS_GENERATION >= 6)
# Whether weather caused by an ability lasts 5 rounds (true) or forever (false). # Whether weather caused by an ability lasts 5 rounds (true) or forever (false).
FIXED_DURATION_WEATHER_FROM_ABILITY = (MECHANICS_GENERATION >= 6) FIXED_DURATION_WEATHER_FROM_ABILITY = (MECHANICS_GENERATION >= 6)
#=============================================================================
# Whether X items (X Attack, etc.) raise their stat by 2 stages (true) or 1 # Whether X items (X Attack, etc.) raise their stat by 2 stages (true) or 1
# (false). # (false).
X_STAT_ITEMS_RAISE_BY_TWO_STAGES = (MECHANICS_GENERATION >= 7) X_STAT_ITEMS_RAISE_BY_TWO_STAGES = (MECHANICS_GENERATION >= 7)
@@ -33,6 +40,18 @@ module Settings
#============================================================================= #=============================================================================
# Whether Pokémon with high happiness will gain more Exp from battles, have a
# chance of avoiding/curing negative effects by themselves, resisting
# fainting, etc.
AFFECTION_EFFECTS = false
# Whether a Pokémon's happiness is limited to 179, and can only be increased
# further with friendship-raising berries. Related to AFFECTION_EFFECTS by
# default as affection effects only start applying above a happiness of 179.
# Also lowers the happiness evolution threshold to 160.
APPLY_HAPPINESS_SOFT_CAP = AFFECTION_EFFECTS
#=============================================================================
# The minimum number of badges required to boost each stat of a player's # The minimum number of badges required to boost each stat of a player's
# Pokémon by 1.1x, in battle only. # Pokémon by 1.1x, in battle only.
NUM_BADGES_BOOST_ATTACK = (MECHANICS_GENERATION >= 4) ? 999 : 1 NUM_BADGES_BOOST_ATTACK = (MECHANICS_GENERATION >= 4) ? 999 : 1
@@ -43,9 +62,6 @@ module Settings
#============================================================================= #=============================================================================
# An array of items which act as Mega Rings for the player (NPCs don't need a
# Mega Ring item, just a Mega Stone held by their Pokémon).
MEGA_RINGS = [:MEGARING, :MEGABRACELET, :MEGACUFF, :MEGACHARM]
# The Game Switch which, while ON, prevents all Pokémon in battle from Mega # The Game Switch which, while ON, prevents all Pokémon in battle from Mega
# Evolving even if they otherwise could. # Evolving even if they otherwise could.
NO_MEGA_EVOLUTION = 34 NO_MEGA_EVOLUTION = 34
@@ -60,6 +76,9 @@ module Settings
# that much Exp (false). This also applies to Exp gained via the Exp Share # that much Exp (false). This also applies to Exp gained via the Exp Share
# (held item version) being distributed to all Exp Share holders. # (held item version) being distributed to all Exp Share holders.
SPLIT_EXP_BETWEEN_GAINERS = (MECHANICS_GENERATION <= 5) SPLIT_EXP_BETWEEN_GAINERS = (MECHANICS_GENERATION <= 5)
# Whether a Pokémon holding a Power item gains 8 (true) or 4 (false) EVs in
# the relevant stat.
MORE_EVS_FROM_POWER_ITEMS = (MECHANICS_GENERATION >= 7)
# Whether the critical capture mechanic applies. Note that its calculation is # Whether the critical capture mechanic applies. Note that its calculation is
# based on a total of 600+ species (i.e. that many species need to be caught # based on a total of 600+ species (i.e. that many species need to be caught
# to provide the greatest critical capture chance of 2.5x), and there may be # to provide the greatest critical capture chance of 2.5x), and there may be
@@ -67,6 +86,13 @@ module Settings
ENABLE_CRITICAL_CAPTURES = (MECHANICS_GENERATION >= 5) ENABLE_CRITICAL_CAPTURES = (MECHANICS_GENERATION >= 5)
# Whether Pokémon gain Exp for capturing a Pokémon. # Whether Pokémon gain Exp for capturing a Pokémon.
GAIN_EXP_FOR_CAPTURE = (MECHANICS_GENERATION >= 6) GAIN_EXP_FOR_CAPTURE = (MECHANICS_GENERATION >= 6)
# Whether the player is asked what to do with a newly caught Pokémon if their
# party is full. If true, the player can toggle whether they are asked this in
# the Options screen.
NEW_CAPTURE_CAN_REPLACE_PARTY_MEMBER = (MECHANICS_GENERATION >= 7)
#=============================================================================
# The Game Switch which, whie ON, prevents the player from losing money if # The Game Switch which, whie ON, prevents the player from losing money if
# they lose a battle (they can still gain money from trainers for winning). # they lose a battle (they can still gain money from trainers for winning).
NO_MONEY_LOSS = 33 NO_MONEY_LOSS = 33

View File

@@ -6,9 +6,9 @@
module SaveData module SaveData
# Contains the file path of the save file. # Contains the file path of the save file.
FILE_PATH = if File.directory?(System.data_directory) FILE_PATH = if File.directory?(System.data_directory)
System.data_directory + '/Game.rxdata' System.data_directory + "/Game.rxdata"
else else
'./Game.rxdata' "./Game.rxdata"
end end
# @return [Boolean] whether the save file exists # @return [Boolean] whether the save file exists
@@ -45,7 +45,7 @@ module SaveData
save_data = get_data_from_file(file_path) save_data = get_data_from_file(file_path)
save_data = to_hash_format(save_data) if save_data.is_a?(Array) save_data = to_hash_format(save_data) if save_data.is_a?(Array)
if !save_data.empty? && run_conversions(save_data) if !save_data.empty? && run_conversions(save_data)
File.open(file_path, 'wb') { |file| Marshal.dump(save_data, file) } File.open(file_path, "wb") { |file| Marshal.dump(save_data, file) }
end end
return save_data return save_data
end end
@@ -57,14 +57,14 @@ module SaveData
def self.save_to_file(file_path) def self.save_to_file(file_path)
validate file_path => String validate file_path => String
save_data = self.compile_save_hash save_data = self.compile_save_hash
File.open(file_path, 'wb') { |file| Marshal.dump(save_data, file) } File.open(file_path, "wb") { |file| Marshal.dump(save_data, file) }
end end
# Deletes the save file (and a possible .bak backup file if one exists) # Deletes the save file (and a possible .bak backup file if one exists)
# @raise [Error::ENOENT] # @raise [Error::ENOENT]
def self.delete_file def self.delete_file
File.delete(FILE_PATH) File.delete(FILE_PATH)
File.delete(FILE_PATH + '.bak') if File.file?(FILE_PATH + '.bak') File.delete(FILE_PATH + ".bak") if File.file?(FILE_PATH + ".bak")
end end
# Converts the pre-v19 format data to the new format. # Converts the pre-v19 format data to the new format.
@@ -85,12 +85,12 @@ module SaveData
# already exists in {FILE_PATH}. # already exists in {FILE_PATH}.
def self.move_old_windows_save def self.move_old_windows_save
return if File.file?(FILE_PATH) return if File.file?(FILE_PATH)
game_title = System.game_title.gsub(/[^\w ]/, '_') game_title = System.game_title.gsub(/[^\w ]/, "_")
home = ENV['HOME'] || ENV['HOMEPATH'] home = ENV["HOME"] || ENV["HOMEPATH"]
return if home.nil? return if home.nil?
old_location = File.join(home, 'Saved Games', game_title) old_location = File.join(home, "Saved Games", game_title)
return unless File.directory?(old_location) return unless File.directory?(old_location)
old_file = File.join(old_location, 'Game.rxdata') old_file = File.join(old_location, "Game.rxdata")
return unless File.file?(old_file) return unless File.file?(old_file)
File.move(old_file, FILE_PATH) File.move(old_file, FILE_PATH)
end end

View File

@@ -114,21 +114,21 @@ module SaveData
# Requires a block with the loaded value as its parameter. # Requires a block with the loaded value as its parameter.
# @see SaveData.register # @see SaveData.register
def load_value(&block) def load_value(&block)
raise ArgumentError, 'No block given to load_value' unless block_given? raise ArgumentError, "No block given to load_value" unless block_given?
@load_proc = block @load_proc = block
end end
# Defines what is saved into save data. Requires a block. # Defines what is saved into save data. Requires a block.
# @see SaveData.register # @see SaveData.register
def save_value(&block) def save_value(&block)
raise ArgumentError, 'No block given to save_value' unless block_given? raise ArgumentError, "No block given to save_value" unless block_given?
@save_proc = block @save_proc = block
end end
# If present, defines what the value is set to at the start of a new game. # If present, defines what the value is set to at the start of a new game.
# @see SaveData.register # @see SaveData.register
def new_game_value(&block) def new_game_value(&block)
raise ArgumentError, 'No block given to new_game_value' unless block_given? raise ArgumentError, "No block given to new_game_value" unless block_given?
@new_game_value_proc = block @new_game_value_proc = block
end end
@@ -142,7 +142,7 @@ module SaveData
# save format. Requires a block with the old format array as its parameter. # save format. Requires a block with the old format array as its parameter.
# @see SaveData.register # @see SaveData.register
def from_old_format(&block) def from_old_format(&block)
raise ArgumentError, 'No block given to from_old_format' unless block_given? raise ArgumentError, "No block given to from_old_format" unless block_given?
@old_format_get_proc = block @old_format_get_proc = block
end end
@@ -181,11 +181,11 @@ module SaveData
# new_game_value { Bar.new } # new_game_value { Bar.new }
# end # end
# @param id [Symbol] value id # @param id [Symbol] value id
# @yieldself [Value] # @yield the block of code to be saved as a Value
def self.register(id, &block) def self.register(id, &block)
validate id => Symbol validate id => Symbol
unless block_given? unless block_given?
raise ArgumentError, 'No block given to SaveData.register' raise ArgumentError, "No block given to SaveData.register"
end end
@values << Value.new(id, &block) @values << Value.new(id, &block)
end end

View File

@@ -112,7 +112,7 @@ module SaveData
# @see SaveData.register_conversion # @see SaveData.register_conversion
def to_value(value_id, &block) def to_value(value_id, &block)
validate value_id => Symbol validate value_id => Symbol
raise ArgumentError, 'No block given to to_value' unless block_given? raise ArgumentError, "No block given to to_value" unless block_given?
if @value_procs[value_id].is_a?(Proc) if @value_procs[value_id].is_a?(Proc)
raise "Multiple to_value definitions in conversion #{@id} for #{value_id}" raise "Multiple to_value definitions in conversion #{@id} for #{value_id}"
end end
@@ -122,7 +122,7 @@ module SaveData
# Defines a conversion to the entire save data. # Defines a conversion to the entire save data.
# @see SaveData.register_conversion # @see SaveData.register_conversion
def to_all(&block) def to_all(&block)
raise ArgumentError, 'No block given to to_all' unless block_given? raise ArgumentError, "No block given to to_all" unless block_given?
if @all_proc.is_a?(Proc) if @all_proc.is_a?(Proc)
raise "Multiple to_all definitions in conversion #{@id}" raise "Multiple to_all definitions in conversion #{@id}"
end end
@@ -152,11 +152,11 @@ module SaveData
# save_data[:new_value] = Foo.new # save_data[:new_value] = Foo.new
# end # end
# end # end
# @yield self [Conversion] # @yield the block of code to be saved as a Conversion
def self.register_conversion(id, &block) def self.register_conversion(id, &block)
validate id => Symbol validate id => Symbol
unless block_given? unless block_given?
raise ArgumentError, 'No block given to SaveData.register_conversion' raise ArgumentError, "No block given to SaveData.register_conversion"
end end
conversion = Conversion.new(id, &block) conversion = Conversion.new(id, &block)
@conversions[conversion.trigger_type][conversion.version] ||= [] @conversions[conversion.trigger_type][conversion.version] ||= []
@@ -168,8 +168,8 @@ module SaveData
def self.get_conversions(save_data) def self.get_conversions(save_data)
conversions_to_run = [] conversions_to_run = []
versions = { versions = {
essentials: save_data[:essentials_version] || '18.1', essentials: save_data[:essentials_version] || "18.1",
game: save_data[:game_version] || '0.0.0' game: save_data[:game_version] || "0.0.0"
} }
[:essentials, :game].each do |trigger_type| [:essentials, :game].each do |trigger_type|
# Ensure the versions are sorted from lowest to highest # Ensure the versions are sorted from lowest to highest
@@ -194,14 +194,15 @@ module SaveData
validate save_data => Hash validate save_data => Hash
conversions_to_run = self.get_conversions(save_data) conversions_to_run = self.get_conversions(save_data)
return false if conversions_to_run.none? return false if conversions_to_run.none?
File.open(SaveData::FILE_PATH + '.bak', 'wb') { |f| Marshal.dump(save_data, f) } File.open(SaveData::FILE_PATH + ".bak", "wb") { |f| Marshal.dump(save_data, f) }
echoln "Running #{conversions_to_run.length} conversions..." Console.echo_h1 "Running #{conversions_to_run.length} save file conversions"
conversions_to_run.each do |conversion| conversions_to_run.each do |conversion|
echo "#{conversion.title}..." Console.echo_li "#{conversion.title}..."
conversion.run(save_data) conversion.run(save_data)
echoln ' done.' Console.echo_done(true)
end end
echoln '' if conversions_to_run.length > 0 echoln "" if conversions_to_run.length > 0
Console.echo_h2("All save file conversions applied successfully", text: :green)
save_data[:essentials_version] = Essentials::VERSION save_data[:essentials_version] = Essentials::VERSION
save_data[:game_version] = Settings::GAME_VERSION save_data[:game_version] = Settings::GAME_VERSION
return true return true

View File

@@ -2,11 +2,11 @@
SaveData.register(:player) do SaveData.register(:player) do
ensure_class :Player ensure_class :Player
save_value { $Trainer } save_value { $player }
load_value { |value| $Trainer = value } load_value { |value| $player = $Trainer = value }
new_game_value { new_game_value {
trainer_type = nil # Get the first defined trainer type as a placeholder # Get the first defined trainer type as a placeholder
GameData::TrainerType.each { |t| trainer_type = t.id; break } trainer_type = GameData::TrainerType.keys.first
Player.new("Unnamed", trainer_type) Player.new("Unnamed", trainer_type)
} }
from_old_format { |old_format| old_format[0] } from_old_format { |old_format| old_format[0] }
@@ -72,8 +72,8 @@ end
SaveData.register(:map_factory) do SaveData.register(:map_factory) do
ensure_class :PokemonMapFactory ensure_class :PokemonMapFactory
save_value { $MapFactory } save_value { $map_factory }
load_value { |value| $MapFactory = value } load_value { |value| $map_factory = $MapFactory = value }
from_old_format { |old_format| old_format[9] } from_old_format { |old_format| old_format[9] }
end end
@@ -103,8 +103,8 @@ end
SaveData.register(:bag) do SaveData.register(:bag) do
ensure_class :PokemonBag ensure_class :PokemonBag
save_value { $PokemonBag } save_value { $bag }
load_value { |value| $PokemonBag = value } load_value { |value| $bag = $PokemonBag = value }
new_game_value { PokemonBag.new } new_game_value { PokemonBag.new }
from_old_format { |old_format| old_format[13] } from_old_format { |old_format| old_format[13] }
end end
@@ -121,7 +121,7 @@ SaveData.register(:essentials_version) do
load_in_bootup load_in_bootup
ensure_class :String ensure_class :String
save_value { Essentials::VERSION } save_value { Essentials::VERSION }
load_value { |value| $SaveVersion = value } load_value { |value| $save_engine_version = value }
new_game_value { Essentials::VERSION } new_game_value { Essentials::VERSION }
from_old_format { |old_format| old_format[15] } from_old_format { |old_format| old_format[15] }
end end
@@ -130,6 +130,14 @@ SaveData.register(:game_version) do
load_in_bootup load_in_bootup
ensure_class :String ensure_class :String
save_value { Settings::GAME_VERSION } save_value { Settings::GAME_VERSION }
load_value { |value| $game_version = value } load_value { |value| $save_game_version = value }
new_game_value { Settings::GAME_VERSION } new_game_value { Settings::GAME_VERSION }
end end
SaveData.register(:stats) do
load_in_bootup
ensure_class :GameStats
save_value { $stats }
load_value { |value| $stats = value }
new_game_value { GameStats.new }
end

View File

@@ -1,242 +1,350 @@
# Contains conversions defined in Essentials by default. #===============================================================================
# Conversions required to support backwards compatibility with old save files
# (within reason).
#===============================================================================
SaveData.register_conversion(:v19_define_versions) do # Planted berries accidentally weren't converted in v19 to change their
essentials_version 19 # numerical IDs to symbolic IDs (for the berry planted and for mulch laid down).
display_title 'Adding game version and Essentials version to save data' # Since item numerical IDs no longer exist, this conversion needs to have a list
to_all do |save_data| # of them in order to convert planted berry data properly.
unless save_data.has_key?(:essentials_version) SaveData.register_conversion(:v20_fix_planted_berry_numerical_ids) do
save_data[:essentials_version] = Essentials::VERSION essentials_version 20
end display_title "Fixing berry plant IDs data"
unless save_data.has_key?(:game_version)
save_data[:game_version] = Settings::GAME_VERSION
end
end
end
SaveData.register_conversion(:v19_convert_PokemonSystem) do
essentials_version 19
display_title 'Updating PokemonSystem class'
to_all do |save_data|
new_system = PokemonSystem.new
new_system.textspeed = save_data[:pokemon_system].textspeed || new_system.textspeed
new_system.battlescene = save_data[:pokemon_system].battlescene || new_system.battlescene
new_system.battlestyle = save_data[:pokemon_system].battlestyle || new_system.battlestyle
new_system.frame = save_data[:pokemon_system].frame || new_system.frame
new_system.textskin = save_data[:pokemon_system].textskin || new_system.textskin
new_system.screensize = save_data[:pokemon_system].screensize || new_system.screensize
new_system.language = save_data[:pokemon_system].language || new_system.language
new_system.runstyle = save_data[:pokemon_system].runstyle || new_system.runstyle
new_system.bgmvolume = save_data[:pokemon_system].bgmvolume || new_system.bgmvolume
new_system.sevolume = save_data[:pokemon_system].sevolume || new_system.sevolume
new_system.textinput = save_data[:pokemon_system].textinput || new_system.textinput
save_data[:pokemon_system] = new_system
end
end
SaveData.register_conversion(:v19_convert_player) do
essentials_version 19
display_title 'Converting player trainer class'
to_all do |save_data|
next if save_data[:player].is_a?(Player)
# Conversion of the party is handled in PokeBattle_Trainer.convert
save_data[:player] = PokeBattle_Trainer.convert(save_data[:player])
end
end
SaveData.register_conversion(:v19_move_global_data_to_player) do
essentials_version 19
display_title 'Moving some global metadata data to player'
to_all do |save_data|
global = save_data[:global_metadata]
player = save_data[:player]
player.character_ID = global.playerID
global.playerID = nil
global.pokedexUnlocked.each_with_index do |value, i|
if value
player.pokedex.unlock(i)
else
player.pokedex.lock(i)
end
end
player.coins = global.coins
global.coins = nil
player.soot = global.sootsack
global.sootsack = nil
player.has_running_shoes = global.runningShoes
global.runningShoes = nil
player.seen_storage_creator = global.seenStorageCreator
global.seenStorageCreator = nil
player.has_snag_machine = global.snagMachine
global.snagMachine = nil
player.seen_purify_chamber = global.seenPurifyChamber
global.seenPurifyChamber = nil
end
end
SaveData.register_conversion(:v19_convert_global_metadata) do
essentials_version 19
display_title 'Adding encounter version variable to global metadata'
to_value :global_metadata do |global| to_value :global_metadata do |global|
global.bridge ||= 0 berry_conversion = {
global.encounter_version ||= 0 389 => :CHERIBERRY,
if global.pcItemStorage 390 => :CHESTOBERRY,
global.pcItemStorage.items.each_with_index do |slot, i| 391 => :PECHABERRY,
item_data = GameData::Item.try_get(slot[0]) 392 => :RAWSTBERRY,
if item_data 393 => :ASPEARBERRY,
slot[0] = item_data.id 394 => :LEPPABERRY,
else 395 => :ORANBERRY,
global.pcItemStorage.items[i] = nil 396 => :PERSIMBERRY,
397 => :LUMBERRY,
398 => :SITRUSBERRY,
399 => :FIGYBERRY,
400 => :WIKIBERRY,
401 => :MAGOBERRY,
402 => :AGUAVBERRY,
403 => :IAPAPABERRY,
404 => :RAZZBERRY,
405 => :BLUKBERRY,
406 => :NANABBERRY,
407 => :WEPEARBERRY,
408 => :PINAPBERRY,
409 => :POMEGBERRY,
410 => :KELPSYBERRY,
411 => :QUALOTBERRY,
412 => :HONDEWBERRY,
413 => :GREPABERRY,
414 => :TAMATOBERRY,
415 => :CORNNBERRY,
416 => :MAGOSTBERRY,
417 => :RABUTABERRY,
418 => :NOMELBERRY,
419 => :SPELONBERRY,
420 => :PAMTREBERRY,
421 => :WATMELBERRY,
422 => :DURINBERRY,
423 => :BELUEBERRY,
424 => :OCCABERRY,
425 => :PASSHOBERRY,
426 => :WACANBERRY,
427 => :RINDOBERRY,
428 => :YACHEBERRY,
429 => :CHOPLEBERRY,
430 => :KEBIABERRY,
431 => :SHUCABERRY,
432 => :COBABERRY,
433 => :PAYAPABERRY,
434 => :TANGABERRY,
435 => :CHARTIBERRY,
436 => :KASIBBERRY,
437 => :HABANBERRY,
438 => :COLBURBERRY,
439 => :BABIRIBERRY,
440 => :CHILANBERRY,
441 => :LIECHIBERRY,
442 => :GANLONBERRY,
443 => :SALACBERRY,
444 => :PETAYABERRY,
445 => :APICOTBERRY,
446 => :LANSATBERRY,
447 => :STARFBERRY,
448 => :ENIGMABERRY,
449 => :MICLEBERRY,
450 => :CUSTAPBERRY,
451 => :JABOCABERRY,
452 => :ROWAPBERRY
}
mulch_conversion = {
59 => :GROWTHMULCH,
60 => :DAMPMULCH,
61 => :STABLEMULCH,
62 => :GOOEYMULCH
}
global.eventvars.each_value do |var|
next if !var || !var.is_a?(Array)
next if var.length < 6 || var.length > 8 # Neither old nor new berry plant
if !var[1].is_a?(Symbol) # Planted berry item
var[1] = berry_conversion[var[1]] || :ORANBERRY
end end
end if var[7] && !var[7].is_a?(Symbol) # Mulch
global.pcItemStorage.items.compact! var[7] = mulch_conversion[var[7]]
end
if global.mailbox
global.mailbox.each_with_index do |mail, i|
global.mailbox[i] = PokemonMail.convert(mail) if mail
end
end
global.phoneNumbers.each do |contact|
contact[1] = GameData::TrainerType.get(contact[1]).id if contact && contact.length == 8
end
if global.partner
global.partner[0] = GameData::TrainerType.get(global.partner[0]).id
global.partner[3].each_with_index do |pkmn, i|
global.partner[3][i] = PokeBattle_Pokemon.convert(pkmn) if pkmn
end
end
if global.daycare
global.daycare.each do |slot|
slot[0] = PokeBattle_Pokemon.convert(slot[0]) if slot && slot[0]
end
end
if global.roamPokemon
global.roamPokemon.each_with_index do |pkmn, i|
global.roamPokemon[i] = PokeBattle_Pokemon.convert(pkmn) if pkmn && pkmn != true
end
end
global.purifyChamber.sets.each do |set|
set.shadow = PokeBattle_Pokemon.convert(set.shadow) if set.shadow
set.list.each_with_index do |pkmn, i|
set.list[i] = PokeBattle_Pokemon.convert(pkmn) if pkmn
end
end
if global.hallOfFame
global.hallOfFame.each do |team|
next if !team
team.each_with_index do |pkmn, i|
team[i] = PokeBattle_Pokemon.convert(pkmn) if pkmn
end
end
end
if global.triads
global.triads.items.each do |card|
card[0] = GameData::Species.get(card[0]).id if card && card[0] && card[0] != 0
end end
end end
end end
end end
SaveData.register_conversion(:v19_1_fix_phone_contacts) do #===============================================================================
essentials_version 19.1
display_title 'Fixing phone contacts data' SaveData.register_conversion(:v20_refactor_planted_berries_data) do
essentials_version 20
display_title "Updating berry plant data format"
to_value :global_metadata do |global| to_value :global_metadata do |global|
global.phoneNumbers.each do |contact| if global.eventvars
contact[1] = GameData::TrainerType.get(contact[1]).id if contact && contact.length == 8 global.eventvars.each_pair do |key, value|
next if !value || !value.is_a?(Array)
case value.length
when 6 # Old berry plant data
data = BerryPlantData.new
if value[1].is_a?(Symbol)
plant_data = GameData::BerryPlant.get(value[1])
data.new_mechanics = false
data.berry_id = value[1]
data.time_alive = value[0] * plant_data.hours_per_stage * 3600
data.time_last_updated = value[3]
data.growth_stage = value[0]
data.replant_count = value[5]
data.watered_this_stage = value[2]
data.watering_count = value[4]
end
global.eventvars[key] = data
when 7, 8 # New berry plant data
data = BerryPlantData.new
if value[1].is_a?(Symbol)
data.new_mechanics = true
data.berry_id = value[1]
data.mulch_id = value[7] if value[7].is_a?(Symbol)
data.time_alive = value[2]
data.time_last_updated = value[3]
data.growth_stage = value[0]
data.replant_count = value[5]
data.moisture_level = value[4]
data.yield_penalty = value[6]
end
global.eventvars[key] = data
end
end
end end
end end
end end
SaveData.register_conversion(:v19_convert_bag) do #===============================================================================
essentials_version 19
display_title 'Converting item IDs in Bag' SaveData.register_conversion(:v20_refactor_follower_data) do
essentials_version 20
display_title "Updating follower data format"
to_value :global_metadata do |global|
# NOTE: dependentEvents is still defined in class PokemonGlobalMetadata just
# for the sake of this conversion. It will be removed in future.
if global.dependentEvents && global.dependentEvents.length > 0
global.followers = []
global.dependentEvents.each do |follower|
data = FollowerData.new(follower[0], follower[1], "reflection",
follower[2], follower[3], follower[4],
follower[5], follower[6], follower[7])
data.name = follower[8]
data.common_event_id = follower[9]
global.followers.push(data)
end
end
global.dependentEvents = nil
end
end
#===============================================================================
SaveData.register_conversion(:v20_refactor_day_care_variables) do
essentials_version 20
display_title "Refactoring Day Care variables"
to_value :global_metadata do |global|
global.instance_eval do
@day_care = DayCare.new if @day_care.nil?
if !@daycare.nil?
@daycare.each do |old_slot|
if !old_slot[0]
old_slot[0] = Pokemon.new(:MANAPHY, 50)
old_slot[1] = 4
end
next if !old_slot[0]
@day_care.slots.each do |slot|
next if slot.filled?
slot.instance_eval do
@pokemon = old_slot[0]
@initial_level = old_slot[1]
if @pokemon && @pokemon.markings.is_a?(Integer)
markings = []
6.times { |i| markings[i] = ((@pokemon.markings & (1 << i)) == 0) ? 0 : 1 }
@pokemon.markings = markings
end
end
end
end
@day_care.egg_generated = ((@daycareEgg.is_a?(Numeric) && @daycareEgg > 0) || @daycareEgg == true)
@day_care.step_counter = @daycareEggSteps
@daycare = nil
@daycareEgg = nil
@daycareEggSteps = nil
end
end
end
end
#===============================================================================
SaveData.register_conversion(:v20_rename_bag_variables) do
essentials_version 20
display_title "Renaming Bag variables"
to_value :bag do |bag| to_value :bag do |bag|
bag.instance_eval do bag.instance_eval do
for pocket in self.pockets if !@lastpocket.nil?
pocket.each_with_index do |item, i| @last_viewed_pocket = @lastpocket
next if !item || !item[0] || item[0] == 0 @lastPocket = nil
item_data = GameData::Item.try_get(item[0])
if item_data
item[0] = item_data.id
else
pocket[i] = nil
end end
if !@choices.nil?
@last_pocket_selections = @choices.clone
@choices = nil
end end
pocket.compact! if !@registeredItems.nil?
@registered_items = @registeredItems || []
@registeredItems = nil
end end
self.registeredIndex # Just to ensure this data exists if !@registeredIndex.nil?
self.registeredItems.each_with_index do |item, i| @ready_menu_selection = @registeredIndex || [0, 0, 1]
next if !item @registeredIndex = nil
if item == 0
self.registeredItems[i] = nil
else
item_data = GameData::Item.try_get(item)
if item_data
self.registeredItems[i] = item_data.id
else
self.registeredItems[i] = nil
end
end
end
self.registeredItems.compact!
end # bag.instance_eval
end # to_value
end
SaveData.register_conversion(:v19_convert_game_variables) do
essentials_version 19
display_title 'Converting classes of things in Game Variables'
to_all do |save_data|
variables = save_data[:variables]
for i in 0..5000
value = variables[i]
next if value.nil?
if value.is_a?(Array)
value.each_with_index do |value2, j|
if value2.is_a?(PokeBattle_Pokemon)
value[j] = PokeBattle_Pokemon.convert(value2)
end
end
elsif value.is_a?(PokeBattle_Pokemon)
variables[i] = PokeBattle_Pokemon.convert(value)
elsif value.is_a?(PokemonBag)
SaveData.run_single_conversions(value, :bag, save_data)
end end
end end
end end
end end
SaveData.register_conversion(:v19_convert_storage) do #===============================================================================
essentials_version 19
display_title 'Converting classes of Pokémon in storage'
to_value :storage_system do |storage|
storage.instance_eval do
for box in 0...self.maxBoxes
for i in 0...self.maxPokemon(box)
self[box, i] = PokeBattle_Pokemon.convert(self[box, i]) if self[box, i]
end
end
self.unlockedWallpapers # Just to ensure this data exists
end # storage.instance_eval
end # to_value
end
SaveData.register_conversion(:v19_convert_game_player) do SaveData.register_conversion(:v20_increment_player_character_id) do
essentials_version 19 essentials_version 20
display_title 'Converting game player character' display_title "Incrementing player character ID"
to_value :game_player do |game_player| to_value :player do |player|
game_player.width = 1 player.character_ID += 1
game_player.height = 1
game_player.sprite_size = [Game_Map::TILE_WIDTH, Game_Map::TILE_HEIGHT]
game_player.pattern_surf ||= 0
game_player.lock_pattern ||= false
game_player.move_speed = game_player.move_speed
end end
end end
SaveData.register_conversion(:v19_convert_game_screen) do #===============================================================================
essentials_version 19
display_title 'Converting game screen' SaveData.register_conversion(:v20_add_pokedex_records) do
essentials_version 20
display_title "Adding more Pokédex records"
to_value :player do |player|
player.pokedex.instance_eval do
@caught_counts = {} if @caught_counts.nil?
@defeated_counts = {} if @defeated_counts.nil?
@seen_eggs = {} if @seen_eggs.nil?
@seen_forms.each_value do |sp|
next if !sp || sp[0][0].is_a?(Array) # Already converted to include shininess
sp[0] = [sp[0], []]
sp[1] = [sp[1], []]
end
end
end
end
#===============================================================================
SaveData.register_conversion(:v20_add_new_default_options) do
essentials_version 20
display_title "Updating Options to include new settings"
to_value :pokemon_system do |option|
option.givenicknames = 0 if option.givenicknames.nil?
option.sendtoboxes = 0 if option.sendtoboxes.nil?
end
end
#===============================================================================
SaveData.register_conversion(:v20_fix_default_weather_type) do
essentials_version 20
display_title "Fixing weather type 0 in effect"
to_value :game_screen do |game_screen| to_value :game_screen do |game_screen|
game_screen.weather(game_screen.weather_type, game_screen.weather_max, 0) game_screen.instance_eval do
@weather_type = :None if @weather_type == 0
end
end
end
#===============================================================================
SaveData.register_conversion(:v20_add_stats) do
essentials_version 20
display_title "Adding stats to save data"
to_all do |save_data|
unless save_data.has_key?(:stats)
save_data[:stats] = GameStats.new
save_data[:stats].play_time = save_data[:frame_count].to_f / Graphics.frame_rate
save_data[:stats].play_sessions = 1
save_data[:stats].time_last_saved = save_data[:stats].play_time
end
end
end
#===============================================================================
SaveData.register_conversion(:v20_convert_pokemon_markings) do
essentials_version 20
display_title "Updating format of Pokémon markings"
to_all do |save_data|
# Create a lambda function that updates a Pokémon's markings
update_markings = lambda do |pkmn|
return if !pkmn || !pkmn.markings.is_a?(Integer)
markings = []
6.times { |i| markings[i] = ((pkmn.markings & (1 << i)) == 0) ? 0 : 1 }
pkmn.markings = markings
end
# Party Pokémon
save_data[:player].party.each { |pkmn| update_markings.call(pkmn) }
# Pokémon storage
save_data[:storage_system].boxes.each do |box|
box.pokemon.each { |pkmn| update_markings.call(pkmn) if pkmn }
end
# NOTE: Pokémon in the Day Care have their markings converted above.
# Partner trainer
if save_data[:global_metadata].partner
save_data[:global_metadata].partner[3].each { |pkmn| update_markings.call(pkmn) }
end
# Roaming Pokémon
if save_data[:global_metadata].roamPokemon
save_data[:global_metadata].roamPokemon.each { |pkmn| update_markings.call(pkmn) }
end
# Purify Chamber
save_data[:global_metadata].purifyChamber.sets.each do |set|
set.list.each { |pkmn| update_markings.call(pkmn) }
update_markings.call(set.shadow) if set.shadow
end
# Hall of Fame records
if save_data[:global_metadata].hallOfFame
save_data[:global_metadata].hallOfFame.each do |team|
next if !team
team.each { |pkmn| update_markings.call(pkmn) }
end
end
# Pokémon stored in Game Variables for some reason
variables = save_data[:variables]
(0..5000).each do |i|
value = variables[i]
case value
when Array
value.each { |value2| update_markings.call(value2) if value2.is_a?(Pokemon) }
when Pokemon
update_markings.call(value)
end
end
end end
end end

View File

@@ -2,18 +2,17 @@
module Game module Game
# Initializes various global variables and loads the game data. # Initializes various global variables and loads the game data.
def self.initialize def self.initialize
$PokemonTemp = PokemonTemp.new
$game_temp = Game_Temp.new $game_temp = Game_Temp.new
$game_system = Game_System.new $game_system = Game_System.new
$data_animations = load_data('Data/Animations.rxdata') $data_animations = load_data("Data/Animations.rxdata")
$data_tilesets = load_data('Data/Tilesets.rxdata') $data_tilesets = load_data("Data/Tilesets.rxdata")
$data_common_events = load_data('Data/CommonEvents.rxdata') $data_common_events = load_data("Data/CommonEvents.rxdata")
$data_system = load_data('Data/System.rxdata') $data_system = load_data("Data/System.rxdata")
pbLoadBattleAnimations pbLoadBattleAnimations
GameData.load_all GameData.load_all
map_file = format('Data/Map%03d.rxdata', $data_system.start_map_id) map_file = sprintf("Data/Map%03d.rxdata", $data_system.start_map_id)
if $data_system.start_map_id == 0 || !pbRgssExists?(map_file) if $data_system.start_map_id == 0 || !pbRgssExists?(map_file)
raise _INTL('No starting position was set in the map editor.') raise _INTL("No starting position was set in the map editor.")
end end
end end
@@ -32,21 +31,22 @@ module Game
# Set language (and choose language if there is no save file) # Set language (and choose language if there is no save file)
if Settings::LANGUAGES.length >= 2 if Settings::LANGUAGES.length >= 2
$PokemonSystem.language = pbChooseLanguage if save_data.empty? $PokemonSystem.language = pbChooseLanguage if save_data.empty?
pbLoadMessages('Data/' + Settings::LANGUAGES[$PokemonSystem.language][1]) pbLoadMessages("Data/" + Settings::LANGUAGES[$PokemonSystem.language][1])
end end
end end
# Called when starting a new game. Initializes global variables # Called when starting a new game. Initializes global variables
# and transfers the player into the map scene. # and transfers the player into the map scene.
def self.start_new def self.start_new
if $game_map && $game_map.events if $game_map&.events
$game_map.events.each_value { |event| event.clear_starting } $game_map.events.each_value { |event| event.clear_starting }
end end
$game_temp.common_event_id = 0 if $game_temp $game_temp.common_event_id = 0 if $game_temp
$PokemonTemp.begunNewGame = true $game_temp.begun_new_game = true
$scene = Scene_Map.new $scene = Scene_Map.new
SaveData.load_new_game_values SaveData.load_new_game_values
$MapFactory = PokemonMapFactory.new($data_system.start_map_id) $stats.play_sessions += 1
$map_factory = PokemonMapFactory.new($data_system.start_map_id)
$game_player.moveto($data_system.start_x, $data_system.start_y) $game_player.moveto($data_system.start_x, $data_system.start_y)
$game_player.refresh $game_player.refresh
$PokemonEncounters = PokemonEncounters.new $PokemonEncounters = PokemonEncounters.new
@@ -61,6 +61,7 @@ module Game
def self.load(save_data) def self.load(save_data)
validate save_data => Hash validate save_data => Hash
SaveData.load_all_values(save_data) SaveData.load_all_values(save_data)
$stats.play_sessions += 1
self.load_map self.load_map
pbAutoplayOnSave pbAutoplayOnSave
$game_map.update $game_map.update
@@ -70,31 +71,31 @@ module Game
# Loads and validates the map. Called when loading a saved game. # Loads and validates the map. Called when loading a saved game.
def self.load_map def self.load_map
$game_map = $MapFactory.map $game_map = $map_factory.map
magic_number_matches = ($game_system.magic_number == $data_system.magic_number) magic_number_matches = ($game_system.magic_number == $data_system.magic_number)
if !magic_number_matches || $PokemonGlobal.safesave if !magic_number_matches || $PokemonGlobal.safesave
if pbMapInterpreterRunning? if pbMapInterpreterRunning?
pbMapInterpreter.setup(nil, 0) pbMapInterpreter.setup(nil, 0)
end end
begin begin
$MapFactory.setup($game_map.map_id) $map_factory.setup($game_map.map_id)
rescue Errno::ENOENT rescue Errno::ENOENT
if $DEBUG if $DEBUG
pbMessage(_INTL('Map {1} was not found.', $game_map.map_id)) pbMessage(_INTL("Map {1} was not found.", $game_map.map_id))
map = pbWarpToMap map = pbWarpToMap
exit unless map exit unless map
$MapFactory.setup(map[0]) $map_factory.setup(map[0])
$game_player.moveto(map[1], map[2]) $game_player.moveto(map[1], map[2])
else else
raise _INTL('The map was not found. The game cannot continue.') raise _INTL("The map was not found. The game cannot continue.")
end end
end end
$game_player.center($game_player.x, $game_player.y) $game_player.center($game_player.x, $game_player.y)
else else
$MapFactory.setMapChanged($game_map.map_id) $map_factory.setMapChanged($game_map.map_id)
end end
if $game_map.events.nil? if $game_map.events.nil?
raise _INTL('The map is corrupt. The game cannot continue.') raise _INTL("The map is corrupt. The game cannot continue.")
end end
$PokemonEncounters = PokemonEncounters.new $PokemonEncounters = PokemonEncounters.new
$PokemonEncounters.setup($game_map.map_id) $PokemonEncounters.setup($game_map.map_id)
@@ -111,6 +112,7 @@ module Game
$PokemonGlobal.safesave = safe $PokemonGlobal.safesave = safe
$game_system.save_count += 1 $game_system.save_count += 1
$game_system.magic_number = $data_system.magic_number $game_system.magic_number = $data_system.magic_number
$stats.set_time_last_saved
begin begin
SaveData.save_to_file(save_file) SaveData.save_to_file(save_file)
Graphics.frame_reset Graphics.frame_reset

View File

@@ -5,35 +5,38 @@
#=============================================================================== #===============================================================================
class Scene_Map class Scene_Map
attr_reader :spritesetGlobal attr_reader :spritesetGlobal
attr_reader :map_renderer
def spriteset def spriteset(map_id = -1)
for i in @spritesets.values return @spritesets[map_id] if map_id > 0 && @spritesets[map_id]
@spritesets.each_value do |i|
return i if i.map == $game_map return i if i.map == $game_map
end end
return @spritesets.values[0] return @spritesets.values[0]
end end
def createSpritesets def createSpritesets
@map_renderer = TilemapRenderer.new(Spriteset_Map.viewport)
@spritesetGlobal = Spriteset_Global.new @spritesetGlobal = Spriteset_Global.new
@spritesets = {} @spritesets = {}
for map in $MapFactory.maps $map_factory.maps.each do |map|
@spritesets[map.map_id] = Spriteset_Map.new(map) @spritesets[map.map_id] = Spriteset_Map.new(map)
end end
$MapFactory.setSceneStarted(self) $map_factory.setSceneStarted(self)
updateSpritesets updateSpritesets
end end
def createSingleSpriteset(map) def createSingleSpriteset(map)
temp = $scene.spriteset.getAnimations temp = $scene.spriteset.getAnimations
@spritesets[map] = Spriteset_Map.new($MapFactory.maps[map]) @spritesets[map] = Spriteset_Map.new($map_factory.maps[map])
$scene.spriteset.restoreAnimations(temp) $scene.spriteset.restoreAnimations(temp)
$MapFactory.setSceneStarted(self) $map_factory.setSceneStarted(self)
updateSpritesets updateSpritesets
end end
def disposeSpritesets def disposeSpritesets
return if !@spritesets return if !@spritesets
for i in @spritesets.keys @spritesets.each_key do |i|
next if !@spritesets[i] next if !@spritesets[i]
@spritesets[i].dispose @spritesets[i].dispose
@spritesets[i] = nil @spritesets[i] = nil
@@ -42,6 +45,8 @@ class Scene_Map
@spritesets = {} @spritesets = {}
@spritesetGlobal.dispose @spritesetGlobal.dispose
@spritesetGlobal = nil @spritesetGlobal = nil
@map_renderer.dispose
@map_renderer = nil
end end
def autofade(mapid) def autofade(mapid)
@@ -50,26 +55,25 @@ class Scene_Map
return if !playingBGM && !playingBGS return if !playingBGM && !playingBGS
map = load_data(sprintf("Data/Map%03d.rxdata", mapid)) map = load_data(sprintf("Data/Map%03d.rxdata", mapid))
if playingBGM && map.autoplay_bgm if playingBGM && map.autoplay_bgm
if (PBDayNight.isNight? rescue false) if (PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/" + map.bgm.name + "_n") &&
pbBGMFade(0.8) if playingBGM.name!=map.bgm.name && playingBGM.name!=map.bgm.name+"_n" playingBGM.name != map.bgm.name + "_n") || playingBGM.name != map.bgm.name
else pbBGMFade(0.8)
pbBGMFade(0.8) if playingBGM.name!=map.bgm.name
end end
end end
if playingBGS && map.autoplay_bgs if playingBGS && map.autoplay_bgs && playingBGS.name != map.bgs.name
pbBGMFade(0.8) if playingBGS.name!=map.bgs.name pbBGMFade(0.8)
end end
Graphics.frame_reset Graphics.frame_reset
end end
def transfer_player(cancelVehicles=true) def transfer_player(cancel_swimming = true)
$game_temp.player_transferring = false $game_temp.player_transferring = false
pbCancelVehicles($game_temp.player_new_map_id) if cancelVehicles pbCancelVehicles($game_temp.player_new_map_id, cancel_swimming)
autofade($game_temp.player_new_map_id) autofade($game_temp.player_new_map_id)
pbBridgeOff pbBridgeOff
@spritesetGlobal.playersprite.clearShadows @spritesetGlobal.playersprite.clearShadows
if $game_map.map_id != $game_temp.player_new_map_id if $game_map.map_id != $game_temp.player_new_map_id
$MapFactory.setup($game_temp.player_new_map_id) $map_factory.setup($game_temp.player_new_map_id)
end end
$game_player.moveto($game_temp.player_new_x, $game_temp.player_new_y) $game_player.moveto($game_temp.player_new_x, $game_temp.player_new_y)
case $game_temp.player_new_direction case $game_temp.player_new_direction
@@ -79,13 +83,14 @@ class Scene_Map
when 8 then $game_player.turn_up when 8 then $game_player.turn_up
end end
$game_player.straighten $game_player.straighten
$game_temp.followers.map_transfer_followers
$game_map.update $game_map.update
disposeSpritesets disposeSpritesets
RPG::Cache.clear RPG::Cache.clear
createSpritesets createSpritesets
if $game_temp.transition_processing if $game_temp.transition_processing
$game_temp.transition_processing = false $game_temp.transition_processing = false
Graphics.transition(20) Graphics.transition
end end
$game_map.autoplay $game_map.autoplay
Graphics.frame_reset Graphics.frame_reset
@@ -111,60 +116,62 @@ class Scene_Map
end end
def miniupdate def miniupdate
$PokemonTemp.miniupdate = true $game_temp.in_mini_update = true
loop do loop do
updateMaps
$game_player.update $game_player.update
updateMaps
$game_system.update $game_system.update
$game_screen.update $game_screen.update
break unless $game_temp.player_transferring break unless $game_temp.player_transferring
transfer_player transfer_player(false)
break if $game_temp.transition_processing break if $game_temp.transition_processing
end end
updateSpritesets updateSpritesets
$PokemonTemp.miniupdate = false $game_temp.in_mini_update = false
end end
def updateMaps def updateMaps
for map in $MapFactory.maps $map_factory.maps.each do |map|
map.update map.update
end end
$MapFactory.updateMaps(self) $map_factory.updateMaps(self)
end end
def updateSpritesets def updateSpritesets
@spritesets = {} if !@spritesets @spritesets = {} if !@spritesets
$map_factory.maps.each do |map|
@spritesets[map.map_id] = Spriteset_Map.new(map) if !@spritesets[map.map_id]
end
keys = @spritesets.keys.clone keys = @spritesets.keys.clone
for i in keys keys.each do |i|
if !$MapFactory.hasMap?(i) if $map_factory.hasMap?(i)
@spritesets[i].dispose if @spritesets[i] @spritesets[i].update
else
@spritesets[i]&.dispose
@spritesets[i] = nil @spritesets[i] = nil
@spritesets.delete(i) @spritesets.delete(i)
else
@spritesets[i].update
end end
end end
@spritesetGlobal.update @spritesetGlobal.update
for map in $MapFactory.maps pbDayNightTint(@map_renderer)
@spritesets[map.map_id] = Spriteset_Map.new(map) if !@spritesets[map.map_id] @map_renderer.update
end EventHandlers.trigger(:on_frame_update)
Events.onMapUpdate.trigger(self)
end end
def update def update
loop do loop do
updateMaps
pbMapInterpreter.update pbMapInterpreter.update
$game_player.update $game_player.update
updateMaps
$game_system.update $game_system.update
$game_screen.update $game_screen.update
break unless $game_temp.player_transferring break unless $game_temp.player_transferring
transfer_player transfer_player(false)
break if $game_temp.transition_processing break if $game_temp.transition_processing
end end
updateSpritesets updateSpritesets
if $game_temp.to_title if $game_temp.title_screen_calling
$game_temp.to_title = false $game_temp.title_screen_calling = false
SaveData.mark_values_as_unloaded SaveData.mark_values_as_unloaded
$scene = pbCallTitle $scene = pbCallTitle
return return
@@ -172,7 +179,7 @@ class Scene_Map
if $game_temp.transition_processing if $game_temp.transition_processing
$game_temp.transition_processing = false $game_temp.transition_processing = false
if $game_temp.transition_name == "" if $game_temp.transition_name == ""
Graphics.transition(20) Graphics.transition
else else
Graphics.transition(40, "Graphics/Transitions/" + $game_temp.transition_name) Graphics.transition(40, "Graphics/Transitions/" + $game_temp.transition_name)
end end
@@ -180,15 +187,15 @@ class Scene_Map
return if $game_temp.message_window_showing return if $game_temp.message_window_showing
if !pbMapInterpreterRunning? if !pbMapInterpreterRunning?
if Input.trigger?(Input::USE) if Input.trigger?(Input::USE)
$PokemonTemp.hiddenMoveEventCalling = true $game_temp.interact_calling = true
elsif Input.trigger?(Input::BACK) elsif Input.trigger?(Input::ACTION)
unless $game_system.menu_disabled || $game_player.moving? unless $game_system.menu_disabled || $game_player.moving?
$game_temp.menu_calling = true $game_temp.menu_calling = true
$game_temp.menu_beep = true $game_temp.menu_beep = true
end end
elsif Input.trigger?(Input::SPECIAL) elsif Input.trigger?(Input::SPECIAL)
unless $game_player.moving? unless $game_player.moving?
$PokemonTemp.keyItemCalling = true $game_temp.ready_menu_calling = true
end end
elsif Input.press?(Input::F9) elsif Input.press?(Input::F9)
$game_temp.debug_calling = true if $DEBUG $game_temp.debug_calling = true if $DEBUG
@@ -199,21 +206,21 @@ class Scene_Map
call_menu call_menu
elsif $game_temp.debug_calling elsif $game_temp.debug_calling
call_debug call_debug
elsif $PokemonTemp.keyItemCalling elsif $game_temp.ready_menu_calling
$PokemonTemp.keyItemCalling = false $game_temp.ready_menu_calling = false
$game_player.straighten $game_player.straighten
pbUseKeyItem pbUseKeyItem
elsif $PokemonTemp.hiddenMoveEventCalling elsif $game_temp.interact_calling
$PokemonTemp.hiddenMoveEventCalling = false $game_temp.interact_calling = false
$game_player.straighten $game_player.straighten
Events.onAction.trigger(self) EventHandlers.trigger(:on_player_interact)
end end
end end
end end
def main def main
createSpritesets createSpritesets
Graphics.transition(20) Graphics.transition
loop do loop do
Graphics.update Graphics.update
Input.update Input.update
@@ -222,8 +229,8 @@ class Scene_Map
end end
Graphics.freeze Graphics.freeze
disposeSpritesets disposeSpritesets
if $game_temp.to_title if $game_temp.title_screen_calling
Graphics.transition(20) Graphics.transition
Graphics.freeze Graphics.freeze
end end
end end

View File

@@ -22,7 +22,7 @@ class Interpreter
def inspect def inspect
str = super.chop str = super.chop
str << format(' @event_id: %d>', @event_id) str << sprintf(" @event_id: %d>", @event_id)
return str return str
end end
@@ -35,6 +35,9 @@ class Interpreter
@child_interpreter = nil # child interpreter @child_interpreter = nil # child interpreter
@branch = {} # branch data @branch = {} # branch data
@buttonInput = false @buttonInput = false
@hidden_choices = []
@renamed_choices = []
end_follower_overrides
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Event Setup # * Event Setup
@@ -59,7 +62,7 @@ class Interpreter
return return
end end
# Check all map events for one that wants to start, and set it up # Check all map events for one that wants to start, and set it up
for event in $game_map.events.values $game_map.events.each_value do |event|
next if !event.starting next if !event.starting
if event.trigger < 3 # Isn't autorun or parallel processing if event.trigger < 3 # Isn't autorun or parallel processing
event.lock event.lock
@@ -69,7 +72,7 @@ class Interpreter
return return
end end
# Check all common events for one that is autorun, and set it up # Check all common events for one that is autorun, and set it up
for common_event in $data_common_events.compact $data_common_events.compact.each do |common_event|
next if common_event.trigger != 1 || !$game_switches[common_event.switch_id] next if common_event.trigger != 1 || !$game_switches[common_event.switch_id]
setup(common_event.list, 0) setup(common_event.list, 0)
return return
@@ -77,7 +80,7 @@ class Interpreter
end end
def running? def running?
return @list != nil return !@list.nil?
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Frame Update # * Frame Update
@@ -92,7 +95,7 @@ class Interpreter
end end
# If this interpreter's map isn't the current map or connected to it, # If this interpreter's map isn't the current map or connected to it,
# forget this interpreter's event ID # forget this interpreter's event ID
if $game_map.map_id != @map_id && !$MapFactory.areConnected?($game_map.map_id, @map_id) if $game_map.map_id != @map_id && !$map_factory.areConnected?($game_map.map_id, @map_id)
@event_id = 0 @event_id = 0
end end
# Update child interpreter if one exists # Update child interpreter if one exists
@@ -106,7 +109,10 @@ class Interpreter
# Do nothing if any event or the player is in the middle of a move route # Do nothing if any event or the player is in the middle of a move route
if @move_route_waiting if @move_route_waiting
return if $game_player.move_route_forcing return if $game_player.move_route_forcing
for event in $game_map.events.values $game_map.events.each_value do |event|
return if event.move_route_forcing
end
$game_temp.followers.each_follower do |event, follower|
return if event.move_route_forcing return if event.move_route_forcing
end end
@move_route_waiting = false @move_route_waiting = false
@@ -138,55 +144,42 @@ class Interpreter
return result return result
rescue Exception rescue Exception
e = $! e = $!
raise if e.is_a?(SystemExit) || "#{e.class}" == "Reset" raise if e.is_a?(SystemExit) || e.class.to_s == "Reset"
event = get_self event = get_self
s = "Backtrace:\r\n" # Gather text for error message
message = pbGetExceptionMessage(e) message = pbGetExceptionMessage(e)
backtrace_text = ""
if e.is_a?(SyntaxError) if e.is_a?(SyntaxError)
script.each_line { |line| script.each_line { |line|
line.gsub!(/\s+$/, "") line.gsub!(/\s+$/, "")
if line[/^\s*\(/] if line[/^\s*\(/]
message += "\r\n***Line '#{line}' shouldn't begin with '('. Try\r\n" message += "\r\n***Line '#{line}' shouldn't begin with '('. Try putting the '('\r\n"
message += "putting the '(' at the end of the previous line instead,\r\n" message += "at the end of the previous line instead, or using 'extendtext.exe'."
message += "or using 'extendtext.exe'."
end
if line[/\:\:\s*$/]
message += "\r\n***Line '#{line}' can't end with '::'. Try putting\r\n"
message += "the next word on the same line, e.g. 'PBSpecies:" + ":MEW'"
end end
} }
else else
for bt in e.backtrace[0, 10] backtrace_text += "\r\n"
s += bt + "\r\n" backtrace_text += "Backtrace:"
e.backtrace[0, 10].each { |i| backtrace_text += "\r\n#{i}" }
backtrace_text.gsub!(/Section(\d+)/) { $RGSS_SCRIPTS[$1.to_i][1] } rescue nil
backtrace_text += "\r\n"
end end
s.gsub!(/Section(\d+)/) { $RGSS_SCRIPTS[$1.to_i][1] } # Assemble error message
end err = "Script error in Interpreter\r\n"
message = "Exception: #{e.class}\r\nMessage: " + message + "\r\n" if $game_map
message += "\r\n***Full script:\r\n#{script}\r\n"
if event && $game_map
map_name = ($game_map.name rescue nil) || "???" map_name = ($game_map.name rescue nil) || "???"
err = "Script error in event #{event.id} (coords #{event.x},#{event.y}), map #{$game_map.map_id} (#{map_name}):\r\n" if event
err += "#{message}\r\n#{s}" err = "Script error in event #{event.id} (coords #{event.x},#{event.y}), map #{$game_map.map_id} (#{map_name})\r\n"
if e.is_a?(Hangup)
$EVENTHANGUPMSG = err
raise
end
elsif $game_map
map_name = ($game_map.name rescue nil) || "???"
err = "Script error in map #{$game_map.map_id} (#{map_name}):\r\n"
err += "#{message}\r\n#{s}"
if e.is_a?(Hangup)
$EVENTHANGUPMSG = err
raise
end
else else
err = "Script error in interpreter:\r\n#{message}\r\n#{s}" err = "Script error in Common Event, map #{$game_map.map_id} (#{map_name})\r\n"
if e.is_a?(Hangup)
$EVENTHANGUPMSG = err
raise
end end
end end
raise err err += "Exception: #{e.class}\r\n"
err += "Message: #{message}\r\n\r\n"
err += "***Full script:\r\n#{script}" # \r\n"
err += backtrace_text
# Raise error
raise EventScriptError.new(err)
end end
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@@ -221,13 +214,13 @@ class Interpreter
# * Freezes all events on the map (for use at the beginning of common events) # * Freezes all events on the map (for use at the beginning of common events)
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def pbGlobalLock def pbGlobalLock
$game_map.events.values.each { |event| event.minilock } $game_map.events.each_value { |event| event.minilock }
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Unfreezes all events on the map (for use at the end of common events) # * Unfreezes all events on the map (for use at the end of common events)
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def pbGlobalUnlock def pbGlobalUnlock
$game_map.events.values.each { |event| event.unlock } $game_map.events.each_value { |event| event.unlock }
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Gets the next index in the interpreter, ignoring certain commands between messages # * Gets the next index in the interpreter, ignoring certain commands between messages
@@ -281,12 +274,30 @@ class Interpreter
temp_index += 1 temp_index += 1
end end
end end
def follower_move_route(id = nil)
@follower_move_route = true
@follower_move_route_id = id
end
def follower_animation(id = nil)
@follower_animation = true
@follower_animation_id = id
end
def end_follower_overrides
@follower_move_route = false
@follower_move_route_id = nil
@follower_animation = false
@follower_animation_id = nil
end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Various methods to be used in a script event command. # * Various methods to be used in a script event command.
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# Helper function that shows a picture in a script. # Helper function that shows a picture in a script.
def pbShowPicture(number, name, origin, x, y, zoomX = 100, zoomY = 100, opacity = 255, blendType = 0) def pbShowPicture(number, name, origin, x, y, zoomX = 100, zoomY = 100, opacity = 255, blendType = 0)
number = number + ($game_temp.in_battle ? 50 : 0) number += ($game_temp.in_battle ? 50 : 0)
$game_screen.pictures[number].show(name, origin, x, y, zoomX, zoomY, opacity, blendType) $game_screen.pictures[number].show(name, origin, x, y, zoomX, zoomY, opacity, blendType)
end end
@@ -295,7 +306,7 @@ class Interpreter
def pbEraseThisEvent def pbEraseThisEvent
if $game_map.events[@event_id] if $game_map.events[@event_id]
$game_map.events[@event_id].erase $game_map.events[@event_id].erase
$PokemonMap.addErasedEvent(@event_id) if $PokemonMap $PokemonMap&.addErasedEvent(@event_id)
end end
@index += 1 @index += 1
return true return true
@@ -325,8 +336,8 @@ class Interpreter
mapid = @map_id if mapid < 0 mapid = @map_id if mapid < 0
old_value = $game_self_switches[[mapid, eventid, switch_name]] old_value = $game_self_switches[[mapid, eventid, switch_name]]
$game_self_switches[[mapid, eventid, switch_name]] = value $game_self_switches[[mapid, eventid, switch_name]] = value
if value != old_value && $MapFactory.hasMap?(mapid) if value != old_value && $map_factory.hasMap?(mapid)
$MapFactory.getMap(mapid, false).need_refresh = true $map_factory.getMap(mapid, false).need_refresh = true
end end
end end
@@ -368,7 +379,7 @@ class Interpreter
end end
def pbGetPokemon(id) def pbGetPokemon(id)
return $Trainer.party[pbGet(id)] return $player.party[pbGet(id)]
end end
def pbSetEventTime(*arg) def pbSetEventTime(*arg)
@@ -377,7 +388,7 @@ class Interpreter
time = time.to_i time = time.to_i
pbSetSelfSwitch(@event_id, "A", true) pbSetSelfSwitch(@event_id, "A", true)
$PokemonGlobal.eventvars[[@map_id, @event_id]] = time $PokemonGlobal.eventvars[[@map_id, @event_id]] = time
for otherevt in arg arg.each do |otherevt|
pbSetSelfSwitch(otherevt, "A", true) pbSetSelfSwitch(otherevt, "A", true)
$PokemonGlobal.eventvars[[@map_id, otherevt]] = time $PokemonGlobal.eventvars[[@map_id, otherevt]] = time
end end
@@ -391,13 +402,14 @@ class Interpreter
# Apply strict version of passable, which treats tiles that are passable # Apply strict version of passable, which treats tiles that are passable
# only from certain directions as fully impassible # only from certain directions as fully impassible
return if !event.can_move_in_direction?($game_player.direction, true) return if !event.can_move_in_direction?($game_player.direction, true)
$stats.strength_push_count += 1
case $game_player.direction case $game_player.direction
when 2 then event.move_down when 2 then event.move_down
when 4 then event.move_left when 4 then event.move_left
when 6 then event.move_right when 6 then event.move_right
when 8 then event.move_up when 8 then event.move_up
end end
$PokemonMap.addMovedEvent(@event_id) if $PokemonMap $PokemonMap&.addMovedEvent(@event_id)
if old_x != event.x || old_y != event.y if old_x != event.x || old_y != event.y
$game_player.lock $game_player.lock
loop do loop do
@@ -426,14 +438,14 @@ class Interpreter
return true if $DEBUG && !GameData::TrainerType.exists?(symbol) return true if $DEBUG && !GameData::TrainerType.exists?(symbol)
tr_type = GameData::TrainerType.get(symbol).id tr_type = GameData::TrainerType.get(symbol).id
pbGlobalLock pbGlobalLock
pbPlayTrainerIntroME(tr_type) pbPlayTrainerIntroBGM(tr_type)
return true return true
end end
def pbTrainerEnd def pbTrainerEnd
pbGlobalUnlock pbGlobalUnlock
event = get_self event = get_self
event.erase_route if event event&.erase_route
end end
def setPrice(item, buy_price = -1, sell_price = -1) def setPrice(item, buy_price = -1, sell_price = -1)
@@ -442,8 +454,8 @@ class Interpreter
$game_temp.mart_prices[item][0] = buy_price if buy_price > 0 $game_temp.mart_prices[item][0] = buy_price if buy_price > 0
if sell_price >= 0 # 0=can't sell if sell_price >= 0 # 0=can't sell
$game_temp.mart_prices[item][1] = sell_price * 2 $game_temp.mart_prices[item][1] = sell_price * 2
else elsif buy_price > 0
$game_temp.mart_prices[item][1] = buy_price if buy_price > 0 $game_temp.mart_prices[item][1] = buy_price
end end
end end

View File

@@ -126,6 +126,7 @@ class Interpreter
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_end def command_end
@list = nil @list = nil
end_follower_overrides
# If main map event and event ID are valid, unlock event # If main map event and event ID are valid, unlock event
if @main && @event_id > 0 && $game_map.events[@event_id] if @main && @event_id > 0 && $game_map.events[@event_id]
$game_map.events[@event_id].unlock $game_map.events[@event_id].unlock
@@ -158,7 +159,7 @@ class Interpreter
return false if $game_temp.message_window_showing return false if $game_temp.message_window_showing
message = @list[@index].parameters[0] message = @list[@index].parameters[0]
message_end = "" message_end = ""
commands = nil choices = nil
number_input_variable = nil number_input_variable = nil
number_input_max_digits = nil number_input_max_digits = nil
# Check the next command(s) for things to add on to this text # Check the next command(s) for things to add on to this text
@@ -174,8 +175,8 @@ class Interpreter
when 101 # Show Text when 101 # Show Text
message_end = "\1" message_end = "\1"
when 102 # Show Choices when 102 # Show Choices
commands = @list[next_index].parameters
@index = next_index @index = next_index
choices = setup_choices(@list[@index].parameters)
when 103 # Input Number when 103 # Input Number
number_input_variable = @list[next_index].parameters[0] number_input_variable = @list[next_index].parameters[0]
number_input_max_digits = @list[next_index].parameters[1] number_input_max_digits = @list[next_index].parameters[1]
@@ -185,15 +186,11 @@ class Interpreter
end end
# Translate the text # Translate the text
message = _MAPINTL($game_map.map_id, message) message = _MAPINTL($game_map.map_id, message)
# Display the text, with commands/number choosing if appropriate # Display the text, with choices/number choosing if appropriate
@message_waiting = true # Lets parallel process events work while a message is displayed @message_waiting = true # Lets parallel process events work while a message is displayed
if commands if choices
cmd_texts = [] command = pbMessage(message + message_end, choices[0], choices[1])
for cmd in commands[0] @branch[@list[@index].indent] = choices[2][command] || command
cmd_texts.push(_MAPINTL($game_map.map_id, cmd))
end
command = pbMessage(message + message_end, cmd_texts, commands[1])
@branch[@list[@index].indent] = command
elsif number_input_variable elsif number_input_variable
params = ChooseNumberParams.new params = ChooseNumberParams.new
params.setMaxDigits(number_input_max_digits) params.setMaxDigits(number_input_max_digits)
@@ -210,17 +207,93 @@ class Interpreter
# * Show Choices # * Show Choices
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_102 def command_102
choices = setup_choices(@list[@index].parameters)
@message_waiting = true @message_waiting = true
command = pbShowCommands(nil, @list[@index].parameters[0], @list[@index].parameters[1]) command = pbShowCommands(nil, choices[0], choices[1])
@message_waiting = false @message_waiting = false
@branch[@list[@index].indent] = command @branch[@list[@index].indent] = choices[2][command] || command
Input.update # Must call Input.update again to avoid extra triggers Input.update # Must call Input.update again to avoid extra triggers
return true return true
end end
def setup_choices(params)
# Get initial options
choices = params[0].clone
cancel_index = params[1]
# Clone @list so the original isn't modified
@list = Marshal.load(Marshal.dump(@list))
# Get more choices
@choice_branch_index = 4
ret = add_more_choices(choices, cancel_index, @index + 1, @list[@index].indent)
# Rename choices
ret[0].each_with_index { |choice, i| ret[0][i] = @renamed_choices[i] if @renamed_choices[i] }
@renamed_choices.clear
# Remove hidden choices
ret[2] = Array.new(ret[0].length) { |i| i }
@hidden_choices.each_with_index do |condition, i|
next if !condition
ret[0][i] = nil
ret[2][i] = nil
end
ret[0].compact!
ret[2].compact!
@hidden_choices.clear
# Translate choices
ret[0].map! { |ch| _MAPINTL($game_map.map_id, ch) }
return ret
end
def add_more_choices(choices, cancel_index, choice_index, indent)
# Find index of next command after the current Show Choices command
loop do
break if @list[choice_index].indent == indent && ![402, 403, 404].include?(@list[choice_index].code)
choice_index += 1
end
next_cmd = @list[choice_index]
# If the next command isn't another Show Choices, we're done
return [choices, cancel_index] if next_cmd.code != 102
# Add more choices
old_length = choices.length
choices += next_cmd.parameters[0]
# Update cancel option
if next_cmd.parameters[1] == 5 # Branch
cancel_index = choices.length + 1
@choice_branch_index = cancel_index - 1
elsif next_cmd.parameters[1] > 0 # A choice
cancel_index = old_length + next_cmd.parameters[1]
@choice_branch_index = -1
end
# Update first Show Choices command to include all options and result of cancelling
@list[@index].parameters[0] = choices
@list[@index].parameters[1] = cancel_index
# Find the "When" lines for this Show Choices command and update their index parameter
temp_index = choice_index + 1
loop do
break if @list[temp_index].indent == indent && ![402, 403, 404].include?(@list[temp_index].code)
if @list[temp_index].code == 402 && @list[temp_index].indent == indent
@list[temp_index].parameters[0] += old_length
end
temp_index += 1
end
# Delete the "Show Choices" line
@list.delete(next_cmd)
# Find more choices to add
return add_more_choices(choices, cancel_index, choice_index + 1, indent)
end
def hide_choice(number, condition = true)
@hidden_choices[number - 1] = condition
end
def rename_choice(number, new_name, condition = true)
return if !condition || nil_or_empty?(new_name)
@renamed_choices[number - 1] = new_name
end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * When [**] # * When [**]
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_402 def command_402
# @parameters[0] is 0/1/2/3 for Choice 1/2/3/4 respectively
if @branch[@list[@index].indent] == @parameters[0] if @branch[@list[@index].indent] == @parameters[0]
@branch.delete(@list[@index].indent) @branch.delete(@list[@index].indent)
return true return true
@@ -231,7 +304,8 @@ class Interpreter
# * When Cancel # * When Cancel
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_403 def command_403
if @branch[@list[@index].indent] == 4 # @parameters[0] is 4 for "Branch"
if @branch[@list[@index].indent] == @choice_branch_index
@branch.delete(@list[@index].indent) @branch.delete(@list[@index].indent)
return true return true
end end
@@ -271,7 +345,7 @@ class Interpreter
Input.update Input.update
pbUpdateSceneMap pbUpdateSceneMap
# Check for input and break if there is one # Check for input and break if there is one
for i in 1..18 (1..18).each do |i|
ret = i if Input.trigger?(i) ret = i if Input.trigger?(i)
end end
break if ret != 0 break if ret != 0
@@ -343,7 +417,7 @@ class Interpreter
character = get_character(@parameters[1]) character = get_character(@parameters[1])
result = (character.direction == @parameters[2]) if character result = (character.direction == @parameters[2]) if character
when 7 # gold when 7 # gold
gold = $Trainer.money gold = $player.money
result = (@parameters[2] == 0) ? (gold >= @parameters[1]) : (gold <= @parameters[1]) result = (@parameters[2] == 0) ? (gold >= @parameters[1]) : (gold <= @parameters[1])
# when 8, 9, 10 # item, weapon, armor # when 8, 9, 10 # item, weapon, armor
when 11 # button when 11 # button
@@ -413,8 +487,8 @@ class Interpreter
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_116 def command_116
if @event_id > 0 if @event_id > 0
$game_map.events[@event_id].erase if $game_map.events[@event_id] $game_map.events[@event_id]&.erase
$PokemonMap.addErasedEvent(@event_id) if $PokemonMap $PokemonMap&.addErasedEvent(@event_id)
end end
@index += 1 @index += 1
return false return false
@@ -459,7 +533,7 @@ class Interpreter
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_121 def command_121
should_refresh = false should_refresh = false
for i in @parameters[0]..@parameters[1] (@parameters[0]..@parameters[1]).each do |i|
next if $game_switches[i] == (@parameters[2] == 0) next if $game_switches[i] == (@parameters[2] == 0)
$game_switches[i] = (@parameters[2] == 0) $game_switches[i] = (@parameters[2] == 0)
should_refresh = true should_refresh = true
@@ -496,8 +570,8 @@ class Interpreter
when 7 # other when 7 # other
case @parameters[4] case @parameters[4]
when 0 then value = $game_map.map_id # map ID when 0 then value = $game_map.map_id # map ID
when 1 then value = $Trainer.pokemon_party.length # party members when 1 then value = $player.pokemon_party.length # party members
when 2 then value = $Trainer.money # gold when 2 then value = $player.money # gold
# when 3 # steps # when 3 # steps
when 4 then value = Graphics.frame_count / Graphics.frame_rate # play time when 4 then value = Graphics.frame_count / Graphics.frame_rate # play time
when 5 then value = $game_system.timer / Graphics.frame_rate # timer when 5 then value = $game_system.timer / Graphics.frame_rate # timer
@@ -505,29 +579,29 @@ class Interpreter
end end
end end
# Apply value and operation to all specified game variables # Apply value and operation to all specified game variables
for i in @parameters[0]..@parameters[1] (@parameters[0]..@parameters[1]).each do |i|
case @parameters[2] case @parameters[2]
when 0 # set when 0 # set
next if $game_variables[i] == value next if $game_variables[i] == value
$game_variables[i] = value $game_variables[i] = value
when 1 # add when 1 # add
next if $game_variables[i] >= 99999999 next if $game_variables[i] >= 99_999_999
$game_variables[i] += value $game_variables[i] += value
when 2 # subtract when 2 # subtract
next if $game_variables[i] <= -99999999 next if $game_variables[i] <= -99_999_999
$game_variables[i] -= value $game_variables[i] -= value
when 3 # multiply when 3 # multiply
next if value == 1 next if value == 1
$game_variables[i] *= value $game_variables[i] *= value
when 4 # divide when 4 # divide
next if value == 1 || value == 0 next if [0, 1].include?(value)
$game_variables[i] /= value $game_variables[i] /= value
when 5 # remainder when 5 # remainder
next if value == 1 || value == 0 next if [0, 1].include?(value)
$game_variables[i] %= value $game_variables[i] %= value
end end
$game_variables[i] = 99999999 if $game_variables[i] > 99999999 $game_variables[i] = 99_999_999 if $game_variables[i] > 99_999_999
$game_variables[i] = -99999999 if $game_variables[i] < -99999999 $game_variables[i] = -99_999_999 if $game_variables[i] < -99_999_999
$game_map.need_refresh = true $game_map.need_refresh = true
end end
return true return true
@@ -560,7 +634,7 @@ class Interpreter
def command_125 def command_125
value = (@parameters[1] == 0) ? @parameters[2] : $game_variables[@parameters[2]] value = (@parameters[1] == 0) ? @parameters[2] : $game_variables[@parameters[2]]
value = -value if @parameters[0] == 1 # Decrease value = -value if @parameters[0] == 1 # Decrease
$Trainer.money += value $player.money += value
return true return true
end end
@@ -572,7 +646,7 @@ class Interpreter
# * Change Windowskin # * Change Windowskin
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_131 def command_131
for i in 0...Settings::SPEECH_WINDOWSKINS.length Settings::SPEECH_WINDOWSKINS.length.times do |i|
next if Settings::SPEECH_WINDOWSKINS[i] != @parameters[0] next if Settings::SPEECH_WINDOWSKINS[i] != @parameters[0]
$PokemonSystem.textskin = i $PokemonSystem.textskin = i
MessageConfig.pbSetSpeechFrame("Graphics/Windowskins/" + Settings::SPEECH_WINDOWSKINS[i]) MessageConfig.pbSetSpeechFrame("Graphics/Windowskins/" + Settings::SPEECH_WINDOWSKINS[i])
@@ -590,10 +664,7 @@ class Interpreter
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Change Battle End ME # * Change Battle End ME
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_133 def command_133; command_dummy; end
($PokemonGlobal.nextBattleME = @parameters[0]) ? @parameters[0].clone : nil
return true
end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Change Save Access # * Change Save Access
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@@ -630,13 +701,12 @@ class Interpreter
$game_temp.player_new_map_id = @parameters[1] $game_temp.player_new_map_id = @parameters[1]
$game_temp.player_new_x = @parameters[2] $game_temp.player_new_x = @parameters[2]
$game_temp.player_new_y = @parameters[3] $game_temp.player_new_y = @parameters[3]
$game_temp.player_new_direction = @parameters[4]
else # Appoint with variables else # Appoint with variables
$game_temp.player_new_map_id = $game_variables[@parameters[1]] $game_temp.player_new_map_id = $game_variables[@parameters[1]]
$game_temp.player_new_x = $game_variables[@parameters[2]] $game_temp.player_new_x = $game_variables[@parameters[2]]
$game_temp.player_new_y = $game_variables[@parameters[3]] $game_temp.player_new_y = $game_variables[@parameters[3]]
$game_temp.player_new_direction = @parameters[4]
end end
$game_temp.player_new_direction = @parameters[4]
@index += 1 @index += 1
# If transition happens with a fade, do the fade # If transition happens with a fade, do the fade
if @parameters[5] == 0 if @parameters[5] == 0
@@ -654,9 +724,10 @@ class Interpreter
character = get_character(@parameters[0]) character = get_character(@parameters[0])
return true if character.nil? return true if character.nil?
# Move the character # Move the character
if @parameters[1] == 0 # Direct appointment case @parameters[1]
when 0 # Direct appointment
character.moveto(@parameters[2], @parameters[3]) character.moveto(@parameters[2], @parameters[3])
elsif @parameters[1] == 1 # Appoint with variables when 1 # Appoint with variables
character.moveto($game_variables[@parameters[2]], $game_variables[@parameters[3]]) character.moveto($game_variables[@parameters[2]], $game_variables[@parameters[3]])
else # Exchange with another event else # Exchange with another event
character2 = get_character(@parameters[2]) character2 = get_character(@parameters[2])
@@ -726,6 +797,11 @@ class Interpreter
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_207 def command_207
character = get_character(@parameters[0]) character = get_character(@parameters[0])
if @follower_animation
character = Followers.get(@follower_animation_id)
@follower_animation = false
@follower_animation_id = nil
end
return true if character.nil? return true if character.nil?
character.animation_id = @parameters[1] character.animation_id = @parameters[1]
return true return true
@@ -742,6 +818,11 @@ class Interpreter
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_209 def command_209
character = get_character(@parameters[0]) character = get_character(@parameters[0])
if @follower_move_route
character = Followers.get(@follower_move_route_id)
@follower_move_route = false
@follower_move_route_id = nil
end
return true if character.nil? return true if character.nil?
character.force_move_route(@parameters[1]) character.force_move_route(@parameters[1])
return true return true
@@ -931,18 +1012,19 @@ class Interpreter
# * Name Input Processing # * Name Input Processing
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_303 def command_303
if $Trainer if $player
$Trainer.name = pbEnterPlayerName(_INTL("Your name?"), 1, @parameters[1], $Trainer.name) $player.name = pbEnterPlayerName(_INTL("Your name?"), 1, @parameters[1], $player.name)
return true return true
end end
if $game_actors && $data_actors && $data_actors[@parameters[0]] != nil if $game_actors && $data_actors && $data_actors[@parameters[0]]
$game_temp.battle_abort = true $game_temp.battle_abort = true
pbFadeOutIn { pbFadeOutIn {
sscene = PokemonEntryScene.new sscene = PokemonEntryScene.new
sscreen = PokemonEntry.new(sscene) sscreen = PokemonEntry.new(sscene)
$game_actors[@parameters[0]].name = sscreen.pbStartScreen( $game_actors[@parameters[0]].name = sscreen.pbStartScreen(
_INTL("Enter {1}'s name.", $game_actors[@parameters[0]].name), _INTL("Enter {1}'s name.", $game_actors[@parameters[0]].name),
1, @parameters[1], $game_actors[@parameters[0]].name) 1, @parameters[1], $game_actors[@parameters[0]].name
)
} }
end end
return true return true
@@ -955,7 +1037,13 @@ class Interpreter
# * Recover All # * Recover All
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_314 def command_314
$Trainer.heal_party if @parameters[0] == 0 if @parameters[0] == 0
if Settings::HEAL_STORED_POKEMON # No need to heal stored Pokémon
$player.heal_party
else
pbEachPokemon { |pkmn, box| pkmn.heal } # Includes party Pokémon
end
end
return true return true
end end
@@ -1006,7 +1094,7 @@ class Interpreter
# * Return to Title Screen # * Return to Title Screen
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def command_354 def command_354
$game_temp.to_title = true $game_temp.title_screen_calling = true
return false return false
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------

View File

@@ -13,21 +13,15 @@ class Event
end end
# Removes an event handler procedure from the event. # Removes an event handler procedure from the event.
def -(method) def -(other)
for i in 0...@callbacks.length @callbacks.delete(other)
next if @callbacks[i]!=method
@callbacks.delete_at(i)
break
end
return self return self
end end
# Adds an event handler procedure from the event. # Adds an event handler procedure from the event.
def +(method) def +(other)
for i in 0...@callbacks.length return self if @callbacks.include?(other)
return self if @callbacks[i]==method @callbacks.push(other)
end
@callbacks.push(method)
return self return self
end end
@@ -45,7 +39,7 @@ class Event
# proc { |sender,arg0,arg1,...| } # proc { |sender,arg0,arg1,...| }
def trigger(*arg) def trigger(*arg)
arglist = arg[1, arg.length] arglist = arg[1, arg.length]
for callback in @callbacks @callbacks.each do |callback|
if callback.arity > 2 && arg.length == callback.arity if callback.arity > 2 && arg.length == callback.arity
# Retrofitted for callbacks that take three or more arguments # Retrofitted for callbacks that take three or more arguments
callback.call(*arg) callback.call(*arg)
@@ -59,14 +53,45 @@ class Event
# by the code where the event occurred. The first argument is the sender of # by the code where the event occurred. The first argument is the sender of
# the event, the other arguments are the event's parameters. # the event, the other arguments are the event's parameters.
def trigger2(*arg) def trigger2(*arg)
for callback in @callbacks @callbacks.each do |callback|
callback.call(*arg) callback.call(*arg)
end end
end end
end end
#=============================================================================== #===============================================================================
# # Same as class Event, but each registered proc has a name (a symbol) so it can
# be referenced individually.
#===============================================================================
class NamedEvent
def initialize
@callbacks = {}
end
# Adds an event handler procedure from the event.
def add(key, proc)
@callbacks[key] = proc if !@callbacks.has_key?(key)
end
# Removes an event handler procedure from the event.
def remove(key)
@callbacks.delete(key)
end
# Clears the event of event handlers.
def clear
@callbacks.clear
end
# Triggers the event and calls all its event handlers. Normally called only
# by the code where the event occurred.
def trigger(*args)
@callbacks.each_value { |callback| callback.call(*args) }
end
end
#===============================================================================
# Unused.
#=============================================================================== #===============================================================================
class HandlerHash class HandlerHash
def initialize(mod) def initialize(mod)
@@ -89,7 +114,7 @@ class HandlerHash
return ret if ret return ret if ret
mod = Object.const_get(@mod) rescue nil mod = Object.const_get(@mod) rescue nil
return nil if !mod return nil if !mod
for key in mod.constants mod.constants.each do |key|
next if mod.const_get(key) != sym next if mod.const_get(key) != sym
ret = key.to_sym ret = key.to_sym
@symbolCache[sym] = ret @symbolCache[sym] = ret
@@ -118,7 +143,7 @@ class HandlerHash
def copy(src, *dests) def copy(src, *dests)
handler = self[src] handler = self[src]
if handler if handler
for dest in dests dests.each do |dest|
self.add(dest, handler) self.add(dest, handler)
end end
end end
@@ -131,7 +156,7 @@ class HandlerHash
symbol = toSymbol(sym) symbol = toSymbol(sym)
ret = @hash[symbol] if symbol && @hash[symbol] # Symbol or string ret = @hash[symbol] if symbol && @hash[symbol] # Symbol or string
unless ret unless ret
for addif in @addIfs @addIfs.each do |addif|
return addif[1] if addif[0].call(id) return addif[1] if addif[0].call(id)
end end
end end
@@ -150,7 +175,8 @@ end
#=============================================================================== #===============================================================================
# A stripped-down version of class HandlerHash which only deals with symbols and # A stripped-down version of class HandlerHash which only deals with symbols and
# doesn't care about whether those symbols actually relate to a defined thing. # doesn't care about whether those symbols are defined as constants in a class
# or module.
#=============================================================================== #===============================================================================
class HandlerHash2 class HandlerHash2
def initialize def initialize
@@ -161,19 +187,12 @@ class HandlerHash2
def [](sym) def [](sym)
sym = sym.id if !sym.is_a?(Symbol) && sym.respond_to?("id") sym = sym.id if !sym.is_a?(Symbol) && sym.respond_to?("id")
return @hash[sym] if sym && @hash[sym] return @hash[sym] if sym && @hash[sym]
for add_if in @add_ifs @add_ifs.each do |add_if|
return add_if[1] if add_if[0].call(sym) return add_if[1] if add_if[0].call(sym)
end end
return nil return nil
end end
def addIf(conditionProc, handler = nil, &handlerBlock)
if ![Proc, Hash].include?(handler.class) && !block_given?
raise ArgumentError, "addIf call for #{self.class.name} has no valid handler (#{handler.inspect} was given)"
end
@add_ifs.push([conditionProc, handler || handlerBlock])
end
def add(sym, handler = nil, &handlerBlock) def add(sym, handler = nil, &handlerBlock)
if ![Proc, Hash].include?(handler.class) && !block_given? if ![Proc, Hash].include?(handler.class) && !block_given?
raise ArgumentError, "#{self.class.name} for #{sym.inspect} has no valid handler (#{handler.inspect} was given)" raise ArgumentError, "#{self.class.name} for #{sym.inspect} has no valid handler (#{handler.inspect} was given)"
@@ -181,12 +200,21 @@ class HandlerHash2
@hash[sym] = handler || handlerBlock if sym @hash[sym] = handler || handlerBlock if sym
end end
def addIf(conditionProc, handler = nil, &handlerBlock)
if ![Proc, Hash].include?(handler.class) && !block_given?
raise ArgumentError, "addIf call for #{self.class.name} has no valid handler (#{handler.inspect} was given)"
end
@add_ifs.push([conditionProc, handler || handlerBlock])
end
def copy(src, *dests) def copy(src, *dests)
handler = self[src] handler = self[src]
return if !handler return if !handler
for dest in dests dests.each { |dest| add(dest, handler) }
self.add(dest, handler)
end end
def remove(key)
@hash.delete(key)
end end
def clear def clear
@@ -196,7 +224,7 @@ class HandlerHash2
def trigger(sym, *args) def trigger(sym, *args)
sym = sym.id if !sym.is_a?(Symbol) && sym.respond_to?("id") sym = sym.id if !sym.is_a?(Symbol) && sym.respond_to?("id")
handler = self[sym] handler = self[sym]
return (handler) ? handler.call(sym, *args) : nil return handler&.call(sym, *args)
end end
end end
@@ -206,7 +234,6 @@ end
#=============================================================================== #===============================================================================
class HandlerHashBasic class HandlerHashBasic
def initialize def initialize
@ordered_keys = []
@hash = {} @hash = {}
@addIfs = [] @addIfs = []
end end
@@ -215,23 +242,18 @@ class HandlerHashBasic
ret = nil ret = nil
ret = @hash[entry] if entry && @hash[entry] ret = @hash[entry] if entry && @hash[entry]
unless ret unless ret
for addif in @addIfs @addIfs.each do |addif|
return addif[1] if addif[0].call(entry) return addif[1] if addif[0].call(entry)
end end
end end
return ret return ret
end end
def each
@ordered_keys.each { |key| yield key, @hash[key] }
end
def add(entry, handler = nil, &handlerBlock) def add(entry, handler = nil, &handlerBlock)
if ![Proc, Hash].include?(handler.class) && !block_given? if ![Proc, Hash].include?(handler.class) && !block_given?
raise ArgumentError, "#{self.class.name} for #{entry.inspect} has no valid handler (#{handler.inspect} was given)" raise ArgumentError, "#{self.class.name} for #{entry.inspect} has no valid handler (#{handler.inspect} was given)"
end end
return if !entry || entry.empty? return if !entry || entry.empty?
@ordered_keys.push(entry) if !@ordered_keys.include?(entry)
@hash[entry] = handler || handlerBlock @hash[entry] = handler || handlerBlock
end end
@@ -245,17 +267,28 @@ class HandlerHashBasic
def copy(src, *dests) def copy(src, *dests)
handler = self[src] handler = self[src]
return if !handler return if !handler
dests.each { |dest| self.add(dest, handler) } dests.each { |dest| add(dest, handler) }
end
def remove(key)
@hash.delete(key)
end end
def clear def clear
@hash.clear @hash.clear
@ordered_keys.clear end
def each
@hash.each_pair { |key, value| yield key, value }
end
def keys
return @hash.keys.clone
end end
def trigger(entry, *args) def trigger(entry, *args)
handler = self[entry] handler = self[entry]
return (handler) ? handler.call(*args) : nil return handler&.call(*args)
end end
end end

View File

@@ -0,0 +1,123 @@
#===============================================================================
# This module stores events that can happen during the game. A procedure can
# subscribe to an event by adding itself to the event. It will then be called
# whenever the event occurs. Existing events are:
#-------------------------------------------------------------------------------
# :on_game_map_setup - When a Game_Map is set up. Typically changes map data.
# :on_new_spriteset_map - When a Spriteset_Map is created. Adds more things to
# show in the overworld.
# :on_frame_update - Once per frame. Various frame/time counters.
# :on_leave_map - When leaving a map. End weather/expired effects.
# :on_enter_map - Upon entering a new map. Set up new effects, end expired
# effects.
# :on_map_or_spriteset_change - Upon entering a new map or when spriteset was
# made. Show things on-screen.
#-------------------------------------------------------------------------------
# :on_player_change_direction - When the player turns in a different direction.
# :on_leave_tile - When any event or the player starts to move from a tile.
# :on_step_taken - When any event or the player finishes a step.
# :on_player_step_taken - When the player finishes a step/ends surfing, except
# as part of a move route. Step-based counters.
# :on_player_step_taken_can_transfer - When the player finishes a step/ends
# surfing, except as part of a move route. Step-based effects that can
# transfer the player elsewhere.
# :on_player_interact - When the player presses the Use button in the
# overworld.
#-------------------------------------------------------------------------------
# :on_trainer_load - When an NPCTrainer is generated (to battle against or as
# a registered partner). Various modifications to that trainer and their
# Pokémon.
# :on_wild_species_chosen - When a species/level have been chosen for a wild
# encounter. Changes the species/level (e.g. roamer, Poké Radar chain).
# :on_wild_pokemon_created - When a Pokemon object has been created for a wild
# encounter. Various modifications to that Pokémon.
# :on_calling_wild_battle - When a wild battle is called. Prevents that wild
# battle and instead starts a different kind of battle (e.g. Safari Zone).
# :on_start_battle - Just before a battle starts. Memorize/reset information
# about party Pokémon, which is used after battle for evolution checks.
# :on_end_battle - Just after a battle ends. Evolution checks, Pickup/Honey
# Gather, blacking out.
# :on_wild_battle_end - After a wild battle. Updates Poké Radar chain info.
#===============================================================================
module EventHandlers
@@events = {}
# Add a named callback for the given event.
def self.add(event, key, proc)
@@events[event] = NamedEvent.new if !@@events.has_key?(event)
@@events[event].add(key, proc)
end
# Remove a named callback from the given event.
def self.remove(event, key)
@@events[event]&.remove(key)
end
# Clear all callbacks for the given event.
def self.clear(key)
@@events[key]&.clear
end
# Trigger all callbacks from an Event if it has been defined.
def self.trigger(event, *args)
return @@events[event]&.trigger(*args)
end
end
#===============================================================================
# This module stores the contents of various menus. Each command in a menu is a
# hash of data (containing its name, relative order, code to run when chosen,
# etc.).
# Menus that use this module are:
#-------------------------------------------------------------------------------
# Pause menu
# Party screen main interact menu
# Pokégear main menu
# Options screen
# PC main menu
# Various debug menus (main, Pokémon, battle, battle Pokémon)
#===============================================================================
module MenuHandlers
@@handlers = {}
def self.add(menu, option, hash)
@@handlers[menu] = HandlerHashBasic.new if !@@handlers.has_key?(menu)
@@handlers[menu].add(option, hash)
end
def self.remove(menu, option)
@@handlers[menu]&.remove(option)
end
def self.clear(menu)
@@handlers[menu]&.clear
end
def self.each(menu)
return if !@@handlers.has_key?(menu)
@@handlers[menu].each { |option, hash| yield option, hash }
end
def self.each_available(menu, *args)
return if !@@handlers.has_key?(menu)
options = @@handlers[menu]
keys = options.keys
sorted_keys = keys.sort_by { |option| options[option]["order"] || keys.index(option) }
sorted_keys.each do |option|
hash = options[option]
next if hash["condition"] && !hash["condition"].call(*args)
if hash["name"].is_a?(Proc)
name = hash["name"].call
else
name = _INTL(hash["name"])
end
yield option, hash, name
end
end
def self.call(menu, option, function, *args)
option_hash = @@handlers[menu][option]
return nil if !option_hash || !option_hash[function]
return option_hash[function].call(*args)
end
end

View File

@@ -1,172 +0,0 @@
#===============================================================================
# This module stores events that can happen during the game. A procedure can
# subscribe to an event by adding itself to the event. It will then be called
# whenever the event occurs.
#===============================================================================
module Events
@@OnMapCreate = Event.new
@@OnMapUpdate = Event.new
@@OnMapChange = Event.new
@@OnMapChanging = Event.new
@@OnMapSceneChange = Event.new
@@OnSpritesetCreate = Event.new
@@OnAction = Event.new
@@OnStepTaken = Event.new
@@OnLeaveTile = Event.new
@@OnStepTakenFieldMovement = Event.new
@@OnStepTakenTransferPossible = Event.new
@@OnStartBattle = Event.new
@@OnEndBattle = Event.new
@@OnWildPokemonCreate = Event.new
@@OnWildBattleOverride = Event.new
@@OnWildBattleEnd = Event.new
@@OnTrainerPartyLoad = Event.new
@@OnChangeDirection = Event.new
# Fires whenever a map is created. Event handler receives two parameters: the
# map (RPG::Map) and the tileset (RPG::Tileset)
def self.onMapCreate; @@OnMapCreate; end
def self.onMapCreate=(v); @@OnMapCreate = v; end
# Fires each frame during a map update.
def self.onMapUpdate; @@OnMapUpdate; end
def self.onMapUpdate=(v); @@OnMapUpdate = v; end
# Fires whenever one map is about to change to a different one. Event handler
# receives the new map ID and the Game_Map object representing the new map.
# When the event handler is called, $game_map still refers to the old map.
def self.onMapChanging; @@OnMapChanging; end
def self.onMapChanging=(v); @@OnMapChanging = v; end
# Fires whenever the player moves to a new map. Event handler receives the old
# map ID or 0 if none. Also fires when the first map of the game is loaded
def self.onMapChange; @@OnMapChange; end
def self.onMapChange=(v); @@OnMapChange = v; end
# Fires whenever the map scene is regenerated and soon after the player moves
# to a new map.
# Parameters:
# e[0] - Scene_Map object.
# e[1] - Whether the player just moved to a new map (either true or false). If
# false, some other code had called $scene.createSpritesets to
# regenerate the map scene without transferring the player elsewhere
def self.onMapSceneChange; @@OnMapSceneChange; end
def self.onMapSceneChange=(v); @@OnMapSceneChange = v; end
# Fires whenever a spriteset is created.
# Parameters:
# e[0] - Spriteset being created. e[0].map is the map associated with the
# spriteset (not necessarily the current map).
# e[1] - Viewport used for tilemap and characters
def self.onSpritesetCreate; @@OnSpritesetCreate; end
def self.onSpritesetCreate=(v); @@OnSpritesetCreate = v; end
# Triggers when the player presses the Action button on the map.
def self.onAction; @@OnAction; end
def self.onAction=(v); @@OnAction = v; end
# Fires whenever the player takes a step.
def self.onStepTaken; @@OnStepTaken; end
def self.onStepTaken=(v); @@OnStepTaken = v; end
# Fires whenever the player or another event leaves a tile.
# Parameters:
# e[0] - Event that just left the tile.
# e[1] - Map ID where the tile is located (not necessarily
# the current map). Use "$MapFactory.getMap(e[1])" to
# get the Game_Map object corresponding to that map.
# e[2] - X-coordinate of the tile
# e[3] - Y-coordinate of the tile
def self.onLeaveTile; @@OnLeaveTile; end
def self.onLeaveTile=(v); @@OnLeaveTile = v; end
# Fires whenever the player or another event enters a tile.
# Parameters:
# e[0] - Event that just entered a tile.
def self.onStepTakenFieldMovement; @@OnStepTakenFieldMovement; end
def self.onStepTakenFieldMovement=(v); @@OnStepTakenFieldMovement = v; end
# Fires whenever the player takes a step. The event handler may possibly move
# the player elsewhere.
# Parameters:
# e[0] - Array that contains a single boolean value. If an event handler moves
# the player to a new map, it should set this value to true. Other
# event handlers should check this parameter's value.
def self.onStepTakenTransferPossible; @@OnStepTakenTransferPossible; end
def self.onStepTakenTransferPossible=(v); @@OnStepTakenTransferPossible = v; end
def self.onStartBattle; @@OnStartBattle; end
def self.onStartBattle=(v); @@OnStartBattle = v; end
def self.onEndBattle; @@OnEndBattle; end
def self.onEndBattle=(v); @@OnEndBattle = v; end
# Triggers whenever a wild Pokémon is created
# Parameters:
# e[0] - Pokémon being created
def self.onWildPokemonCreate; @@OnWildPokemonCreate; end
def self.onWildPokemonCreate=(v); @@OnWildPokemonCreate = v; end
# Triggers at the start of a wild battle. Event handlers can provide their
# own wild battle routines to override the default behavior.
def self.onWildBattleOverride; @@OnWildBattleOverride; end
def self.onWildBattleOverride=(v); @@OnWildBattleOverride = v; end
# Triggers whenever a wild Pokémon battle ends
# Parameters:
# e[0] - Pokémon species
# e[1] - Pokémon level
# e[2] - Battle result (1-win, 2-loss, 3-escaped, 4-caught, 5-draw)
def self.onWildBattleEnd; @@OnWildBattleEnd; end
def self.onWildBattleEnd=(v); @@OnWildBattleEnd = v; end
# Triggers whenever an NPC trainer's Pokémon party is loaded
# Parameters:
# e[0] - Trainer
# e[1] - Items possessed by the trainer
# e[2] - Party
def self.onTrainerPartyLoad; @@OnTrainerPartyLoad; end
def self.onTrainerPartyLoad=(v); @@OnTrainerPartyLoad = v; end
# Fires whenever the player changes direction.
def self.onChangeDirection; @@OnChangeDirection; end
def self.onChangeDirection=(v); @@OnChangeDirection = v; end
end
#===============================================================================
#
#===============================================================================
def pbOnSpritesetCreate(spriteset,viewport)
Events.onSpritesetCreate.trigger(nil,spriteset,viewport)
end
#===============================================================================
# This module stores encounter-modifying events that can happen during the game.
# A procedure can subscribe to an event by adding itself to the event. It will
# then be called whenever the event occurs.
#===============================================================================
module EncounterModifier
@@procs = []
@@procsEnd = []
def self.register(p)
@@procs.push(p)
end
def self.registerEncounterEnd(p)
@@procsEnd.push(p)
end
def self.trigger(encounter)
for prc in @@procs
encounter = prc.call(encounter)
end
return encounter
end
def self.triggerEncounterEnd()
for prc in @@procsEnd
prc.call()
end
end
end

View File

@@ -17,6 +17,7 @@ class Game_Screen
attr_reader :weather_type # weather type attr_reader :weather_type # weather type
attr_reader :weather_max # max number of weather sprites attr_reader :weather_max # max number of weather sprites
attr_accessor :weather_duration # ticks in which the weather should fade in attr_accessor :weather_duration # ticks in which the weather should fade in
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Object Initialization # * Object Initialization
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@@ -35,10 +36,10 @@ class Game_Screen
@shake_direction = 1 @shake_direction = 1
@shake = 0 @shake = 0
@pictures = [nil] @pictures = [nil]
for i in 1..100 (1..100).each do |i|
@pictures.push(Game_Picture.new(i)) @pictures.push(Game_Picture.new(i))
end end
@weather_type = 0 @weather_type = :None
@weather_max = 0.0 @weather_max = 0.0
@weather_duration = 0 @weather_duration = 0
end end
@@ -96,15 +97,15 @@ class Game_Screen
end end
if @fadein_duration && @fadein_duration >= 1 if @fadein_duration && @fadein_duration >= 1
d = @fadein_duration d = @fadein_duration
@brightness = (@brightness*(d-1)+255)/d @brightness = ((@brightness * (d - 1)) + 255) / d
@fadein_duration -= 1 @fadein_duration -= 1
end end
if @tone_duration >= 1 if @tone_duration >= 1
d = @tone_duration d = @tone_duration
@tone.red = (@tone.red*(d-1)+@tone_target.red)/d @tone.red = ((@tone.red * (d - 1)) + @tone_target.red) / d
@tone.green = (@tone.green*(d-1)+@tone_target.green)/d @tone.green = ((@tone.green * (d - 1)) + @tone_target.green) / d
@tone.blue = (@tone.blue*(d-1)+@tone_target.blue)/d @tone.blue = ((@tone.blue * (d - 1)) + @tone_target.blue) / d
@tone.gray = (@tone.gray*(d-1)+@tone_target.gray)/d @tone.gray = ((@tone.gray * (d - 1)) + @tone_target.gray) / d
@tone_duration -= 1 @tone_duration -= 1
end end
if @flash_duration >= 1 if @flash_duration >= 1
@@ -124,11 +125,11 @@ class Game_Screen
@shake_duration -= 1 if @shake_duration >= 1 @shake_duration -= 1 if @shake_duration >= 1
end end
if $game_temp.in_battle if $game_temp.in_battle
for i in 51..100 (51..100).each do |i|
@pictures[i].update @pictures[i].update
end end
else else
for i in 1..50 (1..50).each do |i|
@pictures[i].update @pictures[i].update
end end
end end
@@ -140,8 +141,8 @@ end
#=============================================================================== #===============================================================================
def pbToneChangeAll(tone, duration) def pbToneChangeAll(tone, duration)
$game_screen.start_tone_change(tone, duration * Graphics.frame_rate / 20) $game_screen.start_tone_change(tone, duration * Graphics.frame_rate / 20)
for picture in $game_screen.pictures $game_screen.pictures.each do |picture|
picture.start_tone_change(tone,duration*Graphics.frame_rate/20) if picture picture&.start_tone_change(tone, duration * Graphics.frame_rate / 20)
end end
end end

View File

@@ -5,51 +5,86 @@
# Refer to "$game_temp" for the instance of this class. # Refer to "$game_temp" for the instance of this class.
#=============================================================================== #===============================================================================
class Game_Temp class Game_Temp
attr_accessor :message_window_showing # message window showing # Flags requesting something to happen
attr_accessor :common_event_id # common event ID
attr_accessor :in_battle # in-battle flag
attr_accessor :battle_abort # battle flag: interrupt
attr_accessor :battleback_name # battleback file name
attr_accessor :in_menu # menu is open
attr_accessor :menu_beep # menu: play sound effect flag
attr_accessor :menu_calling # menu calling flag attr_accessor :menu_calling # menu calling flag
attr_accessor :ready_menu_calling # ready menu calling flag
attr_accessor :debug_calling # debug calling flag attr_accessor :debug_calling # debug calling flag
attr_accessor :interact_calling # EventHandlers.trigger(:on_player_interact) flag
attr_accessor :battle_abort # battle flag: interrupt (unused)
attr_accessor :title_screen_calling # return to title screen flag
attr_accessor :common_event_id # common event ID to start
# Flags indicating something is happening
attr_accessor :in_menu # menu is open
attr_accessor :in_storage # in-Pokémon storage flag
attr_accessor :in_battle # in-battle flag
attr_accessor :message_window_showing # message window showing
attr_accessor :ending_surf # jumping off surf base flag
attr_accessor :surf_base_coords # [x, y] while jumping on/off, or nil
attr_accessor :in_mini_update # performing mini update flag
# Battle
attr_accessor :battleback_name # battleback file name
attr_accessor :force_single_battle # force next battle to be 1v1 flag
attr_accessor :waiting_trainer # [trainer, event ID] or nil
attr_accessor :last_battle_record # record of actions in last recorded battle
# Player transfers
attr_accessor :player_transferring # player place movement flag attr_accessor :player_transferring # player place movement flag
attr_accessor :player_new_map_id # player destination: map ID attr_accessor :player_new_map_id # player destination: map ID
attr_accessor :player_new_x # player destination: x-coordinate attr_accessor :player_new_x # player destination: x-coordinate
attr_accessor :player_new_y # player destination: y-coordinate attr_accessor :player_new_y # player destination: y-coordinate
attr_accessor :player_new_direction # player destination: direction attr_accessor :player_new_direction # player destination: direction
attr_accessor :fly_destination # [map ID, x, y] or nil
# Transitions
attr_accessor :transition_processing # transition processing flag attr_accessor :transition_processing # transition processing flag
attr_accessor :transition_name # transition file name attr_accessor :transition_name # transition file name
attr_accessor :to_title # return to title screen flag
attr_accessor :fadestate # for sprite hashes
attr_accessor :background_bitmap attr_accessor :background_bitmap
attr_accessor :fadestate # for sprite hashes
# Other
attr_accessor :begun_new_game # new game flag (true fron new game until saving)
attr_accessor :menu_beep # menu: play sound effect flag
attr_accessor :menu_last_choice # pause menu: index of last selection
attr_accessor :memorized_bgm # set when trainer intro BGM is played
attr_accessor :memorized_bgm_position # set when trainer intro BGM is played
attr_accessor :darkness_sprite # DarknessSprite or nil
attr_accessor :mart_prices attr_accessor :mart_prices
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Object Initialization # * Object Initialization
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def initialize def initialize
@message_window_showing = false # Flags requesting something to happen
@common_event_id = 0
@in_battle = false
@battle_abort = false
@battleback_name = ''
@in_menu = false
@menu_beep = false
@menu_calling = false @menu_calling = false
@ready_menu_calling = false
@debug_calling = false @debug_calling = false
@interact_calling = false
@battle_abort = false
@title_screen_calling = false
@common_event_id = 0
# Flags indicating something is happening
@in_menu = false
@in_storage = false
@in_battle = false
@message_window_showing = false
@ending_surf = false
@in_mini_update = false
# Battle
@battleback_name = ""
@force_single_battle = false
# Player transfers
@player_transferring = false @player_transferring = false
@player_new_map_id = 0 @player_new_map_id = 0
@player_new_x = 0 @player_new_x = 0
@player_new_y = 0 @player_new_y = 0
@player_new_direction = 0 @player_new_direction = 0
# Transitions
@transition_processing = false @transition_processing = false
@transition_name = "" @transition_name = ""
@to_title = false
@fadestate = 0 @fadestate = 0
@background_bitmap = nil # Other
@message_window_showing = false @begun_new_game = false
@transition_processing = false @menu_beep = false
@memorized_bgm = nil
@memorized_bgm_position = 0
@menu_last_choice = 0
@mart_prices = {} @mart_prices = {}
end end

View File

@@ -16,7 +16,7 @@ class Game_Switches
# switch_id : switch ID # switch_id : switch ID
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def [](switch_id) def [](switch_id)
return @data[switch_id] if switch_id <= 5000 && @data[switch_id] != nil return @data[switch_id] if switch_id <= 5000 && @data[switch_id]
return false return false
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------

View File

@@ -16,7 +16,7 @@ class Game_SelfSwitches
# key : key # key : key
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def [](key) def [](key)
return (@data[key]==true) ? true : false return @data[key] == true
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Set Self Switch # * Set Self Switch

View File

@@ -61,11 +61,10 @@ class Game_System
def bgm_play_internal(bgm, position) # :nodoc: def bgm_play_internal(bgm, position) # :nodoc:
@bgm_position = position if !@bgm_paused @bgm_position = position if !@bgm_paused
@playing_bgm = (bgm==nil) ? nil : bgm.clone @playing_bgm = bgm&.clone
if bgm!=nil && bgm.name!="" if bgm && bgm.name != ""
if FileTest.audio_exist?("Audio/BGM/"+bgm.name) if !@defaultBGM && FileTest.audio_exist?("Audio/BGM/" + bgm.name)
bgm_play_internal2("Audio/BGM/"+bgm.name, bgm_play_internal2("Audio/BGM/" + bgm.name, bgm.volume, bgm.pitch, @bgm_position)
bgm.volume,bgm.pitch,@bgm_position) if !@defaultBGM
end end
else else
@bgm_position = position if !@bgm_paused @bgm_position = position if !@bgm_paused
@@ -132,12 +131,11 @@ class Game_System
def setDefaultBGM(bgm, volume = 80, pitch = 100) def setDefaultBGM(bgm, volume = 80, pitch = 100)
bgm = RPG::AudioFile.new(bgm, volume, pitch) if bgm.is_a?(String) bgm = RPG::AudioFile.new(bgm, volume, pitch) if bgm.is_a?(String)
if bgm!=nil && bgm.name!=""
@defaultBGM = nil @defaultBGM = nil
if bgm && bgm.name != ""
self.bgm_play(bgm) self.bgm_play(bgm)
@defaultBGM = bgm.clone @defaultBGM = bgm.clone
else else
@defaultBGM = nil
self.bgm_play(@playing_bgm) self.bgm_play(@playing_bgm)
end end
end end
@@ -146,7 +144,7 @@ class Game_System
def me_play(me) def me_play(me)
me = RPG::AudioFile.new(me) if me.is_a?(String) me = RPG::AudioFile.new(me) if me.is_a?(String)
if me!=nil && me.name!="" if me && me.name != ""
if FileTest.audio_exist?("Audio/ME/" + me.name) if FileTest.audio_exist?("Audio/ME/" + me.name)
vol = me.volume vol = me.volume
vol *= $PokemonSystem.bgmvolume / 100.0 vol *= $PokemonSystem.bgmvolume / 100.0
@@ -162,8 +160,8 @@ class Game_System
################################################################################ ################################################################################
def bgs_play(bgs) def bgs_play(bgs)
@playing_bgs = (bgs==nil) ? nil : bgs.clone @playing_bgs = (bgs.nil?) ? nil : bgs.clone
if bgs!=nil && bgs.name!="" if bgs && bgs.name != ""
if FileTest.audio_exist?("Audio/BGS/" + bgs.name) if FileTest.audio_exist?("Audio/BGS/" + bgs.name)
vol = bgs.volume vol = bgs.volume
vol *= $PokemonSystem.sevolume / 100.0 vol *= $PokemonSystem.sevolume / 100.0
@@ -230,7 +228,7 @@ class Game_System
def se_play(se) def se_play(se)
se = RPG::AudioFile.new(se) if se.is_a?(String) se = RPG::AudioFile.new(se) if se.is_a?(String)
if se!=nil && se.name!="" && FileTest.audio_exist?("Audio/SE/"+se.name) if se && se.name != "" && FileTest.audio_exist?("Audio/SE/" + se.name)
vol = se.volume vol = se.volume
vol *= $PokemonSystem.sevolume / 100.0 vol *= $PokemonSystem.sevolume / 100.0
vol = vol.to_i vol = vol.to_i
@@ -248,36 +246,30 @@ class Game_System
return (@battle_bgm) ? @battle_bgm : $data_system.battle_bgm return (@battle_bgm) ? @battle_bgm : $data_system.battle_bgm
end end
def battle_bgm=(battle_bgm) attr_writer :battle_bgm
@battle_bgm = battle_bgm
end
def battle_end_me def battle_end_me
return (@battle_end_me) ? @battle_end_me : $data_system.battle_end_me return (@battle_end_me) ? @battle_end_me : $data_system.battle_end_me
end end
def battle_end_me=(battle_end_me) attr_writer :battle_end_me
@battle_end_me = battle_end_me
end
################################################################################ ################################################################################
def windowskin_name def windowskin_name
if @windowskin_name==nil if @windowskin_name.nil?
return $data_system.windowskin_name return $data_system.windowskin_name
else else
return @windowskin_name return @windowskin_name
end end
end end
def windowskin_name=(windowskin_name) attr_writer :windowskin_name
@windowskin_name = windowskin_name
end
def update def update
@timer -= 1 if @timer_working && @timer > 0 @timer -= 1 if @timer_working && @timer > 0
if Input.trigger?(Input::SPECIAL) && pbCurrentEventCommentInput(1, "Cut Scene") if Input.trigger?(Input::SPECIAL) && pbCurrentEventCommentInput(1, "Cut Scene")
event = @map_interpreter.get_character(0) event = @map_interpreter.get_self
@map_interpreter.pbSetSelfSwitch(event.id, "A", true) @map_interpreter.pbSetSelfSwitch(event.id, "A", true)
@map_interpreter.command_end @map_interpreter.command_end
event.start event.start

View File

@@ -20,6 +20,7 @@ class Game_Picture
attr_reader :blend_type # blend method attr_reader :blend_type # blend method
attr_reader :tone # color tone attr_reader :tone # color tone
attr_reader :angle # rotation angle attr_reader :angle # rotation angle
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Object Initialization # * Object Initialization
# number : picture number # number : picture number
@@ -65,7 +66,7 @@ class Game_Picture
@zoom_x = zoom_x.to_f @zoom_x = zoom_x.to_f
@zoom_y = zoom_y.to_f @zoom_y = zoom_y.to_f
@opacity = opacity.to_f @opacity = opacity.to_f
@blend_type = blend_type ? blend_type : 0 @blend_type = blend_type || 0
@duration = 0 @duration = 0
@target_x = @x @target_x = @x
@target_y = @y @target_y = @y
@@ -97,7 +98,7 @@ class Game_Picture
@target_zoom_x = zoom_x.to_f @target_zoom_x = zoom_x.to_f
@target_zoom_y = zoom_y.to_f @target_zoom_y = zoom_y.to_f
@target_opacity = opacity.to_f @target_opacity = opacity.to_f
@blend_type = blend_type ? blend_type : 0 @blend_type = blend_type || 0
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Change Rotation Speed # * Change Rotation Speed
@@ -130,19 +131,19 @@ class Game_Picture
def update def update
if @duration >= 1 if @duration >= 1
d = @duration d = @duration
@x = (@x * (d - 1) + @target_x) / d @x = ((@x * (d - 1)) + @target_x) / d
@y = (@y * (d - 1) + @target_y) / d @y = ((@y * (d - 1)) + @target_y) / d
@zoom_x = (@zoom_x * (d - 1) + @target_zoom_x) / d @zoom_x = ((@zoom_x * (d - 1)) + @target_zoom_x) / d
@zoom_y = (@zoom_y * (d - 1) + @target_zoom_y) / d @zoom_y = ((@zoom_y * (d - 1)) + @target_zoom_y) / d
@opacity = (@opacity * (d - 1) + @target_opacity) / d @opacity = ((@opacity * (d - 1)) + @target_opacity) / d
@duration -= 1 @duration -= 1
end end
if @tone_duration >= 1 if @tone_duration >= 1
d = @tone_duration d = @tone_duration
@tone.red = (@tone.red * (d - 1) + @tone_target.red) / d @tone.red = ((@tone.red * (d - 1)) + @tone_target.red) / d
@tone.green = (@tone.green * (d - 1) + @tone_target.green) / d @tone.green = ((@tone.green * (d - 1)) + @tone_target.green) / d
@tone.blue = (@tone.blue * (d - 1) + @tone_target.blue) / d @tone.blue = ((@tone.blue * (d - 1)) + @tone_target.blue) / d
@tone.gray = (@tone.gray * (d - 1) + @tone_target.gray) / d @tone.gray = ((@tone.gray * (d - 1)) + @tone_target.gray) / d
@tone_duration -= 1 @tone_duration -= 1
end end
if @rotate_speed != 0 if @rotate_speed != 0

View File

@@ -57,13 +57,13 @@ class Game_Map
self.display_x = 0 self.display_x = 0
self.display_y = 0 self.display_y = 0
@need_refresh = false @need_refresh = false
Events.onMapCreate.trigger(self,map_id,@map,tileset) EventHandlers.trigger(:on_game_map_setup, map_id, @map, tileset)
@events = {} @events = {}
for i in @map.events.keys @map.events.each_key do |i|
@events[i] = Game_Event.new(@map_id, @map.events[i], self) @events[i] = Game_Event.new(@map_id, @map.events[i], self)
end end
@common_events = {} @common_events = {}
for i in 1...$data_common_events.size (1...$data_common_events.size).each do |i|
@common_events[i] = Game_CommonEvent.new(i) @common_events[i] = Game_CommonEvent.new(i)
end end
@scroll_direction = 2 @scroll_direction = 2
@@ -95,43 +95,42 @@ class Game_Map
def encounter_list; return @map.encounter_list; end def encounter_list; return @map.encounter_list; end
def encounter_step; return @map.encounter_step; end def encounter_step; return @map.encounter_step; end
def data; return @map.data; end def data; return @map.data; end
def tileset_id; return @map.tileset_id; end
def bgm; return @map.bgm; end
def name def name
ret = pbGetMessage(MessageTypes::MapNames,@map_id) return pbGetMapNameFromId(@map_id)
ret.gsub!(/\\PN/,$Trainer.name) if $Trainer end
return ret
def metadata
return GameData::MapMetadata.try_get(@map_id)
end
#-----------------------------------------------------------------------------
# Returns the name of this map's BGM. If it's night time, returns the night
# version of the BGM (if it exists).
#-----------------------------------------------------------------------------
def bgm_name
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/" + @map.bgm.name + "_n")
return @map.bgm.name + "_n"
end
return @map.bgm.name
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Autoplays background music # * Autoplays background music
# Plays music called "[normal BGM]_n" if it's night time and it exists # Plays music called "[normal BGM]_n" if it's night time and it exists
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def autoplayAsCue def autoplayAsCue
if @map.autoplay_bgm pbCueBGM(bgm_name, 1.0, @map.bgm.volume, @map.bgm.pitch) if @map.autoplay_bgm
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/"+ @map.bgm.name+ "_n") pbBGSPlay(@map.bgs) if @map.autoplay_bgs
pbCueBGM(@map.bgm.name+"_n",1.0,@map.bgm.volume,@map.bgm.pitch)
else
pbCueBGM(@map.bgm,1.0)
end
end
if @map.autoplay_bgs
pbBGSPlay(@map.bgs)
end
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# * Plays background music # * Plays background music
# Plays music called "[normal BGM]_n" if it's night time and it exists # Plays music called "[normal BGM]_n" if it's night time and it exists
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def autoplay def autoplay
if @map.autoplay_bgm pbBGMPlay(bgm_name, @map.bgm.volume, @map.bgm.pitch) if @map.autoplay_bgm
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/"+ @map.bgm.name+ "_n") pbBGSPlay(@map.bgs) if @map.autoplay_bgs
pbBGMPlay(@map.bgm.name+"_n",@map.bgm.volume,@map.bgm.pitch)
else
pbBGMPlay(@map.bgm)
end
end
if @map.autoplay_bgs
pbBGSPlay(@map.bgs)
end
end end
def valid?(x, y) def valid?(x, y)
@@ -144,8 +143,8 @@ class Game_Map
def passable?(x, y, d, self_event = nil) def passable?(x, y, d, self_event = nil)
return false if !valid?(x, y) return false if !valid?(x, y)
bit = (1 << (d / 2 - 1)) & 0x0f bit = (1 << ((d / 2) - 1)) & 0x0f
for event in events.values events.each_value do |event|
next if event.tile_id <= 0 next if event.tile_id <= 0
next if event == self_event next if event == self_event
next if !event.at_coordinate?(x, y) next if !event.at_coordinate?(x, y)
@@ -183,14 +182,14 @@ class Game_Map
newy -= 1 newy -= 1
end end
return false if !valid?(newx, newy) return false if !valid?(newx, newy)
for i in [2, 1, 0] [2, 1, 0].each do |i|
tile_id = data[x, y, i] tile_id = data[x, y, i]
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id]) terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
# If already on water, only allow movement to another water tile # If already on water, only allow movement to another water tile
if self_event != nil && terrain.can_surf_freely if self_event && terrain.can_surf_freely
for j in [2, 1, 0] [2, 1, 0].each do |j|
facing_tile_id = data[newx, newy, j] facing_tile_id = data[newx, newy, j]
return false if facing_tile_id == nil return false if facing_tile_id.nil?
facing_terrain = GameData::TerrainTag.try_get(@terrain_tags[facing_tile_id]) facing_terrain = GameData::TerrainTag.try_get(@terrain_tags[facing_tile_id])
if facing_terrain.id != :None && !facing_terrain.ignore_passability if facing_terrain.id != :None && !facing_terrain.ignore_passability
return facing_terrain.can_surf_freely return facing_terrain.can_surf_freely
@@ -200,29 +199,28 @@ class Game_Map
# Can't walk onto ice # Can't walk onto ice
elsif terrain.ice elsif terrain.ice
return false return false
elsif self_event != nil && self_event.x == x && self_event.y == y elsif self_event && self_event.x == x && self_event.y == y
# Can't walk onto ledges # Can't walk onto ledges
for j in [2, 1, 0] [2, 1, 0].each do |j|
facing_tile_id = data[newx, newy, j] facing_tile_id = data[newx, newy, j]
return false if facing_tile_id == nil return false if facing_tile_id.nil?
facing_terrain = GameData::TerrainTag.try_get(@terrain_tags[facing_tile_id]) facing_terrain = GameData::TerrainTag.try_get(@terrain_tags[facing_tile_id])
return false if facing_terrain.ledge return false if facing_terrain.ledge
break if facing_terrain.id != :None && !facing_terrain.ignore_passability break if facing_terrain.id != :None && !facing_terrain.ignore_passability
end end
end end
next if terrain&.ignore_passability
# Regular passability checks # Regular passability checks
if !terrain || !terrain.ignore_passability
passage = @passages[tile_id] passage = @passages[tile_id]
return false if passage & bit != 0 || passage & 0x0f == 0x0f return false if passage & bit != 0 || passage & 0x0f == 0x0f
return true if @priorities[tile_id] == 0 return true if @priorities[tile_id] == 0
end end
end
return true return true
end end
def playerPassable?(x, y, d, self_event = nil) def playerPassable?(x, y, d, self_event = nil)
bit = (1 << (d / 2 - 1)) & 0x0f bit = (1 << ((d / 2) - 1)) & 0x0f
for i in [2, 1, 0] [2, 1, 0].each do |i|
tile_id = data[x, y, i] tile_id = data[x, y, i]
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id]) terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
passage = @passages[tile_id] passage = @passages[tile_id]
@@ -238,12 +236,11 @@ class Game_Map
return (passage & bit == 0 && passage & 0x0f != 0x0f) return (passage & bit == 0 && passage & 0x0f != 0x0f)
end end
end end
next if terrain&.ignore_passability
# Regular passability checks # Regular passability checks
if !terrain || !terrain.ignore_passability
return false if passage & bit != 0 || passage & 0x0f == 0x0f return false if passage & bit != 0 || passage & 0x0f == 0x0f
return true if @priorities[tile_id] == 0 return true if @priorities[tile_id] == 0
end end
end
return true return true
end end
@@ -251,14 +248,14 @@ class Game_Map
# event there, and the tile is fully passable in all directions) # event there, and the tile is fully passable in all directions)
def passableStrict?(x, y, d, self_event = nil) def passableStrict?(x, y, d, self_event = nil)
return false if !valid?(x, y) return false if !valid?(x, y)
for event in events.values events.each_value do |event|
next if event == self_event || event.tile_id < 0 || event.through next if event == self_event || event.tile_id < 0 || event.through
next if !event.at_coordinate?(x, y) next if !event.at_coordinate?(x, y)
next if GameData::TerrainTag.try_get(@terrain_tags[event.tile_id]).ignore_passability next if GameData::TerrainTag.try_get(@terrain_tags[event.tile_id]).ignore_passability
return false if @passages[event.tile_id] & 0x0f != 0 return false if @passages[event.tile_id] & 0x0f != 0
return true if @priorities[event.tile_id] == 0 return true if @priorities[event.tile_id] == 0
end end
for i in [2, 1, 0] [2, 1, 0].each do |i|
tile_id = data[x, y, i] tile_id = data[x, y, i]
next if GameData::TerrainTag.try_get(@terrain_tags[tile_id]).ignore_passability next if GameData::TerrainTag.try_get(@terrain_tags[tile_id]).ignore_passability
return false if @passages[tile_id] & 0x0f != 0 return false if @passages[tile_id] & 0x0f != 0
@@ -268,7 +265,7 @@ class Game_Map
end end
def bush?(x, y) def bush?(x, y)
for i in [2, 1, 0] [2, 1, 0].each do |i|
tile_id = data[x, y, i] tile_id = data[x, y, i]
return false if GameData::TerrainTag.try_get(@terrain_tags[tile_id]).bridge && return false if GameData::TerrainTag.try_get(@terrain_tags[tile_id]).bridge &&
$PokemonGlobal.bridge > 0 $PokemonGlobal.bridge > 0
@@ -278,7 +275,7 @@ class Game_Map
end end
def deepBush?(x, y) def deepBush?(x, y)
for i in [2, 1, 0] [2, 1, 0].each do |i|
tile_id = data[x, y, i] tile_id = data[x, y, i]
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id]) terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
return false if terrain.bridge && $PokemonGlobal.bridge > 0 return false if terrain.bridge && $PokemonGlobal.bridge > 0
@@ -288,7 +285,7 @@ class Game_Map
end end
def counter?(x, y) def counter?(x, y)
for i in [2, 1, 0] [2, 1, 0].each do |i|
tile_id = data[x, y, i] tile_id = data[x, y, i]
passage = @passages[tile_id] passage = @passages[tile_id]
return true if passage & 0x80 == 0x80 return true if passage & 0x80 == 0x80
@@ -298,7 +295,7 @@ class Game_Map
def terrain_tag(x, y, countBridge = false) def terrain_tag(x, y, countBridge = false)
if valid?(x, y) if valid?(x, y)
for i in [2, 1, 0] [2, 1, 0].each do |i|
tile_id = data[x, y, i] tile_id = data[x, y, i]
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id]) terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
next if terrain.id == :None || terrain.ignore_passability next if terrain.id == :None || terrain.ignore_passability
@@ -311,7 +308,7 @@ class Game_Map
# Unused. # Unused.
def check_event(x, y) def check_event(x, y)
for event in self.events.values self.events.each_value do |event|
return event.id if event.at_coordinate?(x, y) return event.id if event.at_coordinate?(x, y)
end end
end end
@@ -319,21 +316,21 @@ class Game_Map
def display_x=(value) def display_x=(value)
return if @display_x == value return if @display_x == value
@display_x = value @display_x = value
if GameData::MapMetadata.exists?(self.map_id) && GameData::MapMetadata.get(self.map_id).snap_edges if metadata&.snap_edges
max_x = (self.width - Graphics.width*1.0/TILE_WIDTH) * REAL_RES_X max_x = (self.width - (Graphics.width.to_f / TILE_WIDTH)) * REAL_RES_X
@display_x = [0, [@display_x, max_x].min].max @display_x = [0, [@display_x, max_x].min].max
end end
$MapFactory.setMapsInRange if $MapFactory $map_factory&.setMapsInRange
end end
def display_y=(value) def display_y=(value)
return if @display_y == value return if @display_y == value
@display_y = value @display_y = value
if GameData::MapMetadata.exists?(self.map_id) && GameData::MapMetadata.get(self.map_id).snap_edges if metadata&.snap_edges
max_y = (self.height - Graphics.height*1.0/TILE_HEIGHT) * REAL_RES_Y max_y = (self.height - (Graphics.height.to_f / TILE_HEIGHT)) * REAL_RES_Y
@display_y = [0, [@display_y, max_y].min].max @display_y = [0, [@display_y, max_y].min].max
end end
$MapFactory.setMapsInRange if $MapFactory $map_factory&.setMapsInRange
end end
def scroll_up(distance) def scroll_up(distance)
@@ -354,7 +351,7 @@ class Game_Map
def start_scroll(direction, distance, speed) def start_scroll(direction, distance, speed)
@scroll_direction = direction @scroll_direction = direction
if direction==2 || direction==8 # down or up if [2, 8].include?(direction) # down or up
@scroll_rest = distance * REAL_RES_Y @scroll_rest = distance * REAL_RES_Y
else else
@scroll_rest = distance * REAL_RES_X @scroll_rest = distance * REAL_RES_X
@@ -375,18 +372,26 @@ class Game_Map
end end
def start_fog_opacity_change(opacity, duration) def start_fog_opacity_change(opacity, duration)
@fog_opacity_target = opacity*1.0 @fog_opacity_target = opacity.to_f
@fog_opacity_duration = duration @fog_opacity_duration = duration
if @fog_opacity_duration == 0 if @fog_opacity_duration == 0
@fog_opacity = @fog_opacity_target @fog_opacity = @fog_opacity_target
end end
end end
def set_tile(x, y, layer, id = 0)
self.data[x, y, layer] = id
end
def erase_tile(x, y, layer)
set_tile(x, y, layer, 0)
end
def refresh def refresh
for event in @events.values @events.each_value do |event|
event.refresh event.refresh
end end
for common_event in @common_events.values @common_events.each_value do |common_event|
common_event.refresh common_event.refresh
end end
@need_refresh = false @need_refresh = false
@@ -394,11 +399,11 @@ class Game_Map
def update def update
# refresh maps if necessary # refresh maps if necessary
if $MapFactory if $map_factory
for i in $MapFactory.maps $map_factory.maps.each do |i|
i.refresh if i.need_refresh i.refresh if i.need_refresh
end end
$MapFactory.setCurrentMap $map_factory.setCurrentMap
end end
# If scrolling # If scrolling
if @scroll_rest > 0 if @scroll_rest > 0
@@ -413,11 +418,11 @@ class Game_Map
@scroll_rest -= distance @scroll_rest -= distance
end end
# Only update events that are on-screen # Only update events that are on-screen
for event in @events.values @events.each_value do |event|
event.update event.update
end end
# Update common events # Update common events
for common_event in @common_events.values @common_events.each_value do |common_event|
common_event.update common_event.update
end end
# Update fog # Update fog
@@ -426,15 +431,15 @@ class Game_Map
if @fog_tone_duration >= 1 if @fog_tone_duration >= 1
d = @fog_tone_duration d = @fog_tone_duration
target = @fog_tone_target target = @fog_tone_target
@fog_tone.red = (@fog_tone.red * (d - 1) + target.red) / d @fog_tone.red = ((@fog_tone.red * (d - 1)) + target.red) / d
@fog_tone.green = (@fog_tone.green * (d - 1) + target.green) / d @fog_tone.green = ((@fog_tone.green * (d - 1)) + target.green) / d
@fog_tone.blue = (@fog_tone.blue * (d - 1) + target.blue) / d @fog_tone.blue = ((@fog_tone.blue * (d - 1)) + target.blue) / d
@fog_tone.gray = (@fog_tone.gray * (d - 1) + target.gray) / d @fog_tone.gray = ((@fog_tone.gray * (d - 1)) + target.gray) / d
@fog_tone_duration -= 1 @fog_tone_duration -= 1
end end
if @fog_opacity_duration >= 1 if @fog_opacity_duration >= 1
d = @fog_opacity_duration d = @fog_opacity_duration
@fog_opacity = (@fog_opacity * (d - 1) + @fog_opacity_target) / d @fog_opacity = ((@fog_opacity * (d - 1)) + @fog_opacity_target) / d
@fog_opacity_duration -= 1 @fog_opacity_duration -= 1
end end
end end

View File

@@ -81,19 +81,34 @@ class Interpreter
if $game_map.scrolling? if $game_map.scrolling?
return false return false
elsif !$game_map.valid?(x, y) elsif !$game_map.valid?(x, y)
print 'Map Autoscroll: given x,y is invalid' print "Map Autoscroll: given x,y is invalid"
return command_skip return command_skip
elsif !(1..6).include?(speed) elsif !(1..6).include?(speed)
print 'Map Autoscroll: invalid speed (1-6 only)' print "Map Autoscroll: invalid speed (1-6 only)"
return command_skip return command_skip
end end
center_x = (Graphics.width/2 - Game_Map::TILE_WIDTH/2) * 4 # X coordinate in the center of the screen center_x = ((Graphics.width / 2) - (Game_Map::TILE_WIDTH / 2)) * 4 # X coordinate in the center of the screen
center_y = (Graphics.height/2 - Game_Map::TILE_HEIGHT/2) * 4 # Y coordinate in the center of the screen center_y = ((Graphics.height / 2) - (Game_Map::TILE_HEIGHT / 2)) * 4 # Y coordinate in the center of the screen
max_x = ($game_map.width - Graphics.width*1.0/Game_Map::TILE_WIDTH) * 4 * Game_Map::TILE_WIDTH max_x = ($game_map.width - (Graphics.width.to_f / Game_Map::TILE_WIDTH)) * 4 * Game_Map::TILE_WIDTH
max_y = ($game_map.height - Graphics.height*1.0/Game_Map::TILE_HEIGHT) * 4 * Game_Map::TILE_HEIGHT max_y = ($game_map.height - (Graphics.height.to_f / Game_Map::TILE_HEIGHT)) * 4 * Game_Map::TILE_HEIGHT
count_x = ($game_map.display_x - [0,[x*Game_Map::REAL_RES_X-center_x,max_x].min].max)/Game_Map::REAL_RES_X count_x = ($game_map.display_x - [0, [(x * Game_Map::REAL_RES_X) - center_x, max_x].min].max) / Game_Map::REAL_RES_X
count_y = ($game_map.display_y - [0,[y*Game_Map::REAL_RES_Y-center_y,max_y].min].max)/Game_Map::REAL_RES_Y count_y = ($game_map.display_y - [0, [(y * Game_Map::REAL_RES_Y) - center_y, max_y].min].max) / Game_Map::REAL_RES_Y
if !@diag if @diag
@diag = false
dir = nil
if count_x != 0 && count_y != 0
return false
elsif count_x > 0
dir = 4
elsif count_x < 0
dir = 6
elsif count_y > 0
dir = 8
elsif count_y < 0
dir = 2
end
count = count_x == 0 ? count_y.abs : count_x.abs
else
@diag = true @diag = true
dir = nil dir = nil
if count_x > 0 if count_x > 0
@@ -110,28 +125,9 @@ class Interpreter
end end
end end
count = [count_x.abs, count_y.abs].min count = [count_x.abs, count_y.abs].min
else
@diag = false
dir = nil
if count_x != 0 && count_y != 0
return false
elsif count_x > 0
dir = 4
elsif count_x < 0
dir = 6
elsif count_y > 0
dir = 8
elsif count_y < 0
dir = 2
end
count = count_x != 0 ? count_x.abs : count_y.abs
end
$game_map.start_scroll(dir, count, speed) if dir != nil
if @diag
return false
else
return true
end end
$game_map.start_scroll(dir, count, speed) if dir
return !@diag
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@@ -148,20 +144,20 @@ end
class Game_Map class Game_Map
def scroll_downright(distance) def scroll_downright(distance)
@display_x = [@display_x + distance, @display_x = [@display_x + distance,
(self.width - Graphics.width*1.0/TILE_WIDTH) * REAL_RES_X].min (self.width - (Graphics.width.to_f / TILE_WIDTH)) * REAL_RES_X].min
@display_y = [@display_y + distance, @display_y = [@display_y + distance,
(self.height - Graphics.height*1.0/TILE_HEIGHT) * REAL_RES_Y].min (self.height - (Graphics.height.to_f / TILE_HEIGHT)) * REAL_RES_Y].min
end end
def scroll_downleft(distance) def scroll_downleft(distance)
@display_x = [@display_x - distance, 0].max @display_x = [@display_x - distance, 0].max
@display_y = [@display_y + distance, @display_y = [@display_y + distance,
(self.height - Graphics.height*1.0/TILE_HEIGHT) * REAL_RES_Y].min (self.height - (Graphics.height.to_f / TILE_HEIGHT)) * REAL_RES_Y].min
end end
def scroll_upright(distance) def scroll_upright(distance)
@display_x = [@display_x + distance, @display_x = [@display_x + distance,
(self.width - Graphics.width*1.0/TILE_WIDTH) * REAL_RES_X].min (self.width - (Graphics.width.to_f / TILE_WIDTH)) * REAL_RES_X].min
@display_y = [@display_y - distance, 0].max @display_y = [@display_y - distance, 0].max
end end

View File

@@ -31,28 +31,28 @@ class PokemonMapFactory
return @maps[@mapIndex] if @maps[@mapIndex] return @maps[@mapIndex] if @maps[@mapIndex]
raise "No maps in save file... (mapIndex=#{@mapIndex})" if @maps.length == 0 raise "No maps in save file... (mapIndex=#{@mapIndex})" if @maps.length == 0
if @maps[0] if @maps[0]
echoln("Using next map, may be incorrect (mapIndex=#{@mapIndex}, length=#{@maps.length})") echoln "Using next map, may be incorrect (mapIndex=#{@mapIndex}, length=#{@maps.length})"
return @maps[0] return @maps[0]
end end
raise "No maps in save file... (all maps empty; mapIndex=#{@mapIndex})" raise "No maps in save file... (all maps empty; mapIndex=#{@mapIndex})"
end end
def hasMap?(id) def hasMap?(id)
for map in @maps @maps.each do |map|
return true if map.map_id == id return true if map.map_id == id
end end
return false return false
end end
def getMapIndex(id) def getMapIndex(id)
for i in 0...@maps.length @maps.length.times do |i|
return i if @maps[i].map_id == id return i if @maps[i].map_id == id
end end
return -1 return -1
end end
def getMap(id, add = true) def getMap(id, add = true)
for map in @maps @maps.each do |map|
return map if map.map_id == id return map if map.map_id == id
end end
map = Game_Map.new map = Game_Map.new
@@ -67,9 +67,7 @@ class PokemonMapFactory
def getNewMap(playerX, playerY) def getNewMap(playerX, playerY)
id = $game_map.map_id id = $game_map.map_id
conns = MapFactoryHelper.getMapConnections MapFactoryHelper.eachConnectionForMap(id) do |conn|
if conns[id]
for conn in conns[id]
mapidB = nil mapidB = nil
newx = 0 newx = 0
newy = 0 newy = 0
@@ -88,7 +86,6 @@ class PokemonMapFactory
return [getMap(mapidB), newx, newy] return [getMap(mapidB), newx, newy]
end end
end end
end
return nil return nil
end end
@@ -117,13 +114,11 @@ class PokemonMapFactory
return if @fixup return if @fixup
@fixup = true @fixup = true
id = $game_map.map_id id = $game_map.map_id
conns = MapFactoryHelper.getMapConnections MapFactoryHelper.eachConnectionForMap(id) do |conn|
if conns[id]
for conn in conns[id]
if conn[0] == id if conn[0] == id
mapA = getMap(conn[0]) mapA = getMap(conn[0])
newdispx = (conn[4] - conn[1]) * Game_Map::REAL_RES_X + mapA.display_x newdispx = ((conn[4] - conn[1]) * Game_Map::REAL_RES_X) + mapA.display_x
newdispy = (conn[5] - conn[2]) * Game_Map::REAL_RES_Y + mapA.display_y newdispy = ((conn[5] - conn[2]) * Game_Map::REAL_RES_Y) + mapA.display_y
if hasMap?(conn[3]) || MapFactoryHelper.mapInRangeById?(conn[3], newdispx, newdispy) if hasMap?(conn[3]) || MapFactoryHelper.mapInRangeById?(conn[3], newdispx, newdispy)
mapB = getMap(conn[3]) mapB = getMap(conn[3])
mapB.display_x = newdispx if mapB.display_x != newdispx mapB.display_x = newdispx if mapB.display_x != newdispx
@@ -131,8 +126,8 @@ class PokemonMapFactory
end end
else else
mapA = getMap(conn[3]) mapA = getMap(conn[3])
newdispx = (conn[1] - conn[4]) * Game_Map::REAL_RES_X + mapA.display_x newdispx = ((conn[1] - conn[4]) * Game_Map::REAL_RES_X) + mapA.display_x
newdispy = (conn[2] - conn[5]) * Game_Map::REAL_RES_Y + mapA.display_y newdispy = ((conn[2] - conn[5]) * Game_Map::REAL_RES_Y) + mapA.display_y
if hasMap?(conn[0]) || MapFactoryHelper.mapInRangeById?(conn[0], newdispx, newdispy) if hasMap?(conn[0]) || MapFactoryHelper.mapInRangeById?(conn[0], newdispx, newdispy)
mapB = getMap(conn[0]) mapB = getMap(conn[0])
mapB.display_x = newdispx if mapB.display_x != newdispx mapB.display_x = newdispx if mapB.display_x != newdispx
@@ -140,21 +135,20 @@ class PokemonMapFactory
end end
end end
end end
end
@fixup = false @fixup = false
end end
def setMapChanging(newID, newMap) def setMapChanging(newID, newMap)
Events.onMapChanging.trigger(self,newID,newMap) EventHandlers.trigger(:on_leave_map, newID, newMap)
end end
def setMapChanged(prevMap) def setMapChanged(prevMap)
Events.onMapChange.trigger(self,prevMap) EventHandlers.trigger(:on_enter_map, prevMap)
@mapChanged = true @mapChanged = true
end end
def setSceneStarted(scene) def setSceneStarted(scene)
Events.onMapSceneChange.trigger(self,scene,@mapChanged) EventHandlers.trigger(:on_map_or_spriteset_change, scene, @mapChanged)
@mapChanged = false @mapChanged = false
end end
@@ -180,15 +174,15 @@ class PokemonMapFactory
return false unless map.passable?(x, y, 0, thisEvent) return false unless map.passable?(x, y, 0, thisEvent)
end end
# Check passability of event(s) in that spot # Check passability of event(s) in that spot
for event in map.events.values map.events.each_value do |event|
next if event == thisEvent || !event.at_coordinate?(x, y) next if event == thisEvent || !event.at_coordinate?(x, y)
return false if !event.through && event.character_name != "" return false if !event.through && event.character_name != ""
end end
# Check passability of player # Check passability of player
if !thisEvent.is_a?(Game_Player) if !thisEvent.is_a?(Game_Player) &&
if $game_map.map_id == mapID && $game_player.x == x && $game_player.y == y $game_map.map_id == mapID && $game_player.x == x && $game_player.y == y &&
return false if !$game_player.through && $game_player.character_name != "" !$game_player.through && $game_player.character_name != ""
end return false
end end
return true return true
end end
@@ -201,13 +195,13 @@ class PokemonMapFactory
return false if !map.valid?(x, y) return false if !map.valid?(x, y)
return true if thisEvent.through return true if thisEvent.through
if thisEvent == $game_player if thisEvent == $game_player
if !($DEBUG && Input.press?(Input::CTRL)) if !($DEBUG && Input.press?(Input::CTRL)) && !map.passableStrict?(x, y, 0, thisEvent)
return false if !map.passableStrict?(x,y,0,thisEvent) return false
end end
else elsif !map.passableStrict?(x, y, 0, thisEvent)
return false if !map.passableStrict?(x,y,0,thisEvent) return false
end end
for event in map.events.values map.events.each_value do |event|
next if event == thisEvent || !event.at_coordinate?(x, y) next if event == thisEvent || !event.at_coordinate?(x, y)
return false if !event.through && event.character_name != "" return false if !event.through && event.character_name != ""
end end
@@ -234,33 +228,28 @@ class PokemonMapFactory
def areConnected?(mapID1, mapID2) def areConnected?(mapID1, mapID2)
return true if mapID1 == mapID2 return true if mapID1 == mapID2
conns = MapFactoryHelper.getMapConnections MapFactoryHelper.eachConnectionForMap(mapID1) do |conn|
if conns[mapID1]
for conn in conns[mapID1]
return true if conn[0] == mapID2 || conn[3] == mapID2 return true if conn[0] == mapID2 || conn[3] == mapID2
end end
end
return false return false
end end
# Returns the coordinate change to go from this position to other position
def getRelativePos(thisMapID, thisX, thisY, otherMapID, otherX, otherY) def getRelativePos(thisMapID, thisX, thisY, otherMapID, otherX, otherY)
if thisMapID == otherMapID # Both events share the same map if thisMapID == otherMapID # Both events share the same map
return [otherX - thisX, otherY - thisY] return [otherX - thisX, otherY - thisY]
end end
conns = MapFactoryHelper.getMapConnections MapFactoryHelper.eachConnectionForMap(thisMapID) do |conn|
if conns[thisMapID]
for conn in conns[thisMapID]
if conn[0] == otherMapID if conn[0] == otherMapID
posX = thisX + conn[1] - conn[4] + otherX posX = conn[4] - conn[1] + otherX - thisX
posY = thisY + conn[2] - conn[5] + otherY posY = conn[5] - conn[2] + otherY - thisY
return [posX, posY] return [posX, posY]
elsif conn[1] == otherMapID elsif conn[3] == otherMapID
posX = thisX + conn[4] - conn[1] + otherX posX = conn[1] - conn[4] + otherX - thisX
posY = thisY + conn[5] - conn[2] + otherY posY = conn[2] - conn[5] + otherY - thisY
return [posX, posY] return [posX, posY]
end end
end end
end
return [0, 0] return [0, 0]
end end
@@ -269,15 +258,14 @@ class PokemonMapFactory
# the array (3,-4), because (5-2=3) and (1-5=-4). # the array (3,-4), because (5-2=3) and (1-5=-4).
def getThisAndOtherEventRelativePos(thisEvent, otherEvent) def getThisAndOtherEventRelativePos(thisEvent, otherEvent)
return [0, 0] if !thisEvent || !otherEvent return [0, 0] if !thisEvent || !otherEvent
return getRelativePos( return getRelativePos(thisEvent.map.map_id, thisEvent.x, thisEvent.y,
thisEvent.map.map_id,thisEvent.x,thisEvent.y,
otherEvent.map.map_id, otherEvent.x, otherEvent.y) otherEvent.map.map_id, otherEvent.x, otherEvent.y)
end end
def getThisAndOtherPosRelativePos(thisEvent, otherMapID, otherX, otherY) def getThisAndOtherPosRelativePos(thisEvent, otherMapID, otherX, otherY)
return [0, 0] if !thisEvent return [0, 0] if !thisEvent
return getRelativePos( return getRelativePos(thisEvent.map.map_id, thisEvent.x, thisEvent.y,
thisEvent.map.map_id,thisEvent.x,thisEvent.y,otherMapID,otherX,otherY) otherMapID, otherX, otherY)
end end
# Unused # Unused
@@ -289,12 +277,12 @@ class PokemonMapFactory
# NOTE: Assumes the event is 1x1 tile in size. Only returns one tile. # NOTE: Assumes the event is 1x1 tile in size. Only returns one tile.
def getFacingTile(direction = nil, event = nil, steps = 1) def getFacingTile(direction = nil, event = nil, steps = 1)
event = $game_player if event==nil event = $game_player if event.nil?
return [0, 0, 0] if !event return [0, 0, 0] if !event
x = event.x x = event.x
y = event.y y = event.y
id = event.map.map_id id = event.map.map_id
direction = event.direction if direction==nil direction = event.direction if direction.nil?
return getFacingTileFromPos(id, x, y, direction, steps) return getFacingTileFromPos(id, x, y, direction, steps)
end end
@@ -330,9 +318,7 @@ class PokemonMapFactory
def getRealTilePos(mapID, x, y) def getRealTilePos(mapID, x, y)
id = mapID id = mapID
return [id, x, y] if getMapNoAdd(id).valid?(x, y) return [id, x, y] if getMapNoAdd(id).valid?(x, y)
conns = MapFactoryHelper.getMapConnections MapFactoryHelper.eachConnectionForMap(id) do |conn|
if conns[id]
for conn in conns[id]
if conn[0] == id if conn[0] == id
newX = x + conn[4] - conn[1] newX = x + conn[4] - conn[1]
newY = y + conn[5] - conn[2] newY = y + conn[5] - conn[2]
@@ -349,7 +335,6 @@ class PokemonMapFactory
return [conn[0], newX, newY] return [conn[0], newX, newY]
end end
end end
end
return nil return nil
end end
@@ -381,31 +366,21 @@ class PokemonMapFactory
def updateMaps(scene) def updateMaps(scene)
updateMapsInternal updateMapsInternal
$MapFactory.setSceneStarted(scene) if @mapChanged $map_factory.setSceneStarted(scene) if @mapChanged
end end
def updateMapsInternal def updateMapsInternal
return if $game_player.moving? return if $game_player.moving?
if !MapFactoryHelper.hasConnections?($game_map.map_id) if !MapFactoryHelper.hasConnections?($game_map.map_id)
return if @maps.length == 1 return if @maps.length == 1
for i in 0...@maps.length @maps.delete_if { |map| $game_map.map_id != map.map_id }
@maps[i] = nil if $game_map.map_id!=@maps[i].map_id
end
@maps.compact!
@mapIndex = getMapIndex($game_map.map_id) @mapIndex = getMapIndex($game_map.map_id)
return return
end end
setMapsInRange setMapsInRange
deleted = false old_num_maps = @maps.length
for i in 0...@maps.length @maps.delete_if { |map| !MapFactoryHelper.mapInRange?(map) }
next if MapFactoryHelper.mapInRange?(@maps[i]) @mapIndex = getMapIndex($game_map.map_id) if @maps.length != old_num_maps
@maps[i] = nil
deleted = true
end
if deleted
@maps.compact!
@mapIndex = getMapIndex($game_map.map_id)
end
end end
end end
@@ -465,6 +440,12 @@ module MapFactoryHelper
return conns[id] ? true : false return conns[id] ? true : false
end end
def self.eachConnectionForMap(id)
conns = MapFactoryHelper.getMapConnections
return if !conns[id]
conns[id].each { |conn| yield conn }
end
# Gets the height and width of the map with id # Gets the height and width of the map with id
def self.getMapDims(id) def self.getMapDims(id)
# Create cache if doesn't exist # Create cache if doesn't exist
@@ -485,7 +466,7 @@ module MapFactoryHelper
# Returns the X or Y coordinate of an edge on the map with id. # Returns the X or Y coordinate of an edge on the map with id.
# Considers the special strings "N","W","E","S" # Considers the special strings "N","W","E","S"
def self.getMapEdge(id, edge) def self.getMapEdge(id, edge)
return 0 if edge=="N" || edge=="W" return 0 if ["N", "W"].include?(edge)
dims = getMapDims(id) # Get dimensions dims = getMapDims(id) # Get dimensions
return dims[0] if edge == "E" return dims[0] if edge == "E"
return dims[1] if edge == "S" return dims[1] if edge == "S"
@@ -498,8 +479,8 @@ module MapFactoryHelper
dispy = map.display_y dispy = map.display_y
return false if dispx >= (map.width + range) * Game_Map::REAL_RES_X return false if dispx >= (map.width + range) * Game_Map::REAL_RES_X
return false if dispy >= (map.height + range) * Game_Map::REAL_RES_Y return false if dispy >= (map.height + range) * Game_Map::REAL_RES_Y
return false if dispx <= -(Graphics.width + range * Game_Map::TILE_WIDTH) * Game_Map::X_SUBPIXELS return false if dispx <= -(Graphics.width + (range * Game_Map::TILE_WIDTH)) * Game_Map::X_SUBPIXELS
return false if dispy <= -(Graphics.height + range * Game_Map::TILE_HEIGHT) * Game_Map::Y_SUBPIXELS return false if dispy <= -(Graphics.height + (range * Game_Map::TILE_HEIGHT)) * Game_Map::Y_SUBPIXELS
return true return true
end end
@@ -508,8 +489,8 @@ module MapFactoryHelper
dims = MapFactoryHelper.getMapDims(id) dims = MapFactoryHelper.getMapDims(id)
return false if dispx >= (dims[0] + range) * Game_Map::REAL_RES_X return false if dispx >= (dims[0] + range) * Game_Map::REAL_RES_X
return false if dispy >= (dims[1] + range) * Game_Map::REAL_RES_Y return false if dispy >= (dims[1] + range) * Game_Map::REAL_RES_Y
return false if dispx <= -(Graphics.width + range * Game_Map::TILE_WIDTH) * Game_Map::X_SUBPIXELS return false if dispx <= -(Graphics.width + (range * Game_Map::TILE_WIDTH)) * Game_Map::X_SUBPIXELS
return false if dispy <= -(Graphics.height + range * Game_Map::TILE_HEIGHT) * Game_Map::Y_SUBPIXELS return false if dispy <= -(Graphics.height + (range * Game_Map::TILE_HEIGHT)) * Game_Map::Y_SUBPIXELS
return true return true
end end
end end
@@ -519,8 +500,8 @@ end
#=============================================================================== #===============================================================================
# Unused # Unused
def updateTilesets def updateTilesets
maps = $MapFactory.maps maps = $map_factory.maps
for map in maps maps.each do |map|
map.updateTileset if map map&.updateTileset
end end
end end

View File

@@ -6,13 +6,15 @@ class Game_Character
attr_reader :y attr_reader :y
attr_reader :real_x attr_reader :real_x
attr_reader :real_y attr_reader :real_y
attr_writer :x_offset # In pixels, positive shifts sprite to the right
attr_writer :y_offset # In pixels, positive shifts sprite down
attr_accessor :width attr_accessor :width
attr_accessor :height attr_accessor :height
attr_accessor :sprite_size attr_accessor :sprite_size
attr_reader :tile_id attr_reader :tile_id
attr_accessor :character_name attr_accessor :character_name
attr_accessor :character_hue attr_accessor :character_hue
attr_reader :opacity attr_accessor :opacity
attr_reader :blend_type attr_reader :blend_type
attr_accessor :direction attr_accessor :direction
attr_accessor :pattern attr_accessor :pattern
@@ -35,6 +37,8 @@ class Game_Character
@y = 0 @y = 0
@real_x = 0 @real_x = 0
@real_y = 0 @real_y = 0
@x_offset = 0
@y_offset = 0
@width = 1 @width = 1
@height = 1 @height = 1
@sprite_size = [Game_Map::TILE_WIDTH, Game_Map::TILE_HEIGHT] @sprite_size = [Game_Map::TILE_WIDTH, Game_Map::TILE_HEIGHT]
@@ -73,10 +77,14 @@ class Game_Character
@bob_height = 0 @bob_height = 0
@wait_count = 0 @wait_count = 0
@moved_this_frame = false @moved_this_frame = false
@moveto_happened = false
@locked = false @locked = false
@prelock_direction = 0 @prelock_direction = 0
end end
def x_offset; return @x_offset || 0; end
def y_offset; return @y_offset || 0; end
def at_coordinate?(check_x, check_y) def at_coordinate?(check_x, check_y)
return check_x >= @x && check_x < @x + @width && return check_x >= @x && check_x < @x + @width &&
check_y > @y - @height && check_y <= @y check_y > @y - @height && check_y <= @y
@@ -88,8 +96,8 @@ class Game_Character
end end
def each_occupied_tile def each_occupied_tile
for i in @x...(@x + @width) (@x...(@x + @width)).each do |i|
for j in (@y - @height + 1)..@y ((@y - @height + 1)..@y).each do |j|
yield i, j yield i, j
end end
end end
@@ -142,7 +150,7 @@ class Game_Character
# 4 => 64 # 1.6 seconds # 4 => 64 # 1.6 seconds
# 5 => 30 # 0.75 seconds # 5 => 30 # 0.75 seconds
# 6 => 0 # 0 seconds, i.e. continuous movement # 6 => 0 # 0 seconds, i.e. continuous movement
self.move_frequency_real = (40 - val * 2) * (6 - val) self.move_frequency_real = (40 - (val * 2)) * (6 - val)
end end
def move_frequency_real def move_frequency_real
@@ -199,19 +207,30 @@ class Game_Character
def calculate_bush_depth def calculate_bush_depth
if @tile_id > 0 || @always_on_top || jumping? if @tile_id > 0 || @always_on_top || jumping?
@bush_depth = 0 @bush_depth = 0
else return
deep_bush = regular_bush = false end
xbehind = @x + (@direction == 4 ? 1 : @direction == 6 ? -1 : 0) xbehind = @x + (@direction == 4 ? 1 : @direction == 6 ? -1 : 0)
ybehind = @y + (@direction == 8 ? 1 : @direction == 2 ? -1 : 0) ybehind = @y + (@direction == 8 ? 1 : @direction == 2 ? -1 : 0)
this_map = (self.map.valid?(@x, @y)) ? [self.map, @x, @y] : $MapFactory.getNewMap(@x, @y) this_map = (self.map.valid?(@x, @y)) ? [self.map, @x, @y] : $map_factory&.getNewMap(@x, @y)
if this_map[0].deepBush?(this_map[1], this_map[2]) && self.map.deepBush?(xbehind, ybehind) behind_map = (self.map.valid?(xbehind, ybehind)) ? [self.map, xbehind, ybehind] : $map_factory&.getNewMap(xbehind, ybehind)
if this_map && this_map[0].deepBush?(this_map[1], this_map[2]) &&
(!behind_map || behind_map[0].deepBush?(behind_map[1], behind_map[2]))
@bush_depth = Game_Map::TILE_HEIGHT @bush_depth = Game_Map::TILE_HEIGHT
elsif !moving? && this_map[0].bush?(this_map[1], this_map[2]) elsif this_map && this_map[0].bush?(this_map[1], this_map[2]) && !moving?
@bush_depth = 12 @bush_depth = 12
else else
@bush_depth = 0 @bush_depth = 0
end end
end end
def fullPattern
case self.direction
when 2 then return self.pattern
when 4 then return self.pattern + 4
when 6 then return self.pattern + 8
when 8 then return self.pattern + 12
end
return 0
end end
#============================================================================= #=============================================================================
@@ -229,12 +248,13 @@ class Game_Character
return false unless self.map.passable?(x, y, d, self) return false unless self.map.passable?(x, y, d, self)
return false unless self.map.passable?(new_x, new_y, 10 - d, self) return false unless self.map.passable?(new_x, new_y, 10 - d, self)
end end
for event in self.map.events.values self.map.events.each_value do |event|
next if self == event || !event.at_coordinate?(new_x, new_y) || event.through next if self == event || !event.at_coordinate?(new_x, new_y) || event.through
return false if self != $game_player || event.character_name != "" return false if self != $game_player || event.character_name != ""
end end
if $game_player.x == new_x && $game_player.y == new_y if $game_player.x == new_x && $game_player.y == new_y &&
return false if !$game_player.through && @character_name != "" !$game_player.through && @character_name != ""
return false
end end
return true return true
end end
@@ -243,24 +263,24 @@ class Game_Character
case dir case dir
when 2, 8 # Down, up when 2, 8 # Down, up
y_diff = (dir == 8) ? @height - 1 : 0 y_diff = (dir == 8) ? @height - 1 : 0
for i in start_x...(start_x + @width) (start_x...(start_x + @width)).each do |i|
return false if !passable?(i, start_y - y_diff, dir, strict) return false if !passable?(i, start_y - y_diff, dir, strict)
end end
return true return true
when 4, 6 # Left, right when 4, 6 # Left, right
x_diff = (dir == 6) ? @width - 1 : 0 x_diff = (dir == 6) ? @width - 1 : 0
for i in (start_y - @height + 1)..start_y ((start_y - @height + 1)..start_y).each do |i|
return false if !passable?(start_x + x_diff, i, dir, strict) return false if !passable?(start_x + x_diff, i, dir, strict)
end end
return true return true
when 1, 3 # Down diagonals when 1, 3 # Down diagonals
# Treated as moving down first and then horizontally, because that # Treated as moving down first and then horizontally, because that
# describes which tiles the character's feet touch # describes which tiles the character's feet touch
for i in start_x...(start_x + @width) (start_x...(start_x + @width)).each do |i|
return false if !passable?(i, start_y, 2, strict) return false if !passable?(i, start_y, 2, strict)
end end
x_diff = (dir == 3) ? @width - 1 : 0 x_diff = (dir == 3) ? @width - 1 : 0
for i in (start_y - @height + 1)..start_y ((start_y - @height + 1)..start_y).each do |i|
return false if !passable?(start_x + x_diff, i + 1, dir + 3, strict) return false if !passable?(start_x + x_diff, i + 1, dir + 3, strict)
end end
return true return true
@@ -268,12 +288,12 @@ class Game_Character
# Treated as moving horizontally first and then up, because that describes # Treated as moving horizontally first and then up, because that describes
# which tiles the character's feet touch # which tiles the character's feet touch
x_diff = (dir == 9) ? @width - 1 : 0 x_diff = (dir == 9) ? @width - 1 : 0
for i in (start_y - @height + 1)..start_y ((start_y - @height + 1)..start_y).each do |i|
return false if !passable?(start_x + x_diff, i, dir - 3, strict) return false if !passable?(start_x + x_diff, i, dir - 3, strict)
end end
x_offset = (dir == 9) ? 1 : -1 x_tile_offset = (dir == 9) ? 1 : -1
for i in start_x...(start_x + @width) (start_x...(start_x + @width)).each do |i|
return false if !passable?(i + x_offset, start_y - @height + 1, 8, strict) return false if !passable?(i + x_tile_offset, start_y - @height + 1, 8, strict)
end end
return true return true
end end
@@ -288,13 +308,14 @@ class Game_Character
# Screen position of the character # Screen position of the character
#============================================================================= #=============================================================================
def screen_x def screen_x
ret = ((@real_x - self.map.display_x) / Game_Map::X_SUBPIXELS).round ret = ((@real_x.to_f - self.map.display_x) / Game_Map::X_SUBPIXELS).round
ret += @width * Game_Map::TILE_WIDTH / 2 ret += @width * Game_Map::TILE_WIDTH / 2
ret += self.x_offset
return ret return ret
end end
def screen_y_ground def screen_y_ground
ret = ((@real_y - self.map.display_y) / Game_Map::Y_SUBPIXELS).round ret = ((@real_y.to_f - self.map.display_y) / Game_Map::Y_SUBPIXELS).round
ret += Game_Map::TILE_HEIGHT ret += Game_Map::TILE_HEIGHT
return ret return ret
end end
@@ -307,8 +328,9 @@ class Game_Character
else else
jump_fraction = ((@jump_distance_left / @jump_distance) - 0.5).abs # 0.5 to 0 to 0.5 jump_fraction = ((@jump_distance_left / @jump_distance) - 0.5).abs # 0.5 to 0 to 0.5
end end
ret += @jump_peak * (4 * jump_fraction**2 - 1) ret += @jump_peak * ((4 * (jump_fraction**2)) - 1)
end end
ret += self.y_offset
return ret return ret
end end
@@ -317,7 +339,7 @@ class Game_Character
z = screen_y_ground z = screen_y_ground
if @tile_id > 0 if @tile_id > 0
begin begin
return z + self.map.priorities[@tile_id] * 32 return z + (self.map.priorities[@tile_id] * 32)
rescue rescue
raise "Event's graphic is an out-of-range tile (event #{@id}, map #{self.map.map_id})" raise "Event's graphic is an out-of-range tile (event #{@id}, map #{self.map.map_id})"
end end
@@ -345,7 +367,7 @@ class Game_Character
end end
def force_move_route(move_route) def force_move_route(move_route)
if @original_move_route == nil if @original_move_route.nil?
@original_move_route = @move_route @original_move_route = @move_route
@original_move_route_index = @move_route_index @original_move_route_index = @move_route_index
end end
@@ -363,6 +385,7 @@ class Game_Character
@real_x = @x * Game_Map::REAL_RES_X @real_x = @x * Game_Map::REAL_RES_X
@real_y = @y * Game_Map::REAL_RES_Y @real_y = @y * Game_Map::REAL_RES_Y
@prelock_direction = 0 @prelock_direction = 0
@moveto_happened = true
calculate_bush_depth calculate_bush_depth
triggerLeaveTile triggerLeaveTile
end end
@@ -370,7 +393,7 @@ class Game_Character
def triggerLeaveTile def triggerLeaveTile
if @oldX && @oldY && @oldMap && if @oldX && @oldY && @oldMap &&
(@oldX != self.x || @oldY != self.y || @oldMap != self.map.map_id) (@oldX != self.x || @oldY != self.y || @oldMap != self.map.map_id)
Events.onLeaveTile.trigger(self,self,@oldMap,@oldX,@oldY) EventHandlers.trigger(:on_leave_tile, self, @oldMap, @oldX, @oldY)
end end
@oldX = self.x @oldX = self.x
@oldY = self.y @oldY = self.y
@@ -394,8 +417,8 @@ class Game_Character
end end
def move_type_toward_player def move_type_toward_player
sx = @x + @width / 2.0 - ($game_player.x + $game_player.width / 2.0) sx = @x + (@width / 2.0) - ($game_player.x + ($game_player.width / 2.0))
sy = @y - @height / 2.0 - ($game_player.y - $game_player.height / 2.0) sy = @y - (@height / 2.0) - ($game_player.y - ($game_player.height / 2.0))
if sx.abs + sy.abs >= 20 if sx.abs + sy.abs >= 20
move_random move_random
return return
@@ -620,13 +643,15 @@ class Game_Character
def move_random_range(xrange = -1, yrange = -1) def move_random_range(xrange = -1, yrange = -1)
dirs = [] # 0=down, 1=left, 2=right, 3=up dirs = [] # 0=down, 1=left, 2=right, 3=up
if xrange < 0 if xrange < 0
dirs.push(1); dirs.push(2) dirs.push(1)
dirs.push(2)
elsif xrange > 0 elsif xrange > 0
dirs.push(1) if @x > @original_x - xrange dirs.push(1) if @x > @original_x - xrange
dirs.push(2) if @x < @original_x + xrange dirs.push(2) if @x < @original_x + xrange
end end
if yrange < 0 if yrange < 0
dirs.push(0); dirs.push(3) dirs.push(0)
dirs.push(3)
elsif yrange > 0 elsif yrange > 0
dirs.push(0) if @y < @original_y + yrange dirs.push(0) if @y < @original_y + yrange
dirs.push(3) if @y > @original_y - yrange dirs.push(3) if @y > @original_y - yrange
@@ -649,8 +674,8 @@ class Game_Character
end end
def move_toward_player def move_toward_player
sx = @x + @width / 2.0 - ($game_player.x + $game_player.width / 2.0) sx = @x + (@width / 2.0) - ($game_player.x + ($game_player.width / 2.0))
sy = @y - @height / 2.0 - ($game_player.y - $game_player.height / 2.0) sy = @y - (@height / 2.0) - ($game_player.y - ($game_player.height / 2.0))
return if sx == 0 && sy == 0 return if sx == 0 && sy == 0
abs_sx = sx.abs abs_sx = sx.abs
abs_sy = sy.abs abs_sy = sy.abs
@@ -671,8 +696,8 @@ class Game_Character
end end
def move_away_from_player def move_away_from_player
sx = @x + @width / 2.0 - ($game_player.x + $game_player.width / 2.0) sx = @x + (@width / 2.0) - ($game_player.x + ($game_player.width / 2.0))
sy = @y - @height / 2.0 - ($game_player.y - $game_player.height / 2.0) sy = @y - (@height / 2.0) - ($game_player.y - ($game_player.height / 2.0))
return if sx == 0 && sy == 0 return if sx == 0 && sy == 0
abs_sx = sx.abs abs_sx = sx.abs
abs_sy = sy.abs abs_sy = sy.abs
@@ -724,7 +749,7 @@ class Game_Character
end end
@x = @x + x_plus @x = @x + x_plus
@y = @y + y_plus @y = @y + y_plus
real_distance = Math::sqrt(x_plus * x_plus + y_plus * y_plus) real_distance = Math.sqrt((x_plus * x_plus) + (y_plus * y_plus))
distance = [1, real_distance].max distance = [1, real_distance].max
@jump_peak = distance * Game_Map::TILE_HEIGHT * 3 / 8 # 3/4 of tile for ledge jumping @jump_peak = distance * Game_Map::TILE_HEIGHT * 3 / 8 # 3/4 of tile for ledge jumping
@jump_distance = [x_plus.abs * Game_Map::REAL_RES_X, y_plus.abs * Game_Map::REAL_RES_Y].max @jump_distance = [x_plus.abs * Game_Map::REAL_RES_X, y_plus.abs * Game_Map::REAL_RES_Y].max
@@ -736,9 +761,6 @@ class Game_Character
@jump_count = Game_Map::REAL_RES_X / jump_speed_real # Number of frames to jump one tile @jump_count = Game_Map::REAL_RES_X / jump_speed_real # Number of frames to jump one tile
end end
@stop_count = 0 @stop_count = 0
if self.is_a?(Game_Player)
$PokemonTemp.dependentEvents.pbMoveDependentEvents
end
triggerLeaveTile triggerLeaveTile
end end
@@ -814,8 +836,8 @@ class Game_Character
end end
def turn_toward_player def turn_toward_player
sx = @x + @width / 2.0 - ($game_player.x + $game_player.width / 2.0) sx = @x + (@width / 2.0) - ($game_player.x + ($game_player.width / 2.0))
sy = @y - @height / 2.0 - ($game_player.y - $game_player.height / 2.0) sy = @y - (@height / 2.0) - ($game_player.y - ($game_player.height / 2.0))
return if sx == 0 && sy == 0 return if sx == 0 && sy == 0
if sx.abs > sy.abs if sx.abs > sy.abs
(sx > 0) ? turn_left : turn_right (sx > 0) ? turn_left : turn_right
@@ -825,8 +847,8 @@ class Game_Character
end end
def turn_away_from_player def turn_away_from_player
sx = @x + @width / 2.0 - ($game_player.x + $game_player.width / 2.0) sx = @x + (@width / 2.0) - ($game_player.x + ($game_player.width / 2.0))
sy = @y - @height / 2.0 - ($game_player.y - $game_player.height / 2.0) sy = @y - (@height / 2.0) - ($game_player.y - ($game_player.height / 2.0))
return if sx == 0 && sy == 0 return if sx == 0 && sy == 0
if sx.abs > sy.abs if sx.abs > sy.abs
(sx > 0) ? turn_right : turn_left (sx > 0) ? turn_right : turn_left
@@ -841,6 +863,8 @@ class Game_Character
def update def update
@moved_last_frame = @moved_this_frame @moved_last_frame = @moved_this_frame
@stopped_last_frame = @stopped_this_frame @stopped_last_frame = @stopped_this_frame
@moved_this_frame = false
@stopped_this_frame = false
if !$game_temp.in_menu if !$game_temp.in_menu
# Update command # Update command
update_command update_command
@@ -905,12 +929,11 @@ class Game_Character
end end
# End of a step, so perform events that happen at this time # End of a step, so perform events that happen at this time
if !jumping? && !moving? if !jumping? && !moving?
Events.onStepTakenFieldMovement.trigger(self, self) EventHandlers.trigger(:on_step_taken, self)
calculate_bush_depth calculate_bush_depth
@stopped_this_frame = true @stopped_this_frame = true
elsif !@moved_last_frame || @stopped_last_frame # Started a new step elsif !@moved_last_frame || @stopped_last_frame # Started a new step
calculate_bush_depth calculate_bush_depth
@stopped_this_frame = false
end end
# Increment animation counter # Increment animation counter
@anime_count += 1 if @walk_anime || @step_anime @anime_count += 1 if @walk_anime || @step_anime
@@ -920,8 +943,6 @@ class Game_Character
def update_stop def update_stop
@anime_count += 1 if @step_anime @anime_count += 1 if @step_anime
@stop_count += 1 if !@starting && !lock? @stop_count += 1 if !@starting && !lock?
@moved_this_frame = false
@stopped_this_frame = false
end end
def update_pattern def update_pattern

View File

@@ -99,7 +99,7 @@ class Game_Event < Game_Character
return $PokemonGlobal.eventvars[[@map_id, @event.id]].to_i return $PokemonGlobal.eventvars[[@map_id, @event.id]].to_i
end end
def expired?(secs=86400) def expired?(secs = 86_400)
ontime = self.variable ontime = self.variable
time = pbGetTimeNow time = pbGetTimeNow
return ontime && (time.to_i > ontime + secs) return ontime && (time.to_i > ontime + secs)
@@ -109,8 +109,8 @@ class Game_Event < Game_Character
ontime = self.variable.to_i ontime = self.variable.to_i
return false if !ontime return false if !ontime
now = pbGetTimeNow now = pbGetTimeNow
elapsed=(now.to_i-ontime)/86400 elapsed = (now.to_i - ontime) / 86_400
elapsed+=1 if (now.to_i-ontime)%86400>(now.hour*3600+now.min*60+now.sec) elapsed += 1 if (now.to_i - ontime) % 86_400 > ((now.hour * 3600) + (now.min * 60) + now.sec)
return elapsed >= days return elapsed >= days
end end
@@ -141,12 +141,12 @@ class Game_Event < Game_Character
def pbCheckEventTriggerAfterTurning def pbCheckEventTriggerAfterTurning
return if $game_system.map_interpreter.running? || @starting return if $game_system.map_interpreter.running? || @starting
if @event.name[/trainer\((\d+)\)/i] return if @trigger != 2 # Event touch
return if !@event.name[/(?:sight|trainer)\((\d+)\)/i]
distance = $~[1].to_i distance = $~[1].to_i
if @trigger==2 && pbEventCanReachPlayer?(self,$game_player,distance) return if !pbEventCanReachPlayer?(self, $game_player, distance)
start if !jumping? && !over_trigger? return if jumping? || over_trigger?
end start
end
end end
def check_event_trigger_touch(dir) def check_event_trigger_touch(dir)
@@ -168,11 +168,12 @@ class Game_Event < Game_Character
end end
def check_event_trigger_auto def check_event_trigger_auto
if @trigger == 2 # Event touch case @trigger
if at_coordinate?($game_player.x, $game_player.y) when 2 # Event touch
start if !jumping? && over_trigger? if at_coordinate?($game_player.x, $game_player.y) && !jumping? && over_trigger?
start
end end
elsif @trigger == 3 # Autorun when 3 # Autorun
start start
end end
end end
@@ -180,7 +181,7 @@ class Game_Event < Game_Character
def refresh def refresh
new_page = nil new_page = nil
unless @erased unless @erased
for page in @event.pages.reverse @event.pages.reverse.each do |page|
c = page.condition c = page.condition
next if c.switch1_valid && !switchIsOn?(c.switch1_id) next if c.switch1_valid && !switchIsOn?(c.switch1_id)
next if c.switch2_valid && !switchIsOn?(c.switch2_id) next if c.switch2_valid && !switchIsOn?(c.switch2_id)
@@ -196,7 +197,7 @@ class Game_Event < Game_Character
return if new_page == @page return if new_page == @page
@page = new_page @page = new_page
clear_starting clear_starting
if @page == nil if @page.nil?
@tile_id = 0 @tile_id = 0
@character_name = "" @character_name = ""
@character_hue = 0 @character_hue = 0
@@ -245,12 +246,12 @@ class Game_Event < Game_Character
def should_update?(recalc = false) def should_update?(recalc = false)
return @to_update if !recalc return @to_update if !recalc
return true if @trigger && (@trigger == 3 || @trigger == 4) return true if @trigger && (@trigger == 3 || @trigger == 4)
return true if @move_route_forcing return true if @move_route_forcing || @moveto_happened
return true if @event.name[/update/i] return true if @event.name[/update/i]
range = 2 # Number of tiles range = 2 # Number of tiles
return false if self.screen_x - @sprite_size[0]/2 > Graphics.width + range * Game_Map::TILE_WIDTH return false if self.screen_x - (@sprite_size[0] / 2) > Graphics.width + (range * Game_Map::TILE_WIDTH)
return false if self.screen_x + @sprite_size[0]/2 < -range * Game_Map::TILE_WIDTH return false if self.screen_x + (@sprite_size[0] / 2) < -range * Game_Map::TILE_WIDTH
return false if self.screen_y_ground - @sprite_size[1] > Graphics.height + range * Game_Map::TILE_HEIGHT return false if self.screen_y_ground - @sprite_size[1] > Graphics.height + (range * Game_Map::TILE_HEIGHT)
return false if self.screen_y_ground < -range * Game_Map::TILE_HEIGHT return false if self.screen_y_ground < -range * Game_Map::TILE_HEIGHT
return true return true
end end
@@ -258,6 +259,7 @@ class Game_Event < Game_Character
def update def update
@to_update = should_update?(true) @to_update = should_update?(true)
return if !@to_update return if !@to_update
@moveto_happened = false
last_moving = moving? last_moving = moving?
super super
if !moving? && last_moving if !moving? && last_moving
@@ -268,7 +270,7 @@ class Game_Event < Game_Character
refresh refresh
end end
check_event_trigger_auto check_event_trigger_auto
if @interpreter != nil if @interpreter
unless @interpreter.running? unless @interpreter.running?
@interpreter.setup(@list, @event.id, @map_id) @interpreter.setup(@list, @event.id, @map_id)
end end

View File

@@ -10,8 +10,10 @@ class Game_Player < Game_Character
attr_accessor :charsetData attr_accessor :charsetData
attr_accessor :encounter_count attr_accessor :encounter_count
SCREEN_CENTER_X = (Settings::SCREEN_WIDTH / 2 - Game_Map::TILE_WIDTH / 2) * Game_Map::X_SUBPIXELS SCREEN_CENTER_X = ((Settings::SCREEN_WIDTH / 2) - (Game_Map::TILE_WIDTH / 2)) * Game_Map::X_SUBPIXELS
SCREEN_CENTER_Y = (Settings::SCREEN_HEIGHT / 2 - Game_Map::TILE_HEIGHT / 2) * Game_Map::Y_SUBPIXELS SCREEN_CENTER_Y = ((Settings::SCREEN_HEIGHT / 2) - (Game_Map::TILE_HEIGHT / 2)) * Game_Map::Y_SUBPIXELS
@@bobFrameSpeed = 1.0 / 15
def initialize(*arg) def initialize(*arg)
super(*arg) super(*arg)
@@ -25,60 +27,174 @@ class Game_Player < Game_Character
return $game_map return $game_map
end end
def pbHasDependentEvents? def map_id
return $PokemonGlobal.dependentEvents.length>0 return $game_map.map_id
end
def screen_z(height = 0)
ret = super
return ret + 1
end
def has_follower?
return $PokemonGlobal.followers.length > 0
end
def can_map_transfer_with_follower?
return $PokemonGlobal.followers.length == 0
end
def can_ride_vehicle_with_follower?
return $PokemonGlobal.followers.length == 0
end
def can_run?
return @move_speed > 3 if @move_route_forcing
return false if $game_temp.in_menu || $game_temp.in_battle ||
$game_temp.message_window_showing || pbMapInterpreterRunning?
return false if !$player.has_running_shoes && !$PokemonGlobal.diving &&
!$PokemonGlobal.surfing && !$PokemonGlobal.bicycle
return false if jumping?
return false if pbTerrainTag.must_walk
return ($PokemonSystem.runstyle == 1) ^ Input.press?(Input::BACK)
end
def set_movement_type(type)
meta = GameData::PlayerMetadata.get($player&.character_ID || 1)
new_charset = nil
case type
when :fishing
new_charset = pbGetPlayerCharset(meta.fish_charset)
when :surf_fishing
new_charset = pbGetPlayerCharset(meta.surf_fish_charset)
when :diving, :diving_fast, :diving_jumping, :diving_stopped
self.move_speed = 3
new_charset = pbGetPlayerCharset(meta.dive_charset)
when :surfing, :surfing_fast, :surfing_jumping, :surfing_stopped
self.move_speed = (type == :surfing_jumping) ? 3 : 4
new_charset = pbGetPlayerCharset(meta.surf_charset)
when :cycling, :cycling_fast, :cycling_jumping, :cycling_stopped
self.move_speed = (type == :cycling_jumping) ? 3 : 5
new_charset = pbGetPlayerCharset(meta.cycle_charset)
when :running
self.move_speed = 4
new_charset = pbGetPlayerCharset(meta.run_charset)
when :ice_sliding
self.move_speed = 4
new_charset = pbGetPlayerCharset(meta.walk_charset)
else # :walking, :jumping, :walking_stopped
self.move_speed = 3
new_charset = pbGetPlayerCharset(meta.walk_charset)
end
@character_name = new_charset if new_charset
end
# Called when the player's character or outfit changes. Assumes the player
# isn't moving.
def refresh_charset
meta = GameData::PlayerMetadata.get($player&.character_ID || 1)
new_charset = nil
if $PokemonGlobal&.diving
new_charset = pbGetPlayerCharset(meta.dive_charset)
elsif $PokemonGlobal&.surfing
new_charset = pbGetPlayerCharset(meta.surf_charset)
elsif $PokemonGlobal&.bicycle
new_charset = pbGetPlayerCharset(meta.cycle_charset)
else
new_charset = pbGetPlayerCharset(meta.walk_charset)
end
@character_name = new_charset if new_charset
end end
def bump_into_object def bump_into_object
return if @bump_se && @bump_se > 0 return if @bump_se && @bump_se > 0
pbSEPlay("Player bump") pbSEPlay("Player bump") if !@move_route_forcing
@bump_se = Graphics.frame_rate / 4 @bump_se = Graphics.frame_rate / 4
end end
def move_generic(dir, turn_enabled = true) def move_generic(dir, turn_enabled = true)
turn_generic(dir, true) if turn_enabled turn_generic(dir, true) if turn_enabled
if !$PokemonTemp.encounterTriggered if !$game_temp.encounter_triggered
if can_move_in_direction?(dir) if can_move_in_direction?(dir)
x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0 x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0
y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0 y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0
return if pbLedge(x_offset, y_offset) return if pbLedge(x_offset, y_offset)
return if pbEndSurf(x_offset, y_offset) return if pbEndSurf(x_offset, y_offset)
turn_generic(dir, true) turn_generic(dir, true)
if !$PokemonTemp.encounterTriggered if !$game_temp.encounter_triggered
@x += x_offset @x += x_offset
@y += y_offset @y += y_offset
$PokemonTemp.dependentEvents.pbMoveDependentEvents if $PokemonGlobal&.diving || $PokemonGlobal&.surfing
$stats.distance_surfed += 1
elsif $PokemonGlobal&.bicycle
$stats.distance_cycled += 1
else
$stats.distance_walked += 1
end
$stats.distance_slid_on_ice += 1 if $PokemonGlobal.sliding
increase_steps increase_steps
end end
elsif !check_event_trigger_touch(dir) elsif !check_event_trigger_touch(dir)
bump_into_object bump_into_object
end end
end end
$PokemonTemp.encounterTriggered = false $game_temp.encounter_triggered = false
end end
def turn_generic(dir, keep_enc_indicator = false) def turn_generic(dir, keep_enc_indicator = false)
old_direction = @direction old_direction = @direction
super(dir) super(dir)
if @direction != old_direction && !@move_route_forcing && !pbMapInterpreterRunning? if @direction != old_direction && !@move_route_forcing && !pbMapInterpreterRunning?
Events.onChangeDirection.trigger(self, self) EventHandlers.trigger(:on_player_change_direction)
$PokemonTemp.encounterTriggered = false if !keep_enc_indicator $game_temp.encounter_triggered = false if !keep_enc_indicator
end end
end end
def pbTriggeredTrainerEvents(triggers,checkIfRunning=true) def jump(x_plus, y_plus)
if x_plus != 0 || y_plus != 0
if x_plus.abs > y_plus.abs
(x_plus < 0) ? turn_left : turn_right
else
(y_plus < 0) ? turn_up : turn_down
end
each_occupied_tile { |i, j| return if !passable?(i + x_plus, j + y_plus, 0) }
end
@x = @x + x_plus
@y = @y + y_plus
real_distance = Math.sqrt((x_plus * x_plus) + (y_plus * y_plus))
distance = [1, real_distance].max
@jump_peak = distance * Game_Map::TILE_HEIGHT * 3 / 8 # 3/4 of tile for ledge jumping
@jump_distance = [x_plus.abs * Game_Map::REAL_RES_X, y_plus.abs * Game_Map::REAL_RES_Y].max
@jump_distance_left = 1 # Just needs to be non-zero
if real_distance > 0 # Jumping to somewhere else
if $PokemonGlobal&.diving || $PokemonGlobal&.surfing
$stats.distance_surfed += x_plus.abs + y_plus.abs
elsif $PokemonGlobal&.bicycle
$stats.distance_cycled += x_plus.abs + y_plus.abs
else
$stats.distance_walked += x_plus.abs + y_plus.abs
end
@jump_count = 0
else # Jumping on the spot
@jump_speed_real = nil # Reset jump speed
@jump_count = Game_Map::REAL_RES_X / jump_speed_real # Number of frames to jump one tile
end
@stop_count = 0
triggerLeaveTile
end
def pbTriggeredTrainerEvents(triggers, checkIfRunning = true, trainer_only = false)
result = [] result = []
# If event is running # If event is running
return result if checkIfRunning && $game_system.map_interpreter.running? return result if checkIfRunning && $game_system.map_interpreter.running?
# All event loops # All event loops
for event in $game_map.events.values $game_map.events.each_value do |event|
next if !event.name[/trainer\((\d+)\)/i] next if !triggers.include?(event.trigger)
next if !event.name[/trainer\((\d+)\)/i] && (trainer_only || !event.name[/sight\((\d+)\)/i])
distance = $~[1].to_i distance = $~[1].to_i
# If event coordinates and triggers are consistent next if !pbEventCanReachPlayer?(event, self, distance)
if pbEventCanReachPlayer?(event,self,distance) && triggers.include?(event.trigger) next if event.jumping? || event.over_trigger?
# If starting determinant is front event (other than jumping) result.push(event)
result.push(event) if !event.jumping? && !event.over_trigger?
end
end end
return result return result
end end
@@ -88,14 +204,13 @@ class Game_Player < Game_Character
# If event is running # If event is running
return result if checkIfRunning && $game_system.map_interpreter.running? return result if checkIfRunning && $game_system.map_interpreter.running?
# All event loops # All event loops
for event in $game_map.events.values $game_map.events.each_value do |event|
next if !triggers.include?(event.trigger)
next if !event.name[/counter\((\d+)\)/i] next if !event.name[/counter\((\d+)\)/i]
distance = $~[1].to_i distance = $~[1].to_i
# If event coordinates and triggers are consistent next if !pbEventFacesPlayer?(event, self, distance)
if pbEventFacesPlayer?(event,self,distance) && triggers.include?(event.trigger) next if event.jumping? || event.over_trigger?
# If starting determinant is front event (other than jumping) result.push(event)
result.push(event) if !event.jumping? && !event.over_trigger?
end
end end
return result return result
end end
@@ -106,14 +221,14 @@ class Game_Player < Game_Character
ret = pbTriggeredTrainerEvents(triggers) ret = pbTriggeredTrainerEvents(triggers)
ret.concat(pbTriggeredCounterEvents(triggers)) ret.concat(pbTriggeredCounterEvents(triggers))
return false if ret.length == 0 return false if ret.length == 0
for event in ret ret.each do |event|
event.start event.start
end end
return true return true
end end
def pbTerrainTag(countBridge = false) def pbTerrainTag(countBridge = false)
return $MapFactory.getTerrainTag(self.map.map_id, @x, @y, countBridge) if $MapFactory return $map_factory.getTerrainTag(self.map.map_id, @x, @y, countBridge) if $map_factory
return $game_map.terrain_tag(@x, @y, countBridge) return $game_map.terrain_tag(@x, @y, countBridge)
end end
@@ -123,7 +238,7 @@ class Game_Player < Game_Character
new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0) new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0) new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
return nil if !$game_map.valid?(new_x, new_y) return nil if !$game_map.valid?(new_x, new_y)
for event in $game_map.events.values $game_map.events.each_value do |event|
next if !event.at_coordinate?(new_x, new_y) next if !event.at_coordinate?(new_x, new_y)
next if event.jumping? || event.over_trigger? next if event.jumping? || event.over_trigger?
return event return event
@@ -132,7 +247,7 @@ class Game_Player < Game_Character
if $game_map.counter?(new_x, new_y) if $game_map.counter?(new_x, new_y)
new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0) new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0) new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
for event in $game_map.events.values $game_map.events.each_value do |event|
next if !event.at_coordinate?(new_x, new_y) next if !event.at_coordinate?(new_x, new_y)
next if event.jumping? || event.over_trigger? next if event.jumping? || event.over_trigger?
return event return event
@@ -143,7 +258,7 @@ class Game_Player < Game_Character
def pbFacingTerrainTag(dir = nil) def pbFacingTerrainTag(dir = nil)
dir = self.direction if !dir dir = self.direction if !dir
return $MapFactory.getFacingTerrainTag(dir, self) if $MapFactory return $map_factory.getFacingTerrainTag(dir, self) if $map_factory
facing = pbFacingTile(dir, self) facing = pbFacingTile(dir, self)
return $game_map.terrain_tag(facing[1], facing[2]) return $game_map.terrain_tag(facing[1], facing[2])
end end
@@ -162,8 +277,8 @@ class Game_Player < Game_Character
# If coordinates are outside of map # If coordinates are outside of map
return false if !$game_map.validLax?(new_x, new_y) return false if !$game_map.validLax?(new_x, new_y)
if !$game_map.valid?(new_x, new_y) if !$game_map.valid?(new_x, new_y)
return false if !$MapFactory return false if !$map_factory
return $MapFactory.isPassableFromEdge?(new_x, new_y) return $map_factory.isPassableFromEdge?(new_x, new_y)
end end
# If debug mode is ON and Ctrl key was pressed # If debug mode is ON and Ctrl key was pressed
return true if $DEBUG && Input.press?(Input::CTRL) return true if $DEBUG && Input.press?(Input::CTRL)
@@ -174,8 +289,8 @@ class Game_Player < Game_Character
# * Set Map Display Position to Center of Screen # * Set Map Display Position to Center of Screen
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def center(x, y) def center(x, y)
self.map.display_x = x * Game_Map::REAL_RES_X - SCREEN_CENTER_X self.map.display_x = (x * Game_Map::REAL_RES_X) - SCREEN_CENTER_X
self.map.display_y = y * Game_Map::REAL_RES_Y - SCREEN_CENTER_Y self.map.display_y = (y * Game_Map::REAL_RES_Y) - SCREEN_CENTER_Y
end end
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@@ -185,9 +300,7 @@ class Game_Player < Game_Character
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def moveto(x, y) def moveto(x, y)
super super
# Centering
center(x, y) center(x, y)
# Make encounter count
make_encounter_count make_encounter_count
end end
@@ -219,7 +332,7 @@ class Game_Player < Game_Character
# If event is running # If event is running
return result if $game_system.map_interpreter.running? return result if $game_system.map_interpreter.running?
# All event loops # All event loops
for event in $game_map.events.values $game_map.events.each_value do |event|
# If event coordinates and triggers are consistent # If event coordinates and triggers are consistent
next if !event.at_coordinate?(@x, @y) next if !event.at_coordinate?(@x, @y)
next if !triggers.include?(event.trigger) next if !triggers.include?(event.trigger)
@@ -243,35 +356,32 @@ class Game_Player < Game_Character
new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0) new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
return false if !$game_map.valid?(new_x, new_y) return false if !$game_map.valid?(new_x, new_y)
# All event loops # All event loops
for event in $game_map.events.values $game_map.events.each_value do |event|
next if !triggers.include?(event.trigger)
# If event coordinates and triggers are consistent # If event coordinates and triggers are consistent
next if !event.at_coordinate?(new_x, new_y) next if !event.at_coordinate?(new_x, new_y)
next if !triggers.include?(event.trigger)
# If starting determinant is front event (other than jumping) # If starting determinant is front event (other than jumping)
next if event.jumping? || event.over_trigger? next if event.jumping? || event.over_trigger?
event.start event.start
result = true result = true
end end
# If fitting event is not found # If fitting event is not found
if result == false if result == false && $game_map.counter?(new_x, new_y)
# If front tile is a counter
if $game_map.counter?(new_x, new_y)
# Calculate coordinates of 1 tile further away # Calculate coordinates of 1 tile further away
new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0) new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0) new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
return false if !$game_map.valid?(new_x, new_y) return false if !$game_map.valid?(new_x, new_y)
# All event loops # All event loops
for event in $game_map.events.values $game_map.events.each_value do |event|
next if !triggers.include?(event.trigger)
# If event coordinates and triggers are consistent # If event coordinates and triggers are consistent
next if !event.at_coordinate?(new_x, new_y) next if !event.at_coordinate?(new_x, new_y)
next if !triggers.include?(event.trigger)
# If starting determinant is front event (other than jumping) # If starting determinant is front event (other than jumping)
next if event.jumping? || event.over_trigger? next if event.jumping? || event.over_trigger?
event.start event.start
result = true result = true
end end
end end
end
return result return result
end end
@@ -284,11 +394,11 @@ class Game_Player < Game_Character
# All event loops # All event loops
x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0 x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0
y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0 y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0
for event in $game_map.events.values $game_map.events.each_value do |event|
next if ![1, 2].include?(event.trigger) # Player touch, event touch next if ![1, 2].include?(event.trigger) # Player touch, event touch
# If event coordinates and triggers are consistent # If event coordinates and triggers are consistent
next if !event.at_coordinate?(@x + x_offset, @y + y_offset) next if !event.at_coordinate?(@x + x_offset, @y + y_offset)
if event.name[/trainer\((\d+)\)/i] if event.name[/(?:sight|trainer)\((\d+)\)/i]
distance = $~[1].to_i distance = $~[1].to_i
next if !pbEventCanReachPlayer?(event, self, distance) next if !pbEventCanReachPlayer?(event, self, distance)
elsif event.name[/counter\((\d+)\)/i] elsif event.name[/counter\((\d+)\)/i]
@@ -312,14 +422,18 @@ class Game_Player < Game_Character
super super
update_screen_position(last_real_x, last_real_y) update_screen_position(last_real_x, last_real_y)
# Update dependent events # Update dependent events
$PokemonTemp.dependentEvents.updateDependentEvents if (!@moved_last_frame || @stopped_last_frame ||
(@stopped_this_frame && $PokemonGlobal.sliding)) && (moving? || jumping?)
$game_temp.followers.move_followers
end
$game_temp.followers.update
# Count down the time between allowed bump sounds # Count down the time between allowed bump sounds
@bump_se -= 1 if @bump_se && @bump_se > 0 @bump_se -= 1 if @bump_se && @bump_se > 0
# Finish up dismounting from surfing # Finish up dismounting from surfing
if $PokemonTemp.endSurf && !moving? if $game_temp.ending_surf && !moving?
pbCancelVehicles pbCancelVehicles
$PokemonTemp.surfJump = nil $game_temp.surf_base_coords = nil
$PokemonTemp.endSurf = false $game_temp.ending_surf = false
end end
update_event_triggering update_event_triggering
end end
@@ -327,7 +441,7 @@ class Game_Player < Game_Character
def update_command_new def update_command_new
dir = Input.dir4 dir = Input.dir4
unless pbMapInterpreterRunning? || $game_temp.message_window_showing || unless pbMapInterpreterRunning? || $game_temp.message_window_showing ||
$PokemonTemp.miniupdate || $game_temp.in_menu $game_temp.in_mini_update || $game_temp.in_menu
# Move player in the direction the directional button is being pressed # Move player in the direction the directional button is being pressed
if @moved_last_frame || if @moved_last_frame ||
(dir > 0 && dir == @lastdir && Graphics.frame_count - @lastdirframe > Graphics.frame_rate / 20) (dir > 0 && dir == @lastdir && Graphics.frame_count - @lastdirframe > Graphics.frame_rate / 20)
@@ -351,6 +465,64 @@ class Game_Player < Game_Character
@lastdir = dir @lastdir = dir
end end
def update_move
if !@moved_last_frame || @stopped_last_frame # Started a new step
if pbTerrainTag.ice
set_movement_type(:ice_sliding)
else#if !@move_route_forcing
faster = can_run?
if $PokemonGlobal&.diving
set_movement_type((faster) ? :diving_fast : :diving)
elsif $PokemonGlobal&.surfing
set_movement_type((faster) ? :surfing_fast : :surfing)
elsif $PokemonGlobal&.bicycle
set_movement_type((faster) ? :cycling_fast : :cycling)
else
set_movement_type((faster) ? :running : :walking)
end
end
if jumping?
if $PokemonGlobal&.diving
set_movement_type(:diving_jumping)
elsif $PokemonGlobal&.surfing
set_movement_type(:surfing_jumping)
elsif $PokemonGlobal&.bicycle
set_movement_type(:cycling_jumping)
else
set_movement_type(:jumping) # Walking speed/charset while jumping
end
end
end
super
end
def update_stop
if @stopped_last_frame
if $PokemonGlobal&.diving
set_movement_type(:diving_stopped)
elsif $PokemonGlobal&.surfing
set_movement_type(:surfing_stopped)
elsif $PokemonGlobal&.bicycle
set_movement_type(:cycling_stopped)
else
set_movement_type(:walking_stopped)
end
end
super
end
def update_pattern
if $PokemonGlobal&.surfing || $PokemonGlobal&.diving
p = ((Graphics.frame_count % 60) * @@bobFrameSpeed).floor
@pattern = p if !@lock_pattern
@pattern_surf = p
@bob_height = (p >= 2) ? 2 : 0
else
@bob_height = 0
super
end
end
# Center player on-screen # Center player on-screen
def update_screen_position(last_real_x, last_real_y) def update_screen_position(last_real_x, last_real_y)
return if self.map.scrolling? || !(@moved_last_frame || @moved_this_frame) return if self.map.scrolling? || !(@moved_last_frame || @moved_this_frame)
@@ -362,7 +534,7 @@ class Game_Player < Game_Character
return if moving? return if moving?
# Try triggering events upon walking into them/in front of them # Try triggering events upon walking into them/in front of them
if @moved_this_frame if @moved_this_frame
$PokemonTemp.dependentEvents.pbTurnDependentEvents $game_temp.followers.turn_followers
result = pbCheckEventTriggerFromDistance([2]) result = pbCheckEventTriggerFromDistance([2])
# Event determinant is via touch of same position event # Event determinant is via touch of same position event
result |= check_event_trigger_here([1, 2]) result |= check_event_trigger_here([1, 2])
@@ -370,7 +542,7 @@ class Game_Player < Game_Character
pbOnStepTaken(result) pbOnStepTaken(result)
end end
# Try to manually interact with events # Try to manually interact with events
if Input.trigger?(Input::USE) && !$PokemonTemp.miniupdate if Input.trigger?(Input::USE) && !$game_temp.in_mini_update
# Same position and front event determinant # Same position and front event determinant
check_event_trigger_here([0]) check_event_trigger_here([0])
check_event_trigger_there([0, 2]) check_event_trigger_there([0, 2])
@@ -380,17 +552,18 @@ end
def pbGetPlayerCharset(meta,charset,trainer=nil,force=false) #===============================================================================
trainer = $Trainer if !trainer #
#===============================================================================
def pbGetPlayerCharset(charset, trainer = nil, force = false)
trainer = $player if !trainer
outfit = (trainer) ? trainer.outfit : 0 outfit = (trainer) ? trainer.outfit : 0
if $game_player && $game_player.charsetData && !force return nil if !force && $game_player&.charsetData &&
return nil if $game_player.charsetData[0] == $Trainer.character_ID && $game_player.charsetData[0] == trainer.character_ID &&
$game_player.charsetData[1] == charset && $game_player.charsetData[1] == charset &&
$game_player.charsetData[2] == outfit $game_player.charsetData[2] == outfit
end $game_player.charsetData = [trainer.character_ID, charset, outfit] if $game_player
$game_player.charsetData = [$Trainer.character_ID,charset,outfit] if $game_player ret = charset
ret = meta[charset]
ret = meta[1] if nil_or_empty?(ret)
if pbResolveBitmap("Graphics/Characters/" + ret + "_" + outfit.to_s) if pbResolveBitmap("Graphics/Characters/" + ret + "_" + outfit.to_s)
ret = ret + "_" + outfit.to_s ret = ret + "_" + outfit.to_s
end end
@@ -398,21 +571,20 @@ def pbGetPlayerCharset(meta,charset,trainer=nil,force=false)
end end
def pbUpdateVehicle def pbUpdateVehicle
meta = GameData::Metadata.get_player($Trainer.character_ID) if $PokemonGlobal&.diving
if meta $game_player.set_movement_type(:diving)
charset = 1 # Regular graphic elsif $PokemonGlobal&.surfing
if $PokemonGlobal.diving; charset = 5 # Diving graphic $game_player.set_movement_type(:surfing)
elsif $PokemonGlobal.surfing; charset = 3 # Surfing graphic elsif $PokemonGlobal&.bicycle
elsif $PokemonGlobal.bicycle; charset = 2 # Bicycle graphic $game_player.set_movement_type(:cycling)
end else
newCharName = pbGetPlayerCharset(meta,charset) $game_player.set_movement_type(:walking)
$game_player.character_name = newCharName if newCharName
end end
end end
def pbCancelVehicles(destination=nil) def pbCancelVehicles(destination = nil, cancel_swimming = true)
$PokemonGlobal.surfing = false $PokemonGlobal.surfing = false if cancel_swimming
$PokemonGlobal.diving = false $PokemonGlobal.diving = false if cancel_swimming
$PokemonGlobal.bicycle = false if !destination || !pbCanUseBike?(destination) $PokemonGlobal.bicycle = false if !destination || !pbCanUseBike?(destination)
pbUpdateVehicle pbUpdateVehicle
end end
@@ -420,14 +592,13 @@ end
def pbCanUseBike?(map_id) def pbCanUseBike?(map_id)
map_metadata = GameData::MapMetadata.try_get(map_id) map_metadata = GameData::MapMetadata.try_get(map_id)
return false if !map_metadata return false if !map_metadata
return true if map_metadata.always_bicycle return map_metadata.always_bicycle || map_metadata.can_bicycle || map_metadata.outdoor_map
val = map_metadata.can_bicycle || map_metadata.outdoor_map
return (val) ? true : false
end end
def pbMountBike def pbMountBike
return if $PokemonGlobal.bicycle return if $PokemonGlobal.bicycle
$PokemonGlobal.bicycle = true $PokemonGlobal.bicycle = true
$stats.cycle_count += 1
pbUpdateVehicle pbUpdateVehicle
bike_bgm = GameData::Metadata.get.bicycle_BGM bike_bgm = GameData::Metadata.get.bicycle_BGM
pbCueBGM(bike_bgm, 0.5) if bike_bgm pbCueBGM(bike_bgm, 0.5) if bike_bgm

View File

@@ -56,7 +56,7 @@ class Game_CommonEvent
def refresh def refresh
# Create an interpreter for parallel process if necessary # Create an interpreter for parallel process if necessary
if self.trigger == 2 && switchIsOn?(self.switch_id) if self.trigger == 2 && switchIsOn?(self.switch_id)
if @interpreter == nil if @interpreter.nil?
@interpreter = Interpreter.new @interpreter = Interpreter.new
end end
else else
@@ -67,15 +67,10 @@ class Game_CommonEvent
# * Frame Update # * Frame Update
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
def update def update
# If parallel process is valid return if !@interpreter
if @interpreter != nil # Set up event if interpreter is not running
# If not running @interpreter.setup(self.list, 0) if !@interpreter.running?
unless @interpreter.running?
# Set up event
@interpreter.setup(self.list, 0)
end
# Update interpreter # Update interpreter
@interpreter.update @interpreter.update
end end
end end
end

View File

@@ -1,102 +0,0 @@
class Game_Player < Game_Character
@@bobFrameSpeed = 1.0/15
def fullPattern
case self.direction
when 2 then return self.pattern
when 4 then return self.pattern + 4
when 6 then return self.pattern + 8
when 8 then return self.pattern + 12
end
return 0
end
def setDefaultCharName(chname,pattern,lockpattern=false)
return if pattern<0 || pattern>=16
@defaultCharacterName = chname
@direction = [2,4,6,8][pattern/4]
@pattern = pattern%4
@lock_pattern = lockpattern
end
def pbCanRun?
return false if $game_temp.in_menu || $game_temp.in_battle ||
@move_route_forcing || $game_temp.message_window_showing ||
pbMapInterpreterRunning?
input = ($PokemonSystem.runstyle == 1) ^ Input.press?(Input::ACTION)
return input && $Trainer.has_running_shoes && !jumping? &&
!$PokemonGlobal.diving && !$PokemonGlobal.surfing &&
!$PokemonGlobal.bicycle && !$game_player.pbTerrainTag.must_walk
end
def pbIsRunning?
return moving? && !@move_route_forcing && pbCanRun?
end
def character_name
@defaultCharacterName = "" if !@defaultCharacterName
return @defaultCharacterName if @defaultCharacterName!=""
if !@move_route_forcing && $Trainer.character_ID>=0
meta = GameData::Metadata.get_player($Trainer.character_ID)
if meta && !$PokemonGlobal.bicycle && !$PokemonGlobal.diving && !$PokemonGlobal.surfing
charset = 1 # Display normal character sprite
if pbCanRun? && (moving? || @wasmoving) && Input.dir4!=0 && meta[4] && meta[4]!=""
charset = 4 # Display running character sprite
end
newCharName = pbGetPlayerCharset(meta,charset)
@character_name = newCharName if newCharName
@wasmoving = moving?
end
end
return @character_name
end
def update_command
if $game_player.pbTerrainTag.ice
self.move_speed = 4 # Sliding on ice
elsif !moving? && !@move_route_forcing && $PokemonGlobal
if $PokemonGlobal.bicycle
self.move_speed = 5 # Cycling
elsif pbCanRun? || $PokemonGlobal.surfing
self.move_speed = 4 # Running, surfing
else
self.move_speed = 3 # Walking, diving
end
end
super
end
def update_pattern
if $PokemonGlobal.surfing || $PokemonGlobal.diving
p = ((Graphics.frame_count%60)*@@bobFrameSpeed).floor
@pattern = p if !@lock_pattern
@pattern_surf = p
@bob_height = (p>=2) ? 2 : 0
else
@bob_height = 0
super
end
end
end
=begin
class Game_Character
alias update_old2 update
def update
if self.is_a?(Game_Event)
if @dependentEvents
for i in 0...@dependentEvents.length
if @dependentEvents[i][0]==$game_map.map_id &&
@dependentEvents[i][1]==self.id
self.move_speed_real = $game_player.move_speed_real
break
end
end
end
end
update_old2
end
end
=end

View File

@@ -0,0 +1,204 @@
#===============================================================================
# Instances of this are stored in @realEvents.
#===============================================================================
class Game_Follower < Game_Event
attr_writer :map
def initialize(event_data)
# Create RPG::Event to base self on
rpg_event = RPG::Event.new(event_data.x, event_data.y)
rpg_event.id = event_data.event_id
rpg_event.name = event_data.event_name
if event_data.common_event_id
# Must setup common event list here and now
common_event = Game_CommonEvent.new(event_data.common_event_id)
rpg_event.pages[0].list = common_event.list
end
# Create self
super(event_data.original_map_id, rpg_event, $map_factory.getMap(event_data.current_map_id))
# Modify self
self.character_name = event_data.character_name
self.character_hue = event_data.character_hue
case event_data.direction
when 2 then turn_down
when 4 then turn_left
when 6 then turn_right
when 8 then turn_up
end
end
#=============================================================================
def move_through(direction)
old_through = @through
@through = true
case direction
when 2 then move_down
when 4 then move_left
when 6 then move_right
when 8 then move_up
end
@through = old_through
end
def move_fancy(direction)
delta_x = (direction == 6) ? 1 : (direction == 4) ? -1 : 0
delta_y = (direction == 2) ? 1 : (direction == 8) ? -1 : 0
new_x = self.x + delta_x
new_y = self.y + delta_y
# Move if new position is the player's, or the new position is passable,
# or self's current position is not passable
if ($game_player.x == new_x && $game_player.y == new_y) ||
location_passable?(new_x, new_y, 10 - direction) ||
!location_passable?(self.x, self.y, direction)
move_through(direction)
end
end
def jump_fancy(direction, leader)
delta_x = (direction == 6) ? 2 : (direction == 4) ? -2 : 0
delta_y = (direction == 2) ? 2 : (direction == 8) ? -2 : 0
half_delta_x = delta_x / 2
half_delta_y = delta_y / 2
if location_passable?(self.x + half_delta_x, self.y + half_delta_y, 10 - direction)
# Can walk over the middle tile normally; just take two steps
move_fancy(direction)
move_fancy(direction)
elsif location_passable?(self.x + delta_x, self.y + delta_y, 10 - direction)
# Can't walk over the middle tile, but can walk over the end tile; jump over
if location_passable?(self.x, self.y, direction)
if leader.jumping?
@jump_speed_real = leader.jump_speed_real
else
# This is doubled because self has to jump 2 tiles in the time it
# takes the leader to move one tile.
@jump_speed_real = leader.move_speed_real * 2
end
jump(delta_x, delta_y)
else
# self's current tile isn't passable; just take two steps ignoring passability
move_through(direction)
move_through(direction)
end
end
end
def fancy_moveto(new_x, new_y, leader)
if self.x - new_x == 1 && self.y == new_y
move_fancy(4)
elsif self.x - new_x == -1 && self.y == new_y
move_fancy(6)
elsif self.x == new_x && self.y - new_y == 1
move_fancy(8)
elsif self.x == new_x && self.y - new_y == -1
move_fancy(2)
elsif self.x - new_x == 2 && self.y == new_y
jump_fancy(4, leader)
elsif self.x - new_x == -2 && self.y == new_y
jump_fancy(6, leader)
elsif self.x == new_x && self.y - new_y == 2
jump_fancy(8, leader)
elsif self.x == new_x && self.y - new_y == -2
jump_fancy(2, leader)
elsif self.x != new_x || self.y != new_y
moveto(new_x, new_y)
end
end
#=============================================================================
def turn_towards_leader(leader)
pbTurnTowardEvent(self, leader)
end
def follow_leader(leader, instant = false, leaderIsTrueLeader = true)
maps_connected = $map_factory.areConnected?(leader.map.map_id, self.map.map_id)
target = nil
# Get the target tile that self wants to move to
if maps_connected
behind_direction = 10 - leader.direction
target = $map_factory.getFacingTile(behind_direction, leader)
if target && $map_factory.getTerrainTag(target[0], target[1], target[2]).ledge
# Get the tile above the ledge (where the leader jumped from)
target = $map_factory.getFacingTileFromPos(target[0], target[1], target[2], behind_direction)
end
target = [leader.map.map_id, leader.x, leader.y] if !target
else
# Map transfer to an unconnected map
target = [leader.map.map_id, leader.x, leader.y]
end
# Move self to the target
if self.map.map_id != target[0]
vector = $map_factory.getRelativePos(target[0], 0, 0, self.map.map_id, @x, @y)
@map = $map_factory.getMap(target[0])
# NOTE: Can't use moveto because vector is outside the boundaries of the
# map, and moveto doesn't allow setting invalid coordinates.
@x = vector[0]
@y = vector[1]
@real_x = @x * Game_Map::REAL_RES_X
@real_y = @y * Game_Map::REAL_RES_Y
end
if instant || !maps_connected
moveto(target[1], target[2])
else
fancy_moveto(target[1], target[2], leader)
end
end
#=============================================================================
def update_move
was_jumping = jumping?
super
if was_jumping && !jumping?
spriteset = $scene.spriteset(map_id)
spriteset&.addUserAnimation(Settings::DUST_ANIMATION_ID, self.x, self.y, true, 1)
end
end
#=============================================================================
private
def location_passable?(x, y, direction)
this_map = self.map
return false if !this_map || !this_map.valid?(x, y)
return true if @through
passed_tile_checks = false
bit = (1 << ((direction / 2) - 1)) & 0x0f
# Check all events for ones using tiles as graphics, and see if they're passable
this_map.events.each_value do |event|
next if event.tile_id < 0 || event.through || !event.at_coordinate?(x, y)
tile_data = GameData::TerrainTag.try_get(this_map.terrain_tags[event.tile_id])
next if tile_data.ignore_passability
next if tile_data.bridge && $PokemonGlobal.bridge == 0
return false if tile_data.ledge
passage = this_map.passages[event.tile_id] || 0
return false if passage & bit != 0
passed_tile_checks = true if (tile_data.bridge && $PokemonGlobal.bridge > 0) ||
(this_map.priorities[event.tile_id] || -1) == 0
break if passed_tile_checks
end
# Check if tiles at (x, y) allow passage for followe
if !passed_tile_checks
[2, 1, 0].each do |i|
tile_id = this_map.data[x, y, i] || 0
next if tile_id == 0
tile_data = GameData::TerrainTag.try_get(this_map.terrain_tags[tile_id])
next if tile_data.ignore_passability
next if tile_data.bridge && $PokemonGlobal.bridge == 0
return false if tile_data.ledge
passage = this_map.passages[tile_id] || 0
return false if passage & bit != 0
break if tile_data.bridge && $PokemonGlobal.bridge > 0
break if (this_map.priorities[tile_id] || -1) == 0
end
end
# Check all events on the map to see if any are in the way
this_map.events.each_value do |event|
next if !event.at_coordinate?(x, y)
return false if !event.through && event.character_name != ""
end
return true
end
end

View File

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

View File

@@ -0,0 +1,435 @@
#===============================================================================
# Data saved in $PokemonGlobal.followers.
#===============================================================================
class FollowerData
attr_accessor :original_map_id
attr_accessor :event_id
attr_accessor :event_name
attr_accessor :current_map_id
attr_accessor :x, :y
attr_accessor :direction
attr_accessor :character_name, :character_hue
attr_accessor :name
attr_accessor :common_event_id
attr_accessor :visible
attr_accessor :invisible_after_transfer
def initialize(original_map_id, event_id, event_name, current_map_id, x, y,
direction, character_name, character_hue)
@original_map_id = original_map_id
@event_id = event_id
@event_name = event_name
@current_map_id = current_map_id
@x = x
@y = y
@direction = direction
@character_name = character_name
@character_hue = character_hue
@name = nil
@common_event_id = nil
@visible = true
@invisible_after_transfer = false
end
def visible?
return @visible && !@invisible_after_transfer
end
def interact(event)
return if !event || event.list.size <= 1
return if !@common_event_id
# Start event
$game_map.refresh if $game_map.need_refresh
event.lock
pbMapInterpreter.setup(event.list, event.id, event.map.map_id)
end
end
#===============================================================================
# Permanently stores data of follower events (i.e. in save files).
#===============================================================================
class PokemonGlobalMetadata
attr_accessor :dependentEvents # Deprecated
attr_writer :followers
def followers
@followers = [] if !@followers
return @followers
end
end
#===============================================================================
# Stores Game_Follower instances just for the current play session.
#===============================================================================
class Game_Temp
attr_writer :followers
def followers
@followers = Game_FollowerFactory.new if !@followers
return @followers
end
end
#===============================================================================
#
#===============================================================================
class Game_FollowerFactory
attr_reader :last_update
def initialize
@events = []
$PokemonGlobal.followers.each do |follower|
@events.push(create_follower_object(follower))
end
@last_update = -1
end
#=============================================================================
def add_follower(event, name = nil, common_event_id = nil)
return if !event
followers = $PokemonGlobal.followers
if followers.any? { |data| data.original_map_id == $game_map.map_id && data.event_id == event.id }
return # Event is already dependent
end
eventData = FollowerData.new($game_map.map_id, event.id, event.name,
$game_map.map_id, event.x, event.y, event.direction,
event.character_name.clone, event.character_hue)
eventData.name = name
eventData.common_event_id = common_event_id
newEvent = create_follower_object(eventData)
followers.push(eventData)
@events.push(newEvent)
@last_update += 1
end
def remove_follower_by_event(event)
followers = $PokemonGlobal.followers
map_id = $game_map.map_id
followers.each_with_index do |follower, i|
next if follower.current_map_id != map_id
next if follower.original_map_id != event.map_id
next if follower.event_id != event.id
followers[i] = nil
@events[i] = nil
@last_update += 1
end
followers.compact!
@events.compact!
end
def remove_follower_by_name(name)
followers = $PokemonGlobal.followers
followers.each_with_index do |follower, i|
next if follower.name != name
followers[i] = nil
@events[i] = nil
@last_update += 1
end
followers.compact!
@events.compact!
end
def remove_all_followers
$PokemonGlobal.followers.clear
@events.clear
@last_update += 1
end
def get_follower_by_index(index = 0)
@events.each_with_index { |event, i| return event if i == index }
return nil
end
def get_follower_by_name(name)
each_follower { |event, follower| return event if follower&.name == name }
return nil
end
def each_follower
$PokemonGlobal.followers.each_with_index { |follower, i| yield @events[i], follower }
end
#=============================================================================
def turn_followers
leader = $game_player
$PokemonGlobal.followers.each_with_index do |follower, i|
event = @events[i]
event.turn_towards_leader(leader)
follower.direction = event.direction
leader = event
end
end
def move_followers
leader = $game_player
$PokemonGlobal.followers.each_with_index do |follower, i|
event = @events[i]
event.follow_leader(leader, false, (i == 0))
follower.x = event.x
follower.y = event.y
follower.current_map_id = event.map.map_id
follower.direction = event.direction
leader = event
end
end
def map_transfer_followers
$PokemonGlobal.followers.each_with_index do |follower, i|
event = @events[i]
event.map = $game_map
event.moveto($game_player.x, $game_player.y)
event.direction = $game_player.direction
event.opacity = 255
follower.x = event.x
follower.y = event.y
follower.current_map_id = event.map.map_id
follower.direction = event.direction
follower.invisible_after_transfer = true
end
end
def follow_into_door
# Setting an event's move route also makes it start along that move route,
# so we need to record all followers' current positions first before setting
# any move routes
follower_pos = []
follower_pos.push([$game_player.map.map_id, $game_player.x, $game_player.y])
$PokemonGlobal.followers.each_with_index do |follower, i|
event = @events[i]
follower_pos.push([event.map.map_id, event.x, event.y])
end
# Calculate and set move route from each follower to player
move_route = []
$PokemonGlobal.followers.each_with_index do |follower, i|
event = @events[i]
leader = follower_pos[i]
vector = $map_factory.getRelativePos(event.map.map_id, event.x, event.y,
leader[0], leader[1], leader[2])
if vector[0] != 0
move_route.prepend((vector[0] > 0) ? PBMoveRoute::Right : PBMoveRoute::Left)
elsif vector[1] != 0
move_route.prepend((vector[1] > 0) ? PBMoveRoute::Down : PBMoveRoute::Up)
end
pbMoveRoute(event, move_route + [PBMoveRoute::Opacity, 0])
end
end
# Used when coming out of a door.
def hide_followers
$PokemonGlobal.followers.each_with_index do |follower, i|
event = @events[i]
event.opacity = 0
end
end
# Used when coming out of a door. Makes all followers invisible until the
# player starts moving.
def put_followers_on_player
$PokemonGlobal.followers.each_with_index do |follower, i|
event = @events[i]
event.moveto($game_player.x, $game_player.y)
event.opacity = 255
follower.x = event.x
follower.y = event.y
follower.invisible_after_transfer = true
end
end
#=============================================================================
def update
followers = $PokemonGlobal.followers
return if followers.length == 0
# Update all followers
leader = $game_player
player_moving = $game_player.moving? || $game_player.jumping?
followers.each_with_index do |follower, i|
event = @events[i]
next if !@events[i]
if follower.invisible_after_transfer && player_moving
follower.invisible_after_transfer = false
event.turn_towards_leader($game_player)
end
event.move_speed = leader.move_speed
event.transparent = !follower.visible?
if $PokemonGlobal.sliding
event.straighten
event.walk_anime = false
else
event.walk_anime = true
end
if event.jumping? || event.moving? || !player_moving
event.update
elsif !event.starting
event.set_starting
event.update
event.clear_starting
end
follower.direction = event.direction
leader = event
end
# Check event triggers
if Input.trigger?(Input::USE) && !$game_temp.in_menu && !$game_temp.in_battle &&
!$game_player.move_route_forcing && !$game_temp.message_window_showing &&
!pbMapInterpreterRunning?
# Get position of tile facing the player
facing_tile = $map_factory.getFacingTile
# Assumes player is 1x1 tile in size
each_follower do |event, follower|
if event.at_coordinate?($game_player.x, $game_player.y) # Underneath player
next if !event.over_trigger?
elsif facing_tile && event.map.map_id == facing_tile[0] &&
event.at_coordinate?(facing_tile[1], facing_tile[2]) # On facing tile
next if event.over_trigger?
else # Somewhere else
next
end
next if event.jumping?
follower.interact(event)
end
end
end
#=============================================================================
private
def create_follower_object(event_data)
return Game_Follower.new(event_data)
end
end
#===============================================================================
#
#===============================================================================
class FollowerSprites
def initialize(viewport)
@viewport = viewport
@sprites = []
@last_update = nil
@disposed = false
end
def dispose
return if @disposed
@sprites.each { |sprite| sprite.dispose }
@sprites.clear
@disposed = true
end
def disposed?
return @disposed
end
def refresh
@sprites.each { |sprite| sprite.dispose }
@sprites.clear
$game_temp.followers.each_follower do |event, follower|
@sprites.push(Sprite_Character.new(@viewport, event))
end
end
def update
if $game_temp.followers.last_update != @last_update
refresh
@last_update = $game_temp.followers.last_update
end
@sprites.each { |sprite| sprite.update }
end
end
#===============================================================================
# Helper module for adding/removing/getting followers.
#===============================================================================
module Followers
module_function
# @param event_id [Integer] ID of the event on the current map to be added as a follower
# @param name [String] identifier name of the follower to be added
# @param common_event_id [Integer] ID of the Common Event triggered when interacting with this follower
def add(event_id, name, common_event_id)
$game_temp.followers.add_follower($game_map.events[event_id], name, common_event_id)
end
# @param event [Game_Event] map event to be added as a follower
def add_event(event)
$game_temp.followers.add_follower(event)
end
# @param name [String] identifier name of the follower to be removed
def remove(name)
$game_temp.followers.remove_follower_by_name(name)
end
# @param event [Game_Event] map event to be removed as a follower
def remove_event(event)
$game_temp.followers.remove_follower_by_event(event)
end
# Removes all followers.
def clear
$game_temp.followers.remove_all_followers
pbDeregisterPartner rescue nil
end
# @param name [String, nil] name of the follower to get, or nil for the first follower
# @return [Game_Follower, nil] follower object
def get(name = nil)
return $game_temp.followers.get_follower_by_name(name) if name
return $game_temp.followers.get_follower_by_index
end
def follow_into_door
$game_temp.followers.follow_into_door
end
def hide_followers
$game_temp.followers.hide_followers
end
def put_followers_on_player
$game_temp.followers.put_followers_on_player
end
end
#===============================================================================
# Deprecated methods
#===============================================================================
# @deprecated This method is slated to be removed in v21.
def pbAddDependency2(event_id, name, common_event_id)
Deprecation.warn_method("pbAddDependency2", "v21", "Followers.add(event_id, name, common_event_id)")
Followers.add(event_id, name, common_event_id)
end
# @deprecated This method is slated to be removed in v21.
def pbAddDependency(event)
Deprecation.warn_method("pbAddDependency", "v21", "Followers.add_event(event)")
Followers.add_event(event)
end
# @deprecated This method is slated to be removed in v21.
def pbRemoveDependency2(name)
Deprecation.warn_method("pbRemoveDependency2", "v21", "Followers.remove(name)")
Followers.remove(name)
end
# @deprecated This method is slated to be removed in v21.
def pbRemoveDependency(event)
Deprecation.warn_method("pbRemoveDependency", "v21", "Followers.remove_event(event)")
Followers.remove_event(event)
end
# @deprecated This method is slated to be removed in v21.
def pbRemoveDependencies
Deprecation.warn_method("pbRemoveDependencies", "v21", "Followers.clear")
Followers.clear
end
# @deprecated This method is slated to be removed in v21.
def pbGetDependency(name)
Deprecation.warn_method("pbGetDependency", "v21", "Followers.get(name)")
Followers.get(name)
end

View File

@@ -0,0 +1,198 @@
#===============================================================================
# Stored in $stats
#===============================================================================
class GameStats
# Travel
attr_accessor :distance_walked, :distance_cycled, :distance_surfed # surfed includes diving
attr_accessor :distance_slid_on_ice # Also counted in distance_walked
attr_accessor :cycle_count, :surf_count, :dive_count
# Field actions
attr_accessor :fly_count, :cut_count, :flash_count
attr_accessor :rock_smash_count, :rock_smash_battles
attr_accessor :headbutt_count, :headbutt_battles
attr_accessor :strength_push_count # Number of shoves, not the times Strength was used
attr_accessor :waterfall_count, :waterfalls_descended
# Items
attr_accessor :repel_count
attr_accessor :itemfinder_count
attr_accessor :fishing_count, :fishing_battles
attr_accessor :poke_radar_count, :poke_radar_longest_chain
attr_accessor :berry_plants_picked, :max_yield_berry_plants
attr_accessor :berries_planted
# NPCs
attr_accessor :poke_center_count
attr_accessor :revived_fossil_count
attr_accessor :lottery_prize_count # Times won any prize at all
# Pokémon
attr_accessor :eggs_hatched
attr_accessor :evolution_count, :evolutions_cancelled
attr_accessor :trade_count
attr_accessor :moves_taught_by_item, :moves_taught_by_tutor, :moves_taught_by_reminder
attr_accessor :day_care_deposits, :day_care_levels_gained
attr_accessor :pokerus_infections
attr_accessor :shadow_pokemon_purified
# Battles
attr_accessor :wild_battles_won, :wild_battles_lost # Lost includes fled from
attr_accessor :trainer_battles_won, :trainer_battles_lost
attr_accessor :total_exp_gained
attr_accessor :battle_money_gained, :battle_money_lost
attr_accessor :blacked_out_count
attr_accessor :mega_evolution_count
attr_accessor :failed_poke_ball_count
# Currency
attr_accessor :money_spent_at_marts
attr_accessor :money_earned_at_marts
attr_accessor :mart_items_bought, :premier_balls_earned
attr_accessor :drinks_bought, :drinks_won # From vending machines
attr_accessor :coins_won, :coins_lost # Not bought, not spent
attr_accessor :battle_points_won, :battle_points_spent # Currently unused
attr_accessor :soot_collected
# Special stats
attr_accessor :gym_leader_attempts # An array of integers
attr_accessor :times_to_get_badges # An array of times in seconds
attr_accessor :elite_four_attempts
attr_accessor :hall_of_fame_entry_count # See also Game Variable 13
attr_accessor :time_to_enter_hall_of_fame # In seconds
attr_accessor :safari_pokemon_caught, :most_captures_per_safari_game
attr_accessor :bug_contest_count, :bug_contest_wins
# Play
attr_accessor :play_time # In seconds
attr_accessor :play_sessions
attr_accessor :time_last_saved # In seconds
def initialize
# Travel
@distance_walked = 0
@distance_cycled = 0
@distance_surfed = 0
@distance_slid_on_ice = 0
@cycle_count = 0
@surf_count = 0
@dive_count = 0
# Field actions
@fly_count = 0
@cut_count = 0
@flash_count = 0
@rock_smash_count = 0
@rock_smash_battles = 0
@headbutt_count = 0
@headbutt_battles = 0
@strength_push_count = 0
@waterfall_count = 0
@waterfalls_descended = 0
# Items
@repel_count = 0
@itemfinder_count = 0
@fishing_count = 0
@fishing_battles = 0
@poke_radar_count = 0
@poke_radar_longest_chain = 0
@berry_plants_picked = 0
@max_yield_berry_plants = 0
@berries_planted = 0
# NPCs
@poke_center_count = 0 # Incremented in Poké Center nurse events
@revived_fossil_count = 0 # Incremented in fossil reviver events
@lottery_prize_count = 0 # Incremented in lottery NPC events
# Pokémon
@eggs_hatched = 0
@evolution_count = 0
@evolutions_cancelled = 0
@trade_count = 0
@moves_taught_by_item = 0
@moves_taught_by_tutor = 0
@moves_taught_by_reminder = 0
@day_care_deposits = 0
@day_care_levels_gained = 0
@pokerus_infections = 0
@shadow_pokemon_purified = 0
# Battles
@wild_battles_won = 0
@wild_battles_lost = 0
@trainer_battles_won = 0
@trainer_battles_lost = 0
@total_exp_gained = 0
@battle_money_gained = 0
@battle_money_lost = 0
@blacked_out_count = 0
@mega_evolution_count = 0
@failed_poke_ball_count = 0
# Currency
@money_spent_at_marts = 0
@money_earned_at_marts = 0
@mart_items_bought = 0
@premier_balls_earned = 0
@drinks_bought = 0 # Incremented in vending machine events
@drinks_won = 0 # Incremented in vending machine events
@coins_won = 0
@coins_lost = 0
@battle_points_won = 0
@battle_points_spent = 0
@soot_collected = 0
# Special stats
@gym_leader_attempts = [0] * 50 # Incremented in Gym Leader events (50 is arbitrary but suitably large)
@times_to_get_badges = [] # Set with set_time_to_badge(number) in Gym Leader events
@elite_four_attempts = 0 # Incremented in door event leading to the first E4 member
@hall_of_fame_entry_count = 0 # Incremented in Hall of Fame event
@time_to_enter_hall_of_fame = 0 # Set with set_time_to_hall_of_fame in Hall of Fame event
@safari_pokemon_caught = 0
@most_captures_per_safari_game = 0
@bug_contest_count = 0
@bug_contest_wins = 0
# Play
@play_time = 0
@play_sessions = 0
@time_last_saved = 0
end
def distance_moved
return @distance_walked + @distance_cycled + @distance_surfed
end
def caught_pokemon_count
return 0 if !$player
ret = 0
GameData::Species.each_species { |sp| ret += $player.pokedex.caught_count(sp) }
return ret
end
def save_count
return $game_system&.save_count || 0
end
def set_time_to_badge(number)
@times_to_get_badges[number] = @play_time
end
def set_time_to_hall_of_fame
@time_to_enter_hall_of_fame = @play_time
end
def play_time_per_session
return @play_time / @play_sessions
end
def set_time_last_saved
@time_last_saved = @play_time
end
def time_since_last_save
return @play_time - @time_last_saved
end
end
#===============================================================================
#
#===============================================================================
module Graphics
unless defined?(update_stats_play_time)
class << Graphics
alias update_stats_play_time update
end
end
def self.update
update_stats_play_time
$stats.play_time += self.delta_s if $stats && $PokemonEncounters
end
end

View File

@@ -7,11 +7,11 @@ class Sprite_Picture
end end
def dispose def dispose
@sprite.dispose if @sprite @sprite&.dispose
end end
def update def update
@sprite.update if @sprite @sprite&.update
# If picture file name is different from current one # If picture file name is different from current one
if @picture_name != @picture.name if @picture_name != @picture.name
# Remember file name to instance variables # Remember file name to instance variables
@@ -27,7 +27,7 @@ class Sprite_Picture
if @picture_name == "" if @picture_name == ""
# Set sprite to invisible # Set sprite to invisible
if @sprite if @sprite
@sprite.dispose if @sprite @sprite&.dispose
@sprite = nil @sprite = nil
end end
return return

View File

@@ -7,7 +7,7 @@ class Sprite_Timer
end end
def dispose def dispose
@timer.dispose if @timer @timer&.dispose
@timer = nil @timer = nil
@disposed = true @disposed = true
end end
@@ -38,8 +38,8 @@ class Sprite_Timer
@timer.text = _ISPRINTF("<ac>{1:02d}:{2:02d}", min, sec) @timer.text = _ISPRINTF("<ac>{1:02d}:{2:02d}", min, sec)
end end
@timer.update @timer.update
else elsif @timer
@timer.visible=false if @timer @timer.visible = false
end end
end end
end end

View File

@@ -8,7 +8,7 @@ class BushBitmap
end end
def dispose def dispose
@bitmaps.each { |b| b.dispose if b } @bitmaps.each { |b| b&.dispose }
end end
def bitmap def bitmap
@@ -28,7 +28,7 @@ class BushBitmap
ret = Bitmap.new(bitmap.width, bitmap.height) ret = Bitmap.new(bitmap.width, bitmap.height)
charheight = ret.height / 4 charheight = ret.height / 4
cy = charheight - depth - 2 cy = charheight - depth - 2
for i in 0...4 4.times do |i|
y = i * charheight y = i * charheight
if cy >= 0 if cy >= 0
ret.blt(0, y, bitmap, Rect.new(0, y, ret.width, cy)) ret.blt(0, y, bitmap, Rect.new(0, y, ret.width, cy))
@@ -80,13 +80,13 @@ class Sprite_Character < RPG::Sprite
end end
def dispose def dispose
@bushbitmap.dispose if @bushbitmap @bushbitmap&.dispose
@bushbitmap = nil @bushbitmap = nil
@charbitmap.dispose if @charbitmap @charbitmap&.dispose
@charbitmap = nil @charbitmap = nil
@reflection.dispose if @reflection @reflection&.dispose
@reflection = nil @reflection = nil
@surfbase.dispose if @surfbase @surfbase&.dispose
@surfbase = nil @surfbase = nil
super super
end end
@@ -102,12 +102,12 @@ class Sprite_Character < RPG::Sprite
@character_name = @character.character_name @character_name = @character.character_name
@character_hue = @character.character_hue @character_hue = @character.character_hue
@oldbushdepth = @character.bush_depth @oldbushdepth = @character.bush_depth
@charbitmap&.dispose
if @tile_id >= 384 if @tile_id >= 384
@charbitmap.dispose if @charbitmap
@charbitmap = pbGetTileBitmap(@character.map.tileset_name, @tile_id, @charbitmap = pbGetTileBitmap(@character.map.tileset_name, @tile_id,
@character_hue, @character.width, @character.height) @character_hue, @character.width, @character.height)
@charbitmapAnimated = false @charbitmapAnimated = false
@bushbitmap.dispose if @bushbitmap @bushbitmap&.dispose
@bushbitmap = nil @bushbitmap = nil
@spriteoffset = false @spriteoffset = false
@cw = Game_Map::TILE_WIDTH * @character.width @cw = Game_Map::TILE_WIDTH * @character.width
@@ -115,21 +115,20 @@ class Sprite_Character < RPG::Sprite
self.src_rect.set(0, 0, @cw, @ch) self.src_rect.set(0, 0, @cw, @ch)
self.ox = @cw / 2 self.ox = @cw / 2
self.oy = @ch self.oy = @ch
@character.sprite_size = [@cw, @ch]
else else
@charbitmap.dispose if @charbitmap
@charbitmap = AnimatedBitmap.new( @charbitmap = AnimatedBitmap.new(
'Graphics/Characters/' + @character_name, @character_hue) "Graphics/Characters/" + @character_name, @character_hue
RPG::Cache.retain('Graphics/Characters/', @character_name, @character_hue) if @character == $game_player )
RPG::Cache.retain("Graphics/Characters/", @character_name, @character_hue) if @character == $game_player
@charbitmapAnimated = true @charbitmapAnimated = true
@bushbitmap.dispose if @bushbitmap @bushbitmap&.dispose
@bushbitmap = nil @bushbitmap = nil
@spriteoffset = @character_name[/offset/i] @spriteoffset = @character_name[/offset/i]
@cw = @charbitmap.width / 4 @cw = @charbitmap.width / 4
@ch = @charbitmap.height / 4 @ch = @charbitmap.height / 4
self.ox = @cw / 2 self.ox = @cw / 2
@character.sprite_size = [@cw, @ch]
end end
@character.sprite_size = [@cw, @ch]
end end
@charbitmap.update if @charbitmapAnimated @charbitmap.update if @charbitmapAnimated
bushdepth = @character.bush_depth bushdepth = @character.bush_depth
@@ -157,17 +156,14 @@ class Sprite_Character < RPG::Sprite
self.x = @character.screen_x self.x = @character.screen_x
self.y = @character.screen_y self.y = @character.screen_y
self.z = @character.screen_z(@ch) self.z = @character.screen_z(@ch)
# self.zoom_x = Game_Map::TILE_WIDTH / 32.0
# self.zoom_y = Game_Map::TILE_HEIGHT / 32.0
self.opacity = @character.opacity self.opacity = @character.opacity
self.blend_type = @character.blend_type self.blend_type = @character.blend_type
# self.bush_depth = @character.bush_depth
if @character.animation_id != 0 if @character.animation_id != 0
animation = $data_animations[@character.animation_id] animation = $data_animations[@character.animation_id]
animation(animation, true) animation(animation, true)
@character.animation_id = 0 @character.animation_id = 0
end end
@reflection.update if @reflection @reflection&.update
@surfbase.update if @surfbase @surfbase&.update
end end
end end

View File

@@ -8,12 +8,10 @@ class Sprite_Reflection
@event = event @event = event
@height = 0 @height = 0
@fixedheight = false @fixedheight = false
if @event && @event!=$game_player if @event && @event != $game_player && @event.name[/reflection\((\d+)\)/i]
if @event.name[/reflection\((\d+)\)/i]
@height = $~[1].to_i || 0 @height = $~[1].to_i || 0
@fixedheight = true @fixedheight = true
end end
end
@viewport = viewport @viewport = viewport
@disposed = false @disposed = false
update update
@@ -21,7 +19,7 @@ class Sprite_Reflection
def dispose def dispose
if !@disposed if !@disposed
@sprite.dispose if @sprite @sprite&.dispose
@sprite = nil @sprite = nil
@disposed = true @disposed = true
end end
@@ -57,12 +55,13 @@ class Sprite_Reflection
y += @height * 16 y += @height * 16
width = @rsprite.src_rect.width width = @rsprite.src_rect.width
height = @rsprite.src_rect.height height = @rsprite.src_rect.height
@sprite.x = x+width/2 @sprite.x = x + (width / 2)
@sprite.y = y+height+height/2 @sprite.y = y + height + (height / 2)
@sprite.ox = width / 2 @sprite.ox = width / 2
@sprite.oy = height/2-2 # Hard-coded 2 pixel shift up @sprite.oy = (height / 2) - 2 # Hard-coded 2 pixel shift up
@sprite.oy -= @rsprite.character.bob_height * 2 @sprite.oy -= @rsprite.character.bob_height * 2
@sprite.z = -50 # Still water is -100, map is 0 and above @sprite.z = -50 # Still water is -100, map is 0 and above
@sprite.z += 1 if @event == $game_player
@sprite.zoom_x = @rsprite.zoom_x @sprite.zoom_x = @rsprite.zoom_x
@sprite.zoom_y = @rsprite.zoom_y @sprite.zoom_y = @rsprite.zoom_y
frame = (Graphics.frame_count % 40) / 10 frame = (Graphics.frame_count % 40) / 10

View File

@@ -21,7 +21,7 @@ class Sprite_SurfBase
def dispose def dispose
return if @disposed return if @disposed
@sprite.dispose if @sprite @sprite&.dispose
@sprite = nil @sprite = nil
@surfbitmap.dispose @surfbitmap.dispose
@divebitmap.dispose @divebitmap.dispose
@@ -62,9 +62,9 @@ class Sprite_SurfBase
sx = @event.pattern_surf * cw sx = @event.pattern_surf * cw
sy = ((@event.direction - 2) / 2) * ch sy = ((@event.direction - 2) / 2) * ch
@sprite.src_rect.set(sx, sy, cw, ch) @sprite.src_rect.set(sx, sy, cw, ch)
if $PokemonTemp.surfJump if $game_temp.surf_base_coords
@sprite.x = ($PokemonTemp.surfJump[0]*Game_Map::REAL_RES_X-@event.map.display_x+3)/4+(Game_Map::TILE_WIDTH/2) @sprite.x = ((($game_temp.surf_base_coords[0] * Game_Map::REAL_RES_X) - @event.map.display_x + 3) / 4) + (Game_Map::TILE_WIDTH / 2)
@sprite.y = ($PokemonTemp.surfJump[1]*Game_Map::REAL_RES_Y-@event.map.display_y+3)/4+(Game_Map::TILE_HEIGHT/2)+16 @sprite.y = ((($game_temp.surf_base_coords[1] * Game_Map::REAL_RES_Y) - @event.map.display_y + 3) / 4) + (Game_Map::TILE_HEIGHT / 2) + 16
else else
@sprite.x = @rsprite.x @sprite.x = @rsprite.x
@sprite.y = @rsprite.y @sprite.y = @rsprite.y

View File

@@ -1,12 +1,14 @@
class Spriteset_Global class Spriteset_Global
attr_reader :playersprite attr_reader :playersprite
@@viewport2 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT) @@viewport2 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT)
@@viewport2.z = 200 @@viewport2.z = 200
def initialize def initialize
@follower_sprites = FollowerSprites.new(Spriteset_Map.viewport)
@playersprite = Sprite_Character.new(Spriteset_Map.viewport, $game_player) @playersprite = Sprite_Character.new(Spriteset_Map.viewport, $game_player)
@picture_sprites = [] @picture_sprites = []
for i in 1..100 (1..100).each do |i|
@picture_sprites.push(Sprite_Picture.new(@@viewport2, $game_screen.pictures[i])) @picture_sprites.push(Sprite_Picture.new(@@viewport2, $game_screen.pictures[i]))
end end
@timer_sprite = Sprite_Timer.new @timer_sprite = Sprite_Timer.new
@@ -14,15 +16,18 @@ class Spriteset_Global
end end
def dispose def dispose
@follower_sprites.dispose
@follower_sprites = nil
@playersprite.dispose @playersprite.dispose
@picture_sprites.each { |sprite| sprite.dispose }
@timer_sprite.dispose
@playersprite = nil @playersprite = nil
@picture_sprites.each { |sprite| sprite.dispose }
@picture_sprites.clear @picture_sprites.clear
@timer_sprite.dispose
@timer_sprite = nil @timer_sprite = nil
end end
def update def update
@follower_sprites.update
@playersprite.update @playersprite.update
@picture_sprites.each { |sprite| sprite.update } @picture_sprites.each { |sprite| sprite.update }
@timer_sprite.update @timer_sprite.update

View File

@@ -1,3 +1,4 @@
# Unused
class ClippableSprite < Sprite_Character class ClippableSprite < Sprite_Character
def initialize(viewport, event, tilemap) def initialize(viewport, event, tilemap)
@tilemap = tilemap @tilemap = tilemap
@@ -8,22 +9,22 @@ class ClippableSprite < Sprite_Character
def update def update
super super
@_src_rect = self.src_rect @_src_rect = self.src_rect
tmright = @tilemap.map_data.xsize*Game_Map::TILE_WIDTH-@tilemap.ox tmright = (@tilemap.map_data.xsize * Game_Map::TILE_WIDTH) - @tilemap.ox
echoln("x=#{self.x},ox=#{self.ox},tmright=#{tmright},tmox=#{@tilemap.ox}") echoln "x=#{self.x},ox=#{self.ox},tmright=#{tmright},tmox=#{@tilemap.ox}"
if @tilemap.ox - self.ox < -self.x if @tilemap.ox - self.ox < -self.x
# clipped on left # clipped on left
diff = -self.x - @tilemap.ox + self.ox diff = -self.x - @tilemap.ox + self.ox
self.src_rect = Rect.new(@_src_rect.x + diff, @_src_rect.y, self.src_rect = Rect.new(@_src_rect.x + diff, @_src_rect.y,
@_src_rect.width - diff, @_src_rect.height) @_src_rect.width - diff, @_src_rect.height)
echoln("clipped out left: #{diff} #{@tilemap.ox-self.ox} #{self.x}") echoln "clipped out left: #{diff} #{@tilemap.ox - self.ox} #{self.x}"
elsif tmright - self.ox < self.x elsif tmright - self.ox < self.x
# clipped on right # clipped on right
diff = self.x - tmright + self.ox diff = self.x - tmright + self.ox
self.src_rect = Rect.new(@_src_rect.x, @_src_rect.y, self.src_rect = Rect.new(@_src_rect.x, @_src_rect.y,
@_src_rect.width - diff, @_src_rect.height) @_src_rect.width - diff, @_src_rect.height)
echoln("clipped out right: #{diff} #{tmright+self.ox} #{self.x}") echoln "clipped out right: #{diff} #{tmright + self.ox} #{self.x}"
else else
echoln("-not- clipped out left: #{diff} #{@tilemap.ox-self.ox} #{self.x}") echoln "-not- clipped out left: #{diff} #{@tilemap.ox - self.ox} #{self.x}"
end end
end end
end end
@@ -32,7 +33,7 @@ end
class Spriteset_Map class Spriteset_Map
attr_reader :map attr_reader :map
attr_accessor :tilemap
@@viewport0 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT) # Panorama @@viewport0 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT) # Panorama
@@viewport0.z = -100 @@viewport0.z = -100
@@viewport1 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT) # Map, events, player, fog @@viewport1 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT) # Map, events, player, fog
@@ -40,47 +41,38 @@ class Spriteset_Map
@@viewport3 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT) # Flashing @@viewport3 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT) # Flashing
@@viewport3.z = 500 @@viewport3.z = 500
def Spriteset_Map.viewport # For access by Spriteset_Global def self.viewport # For access by Spriteset_Global
return @@viewport1 return @@viewport1
end end
def initialize(map = nil) def initialize(map = nil)
@map = (map) ? map : $game_map @map = (map) ? map : $game_map
@tilemap = TilemapLoader.new(@@viewport1) $scene.map_renderer.add_tileset(@map.tileset_name)
@tilemap.tileset = pbGetTileset(@map.tileset_name) @map.autotile_names.each { |filename| $scene.map_renderer.add_autotile(filename) }
for i in 0...7 $scene.map_renderer.add_extra_autotiles(@map.tileset_id)
autotile_name = @map.autotile_names[i]
@tilemap.autotiles[i] = pbGetAutotile(autotile_name)
end
@tilemap.map_data = @map.data
@tilemap.priorities = @map.priorities
@tilemap.terrain_tags = @map.terrain_tags
@panorama = AnimatedPlane.new(@@viewport0) @panorama = AnimatedPlane.new(@@viewport0)
@fog = AnimatedPlane.new(@@viewport1) @fog = AnimatedPlane.new(@@viewport1)
@fog.z = 3000 @fog.z = 3000
@character_sprites = [] @character_sprites = []
for i in @map.events.keys.sort @map.events.keys.sort.each do |i|
sprite = Sprite_Character.new(@@viewport1, @map.events[i]) sprite = Sprite_Character.new(@@viewport1, @map.events[i])
@character_sprites.push(sprite) @character_sprites.push(sprite)
end end
@weather = RPG::Weather.new(@@viewport1) @weather = RPG::Weather.new(@@viewport1)
pbOnSpritesetCreate(self,@@viewport1) EventHandlers.trigger(:on_new_spriteset_map, self, @@viewport1)
update update
end end
def dispose def dispose
@tilemap.tileset.dispose if $scene.is_a?(Scene_Map)
for i in 0...7 $scene.map_renderer.remove_tileset(@map.tileset_name)
@tilemap.autotiles[i].dispose @map.autotile_names.each { |filename| $scene.map_renderer.remove_autotile(filename) }
$scene.map_renderer.remove_extra_autotiles(@map.tileset_id)
end end
@tilemap.dispose
@panorama.dispose @panorama.dispose
@fog.dispose @fog.dispose
for sprite in @character_sprites @character_sprites.each { |sprite| sprite.dispose }
sprite.dispose
end
@weather.dispose @weather.dispose
@tilemap = nil
@panorama = nil @panorama = nil
@fog = nil @fog = nil
@character_sprites.clear @character_sprites.clear
@@ -99,26 +91,23 @@ class Spriteset_Map
if @panorama_name != @map.panorama_name || @panorama_hue != @map.panorama_hue if @panorama_name != @map.panorama_name || @panorama_hue != @map.panorama_hue
@panorama_name = @map.panorama_name @panorama_name = @map.panorama_name
@panorama_hue = @map.panorama_hue @panorama_hue = @map.panorama_hue
@panorama.setPanorama(nil) if @panorama.bitmap!=nil @panorama.set_panorama(nil) if !@panorama.bitmap.nil?
@panorama.setPanorama(@panorama_name,@panorama_hue) if @panorama_name!="" @panorama.set_panorama(@panorama_name, @panorama_hue) if !nil_or_empty?(@panorama_name)
Graphics.frame_reset Graphics.frame_reset
end end
if @fog_name != @map.fog_name || @fog_hue != @map.fog_hue if @fog_name != @map.fog_name || @fog_hue != @map.fog_hue
@fog_name = @map.fog_name @fog_name = @map.fog_name
@fog_hue = @map.fog_hue @fog_hue = @map.fog_hue
@fog.setFog(nil) if @fog.bitmap!=nil @fog.set_fog(nil) if !@fog.bitmap.nil?
@fog.setFog(@fog_name,@fog_hue) if @fog_name!="" @fog.set_fog(@fog_name, @fog_hue) if !nil_or_empty?(@fog_name)
Graphics.frame_reset Graphics.frame_reset
end end
tmox = (@map.display_x / Game_Map::X_SUBPIXELS).round tmox = (@map.display_x / Game_Map::X_SUBPIXELS).round
tmoy = (@map.display_y / Game_Map::Y_SUBPIXELS).round tmoy = (@map.display_y / Game_Map::Y_SUBPIXELS).round
@tilemap.ox = tmox
@tilemap.oy = tmoy
@@viewport1.rect.set(0, 0, Graphics.width, Graphics.height) @@viewport1.rect.set(0, 0, Graphics.width, Graphics.height)
@@viewport1.ox = 0 @@viewport1.ox = 0
@@viewport1.oy = 0 @@viewport1.oy = 0
@@viewport1.ox += $game_screen.shake @@viewport1.ox += $game_screen.shake
@tilemap.update
@panorama.ox = tmox / 2 @panorama.ox = tmox / 2
@panorama.oy = tmoy / 2 @panorama.oy = tmoy / 2
@fog.ox = tmox + @map.fog_ox @fog.ox = tmox + @map.fog_ox
@@ -130,13 +119,13 @@ class Spriteset_Map
@fog.tone = @map.fog_tone @fog.tone = @map.fog_tone
@panorama.update @panorama.update
@fog.update @fog.update
for sprite in @character_sprites @character_sprites.each do |sprite|
sprite.update sprite.update
end end
if self.map!=$game_map if self.map == $game_map
@weather.fade_in(:None, 0, 20)
else
@weather.fade_in($game_screen.weather_type, $game_screen.weather_max, $game_screen.weather_duration) @weather.fade_in($game_screen.weather_type, $game_screen.weather_max, $game_screen.weather_duration)
else
@weather.fade_in(:None, 0, 20)
end end
@weather.ox = tmox @weather.ox = tmox
@weather.oy = tmoy @weather.oy = tmoy

View File

@@ -18,9 +18,9 @@ class AnimationSprite < RPG::Sprite
end end
def setCoords def setCoords
self.x = ((@tileX * Game_Map::REAL_RES_X - @map.display_x) / Game_Map::X_SUBPIXELS).ceil self.x = (((@tileX * Game_Map::REAL_RES_X) - @map.display_x) / Game_Map::X_SUBPIXELS).ceil
self.x += Game_Map::TILE_WIDTH / 2 self.x += Game_Map::TILE_WIDTH / 2
self.y = ((@tileY * Game_Map::REAL_RES_Y - @map.display_y) / Game_Map::Y_SUBPIXELS).ceil self.y = (((@tileY * Game_Map::REAL_RES_Y) - @map.display_y) / Game_Map::Y_SUBPIXELS).ceil
self.y += Game_Map::TILE_HEIGHT self.y += Game_Map::TILE_HEIGHT
end end
@@ -41,9 +41,9 @@ end
class Spriteset_Map class Spriteset_Map
alias _animationSprite_initialize initialize alias _animationSprite_initialize initialize unless private_method_defined?(:_animationSprite_initialize)
alias _animationSprite_update update alias _animationSprite_update update unless method_defined?(:_animationSprite_update)
alias _animationSprite_dispose dispose alias _animationSprite_dispose dispose unless method_defined?(:_animationSprite_dispose)
def initialize(map = nil) def initialize(map = nil)
@usersprites = [] @usersprites = []
@@ -51,36 +51,29 @@ class Spriteset_Map
end end
def addUserAnimation(animID, x, y, tinting = false, height = 3) def addUserAnimation(animID, x, y, tinting = false, height = 3)
sprite=AnimationSprite.new(animID,$game_map,x,y,@@viewport1,tinting,height) sprite = AnimationSprite.new(animID, self.map, x, y, @@viewport1, tinting, height)
addUserSprite(sprite) addUserSprite(sprite)
return sprite return sprite
end end
def addUserSprite(sprite) def addUserSprite(new_sprite)
for i in 0...@usersprites.length @usersprites.each_with_index do |sprite, i|
if @usersprites[i]==nil || @usersprites[i].disposed? next if sprite && !sprite.disposed?
@usersprites[i]=sprite @usersprites[i] = new_sprite
return return
end end
end @usersprites.push(new_sprite)
@usersprites.push(sprite)
end end
def dispose def dispose
_animationSprite_dispose _animationSprite_dispose
for i in 0...@usersprites.length @usersprites.each { |sprite| sprite.dispose }
@usersprites[i].dispose
end
@usersprites.clear @usersprites.clear
end end
def update def update
return if @tilemap.disposed?
pbDayNightTint(@tilemap)
@@viewport3.tone.set(0, 0, 0, 0) @@viewport3.tone.set(0, 0, 0, 0)
_animationSprite_update _animationSprite_update
for i in 0...@usersprites.length @usersprites.each { |sprite| sprite.update if !sprite.disposed? }
@usersprites[i].update if !@usersprites[i].disposed?
end
end end
end end

View File

@@ -19,7 +19,7 @@ class Sprite_Shadow < RPG::Sprite
end end
def dispose def dispose
@chbitmap.dispose if @chbitmap @chbitmap&.dispose
super super
end end
@@ -35,8 +35,8 @@ class Sprite_Shadow < RPG::Sprite
@tile_id = @character.tile_id @tile_id = @character.tile_id
@character_name = @character.character_name @character_name = @character.character_name
@character_hue = @character.character_hue @character_hue = @character.character_hue
@chbitmap&.dispose
if @tile_id >= 384 if @tile_id >= 384
@chbitmap.dispose if @chbitmap
@chbitmap = pbGetTileBitmap(@character.map.tileset_name, @chbitmap = pbGetTileBitmap(@character.map.tileset_name,
@tile_id, @character.character_hue) @tile_id, @character.character_hue)
self.src_rect.set(0, 0, 32, 32) self.src_rect.set(0, 0, 32, 32)
@@ -45,9 +45,8 @@ class Sprite_Shadow < RPG::Sprite
self.ox = 16 self.ox = 16
self.oy = 32 self.oy = 32
else else
@chbitmap.dispose if @chbitmap @chbitmap = AnimatedBitmap.new("Graphics/Characters/" + @character.character_name,
@chbitmap = AnimatedBitmap.new( @character.character_hue)
'Graphics/Characters/'+@character.character_name,@character.character_hue)
@cw = @chbitmap.width / 4 @cw = @chbitmap.width / 4
@ch = @chbitmap.height / 4 @ch = @chbitmap.height / 4
self.ox = @cw / 2 self.ox = @cw / 2
@@ -90,7 +89,7 @@ class Sprite_Shadow < RPG::Sprite
@deltay = ScreenPosHelper.pbScreenY(@source) - self.y @deltay = ScreenPosHelper.pbScreenY(@source) - self.y
self.color = Color.new(0, 0, 0) self.color = Color.new(0, 0, 0)
@distance = ((@deltax**2) + (@deltay**2)) @distance = ((@deltax**2) + (@deltay**2))
self.opacity = @self_opacity * 13000 / ((@distance * 370 / @distancemax) + 6000) self.opacity = @self_opacity * 13_000 / ((@distance * 370 / @distancemax) + 6000)
self.angle = 57.3 * Math.atan2(@deltax, @deltay) self.angle = 57.3 * Math.atan2(@deltax, @deltay)
@angle_trigo = self.angle + 90 @angle_trigo = self.angle + 90
@angle_trigo += 360 if @angle_trigo < 0 @angle_trigo += 360 if @angle_trigo < 0
@@ -124,7 +123,7 @@ end
# ? CLASS Sprite_Character edit # ? CLASS Sprite_Character edit
#=================================================== #===================================================
class Sprite_Character < RPG::Sprite class Sprite_Character < RPG::Sprite
alias :shadow_initialize :initialize alias shadow_initialize initialize unless private_method_defined?(:shadow_initialize)
def initialize(viewport, character = nil) def initialize(viewport, character = nil)
@ombrelist = [] @ombrelist = []
@@ -135,34 +134,30 @@ class Sprite_Character < RPG::Sprite
def setShadows(map, shadows) def setShadows(map, shadows)
if character.is_a?(Game_Event) && shadows.length > 0 if character.is_a?(Game_Event) && shadows.length > 0
params = XPML_read(map, "Shadow", @character, 4) params = XPML_read(map, "Shadow", @character, 4)
if params != nil if params
for i in 0...shadows.size shadows.each do |shadow|
@ombrelist.push(Sprite_Shadow.new(viewport, @character, shadows[i])) @ombrelist.push(Sprite_Shadow.new(viewport, @character, shadows))
end end
end end
end end
if character.is_a?(Game_Player) && shadows.length > 0 if character.is_a?(Game_Player) && shadows.length > 0
for i in 0...shadows.size shadows.each do |shadow|
@ombrelist.push(Sprite_Shadow.new(viewport, $game_player, shadows[i])) @ombrelist.push(Sprite_Shadow.new(viewport, $game_player, shadow))
end end
end end
update update
end end
def clearShadows def clearShadows
@ombrelist.each { |s| s.dispose if s } @ombrelist.each { |s| s&.dispose }
@ombrelist.clear @ombrelist.clear
end end
alias shadow_update update alias shadow_update update unless method_defined?(:shadow_update)
def update def update
shadow_update shadow_update
if @ombrelist.length>0 @ombrelist.each { |ombre| ombre.update }
for i in 0...@ombrelist.size
@ombrelist[i].update
end
end
end end
end end
@@ -183,24 +178,24 @@ end
class Spriteset_Map class Spriteset_Map
attr_accessor :shadows attr_accessor :shadows
alias shadow_initialize initialize alias shadow_initialize initialize unless private_method_defined?(:shadow_initialize)
def initialize(map = nil) def initialize(map = nil)
@shadows = [] @shadows = []
warn = false warn = false
map = $game_map if !map map = $game_map if !map
for k in map.events.keys.sort map.events.keys.sort.each do |k|
ev = map.events[k] ev = map.events[k]
warn = true if (ev.list != nil && ev.list.length > 0 && warn = true if ev.list && ev.list.length > 0 && ev.list[0].code == 108 &&
ev.list[0].code == 108 && (ev.list[0].parameters == ["s"] || ev.list[0].parameters == ["o"])
(ev.list[0].parameters == ["s"] || ev.list[0].parameters == ["o"]))
params = XPML_read(map, "Shadow Source", ev, 4) params = XPML_read(map, "Shadow Source", ev, 4)
@shadows.push([ev] + params) if params != nil @shadows.push([ev] + params) if params
end end
if warn == true if warn == true
p "Warning : At least one event on this map uses the obsolete way to add shadows" p "Warning : At least one event on this map uses the obsolete way to add shadows"
end end
shadow_initialize(map) shadow_initialize(map)
for sprite in @character_sprites @character_sprites.each do |sprite|
sprite.setShadows(map, @shadows) sprite.setShadows(map, @shadows)
end end
$scene.spritesetGlobal.playersprite.setShadows(map, @shadows) $scene.spritesetGlobal.playersprite.setShadows(map, @shadows)
@@ -230,29 +225,22 @@ end
#=================================================== #===================================================
def XPML_read(map, markup, event, max_param_number = 0) def XPML_read(map, markup, event, max_param_number = 0)
parameter_list = nil parameter_list = nil
return nil if !event || event.list == nil return nil if !event || event.list.nil?
for i in 0...event.list.size event.list.size.times do |i|
if event.list[i].code == 108 && next unless event.list[i].code == 108 &&
event.list[i].parameters[0].downcase == "begin " + markup.downcase event.list[i].parameters[0].downcase == "begin " + markup.downcase
parameter_list = [] if parameter_list == nil parameter_list = [] if parameter_list.nil?
for j in i+1...event.list.size ((i + 1)...event.list.size).each do |j|
if event.list[j].code == 108 return parameter_list if event.list[j].code != 108
parts = event.list[j].parameters[0].split parts = event.list[j].parameters[0].split
if parts.size != 1 && parts[0].downcase != "begin" return parameter_list if parts.size == 1 || parts[0].downcase == "begin"
if parts[1].to_i != 0 || parts[1] == "0" if parts[1].to_i != 0 || parts[1] == "0"
parameter_list.push(parts[1].to_i) parameter_list.push(parts[1].to_i)
else else
parameter_list.push(parts[1]) parameter_list.push(parts[1])
end end
else
return parameter_list
end
else
return parameter_list
end
return parameter_list if max_param_number != 0 && j == i + max_param_number return parameter_list if max_param_number != 0 && j == i + max_param_number
end end
end end
end
return parameter_list return parameter_list
end end

View File

@@ -31,7 +31,7 @@ class Particle_Engine
def dispose def dispose
return if disposed? return if disposed?
for particle in @effect @effect.each do |particle|
next if particle.nil? next if particle.nil?
particle.dispose particle.dispose
end end
@@ -57,17 +57,17 @@ class Particle_Engine
def realloc_effect(event, particle) def realloc_effect(event, particle)
type = pbEventCommentInput(event, 1, "Particle Engine Type") type = pbEventCommentInput(event, 1, "Particle Engine Type")
if type.nil? if type.nil?
particle.dispose if particle particle&.dispose
return nil return nil
end end
type = type[0].downcase type = type[0].downcase
cls = @effects[type] cls = @effects[type]
if cls.nil? if cls.nil?
particle.dispose if particle particle&.dispose
return nil return nil
end end
if !particle || !particle.is_a?(cls) if !particle || !particle.is_a?(cls)
particle.dispose if particle particle&.dispose
particle = cls.new(event, @viewport) particle = cls.new(event, @viewport)
end end
return particle return particle
@@ -80,13 +80,12 @@ class Particle_Engine
def update def update
if @firsttime if @firsttime
@firsttime = false @firsttime = false
for event in @map.events.values @map.events.each_value do |event|
remove_effect(event) remove_effect(event)
add_effect(event) add_effect(event)
end end
end end
for i in 0...@effect.length @effect.each_with_index do |particle, i|
particle = @effect[i]
next if particle.nil? next if particle.nil?
if particle.event.pe_refresh if particle.event.pe_refresh
event = particle.event event = particle.event
@@ -94,7 +93,7 @@ class Particle_Engine
particle = realloc_effect(event, particle) particle = realloc_effect(event, particle)
@effect[i] = particle @effect[i] = particle
end end
particle.update if particle particle&.update
end end
end end
end end
@@ -136,7 +135,7 @@ class ParticleSprite
end end
def dispose def dispose
@sprite.dispose if @sprite @sprite&.dispose
end end
def bitmap=(value) def bitmap=(value)
@@ -217,7 +216,7 @@ class ParticleEffect_Event < ParticleEffect
@zoffset = zOffset @zoffset = zOffset
@bmwidth = 32 @bmwidth = 32
@bmheight = 32 @bmheight = 32
for i in 0...@maxparticless @maxparticless.times do |i|
@particlex[i] = -@xoffset @particlex[i] = -@xoffset
@particley[i] = -@yoffset @particley[i] = -@yoffset
@particles[i] = ParticleSprite.new(@viewport) @particles[i] = ParticleSprite.new(@viewport)
@@ -261,9 +260,9 @@ class ParticleEffect_Event < ParticleEffect
@real_y = newRealY @real_y = newRealY
if @opacityvar > 0 && @viewport if @opacityvar > 0 && @viewport
opac = 255.0 / @opacityvar opac = 255.0 / @opacityvar
minX = opac*(-@xgravity*1.0 / @slowdown).floor + @startingx minX = (opac * (-@xgravity.to_f / @slowdown).floor) + @startingx
maxX = opac*(@xgravity*1.0 / @slowdown).floor + @startingx maxX = (opac * (@xgravity.to_f / @slowdown).floor) + @startingx
minY = opac*(-@ygravity*1.0 / @slowdown).floor + @startingy minY = (opac * (-@ygravity.to_f / @slowdown).floor) + @startingy
maxY = @startingy maxY = @startingy
minX -= @bmwidth minX -= @bmwidth
minY -= @bmheight minY -= @bmheight
@@ -275,7 +274,7 @@ class ParticleEffect_Event < ParticleEffect
end end
end end
particleZ = selfZ + @zoffset particleZ = selfZ + @zoffset
for i in 0...@maxparticless @maxparticless.times do |i|
@particles[i].z = particleZ @particles[i].z = particleZ
if @particles[i].y <= @ytop if @particles[i].y <= @ytop
@particles[i].y = @startingy + @yoffset @particles[i].y = @startingy + @yoffset
@@ -309,15 +308,13 @@ class ParticleEffect_Event < ParticleEffect
@particlex[i] = 0.0 @particlex[i] = 0.0
@particley[i] = 0.0 @particley[i] = 0.0
end end
else elsif @opacity[i] <= 0
if @opacity[i] <= 0
@opacity[i] = 250 @opacity[i] = 250
@particles[i].y = @startingy + @yoffset @particles[i].y = @startingy + @yoffset
@particles[i].x = @startingx + @xoffset @particles[i].x = @startingx + @xoffset
@particlex[i] = 0.0 @particlex[i] = 0.0
@particley[i] = 0.0 @particley[i] = 0.0
end end
end
calcParticlePos(i) calcParticlePos(i)
if @randomhue == 1 if @randomhue == 1
@hue += 0.5 @hue += 0.5
@@ -333,11 +330,11 @@ class ParticleEffect_Event < ParticleEffect
def calcParticlePos(i) def calcParticlePos(i)
@leftright = rand(2) @leftright = rand(2)
if @leftright == 1 if @leftright == 1
xo = -@xgravity*1.0 / @slowdown xo = -@xgravity.to_f / @slowdown
else else
xo = @xgravity*1.0 / @slowdown xo = @xgravity.to_f / @slowdown
end end
yo = -@ygravity*1.0 / @slowdown yo = -@ygravity.to_f / @slowdown
@particlex[i] += xo @particlex[i] += xo
@particley[i] += yo @particley[i] += yo
@particlex[i] -= @__offsetx @particlex[i] -= @__offsetx
@@ -349,10 +346,10 @@ class ParticleEffect_Event < ParticleEffect
end end
def dispose def dispose
for particle in @particles @particles.each do |particle|
particle.dispose particle.dispose
end end
for bitmap in @bitmaps.values @bitmaps.each_value do |bitmap|
bitmap.dispose bitmap.dispose
end end
@particles.clear @particles.clear
@@ -390,7 +387,7 @@ class Particle_Engine::Teleport < ParticleEffect_Event
setParameters([1, 1, 1, 10, rand(360), 1, -64, setParameters([1, 1, 1, 10, rand(360), 1, -64,
Graphics.height, -64, Graphics.width, 0, 3, -8, -15, 20, 0]) Graphics.height, -64, Graphics.width, 0, 3, -8, -15, 20, 0])
initParticles("wideportal", 250) initParticles("wideportal", 250)
for i in 0...@maxparticless @maxparticless.times do |i|
@particles[i].ox = 16 @particles[i].ox = 16
@particles[i].oy = 16 @particles[i].oy = 16
end end
@@ -449,7 +446,7 @@ class Particle_Engine::SootSmoke < ParticleEffect_Event
setParameters([0, 0, 0, 30, 0, 0.5, -64, setParameters([0, 0, 0, 30, 0, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -15, 5, 80]) Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -15, 5, 80])
initParticles("smoke", 100, 0) initParticles("smoke", 100, 0)
for i in 0...@maxparticless @maxparticless.times do |i|
@particles[i].blend_type = rand(6) < 3 ? 1 : 2 @particles[i].blend_type = rand(6) < 3 ? 1 : 2
end end
end end
@@ -474,7 +471,7 @@ class Particle_Engine::FixedTeleport < ParticleEffect_Event
setParameters([1, 0, 1, 10, rand(360), 1, setParameters([1, 0, 1, 10, rand(360), 1,
-Graphics.height, Graphics.height, 0, Graphics.width, 0, 3, -8, -15, 20, 0]) -Graphics.height, Graphics.height, 0, Graphics.width, 0, 3, -8, -15, 20, 0])
initParticles("wideportal", 250) initParticles("wideportal", 250)
for i in 0...@maxparticless @maxparticless.times do |i|
@particles[i].ox = 16 @particles[i].ox = 16
@particles[i].oy = 16 @particles[i].oy = 16
end end
@@ -490,7 +487,7 @@ class Particle_Engine::StarTeleport < ParticleEffect_Event
setParameters([0, 0, 1, 10, 0, 1, setParameters([0, 0, 1, 10, 0, 1,
-Graphics.height, Graphics.height, 0, Graphics.width, 0, 3, -8, -15, 10, 0]) -Graphics.height, Graphics.height, 0, Graphics.width, 0, 3, -8, -15, 10, 0])
initParticles("star", 250) initParticles("star", 250)
for i in 0...@maxparticless @maxparticless.times do |i|
@particles[i].ox = 48 @particles[i].ox = 48
@particles[i].oy = 48 @particles[i].oy = 48
end end
@@ -505,7 +502,7 @@ class Particle_Engine::Smokescreen < ParticleEffect_Event
setParameters([0, 0, 0, 250, 0, 0.2, -64, setParameters([0, 0, 0, 250, 0, 0.2, -64,
Graphics.height, -64, Graphics.width, 0.8, 0.8, -5, -15, 5, 80]) Graphics.height, -64, Graphics.width, 0.8, 0.8, -5, -15, 5, 80])
initParticles(nil, 100) initParticles(nil, 100)
for i in 0...@maxparticless @maxparticless.times do |i|
rnd = rand(3) rnd = rand(3)
@opacity[i] = (rnd == 0) ? 1 : 100 @opacity[i] = (rnd == 0) ? 1 : 100
filename = (rnd == 0) ? "explosionsmoke" : "smoke" filename = (rnd == 0) ? "explosionsmoke" : "smoke"
@@ -520,9 +517,9 @@ class Particle_Engine::Smokescreen < ParticleEffect_Event
end end
multiple = 1.7 multiple = 1.7
xgrav = @xgravity * multiple / @slowdown xgrav = @xgravity * multiple / @slowdown
xgrav = -xgrav if (rand(2)==1) xgrav = -xgrav if rand(2) == 1
ygrav = @ygravity * multiple / @slowdown ygrav = @ygravity * multiple / @slowdown
ygrav = -ygrav if (rand(2)==1) ygrav = -ygrav if rand(2) == 1
@particlex[i] += xgrav @particlex[i] += xgrav
@particley[i] += ygrav @particley[i] += ygrav
@particlex[i] -= @__offsetx @particlex[i] -= @__offsetx
@@ -557,7 +554,7 @@ class Particle_Engine::Splash < ParticleEffect_Event
def update def update
super super
for i in 0...@maxparticless @maxparticless.times do |i|
@particles[i].opacity = 50 @particles[i].opacity = 50
@particles[i].update @particles[i].update
end end
@@ -569,7 +566,8 @@ end
class Game_Event < Game_Character class Game_Event < Game_Character
attr_accessor :pe_refresh attr_accessor :pe_refresh
alias nf_particles_game_map_initialize initialize alias nf_particles_game_map_initialize initialize unless private_method_defined?(:nf_particles_game_map_initialize)
def initialize(map_id, event, map = nil) def initialize(map_id, event, map = nil)
@pe_refresh = false @pe_refresh = false
begin begin
@@ -579,7 +577,8 @@ class Game_Event < Game_Character
end end
end end
alias nf_particles_game_map_refresh refresh alias nf_particles_game_map_refresh refresh unless method_defined?(:nf_particles_game_map_refresh)
def refresh def refresh
nf_particles_game_map_refresh nf_particles_game_map_refresh
@pe_refresh = true @pe_refresh = true

View File

@@ -1,65 +1,69 @@
class PictureOrigin class PictureOrigin
TopLeft = 0 TOP_LEFT = 0
Center = 1 CENTER = 1
TopRight = 2 TOP_RIGHT = 2
BottomLeft = 3 BOTTOM_LEFT = 3
LowerLeft = 3 LOWER_LEFT = 3
BottomRight = 4 BOTTOM_RIGHT = 4
LowerRight = 4 LOWER_RIGHT = 4
Top = 5 TOP = 5
Bottom = 6 BOTTOM = 6
Left = 7 LEFT = 7
Right = 8 RIGHT = 8
end end
class Processes class Processes
XY = 0 XY = 0
DeltaXY = 1 DELTA_XY = 1
Z = 2 Z = 2
Curve = 3 CURVE = 3
Zoom = 4 ZOOM = 4
Angle = 5 ANGLE = 5
Tone = 6 TONE = 6
Color = 7 COLOR = 7
Hue = 8 HUE = 8
Opacity = 9 OPACITY = 9
Visible = 10 VISIBLE = 10
BlendType = 11 BLEND_TYPE = 11
SE = 12 SE = 12
Name = 13 NAME = 13
Origin = 14 ORIGIN = 14
Src = 15 SRC = 15
SrcSize = 16 SRC_SIZE = 16
CropBottom = 17 CROP_BOTTOM = 17
end end
def getCubicPoint2(src, t) def getCubicPoint2(src, t)
x0 = src[0]; y0 = src[1] x0 = src[0]
cx0 = src[2]; cy0 = src[3] y0 = src[1]
cx1 = src[4]; cy1 = src[5] cx0 = src[2]
x1 = src[6]; y1 = src[7] cy0 = src[3]
cx1 = src[4]
cy1 = src[5]
x1 = src[6]
y1 = src[7]
x1 = cx1+(x1-cx1)*t x1 = cx1 + ((x1 - cx1) * t)
x0 = x0+(cx0-x0)*t x0 = x0 + ((cx0 - x0) * t)
cx0 = cx0+(cx1-cx0)*t cx0 = cx0 + ((cx1 - cx0) * t)
cx1 = cx0+(x1-cx0)*t cx1 = cx0 + ((x1 - cx0) * t)
cx0 = x0+(cx0-x0)*t cx0 = x0 + ((cx0 - x0) * t)
cx = cx0+(cx1-cx0)*t cx = cx0 + ((cx1 - cx0) * t)
# a = x1 - 3 * cx1 + 3 * cx0 - x0 # a = x1 - 3 * cx1 + 3 * cx0 - x0
# b = 3 * (cx1 - 2 * cx0 + x0) # b = 3 * (cx1 - 2 * cx0 + x0)
# c = 3 * (cx0 - x0) # c = 3 * (cx0 - x0)
# d = x0 # d = x0
# cx = a*t*t*t + b*t*t + c*t + d # cx = a*t*t*t + b*t*t + c*t + d
y1 = cy1+(y1-cy1)*t y1 = cy1 + ((y1 - cy1) * t)
y0 = y0+(cy0-y0)*t y0 = y0 + ((cy0 - y0) * t)
cy0 = cy0+(cy1-cy0)*t cy0 = cy0 + ((cy1 - cy0) * t)
cy1 = cy0+(y1-cy0)*t cy1 = cy0 + ((y1 - cy0) * t)
cy0 = y0+(cy0-y0)*t cy0 = y0 + ((cy0 - y0) * t)
cy = cy0+(cy1-cy0)*t cy = cy0 + ((cy1 - cy0) * t)
# a = y1 - 3 * cy1 + 3 * cy0 - y0 # a = y1 - 3 * cy1 + 3 * cy0 - y0
# b = 3 * (cy1 - 2 * cy0 + y0) # b = 3 * (cy1 - 2 * cy0 + y0)
# c = 3 * (cy0 - y0) # c = 3 * (cy0 - y0)
@@ -110,16 +114,20 @@ class PictureEx
@visible = true @visible = true
@blend_type = 0 @blend_type = 0
@name = "" @name = ""
@origin = PictureOrigin::TopLeft @origin = PictureOrigin::TOP_LEFT
@src_rect = Rect.new(0, 0, -1, -1) @src_rect = Rect.new(0, 0, -1, -1)
@cropBottom = -1 @cropBottom = -1
@frameUpdates = [] @frameUpdates = []
end end
def callback(cb) def callback(cb)
if cb.is_a?(Proc); cb.call(self) case cb
elsif cb.is_a?(Array); cb[0].method(cb[1]).call(self) when Proc
elsif cb.is_a?(Method); cb.call(self) cb.call(self)
when Array
cb[0].method(cb[1]).call(self, *cb[2])
when Method
cb.call(self)
end end
end end
@@ -134,7 +142,7 @@ class PictureEx
def totalDuration def totalDuration
ret = 0 ret = 0
for process in @processes @processes.each do |process|
dur = process[1] + process[2] dur = process[1] + process[2]
ret = dur if dur > ret ret = dur if dur > ret
end end
@@ -163,7 +171,9 @@ class PictureEx
# the angle another way too. # the angle another way too.
def rotate(speed) def rotate(speed)
@rotate_speed = speed * 20.0 / Graphics.frame_rate @rotate_speed = speed * 20.0 / Graphics.frame_rate
while @rotate_speed<0; @rotate_speed += 360; end while @rotate_speed < 0
@rotate_speed += 360
end
@rotate_speed %= 360 @rotate_speed %= 360
end end
@@ -176,7 +186,7 @@ class PictureEx
end end
def adjustPosition(xOffset, yOffset) def adjustPosition(xOffset, yOffset)
for process in @processes @processes.each do |process|
next if process[0] != Processes::XY next if process[0] != Processes::XY
process[5] += xOffset process[5] += xOffset
process[6] += yOffset process[6] += yOffset
@@ -203,12 +213,12 @@ class PictureEx
def moveCurve(delay, duration, x1, y1, x2, y2, x3, y3, cb = nil) def moveCurve(delay, duration, x1, y1, x2, y2, x3, y3, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration) delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::Curve,delay,duration,0,cb,[@x,@y,x1,y1,x2,y2,x3,y3]]) @processes.push([Processes::CURVE, delay, duration, 0, cb, [@x, @y, x1, y1, x2, y2, x3, y3]])
end end
def moveDelta(delay, duration, x, y, cb = nil) def moveDelta(delay, duration, x, y, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration) delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::DeltaXY,delay,duration,0,cb,@x,@y,x,y]) @processes.push([Processes::DELTA_XY, delay, duration, 0, cb, @x, @y, x, y])
end end
def setDelta(delay, x, y, cb = nil) def setDelta(delay, x, y, cb = nil)
@@ -226,7 +236,7 @@ class PictureEx
def moveZoomXY(delay, duration, zoom_x, zoom_y, cb = nil) def moveZoomXY(delay, duration, zoom_x, zoom_y, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration) delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::Zoom,delay,duration,0,cb,@zoom_x,@zoom_y,zoom_x,zoom_y]) @processes.push([Processes::ZOOM, delay, duration, 0, cb, @zoom_x, @zoom_y, zoom_x, zoom_y])
end end
def setZoomXY(delay, zoom_x, zoom_y, cb = nil) def setZoomXY(delay, zoom_x, zoom_y, cb = nil)
@@ -243,7 +253,7 @@ class PictureEx
def moveAngle(delay, duration, angle, cb = nil) def moveAngle(delay, duration, angle, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration) delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::Angle,delay,duration,0,cb,@angle,angle]) @processes.push([Processes::ANGLE, delay, duration, 0, cb, @angle, angle])
end end
def setAngle(delay, angle, cb = nil) def setAngle(delay, angle, cb = nil)
@@ -253,7 +263,7 @@ class PictureEx
def moveTone(delay, duration, tone, cb = nil) def moveTone(delay, duration, tone, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration) delay, duration = ensureDelayAndDuration(delay, duration)
target = (tone) ? tone.clone : Tone.new(0, 0, 0, 0) target = (tone) ? tone.clone : Tone.new(0, 0, 0, 0)
@processes.push([Processes::Tone,delay,duration,0,cb,@tone.clone,target]) @processes.push([Processes::TONE, delay, duration, 0, cb, @tone.clone, target])
end end
def setTone(delay, tone, cb = nil) def setTone(delay, tone, cb = nil)
@@ -263,7 +273,7 @@ class PictureEx
def moveColor(delay, duration, color, cb = nil) def moveColor(delay, duration, color, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration) delay, duration = ensureDelayAndDuration(delay, duration)
target = (color) ? color.clone : Color.new(0, 0, 0, 0) target = (color) ? color.clone : Color.new(0, 0, 0, 0)
@processes.push([Processes::Color,delay,duration,0,cb,@color.clone,target]) @processes.push([Processes::COLOR, delay, duration, 0, cb, @color.clone, target])
end end
def setColor(delay, color, cb = nil) def setColor(delay, color, cb = nil)
@@ -273,7 +283,7 @@ class PictureEx
# Hue changes don't actually work. # Hue changes don't actually work.
def moveHue(delay, duration, hue, cb = nil) def moveHue(delay, duration, hue, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration) delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::Hue,delay,duration,0,cb,@hue,hue]) @processes.push([Processes::HUE, delay, duration, 0, cb, @hue, hue])
end end
# Hue changes don't actually work. # Hue changes don't actually work.
@@ -283,7 +293,7 @@ class PictureEx
def moveOpacity(delay, duration, opacity, cb = nil) def moveOpacity(delay, duration, opacity, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration) delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::Opacity,delay,duration,0,cb,@opacity,opacity]) @processes.push([Processes::OPACITY, delay, duration, 0, cb, @opacity, opacity])
end end
def setOpacity(delay, opacity, cb = nil) def setOpacity(delay, opacity, cb = nil)
@@ -292,13 +302,13 @@ class PictureEx
def setVisible(delay, visible, cb = nil) def setVisible(delay, visible, cb = nil)
delay = ensureDelay(delay) delay = ensureDelay(delay)
@processes.push([Processes::Visible,delay,0,0,cb,visible]) @processes.push([Processes::VISIBLE, delay, 0, 0, cb, visible])
end end
# Only values of 0 (normal), 1 (additive) and 2 (subtractive) are allowed. # Only values of 0 (normal), 1 (additive) and 2 (subtractive) are allowed.
def setBlendType(delay, blend, cb = nil) def setBlendType(delay, blend, cb = nil)
delay = ensureDelayAndDuration(delay) delay = ensureDelayAndDuration(delay)
@processes.push([Processes::BlendType,delay,0,0,cb,blend]) @processes.push([Processes::BLEND_TYPE, delay, 0, 0, cb, blend])
end end
def setSE(delay, seFile, volume = nil, pitch = nil, cb = nil) def setSE(delay, seFile, volume = nil, pitch = nil, cb = nil)
@@ -308,35 +318,34 @@ class PictureEx
def setName(delay, name, cb = nil) def setName(delay, name, cb = nil)
delay = ensureDelay(delay) delay = ensureDelay(delay)
@processes.push([Processes::Name,delay,0,0,cb,name]) @processes.push([Processes::NAME, delay, 0, 0, cb, name])
end end
def setOrigin(delay, origin, cb = nil) def setOrigin(delay, origin, cb = nil)
delay = ensureDelay(delay) delay = ensureDelay(delay)
@processes.push([Processes::Origin,delay,0,0,cb,origin]) @processes.push([Processes::ORIGIN, delay, 0, 0, cb, origin])
end end
def setSrc(delay, srcX, srcY, cb = nil) def setSrc(delay, srcX, srcY, cb = nil)
delay = ensureDelay(delay) delay = ensureDelay(delay)
@processes.push([Processes::Src,delay,0,0,cb,srcX,srcY]) @processes.push([Processes::SRC, delay, 0, 0, cb, srcX, srcY])
end end
def setSrcSize(delay, srcWidth, srcHeight, cb = nil) def setSrcSize(delay, srcWidth, srcHeight, cb = nil)
delay = ensureDelay(delay) delay = ensureDelay(delay)
@processes.push([Processes::SrcSize,delay,0,0,cb,srcWidth,srcHeight]) @processes.push([Processes::SRC_SIZE, delay, 0, 0, cb, srcWidth, srcHeight])
end end
# Used to cut Pokémon sprites off when they faint and sink into the ground. # Used to cut Pokémon sprites off when they faint and sink into the ground.
def setCropBottom(delay, y, cb = nil) def setCropBottom(delay, y, cb = nil)
delay = ensureDelay(delay) delay = ensureDelay(delay)
@processes.push([Processes::CropBottom,delay,0,0,cb,y]) @processes.push([Processes::CROP_BOTTOM, delay, 0, 0, cb, y])
end end
def update def update
procEnded = false procEnded = false
@frameUpdates.clear @frameUpdates.clear
for i in 0...@processes.length @processes.each_with_index do |process, i|
process = @processes[i]
# Decrease delay of processes that are scheduled to start later # Decrease delay of processes that are scheduled to start later
if process[1] >= 0 if process[1] >= 0
# Set initial values if the process will start this frame # Set initial values if the process will start this frame
@@ -345,28 +354,28 @@ class PictureEx
when Processes::XY when Processes::XY
process[5] = @x process[5] = @x
process[6] = @y process[6] = @y
when Processes::DeltaXY when Processes::DELTA_XY
process[5] = @x process[5] = @x
process[6] = @y process[6] = @y
process[7] += @x process[7] += @x
process[8] += @y process[8] += @y
when Processes::Curve when Processes::CURVE
process[5][0] = @x process[5][0] = @x
process[5][1] = @y process[5][1] = @y
when Processes::Z when Processes::Z
process[5] = @z process[5] = @z
when Processes::Zoom when Processes::ZOOM
process[5] = @zoom_x process[5] = @zoom_x
process[6] = @zoom_y process[6] = @zoom_y
when Processes::Angle when Processes::ANGLE
process[5] = @angle process[5] = @angle
when Processes::Tone when Processes::TONE
process[5] = @tone.clone process[5] = @tone.clone
when Processes::Color when Processes::COLOR
process[5] = @color.clone process[5] = @color.clone
when Processes::Hue when Processes::HUE
process[5] = @hue process[5] = @hue
when Processes::Opacity when Processes::OPACITY
process[5] = @opacity process[5] = @opacity
end end
end end
@@ -380,67 +389,68 @@ class PictureEx
fra = (process[2] == 0) ? 1 : process[3] # Frame counter fra = (process[2] == 0) ? 1 : process[3] # Frame counter
dur = (process[2] == 0) ? 1 : process[2] # Total duration of process dur = (process[2] == 0) ? 1 : process[2] # Total duration of process
case process[0] case process[0]
when Processes::XY, Processes::DeltaXY when Processes::XY, Processes::DELTA_XY
@x = process[5] + fra * (process[7] - process[5]) / dur @x = process[5] + (fra * (process[7] - process[5]) / dur)
@y = process[6] + fra * (process[8] - process[6]) / dur @y = process[6] + (fra * (process[8] - process[6]) / dur)
when Processes::Curve when Processes::CURVE
@x, @y = getCubicPoint2(process[5], fra.to_f / dur) @x, @y = getCubicPoint2(process[5], fra.to_f / dur)
when Processes::Z when Processes::Z
@z = process[5] + fra * (process[6] - process[5]) / dur @z = process[5] + (fra * (process[6] - process[5]) / dur)
when Processes::Zoom when Processes::ZOOM
@zoom_x = process[5] + fra * (process[7] - process[5]) / dur @zoom_x = process[5] + (fra * (process[7] - process[5]) / dur)
@zoom_y = process[6] + fra * (process[8] - process[6]) / dur @zoom_y = process[6] + (fra * (process[8] - process[6]) / dur)
when Processes::Angle when Processes::ANGLE
@angle = process[5] + fra * (process[6] - process[5]) / dur @angle = process[5] + (fra * (process[6] - process[5]) / dur)
when Processes::Tone when Processes::TONE
@tone.red = process[5].red + fra * (process[6].red - process[5].red) / dur @tone.red = process[5].red + (fra * (process[6].red - process[5].red) / dur)
@tone.green = process[5].green + fra * (process[6].green - process[5].green) / dur @tone.green = process[5].green + (fra * (process[6].green - process[5].green) / dur)
@tone.blue = process[5].blue + fra * (process[6].blue - process[5].blue) / dur @tone.blue = process[5].blue + (fra * (process[6].blue - process[5].blue) / dur)
@tone.gray = process[5].gray + fra * (process[6].gray - process[5].gray) / dur @tone.gray = process[5].gray + (fra * (process[6].gray - process[5].gray) / dur)
when Processes::Color when Processes::COLOR
@color.red = process[5].red + fra * (process[6].red - process[5].red) / dur @color.red = process[5].red + (fra * (process[6].red - process[5].red) / dur)
@color.green = process[5].green + fra * (process[6].green - process[5].green) / dur @color.green = process[5].green + (fra * (process[6].green - process[5].green) / dur)
@color.blue = process[5].blue + fra * (process[6].blue - process[5].blue) / dur @color.blue = process[5].blue + (fra * (process[6].blue - process[5].blue) / dur)
@color.alpha = process[5].alpha + fra * (process[6].alpha - process[5].alpha) / dur @color.alpha = process[5].alpha + (fra * (process[6].alpha - process[5].alpha) / dur)
when Processes::Hue when Processes::HUE
@hue = (process[6] - process[5]).to_f / dur @hue = (process[6] - process[5]).to_f / dur
when Processes::Opacity when Processes::OPACITY
@opacity = process[5] + fra * (process[6] - process[5]) / dur @opacity = process[5] + (fra * (process[6] - process[5]) / dur)
when Processes::Visible when Processes::VISIBLE
@visible = process[5] @visible = process[5]
when Processes::BlendType when Processes::BLEND_TYPE
@blend_type = process[5] @blend_type = process[5]
when Processes::SE when Processes::SE
pbSEPlay(process[5], process[6], process[7]) pbSEPlay(process[5], process[6], process[7])
when Processes::Name when Processes::NAME
@name = process[5] @name = process[5]
when Processes::Origin when Processes::ORIGIN
@origin = process[5] @origin = process[5]
when Processes::Src when Processes::SRC
@src_rect.x = process[5] @src_rect.x = process[5]
@src_rect.y = process[6] @src_rect.y = process[6]
when Processes::SrcSize when Processes::SRC_SIZE
@src_rect.width = process[5] @src_rect.width = process[5]
@src_rect.height = process[6] @src_rect.height = process[6]
when Processes::CropBottom when Processes::CROP_BOTTOM
@cropBottom = process[5] @cropBottom = process[5]
end end
# Increase frame counter # Increase frame counter
process[3] += 1 process[3] += 1
if process[3]>process[2] next if process[3] <= process[2]
# Process has ended, erase it # Process has ended, erase it
callback(process[4]) if process[4] callback(process[4]) if process[4]
@processes[i] = nil @processes[i] = nil
procEnded = true procEnded = true
end end
end
# Clear out empty spaces in @processes array caused by finished processes # Clear out empty spaces in @processes array caused by finished processes
@processes.compact! if procEnded @processes.compact! if procEnded
# Add the constant rotation speed # Add the constant rotation speed
if @rotate_speed != 0 if @rotate_speed != 0
@frameUpdates.push(Processes::Angle) if !@frameUpdates.include?(Processes::Angle) @frameUpdates.push(Processes::ANGLE) if !@frameUpdates.include?(Processes::ANGLE)
@angle += @rotate_speed @angle += @rotate_speed
while @angle<0; @angle += 360; end while @angle < 0
@angle += 360
end
@angle %= 360 @angle %= 360
end end
end end
@@ -453,54 +463,54 @@ end
#=============================================================================== #===============================================================================
def setPictureSprite(sprite, picture, iconSprite = false) def setPictureSprite(sprite, picture, iconSprite = false)
return if picture.frameUpdates.length == 0 return if picture.frameUpdates.length == 0
for i in 0...picture.frameUpdates.length picture.frameUpdates.each do |type|
case picture.frameUpdates[i] case type
when Processes::XY, Processes::DeltaXY when Processes::XY, Processes::DELTA_XY
sprite.x = picture.x.round sprite.x = picture.x.round
sprite.y = picture.y.round sprite.y = picture.y.round
when Processes::Z when Processes::Z
sprite.z = picture.z sprite.z = picture.z
when Processes::Zoom when Processes::ZOOM
sprite.zoom_x = picture.zoom_x / 100.0 sprite.zoom_x = picture.zoom_x / 100.0
sprite.zoom_y = picture.zoom_y / 100.0 sprite.zoom_y = picture.zoom_y / 100.0
when Processes::Angle when Processes::ANGLE
sprite.angle = picture.angle sprite.angle = picture.angle
when Processes::Tone when Processes::TONE
sprite.tone = picture.tone sprite.tone = picture.tone
when Processes::Color when Processes::COLOR
sprite.color = picture.color sprite.color = picture.color
when Processes::Hue when Processes::HUE
# This doesn't do anything. # This doesn't do anything.
when Processes::BlendType when Processes::BLEND_TYPE
sprite.blend_type = picture.blend_type sprite.blend_type = picture.blend_type
when Processes::Opacity when Processes::OPACITY
sprite.opacity = picture.opacity sprite.opacity = picture.opacity
when Processes::Visible when Processes::VISIBLE
sprite.visible = picture.visible sprite.visible = picture.visible
when Processes::Name when Processes::NAME
sprite.name = picture.name if iconSprite && sprite.name != picture.name sprite.name = picture.name if iconSprite && sprite.name != picture.name
when Processes::Origin when Processes::ORIGIN
case picture.origin case picture.origin
when PictureOrigin::TopLeft, PictureOrigin::Left, PictureOrigin::BottomLeft when PictureOrigin::TOP_LEFT, PictureOrigin::LEFT, PictureOrigin::BOTTOM_LEFT
sprite.ox = 0 sprite.ox = 0
when PictureOrigin::Top, PictureOrigin::Center, PictureOrigin::Bottom when PictureOrigin::TOP, PictureOrigin::CENTER, PictureOrigin::BOTTOM
sprite.ox = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.width / 2 : 0 sprite.ox = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.width / 2 : 0
when PictureOrigin::TopRight, PictureOrigin::Right, PictureOrigin::BottomRight when PictureOrigin::TOP_RIGHT, PictureOrigin::RIGHT, PictureOrigin::BOTTOM_RIGHT
sprite.ox = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.width : 0 sprite.ox = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.width : 0
end end
case picture.origin case picture.origin
when PictureOrigin::TopLeft, PictureOrigin::Top, PictureOrigin::TopRight when PictureOrigin::TOP_LEFT, PictureOrigin::TOP, PictureOrigin::TOP_RIGHT
sprite.oy = 0 sprite.oy = 0
when PictureOrigin::Left, PictureOrigin::Center, PictureOrigin::Right when PictureOrigin::LEFT, PictureOrigin::CENTER, PictureOrigin::RIGHT
sprite.oy = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.height / 2 : 0 sprite.oy = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.height / 2 : 0
when PictureOrigin::BottomLeft, PictureOrigin::Bottom, PictureOrigin::BottomRight when PictureOrigin::BOTTOM_LEFT, PictureOrigin::BOTTOM, PictureOrigin::BOTTOM_RIGHT
sprite.oy = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.height : 0 sprite.oy = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.height : 0
end end
when Processes::Src when Processes::SRC
next unless iconSprite && sprite.src_rect next unless iconSprite && sprite.src_rect
sprite.src_rect.x = picture.src_rect.x sprite.src_rect.x = picture.src_rect.x
sprite.src_rect.y = picture.src_rect.y sprite.src_rect.y = picture.src_rect.y
when Processes::SrcSize when Processes::SRC_SIZE
next unless iconSprite && sprite.src_rect next unless iconSprite && sprite.src_rect
sprite.src_rect.width = picture.src_rect.width sprite.src_rect.width = picture.src_rect.width
sprite.src_rect.height = picture.src_rect.height sprite.src_rect.height = picture.src_rect.height

View File

@@ -25,7 +25,7 @@ class Interpolator
@frames = frames @frames = frames
@step = 0 @step = 0
@sprite = sprite @sprite = sprite
for item in items items.each do |item|
case item[0] case item[0]
when ZOOM_X when ZOOM_X
@tweensteps[item[0]] = [sprite.zoom_x, item[1] - sprite.zoom_x] @tweensteps[item[0]] = [sprite.zoom_x, item[1] - sprite.zoom_x]
@@ -38,12 +38,11 @@ class Interpolator
when OPACITY when OPACITY
@tweensteps[item[0]] = [sprite.opacity, item[1] - sprite.opacity] @tweensteps[item[0]] = [sprite.opacity, item[1] - sprite.opacity]
when COLOR when COLOR
@tweensteps[item[0]] = [sprite.color.clone,Color.new( @tweensteps[item[0]] = [sprite.color.clone,
item[1].red-sprite.color.red, Color.new(item[1].red - sprite.color.red,
item[1].green - sprite.color.green, item[1].green - sprite.color.green,
item[1].blue - sprite.color.blue, item[1].blue - sprite.color.blue,
item[1].alpha-sprite.color.alpha item[1].alpha - sprite.color.alpha)]
)]
end end
end end
@tweening = true @tweening = true
@@ -52,28 +51,26 @@ class Interpolator
def update def update
if @tweening if @tweening
t = (@step*1.0)/@frames t = @step.to_f / @frames
for i in 0...@tweensteps.length @tweensteps.length.times do |i|
item = @tweensteps[i] item = @tweensteps[i]
next if !item next if !item
case i case i
when ZOOM_X when ZOOM_X
@sprite.zoom_x = item[0]+item[1]*t @sprite.zoom_x = item[0] + (item[1] * t)
when ZOOM_Y when ZOOM_Y
@sprite.zoom_y = item[0]+item[1]*t @sprite.zoom_y = item[0] + (item[1] * t)
when X when X
@sprite.x = item[0]+item[1]*t @sprite.x = item[0] + (item[1] * t)
when Y when Y
@sprite.y = item[0]+item[1]*t @sprite.y = item[0] + (item[1] * t)
when OPACITY when OPACITY
@sprite.opacity = item[0]+item[1]*t @sprite.opacity = item[0] + (item[1] * t)
when COLOR when COLOR
@sprite.color = Color.new( @sprite.color = Color.new(item[0].red + (item[1].red * t),
item[0].red+item[1].red*t, item[0].green + (item[1].green * t),
item[0].green+item[1].green*t, item[0].blue + (item[1].blue * t),
item[0].blue+item[1].blue*t, item[0].alpha + (item[1].alpha * t))
item[0].alpha+item[1].alpha*t
)
end end
end end
@step += 1 @step += 1
@@ -111,19 +108,19 @@ class RectInterpolator
def update def update
return if done? return if done?
t = (@curframe*1.0/@frames) t = @curframe.to_f / @frames
x1 = @oldrect.x x1 = @oldrect.x
x2 = @newrect.x x2 = @newrect.x
x = x1+t*(x2-x1) x = x1 + (t * (x2 - x1))
y1 = @oldrect.y y1 = @oldrect.y
y2 = @newrect.y y2 = @newrect.y
y = y1+t*(y2-y1) y = y1 + (t * (y2 - y1))
rx1 = @oldrect.x + @oldrect.width rx1 = @oldrect.x + @oldrect.width
rx2 = @newrect.x + @newrect.width rx2 = @newrect.x + @newrect.width
rx = rx1+t*(rx2-rx1) rx = rx1 + (t * (rx2 - rx1))
ry1 = @oldrect.y + @oldrect.height ry1 = @oldrect.y + @oldrect.height
ry2 = @newrect.y + @newrect.height ry2 = @newrect.y + @newrect.height
ry = ry1+t*(ry2-ry1) ry = ry1 + (t * (ry2 - ry1))
minx = x < rx ? x : rx minx = x < rx ? x : rx
maxx = x > rx ? x : rx maxx = x > rx ? x : rx
miny = y < ry ? y : ry miny = y < ry ? y : ry
@@ -160,13 +157,13 @@ class PointInterpolator
def update def update
return if done? return if done?
t = (@curframe*1.0/@frames) t = @curframe.to_f / @frames
rx1 = @oldx rx1 = @oldx
rx2 = @newx rx2 = @newx
@x = rx1+t*(rx2-rx1) @x = rx1 + (t * (rx2 - rx1))
ry1 = @oldy ry1 = @oldy
ry2 = @newy ry2 = @newy
@y = ry1+t*(ry2-ry1) @y = ry1 + (t * (ry2 - ry1))
@curframe += 1 @curframe += 1
end end
end end

View File

@@ -29,7 +29,7 @@ module ScreenPosHelper
end end
def self.pbScreenZ(ch, height = nil) def self.pbScreenZ(ch, height = nil)
if height==nil if height.nil?
height = 0 height = 0
if ch.tile_id > 0 if ch.tile_id > 0
height = 32 height = 32

View File

@@ -1,59 +0,0 @@
class TilemapLoader
def initialize(viewport)
@viewport = viewport
@tilemap = nil
@color = Color.new(0,0,0,0)
@tone = Tone.new(0,0,0,0)
updateClass
end
def updateClass
setClass(CustomTilemap)
end
def setClass(cls)
newtilemap = cls.new(@viewport)
if @tilemap
newtilemap.tileset = @tilemap.tileset
newtilemap.map_data = @tilemap.map_data
newtilemap.flash_data = @tilemap.flash_data
newtilemap.priorities = @tilemap.priorities
newtilemap.terrain_tags = @tilemap.terrain_tags
newtilemap.visible = @tilemap.visible
newtilemap.ox = @tilemap.ox
newtilemap.oy = @tilemap.oy
for i in 0...7
newtilemap.autotiles[i] = @tilemap.autotiles[i]
end
@tilemap.dispose
@tilemap = newtilemap
newtilemap.update
else
@tilemap = newtilemap
end
end
def dispose; @tilemap.dispose; end
def disposed?; @tilemap && @tilemap.disposed?; end
def update; @tilemap.update; end
def viewport; @tilemap.viewport; end
def autotiles; @tilemap.autotiles; end
def tileset; @tilemap.tileset; end
def tileset=(v); @tilemap.tileset = v; end
def map_data; @tilemap.map_data; end
def map_data=(v); @tilemap.map_data = v; end
def flash_data; @tilemap.flash_data; end
def flash_data=(v); @tilemap.flash_data = v; end
def priorities; @tilemap.priorities; end
def priorities=(v); @tilemap.priorities = v; end
def terrain_tags; (@tilemap.terrain_tags rescue nil); end
def terrain_tags=(v); (@tilemap.terrain_tags = v rescue nil); end
def visible; @tilemap.visible; end
def visible=(v); @tilemap.visible = v; end
def tone; (@tilemap.tone rescue @tone); end
def tone=(value); (@tilemap.tone = value rescue nil); end
def ox; @tilemap.ox; end
def ox=(v); @tilemap.ox = v; end
def oy; @tilemap.oy; end
def oy=(v); @tilemap.oy = v; end
end

View File

@@ -0,0 +1,609 @@
#===============================================================================
#
#===============================================================================
class TilemapRenderer
attr_reader :tilesets
attr_reader :autotiles
attr_accessor :tone
attr_accessor :color
attr_reader :viewport
attr_accessor :ox # Does nothing
attr_accessor :oy # Does nothing
attr_accessor :visible # Does nothing
DISPLAY_TILE_WIDTH = Game_Map::TILE_WIDTH rescue 32
DISPLAY_TILE_HEIGHT = Game_Map::TILE_HEIGHT rescue 32
SOURCE_TILE_WIDTH = 32
SOURCE_TILE_HEIGHT = 32
TILESET_TILES_PER_ROW = 8
AUTOTILES_COUNT = 8 # Counting the blank tile as an autotile
TILES_PER_AUTOTILE = 48
TILESET_START_ID = AUTOTILES_COUNT * TILES_PER_AUTOTILE
# If an autotile's filename ends with "[x]", its frame duration will be x/20
# seconds instead.
AUTOTILE_FRAME_DURATION = 5 # In 1/20ths of a second
# Filenames of extra autotiles for each tileset. Each tileset's entry is an
# array containing two other arrays (you can leave either of those empty, but
# they must be defined):
# - The first sub-array is for large autotiles, i.e. ones with 48 different
# tile layouts. For example, "Brick path" and "Sea".
# - The second is for single tile autotiles. For example, "Flowers1" and
# "Waterfall"
# Ihe top tiles of the tileset will instead use these autotiles. Large
# autotiles come first, in the same 8x6 layout as you see when you double-
# click on a real autotile in RMXP. After that are the single tile autotiles.
# Extra autotiles are only useful if the tiles are animated, because otherwise
# you just have some tiles which belong in the tileset instead.
EXTRA_AUTOTILES = {
# Examples:
# 1 => [["Sand shore"], ["Flowers2"]],
# 2 => [[], ["Flowers2", "Waterfall", "Waterfall crest", "Waterfall bottom"]],
# 6 => [["Water rock", "Sea deep"], []]
}
#=============================================================================
#
#=============================================================================
class TilesetBitmaps
attr_accessor :changed
attr_accessor :bitmaps
def initialize
@bitmaps = {}
@bitmap_wraps = {} # Whether each tileset is a mega texture and has multiple columns
@load_counts = {}
@bridge = 0
@changed = true
end
def [](filename)
return @bitmaps[filename]
end
def []=(filename, bitmap)
return if nil_or_empty?(filename)
@bitmaps[filename] = bitmap
@bitmap_wraps[filename] = false
@changed = true
end
def add(filename)
return if nil_or_empty?(filename)
if @bitmaps[filename]
@load_counts[filename] += 1
return
end
bitmap = pbGetTileset(filename)
@bitmap_wraps[filename] = false
if bitmap.mega?
self[filename] = TilemapRenderer::TilesetWrapper.wrapTileset(bitmap)
@bitmap_wraps[filename] = true
bitmap.dispose
else
self[filename] = bitmap
end
@load_counts[filename] = 1
end
def remove(filename)
return if nil_or_empty?(filename) || !@bitmaps[filename]
if @load_counts[filename] > 1
@load_counts[filename] -= 1
return
end
@bitmaps[filename].dispose
@bitmaps.delete(filename)
@bitmap_wraps.delete(filename)
@load_counts.delete(filename)
end
def set_src_rect(tile, tile_id)
return if nil_or_empty?(tile.filename)
return if !@bitmaps[tile.filename]
tile.src_rect.x = ((tile_id - TILESET_START_ID) % TILESET_TILES_PER_ROW) * SOURCE_TILE_WIDTH
tile.src_rect.y = ((tile_id - TILESET_START_ID) / TILESET_TILES_PER_ROW) * SOURCE_TILE_HEIGHT
if @bitmap_wraps[tile.filename]
height = @bitmaps[tile.filename].height
col = (tile_id - TILESET_START_ID) * SOURCE_TILE_HEIGHT / (TILESET_TILES_PER_ROW * height)
tile.src_rect.x += col * TILESET_TILES_PER_ROW * SOURCE_TILE_WIDTH
tile.src_rect.y -= col * height
end
end
def update; end
end
#=============================================================================
#
#=============================================================================
class AutotileBitmaps < TilesetBitmaps
attr_reader :current_frames
def initialize
super
@frame_counts = {} # Number of frames in each autotile
@frame_durations = {} # How long each frame lasts per autotile
@current_frames = {} # Which frame each autotile is currently showing
@timer = 0.0
end
def []=(filename, value)
super
return if nil_or_empty?(filename)
frame_count(filename, true)
set_current_frame(filename)
end
def add(filename)
return if nil_or_empty?(filename)
if @bitmaps[filename]
@load_counts[filename] += 1
return
end
orig_bitmap = pbGetAutotile(filename)
@bitmap_wraps[filename] = false
duration = AUTOTILE_FRAME_DURATION
if filename[/\[\s*(\d+?)\s*\]\s*$/]
duration = $~[1].to_i
end
@frame_durations[filename] = duration.to_f / 20
bitmap = AutotileExpander.expand(orig_bitmap)
self[filename] = bitmap
if bitmap.height > SOURCE_TILE_HEIGHT && bitmap.height < TILES_PER_AUTOTILE * SOURCE_TILE_HEIGHT
@bitmap_wraps[filename] = true
end
orig_bitmap.dispose if orig_bitmap != bitmap
@load_counts[filename] = 1
end
def remove(filename)
super
return if @load_counts[filename] && @load_counts[filename] > 0
@frame_counts.delete(filename)
@current_frames.delete(filename)
@frame_durations.delete(filename)
end
def frame_count(filename, force_recalc = false)
if !@frame_counts[filename] || force_recalc
return 0 if !@bitmaps[filename]
bitmap = @bitmaps[filename]
@frame_counts[filename] = [bitmap.width / SOURCE_TILE_WIDTH, 1].max
if bitmap.height > SOURCE_TILE_HEIGHT && @bitmap_wraps[filename]
@frame_counts[filename] /= 2
end
end
return @frame_counts[filename]
end
def animated?(filename)
return frame_count(filename) > 1
end
def current_frame(filename)
if !@current_frames[filename]
set_current_frame(filename)
end
return @current_frames[filename]
end
def set_current_frame(filename)
frames = frame_count(filename)
if frames < 2
@current_frames[filename] = 0
else
@current_frames[filename] = (@timer / @frame_durations[filename]).floor % frames
end
end
def set_src_rect(tile, tile_id)
return if nil_or_empty?(tile.filename)
return if !@bitmaps[tile.filename]
frame = current_frame(tile.filename)
if @bitmaps[tile.filename].height == SOURCE_TILE_HEIGHT
tile.src_rect.x = frame * SOURCE_TILE_WIDTH
tile.src_rect.y = 0
return
end
wraps = @bitmap_wraps[tile.filename]
high_id = ((tile_id % TILES_PER_AUTOTILE) >= TILES_PER_AUTOTILE / 2)
tile.src_rect.x = 0
tile.src_rect.y = (tile_id % TILES_PER_AUTOTILE) * SOURCE_TILE_HEIGHT
if wraps && high_id
tile.src_rect.x = SOURCE_TILE_WIDTH
tile.src_rect.y -= SOURCE_TILE_HEIGHT * TILES_PER_AUTOTILE / 2
end
tile.src_rect.x += frame * SOURCE_TILE_WIDTH * (wraps ? 2 : 1)
end
def update
super
@timer += Graphics.delta_s
# Update the current frame for each autotile
@bitmaps.each_key do |filename|
next if !@bitmaps[filename] || @bitmaps[filename].disposed?
old_frame = @current_frames[filename]
set_current_frame(filename)
@changed = true if @current_frames[filename] != old_frame
end
end
end
#=============================================================================
#
#=============================================================================
class TileSprite < Sprite
attr_accessor :filename
attr_accessor :tile_id
attr_accessor :is_autotile
attr_accessor :animated
attr_accessor :priority
attr_accessor :shows_reflection
attr_accessor :bridge
attr_accessor :need_refresh
def set_bitmap(filename, tile_id, autotile, animated, priority, bitmap)
self.bitmap = bitmap
self.src_rect = Rect.new(0, 0, DISPLAY_TILE_WIDTH, DISPLAY_TILE_HEIGHT)
@filename = filename
@tile_id = tile_id
@is_autotile = autotile
@animated = animated
@priority = priority
@shows_reflection = false
@bridge = false
self.visible = !bitmap.nil?
@need_refresh = true
end
end
#=============================================================================
#
#=============================================================================
def initialize(viewport)
@tilesets = TilesetBitmaps.new
@autotiles = AutotileBitmaps.new
@tiles_horizontal_count = (Graphics.width.to_f / DISPLAY_TILE_WIDTH).ceil + 1
@tiles_vertical_count = (Graphics.height.to_f / DISPLAY_TILE_HEIGHT).ceil + 1
@tone = Tone.new(0, 0, 0, 0)
@old_tone = Tone.new(0, 0, 0, 0)
@color = Color.new(0, 0, 0, 0)
@old_color = Color.new(0, 0, 0, 0)
@self_viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport = (viewport) ? viewport : @self_viewport
@old_viewport_ox = 0
@old_viewport_oy = 0
# NOTE: The extra tiles horizontally/vertically hang off the left and top
# edges of the screen, because the pixel_offset values are positive
# and are added to the tile sprite coordinates.
@tiles = []
@tiles_horizontal_count.times do |i|
@tiles[i] = []
@tiles_vertical_count.times do |j|
@tiles[i][j] = Array.new(3) { TileSprite.new(@viewport) }
end
end
@current_map_id = 0
@tile_offset_x = 0
@tile_offset_y = 0
@pixel_offset_x = 0
@pixel_offset_y = 0
@ox = 0
@oy = 0
@visible = true
@disposed = false
end
def dispose
return if disposed?
@tiles.each do |col|
col.each do |coord|
coord.each { |tile| tile.dispose }
end
end
@tilesets.bitmaps.each_value { |bitmap| bitmap.dispose }
@autotiles.bitmaps.each_value { |bitmap| bitmap.dispose }
@self_viewport.dispose
@self_viewport = nil
@disposed = true
end
def disposed?
return @disposed
end
#=============================================================================
def add_tileset(filename)
@tilesets.add(filename)
end
def remove_tileset(filename)
@tilesets.remove(filename)
end
def add_autotile(filename)
@autotiles.add(filename)
end
def remove_autotile(filename)
@autotiles.remove(filename)
end
def add_extra_autotiles(tileset_id)
return if !EXTRA_AUTOTILES[tileset_id]
EXTRA_AUTOTILES[tileset_id].each do |arr|
arr.each { |filename| add_autotile(filename) }
end
end
def remove_extra_autotiles(tileset_id)
return if !EXTRA_AUTOTILES[tileset_id]
EXTRA_AUTOTILES[tileset_id].each do |arr|
arr.each { |filename| remove_autotile(filename) }
end
end
#=============================================================================
def refresh; end
def refresh_tile_bitmap(tile, map, tile_id)
tile.tile_id = tile_id
if tile_id < TILES_PER_AUTOTILE
tile.set_bitmap("", tile_id, false, false, 0, nil)
tile.shows_reflection = false
tile.bridge = false
else
terrain_tag = map.terrain_tags[tile_id] || 0
terrain_tag_data = GameData::TerrainTag.try_get(terrain_tag)
priority = map.priorities[tile_id] || 0
single_autotile_start_id = TILESET_START_ID
true_tileset_start_id = TILESET_START_ID
extra_autotile_arrays = EXTRA_AUTOTILES[map.tileset_id]
if extra_autotile_arrays
large_autotile_count = extra_autotile_arrays[0].length
single_autotile_count = extra_autotile_arrays[1].length
single_autotile_start_id += large_autotile_count * TILES_PER_AUTOTILE
true_tileset_start_id += large_autotile_count * TILES_PER_AUTOTILE
true_tileset_start_id += single_autotile_count
end
if tile_id < true_tileset_start_id
filename = ""
if tile_id < TILESET_START_ID # Real autotiles
filename = map.autotile_names[(tile_id / TILES_PER_AUTOTILE) - 1]
elsif tile_id < single_autotile_start_id # Large extra autotiles
filename = extra_autotile_arrays[0][(tile_id - TILESET_START_ID) / TILES_PER_AUTOTILE]
else # Single extra autotiles
filename = extra_autotile_arrays[1][tile_id - single_autotile_start_id]
end
tile.set_bitmap(filename, tile_id, true, @autotiles.animated?(filename),
priority, @autotiles[filename])
else
filename = map.tileset_name
tile.set_bitmap(filename, tile_id, false, false, priority, @tilesets[filename])
end
tile.shows_reflection = terrain_tag_data&.shows_reflections
tile.bridge = terrain_tag_data&.bridge
end
refresh_tile_src_rect(tile, tile_id)
end
def refresh_tile_src_rect(tile, tile_id)
if tile.is_autotile
@autotiles.set_src_rect(tile, tile_id)
else
@tilesets.set_src_rect(tile, tile_id)
end
end
# For animated autotiles only
def refresh_tile_frame(tile, tile_id)
return if !tile.animated
@autotiles.set_src_rect(tile, tile_id)
end
# x and y are the positions of tile within @tiles, not a map x/y
def refresh_tile_coordinates(tile, x, y)
tile.x = (x * DISPLAY_TILE_WIDTH) - @pixel_offset_x
tile.y = (y * DISPLAY_TILE_HEIGHT) - @pixel_offset_y
end
def refresh_tile_z(tile, map, y, layer, tile_id)
if tile.shows_reflection
tile.z = -100
elsif tile.bridge && $PokemonGlobal.bridge > 0
tile.z = 0
else
priority = tile.priority
tile.z = (priority == 0) ? 0 : (y * DISPLAY_TILE_HEIGHT) + (priority * 32) + 32
end
end
def refresh_tile(tile, x, y, map, layer, tile_id)
refresh_tile_bitmap(tile, map, tile_id)
refresh_tile_coordinates(tile, x, y)
refresh_tile_z(tile, map, y, layer, tile_id)
tile.need_refresh = false
end
#=============================================================================
def check_if_screen_moved
ret = false
# Check for map change
if @current_map_id != $game_map.map_id
if MapFactoryHelper.hasConnections?(@current_map_id)
offsets = $map_factory.getRelativePos(@current_map_id, 0, 0, $game_map.map_id, 0, 0)
if offsets
@tile_offset_x -= offsets[0]
@tile_offset_y -= offsets[1]
else
ret = true # Need a full refresh
end
else
ret = true
end
@current_map_id = $game_map.map_id
end
# Check for tile movement
current_map_display_x = ($game_map.display_x.to_f / Game_Map::X_SUBPIXELS).round
current_map_display_y = ($game_map.display_y.to_f / Game_Map::Y_SUBPIXELS).round
new_tile_offset_x = current_map_display_x / DISPLAY_TILE_WIDTH
new_tile_offset_y = current_map_display_y / DISPLAY_TILE_HEIGHT
if new_tile_offset_x != @tile_offset_x
if new_tile_offset_x > @tile_offset_x
# Take tile stacks off the right and insert them at the beginning (left)
(new_tile_offset_x - @tile_offset_x).times do
c = @tiles.shift
@tiles.push(c)
c.each do |coord|
coord.each { |tile| tile.need_refresh = true }
end
end
else
# Take tile stacks off the beginning (left) and push them onto the end (right)
(@tile_offset_x - new_tile_offset_x).times do
c = @tiles.pop
@tiles.prepend(c)
c.each do |coord|
coord.each { |tile| tile.need_refresh = true }
end
end
end
@screen_moved = true
@tile_offset_x = new_tile_offset_x
end
if new_tile_offset_y != @tile_offset_y
if new_tile_offset_y > @tile_offset_y
# Take tile stacks off the bottom and insert them at the beginning (top)
@tiles.each do |col|
(new_tile_offset_y - @tile_offset_y).times do
c = col.shift
col.push(c)
c.each { |tile| tile.need_refresh = true }
end
end
else
# Take tile stacks off the beginning (top) and push them onto the end (bottom)
@tiles.each do |col|
(@tile_offset_y - new_tile_offset_y).times do
c = col.pop
col.prepend(c)
c.each { |tile| tile.need_refresh = true }
end
end
end
@screen_moved = true
@screen_moved_vertically = true
@tile_offset_y = new_tile_offset_y
end
# Check for pixel movement
new_pixel_offset_x = current_map_display_x % SOURCE_TILE_WIDTH
new_pixel_offset_y = current_map_display_y % SOURCE_TILE_HEIGHT
if new_pixel_offset_x != @pixel_offset_x
@screen_moved = true
@pixel_offset_x = new_pixel_offset_x
end
if new_pixel_offset_y != @pixel_offset_y
@screen_moved = true
@screen_moved_vertically = true
@pixel_offset_y = new_pixel_offset_y
end
return ret
end
#=============================================================================
def update
# Update tone
if @old_tone != @tone
@tiles.each do |col|
col.each do |coord|
coord.each { |tile| tile.tone = @tone }
end
end
@old_tone = @tone.clone
end
# Update color
if @old_color != @color
@tiles.each do |col|
col.each do |coord|
coord.each { |tile| tile.color = @tone }
end
end
@old_color = @color.clone
end
# Recalculate autotile frames
@tilesets.update
@autotiles.update
do_full_refresh = false
if @viewport.ox != @old_viewport_ox || @viewport.oy != @old_viewport_oy
@old_viewport_ox = @viewport.ox
@old_viewport_oy = @viewport.oy
do_full_refresh = true
end
# Check whether the screen has moved since the last update
@screen_moved = false
@screen_moved_vertically = false
if $PokemonGlobal.bridge != @bridge
@bridge = $PokemonGlobal.bridge
@screen_moved_vertically = true # To update bridge tiles' z values
end
do_full_refresh = true if check_if_screen_moved
# Update all tile sprites
visited = []
@tiles_horizontal_count.times do |i|
visited[i] = []
@tiles_vertical_count.times { |j| visited[i][j] = false }
end
$map_factory.maps.each do |map|
# Calculate x/y ranges of tile sprites that represent them
map_display_x = (map.display_x.to_f / Game_Map::X_SUBPIXELS).round
map_display_y = (map.display_y.to_f / Game_Map::Y_SUBPIXELS).round
map_display_x_tile = map_display_x / DISPLAY_TILE_WIDTH
map_display_y_tile = map_display_y / DISPLAY_TILE_HEIGHT
start_x = [-map_display_x_tile, 0].max
start_y = [-map_display_y_tile, 0].max
end_x = @tiles_horizontal_count - 1
end_x = [end_x, map.width - map_display_x_tile - 1].min
end_y = @tiles_vertical_count - 1
end_y = [end_y, map.height - map_display_y_tile - 1].min
next if start_x > end_x || start_y > end_y || end_x < 0 || end_y < 0
# Update all tile sprites representing this map
(start_x..end_x).each do |i|
tile_x = i + map_display_x_tile
(start_y..end_y).each do |j|
tile_y = j + map_display_y_tile
@tiles[i][j].each_with_index do |tile, layer|
tile_id = map.data[tile_x, tile_y, layer]
if do_full_refresh || tile.need_refresh || tile.tile_id != tile_id
refresh_tile(tile, i, j, map, layer, tile_id)
else
refresh_tile_frame(tile, tile_id) if tile.animated && @autotiles.changed
# Update tile's x/y coordinates
refresh_tile_coordinates(tile, i, j) if @screen_moved
# Update tile's z value
refresh_tile_z(tile, map, j, layer, tile_id) if @screen_moved_vertically
end
end
# Record x/y as visited
visited[i][j] = true
end
end
end
# Clear all unvisited tile sprites
@tiles.each_with_index do |col, i|
col.each_with_index do |coord, j|
next if visited[i][j]
coord.each do |tile|
tile.set_bitmap("", 0, false, false, 0, nil)
tile.shows_reflection = false
tile.bridge = false
end
end
end
@autotiles.changed = false
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,96 @@
#=======================================================================
# This module is a little fix that works around PC hardware limitations.
# Since Essentials isn't working with software rendering anymore, it now
# has to deal with the limits of the GPU. For the most part this is no
# big deal, but people do have some really big tilesets.
#
# The fix is simple enough: If your tileset is too big, a new
# bitmap will be constructed with all the excess pixels sent to the
# image's right side. This basically means that you now have a limit
# far higher than you should ever actually need.
#
# Hardware limit -> max tileset length:
# 1024px -> 4096px
# 2048px -> 16384px (enough to get the normal limit)
# 4096px -> 65536px (enough to load pretty much any tileset)
# 8192px -> 262144px
# 16384px -> 1048576px (what most people have at this point)
# ~Roza/Zoroark
#=======================================================================
class TilemapRenderer
module TilesetWrapper
TILESET_WIDTH = SOURCE_TILE_WIDTH * TILESET_TILES_PER_ROW
# Looks useless, but covers weird numbers given to mkxp.json or a funky driver
MAX_TEX_SIZE = (Bitmap.max_size / 1024) * 1024
MAX_TEX_SIZE_BOOSTED = (MAX_TEX_SIZE**2) / TILESET_WIDTH
module_function
def wrapTileset(originalbmp)
width = originalbmp.width
height = originalbmp.height
if width == TILESET_WIDTH && originalbmp.mega?
columns = (height / MAX_TEX_SIZE.to_f).ceil
if columns * TILESET_WIDTH > MAX_TEX_SIZE
raise "Tileset is too long!\n\nSIZE: #{originalbmp.height}px\nHARDWARE LIMIT: #{MAX_TEX_SIZE}px\nBOOSTED LIMIT: #{MAX_TEX_SIZE_BOOSTED}px"
end
bmp = Bitmap.new(TILESET_WIDTH * columns, MAX_TEX_SIZE)
remainder = height % MAX_TEX_SIZE
columns.times do |col|
srcrect = Rect.new(0, col * MAX_TEX_SIZE, width, (col + 1 == columns) ? remainder : MAX_TEX_SIZE)
bmp.blt(col * TILESET_WIDTH, 0, originalbmp, srcrect)
end
return bmp
end
return originalbmp
end
def getWrappedRect(src_rect)
ret = Rect.new(0, 0, 0, 0)
col = (src_rect.y / MAX_TEX_SIZE.to_f).floor
ret.x = (col * TILESET_WIDTH) + src_rect.x.clamp(0, TILESET_WIDTH)
ret.y = src_rect.y % MAX_TEX_SIZE
ret.width = src_rect.width.clamp(0, TILESET_WIDTH - src_rect.x)
ret.height = src_rect.height.clamp(0, MAX_TEX_SIZE)
return ret
end
private
def blitWrappedPixels(destX, destY, dest, src, srcrect)
if srcrect.y + srcrect.width < MAX_TEX_SIZE
# Save the processing power
dest.blt(destX, destY, src, srcrect)
return
end
merge = (srcrect.y % MAX_TEX_SIZE) > ((srcrect.y + srcrect.height) % MAX_TEX_SIZE)
srcrect_mod = getWrappedRect(srcrect)
if merge
# FIXME: won't work on heights longer than two columns, but nobody should need
# more than 32k pixels high at once anyway
side = {
:a => MAX_TEX_SIZE - srcrect_mod.y,
:b => srcrect_mod.height - MAX_TEX_SIZE + srcrect_mod.y
}
dest.blt(destX, destY, src, Rect.new(srcrect_mod.x, srcrect_mod.y, srcrect_mod.width, side[:a]))
dest.blt(destX, destY + side[:a], src, Rect.new(srcrect_mod.x + TILESET_WIDTH, 0, srcrect_mod.width, side[:b]))
else
dest.blt(destX, destY, src, srcrect_mod)
end
end
def stretchBlitWrappedPixels(destrect, dest, src, srcrect)
if srcrect.y + srcrect.width < MAX_TEX_SIZE
# Save the processing power
dest.stretch_blt(destrect, src, srcrect)
return
end
# Does a regular blit to a non-megasurface, then stretch_blts that to
# the destination. Yes it is slow
tmp = Bitmap.new(srcrect.width, srcrect.height)
blitWrappedPixels(0, 0, tmp, src, srcrect)
dest.stretch_blt(destrect, tmp, Rect.new(0, 0, srcrect.width, srcrect.height))
end
end
end

View File

@@ -0,0 +1,72 @@
class TilemapRenderer
module AutotileExpander
MAX_TEXTURE_SIZE = (Bitmap.max_size / 1024) * 1024
module_function
# This doesn't allow for cache sizes smaller than 768, but if that applies
# to you, you've got bigger problems.
def expand(bitmap)
return bitmap if bitmap.height == SOURCE_TILE_HEIGHT
expanded_format = (bitmap.height == SOURCE_TILE_HEIGHT * 6)
wrap = false
if MAX_TEXTURE_SIZE < TILES_PER_AUTOTILE * SOURCE_TILE_HEIGHT
wrap = true # Each autotile will occupy two columns instead of one
end
frames_count = [bitmap.width / (3 * SOURCE_TILE_WIDTH), 1].max
new_bitmap = Bitmap.new(frames_count * (wrap ? 2 : 1) * SOURCE_TILE_WIDTH,
TILES_PER_AUTOTILE * SOURCE_TILE_HEIGHT / (wrap ? 2 : 1))
rect = Rect.new(0, 0, SOURCE_TILE_WIDTH / 2, SOURCE_TILE_HEIGHT / 2)
TILES_PER_AUTOTILE.times do |id|
pattern = TileDrawingHelper::AUTOTILE_PATTERNS[id >> 3][id % TILESET_TILES_PER_ROW]
wrap_offset_x = (wrap && id >= TILES_PER_AUTOTILE / 2) ? SOURCE_TILE_WIDTH : 0
wrap_offset_y = (wrap && id >= TILES_PER_AUTOTILE / 2) ? (TILES_PER_AUTOTILE / 2) * SOURCE_TILE_HEIGHT : 0
frames_count.times do |frame|
if expanded_format && [1, 2, 4, 8].include?(id)
dest_x = frame * SOURCE_TILE_WIDTH * (wrap ? 2 : 1)
dest_x += wrap_offset_x
next if dest_x > MAX_TEXTURE_SIZE
dest_y = id * SOURCE_TILE_HEIGHT
dest_y -= wrap_offset_y
next if dest_y > MAX_TEXTURE_SIZE
case id
when 1 # Top left corner
new_bitmap.blt(dest_x, dest_y, bitmap,
Rect.new(frame * SOURCE_TILE_WIDTH * 3, SOURCE_TILE_HEIGHT * 4,
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
when 2 # Top right corner
new_bitmap.blt(dest_x, dest_y, bitmap,
Rect.new(SOURCE_TILE_WIDTH + (frame * SOURCE_TILE_WIDTH * 3), SOURCE_TILE_HEIGHT * 4,
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
when 4 # Bottom right corner
new_bitmap.blt(dest_x, dest_y, bitmap,
Rect.new(SOURCE_TILE_WIDTH + (frame * SOURCE_TILE_WIDTH * 3), SOURCE_TILE_HEIGHT * 5,
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
when 8 # Bottom left corner
new_bitmap.blt(dest_x, dest_y, bitmap,
Rect.new(frame * SOURCE_TILE_WIDTH * 3, SOURCE_TILE_HEIGHT * 5,
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
end
next
end
pattern.each_with_index do |src_chunk, i|
real_src_chunk = src_chunk - 1
dest_x = (i % 2) * SOURCE_TILE_WIDTH / 2
dest_x += frame * SOURCE_TILE_WIDTH * (wrap ? 2 : 1)
dest_x += wrap_offset_x
next if dest_x > MAX_TEXTURE_SIZE
dest_y = (i / 2) * SOURCE_TILE_HEIGHT / 2
dest_y += id * SOURCE_TILE_HEIGHT
dest_y -= wrap_offset_y
next if dest_y > MAX_TEXTURE_SIZE
rect.x = (real_src_chunk % 6) * SOURCE_TILE_WIDTH / 2
rect.x += SOURCE_TILE_WIDTH * 3 * frame
rect.y = (real_src_chunk / 6) * SOURCE_TILE_HEIGHT / 2
new_bitmap.blt(dest_x, dest_y, bitmap, rect)
end
end
end
return new_bitmap
end
end
end

View File

@@ -1,228 +0,0 @@
class TileDrawingHelper
attr_accessor :tileset
attr_accessor :autotiles
Autotiles = [
[ [27, 28, 33, 34], [ 5, 28, 33, 34], [27, 6, 33, 34], [ 5, 6, 33, 34],
[27, 28, 33, 12], [ 5, 28, 33, 12], [27, 6, 33, 12], [ 5, 6, 33, 12] ],
[ [27, 28, 11, 34], [ 5, 28, 11, 34], [27, 6, 11, 34], [ 5, 6, 11, 34],
[27, 28, 11, 12], [ 5, 28, 11, 12], [27, 6, 11, 12], [ 5, 6, 11, 12] ],
[ [25, 26, 31, 32], [25, 6, 31, 32], [25, 26, 31, 12], [25, 6, 31, 12],
[15, 16, 21, 22], [15, 16, 21, 12], [15, 16, 11, 22], [15, 16, 11, 12] ],
[ [29, 30, 35, 36], [29, 30, 11, 36], [ 5, 30, 35, 36], [ 5, 30, 11, 36],
[39, 40, 45, 46], [ 5, 40, 45, 46], [39, 6, 45, 46], [ 5, 6, 45, 46] ],
[ [25, 30, 31, 36], [15, 16, 45, 46], [13, 14, 19, 20], [13, 14, 19, 12],
[17, 18, 23, 24], [17, 18, 11, 24], [41, 42, 47, 48], [ 5, 42, 47, 48] ],
[ [37, 38, 43, 44], [37, 6, 43, 44], [13, 18, 19, 24], [13, 14, 43, 44],
[37, 42, 43, 48], [17, 18, 47, 48], [13, 18, 43, 48], [ 1, 2, 7, 8] ]
]
# converts neighbors returned from tableNeighbors to tile indexes
NeighborsToTiles = [
46, 44, 46, 44, 43, 41, 43, 40, 46, 44, 46, 44, 43, 41, 43, 40,
42, 32, 42, 32, 35, 19, 35, 18, 42, 32, 42, 32, 34, 17, 34, 16,
46, 44, 46, 44, 43, 41, 43, 40, 46, 44, 46, 44, 43, 41, 43, 40,
42, 32, 42, 32, 35, 19, 35, 18, 42, 32, 42, 32, 34, 17, 34, 16,
45, 39, 45, 39, 33, 31, 33, 29, 45, 39, 45, 39, 33, 31, 33, 29,
37, 27, 37, 27, 23, 15, 23, 13, 37, 27, 37, 27, 22, 11, 22, 9,
45, 39, 45, 39, 33, 31, 33, 29, 45, 39, 45, 39, 33, 31, 33, 29,
36, 26, 36, 26, 21, 7, 21, 5, 36, 26, 36, 26, 20, 3, 20, 1,
46, 44, 46, 44, 43, 41, 43, 40, 46, 44, 46, 44, 43, 41, 43, 40,
42, 32, 42, 32, 35, 19, 35, 18, 42, 32, 42, 32, 34, 17, 34, 16,
46, 44, 46, 44, 43, 41, 43, 40, 46, 44, 46, 44, 43, 41, 43, 40,
42, 32, 42, 32, 35, 19, 35, 18, 42, 32, 42, 32, 34, 17, 34, 16,
45, 38, 45, 38, 33, 30, 33, 28, 45, 38, 45, 38, 33, 30, 33, 28,
37, 25, 37, 25, 23, 14, 23, 12, 37, 25, 37, 25, 22, 10, 22, 8,
45, 38, 45, 38, 33, 30, 33, 28, 45, 38, 45, 38, 33, 30, 33, 28,
36, 24, 36, 24, 21, 6, 21, 4, 36, 24, 36, 24, 20, 2, 20, 0
]
def self.tableNeighbors(data,x,y)
return 0 if x < 0 || x >= data.xsize
return 0 if y < 0 || y >= data.ysize
t = data[x,y]
xp1 = [x + 1, data.xsize - 1].min
yp1 = [y + 1, data.ysize - 1].min
xm1 = [x - 1, 0].max
ym1 = [y - 1, 0].max
i = 0
i |= 0x01 if data[ x, ym1] == t # N
i |= 0x02 if data[xp1, ym1] == t # NE
i |= 0x04 if data[xp1, y] == t # E
i |= 0x08 if data[xp1, yp1] == t # SE
i |= 0x10 if data[ x, yp1] == t # S
i |= 0x20 if data[xm1, yp1] == t # SW
i |= 0x40 if data[xm1, y] == t # W
i |= 0x80 if data[xm1, ym1] == t # NW
return i
end
def self.fromTileset(tileset)
bmtileset=pbGetTileset(tileset.tileset_name)
bmautotiles=[]
for i in 0...7
bmautotiles.push(pbGetAutotile(tileset.autotile_names[i]))
end
return self.new(bmtileset,bmautotiles)
end
def initialize(tileset, autotiles)
if tileset.mega?
@tileset = TileWrap::wrapTileset(tileset)
tileset.dispose
@shouldWrap = true
else
@tileset = tileset
@shouldWrap = false
end
@autotiles = autotiles
end
def dispose
@tileset.dispose if @tileset
@tileset = nil
for i in 0...@autotiles.length
@autotiles[i].dispose
@autotiles[i] = nil
end
end
def bltSmallAutotile(bitmap,x,y,cxTile,cyTile,id,frame)
return if id >= 384 || frame < 0 || !@autotiles
autotile = @autotiles[id / 48 - 1]
return if !autotile || autotile.disposed?
cxTile = [cxTile / 2, 1].max
cyTile = [cyTile / 2, 1].max
if autotile.height == 32
anim = frame * 32
src_rect = Rect.new(anim, 0, 32, 32)
bitmap.stretch_blt(Rect.new(x, y, cxTile * 2, cyTile * 2), autotile, src_rect)
else
anim = frame * 96
id %= 48
tiles = TileDrawingHelper::Autotiles[id >> 3][id & 7]
src = Rect.new(0, 0, 0, 0)
for i in 0...4
tile_position = tiles[i] - 1
src.set(tile_position % 6 * 16 + anim, tile_position / 6 * 16, 16, 16)
bitmap.stretch_blt(Rect.new(i % 2 * cxTile + x, i / 2 * cyTile + y, cxTile, cyTile),
autotile, src)
end
end
end
def bltSmallRegularTile(bitmap,x,y,cxTile,cyTile,id)
return if id < 384 || !@tileset || @tileset.disposed?
rect = Rect.new((id - 384) % 8 * 32, (id - 384) / 8 * 32, 32, 32)
rect = TileWrap::getWrappedRect(rect) if @shouldWrap
bitmap.stretch_blt(Rect.new(x, y, cxTile, cyTile), @tileset, rect)
end
def bltSmallTile(bitmap,x,y,cxTile,cyTile,id,frame=0)
if id >= 384
bltSmallRegularTile(bitmap, x, y, cxTile, cyTile, id)
elsif id > 0
bltSmallAutotile(bitmap, x, y, cxTile, cyTile, id, frame)
end
end
def bltAutotile(bitmap,x,y,id,frame)
bltSmallAutotile(bitmap, x, y, 32, 32, id, frame)
end
def bltRegularTile(bitmap,x,y,id)
bltSmallRegularTile(bitmap, x, y, 32, 32, id)
end
def bltTile(bitmap,x,y,id,frame=0)
if id >= 384
bltRegularTile(bitmap, x, y, id)
elsif id > 0
bltAutotile(bitmap, x, y, id, frame)
end
end
end
#===============================================================================
#
#===============================================================================
def createMinimap(mapid)
map=load_data(sprintf("Data/Map%03d.rxdata",mapid)) rescue nil
return BitmapWrapper.new(32,32) if !map
bitmap=BitmapWrapper.new(map.width*4,map.height*4)
black=Color.new(0,0,0)
tilesets=$data_tilesets
tileset=tilesets[map.tileset_id]
return bitmap if !tileset
helper=TileDrawingHelper.fromTileset(tileset)
for y in 0...map.height
for x in 0...map.width
for z in 0..2
id=map.data[x,y,z]
id=0 if !id
helper.bltSmallTile(bitmap,x*4,y*4,4,4,id)
end
end
end
bitmap.fill_rect(0,0,bitmap.width,1,black)
bitmap.fill_rect(0,bitmap.height-1,bitmap.width,1,black)
bitmap.fill_rect(0,0,1,bitmap.height,black)
bitmap.fill_rect(bitmap.width-1,0,1,bitmap.height,black)
return bitmap
end
def bltMinimapAutotile(dstBitmap,x,y,srcBitmap,id)
return if id>=48 || !srcBitmap || srcBitmap.disposed?
anim=0
cxTile=3
cyTile=3
tiles = TileDrawingHelper::Autotiles[id>>3][id&7]
src=Rect.new(0,0,0,0)
for i in 0...4
tile_position = tiles[i] - 1
src.set(
tile_position % 6 * cxTile + anim,
tile_position / 6 * cyTile, cxTile, cyTile)
dstBitmap.blt(i%2*cxTile+x,i/2*cyTile+y, srcBitmap, src)
end
end
def passable?(passages,tile_id)
return false if tile_id == nil
passage = passages[tile_id]
return (passage && passage<15)
end
# Unused
def getPassabilityMinimap(mapid)
map = load_data(sprintf("Data/Map%03d.rxdata",mapid))
tileset = $data_tilesets[map.tileset_id]
minimap = AnimatedBitmap.new("Graphics/Pictures/minimap_tiles")
ret = Bitmap.new(map.width*6,map.height*6)
passtable = Table.new(map.width,map.height)
passages = tileset.passages
for i in 0...map.width
for j in 0...map.height
pass=true
for z in [2,1,0]
if !passable?(passages,map.data[i,j,z])
pass=false
break
end
end
passtable[i,j]=pass ? 1 : 0
end
end
neighbors=TileDrawingHelper::NeighborsToTiles
for i in 0...map.width
for j in 0...map.height
if passtable[i,j]==0
nb=TileDrawingHelper.tableNeighbors(passtable,i,j)
tile=neighbors[nb]
bltMinimapAutotile(ret,i*6,j*6,minimap.bitmap,tile)
end
end
end
minimap.disposes
return ret
end

View File

@@ -0,0 +1,226 @@
class TileDrawingHelper
attr_accessor :tileset
attr_accessor :autotiles
AUTOTILE_PATTERNS = [
[[27, 28, 33, 34], [5, 28, 33, 34], [27, 6, 33, 34], [5, 6, 33, 34],
[27, 28, 33, 12], [5, 28, 33, 12], [27, 6, 33, 12], [5, 6, 33, 12]],
[[27, 28, 11, 34], [5, 28, 11, 34], [27, 6, 11, 34], [5, 6, 11, 34],
[27, 28, 11, 12], [5, 28, 11, 12], [27, 6, 11, 12], [5, 6, 11, 12]],
[[25, 26, 31, 32], [25, 6, 31, 32], [25, 26, 31, 12], [25, 6, 31, 12],
[15, 16, 21, 22], [15, 16, 21, 12], [15, 16, 11, 22], [15, 16, 11, 12]],
[[29, 30, 35, 36], [29, 30, 11, 36], [5, 30, 35, 36], [5, 30, 11, 36],
[39, 40, 45, 46], [5, 40, 45, 46], [39, 6, 45, 46], [5, 6, 45, 46]],
[[25, 30, 31, 36], [15, 16, 45, 46], [13, 14, 19, 20], [13, 14, 19, 12],
[17, 18, 23, 24], [17, 18, 11, 24], [41, 42, 47, 48], [5, 42, 47, 48]],
[[37, 38, 43, 44], [37, 6, 43, 44], [13, 18, 19, 24], [13, 14, 43, 44],
[37, 42, 43, 48], [17, 18, 47, 48], [13, 18, 43, 48], [1, 2, 7, 8]]
]
# converts neighbors returned from tableNeighbors to tile indexes
NEIGHBORS_TO_AUTOTILE_INDEX = [
46, 44, 46, 44, 43, 41, 43, 40, 46, 44, 46, 44, 43, 41, 43, 40,
42, 32, 42, 32, 35, 19, 35, 18, 42, 32, 42, 32, 34, 17, 34, 16,
46, 44, 46, 44, 43, 41, 43, 40, 46, 44, 46, 44, 43, 41, 43, 40,
42, 32, 42, 32, 35, 19, 35, 18, 42, 32, 42, 32, 34, 17, 34, 16,
45, 39, 45, 39, 33, 31, 33, 29, 45, 39, 45, 39, 33, 31, 33, 29,
37, 27, 37, 27, 23, 15, 23, 13, 37, 27, 37, 27, 22, 11, 22, 9,
45, 39, 45, 39, 33, 31, 33, 29, 45, 39, 45, 39, 33, 31, 33, 29,
36, 26, 36, 26, 21, 7, 21, 5, 36, 26, 36, 26, 20, 3, 20, 1,
46, 44, 46, 44, 43, 41, 43, 40, 46, 44, 46, 44, 43, 41, 43, 40,
42, 32, 42, 32, 35, 19, 35, 18, 42, 32, 42, 32, 34, 17, 34, 16,
46, 44, 46, 44, 43, 41, 43, 40, 46, 44, 46, 44, 43, 41, 43, 40,
42, 32, 42, 32, 35, 19, 35, 18, 42, 32, 42, 32, 34, 17, 34, 16,
45, 38, 45, 38, 33, 30, 33, 28, 45, 38, 45, 38, 33, 30, 33, 28,
37, 25, 37, 25, 23, 14, 23, 12, 37, 25, 37, 25, 22, 10, 22, 8,
45, 38, 45, 38, 33, 30, 33, 28, 45, 38, 45, 38, 33, 30, 33, 28,
36, 24, 36, 24, 21, 6, 21, 4, 36, 24, 36, 24, 20, 2, 20, 0
]
def self.tableNeighbors(data, x, y)
return 0 if x < 0 || x >= data.xsize
return 0 if y < 0 || y >= data.ysize
t = data[x, y]
xp1 = [x + 1, data.xsize - 1].min
yp1 = [y + 1, data.ysize - 1].min
xm1 = [x - 1, 0].max
ym1 = [y - 1, 0].max
i = 0
i |= 0x01 if data[x, ym1] == t # N
i |= 0x02 if data[xp1, ym1] == t # NE
i |= 0x04 if data[xp1, y] == t # E
i |= 0x08 if data[xp1, yp1] == t # SE
i |= 0x10 if data[x, yp1] == t # S
i |= 0x20 if data[xm1, yp1] == t # SW
i |= 0x40 if data[xm1, y] == t # W
i |= 0x80 if data[xm1, ym1] == t # NW
return i
end
def self.fromTileset(tileset)
bmtileset = pbGetTileset(tileset.tileset_name)
bmautotiles = []
7.times do |i|
bmautotiles.push(pbGetAutotile(tileset.autotile_names[i]))
end
return self.new(bmtileset, bmautotiles)
end
def initialize(tileset, autotiles)
if tileset.mega?
@tileset = TilemapRenderer::TilesetWrapper.wrapTileset(tileset)
tileset.dispose
@shouldWrap = true
else
@tileset = tileset
@shouldWrap = false
end
@autotiles = autotiles
end
def dispose
@tileset&.dispose
@tileset = nil
@autotiles.each_with_index do |autotile, i|
autotile.dispose
@autotiles[i] = nil
end
end
def bltSmallAutotile(bitmap, x, y, cxTile, cyTile, id, frame)
return if id >= 384 || frame < 0 || !@autotiles
autotile = @autotiles[(id / 48) - 1]
return if !autotile || autotile.disposed?
cxTile = [cxTile / 2, 1].max
cyTile = [cyTile / 2, 1].max
if autotile.height == 32
anim = frame * 32
src_rect = Rect.new(anim, 0, 32, 32)
bitmap.stretch_blt(Rect.new(x, y, cxTile * 2, cyTile * 2), autotile, src_rect)
else
anim = frame * 96
id %= 48
tiles = AUTOTILE_PATTERNS[id >> 3][id & 7]
src = Rect.new(0, 0, 0, 0)
4.times do |i|
tile_position = tiles[i] - 1
src.set((tile_position % 6 * 16) + anim, tile_position / 6 * 16, 16, 16)
bitmap.stretch_blt(Rect.new((i % 2 * cxTile) + x, (i / 2 * cyTile) + y, cxTile, cyTile),
autotile, src)
end
end
end
def bltSmallRegularTile(bitmap, x, y, cxTile, cyTile, id)
return if id < 384 || !@tileset || @tileset.disposed?
rect = Rect.new((id - 384) % 8 * 32, (id - 384) / 8 * 32, 32, 32)
rect = TilemapRenderer::TilesetWrapper.getWrappedRect(rect) if @shouldWrap
bitmap.stretch_blt(Rect.new(x, y, cxTile, cyTile), @tileset, rect)
end
def bltSmallTile(bitmap, x, y, cxTile, cyTile, id, frame = 0)
if id >= 384
bltSmallRegularTile(bitmap, x, y, cxTile, cyTile, id)
elsif id > 0
bltSmallAutotile(bitmap, x, y, cxTile, cyTile, id, frame)
end
end
def bltAutotile(bitmap, x, y, id, frame)
bltSmallAutotile(bitmap, x, y, 32, 32, id, frame)
end
def bltRegularTile(bitmap, x, y, id)
bltSmallRegularTile(bitmap, x, y, 32, 32, id)
end
def bltTile(bitmap, x, y, id, frame = 0)
if id >= 384
bltRegularTile(bitmap, x, y, id)
elsif id > 0
bltAutotile(bitmap, x, y, id, frame)
end
end
end
#===============================================================================
#
#===============================================================================
def createMinimap(mapid)
map = load_data(sprintf("Data/Map%03d.rxdata", mapid)) rescue nil
return BitmapWrapper.new(32, 32) if !map
bitmap = BitmapWrapper.new(map.width * 4, map.height * 4)
black = Color.new(0, 0, 0)
tilesets = $data_tilesets
tileset = tilesets[map.tileset_id]
return bitmap if !tileset
helper = TileDrawingHelper.fromTileset(tileset)
map.height.times do |y|
map.width.times do |x|
3.times do |z|
id = map.data[x, y, z]
id = 0 if !id
helper.bltSmallTile(bitmap, x * 4, y * 4, 4, 4, id)
end
end
end
bitmap.fill_rect(0, 0, bitmap.width, 1, black)
bitmap.fill_rect(0, bitmap.height - 1, bitmap.width, 1, black)
bitmap.fill_rect(0, 0, 1, bitmap.height, black)
bitmap.fill_rect(bitmap.width - 1, 0, 1, bitmap.height, black)
return bitmap
end
def bltMinimapAutotile(dstBitmap, x, y, srcBitmap, id)
return if id >= 48 || !srcBitmap || srcBitmap.disposed?
anim = 0
cxTile = 3
cyTile = 3
tiles = TileDrawingHelper::AUTOTILE_PATTERNS[id >> 3][id & 7]
src = Rect.new(0, 0, 0, 0)
4.times do |i|
tile_position = tiles[i] - 1
src.set((tile_position % 6 * cxTile) + anim,
tile_position / 6 * cyTile, cxTile, cyTile)
dstBitmap.blt((i % 2 * cxTile) + x, (i / 2 * cyTile) + y, srcBitmap, src)
end
end
def passable?(passages, tile_id)
return false if tile_id.nil?
passage = passages[tile_id]
return (passage && passage < 15)
end
# Unused
def getPassabilityMinimap(mapid)
map = load_data(sprintf("Data/Map%03d.rxdata", mapid))
tileset = $data_tilesets[map.tileset_id]
minimap = AnimatedBitmap.new("Graphics/Pictures/minimap_tiles")
ret = Bitmap.new(map.width * 6, map.height * 6)
passtable = Table.new(map.width, map.height)
passages = tileset.passages
map.width.times do |i|
map.height.times do |j|
pass = true
[2, 1, 0].each do |z|
if !passable?(passages, map.data[i, j, z])
pass = false
break
end
end
passtable[i, j] = pass ? 1 : 0
end
end
neighbors = TileDrawingHelper::NEIGHBORS_TO_AUTOTILE_INDEX
map.width.times do |i|
map.height.times do |j|
next if passtable[i, j] != 0
nb = TileDrawingHelper.tableNeighbors(passtable, i, j)
tile = neighbors[nb]
bltMinimapAutotile(ret, i * 6, j * 6, minimap.bitmap, tile)
end
end
minimap.disposes
return ret
end

View File

@@ -27,7 +27,7 @@ module RPG
def self.fromCache(i) def self.fromCache(i)
return nil if !@cache.include?(i) return nil if !@cache.include?(i)
obj = @cache[i] obj = @cache[i]
return nil if obj && obj.disposed? return nil if obj&.disposed?
return obj return obj
end end

View File

@@ -4,11 +4,14 @@ module MessageConfig
DARK_TEXT_MAIN_COLOR = Color.new(80, 80, 88) DARK_TEXT_MAIN_COLOR = Color.new(80, 80, 88)
DARK_TEXT_SHADOW_COLOR = Color.new(160, 160, 168) DARK_TEXT_SHADOW_COLOR = Color.new(160, 160, 168)
FONT_NAME = "Power Green" FONT_NAME = "Power Green"
FONT_SIZE = 29 FONT_SIZE = 27
FONT_Y_OFFSET = 8
SMALL_FONT_NAME = "Power Green Small" SMALL_FONT_NAME = "Power Green Small"
SMALL_FONT_SIZE = 25 SMALL_FONT_SIZE = 21
SMALL_FONT_Y_OFFSET = 8
NARROW_FONT_NAME = "Power Green Narrow" NARROW_FONT_NAME = "Power Green Narrow"
NARROW_FONT_SIZE = 29 NARROW_FONT_SIZE = 27
NARROW_FONT_Y_OFFSET = 8
# 0 = Pause cursor is displayed at end of text # 0 = Pause cursor is displayed at end of text
# 1 = Pause cursor is displayed at bottom right # 1 = Pause cursor is displayed at bottom right
# 2 = Pause cursor is displayed at lower middle side # 2 = Pause cursor is displayed at lower middle side
@@ -144,12 +147,13 @@ module MessageConfig
end end
def self.pbTryFonts(*args) def self.pbTryFonts(*args)
for a in args args.each do |a|
next if !a next if !a
if a.is_a?(String) case a
when String
return a if Font.exist?(a) return a if Font.exist?(a)
elsif a.is_a?(Array) when Array
for aa in a a.each do |aa|
ret = MessageConfig.pbTryFonts(aa) ret = MessageConfig.pbTryFonts(aa)
return ret if ret != "" return ret if ret != ""
end end
@@ -176,8 +180,8 @@ end
def pbBottomLeftLines(window, lines, width = nil) def pbBottomLeftLines(window, lines, width = nil)
window.x = 0 window.x = 0
window.width=width ? width : Graphics.width window.width = width || Graphics.width
window.height=(window.borderY rescue 32)+lines*32 window.height = (window.borderY rescue 32) + (lines * 32)
window.y = Graphics.height - window.height window.y = Graphics.height - window.height
end end
@@ -230,9 +234,9 @@ end
# internal function # internal function
def pbRepositionMessageWindow(msgwindow, linecount = 2) def pbRepositionMessageWindow(msgwindow, linecount = 2)
msgwindow.height=32*linecount+msgwindow.borderY msgwindow.height = (32 * linecount) + msgwindow.borderY
msgwindow.y = (Graphics.height) - (msgwindow.height) msgwindow.y = (Graphics.height) - (msgwindow.height)
if $game_system && $game_system.respond_to?("message_position") if $game_system
case $game_system.message_position case $game_system.message_position
when 0 # up when 0 # up
msgwindow.y = 0 msgwindow.y = 0
@@ -241,11 +245,7 @@ def pbRepositionMessageWindow(msgwindow, linecount=2)
when 2 when 2
msgwindow.y = (Graphics.height) - (msgwindow.height) msgwindow.y = (Graphics.height) - (msgwindow.height)
end end
end msgwindow.opacity = 0 if $game_system.message_frame != 0
if $game_system && $game_system.respond_to?("message_frame")
if $game_system.message_frame != 0
msgwindow.opacity = 0
end
end end
end end
@@ -282,13 +282,13 @@ def isDarkBackground(background,rect=nil)
return true if rect.width <= 0 || rect.height <= 0 return true if rect.width <= 0 || rect.height <= 0
xSeg = (rect.width / 16) xSeg = (rect.width / 16)
xLoop = (xSeg == 0) ? 1 : 16 xLoop = (xSeg == 0) ? 1 : 16
xStart = (xSeg==0) ? rect.x+(rect.width/2) : rect.x+xSeg/2 xStart = (xSeg == 0) ? rect.x + (rect.width / 2) : rect.x + (xSeg / 2)
ySeg = (rect.height / 16) ySeg = (rect.height / 16)
yLoop = (ySeg == 0) ? 1 : 16 yLoop = (ySeg == 0) ? 1 : 16
yStart = (ySeg==0) ? rect.y+(rect.height/2) : rect.y+ySeg/2 yStart = (ySeg == 0) ? rect.y + (rect.height / 2) : rect.y + (ySeg / 2)
count = 0 count = 0
y = yStart y = yStart
r = 0; g = 0; b = 0 r = g = b = 0
yLoop.times do yLoop.times do
x = xStart x = xStart
xLoop.times do xLoop.times do
@@ -307,7 +307,7 @@ def isDarkBackground(background,rect=nil)
r /= count r /= count
g /= count g /= count
b /= count b /= count
return (r*0.299+g*0.587+b*0.114)<160 return ((r * 0.299) + (g * 0.587) + (b * 0.114)) < 160
end end
def isDarkWindowskin(windowskin) def isDarkWindowskin(windowskin)
@@ -320,7 +320,7 @@ def isDarkWindowskin(windowskin)
return isDarkBackground(windowskin, Rect.new(32, 16, 16, 16)) return isDarkBackground(windowskin, Rect.new(32, 16, 16, 16))
else else
clr = windowskin.get_pixel(windowskin.width / 2, windowskin.height / 2) clr = windowskin.get_pixel(windowskin.width / 2, windowskin.height / 2)
return (clr.red*0.299+clr.green*0.587+clr.blue*0.114)<160 return ((clr.red * 0.299) + (clr.green * 0.587) + (clr.blue * 0.114)) < 160
end end
end end
@@ -356,14 +356,14 @@ def getSkinColor(windowskin,color,isDarkSkin)
end end
# Special colour as listed above # Special colour as listed above
if isDarkSkin && color != 12 # Dark background, light text if isDarkSkin && color != 12 # Dark background, light text
return sprintf("<c3=%s,%s>",textcolors[2*(color-1)+1],textcolors[2*(color-1)]) return sprintf("<c3=%s,%s>", textcolors[(2 * (color - 1)) + 1], textcolors[2 * (color - 1)])
end end
# Light background, dark text # Light background, dark text
return sprintf("<c3=%s,%s>",textcolors[2*(color-1)],textcolors[2*(color-1)+1]) return sprintf("<c3=%s,%s>", textcolors[2 * (color - 1)], textcolors[(2 * (color - 1)) + 1])
else # VX windowskin else # VX windowskin
color = 0 if color >= 32 color = 0 if color >= 32
x = 64 + (color % 8) * 8 x = 64 + ((color % 8) * 8)
y = 96 + (color / 8) * 8 y = 96 + ((color / 8) * 8)
pixel = windowskin.get_pixel(x, y) pixel = windowskin.get_pixel(x, y)
return shadowctagFromColor(pixel) return shadowctagFromColor(pixel)
end end
@@ -396,10 +396,10 @@ end
def pbDoEnsureBitmap(bitmap, dwidth, dheight) def pbDoEnsureBitmap(bitmap, dwidth, dheight)
if !bitmap || bitmap.disposed? || bitmap.width < dwidth || bitmap.height < dheight if !bitmap || bitmap.disposed? || bitmap.width < dwidth || bitmap.height < dheight
oldfont = (bitmap && !bitmap.disposed?) ? bitmap.font : nil oldfont = (bitmap && !bitmap.disposed?) ? bitmap.font : nil
bitmap.dispose if bitmap bitmap&.dispose
bitmap = Bitmap.new([1, dwidth].max, [1, dheight].max) bitmap = Bitmap.new([1, dwidth].max, [1, dheight].max)
(oldfont) ? bitmap.font = oldfont : pbSetSystemFont(bitmap) (oldfont) ? bitmap.font = oldfont : pbSetSystemFont(bitmap)
bitmap.font.shadow = false if bitmap.font && bitmap.font.respond_to?("shadow") bitmap.font.shadow = false if bitmap.font.respond_to?("shadow")
end end
return bitmap return bitmap
end end
@@ -411,18 +411,21 @@ end
def pbSetSystemFont(bitmap) def pbSetSystemFont(bitmap)
bitmap.font.name = MessageConfig.pbGetSystemFontName bitmap.font.name = MessageConfig.pbGetSystemFontName
bitmap.font.size = MessageConfig::FONT_SIZE bitmap.font.size = MessageConfig::FONT_SIZE
bitmap.text_offset_y = MessageConfig::FONT_Y_OFFSET
end end
# Sets a bitmap's font to the system small font. # Sets a bitmap's font to the system small font.
def pbSetSmallFont(bitmap) def pbSetSmallFont(bitmap)
bitmap.font.name = MessageConfig.pbGetSmallFontName bitmap.font.name = MessageConfig.pbGetSmallFontName
bitmap.font.size = MessageConfig::SMALL_FONT_SIZE bitmap.font.size = MessageConfig::SMALL_FONT_SIZE
bitmap.text_offset_y = MessageConfig::SMALL_FONT_Y_OFFSET
end end
# Sets a bitmap's font to the system narrow font. # Sets a bitmap's font to the system narrow font.
def pbSetNarrowFont(bitmap) def pbSetNarrowFont(bitmap)
bitmap.font.name = MessageConfig.pbGetNarrowFontName bitmap.font.name = MessageConfig.pbGetNarrowFontName
bitmap.font.size = MessageConfig::NARROW_FONT_SIZE bitmap.font.size = MessageConfig::NARROW_FONT_SIZE
bitmap.text_offset_y = MessageConfig::NARROW_FONT_Y_OFFSET
end end
#=============================================================================== #===============================================================================
@@ -445,10 +448,10 @@ def pbSrcOver(dstColor,srcColor)
cg = dstColor.green * dstColor.alpha / 255 cg = dstColor.green * dstColor.alpha / 255
cb = dstColor.blue * dstColor.alpha / 255 cb = dstColor.blue * dstColor.alpha / 255
ica = 255 - dstColor.alpha ica = 255 - dstColor.alpha
a=255-(iea*ica)/255 a = 255 - ((iea * ica) / 255)
r=(iea*cr)/255+er r = ((iea * cr) / 255) + er
g=(iea*cg)/255+eg g = ((iea * cg) / 255) + eg
b=(iea*cb)/255+eb b = ((iea * cb) / 255) + eb
r = (a == 0) ? 0 : r * 255 / a r = (a == 0) ? 0 : r * 255 / a
g = (a == 0) ? 0 : g * 255 / a g = (a == 0) ? 0 : g * 255 / a
b = (a == 0) ? 0 : b * 255 / a b = (a == 0) ? 0 : b * 255 / a
@@ -458,14 +461,14 @@ end
def pbSetSpritesToColor(sprites, color) def pbSetSpritesToColor(sprites, color)
return if !sprites || !color return if !sprites || !color
colors = {} colors = {}
for i in sprites sprites.each do |i|
next if !i[1] || pbDisposed?(i[1]) next if !i[1] || pbDisposed?(i[1])
colors[i[0]] = i[1].color.clone colors[i[0]] = i[1].color.clone
i[1].color = pbSrcOver(i[1].color, color) i[1].color = pbSrcOver(i[1].color, color)
end end
Graphics.update Graphics.update
Input.update Input.update
for i in colors colors.each do |i|
next if !sprites[i[0]] next if !sprites[i[0]]
sprites[i[0]].color = i[1] sprites[i[0]].color = i[1]
end end
@@ -483,7 +486,7 @@ def using(window)
end end
def pbUpdateSpriteHash(windows) def pbUpdateSpriteHash(windows)
for i in windows windows.each do |i|
window = i[1] window = i[1]
if window if window
if window.is_a?(Sprite) || window.is_a?(Window) if window.is_a?(Sprite) || window.is_a?(Window)
@@ -506,7 +509,7 @@ end
# Disposes all objects in the specified hash. # Disposes all objects in the specified hash.
def pbDisposeSpriteHash(sprites) def pbDisposeSpriteHash(sprites)
return if !sprites return if !sprites
for i in sprites.keys sprites.each_key do |i|
pbDisposeSprite(sprites, i) pbDisposeSprite(sprites, i)
end end
sprites.clear sprites.clear
@@ -555,7 +558,7 @@ def pbFadeOutIn(z=99999,nofadeout=false)
viewport.z = z viewport.z = z
numFrames = (Graphics.frame_rate * 0.4).floor numFrames = (Graphics.frame_rate * 0.4).floor
alphaDiff = (255.0 / numFrames).ceil alphaDiff = (255.0 / numFrames).ceil
for j in 0..numFrames (0..numFrames).each do |j|
col.set(0, 0, 0, j * alphaDiff) col.set(0, 0, 0, j * alphaDiff)
viewport.color = col viewport.color = col
Graphics.update Graphics.update
@@ -563,11 +566,13 @@ def pbFadeOutIn(z=99999,nofadeout=false)
end end
pbPushFade pbPushFade
begin begin
yield if block_given? val = 0
val = yield if block_given?
nofadeout = true if val == 99999 # Ugly hack used by Town Map in the Bag/Pokégear
ensure ensure
pbPopFade pbPopFade
if !nofadeout if !nofadeout
for j in 0..numFrames (0..numFrames).each do |j|
col.set(0, 0, 0, (numFrames - j) * alphaDiff) col.set(0, 0, 0, (numFrames - j) * alphaDiff)
viewport.color = col viewport.color = col
Graphics.update Graphics.update
@@ -584,7 +589,7 @@ def pbFadeOutInWithUpdate(z,sprites,nofadeout=false)
viewport.z = z viewport.z = z
numFrames = (Graphics.frame_rate * 0.4).floor numFrames = (Graphics.frame_rate * 0.4).floor
alphaDiff = (255.0 / numFrames).ceil alphaDiff = (255.0 / numFrames).ceil
for j in 0..numFrames (0..numFrames).each do |j|
col.set(0, 0, 0, j * alphaDiff) col.set(0, 0, 0, j * alphaDiff)
viewport.color = col viewport.color = col
pbUpdateSpriteHash(sprites) pbUpdateSpriteHash(sprites)
@@ -597,7 +602,7 @@ def pbFadeOutInWithUpdate(z,sprites,nofadeout=false)
ensure ensure
pbPopFade pbPopFade
if !nofadeout if !nofadeout
for j in 0..numFrames (0..numFrames).each do |j|
col.set(0, 0, 0, (numFrames - j) * alphaDiff) col.set(0, 0, 0, (numFrames - j) * alphaDiff)
viewport.color = col viewport.color = col
pbUpdateSpriteHash(sprites) pbUpdateSpriteHash(sprites)
@@ -630,12 +635,12 @@ def pbFadeOutAndHide(sprites)
numFrames = (Graphics.frame_rate * 0.4).floor numFrames = (Graphics.frame_rate * 0.4).floor
alphaDiff = (255.0 / numFrames).ceil alphaDiff = (255.0 / numFrames).ceil
pbDeactivateWindows(sprites) { pbDeactivateWindows(sprites) {
for j in 0..numFrames (0..numFrames).each do |j|
pbSetSpritesToColor(sprites, Color.new(0, 0, 0, j * alphaDiff)) pbSetSpritesToColor(sprites, Color.new(0, 0, 0, j * alphaDiff))
(block_given?) ? yield : pbUpdateSpriteHash(sprites) (block_given?) ? yield : pbUpdateSpriteHash(sprites)
end end
} }
for i in sprites sprites.each do |i|
next if !i[1] next if !i[1]
next if pbDisposed?(i[1]) next if pbDisposed?(i[1])
visiblesprites[i[0]] = true if i[1].visible visiblesprites[i[0]] = true if i[1].visible
@@ -646,7 +651,7 @@ end
def pbFadeInAndShow(sprites, visiblesprites = nil) def pbFadeInAndShow(sprites, visiblesprites = nil)
if visiblesprites if visiblesprites
for i in visiblesprites visiblesprites.each do |i|
if i[1] && sprites[i[0]] && !pbDisposed?(sprites[i[0]]) if i[1] && sprites[i[0]] && !pbDisposed?(sprites[i[0]])
sprites[i[0]].visible = true sprites[i[0]].visible = true
end end
@@ -655,7 +660,7 @@ def pbFadeInAndShow(sprites,visiblesprites=nil)
numFrames = (Graphics.frame_rate * 0.4).floor numFrames = (Graphics.frame_rate * 0.4).floor
alphaDiff = (255.0 / numFrames).ceil alphaDiff = (255.0 / numFrames).ceil
pbDeactivateWindows(sprites) { pbDeactivateWindows(sprites) {
for j in 0..numFrames (0..numFrames).each do |j|
pbSetSpritesToColor(sprites, Color.new(0, 0, 0, ((numFrames - j) * alphaDiff))) pbSetSpritesToColor(sprites, Color.new(0, 0, 0, ((numFrames - j) * alphaDiff)))
(block_given?) ? yield : pbUpdateSpriteHash(sprites) (block_given?) ? yield : pbUpdateSpriteHash(sprites)
end end
@@ -666,8 +671,8 @@ end
# _activeStatuses_ is the result of a previous call to pbActivateWindows # _activeStatuses_ is the result of a previous call to pbActivateWindows
def pbRestoreActivations(sprites, activeStatuses) def pbRestoreActivations(sprites, activeStatuses)
return if !sprites || !activeStatuses return if !sprites || !activeStatuses
for k in activeStatuses.keys activeStatuses.each_key do |k|
if sprites[k] && sprites[k].is_a?(Window) && !pbDisposed?(sprites[k]) if sprites[k].is_a?(Window) && !pbDisposed?(sprites[k])
sprites[k].active = activeStatuses[k] ? true : false sprites[k].active = activeStatuses[k] ? true : false
end end
end end
@@ -689,8 +694,8 @@ end
def pbActivateWindow(sprites, key) def pbActivateWindow(sprites, key)
return if !sprites return if !sprites
activeStatuses = {} activeStatuses = {}
for i in sprites sprites.each do |i|
if i[1] && i[1].is_a?(Window) && !pbDisposed?(i[1]) if i[1].is_a?(Window) && !pbDisposed?(i[1])
activeStatuses[i[0]] = i[1].active activeStatuses[i[0]] = i[1].active
i[1].active = (i[0] == key) i[1].active = (i[0] == key)
end end
@@ -718,13 +723,13 @@ end
def addBackgroundPlane(sprites, planename, background, viewport = nil) def addBackgroundPlane(sprites, planename, background, viewport = nil)
sprites[planename] = AnimatedPlane.new(viewport) sprites[planename] = AnimatedPlane.new(viewport)
bitmapName = pbResolveBitmap("Graphics/Pictures/#{background}") bitmapName = pbResolveBitmap("Graphics/Pictures/#{background}")
if bitmapName==nil if bitmapName.nil?
# Plane should exist in any case # Plane should exist in any case
sprites[planename].bitmap = nil sprites[planename].bitmap = nil
sprites[planename].visible = false sprites[planename].visible = false
else else
sprites[planename].setBitmap(bitmapName) sprites[planename].setBitmap(bitmapName)
for spr in sprites.values sprites.each_value do |spr|
if spr.is_a?(Window) if spr.is_a?(Window)
spr.windowskin = nil spr.windowskin = nil
end end
@@ -740,13 +745,13 @@ end
# _viewport_ is a viewport to place the background in. # _viewport_ is a viewport to place the background in.
def addBackgroundOrColoredPlane(sprites, planename, background, color, viewport = nil) def addBackgroundOrColoredPlane(sprites, planename, background, color, viewport = nil)
bitmapName = pbResolveBitmap("Graphics/Pictures/#{background}") bitmapName = pbResolveBitmap("Graphics/Pictures/#{background}")
if bitmapName==nil if bitmapName.nil?
# Plane should exist in any case # Plane should exist in any case
sprites[planename] = ColoredPlane.new(color, viewport) sprites[planename] = ColoredPlane.new(color, viewport)
else else
sprites[planename] = AnimatedPlane.new(viewport) sprites[planename] = AnimatedPlane.new(viewport)
sprites[planename].setBitmap(bitmapName) sprites[planename].setBitmap(bitmapName)
for spr in sprites.values sprites.each_value do |spr|
if spr.is_a?(Window) if spr.is_a?(Window)
spr.windowskin = nil spr.windowskin = nil
end end
@@ -773,8 +778,8 @@ end
if !defined?(_INTL) if !defined?(_INTL)
def _INTL(*args) def _INTL(*args)
string = args[0].clone string = args[0].clone
for i in 1...args.length (1...args.length).each do |i|
string.gsub!(/\{#{i}\}/,"#{args[i]}") string.gsub!(/\{#{i}\}/, args[i].to_s)
end end
return string return string
end end
@@ -783,7 +788,7 @@ end
if !defined?(_ISPRINTF) if !defined?(_ISPRINTF)
def _ISPRINTF(*args) def _ISPRINTF(*args)
string = args[0].clone string = args[0].clone
for i in 1...args.length (1...args.length).each do |i|
string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m| string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m|
next sprintf("%" + $1, args[i]) next sprintf("%" + $1, args[i])
} }
@@ -795,8 +800,8 @@ end
if !defined?(_MAPINTL) if !defined?(_MAPINTL)
def _MAPINTL(*args) def _MAPINTL(*args)
string = args[1].clone string = args[1].clone
for i in 2...args.length (2...args.length).each do |i|
string.gsub!(/\{#{i}\}/,"#{args[i+1]}") string.gsub!(/\{#{i}\}/, args[i + 1].to_s)
end end
return string return string
end end

View File

@@ -6,7 +6,6 @@ class WindowCursorRect < Rect
def empty def empty
return unless needs_update?(0, 0, 0, 0) return unless needs_update?(0, 0, 0, 0)
set(0, 0, 0, 0) set(0, 0, 0, 0)
end end
@@ -16,9 +15,7 @@ class WindowCursorRect < Rect
def set(x, y, width, height) def set(x, y, width, height)
return unless needs_update?(x, y, width, height) return unless needs_update?(x, y, width, height)
super(x, y, width, height) super(x, y, width, height)
@window.width = @window.width @window.width = @window.width
end end
@@ -92,7 +89,7 @@ class Window
@cursorbitmap = nil @cursorbitmap = nil
@bgbitmap = nil @bgbitmap = nil
@viewport = viewport @viewport = viewport
for i in @spritekeys @spritekeys.each do |i|
@sprites[i] = Sprite.new(@viewport) @sprites[i] = Sprite.new(@viewport)
end end
@disposed = false @disposed = false
@@ -129,17 +126,17 @@ class Window
def dispose def dispose
if !self.disposed? if !self.disposed?
for i in @sprites @sprites.each do |i|
i[1].dispose if i[1] i[1]&.dispose
@sprites[i[0]] = nil @sprites[i[0]] = nil
end end
for i in 0...@sidebitmaps.length @sidebitmaps.each_with_index do |bitmap, i|
@sidebitmaps[i].dispose if @sidebitmaps[i] bitmap&.dispose
@sidebitmaps[i] = nil @sidebitmaps[i] = nil
end end
@blankcontents.dispose @blankcontents.dispose
@cursorbitmap.dispose if @cursorbitmap @cursorbitmap&.dispose
@backbitmap.dispose if @backbitmap @backbitmap&.dispose
@sprites.clear @sprites.clear
@sidebitmaps.clear @sidebitmaps.clear
@_windowskin = nil @_windowskin = nil
@@ -167,7 +164,7 @@ class Window
def viewport=(value) def viewport=(value)
@viewport = value @viewport = value
for i in @spritekeys @spritekeys.each do |i|
@sprites[i].dispose @sprites[i].dispose
if @sprites[i].is_a?(Sprite) if @sprites[i].is_a?(Sprite)
@sprites[i] = Sprite.new(@viewport) @sprites[i] = Sprite.new(@viewport)
@@ -194,7 +191,7 @@ class Window
def windowskin=(value) def windowskin=(value)
@_windowskin = value @_windowskin = value
if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128 if value.is_a?(Bitmap) && !value.disposed? && value.width == 128
@rpgvx = true @rpgvx = true
else else
@rpgvx = false @rpgvx = false
@@ -213,10 +210,10 @@ class Window
end end
def cursor_rect=(value) def cursor_rect=(value)
if !value if value
@cursor_rect.empty
else
@cursor_rect.set(value.x, value.y, value.width, value.height) @cursor_rect.set(value.x, value.y, value.width, value.height)
else
@cursor_rect.empty
end end
end end
@@ -289,7 +286,7 @@ class Window
def flash(color, duration) def flash(color, duration)
return if disposed? return if disposed?
for i in @sprites @sprites.each do |i|
i[1].flash(color, duration) i[1].flash(color, duration)
end end
end end
@@ -316,7 +313,7 @@ class Window
mustchange = true mustchange = true
end end
privRefresh if mustchange privRefresh if mustchange
for i in @sprites @sprites.each do |i|
i[1].update i[1].update
end end
end end
@@ -325,7 +322,7 @@ class Window
def ensureBitmap(bitmap, dwidth, dheight) def ensureBitmap(bitmap, dwidth, dheight)
if !bitmap || bitmap.disposed? || bitmap.width < dwidth || bitmap.height < dheight if !bitmap || bitmap.disposed? || bitmap.width < dwidth || bitmap.height < dheight
bitmap.dispose if bitmap bitmap&.dispose
bitmap = Bitmap.new([1, dwidth].max, [1, dheight].max) bitmap = Bitmap.new([1, dwidth].max, [1, dheight].max)
end end
return bitmap return bitmap
@@ -335,8 +332,12 @@ class Window
return if !srcbitmap || srcbitmap.disposed? return if !srcbitmap || srcbitmap.disposed?
left = dstrect.x left = dstrect.x
top = dstrect.y top = dstrect.y
y=0;loop do break unless y<dstrect.height y = 0
x=0;loop do break unless x<dstrect.width loop do
break unless y < dstrect.height
x = 0
loop do
break unless x < dstrect.width
dstbitmap.blt(x + left, y + top, srcbitmap, srcrect) dstbitmap.blt(x + left, y + top, srcbitmap, srcrect)
x += srcrect.width x += srcrect.width
end end
@@ -349,14 +350,14 @@ class Window
backopac = self.back_opacity * self.opacity / 255 backopac = self.back_opacity * self.opacity / 255
contopac = self.contents_opacity contopac = self.contents_opacity
cursoropac = @cursoropacity * contopac / 255 cursoropac = @cursoropacity * contopac / 255
for i in 0...4 4.times do |i|
@sprites["corner#{i}"].bitmap = @_windowskin @sprites["corner#{i}"].bitmap = @_windowskin
@sprites["scroll#{i}"].bitmap = @_windowskin @sprites["scroll#{i}"].bitmap = @_windowskin
end end
@sprites["pause"].bitmap = @_windowskin @sprites["pause"].bitmap = @_windowskin
@sprites["contents"].bitmap = @contents @sprites["contents"].bitmap = @contents
if @_windowskin && !@_windowskin.disposed? if @_windowskin && !@_windowskin.disposed?
for i in 0...4 4.times do |i|
@sprites["corner#{i}"].opacity = @opacity @sprites["corner#{i}"].opacity = @opacity
@sprites["corner#{i}"].tone = @tone @sprites["corner#{i}"].tone = @tone
@sprites["corner#{i}"].color = @color @sprites["corner#{i}"].color = @color
@@ -373,7 +374,7 @@ class Window
@sprites["scroll#{i}"].color = @color @sprites["scroll#{i}"].color = @color
@sprites["scroll#{i}"].visible = @visible @sprites["scroll#{i}"].visible = @visible
end end
for i in ["back","cursor","pause","contents"] ["back", "cursor", "pause", "contents"].each do |i|
@sprites[i].color = @color @sprites[i].color = @color
@sprites[i].tone = @tone @sprites[i].tone = @tone
@sprites[i].blend_type = @blend_type @sprites[i].blend_type = @blend_type
@@ -395,7 +396,7 @@ class Window
@sprites["scroll3"].visible = @visible && hascontents && @sprites["scroll3"].visible = @visible && hascontents &&
(@contents.height - @oy) > @height - 32 (@contents.height - @oy) > @height - 32
else else
for i in 0...4 4.times do |i|
@sprites["corner#{i}"].visible = false @sprites["corner#{i}"].visible = false
@sprites["side#{i}"].visible = false @sprites["side#{i}"].visible = false
@sprites["scroll#{i}"].visible = false @sprites["scroll#{i}"].visible = false
@@ -409,7 +410,7 @@ class Window
@sprites["pause"].visible = false @sprites["pause"].visible = false
@sprites["cursor"].visible = false @sprites["cursor"].visible = false
end end
for i in @sprites @sprites.each do |i|
i[1].z = @z i[1].z = @z
end end
if @rpgvx if @rpgvx
@@ -432,10 +433,10 @@ class Window
backRect = Rect.new(0, 0, 128, 128) backRect = Rect.new(0, 0, 128, 128)
blindsRect = nil blindsRect = nil
end end
@sprites["corner0"].src_rect.set(trimX,trimY+0,16,16); @sprites["corner0"].src_rect.set(trimX, trimY + 0, 16, 16)
@sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16); @sprites["corner1"].src_rect.set(trimX + 48, trimY + 0, 16, 16)
@sprites["corner2"].src_rect.set(trimX,trimY+48,16,16); @sprites["corner2"].src_rect.set(trimX, trimY + 48, 16, 16)
@sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16); @sprites["corner3"].src_rect.set(trimX + 48, trimY + 48, 16, 16)
@sprites["scroll0"].src_rect.set(trimX + 24, trimY + 16, 16, 8) # up @sprites["scroll0"].src_rect.set(trimX + 24, trimY + 16, 16, 8) # up
@sprites["scroll3"].src_rect.set(trimX + 24, trimY + 40, 16, 8) # down @sprites["scroll3"].src_rect.set(trimX + 24, trimY + 40, 16, 8) # down
@sprites["scroll1"].src_rect.set(trimX + 16, trimY + 24, 8, 16) # left @sprites["scroll1"].src_rect.set(trimX + 16, trimY + 24, 8, 16) # left
@@ -457,15 +458,14 @@ class Window
trimX + 32, trimY + 64, trimX + 32, trimY + 64,
trimX + 48, trimY + 64, trimX + 48, trimY + 64,
trimX + 32, trimY + 80, trimX + 32, trimY + 80,
trimX+48,trimY+80, trimX + 48, trimY + 80
] ]
pauseWidth = 16 pauseWidth = 16
pauseHeight = 16 pauseHeight = 16
@sprites["pause"].src_rect.set( @sprites["pause"].src_rect.set(pauseRects[@pauseframe * 2],
pauseRects[@pauseframe*2], pauseRects[(@pauseframe * 2) + 1],
pauseRects[@pauseframe*2+1], pauseWidth,
pauseWidth,pauseHeight pauseHeight)
)
@sprites["pause"].x = @x + (@width / 2) - (pauseWidth / 2) @sprites["pause"].x = @x + (@width / 2) - (pauseWidth / 2)
@sprites["pause"].y = @y + @height - 16 # 16 refers to skin margin @sprites["pause"].y = @y + @height - 16 # 16 refers to skin margin
@sprites["contents"].x = @x + 16 @sprites["contents"].x = @x + 16
@@ -486,13 +486,13 @@ class Window
@sprites["side2"].y = @y + 16 @sprites["side2"].y = @y + 16
@sprites["side3"].x = @x + 16 @sprites["side3"].x = @x + 16
@sprites["side3"].y = @y + @height - 16 @sprites["side3"].y = @y + @height - 16
@sprites["scroll0"].x = @x+@width / 2 - 8 @sprites["scroll0"].x = @x + (@width / 2) - 8
@sprites["scroll0"].y = @y + 8 @sprites["scroll0"].y = @y + 8
@sprites["scroll1"].x = @x + 8 @sprites["scroll1"].x = @x + 8
@sprites["scroll1"].y = @y+@height / 2 - 8 @sprites["scroll1"].y = @y + (@height / 2) - 8
@sprites["scroll2"].x = @x + @width - 16 @sprites["scroll2"].x = @x + @width - 16
@sprites["scroll2"].y = @y+@height / 2 - 8 @sprites["scroll2"].y = @y + (@height / 2) - 8
@sprites["scroll3"].x = @x+@width / 2 - 8 @sprites["scroll3"].x = @x + (@width / 2) - 8
@sprites["scroll3"].y = @y + @height - 16 @sprites["scroll3"].y = @y + @height - 16
@sprites["back"].x = @x + 2 @sprites["back"].x = @x + 2
@sprites["back"].y = @y + 2 @sprites["back"].y = @y + 2
@@ -522,39 +522,33 @@ class Window
@cursorbitmap.clear @cursorbitmap.clear
@sprites["cursor"].bitmap = @cursorbitmap @sprites["cursor"].bitmap = @cursorbitmap
@sprites["cursor"].src_rect.set(0, 0, width, height) @sprites["cursor"].src_rect.set(0, 0, width, height)
rect = Rect.new(margin,margin, rect = Rect.new(margin, margin, width - fullmargin, height - fullmargin)
width - fullmargin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8]) @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8])
@cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4]) # top left @cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4]) # top left
@cursorbitmap.blt(width - margin, 0, @_windowskin, cursorrects[5]) # top right @cursorbitmap.blt(width - margin, 0, @_windowskin, cursorrects[5]) # top right
@cursorbitmap.blt(0, height - margin, @_windowskin, cursorrects[6]) # bottom right @cursorbitmap.blt(0, height - margin, @_windowskin, cursorrects[6]) # bottom right
@cursorbitmap.blt(width - margin, height - margin, @_windowskin, cursorrects[7]) # bottom left @cursorbitmap.blt(width - margin, height - margin, @_windowskin, cursorrects[7]) # bottom left
rect = Rect.new(margin, 0, rect = Rect.new(margin, 0, width - fullmargin, margin)
width - fullmargin, margin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0]) @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0])
rect = Rect.new(0, margin, rect = Rect.new(0, margin, margin, height - fullmargin)
margin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1]) @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1])
rect = Rect.new(width - margin, margin, rect = Rect.new(width - margin, margin, margin, height - fullmargin)
margin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2]) @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2])
rect = Rect.new(margin, height-margin, rect = Rect.new(margin, height - margin, width - fullmargin, margin)
width - fullmargin, margin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3]) @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3])
else else
@sprites["cursor"].visible = false @sprites["cursor"].visible = false
@sprites["cursor"].src_rect.set(0, 0, 0, 0) @sprites["cursor"].src_rect.set(0, 0, 0, 0)
end end
for i in 0...4 4.times do |i|
dwidth = (i==0 || i==3) ? @width-32 : 16 dwidth = [0, 3].include?(i) ? @width - 32 : 16
dheight = (i==0 || i==3) ? 16 : @height-32 dheight = [0, 3].include?(i) ? 16 : @height - 32
@sidebitmaps[i] = ensureBitmap(@sidebitmaps[i], dwidth, dheight) @sidebitmaps[i] = ensureBitmap(@sidebitmaps[i], dwidth, dheight)
@sprites["side#{i}"].bitmap = @sidebitmaps[i] @sprites["side#{i}"].bitmap = @sidebitmaps[i]
@sprites["side#{i}"].src_rect.set(0, 0, dwidth, dheight) @sprites["side#{i}"].src_rect.set(0, 0, dwidth, dheight)
@sidebitmaps[i].clear @sidebitmaps[i].clear
if sideRects[i].width > 0 && sideRects[i].height > 0 if sideRects[i].width > 0 && sideRects[i].height > 0
@sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect, @sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect, @_windowskin, sideRects[i])
@_windowskin,sideRects[i])
end end
end end
backwidth = @width - 4 backwidth = @width - 4
@@ -577,24 +571,24 @@ class Window
@sprites["back"].src_rect.set(0, 0, 0, 0) @sprites["back"].src_rect.set(0, 0, 0, 0)
end end
end end
if @openness!=255 if @openness == 255
opn=@openness/255.0 @spritekeys.each do |k|
for k in @spritekeys
sprite = @sprites[k] sprite = @sprites[k]
ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height sprite.zoom_y = 1.0
end
else
opn = @openness / 255.0
@spritekeys.each do |k|
sprite = @sprites[k]
ratio = (@height <= 0) ? 0 : (sprite.y - @y) / @height.to_f
sprite.zoom_y = opn sprite.zoom_y = opn
sprite.oy = 0 sprite.oy = 0
sprite.y = (@y + (@height / 2.0) + (@height * ratio * opn) - (@height / 2 * opn)).floor sprite.y = (@y + (@height / 2.0) + (@height * ratio * opn) - (@height / 2 * opn)).floor
end end
else
for k in @spritekeys
sprite=@sprites[k]
sprite.zoom_y=1.0
end
end end
i = 0 i = 0
# Ensure Z order # Ensure Z order
for k in @spritekeys @spritekeys.each do |k|
sprite = @sprites[k] sprite = @sprites[k]
y = sprite.y y = sprite.y
sprite.y = i sprite.y = i

View File

@@ -66,7 +66,7 @@ class SpriteWindow < Window
@sidebitmaps = [nil, nil, nil, nil] @sidebitmaps = [nil, nil, nil, nil]
@cursorbitmap = nil @cursorbitmap = nil
@bgbitmap = nil @bgbitmap = nil
for i in @spritekeys @spritekeys.each do |i|
@sprites[i] = Sprite.new(@viewport) @sprites[i] = Sprite.new(@viewport)
end end
@disposed = false @disposed = false
@@ -112,17 +112,17 @@ class SpriteWindow < Window
def dispose def dispose
if !self.disposed? if !self.disposed?
for i in @sprites @sprites.each do |i|
i[1].dispose if i[1] i[1]&.dispose
@sprites[i[0]] = nil @sprites[i[0]] = nil
end end
for i in 0...@sidebitmaps.length @sidebitmaps.each_with_index do |bitmap, i|
@sidebitmaps[i].dispose if @sidebitmaps[i] bitmap&.dispose
@sidebitmaps[i] = nil @sidebitmaps[i] = nil
end end
@blankcontents.dispose @blankcontents.dispose
@cursorbitmap.dispose if @cursorbitmap @cursorbitmap&.dispose
@backbitmap.dispose if @backbitmap @backbitmap&.dispose
@sprites.clear @sprites.clear
@sidebitmaps.clear @sidebitmaps.clear
@_windowskin = nil @_windowskin = nil
@@ -142,10 +142,8 @@ class SpriteWindow < Window
def viewport=(value) def viewport=(value)
@viewport = value @viewport = value
for i in @spritekeys @spritekeys.each do |i|
@sprites[i].dispose if @sprites[i] @sprites[i]&.dispose
end
for i in @spritekeys
if @sprites[i].is_a?(Sprite) if @sprites[i].is_a?(Sprite)
@sprites[i] = Sprite.new(@viewport) @sprites[i] = Sprite.new(@viewport)
else else
@@ -191,10 +189,10 @@ class SpriteWindow < Window
end end
def cursor_rect=(value) def cursor_rect=(value)
if !value if value
@cursor_rect.empty
else
@cursor_rect.set(value.x, value.y, value.width, value.height) @cursor_rect.set(value.x, value.y, value.width, value.height)
else
@cursor_rect.empty
end end
end end
@@ -290,7 +288,7 @@ class SpriteWindow < Window
def flash(color, duration) def flash(color, duration)
return if disposed? return if disposed?
@flash = duration + 1 @flash = duration + 1
for i in @sprites @sprites.each do |i|
i[1].flash(color, duration) i[1].flash(color, duration)
end end
end end
@@ -306,11 +304,10 @@ class SpriteWindow < Window
@cursoropacity += 8 @cursoropacity += 8
@cursorblink = 0 if @cursoropacity >= 255 @cursorblink = 0 if @cursoropacity >= 255
end end
privRefreshCursor
else else
@cursoropacity = 128 @cursoropacity = 128
privRefreshCursor
end end
privRefreshCursor
if @pause if @pause
oldpauseframe = @pauseframe oldpauseframe = @pauseframe
oldpauseopacity = @pauseopacity oldpauseopacity = @pauseopacity
@@ -320,7 +317,7 @@ class SpriteWindow < Window
end end
privRefresh if mustchange privRefresh if mustchange
if @flash > 0 if @flash > 0
for i in @sprites.values @sprites.each_value do |i|
i.update i.update
end end
@flash -= 1 @flash -= 1
@@ -361,7 +358,7 @@ class SpriteWindow < Window
@trim = [16, 16, 16, 16] @trim = [16, 16, 16, 16]
end end
else else
if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128 if value.is_a?(Bitmap) && !value.disposed? && value.width == 128
@rpgvx = true @rpgvx = true
else else
@rpgvx = false @rpgvx = false
@@ -445,7 +442,7 @@ class SpriteWindow < Window
def ensureBitmap(bitmap, dwidth, dheight) def ensureBitmap(bitmap, dwidth, dheight)
if !bitmap || bitmap.disposed? || bitmap.width < dwidth || bitmap.height < dheight if !bitmap || bitmap.disposed? || bitmap.width < dwidth || bitmap.height < dheight
bitmap.dispose if bitmap bitmap&.dispose
bitmap = Bitmap.new([1, dwidth].max, [1, dheight].max) bitmap = Bitmap.new([1, dwidth].max, [1, dheight].max)
end end
return bitmap return bitmap
@@ -455,8 +452,12 @@ class SpriteWindow < Window
return if !srcbitmap || srcbitmap.disposed? return if !srcbitmap || srcbitmap.disposed?
left = dstrect.x left = dstrect.x
top = dstrect.y top = dstrect.y
y=0;loop do break unless y<dstrect.height y = 0
x=0;loop do break unless x<dstrect.width loop do
break unless y < dstrect.height
x = 0
loop do
break unless x < dstrect.width
dstbitmap.blt(x + left, y + top, srcbitmap, srcrect) dstbitmap.blt(x + left, y + top, srcbitmap, srcrect)
x += srcrect.width x += srcrect.width
end end
@@ -476,20 +477,20 @@ class SpriteWindow < Window
contopac = self.contents_opacity contopac = self.contents_opacity
cursoropac = @cursoropacity * contopac / 255 cursoropac = @cursoropacity * contopac / 255
haveskin = @_windowskin && !@_windowskin.disposed? haveskin = @_windowskin && !@_windowskin.disposed?
for i in 0...4 4.times do |i|
@sprites["corner#{i}"].bitmap = @_windowskin @sprites["corner#{i}"].bitmap = @_windowskin
@sprites["scroll#{i}"].bitmap = @_windowskin @sprites["scroll#{i}"].bitmap = @_windowskin
end end
@sprites["pause"].bitmap = @_windowskin @sprites["pause"].bitmap = @_windowskin
@sprites["contents"].bitmap = @contents @sprites["contents"].bitmap = @contents
if haveskin if haveskin
for i in 0...4 4.times do |i|
@sprites["corner#{i}"].opacity=@opacity @sprites["corner#{i}"].opacity = backopac
@sprites["corner#{i}"].tone = @tone @sprites["corner#{i}"].tone = @tone
@sprites["corner#{i}"].color = @color @sprites["corner#{i}"].color = @color
@sprites["corner#{i}"].visible = @visible @sprites["corner#{i}"].visible = @visible
@sprites["corner#{i}"].blend_type = @blend_type @sprites["corner#{i}"].blend_type = @blend_type
@sprites["side#{i}"].opacity=@opacity @sprites["side#{i}"].opacity = backopac
@sprites["side#{i}"].tone = @tone @sprites["side#{i}"].tone = @tone
@sprites["side#{i}"].color = @color @sprites["side#{i}"].color = @color
@sprites["side#{i}"].blend_type = @blend_type @sprites["side#{i}"].blend_type = @blend_type
@@ -500,7 +501,7 @@ class SpriteWindow < Window
@sprites["scroll#{i}"].visible = @visible @sprites["scroll#{i}"].visible = @visible
@sprites["scroll#{i}"].blend_type = @blend_type @sprites["scroll#{i}"].blend_type = @blend_type
end end
for i in ["back","cursor","pause","contents"] ["back", "cursor", "pause", "contents"].each do |i|
@sprites[i].color = @color @sprites[i].color = @color
@sprites[i].tone = @tone @sprites[i].tone = @tone
@sprites[i].blend_type = @blend_type @sprites[i].blend_type = @blend_type
@@ -523,7 +524,7 @@ class SpriteWindow < Window
@sprites["scroll2"].visible = false @sprites["scroll2"].visible = false
@sprites["scroll3"].visible = false @sprites["scroll3"].visible = false
else else
for i in 0...4 4.times do |i|
@sprites["corner#{i}"].visible = false @sprites["corner#{i}"].visible = false
@sprites["side#{i}"].visible = false @sprites["side#{i}"].visible = false
@sprites["scroll#{i}"].visible = false @sprites["scroll#{i}"].visible = false
@@ -537,7 +538,7 @@ class SpriteWindow < Window
@sprites["pause"].visible = false @sprites["pause"].visible = false
@sprites["cursor"].visible = false @sprites["cursor"].visible = false
end end
for i in @spritekeys @spritekeys.each do |i|
@sprites[i].z = @z @sprites[i].z = @z
end end
if (@compat & CompatBits::CorrectZ) > 0 && @skinformat == 0 && !@rpgvx if (@compat & CompatBits::CorrectZ) > 0 && @skinformat == 0 && !@rpgvx
@@ -567,33 +568,29 @@ class SpriteWindow < Window
blindsRect = nil blindsRect = nil
end end
if @_windowskin && !@_windowskin.disposed? if @_windowskin && !@_windowskin.disposed?
@sprites["corner0"].src_rect.set(trimX,trimY+0,16,16); @sprites["corner0"].src_rect.set(trimX, trimY + 0, 16, 16)
@sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16); @sprites["corner1"].src_rect.set(trimX + 48, trimY + 0, 16, 16)
@sprites["corner2"].src_rect.set(trimX,trimY+48,16,16); @sprites["corner2"].src_rect.set(trimX, trimY + 48, 16, 16)
@sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16); @sprites["corner3"].src_rect.set(trimX + 48, trimY + 48, 16, 16)
@sprites["scroll0"].src_rect.set(trimX + 24, trimY + 16, 16, 8) # up @sprites["scroll0"].src_rect.set(trimX + 24, trimY + 16, 16, 8) # up
@sprites["scroll3"].src_rect.set(trimX + 24, trimY + 40, 16, 8) # down @sprites["scroll3"].src_rect.set(trimX + 24, trimY + 40, 16, 8) # down
@sprites["scroll1"].src_rect.set(trimX + 16, trimY + 24, 8, 16) # left @sprites["scroll1"].src_rect.set(trimX + 16, trimY + 24, 8, 16) # left
@sprites["scroll2"].src_rect.set(trimX + 40, trimY + 24, 8, 16) # right @sprites["scroll2"].src_rect.set(trimX + 40, trimY + 24, 8, 16) # right
cursorX = trimX cursorX = trimX
cursorY = trimY + 64 cursorY = trimY + 64
sideRects=[ sideRects = [Rect.new(trimX + 16, trimY + 0, 32, 16),
Rect.new(trimX+16,trimY+0,32,16),
Rect.new(trimX, trimY + 16, 16, 32), Rect.new(trimX, trimY + 16, 16, 32),
Rect.new(trimX + 48, trimY + 16, 16, 32), Rect.new(trimX + 48, trimY + 16, 16, 32),
Rect.new(trimX+16,trimY+48,32,16) Rect.new(trimX + 16, trimY + 48, 32, 16)]
] pauseRects = [trimX + 32, trimY + 64,
pauseRects=[
trimX+32,trimY+64,
trimX + 48, trimY + 64, trimX + 48, trimY + 64,
trimX + 32, trimY + 80, trimX + 32, trimY + 80,
trimX+48,trimY+80, trimX + 48, trimY + 80]
]
pauseWidth = 16 pauseWidth = 16
pauseHeight = 16 pauseHeight = 16
@sprites["pause"].src_rect.set( @sprites["pause"].src_rect.set(
pauseRects[@pauseframe * 2], pauseRects[@pauseframe * 2],
pauseRects[@pauseframe*2+1], pauseRects[(@pauseframe * 2) + 1],
pauseWidth, pauseHeight pauseWidth, pauseHeight
) )
end end
@@ -613,12 +610,11 @@ class SpriteWindow < Window
endX = (!@_windowskin || @_windowskin.disposed?) ? @skinrect.x : @_windowskin.width - cx endX = (!@_windowskin || @_windowskin.disposed?) ? @skinrect.x : @_windowskin.width - cx
# height of bottom end of window # height of bottom end of window
endY = (!@_windowskin || @_windowskin.disposed?) ? @skinrect.y : @_windowskin.height - cy endY = (!@_windowskin || @_windowskin.disposed?) ? @skinrect.y : @_windowskin.height - cy
@sprites["corner0"].src_rect.set(0,0,startX,startY); @sprites["corner0"].src_rect.set(0, 0, startX, startY)
@sprites["corner1"].src_rect.set(cx,0,endX,startY); @sprites["corner1"].src_rect.set(cx, 0, endX, startY)
@sprites["corner2"].src_rect.set(0,cy,startX,endY); @sprites["corner2"].src_rect.set(0, cy, startX, endY)
@sprites["corner3"].src_rect.set(cx,cy,endX,endY); @sprites["corner3"].src_rect.set(cx, cy, endX, endY)
backRect=Rect.new(@skinrect.x,@skinrect.y, backRect = Rect.new(@skinrect.x, @skinrect.y, @skinrect.width, @skinrect.height)
@skinrect.width,@skinrect.height);
blindsRect = nil blindsRect = nil
sideRects = [ sideRects = [
Rect.new(startX, 0, @skinrect.width, startY), # side0 (top) Rect.new(startX, 0, @skinrect.width, startY), # side0 (top)
@@ -635,16 +631,14 @@ class SpriteWindow < Window
end end
@sprites["contents"].x = @x + trimStartX @sprites["contents"].x = @x + trimStartX
@sprites["contents"].y = @y + trimStartY @sprites["contents"].y = @y + trimStartY
if (@compat & CompatBits::ShowScrollArrows)>0 && @skinformat==0 if (@compat & CompatBits::ShowScrollArrows) > 0 && @skinformat == 0 &&
# Compatibility mode: Make scroll arrows visible @_windowskin && !@_windowskin.disposed? &&
if @skinformat==0 && @_windowskin && !@_windowskin.disposed? &&
@contents && !@contents.disposed? @contents && !@contents.disposed?
@sprites["scroll0"].visible = @visible && hascontents && @oy > 0 @sprites["scroll0"].visible = @visible && hascontents && @oy > 0
@sprites["scroll1"].visible = @visible && hascontents && @ox > 0 @sprites["scroll1"].visible = @visible && hascontents && @ox > 0
@sprites["scroll2"].visible = @visible && (@contents.width - @ox) > @width - trimWidth @sprites["scroll2"].visible = @visible && (@contents.width - @ox) > @width - trimWidth
@sprites["scroll3"].visible = @visible && (@contents.height - @oy) > @height - trimHeight @sprites["scroll3"].visible = @visible && (@contents.height - @oy) > @height - trimHeight
end end
end
if @_windowskin && !@_windowskin.disposed? if @_windowskin && !@_windowskin.disposed?
borderX = startX + endX borderX = startX + endX
borderY = startY + endY borderY = startY + endY
@@ -664,13 +658,13 @@ class SpriteWindow < Window
@sprites["side2"].y = @y + startY @sprites["side2"].y = @y + startY
@sprites["side3"].x = @x + startX @sprites["side3"].x = @x + startX
@sprites["side3"].y = @y + @height - endY @sprites["side3"].y = @y + @height - endY
@sprites["scroll0"].x = @x+@width / 2 - 8 @sprites["scroll0"].x = @x + (@width / 2) - 8
@sprites["scroll0"].y = @y + 8 @sprites["scroll0"].y = @y + 8
@sprites["scroll1"].x = @x + 8 @sprites["scroll1"].x = @x + 8
@sprites["scroll1"].y = @y+@height / 2 - 8 @sprites["scroll1"].y = @y + (@height / 2) - 8
@sprites["scroll2"].x = @x + @width - 16 @sprites["scroll2"].x = @x + @width - 16
@sprites["scroll2"].y = @y+@height / 2 - 8 @sprites["scroll2"].y = @y + (@height / 2) - 8
@sprites["scroll3"].x = @x+@width / 2 - 8 @sprites["scroll3"].x = @x + (@width / 2) - 8
@sprites["scroll3"].y = @y + @height - 16 @sprites["scroll3"].y = @y + @height - 16
@sprites["cursor"].x = @x + startX + @cursor_rect.x @sprites["cursor"].x = @x + startX + @cursor_rect.x
@sprites["cursor"].y = @y + startY + @cursor_rect.y @sprites["cursor"].y = @y + startY + @cursor_rect.y
@@ -729,7 +723,7 @@ class SpriteWindow < Window
@sprites["cursor"].src_rect.set(0, 0, 0, 0) @sprites["cursor"].src_rect.set(0, 0, 0, 0)
end end
end end
for i in 0..3 4.times do |i|
case i case i
when 0 when 0
dwidth = @width - startX - endX dwidth = @width - startX - endX
@@ -785,26 +779,26 @@ class SpriteWindow < Window
@sprites["back"].src_rect.set(0, 0, 0, 0) @sprites["back"].src_rect.set(0, 0, 0, 0)
end end
end end
if @openness!=255 if @openness == 255
opn=@openness/255.0 @spritekeys.each do |k|
for k in @spritekeys
sprite = @sprites[k] sprite = @sprites[k]
ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height sprite.zoom_x = 1.0
sprite.zoom_y = 1.0
end
else
opn = @openness / 255.0
@spritekeys.each do |k|
sprite = @sprites[k]
ratio = (@height <= 0) ? 0 : (sprite.y - @y) / @height.to_f
sprite.zoom_y = opn sprite.zoom_y = opn
sprite.zoom_x = 1.0 sprite.zoom_x = 1.0
sprite.oy = 0 sprite.oy = 0
sprite.y = (@y + (@height / 2.0) + (@height * ratio * opn) - (@height / 2 * opn)).floor sprite.y = (@y + (@height / 2.0) + (@height * ratio * opn) - (@height / 2 * opn)).floor
end end
else
for k in @spritekeys
sprite=@sprites[k]
sprite.zoom_x=1.0
sprite.zoom_y=1.0
end
end end
i = 0 i = 0
# Ensure Z order # Ensure Z order
for k in @spritekeys @spritekeys.each do |k|
sprite = @sprites[k] sprite = @sprites[k]
y = sprite.y y = sprite.y
sprite.y = i sprite.y = i
@@ -834,19 +828,19 @@ class SpriteWindow_Base < SpriteWindow
self.width = width self.width = width
self.height = height self.height = height
self.z = 100 self.z = 100
@curframe=MessageConfig.pbGetSystemFrame() @curframe = MessageConfig.pbGetSystemFrame
@curfont=MessageConfig.pbGetSystemFontName() @curfont = MessageConfig.pbGetSystemFontName
@sysframe = AnimatedBitmap.new(@curframe) @sysframe = AnimatedBitmap.new(@curframe)
RPG::Cache.retain(@curframe) if @curframe && !@curframe.empty? RPG::Cache.retain(@curframe) if @curframe && !@curframe.empty?
@customskin = nil @customskin = nil
__setWindowskin(@sysframe.bitmap) __setWindowskin(@sysframe.bitmap)
__resolveSystemFrame() __resolveSystemFrame
pbSetSystemFont(self.contents) if self.contents pbSetSystemFont(self.contents) if self.contents
end end
def __setWindowskin(skin) def __setWindowskin(skin)
if skin && (skin.width==192 && skin.height==128) || # RPGXP Windowskin if skin && ((skin.width == 192 && skin.height == 128) || # RPGXP Windowskin
(skin.width==128 && skin.height==128) # RPGVX Windowskin (skin.width == 128 && skin.height == 128)) # RPGVX Windowskin
self.skinformat = 0 self.skinformat = 0
else else
self.skinformat = 1 self.skinformat = 1
@@ -857,7 +851,7 @@ class SpriteWindow_Base < SpriteWindow
def __resolveSystemFrame def __resolveSystemFrame
if self.skinformat == 1 if self.skinformat == 1
if !@resolvedFrame if !@resolvedFrame
@resolvedFrame=MessageConfig.pbGetSystemFrame() @resolvedFrame = MessageConfig.pbGetSystemFrame
@resolvedFrame.sub!(/\.[^\.\/\\]+$/, "") @resolvedFrame.sub!(/\.[^\.\/\\]+$/, "")
end end
self.loadSkinFile("#{@resolvedFrame}.txt") if @resolvedFrame != "" self.loadSkinFile("#{@resolvedFrame}.txt") if @resolvedFrame != ""
@@ -865,7 +859,7 @@ class SpriteWindow_Base < SpriteWindow
end end
def setSkin(skin) # Filename of windowskin to apply. Supports XP, VX, and animated skins. def setSkin(skin) # Filename of windowskin to apply. Supports XP, VX, and animated skins.
@customskin.dispose if @customskin @customskin&.dispose
@customskin = nil @customskin = nil
resolvedName = pbResolveBitmap(skin) resolvedName = pbResolveBitmap(skin)
return if nil_or_empty?(resolvedName) return if nil_or_empty?(resolvedName)
@@ -879,10 +873,10 @@ class SpriteWindow_Base < SpriteWindow
end end
def setSystemFrame def setSystemFrame
@customskin.dispose if @customskin @customskin&.dispose
@customskin = nil @customskin = nil
__setWindowskin(@sysframe.bitmap) __setWindowskin(@sysframe.bitmap)
__resolveSystemFrame() __resolveSystemFrame
end end
def update def update
@@ -900,23 +894,23 @@ class SpriteWindow_Base < SpriteWindow
end end
end end
end end
if @curframe!=MessageConfig.pbGetSystemFrame() if @curframe != MessageConfig.pbGetSystemFrame
@curframe=MessageConfig.pbGetSystemFrame() @curframe = MessageConfig.pbGetSystemFrame
if @sysframe && !@customskin if @sysframe && !@customskin
@sysframe.dispose if @sysframe @sysframe&.dispose
@sysframe = AnimatedBitmap.new(@curframe) @sysframe = AnimatedBitmap.new(@curframe)
RPG::Cache.retain(@curframe) if @curframe && !@curframe.empty? RPG::Cache.retain(@curframe) if @curframe && !@curframe.empty?
@resolvedFrame = nil @resolvedFrame = nil
__setWindowskin(@sysframe.bitmap) __setWindowskin(@sysframe.bitmap)
__resolveSystemFrame() __resolveSystemFrame
end end
begin begin
refresh refresh
rescue NoMethodError rescue NoMethodError
end end
end end
if @curfont!=MessageConfig.pbGetSystemFontName() if @curfont != MessageConfig.pbGetSystemFontName
@curfont=MessageConfig.pbGetSystemFontName() @curfont = MessageConfig.pbGetSystemFontName
if self.contents && !self.contents.disposed? if self.contents && !self.contents.disposed?
pbSetSystemFont(self.contents) pbSetSystemFont(self.contents)
end end
@@ -928,9 +922,9 @@ class SpriteWindow_Base < SpriteWindow
end end
def dispose def dispose
self.contents.dispose if self.contents self.contents&.dispose
@sysframe.dispose @sysframe.dispose
@customskin.dispose if @customskin @customskin&.dispose
super super
end end
end end

View File

@@ -101,7 +101,7 @@ class Window_UnformattedTextPokemon < SpriteWindow_Base
self.contents = pbDoEnsureBitmap(self.contents, self.width - self.borderX, self.contents = pbDoEnsureBitmap(self.contents, self.width - self.borderX,
self.height - self.borderY) self.height - self.borderY)
self.contents.clear self.contents.clear
drawTextEx(self.contents,0,4,self.contents.width,0, drawTextEx(self.contents, 0, -2, self.contents.width, 0, # TEXT OFFSET
@text.gsub(/\r/, ""), @baseColor, @shadowColor) @text.gsub(/\r/, ""), @baseColor, @shadowColor)
end end
end end
@@ -134,7 +134,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
@lastDrawnChar = -1 @lastDrawnChar = -1
@fmtchars = [] @fmtchars = []
@frameskipChanged = false @frameskipChanged = false
@frameskip = MessageConfig.pbGetTextSpeed() @frameskip = MessageConfig.pbGetTextSpeed
super(0, 0, 33, 33) super(0, 0, 33, 33)
@pausesprite = nil @pausesprite = nil
@text = "" @text = ""
@@ -160,7 +160,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
def dispose def dispose
return if disposed? return if disposed?
@pausesprite.dispose if @pausesprite @pausesprite&.dispose
@pausesprite = nil @pausesprite = nil
super super
end end
@@ -235,7 +235,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
cwidth = (maxwidth < 0) ? Graphics.width : maxwidth cwidth = (maxwidth < 0) ? Graphics.width : maxwidth
chars = getFormattedTextForDims(self.contents, 0, 0, chars = getFormattedTextForDims(self.contents, 0, 0,
cwidth - self.borderX - 2 - 6, -1, text, @lineHeight, true) cwidth - self.borderX - 2 - 6, -1, text, @lineHeight, true)
for ch in chars chars.each do |ch|
dims[0] = [dims[0], ch[1] + ch[3]].max dims[0] = [dims[0], ch[1] + ch[3]].max
dims[1] = [dims[1], ch[2] + ch[4]].max dims[1] = [dims[1], ch[2] + ch[4]].max
end end
@@ -312,12 +312,11 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
self.width - self.borderX - SpriteWindow_Base::TEXTPADDING, -1, self.width - self.borderX - SpriteWindow_Base::TEXTPADDING, -1,
shadowctag(@baseColor, @shadowColor) + value, 32, true) shadowctag(@baseColor, @shadowColor) + value, 32, true)
@oldfont = self.contents.font.clone @oldfont = self.contents.font.clone
for ch in fmt fmt.each do |ch|
chx = ch[1] + ch[3] chx = ch[1] + ch[3]
chy = ch[2] + ch[4] chy = ch[2] + ch[4]
width = chx if width < chx width = chx if width < chx
height = chy if height < chy height = chy if height < chy
ch[2] += 4
if !ch[5] && ch[0] == "\n" if !ch[5] && ch[0] == "\n"
numlines += 1 numlines += 1
if numlines >= visiblelines if numlines >= visiblelines
@@ -340,12 +339,11 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
self.width - self.borderX - SpriteWindow_Base::TEXTPADDING, -1, self.width - self.borderX - SpriteWindow_Base::TEXTPADDING, -1,
shadowctag(@baseColor, @shadowColor) + value, 32, true) shadowctag(@baseColor, @shadowColor) + value, 32, true)
@oldfont = self.contents.font.clone @oldfont = self.contents.font.clone
for ch in @fmtchars @fmtchars.each do |ch|
chx = ch[1] + ch[3] chx = ch[1] + ch[3]
chy = ch[2] + ch[4] chy = ch[2] + ch[4]
width = chx if width < chx width = chx if width < chx
height = chy if height < chy height = chy if height < chy
ch[2] += 4
@textchars.push(ch[5] ? "" : ch[0]) @textchars.push(ch[5] ? "" : ch[0])
end end
end end
@@ -390,7 +388,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
def maxPosition def maxPosition
pos = 0 pos = 0
for ch in @fmtchars @fmtchars.each do |ch|
# index after the last character's index # index after the last character's index
pos = ch[14] + 1 if pos < ch[14] + 1 pos = ch[14] + 1 if pos < ch[14] + 1
end end
@@ -481,7 +479,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
end end
maxX = self.width - self.borderX maxX = self.width - self.borderX
maxY = self.height - self.borderY maxY = self.height - self.borderY
for i in @drawncurchar+1..numchars (@drawncurchar + 1..numchars).each do |i|
next if i >= @fmtchars.length next if i >= @fmtchars.length
if !self.letterbyletter if !self.letterbyletter
next if @fmtchars[i][1] >= maxX next if @fmtchars[i][1] >= maxX
@@ -490,10 +488,8 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
drawSingleFormattedChar(self.contents, @fmtchars[i]) drawSingleFormattedChar(self.contents, @fmtchars[i])
@lastDrawnChar = i @lastDrawnChar = i
end end
if !self.letterbyletter
# all characters were drawn, reset old font # all characters were drawn, reset old font
self.contents.font = @oldfont if @oldfont self.contents.font = @oldfont if !self.letterbyletter && @oldfont
end
if numchars > 0 && numchars != @numtextchars if numchars > 0 && numchars != @numtextchars
fch = @fmtchars[numchars - 1] fch = @fmtchars[numchars - 1]
if fch if fch
@@ -579,7 +575,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
def update def update
super super
@pausesprite.update if @pausesprite && @pausesprite.visible @pausesprite.update if @pausesprite&.visible
if @waitcount > 0 if @waitcount > 0
@waitcount -= 1 @waitcount -= 1
return return
@@ -601,7 +597,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
break if @textchars[@curchar] == "\n" || # newline break if @textchars[@curchar] == "\n" || # newline
@textchars[@curchar] == "\1" || # pause @textchars[@curchar] == "\1" || # pause
@textchars[@curchar] == "\2" || # letter-by-letter break @textchars[@curchar] == "\2" || # letter-by-letter break
@textchars[@curchar]==nil @textchars[@curchar].nil?
end end
end end
end end
@@ -621,7 +617,7 @@ class Window_InputNumberPokemon < SpriteWindow_Base
@sign = false @sign = false
@negative = false @negative = false
super(0, 0, 32, 32) super(0, 0, 32, 32)
self.width=digits_max*24+8+self.borderX self.width = (digits_max * 24) + 8 + self.borderX
self.height = 32 + self.borderY self.height = 32 + self.borderY
colors = getDefaultTextColors(self.windowskin) colors = getDefaultTextColors(self.windowskin)
@baseColor = colors[0] @baseColor = colors[0]
@@ -644,16 +640,16 @@ class Window_InputNumberPokemon < SpriteWindow_Base
value = 0 if !value.is_a?(Numeric) value = 0 if !value.is_a?(Numeric)
if @sign if @sign
@negative = (value < 0) @negative = (value < 0)
@number = [value.abs, 10 ** @digits_max - 1].min @number = [value.abs, (10**@digits_max) - 1].min
else else
@number = [[value, 0].max, 10 ** @digits_max - 1].min @number = [[value, 0].max, (10**@digits_max) - 1].min
end end
refresh refresh
end end
def sign=(value) def sign=(value)
@sign = value @sign = value
self.width=@digits_max*24+8+self.borderX+(@sign ? 24 : 0) self.width = (@digits_max * 24) + 8 + self.borderX + (@sign ? 24 : 0)
@index = (@digits_max - 1) + (@sign ? 1 : 0) @index = (@digits_max - 1) + (@sign ? 1 : 0)
refresh refresh
end end
@@ -667,7 +663,7 @@ class Window_InputNumberPokemon < SpriteWindow_Base
if @sign if @sign
textHelper(0, 0, @negative ? "-" : "+", 0) textHelper(0, 0, @negative ? "-" : "+", 0)
end end
for i in 0...@digits_max @digits_max.times do |i|
index = i + (@sign ? 1 : 0) index = i + (@sign ? 1 : 0)
textHelper(index * 24, 0, s[i, 1], index) textHelper(index * 24, 0, s[i, 1], index)
end end
@@ -679,7 +675,7 @@ class Window_InputNumberPokemon < SpriteWindow_Base
refresh if @frame % 15 == 0 refresh if @frame % 15 == 0
if self.active if self.active
if Input.repeat?(Input::UP) || Input.repeat?(Input::DOWN) if Input.repeat?(Input::UP) || Input.repeat?(Input::DOWN)
pbPlayCursorSE() pbPlayCursorSE
if @index == 0 && @sign if @index == 0 && @sign
@negative = !@negative @negative = !@negative
else else
@@ -696,14 +692,14 @@ class Window_InputNumberPokemon < SpriteWindow_Base
refresh refresh
elsif Input.repeat?(Input::RIGHT) elsif Input.repeat?(Input::RIGHT)
if digits >= 2 if digits >= 2
pbPlayCursorSE() pbPlayCursorSE
@index = (@index + 1) % digits @index = (@index + 1) % digits
@frame = 0 @frame = 0
refresh refresh
end end
elsif Input.repeat?(Input::LEFT) elsif Input.repeat?(Input::LEFT)
if digits >= 2 if digits >= 2
pbPlayCursorSE() pbPlayCursorSE
@index = (@index + digits - 1) % digits @index = (@index + digits - 1) % digits
@frame = 0 @frame = 0
refresh refresh
@@ -717,9 +713,12 @@ class Window_InputNumberPokemon < SpriteWindow_Base
def textHelper(x, y, text, i) def textHelper(x, y, text, i)
textwidth = self.contents.text_size(text).width textwidth = self.contents.text_size(text).width
pbDrawShadowText(self.contents, x+(12-textwidth/2), y, textwidth+4, 32, text, @baseColor, @shadowColor) pbDrawShadowText(self.contents,
x + (12 - (textwidth / 2)),
y - 2 + (self.contents.text_offset_y || 0), # TEXT OFFSET (the - 2)
textwidth + 4, 32, text, @baseColor, @shadowColor)
if @index == i && @active && @frame / 15 == 0 if @index == i && @active && @frame / 15 == 0
self.contents.fill_rect(x+(12-textwidth/2), y+30, textwidth, 2, @baseColor) self.contents.fill_rect(x + (12 - (textwidth / 2)), y + 30, textwidth, 2, @baseColor)
end end
end end
end end
@@ -731,12 +730,13 @@ end
#=============================================================================== #===============================================================================
class SpriteWindow_Selectable < SpriteWindow_Base class SpriteWindow_Selectable < SpriteWindow_Base
attr_reader :index attr_reader :index
attr_writer :ignore_input
def initialize(x, y, width, height) def initialize(x, y, width, height)
super(x, y, width, height) super(x, y, width, height)
@item_max = 1 @item_max = 1
@column_max = 1 @column_max = 1
@virtualOy=0 @virtualOy = 2 # TEXT OFFSET
@index = -1 @index = -1
@row_height = 32 @row_height = 32
@column_spacing = 32 @column_spacing = 32
@@ -789,10 +789,6 @@ class SpriteWindow_Selectable < SpriteWindow_Base
end end
end end
def ignore_input=(value)
@ignore_input=value
end
def count def count
return @item_max return @item_max
end end
@@ -808,7 +804,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
def top_row=(row) def top_row=(row)
row = row_max - 1 if row > row_max - 1 row = row_max - 1 if row > row_max - 1
row = 0 if row < 0 row = 0 if row < 0
@virtualOy = row*@row_height @virtualOy = (row * @row_height) + 2 # TEXT OFFSET (the + 2)
end end
def top_item def top_item
@@ -828,9 +824,9 @@ class SpriteWindow_Selectable < SpriteWindow_Base
item > self.top_item + self.page_item_max item > self.top_item + self.page_item_max
return Rect.new(0, 0, 0, 0) return Rect.new(0, 0, 0, 0)
else else
cursor_width = (self.width-self.borderX-(@column_max-1)*@column_spacing) / @column_max cursor_width = (self.width - self.borderX - ((@column_max - 1) * @column_spacing)) / @column_max
x = item % @column_max * (cursor_width + @column_spacing) x = item % @column_max * (cursor_width + @column_spacing)
y = item / @column_max * @row_height - @virtualOy y = (item / @column_max * @row_height) - @virtualOy
return Rect.new(x, y, cursor_width, @row_height) return Rect.new(x, y, cursor_width, @row_height)
end end
end end
@@ -850,7 +846,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
oldindex = @index oldindex = @index
@index = (@index - @column_max + @item_max) % @item_max @index = (@index - @column_max + @item_max) % @item_max
if @index != oldindex if @index != oldindex
pbPlayCursorSE() pbPlayCursorSE
update_cursor_rect update_cursor_rect
end end
end end
@@ -860,7 +856,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
oldindex = @index oldindex = @index
@index = (@index + @column_max) % @item_max @index = (@index + @column_max) % @item_max
if @index != oldindex if @index != oldindex
pbPlayCursorSE() pbPlayCursorSE
update_cursor_rect update_cursor_rect
end end
end end
@@ -869,7 +865,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
oldindex = @index oldindex = @index
@index -= 1 @index -= 1
if @index != oldindex if @index != oldindex
pbPlayCursorSE() pbPlayCursorSE
update_cursor_rect update_cursor_rect
end end
end end
@@ -878,7 +874,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
oldindex = @index oldindex = @index
@index += 1 @index += 1
if @index != oldindex if @index != oldindex
pbPlayCursorSE() pbPlayCursorSE
update_cursor_rect update_cursor_rect
end end
end end
@@ -887,7 +883,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
oldindex = @index oldindex = @index
@index = [self.index - self.page_item_max, 0].max @index = [self.index - self.page_item_max, 0].max
if @index != oldindex if @index != oldindex
pbPlayCursorSE() pbPlayCursorSE
self.top_row -= self.page_row_max self.top_row -= self.page_row_max
update_cursor_rect update_cursor_rect
end end
@@ -897,7 +893,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
oldindex = @index oldindex = @index
@index = [self.index + self.page_item_max, @item_max - 1].min @index = [self.index + self.page_item_max, @item_max - 1].min
if @index != oldindex if @index != oldindex
pbPlayCursorSE() pbPlayCursorSE
self.top_row += self.page_row_max self.top_row += self.page_row_max
update_cursor_rect update_cursor_rect
end end
@@ -949,7 +945,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
# End of code # End of code
cursor_width = (self.width - self.borderX) / @column_max cursor_width = (self.width - self.borderX) / @column_max
x = self.index % @column_max * (cursor_width + @column_spacing) x = self.index % @column_max * (cursor_width + @column_spacing)
y = self.index / @column_max * @row_height - @virtualOy y = (self.index / @column_max * @row_height) - @virtualOy
self.cursor_rect.set(x, y, cursor_width, @row_height) self.cursor_rect.set(x, y, cursor_width, @row_height)
self.refresh if dorefresh || force self.refresh if dorefresh || force
end end
@@ -995,8 +991,8 @@ module UpDownArrowMixin
def adjustForZoom(sprite) def adjustForZoom(sprite)
sprite.zoom_x = self.zoom_x sprite.zoom_x = self.zoom_x
sprite.zoom_y = self.zoom_y sprite.zoom_y = self.zoom_y
sprite.x = sprite.x*self.zoom_x + self.offset_x/self.zoom_x sprite.x = (sprite.x * self.zoom_x) + (self.offset_x / self.zoom_x)
sprite.y = sprite.y*self.zoom_y + self.offset_y/self.zoom_y sprite.y = (sprite.y * self.zoom_y) + (self.offset_y / self.zoom_y)
end end
def update def update
@@ -1087,7 +1083,7 @@ class Window_DrawableCommand < SpriteWindow_SelectableEx
width = 0 width = 0
tmpbitmap = BitmapWrapper.new(1, 1) tmpbitmap = BitmapWrapper.new(1, 1)
pbSetSystemFont(tmpbitmap) pbSetSystemFont(tmpbitmap)
for i in commands commands.each do |i|
width = [width, tmpbitmap.text_size(i).width].max width = [width, tmpbitmap.text_size(i).width].max
end end
# one 16 to allow cursor # one 16 to allow cursor
@@ -1095,8 +1091,8 @@ class Window_DrawableCommand < SpriteWindow_SelectableEx
tmpbitmap.dispose tmpbitmap.dispose
end end
# Store suggested width and height of window # Store suggested width and height of window
dims[0] = [self.borderX+1,(width*self.columns)+self.borderX+ dims[0] = [self.borderX + 1,
(self.columns-1)*self.columnSpacing].max (width * self.columns) + self.borderX + ((self.columns - 1) * self.columnSpacing)].max
dims[1] = [self.borderY + 1, windowheight].max dims[1] = [self.borderY + 1, windowheight].max
dims[1] = [dims[1], Graphics.height].min dims[1] = [dims[1], Graphics.height].min
end end
@@ -1111,7 +1107,7 @@ class Window_DrawableCommand < SpriteWindow_SelectableEx
def drawCursor(index, rect) def drawCursor(index, rect)
if self.index == index if self.index == index
pbCopyBitmap(self.contents,@selarrow.bitmap,rect.x,rect.y) pbCopyBitmap(self.contents, @selarrow.bitmap, rect.x, rect.y + 2) # TEXT OFFSET (counters the offset above)
end end
return Rect.new(rect.x + 16, rect.y, rect.width - 16, rect.height) return Rect.new(rect.x + 16, rect.y, rect.width - 16, rect.height)
end end
@@ -1120,16 +1116,15 @@ class Window_DrawableCommand < SpriteWindow_SelectableEx
return 0 return 0
end end
def drawItem(index,count,rect) # to be implemented by derived classes def drawItem(index, count, rect); end # to be implemented by derived classes
end
def refresh def refresh
@item_max = itemCount() @item_max = itemCount
dwidth = self.width - self.borderX dwidth = self.width - self.borderX
dheight = self.height - self.borderY dheight = self.height - self.borderY
self.contents = pbDoEnsureBitmap(self.contents, dwidth, dheight) self.contents = pbDoEnsureBitmap(self.contents, dwidth, dheight)
self.contents.clear self.contents.clear
for i in 0...@item_max @item_max.times do |i|
next if i < self.top_item || i > self.top_item + self.page_item_max next if i < self.top_item || i > self.top_item + self.page_item_max
drawItem(i, @item_max, itemRect(i)) drawItem(i, @item_max, itemRect(i))
end end
@@ -1229,8 +1224,8 @@ class Window_CommandPokemon < Window_DrawableCommand
def drawItem(index, _count, rect) def drawItem(index, _count, rect)
pbSetSystemFont(self.contents) if @starting pbSetSystemFont(self.contents) if @starting
rect = drawCursor(index, rect) rect = drawCursor(index, rect)
pbDrawShadowText(self.contents,rect.x,rect.y,rect.width,rect.height, pbDrawShadowText(self.contents, rect.x, rect.y + (self.contents.text_offset_y || 0),
@commands[index],self.baseColor,self.shadowColor) rect.width, rect.height, @commands[index], self.baseColor, self.shadowColor)
end end
end end
@@ -1254,7 +1249,7 @@ class Window_AdvancedCommandPokemon < Window_DrawableCommand
chars = getFormattedText(bitmap, 0, 0, chars = getFormattedText(bitmap, 0, 0,
Graphics.width - self.borderX - SpriteWindow_Base::TEXTPADDING - 16, Graphics.width - self.borderX - SpriteWindow_Base::TEXTPADDING - 16,
-1, text, self.rowHeight, true, true) -1, text, self.rowHeight, true, true)
for ch in chars chars.each do |ch|
dims[0] = dims[0] ? [dims[0], ch[1]].min : ch[1] dims[0] = dims[0] ? [dims[0], ch[1]].min : ch[1]
dims[1] = [dims[1], ch[1] + ch[3]].max dims[1] = [dims[1], ch[1] + ch[3]].max
end end
@@ -1348,8 +1343,7 @@ class Window_AdvancedCommandPokemon < Window_DrawableCommand
pbDrawShadowText(self.contents, rect.x, rect.y, rect.width, rect.height, pbDrawShadowText(self.contents, rect.x, rect.y, rect.width, rect.height,
@commands[index], self.baseColor, self.shadowColor) @commands[index], self.baseColor, self.shadowColor)
else else
chars=getFormattedText( chars = getFormattedText(self.contents, rect.x, rect.y + 4, rect.width, rect.height,
self.contents,rect.x,rect.y+4,rect.width,rect.height,
@commands[index], rect.height, true, true) @commands[index], rect.height, true, true)
drawFormattedChars(self.contents, chars) drawFormattedChars(self.contents, chars)
end end

View File

@@ -13,7 +13,7 @@ class IconWindow < SpriteWindow_Base
end end
def dispose def dispose
clearBitmaps() clearBitmaps
super super
end end
@@ -26,7 +26,7 @@ class IconWindow < SpriteWindow_Base
end end
def clearBitmaps def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap @_iconbitmap&.dispose
@_iconbitmap = nil @_iconbitmap = nil
self.contents = nil if !self.disposed? self.contents = nil if !self.disposed?
end end
@@ -38,15 +38,15 @@ class IconWindow < SpriteWindow_Base
# Sets the icon's filename. # Sets the icon's filename.
def setBitmap(file, hue = 0) def setBitmap(file, hue = 0)
clearBitmaps() clearBitmaps
@name = file @name = file
return if file==nil return if file.nil?
if file!="" if file == ""
@_iconbitmap = nil
else
@_iconbitmap = AnimatedBitmap.new(file, hue) @_iconbitmap = AnimatedBitmap.new(file, hue)
# for compatibility # for compatibility
self.contents = @_iconbitmap ? @_iconbitmap.bitmap : nil self.contents = @_iconbitmap ? @_iconbitmap.bitmap : nil
else
@_iconbitmap=nil
end end
end end
end end
@@ -67,7 +67,7 @@ class PictureWindow < SpriteWindow_Base
end end
def dispose def dispose
clearBitmaps() clearBitmaps
super super
end end
@@ -84,7 +84,7 @@ class PictureWindow < SpriteWindow_Base
end end
def clearBitmaps def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap @_iconbitmap&.dispose
@_iconbitmap = nil @_iconbitmap = nil
self.contents = nil if !self.disposed? self.contents = nil if !self.disposed?
end end
@@ -92,25 +92,24 @@ class PictureWindow < SpriteWindow_Base
# Sets the icon's bitmap or filename. (hue parameter # Sets the icon's bitmap or filename. (hue parameter
# is ignored unless pathOrBitmap is a filename) # is ignored unless pathOrBitmap is a filename)
def setBitmap(pathOrBitmap, hue = 0) def setBitmap(pathOrBitmap, hue = 0)
clearBitmaps() clearBitmaps
if pathOrBitmap!=nil && pathOrBitmap!="" if pathOrBitmap && pathOrBitmap != ""
if pathOrBitmap.is_a?(Bitmap) case pathOrBitmap
when Bitmap
@_iconbitmap = pathOrBitmap @_iconbitmap = pathOrBitmap
self.contents = @_iconbitmap self.contents = @_iconbitmap
self.width = @_iconbitmap.width + self.borderX self.width = @_iconbitmap.width + self.borderX
self.height = @_iconbitmap.height + self.borderY self.height = @_iconbitmap.height + self.borderY
elsif pathOrBitmap.is_a?(AnimatedBitmap) when AnimatedBitmap
@_iconbitmap = pathOrBitmap @_iconbitmap = pathOrBitmap
self.contents = @_iconbitmap.bitmap self.contents = @_iconbitmap.bitmap
self.width = @_iconbitmap.bitmap.width + self.borderX self.width = @_iconbitmap.bitmap.width + self.borderX
self.height = @_iconbitmap.bitmap.height + self.borderY self.height = @_iconbitmap.bitmap.height + self.borderY
else else
@_iconbitmap = AnimatedBitmap.new(pathOrBitmap, hue) @_iconbitmap = AnimatedBitmap.new(pathOrBitmap, hue)
self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil self.contents = @_iconbitmap&.bitmap
self.width=@_iconbitmap ? @_iconbitmap.bitmap.width+self.borderX : self.width = self.borderX + (@_iconbitmap&.bitmap&.width || 32)
32+self.borderX self.height = self.borderY + (@_iconbitmap&.bitmap&.height || 32)
self.height=@_iconbitmap ? @_iconbitmap.bitmap.height+self.borderY :
32+self.borderY
end end
else else
@_iconbitmap = nil @_iconbitmap = nil

View File

@@ -245,13 +245,14 @@ class IconSprite < SpriteWrapper
attr_reader :name attr_reader :name
def initialize(*args) def initialize(*args)
if args.length==0 case args.length
when 0
super(nil) super(nil)
self.bitmap = nil self.bitmap = nil
elsif args.length==1 when 1
super(args[0]) super(args[0])
self.bitmap = nil self.bitmap = nil
elsif args.length==2 when 2
super(nil) super(nil)
self.x = args[0] self.x = args[0]
self.y = args[1] self.y = args[1]
@@ -265,7 +266,7 @@ class IconSprite < SpriteWrapper
end end
def dispose def dispose
clearBitmaps() clearBitmaps
super super
end end
@@ -277,21 +278,21 @@ class IconSprite < SpriteWrapper
# Sets the icon's filename. # Sets the icon's filename.
def setBitmap(file, hue = 0) def setBitmap(file, hue = 0)
oldrc = self.src_rect oldrc = self.src_rect
clearBitmaps() clearBitmaps
@name = file @name = file
return if file==nil return if file.nil?
if file!="" if file == ""
@_iconbitmap = nil
else
@_iconbitmap = AnimatedBitmap.new(file, hue) @_iconbitmap = AnimatedBitmap.new(file, hue)
# for compatibility # for compatibility
self.bitmap = @_iconbitmap ? @_iconbitmap.bitmap : nil self.bitmap = @_iconbitmap ? @_iconbitmap.bitmap : nil
self.src_rect = oldrc self.src_rect = oldrc
else
@_iconbitmap=nil
end end
end end
def clearBitmaps def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap @_iconbitmap&.dispose
@_iconbitmap = nil @_iconbitmap = nil
self.bitmap = nil if !self.disposed? self.bitmap = nil if !self.disposed?
end end
@@ -335,7 +336,7 @@ class ChangelingSprite < SpriteWrapper
end end
def addBitmap(key, path) def addBitmap(key, path)
@bitmaps[key].dispose if @bitmaps[key] @bitmaps[key]&.dispose
@bitmaps[key] = AnimatedBitmap.new(path) @bitmaps[key] = AnimatedBitmap.new(path)
end end
@@ -346,14 +347,14 @@ class ChangelingSprite < SpriteWrapper
def dispose def dispose
return if disposed? return if disposed?
for bm in @bitmaps.values; bm.dispose; end @bitmaps.each_value { |bm| bm.dispose }
@bitmaps.clear @bitmaps.clear
super super
end end
def update def update
return if disposed? return if disposed?
for bm in @bitmaps.values; bm.update; end @bitmaps.each_value { |bm| bm.update }
self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil
end end
end end

View File

@@ -6,10 +6,10 @@ class AnimatedBitmap
raise "Filename is nil (missing graphic)." if file.nil? raise "Filename is nil (missing graphic)." if file.nil?
path = file path = file
filename = "" filename = ""
if file.last != '/' # Isn't just a directory if file.last != "/" # Isn't just a directory
split_file = file.split(/[\\\/]/) split_file = file.split(/[\\\/]/)
filename = split_file.pop filename = split_file.pop
path = split_file.join('/') + '/' path = split_file.join("/") + "/"
end end
if filename[/^\[\d+(?:,\d+)?\]/] # Starts with 1 or 2 numbers in square brackets if filename[/^\[\d+(?:,\d+)?\]/] # Starts with 1 or 2 numbers in square brackets
@bitmap = PngAnimatedBitmap.new(path, filename, hue) @bitmap = PngAnimatedBitmap.new(path, filename, hue)
@@ -57,7 +57,7 @@ class PngAnimatedBitmap
end end
@frameDelay = delay @frameDelay = delay
subWidth = panorama.width / numFrames subWidth = panorama.width / numFrames
for i in 0...numFrames numFrames.times do |i|
subBitmap = BitmapWrapper.new(subWidth, panorama.height) subBitmap = BitmapWrapper.new(subWidth, panorama.height)
subBitmap.blt(0, 0, panorama, Rect.new(subWidth * i, 0, subWidth, panorama.height)) subBitmap.blt(0, 0, panorama, Rect.new(subWidth * i, 0, subWidth, panorama.height))
@frames.push(subBitmap) @frames.push(subBitmap)
@@ -76,7 +76,7 @@ class PngAnimatedBitmap
def height; self.bitmap.height; end def height; self.bitmap.height; end
def deanimate def deanimate
for i in 1...@frames.length (1...@frames.length).each do |i|
@frames[i].dispose @frames[i].dispose
end end
@frames = [@frames[0]] @frames = [@frames[0]]
@@ -134,9 +134,7 @@ class PngAnimatedBitmap
def copy def copy
x = self.clone x = self.clone
x.frames = x.frames.clone x.frames = x.frames.clone
for i in 0...x.frames.length x.frames.each_with_index { |frame, i| x.frames[i] = frame.copy }
x.frames[i] = x.frames[i].copy
end
return x return x
end end
end end

View File

@@ -6,225 +6,69 @@ class Plane
def refresh; end def refresh; end
end end
#===============================================================================
# This class works around a limitation that planes are always
# 640 by 480 pixels in size regardless of the window's size.
#===============================================================================
class LargePlane < Plane
attr_accessor :borderX
attr_accessor :borderY
def initialize(viewport=nil)
@__sprite=Sprite.new(viewport)
@__disposed=false
@__ox=0
@__oy=0
@__bitmap=nil
@__visible=true
@__sprite.visible=false
@borderX=0
@borderY=0
end
def disposed?
return @__disposed
end
def dispose
if !@__disposed
@__sprite.bitmap.dispose if @__sprite.bitmap
@__sprite.dispose
@__sprite=nil
@__bitmap=nil
@__disposed=true
end
#super
end
def ox; @__ox; end
def oy; @__oy; end
def ox=(value);
return if @__ox==value
@__ox = value
refresh
end
def oy=(value);
return if @__oy==value
@__oy = value
refresh
end
def bitmap
return @__bitmap
end
def bitmap=(value)
if value==nil
if @__bitmap!=nil
@__bitmap=nil
@__sprite.visible=(@__visible && !@__bitmap.nil?)
end
elsif @__bitmap!=value && !value.disposed?
@__bitmap=value
refresh
elsif value.disposed?
if @__bitmap!=nil
@__bitmap=nil
@__sprite.visible=(@__visible && !@__bitmap.nil?)
end
end
end
def viewport; @__sprite.viewport; end
def zoom_x; @__sprite.zoom_x; end
def zoom_y; @__sprite.zoom_y; end
def opacity; @__sprite.opacity; end
def blend_type; @__sprite.blend_type; end
def visible; @__visible; end
def z; @__sprite.z; end
def color; @__sprite.color; end
def tone; @__sprite.tone; end
def zoom_x=(v);
return if @__sprite.zoom_x==v
@__sprite.zoom_x = v
refresh
end
def zoom_y=(v);
return if @__sprite.zoom_y==v
@__sprite.zoom_y = v
refresh
end
def opacity=(v); @__sprite.opacity=(v); end
def blend_type=(v); @__sprite.blend_type=(v); end
def visible=(v); @__visible=v; @__sprite.visible=(@__visible && !@__bitmap.nil?); end
def z=(v); @__sprite.z=(v); end
def color=(v); @__sprite.color=(v); end
def tone=(v); @__sprite.tone=(v); end
def update; ;end
def refresh
@__sprite.visible = (@__visible && !@__bitmap.nil?)
if @__bitmap
if !@__bitmap.disposed?
@__ox += @__bitmap.width*@__sprite.zoom_x if @__ox<0
@__oy += @__bitmap.height*@__sprite.zoom_y if @__oy<0
@__ox -= @__bitmap.width*@__sprite.zoom_x if @__ox>@__bitmap.width
@__oy -= @__bitmap.height*@__sprite.zoom_y if @__oy>@__bitmap.height
dwidth = (Graphics.width/@__sprite.zoom_x+@borderX).to_i # +2
dheight = (Graphics.height/@__sprite.zoom_y+@borderY).to_i # +2
@__sprite.bitmap = ensureBitmap(@__sprite.bitmap,dwidth,dheight)
@__sprite.bitmap.clear
tileBitmap(@__sprite.bitmap,@__bitmap,@__bitmap.rect)
else
@__sprite.visible = false
end
end
end
private
def ensureBitmap(bitmap,dwidth,dheight)
if !bitmap || bitmap.disposed? || bitmap.width<dwidth || bitmap.height<dheight
bitmap.dispose if bitmap
bitmap = Bitmap.new([1,dwidth].max,[1,dheight].max)
end
return bitmap
end
def tileBitmap(dstbitmap,srcbitmap,srcrect)
return if !srcbitmap || srcbitmap.disposed?
dstrect = dstbitmap.rect
left = (dstrect.x-@__ox/@__sprite.zoom_x).to_i
top = (dstrect.y-@__oy/@__sprite.zoom_y).to_i
while left>0; left -= srcbitmap.width; end
while top>0; top -= srcbitmap.height; end
y = top
while y<dstrect.height
x = left
while x<dstrect.width
dstbitmap.blt(x+@borderX,y+@borderY,srcbitmap,srcrect)
x += srcrect.width
end
y += srcrect.height
end
end
end
#=============================================================================== #===============================================================================
# A plane class that displays a single color. # A plane class that displays a single color.
#=============================================================================== #===============================================================================
class ColoredPlane < LargePlane class ColoredPlane < Plane
def initialize(color, viewport = nil) def initialize(color, viewport = nil)
super(viewport) super(viewport)
self.bitmap = Bitmap.new(32, 32) self.bitmap = Bitmap.new(32, 32)
setPlaneColor(color) set_plane_color(color)
end end
def dispose def dispose
self.bitmap.dispose if self.bitmap self.bitmap&.dispose
super super
end end
def setPlaneColor(value) def set_plane_color(value)
self.bitmap.fill_rect(0, 0, self.bitmap.width, self.bitmap.height, value) self.bitmap.fill_rect(0, 0, self.bitmap.width, self.bitmap.height, value)
self.refresh refresh
end end
end end
#=============================================================================== #===============================================================================
# A plane class that supports animated images. # A plane class that supports animated images.
#=============================================================================== #===============================================================================
class AnimatedPlane < LargePlane class AnimatedPlane < Plane
def initialize(viewport) def initialize(viewport)
super(viewport) super(viewport)
@bitmap = nil @bitmap = nil
end end
def dispose def dispose
clearBitmaps() clear_bitmap
super super
end end
def update
super
if @bitmap
@bitmap.update
self.bitmap=@bitmap.bitmap
end
end
def clearBitmaps
@bitmap.dispose if @bitmap
@bitmap=nil
self.bitmap=nil if !self.disposed?
end
def setPanorama(file, hue=0)
clearBitmaps()
return if file==nil
@bitmap=AnimatedBitmap.new("Graphics/Panoramas/"+file,hue)
end
def setFog(file, hue=0)
clearBitmaps()
return if file==nil
@bitmap=AnimatedBitmap.new("Graphics/Fogs/"+file,hue)
end
def setBitmap(file, hue = 0) def setBitmap(file, hue = 0)
clearBitmaps() clear_bitmap
return if file==nil return if file.nil?
@bitmap = AnimatedBitmap.new(file, hue) @bitmap = AnimatedBitmap.new(file, hue)
self.bitmap = @bitmap.bitmap if @bitmap
end
def set_panorama(file, hue = 0)
if file.is_a?(String) && file.length > 0
setBitmap("Graphics/Panoramas/" + file, hue)
else
clear_bitmap
end
end
def set_fog(file, hue = 0)
if file.is_a?(String) && file.length > 0
setBitmap("Graphics/Fogs/" + file, hue)
else
clear_bitmap
end
end
private
def clear_bitmap
@bitmap&.dispose
@bitmap = nil
self.bitmap = nil if !self.disposed?
end end
end end

View File

@@ -45,26 +45,27 @@ end
def rgbToColor(param) def rgbToColor(param)
return Font.default_color if !param return Font.default_color if !param
baseint = param.to_i(16) baseint = param.to_i(16)
if param.length==8 # 32-bit hex case param.length
when 8 # 32-bit hex
return Color.new( return Color.new(
(baseint >> 24) & 0xFF, (baseint >> 24) & 0xFF,
(baseint >> 16) & 0xFF, (baseint >> 16) & 0xFF,
(baseint >> 8) & 0xFF, (baseint >> 8) & 0xFF,
(baseint) & 0xFF (baseint) & 0xFF
) )
elsif param.length==6 # 24-bit hex when 6 # 24-bit hex
return Color.new( return Color.new(
(baseint >> 16) & 0xFF, (baseint >> 16) & 0xFF,
(baseint >> 8) & 0xFF, (baseint >> 8) & 0xFF,
(baseint) & 0xFF (baseint) & 0xFF
) )
elsif param.length==4 # 16-bit hex when 4 # 16-bit hex
return Color.new( return Color.new(
((baseint) & 0x1F) << 3, ((baseint) & 0x1F) << 3,
((baseint >> 5) & 0x1F) << 3, ((baseint >> 5) & 0x1F) << 3,
((baseint >> 10) & 0x1F) << 3 ((baseint >> 10) & 0x1F) << 3
) )
elsif param.length==1 # Color number when 1 # Color number
i = param.to_i i = param.to_i
return Font.default_color if i >= 8 return Font.default_color if i >= 8
return [ return [
@@ -93,11 +94,13 @@ end
def getContrastColor(color) def getContrastColor(color)
raise "No color given" if !color raise "No color given" if !color
r=color.red; g=color.green; b=color.blue r = color.red
g = color.green
b = color.blue
yuv = [ yuv = [
r * 0.299 + g * 0.587 + b * 0.114, (r * 0.299) + (g * 0.587) + (b * 0.114),
r * -0.1687 + g * -0.3313 + b * 0.500 + 0.5, (r * -0.1687) + (g * -0.3313) + (b * 0.500) + 0.5,
r * 0.500 + g * -0.4187 + b * -0.0813 + 0.5 (r * 0.500) + (g * -0.4187) + (b * -0.0813) + 0.5
] ]
if yuv[0] < 127.5 if yuv[0] < 127.5
yuv[0] += (255 - yuv[0]) / 2 yuv[0] += (255 - yuv[0]) / 2
@@ -105,9 +108,9 @@ def getContrastColor(color)
yuv[0] = yuv[0] / 2 yuv[0] = yuv[0] / 2
end end
return Color.new( return Color.new(
yuv[0] + 1.4075 * (yuv[2] - 0.5), yuv[0] + (1.4075 * (yuv[2] - 0.5)),
yuv[0] - 0.3455 * (yuv[1] - 0.5) - 0.7169 * (yuv[2] - 0.5), yuv[0] - (0.3455 * (yuv[1] - 0.5)) - (0.7169 * (yuv[2] - 0.5)),
yuv[0] + 1.7790 * (yuv[1] - 0.5), yuv[0] + (1.7790 * (yuv[1] - 0.5)),
color.alpha color.alpha
) )
end end
@@ -160,8 +163,7 @@ def getFormattedTextForDims(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight,
if newlineBreaks if newlineBreaks
text2.gsub!(/<(\/?)(br)(\s*\=\s*([^>]*))?>/i, "\n") text2.gsub!(/<(\/?)(br)(\s*\=\s*([^>]*))?>/i, "\n")
end end
return getFormattedText( return getFormattedText(bitmap, xDst, yDst, widthDst, heightDst,
bitmap,xDst,yDst,widthDst,heightDst,
text2, lineheight, newlineBreaks, text2, lineheight, newlineBreaks,
explicitBreaksOnly, true) explicitBreaksOnly, true)
end end
@@ -172,7 +174,7 @@ def getFormattedTextFast(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight,
characters = [] characters = []
textchunks = [] textchunks = []
textchunks.push(text) textchunks.push(text)
text=textchunks.join("") text = textchunks.join
textchars = text.scan(/./m) textchars = text.scan(/./m)
lastword = [0, 0] # position of last word lastword = [0, 0] # position of last word
hadspace = false hadspace = false
@@ -196,7 +198,7 @@ def getFormattedTextFast(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight,
if textchars[position] == "\n" if textchars[position] == "\n"
if newlineBreaks # treat newline as break if newlineBreaks # treat newline as break
havenl = true havenl = true
characters.push(["\n",x,y*lineheight+yDst,0,lineheight,false,false, characters.push(["\n", x, (y * lineheight) + yDst, 0, lineheight, false, false,
false, colorclone, nil, false, false, "", 8, position, nil, 0]) false, colorclone, nil, false, false, "", 8, position, nil, 0])
y += 1 y += 1
x = 0 x = 0
@@ -222,8 +224,7 @@ def getFormattedTextFast(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight,
# Push character # Push character
if heightDst < 0 || yStart < yDst + heightDst if heightDst < 0 || yStart < yDst + heightDst
havenl = true if isWaitChar(textchars[position]) havenl = true if isWaitChar(textchars[position])
characters.push([ characters.push([textchars[position],
textchars[position],
x + xStart, texty, width + 2, lineheight, x + xStart, texty, width + 2, lineheight,
false, bold, italic, colorclone, nil, false, false, false, bold, italic, colorclone, nil, false, false,
defaultfontname, bitmap.font.size, position, nil, 0]) defaultfontname, bitmap.font.size, position, nil, 0])
@@ -232,12 +233,12 @@ def getFormattedTextFast(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight,
if !explicitBreaksOnly && x + 2 > widthDst && lastword[1] != 0 && if !explicitBreaksOnly && x + 2 > widthDst && lastword[1] != 0 &&
(!hadnonspace || !hadspace) (!hadnonspace || !hadspace)
havenl = true havenl = true
characters.insert(lastword[0],["\n",x,y*lineheight+yDst,0,lineheight, characters.insert(lastword[0], ["\n", x, (y * lineheight) + yDst, 0, lineheight,
false, false, false, colorclone, nil, false, false, "", 8, position]) false, false, false, colorclone, nil, false, false, "", 8, position])
lastword[0] += 1 lastword[0] += 1
y += 1 y += 1
x = 0 x = 0
for i in lastword[0]...characters.length (lastword[0]...characters.length).each do |i|
characters[i][2] += lineheight characters[i][2] += lineheight
charwidth = characters[i][3] - 2 charwidth = characters[i][3] - 2
characters[i][1] = x characters[i][1] = x
@@ -247,76 +248,36 @@ def getFormattedTextFast(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight,
end end
position += 1 position += 1
end end
# This code looks at whether the text occupies exactly two lines when
# displayed. If it does, it balances the length of each line.
=begin
# Count total number of lines
numlines = (x==0 && y>0) ? y-1 : y
realtext = (newlineBreaks) ? text : text.gsub(/\n/," ")
if numlines==2 && !explicitBreaksOnly && !realtext[/\n/] && realtext.length>=50
# Set half to middle of text (known to contain no formatting)
half = realtext.length/2
leftSearch = 0
rightSearch = 0
# Search left for a space
i = half; while i>=0
break if realtext[i,1][/\s/]||isWaitChar(realtext[i]) # found a space
leftSearch += 1
i -= 1
end
# Search right for a space
i = half; while i<realtext.length
break if realtext[i,1][/\s/]||isWaitChar(realtext[i]) # found a space
rightSearch += 1
i += 1
end
# Move half left or right whichever is closer
trialHalf = half+((leftSearch<rightSearch) ? -leftSearch : rightSearch)
if trialHalf!=0 && trialHalf!=realtext.length
# Insert newline and re-call this function (force explicitBreaksOnly)
newText = realtext.clone
newText.insert(trialHalf,"\n")
return getFormattedTextFast(bitmap,xDst,yDst,
widthDst,heightDst,newText,lineheight,true,explicitBreaksOnly)
end
end
=end
# Eliminate spaces before newlines and pause character # Eliminate spaces before newlines and pause character
if havenl if havenl
firstspace = -1 firstspace = -1
for i in 0...characters.length characters.length.times do |i|
if characters[i][5] != false # If not a character if characters[i][5] != false # If not a character
firstspace = -1 firstspace = -1
elsif (characters[i][0] == "\n" || isWaitChar(characters[i][0])) && elsif (characters[i][0] == "\n" || isWaitChar(characters[i][0])) &&
firstspace >= 0 firstspace >= 0
for j in firstspace...i (firstspace...i).each do |j|
characters[j] = nil characters[j] = nil
end end
firstspace = -1 firstspace = -1
elsif characters[i][0][/[ \r\t]/] elsif characters[i][0][/[ \r\t]/]
if firstspace<0 firstspace = i if firstspace < 0
firstspace=i
end
else else
firstspace = -1 firstspace = -1
end end
end end
if firstspace > 0 if firstspace > 0
for j in firstspace...characters.length (firstspace...characters.length).each do |j|
characters[j] = nil characters[j] = nil
end end
end end
characters.compact! characters.compact!
end end
for i in 0...characters.length characters.each { |char| char[1] = xDst + char[1] }
characters[i][1]=xDst+characters[i][1]
end
# Remove all characters with Y greater or equal to _yDst_+_heightDst_ # Remove all characters with Y greater or equal to _yDst_+_heightDst_
if heightDst >= 0 if heightDst >= 0
for i in 0...characters.length characters.each_with_index do |char, i|
if characters[i][2]>=yDst+heightDst characters[i] = nil if char[2] >= yDst + heightDst
characters[i]=nil
end
end end
characters.compact! characters.compact!
end end
@@ -324,7 +285,7 @@ def getFormattedTextFast(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight,
end end
def isWaitChar(x) def isWaitChar(x)
return (x=="\001" || x=="\002") return (["\001", "\002"].include?(x))
end end
def getLastParam(array, default) def getLastParam(array, default)
@@ -340,10 +301,10 @@ def getLastColors(colorstack,opacitystack,defaultcolors)
colors = getLastParam(colorstack, defaultcolors) colors = getLastParam(colorstack, defaultcolors)
opacity = getLastParam(opacitystack, 255) opacity = getLastParam(opacitystack, 255)
if opacity != 255 if opacity != 255
colors=[Color.new(colors[0].red,colors[0].green,colors[0].blue, colors = [
colors[0].alpha*opacity/255), Color.new(colors[0].red, colors[0].green, colors[0].blue, colors[0].alpha * opacity / 255),
colors[1] ? Color.new(colors[1].red,colors[1].green,colors[1].blue, colors[1] ? Color.new(colors[1].red, colors[1].green, colors[1].blue, colors[1].alpha * opacity / 255) : nil
colors[1].alpha*opacity/255) : nil] ]
end end
return colors return colors
end end
@@ -432,35 +393,34 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
end end
textchunks = [] textchunks = []
controls = [] controls = []
oldtext=text # oldtext = text
while text[FORMATREGEXP] while text[FORMATREGEXP]
textchunks.push($~.pre_match) textchunks.push($~.pre_match)
if $~[3] if $~[3]
controls.push([$~[2].downcase,$~[4],-1,$~[1]=="/" ? true : false]) controls.push([$~[2].downcase, $~[4], -1, $~[1] == "/"])
else else
controls.push([$~[2].downcase,"",-1,$~[1]=="/" ? true : false]) controls.push([$~[2].downcase, "", -1, $~[1] == "/"])
end end
text = $~.post_match text = $~.post_match
end end
if controls.length == 0 if controls.length == 0
ret = getFormattedTextFast(bitmap, xDst, yDst, widthDst, heightDst, text, lineheight, ret = getFormattedTextFast(bitmap, xDst, yDst, widthDst, heightDst, text, lineheight,
newlineBreaks, explicitBreaksOnly) newlineBreaks, explicitBreaksOnly)
dummybitmap.dispose if dummybitmap dummybitmap&.dispose
return ret return ret
end end
x = y = 0 x = y = 0
characters = [] characters = []
charactersInternal = [] charactersInternal = []
realtext=nil # realtext = nil
realtextStart="" # realtextStart = ""
if !explicitBreaksOnly && textchunks.join("").length==0 # if !explicitBreaksOnly && textchunks.join.length == 0
# All commands occurred at the beginning of the text string # # All commands occurred at the beginning of the text string
realtext=(newlineBreaks) ? text : text.gsub(/\n/," ") # realtext = (newlineBreaks) ? text : text.gsub(/\n/, " ")
realtextStart=oldtext[0,oldtext.length-realtext.length] # realtextStart = oldtext[0, oldtext.length - realtext.length]
realtextHalf=text.length/2 # end
end
textchunks.push(text) textchunks.push(text)
for chunk in textchunks textchunks.each do |chunk|
chunk.gsub!(/&lt;/, "<") chunk.gsub!(/&lt;/, "<")
chunk.gsub!(/&gt;/, ">") chunk.gsub!(/&gt;/, ">")
chunk.gsub!(/&apos;/, "'") chunk.gsub!(/&apos;/, "'")
@@ -468,11 +428,11 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
chunk.gsub!(/&amp;/, "&") chunk.gsub!(/&amp;/, "&")
end end
textlen = 0 textlen = 0
for i in 0...controls.length controls.each_with_index do |control, i|
textlen += textchunks[i].scan(/./m).length textlen += textchunks[i].scan(/./m).length
controls[i][2]=textlen control[2] = textlen
end end
text=textchunks.join("") text = textchunks.join
textchars = text.scan(/./m) textchars = text.scan(/./m)
colorstack = [] colorstack = []
boldcount = 0 boldcount = 0
@@ -511,19 +471,20 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
graphicWidth = nil graphicWidth = nil
graphicHeight = nil graphicHeight = nil
graphicRect = nil graphicRect = nil
for i in 0...controls.length controls.length.times do |i|
if controls[i] && controls[i][2] == position if controls[i] && controls[i][2] == position
control = controls[i][0] control = controls[i][0]
param = controls[i][1] param = controls[i][1]
endtag = controls[i][3] endtag = controls[i][3]
if control=="c" case control
when "c"
if endtag if endtag
colorstack.pop colorstack.pop
else else
color = rgbToColor(param) color = rgbToColor(param)
colorstack.push([color, nil]) colorstack.push([color, nil])
end end
elsif control=="c2" when "c2"
if endtag if endtag
colorstack.pop colorstack.pop
else else
@@ -531,7 +492,7 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
shadow = Rgb16ToColor(param[4, 4]) shadow = Rgb16ToColor(param[4, 4])
colorstack.push([base, shadow]) colorstack.push([base, shadow])
end end
elsif control=="c3" when "c3"
if endtag if endtag
colorstack.pop colorstack.pop
else else
@@ -542,25 +503,25 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
shadow = (param[1] && param[1] != "") ? rgbToColor(param[1]) : oldColors[1] shadow = (param[1] && param[1] != "") ? rgbToColor(param[1]) : oldColors[1]
colorstack.push([base, shadow]) colorstack.push([base, shadow])
end end
elsif control=="o" when "o"
if endtag if endtag
opacitystack.pop opacitystack.pop
else else
opacitystack.push(param.sub(/\s+$/, "").to_i) opacitystack.push(param.sub(/\s+$/, "").to_i)
end end
elsif control=="b" when "b"
boldcount += (endtag ? -1 : 1) boldcount += (endtag ? -1 : 1)
elsif control=="i" when "i"
italiccount += (endtag ? -1 : 1) italiccount += (endtag ? -1 : 1)
elsif control=="u" when "u"
underlinecount += (endtag ? -1 : 1) underlinecount += (endtag ? -1 : 1)
elsif control=="s" when "s"
strikecount += (endtag ? -1 : 1) strikecount += (endtag ? -1 : 1)
elsif control=="outln" when "outln"
outlinecount += (endtag ? -1 : 1) outlinecount += (endtag ? -1 : 1)
elsif control=="outln2" when "outln2"
outline2count += (endtag ? -1 : 1) outline2count += (endtag ? -1 : 1)
elsif control=="fs" # Font size when "fs" # Font size
if endtag if endtag
fontsizestack.pop fontsizestack.pop
else else
@@ -568,7 +529,7 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
end end
fontsize = getLastParam(fontsizestack, defaultfontsize) fontsize = getLastParam(fontsizestack, defaultfontsize)
bitmap.font.size = fontsize bitmap.font.size = fontsize
elsif control=="fn" # Font name when "fn" # Font name
if endtag if endtag
fontnamestack.pop fontnamestack.pop
else else
@@ -577,38 +538,35 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
end end
fontname = getLastParam(fontnamestack, defaultfontname) fontname = getLastParam(fontnamestack, defaultfontname)
bitmap.font.name = fontname bitmap.font.name = fontname
elsif control=="ar" # Right align when "ar" # Right align
if !endtag if endtag
alignstack.pop
else
alignstack.push(1) alignstack.push(1)
nextline=1 if x>0 && nextline==0
else
alignstack.pop
nextline=1 if x>0 && nextline==0
end end
elsif control=="al" # Left align nextline = 1 if x > 0 && nextline == 0
if !endtag when "al" # Left align
if endtag
alignstack.pop
else
alignstack.push(0) alignstack.push(0)
nextline=1 if x>0 && nextline==0
else
alignstack.pop
nextline=1 if x>0 && nextline==0
end end
elsif control=="ac" # Center align nextline = 1 if x > 0 && nextline == 0
if !endtag when "ac" # Center align
if endtag
alignstack.pop
else
alignstack.push(2) alignstack.push(2)
nextline=1 if x>0 && nextline==0
else
alignstack.pop
nextline=1 if x>0 && nextline==0
end end
elsif control=="icon" # Icon nextline = 1 if x > 0 && nextline == 0
when "icon" # Icon
if !endtag if !endtag
param = param.sub(/\s+$/, "") param = param.sub(/\s+$/, "")
graphic = "Graphics/Icons/#{param}" graphic = "Graphics/Icons/#{param}"
controls[i] = nil controls[i] = nil
break break
end end
elsif control=="img" # Icon when "img" # Icon
if !endtag if !endtag
param = param.sub(/\s+$/, "") param = param.sub(/\s+$/, "")
param = param.split("|") param = param.split("|")
@@ -622,14 +580,15 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
controls[i] = nil controls[i] = nil
break break
end end
elsif control=="br" # Line break when "br" # Line break
if !endtag if !endtag
nextline += 1 nextline += 1
end end
elsif control=="r" # Right align this line when "r" # Right align this line
if !endtag if !endtag
x = 0 x = 0
rightalign=1; lastword=[characters.length,x] rightalign = 1
lastword = [characters.length, x]
end end
end end
controls[i] = nil controls[i] = nil
@@ -647,6 +606,7 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
width = graphicWidth # +8 # No padding width = graphicWidth # +8 # No padding
xStart = 0 # 4 xStart = 0 # 4
yStart = [(lineheight / 2) - (graphicHeight / 2), 0].max yStart = [(lineheight / 2) - (graphicHeight / 2), 0].max
yStart += 4 # TEXT OFFSET
graphicRect = Rect.new(graphicX, graphicY, graphicWidth, graphicHeight) graphicRect = Rect.new(graphicX, graphicY, graphicWidth, graphicHeight)
else else
xStart = 0 xStart = 0
@@ -661,7 +621,7 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
end end
nextline.times do nextline.times do
havenl = true havenl = true
characters.push(["\n",x,y*lineheight+yDst,0,lineheight,false,false,false, characters.push(["\n", x, (y * lineheight) + yDst, 0, lineheight, false, false, false,
defaultcolors[0], defaultcolors[1], false, false, "", 8, position, nil, 0]) defaultcolors[0], defaultcolors[1], false, false, "", 8, position, nil, 0])
charactersInternal.push([alignment, y, 0]) charactersInternal.push([alignment, y, 0])
y += 1 y += 1
@@ -675,7 +635,7 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
if newlineBreaks if newlineBreaks
if nextline == 0 if nextline == 0
havenl = true havenl = true
characters.push(["\n",x,y*lineheight+yDst,0,lineheight,false,false,false, characters.push(["\n", x, (y * lineheight) + yDst, 0, lineheight, false, false, false,
defaultcolors[0], defaultcolors[1], false, false, "", 8, position, nil, 0]) defaultcolors[0], defaultcolors[1], false, false, "", 8, position, nil, 0])
charactersInternal.push([alignment, y, 0]) charactersInternal.push([alignment, y, 0])
y += 1 y += 1
@@ -704,35 +664,34 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
elsif isspace elsif isspace
hadspace = true hadspace = true
end end
texty=(lineheight*y)+yDst+yStart texty = (lineheight * y) + yDst + yStart - 2 # TEXT OFFSET
colors = getLastColors(colorstack, opacitystack, defaultcolors) colors = getLastColors(colorstack, opacitystack, defaultcolors)
# Push character # Push character
if heightDst < 0 || texty < yDst + heightDst if heightDst < 0 || texty < yDst + heightDst
havenl = true if !graphic && isWaitChar(textchars[position]) havenl = true if !graphic && isWaitChar(textchars[position])
extraspace = (!graphic && italiccount > 0) ? 2 + (width / 2) : 2 extraspace = (!graphic && italiccount > 0) ? 2 + (width / 2) : 2
characters.push([ characters.push([graphic || textchars[position],
graphic ? graphic : textchars[position],
x + xStart, texty, width + extraspace, lineheight, x + xStart, texty, width + extraspace, lineheight,
graphic ? true : false, graphic ? true : false,
(boldcount > 0), (italiccount > 0), colors[0], colors[1], (boldcount > 0), (italiccount > 0), colors[0], colors[1],
(underlinecount > 0), (strikecount > 0), fontname, fontsize, (underlinecount > 0), (strikecount > 0), fontname, fontsize,
position, graphicRect, position, graphicRect,
((outlinecount>0) ? 1 : 0)+((outline2count>0) ? 2 : 0) ((outlinecount > 0) ? 1 : 0) + ((outline2count > 0) ? 2 : 0)])
])
charactersInternal.push([alignment, y, xStart, textchars[position], extraspace]) charactersInternal.push([alignment, y, xStart, textchars[position], extraspace])
end end
x += width x += width
if !explicitBreaksOnly && x + 2 > widthDst && lastword[1] != 0 && if !explicitBreaksOnly && x + 2 > widthDst && lastword[1] != 0 &&
(!hadnonspace || !hadspace) (!hadnonspace || !hadspace)
havenl = true havenl = true
characters.insert(lastword[0],["\n",x,y*lineheight+yDst,0,lineheight,false, characters.insert(lastword[0], ["\n", x, (y * lineheight) + yDst, 0, lineheight,
false,false,defaultcolors[0],defaultcolors[1],false,false,"",8,position, false, false, false,
nil]) defaultcolors[0], defaultcolors[1],
false, false, "", 8, position, nil])
charactersInternal.insert(lastword[0], [alignment, y, 0]) charactersInternal.insert(lastword[0], [alignment, y, 0])
lastword[0] += 1 lastword[0] += 1
y += 1 y += 1
x = 0 x = 0
for i in lastword[0]...characters.length (lastword[0]...characters.length).each do |i|
characters[i][2] += lineheight characters[i][2] += lineheight
charactersInternal[i][1] += 1 charactersInternal[i][1] += 1
extraspace = (charactersInternal[i][4]) ? charactersInternal[i][4] : 0 extraspace = (charactersInternal[i][4]) ? charactersInternal[i][4] : 0
@@ -755,13 +714,15 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
leftSearch = 0 leftSearch = 0
rightSearch = 0 rightSearch = 0
# Search left for a space # Search left for a space
i = half; while i>=0 i = half
while i>=0
break if realtext[i,1][/\s/]||isWaitChar(realtext[i,1]) # found a space break if realtext[i,1][/\s/]||isWaitChar(realtext[i,1]) # found a space
leftSearch += 1 leftSearch += 1
i -= 1 i -= 1
end end
# Search right for a space # Search right for a space
i = half; while i<realtext.length i = half
while i<realtext.length
break if realtext[i,1][/\s/]||isWaitChar(realtext[i,1]) # found a space break if realtext[i,1][/\s/]||isWaitChar(realtext[i,1]) # found a space
rightSearch += 1 rightSearch += 1
i += 1 i += 1
@@ -790,12 +751,12 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
if havenl if havenl
# Eliminate spaces before newlines and pause character # Eliminate spaces before newlines and pause character
firstspace = -1 firstspace = -1
for i in 0...characters.length characters.length.times do |i|
if characters[i][5] != false # If not a character if characters[i][5] != false # If not a character
firstspace = -1 firstspace = -1
elsif (characters[i][0] == "\n" || isWaitChar(characters[i][0])) && elsif (characters[i][0] == "\n" || isWaitChar(characters[i][0])) &&
firstspace >= 0 firstspace >= 0
for j in firstspace...i (firstspace...i).each do |j|
characters[j] = nil characters[j] = nil
charactersInternal[j] = nil charactersInternal[j] = nil
end end
@@ -809,7 +770,7 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
end end
end end
if firstspace > 0 if firstspace > 0
for j in firstspace...characters.length (firstspace...characters.length).each do |j|
characters[j] = nil characters[j] = nil
charactersInternal[j] = nil charactersInternal[j] = nil
end end
@@ -824,7 +785,7 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
lastalign = 0 lastalign = 0
lasty = 0 lasty = 0
runstart = 0 runstart = 0
for i in 0...characters.length characters.length.times do |i|
c = characters[i] c = characters[i]
if i > 0 && (charactersInternal[i][0] != lastalign || if i > 0 && (charactersInternal[i][0] != lastalign ||
charactersInternal[i][1] != lasty) charactersInternal[i][1] != lasty)
@@ -842,7 +803,7 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
if collapseAlignments if collapseAlignments
# Calculate the total width of each line # Calculate the total width of each line
totalLineWidths = [] totalLineWidths = []
for block in widthblocks widthblocks.each do |block|
y = block[4] y = block[4]
if !totalLineWidths[y] if !totalLineWidths[y]
totalLineWidths[y] = 0 totalLineWidths[y] = 0
@@ -857,9 +818,9 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
widthDst = [widthDst, (totalLineWidths.compact.max || 0)].min widthDst = [widthDst, (totalLineWidths.compact.max || 0)].min
end end
# Now, based on the text runs found, recalculate Xs # Now, based on the text runs found, recalculate Xs
for block in widthblocks widthblocks.each do |block|
next if block[0] >= block[1] next if block[0] >= block[1]
for i in block[0]...block[1] (block[0]...block[1]).each do |i|
case block[2] case block[2]
when 1 then characters[i][1] = xDst + (widthDst - block[3] - 4) + characters[i][1] when 1 then characters[i][1] = xDst + (widthDst - block[3] - 4) + characters[i][1]
when 2 then characters[i][1] = xDst + ((widthDst / 2) - (block[3] / 2)) + characters[i][1] when 2 then characters[i][1] = xDst + ((widthDst / 2) - (block[3] / 2)) + characters[i][1]
@@ -868,16 +829,9 @@ def getFormattedText(bitmap,xDst,yDst,widthDst,heightDst,text,lineheight=32,
end end
end end
# Remove all characters with Y greater or equal to _yDst_+_heightDst_ # Remove all characters with Y greater or equal to _yDst_+_heightDst_
if heightDst>=0 characters.delete_if { |ch| ch[2] >= yDst + heightDst } if heightDst >= 0
for i in 0...characters.length
if characters[i][2]>=yDst+heightDst
characters[i]=nil
end
end
characters.compact!
end
bitmap.font = oldfont bitmap.font = oldfont
dummybitmap.dispose if dummybitmap dummybitmap&.dispose
return characters return characters
end end
@@ -901,7 +855,7 @@ def getLineBrokenText(bitmap,value,width,dims)
return ret if !bitmap || bitmap.disposed? || width <= 0 return ret if !bitmap || bitmap.disposed? || width <= 0
textmsg = value.clone textmsg = value.clone
ret.push(["", 0, 0, 0, bitmap.text_size("X").height, 0, 0, 0, 0]) ret.push(["", 0, 0, 0, bitmap.text_size("X").height, 0, 0, 0, 0])
while ((c = textmsg.slice!(/\n|(\S*([ \r\t\f]?))/)) != nil) while (c = textmsg.slice!(/\n|(\S*([ \r\t\f]?))/)) != nil
break if c == "" break if c == ""
length = c.scan(/./m).length length = c.scan(/./m).length
ccheck = c ccheck = c
@@ -917,7 +871,7 @@ def getLineBrokenText(bitmap,value,width,dims)
next next
end end
words = [ccheck] words = [ccheck]
for i in 0...words.length words.length.times do |i|
word = words[i] word = words[i]
if word && word != "" if word && word != ""
textSize = bitmap.text_size(word) textSize = bitmap.text_size(word)
@@ -965,15 +919,14 @@ def getLineBrokenChunks(bitmap,value,width,dims,plain=false)
y += 32 y += 32
next next
end end
if ccheck[/</] && !plain
textcols = [] textcols = []
if ccheck[/</] && !plain
ccheck.scan(re) { textcols.push(rgbToColor($1)) } ccheck.scan(re) { textcols.push(rgbToColor($1)) }
words = ccheck.split(reNoMatch) # must have no matches because split can include match words = ccheck.split(reNoMatch) # must have no matches because split can include match
else else
textcols=[]
words = [ccheck] words = [ccheck]
end end
for i in 0...words.length words.length.times do |i|
word = words[i] word = words[i]
if word && word != "" if word && word != ""
textSize = bitmap.text_size(word) textSize = bitmap.text_size(word)
@@ -999,25 +952,25 @@ def getLineBrokenChunks(bitmap,value,width,dims,plain=false)
end end
def renderLineBrokenChunks(bitmap, xDst, yDst, normtext, maxheight = 0) def renderLineBrokenChunks(bitmap, xDst, yDst, normtext, maxheight = 0)
for i in 0...normtext.length normtext.each do |text|
width=normtext[i][3] width = text[3]
textx=normtext[i][1]+xDst textx = text[1] + xDst
texty=normtext[i][2]+yDst texty = text[2] + yDst
if maxheight==0 || normtext[i][2]<maxheight if maxheight == 0 || text[2] < maxheight
bitmap.font.color=normtext[i][5] bitmap.font.color = text[5]
bitmap.draw_text(textx,texty,width+2,normtext[i][4],normtext[i][0]) bitmap.draw_text(textx, texty, width + 2, text[4], text[0])
end end
end end
end end
def renderLineBrokenChunksWithShadow(bitmap, xDst, yDst, normtext, maxheight, baseColor, shadowColor) def renderLineBrokenChunksWithShadow(bitmap, xDst, yDst, normtext, maxheight, baseColor, shadowColor)
for i in 0...normtext.length normtext.each do |text|
width=normtext[i][3] width = text[3]
textx=normtext[i][1]+xDst textx = text[1] + xDst
texty=normtext[i][2]+yDst texty = text[2] + yDst
if maxheight==0 || normtext[i][2]<maxheight if maxheight == 0 || text[2] < maxheight
height=normtext[i][4] height = text[4]
text=normtext[i][0] text = text[0]
bitmap.font.color = shadowColor bitmap.font.color = shadowColor
bitmap.draw_text(textx + 2, texty, width + 2, height, text) bitmap.draw_text(textx + 2, texty, width + 2, height, text)
bitmap.draw_text(textx, texty + 2, width + 2, height, text) bitmap.draw_text(textx, texty + 2, width + 2, height, text)
@@ -1031,7 +984,7 @@ end
def drawBitmapBuffer(chars) def drawBitmapBuffer(chars)
width = 1 width = 1
height = 1 height = 1
for ch in chars chars.each do |ch|
chx = ch[1] + ch[3] chx = ch[1] + ch[3]
chy = ch[2] + ch[4] chy = ch[2] + ch[4]
width = chx if width < chx width = chx if width < chx
@@ -1085,8 +1038,8 @@ def drawSingleFormattedChar(bitmap,ch)
end end
bitmap.font.color = ch[8] if bitmap.font.color != ch[8] bitmap.font.color = ch[8] if bitmap.font.color != ch[8]
bitmap.draw_text(ch[1] + offset, ch[2] + offset, ch[3], ch[4], ch[0]) bitmap.draw_text(ch[1] + offset, ch[2] + offset, ch[3], ch[4], ch[0])
else elsif bitmap.font.color != ch[8]
bitmap.font.color=ch[8] if bitmap.font.color!=ch[8] bitmap.font.color = ch[8]
end end
if ch[10] # underline if ch[10] # underline
bitmap.fill_rect(ch[1], ch[2] + ch[4] - 4 - [(ch[4] - bitmap.font.size) / 2, 0].max - 2, bitmap.fill_rect(ch[1], ch[2] + ch[4] - 4 - [(ch[4] - bitmap.font.size) / 2, 0].max - 2,
@@ -1101,7 +1054,7 @@ end
def drawFormattedChars(bitmap, chars) def drawFormattedChars(bitmap, chars)
return if chars.length == 0 || !bitmap || bitmap.disposed? return if chars.length == 0 || !bitmap || bitmap.disposed?
oldfont = bitmap.font.clone oldfont = bitmap.font.clone
for ch in chars chars.each do |ch|
drawSingleFormattedChar(bitmap, ch) drawSingleFormattedChar(bitmap, ch)
end end
bitmap.font = oldfont bitmap.font = oldfont
@@ -1110,10 +1063,10 @@ end
# Unused # Unused
def drawTextTable(bitmap, x, y, totalWidth, rowHeight, columnWidthPercents, table) def drawTextTable(bitmap, x, y, totalWidth, rowHeight, columnWidthPercents, table)
yPos = y yPos = y
for i in 0...table.length table.length.times do |i|
row = table[i] row = table[i]
xPos = x xPos = x
for j in 0...row.length row.length.times do |j|
cell = row[j] cell = row[j]
cellwidth = columnWidthPercents[j] * totalWidth / 100 cellwidth = columnWidthPercents[j] * totalWidth / 100
chars = getFormattedText(bitmap, xPos, yPos, cellwidth, -1, cell, rowHeight) chars = getFormattedText(bitmap, xPos, yPos, cellwidth, -1, cell, rowHeight)
@@ -1131,8 +1084,8 @@ def drawTextEx(bitmap,x,y,width,numlines,text,baseColor,shadowColor)
end end
def drawFormattedTextEx(bitmap, x, y, width, text, baseColor = nil, shadowColor = nil, lineheight = 32) def drawFormattedTextEx(bitmap, x, y, width, text, baseColor = nil, shadowColor = nil, lineheight = 32)
base=!baseColor ? Color.new(12*8,12*8,12*8) : baseColor.clone base = baseColor ? baseColor.clone : Color.new(96, 96, 96)
shadow=!shadowColor ? Color.new(26*8,26*8,25*8) : shadowColor.clone shadow = shadowColor ? shadowColor.clone : Color.new(208, 208, 200)
text = "<c2=" + colorToRgb16(base) + colorToRgb16(shadow) + ">" + text text = "<c2=" + colorToRgb16(base) + colorToRgb16(shadow) + ">" + text
chars = getFormattedText(bitmap, x, y, width, -1, text, lineheight) chars = getFormattedText(bitmap, x, y, width, -1, text, lineheight)
drawFormattedChars(bitmap, chars) drawFormattedChars(bitmap, chars)
@@ -1148,7 +1101,6 @@ def pbDrawShadowText(bitmap,x,y,width,height,string,baseColor,shadowColor=nil,al
return if !bitmap || !string return if !bitmap || !string
width = (width < 0) ? bitmap.text_size(string).width + 1 : width width = (width < 0) ? bitmap.text_size(string).width + 1 : width
height = (height < 0) ? bitmap.text_size(string).height + 1 : height height = (height < 0) ? bitmap.text_size(string).height + 1 : height
y += 4
if shadowColor && shadowColor.alpha > 0 if shadowColor && shadowColor.alpha > 0
bitmap.font.color = shadowColor bitmap.font.color = shadowColor
bitmap.draw_text(x + 2, y, width, height, string, align) bitmap.draw_text(x + 2, y, width, height, string, align)
@@ -1193,13 +1145,14 @@ end
# 5 - Shadow color # 5 - Shadow color
# 6 - If true or 1, the text has an outline. Otherwise, the text has a shadow. # 6 - If true or 1, the text has an outline. Otherwise, the text has a shadow.
def pbDrawTextPositions(bitmap, textpos) def pbDrawTextPositions(bitmap, textpos)
for i in textpos textpos.each do |i|
textsize = bitmap.text_size(i[0]) textsize = bitmap.text_size(i[0])
x = i[1] x = i[1]
y = i[2] + 6 y = i[2]
if i[3]==true || i[3]==1 # right align case i[3]
when true, 1 # right align
x -= textsize.width x -= textsize.width
elsif i[3]==2 # centered when 2 # centered
x -= (textsize.width / 2) x -= (textsize.width / 2)
end end
if i[6] == true || i[6] == 1 # outline text if i[6] == true || i[6] == 1 # outline text
@@ -1221,7 +1174,7 @@ def pbCopyBitmap(dstbm,srcbm,x,y,opacity=255)
end end
def pbDrawImagePositions(bitmap, textpos) def pbDrawImagePositions(bitmap, textpos)
for i in textpos textpos.each do |i|
srcbitmap = AnimatedBitmap.new(pbBitmapName(i[0])) srcbitmap = AnimatedBitmap.new(pbBitmapName(i[0]))
x = i[1] x = i[1]
y = i[2] y = i[2]

View File

@@ -1,102 +1,22 @@
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
class Scene_Map
def updatemini
oldmws=$game_temp.message_window_showing
$game_temp.message_window_showing=true
loop do
$game_map.update
$game_player.update
$game_system.update
if $game_screen
$game_screen.update
else
$game_map.screen.update
end
break unless $game_temp.player_transferring
transfer_player
break if $game_temp.transition_processing
end
$game_temp.message_window_showing=oldmws
@spriteset.update if @spriteset
@message_window.update if @message_window
end
end
class Scene_Battle
def updatemini
if self.respond_to?("update_basic")
update_basic(true)
update_info_viewport # Update information viewport
else
oldmws=$game_temp.message_window_showing
$game_temp.message_window_showing=true
# Update system (timer) and screen
$game_system.update
if $game_screen
$game_screen.update
else
$game_map.screen.update
end
# If timer has reached 0
if $game_system.timer_working && $game_system.timer == 0
# Abort battle
$game_temp.battle_abort = true
end
# Update windows
@help_window.update if @help_window
@party_command_window.update if @party_command_window
@actor_command_window.update if @actor_command_window
@status_window.update if @status_window
$game_temp.message_window_showing=oldmws
@message_window.update if @message_window
# Update sprite set
@spriteset.update if @spriteset
end
end
end
def pbMapInterpreter def pbMapInterpreter
if $game_map.respond_to?("interpreter") return $game_system&.map_interpreter
return $game_map.interpreter
elsif $game_system
return $game_system.map_interpreter
end
return nil
end end
def pbMapInterpreterRunning? def pbMapInterpreterRunning?
interp = pbMapInterpreter interp = pbMapInterpreter
return interp && interp.running? return interp&.running?
end end
# Unused
def pbRefreshSceneMap def pbRefreshSceneMap
if $scene && $scene.is_a?(Scene_Map) $scene.miniupdate if $scene.is_a?(Scene_Map)
if $scene.respond_to?("miniupdate")
$scene.miniupdate
else
$scene.updatemini
end
elsif $scene && $scene.is_a?(Scene_Battle)
$scene.updatemini
end
end end
def pbUpdateSceneMap def pbUpdateSceneMap
if $scene && $scene.is_a?(Scene_Map) && !pbIsFaded? $scene.miniupdate if $scene.is_a?(Scene_Map) && !pbIsFaded?
if $scene.respond_to?("miniupdate")
$scene.miniupdate
else
$scene.updatemini
end
elsif $scene && $scene.is_a?(Scene_Battle)
$scene.updatemini
end
end end
#=============================================================================== #===============================================================================
@@ -107,26 +27,24 @@ def pbEventCommentInput(*args)
list = args[0].list # List of commands for event or event page list = args[0].list # List of commands for event or event page
elements = args[1] # Number of elements elements = args[1] # Number of elements
trigger = args[2] # Trigger trigger = args[2] # Trigger
return nil if list == nil return nil if list.nil?
return nil unless list.is_a?(Array) return nil unless list.is_a?(Array)
for item in list list.each do |item|
next unless item.code == 108 || item.code == 408 next if ![108, 108].include?(item.code)
if item.parameters[0] == trigger next if item.parameters[0] != trigger
start = list.index(item) + 1 start = list.index(item) + 1
finish = start + elements finish = start + elements
for id in start...finish (start...finish).each do |id|
next if !list[id] parameters.push(list[id].parameters[0]) if list[id]
parameters.push(list[id].parameters[0])
end end
return parameters return parameters
end end
end
return nil return nil
end end
def pbCurrentEventCommentInput(elements, trigger) def pbCurrentEventCommentInput(elements, trigger)
return nil if !pbMapInterpreterRunning? return nil if !pbMapInterpreterRunning?
event = pbMapInterpreter.get_character(0) event = pbMapInterpreter.get_self
return nil if !event return nil if !event
return pbEventCommentInput(event, elements, trigger) return pbEventCommentInput(event, elements, trigger)
end end
@@ -137,6 +55,9 @@ end
# #
#=============================================================================== #===============================================================================
class ChooseNumberParams class ChooseNumberParams
attr_reader :messageSkin # Set the full path for the message's window skin
attr_reader :skin
def initialize def initialize
@maxDigits = 0 @maxDigits = 0
@minNumber = 0 @minNumber = 0
@@ -152,18 +73,10 @@ class ChooseNumberParams
@messageSkin = value @messageSkin = value
end end
def messageSkin # Set the full path for the message's window skin
@messageSkin
end
def setSkin(value) def setSkin(value)
@skin = value @skin = value
end end
def skin
@skin
end
def setNegativesAllowed(value) def setNegativesAllowed(value)
@negativeAllowed = value @negativeAllowed = value
end end
@@ -272,20 +185,20 @@ def pbChooseNumber(msgwindow,params)
Input.update Input.update
pbUpdateSceneMap pbUpdateSceneMap
cmdwindow.update cmdwindow.update
msgwindow.update if msgwindow msgwindow&.update
yield if block_given? yield if block_given?
if Input.trigger?(Input::USE) if Input.trigger?(Input::USE)
ret = cmdwindow.number ret = cmdwindow.number
if ret > maximum if ret > maximum
pbPlayBuzzerSE() pbPlayBuzzerSE
elsif ret < minimum elsif ret < minimum
pbPlayBuzzerSE() pbPlayBuzzerSE
else else
pbPlayDecisionSE() pbPlayDecisionSE
break break
end end
elsif Input.trigger?(Input::BACK) elsif Input.trigger?(Input::BACK)
pbPlayCancelSE() pbPlayCancelSE
ret = cancelNumber ret = cancelNumber
break break
end end
@@ -306,14 +219,12 @@ class FaceWindowVX < SpriteWindow_Base
faceinfo = face.split(",") faceinfo = face.split(",")
facefile = pbResolveBitmap("Graphics/Faces/" + faceinfo[0]) facefile = pbResolveBitmap("Graphics/Faces/" + faceinfo[0])
facefile = pbResolveBitmap("Graphics/Pictures/" + faceinfo[0]) if !facefile facefile = pbResolveBitmap("Graphics/Pictures/" + faceinfo[0]) if !facefile
self.contents.dispose if self.contents self.contents&.dispose
@faceIndex = faceinfo[1].to_i @faceIndex = faceinfo[1].to_i
@facebitmaptmp = AnimatedBitmap.new(facefile) @facebitmaptmp = AnimatedBitmap.new(facefile)
@facebitmap = BitmapWrapper.new(96, 96) @facebitmap = BitmapWrapper.new(96, 96)
@facebitmap.blt(0,0,@facebitmaptmp.bitmap,Rect.new( @facebitmap.blt(0, 0, @facebitmaptmp.bitmap,
(@faceIndex % 4) * 96, Rect.new((@faceIndex % 4) * 96, (@faceIndex / 4) * 96, 96, 96))
(@faceIndex / 4) * 96, 96, 96
))
self.contents = @facebitmap self.contents = @facebitmap
end end
@@ -321,16 +232,14 @@ class FaceWindowVX < SpriteWindow_Base
super super
if @facebitmaptmp.totalFrames > 1 if @facebitmaptmp.totalFrames > 1
@facebitmaptmp.update @facebitmaptmp.update
@facebitmap.blt(0,0,@facebitmaptmp.bitmap,Rect.new( @facebitmap.blt(0, 0, @facebitmaptmp.bitmap,
(@faceIndex % 4) * 96, Rect.new((@faceIndex % 4) * 96, (@faceIndex / 4) * 96, 96, 96))
(@faceIndex / 4) * 96, 96, 96
))
end end
end end
def dispose def dispose
@facebitmaptmp.dispose @facebitmaptmp.dispose
@facebitmap.dispose if @facebitmap @facebitmap&.dispose
super super
end end
end end
@@ -351,9 +260,10 @@ def pbGetBasicMapNameFromId(id)
end end
def pbGetMapNameFromId(id) def pbGetMapNameFromId(id)
map=pbGetBasicMapNameFromId(id) name = pbGetMessage(MessageTypes::MapNames, id)
map.gsub!(/\\PN/,$Trainer.name) if $Trainer name = pbGetBasicMapNameFromId(id) if nil_or_empty?(name)
return map name.gsub!(/\\PN/, $player.name) if $player
return name
end end
def pbCsvField!(str) def pbCsvField!(str)
@@ -405,21 +315,11 @@ end
# Money and coins windows # Money and coins windows
#=============================================================================== #===============================================================================
def pbGetGoldString def pbGetGoldString
moneyString="" return _INTL("${1}", $player.money.to_s_formatted)
begin
moneyString=_INTL("${1}",$Trainer.money.to_s_formatted)
rescue
if $data_system.respond_to?("words")
moneyString=_INTL("{1} {2}",$game_party.gold,$data_system.words.gold)
else
moneyString=_INTL("{1} {2}",$game_party.gold,Vocab.gold)
end
end
return moneyString
end end
def pbDisplayGoldWindow(msgwindow) def pbDisplayGoldWindow(msgwindow)
moneyString=pbGetGoldString() moneyString = pbGetGoldString
goldwindow = Window_AdvancedTextPokemon.new(_INTL("Money:\n<ar>{1}</ar>", moneyString)) goldwindow = Window_AdvancedTextPokemon.new(_INTL("Money:\n<ar>{1}</ar>", moneyString))
goldwindow.setSkin("Graphics/Windowskins/goldskin") goldwindow.setSkin("Graphics/Windowskins/goldskin")
goldwindow.resizeToFit(goldwindow.text, Graphics.width) goldwindow.resizeToFit(goldwindow.text, Graphics.width)
@@ -435,7 +335,7 @@ def pbDisplayGoldWindow(msgwindow)
end end
def pbDisplayCoinsWindow(msgwindow, goldwindow) def pbDisplayCoinsWindow(msgwindow, goldwindow)
coinString=($Trainer) ? $Trainer.coins.to_s_formatted : "0" coinString = ($player) ? $player.coins.to_s_formatted : "0"
coinwindow = Window_AdvancedTextPokemon.new(_INTL("Coins:\n<ar>{1}</ar>", coinString)) coinwindow = Window_AdvancedTextPokemon.new(_INTL("Coins:\n<ar>{1}</ar>", coinString))
coinwindow.setSkin("Graphics/Windowskins/goldskin") coinwindow.setSkin("Graphics/Windowskins/goldskin")
coinwindow.resizeToFit(coinwindow.text, Graphics.width) coinwindow.resizeToFit(coinwindow.text, Graphics.width)
@@ -451,7 +351,7 @@ def pbDisplayCoinsWindow(msgwindow,goldwindow)
end end
def pbDisplayBattlePointsWindow(msgwindow) def pbDisplayBattlePointsWindow(msgwindow)
pointsString = ($Trainer) ? $Trainer.battle_points.to_s_formatted : "0" pointsString = ($player) ? $player.battle_points.to_s_formatted : "0"
pointswindow = Window_AdvancedTextPokemon.new(_INTL("Battle Points:\n<ar>{1}</ar>", pointsString)) pointswindow = Window_AdvancedTextPokemon.new(_INTL("Battle Points:\n<ar>{1}</ar>", pointsString))
pointswindow.setSkin("Graphics/Windowskins/goldskin") pointswindow.setSkin("Graphics/Windowskins/goldskin")
pointswindow.resizeToFit(pointswindow.text, Graphics.width) pointswindow.resizeToFit(pointswindow.text, Graphics.width)
@@ -473,32 +373,32 @@ end
#=============================================================================== #===============================================================================
def pbCreateStatusWindow(viewport = nil) def pbCreateStatusWindow(viewport = nil)
msgwindow = Window_AdvancedTextPokemon.new("") msgwindow = Window_AdvancedTextPokemon.new("")
if !viewport if viewport
msgwindow.z=99999
else
msgwindow.viewport = viewport msgwindow.viewport = viewport
else
msgwindow.z = 99999
end end
msgwindow.visible = false msgwindow.visible = false
msgwindow.letterbyletter = false msgwindow.letterbyletter = false
pbBottomLeftLines(msgwindow, 2) pbBottomLeftLines(msgwindow, 2)
skinfile=MessageConfig.pbGetSpeechFrame() skinfile = MessageConfig.pbGetSpeechFrame
msgwindow.setSkin(skinfile) msgwindow.setSkin(skinfile)
return msgwindow return msgwindow
end end
def pbCreateMessageWindow(viewport = nil, skin = nil) def pbCreateMessageWindow(viewport = nil, skin = nil)
msgwindow = Window_AdvancedTextPokemon.new("") msgwindow = Window_AdvancedTextPokemon.new("")
if !viewport if viewport
msgwindow.z=99999
else
msgwindow.viewport = viewport msgwindow.viewport = viewport
else
msgwindow.z = 99999
end end
msgwindow.visible = true msgwindow.visible = true
msgwindow.letterbyletter = true msgwindow.letterbyletter = true
msgwindow.back_opacity = MessageConfig::WINDOW_OPACITY msgwindow.back_opacity = MessageConfig::WINDOW_OPACITY
pbBottomLeftLines(msgwindow, 2) pbBottomLeftLines(msgwindow, 2)
$game_temp.message_window_showing = true if $game_temp $game_temp.message_window_showing = true if $game_temp
skin=MessageConfig.pbGetSpeechFrame() if !skin skin = MessageConfig.pbGetSpeechFrame if !skin
msgwindow.setSkin(skin) msgwindow.setSkin(skin)
return msgwindow return msgwindow
end end
@@ -542,14 +442,14 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
next $game_actors[m].name next $game_actors[m].name
} }
end end
text.gsub!(/\\pn/i,$Trainer.name) if $Trainer text.gsub!(/\\pn/i, $player.name) if $player
text.gsub!(/\\pm/i,_INTL("${1}",$Trainer.money.to_s_formatted)) if $Trainer text.gsub!(/\\pm/i, _INTL("${1}", $player.money.to_s_formatted)) if $player
text.gsub!(/\\n/i, "\n") text.gsub!(/\\n/i, "\n")
text.gsub!(/\\\[([0-9a-f]{8,8})\]/i) { "<c2=" + $1 + ">" } text.gsub!(/\\\[([0-9a-f]{8,8})\]/i) { "<c2=" + $1 + ">" }
text.gsub!(/\\pg/i,"\\b") if $Trainer && $Trainer.male? text.gsub!(/\\pg/i, "\\b") if $player&.male?
text.gsub!(/\\pg/i,"\\r") if $Trainer && $Trainer.female? text.gsub!(/\\pg/i, "\\r") if $player&.female?
text.gsub!(/\\pog/i,"\\r") if $Trainer && $Trainer.male? text.gsub!(/\\pog/i, "\\r") if $player&.male?
text.gsub!(/\\pog/i,"\\b") if $Trainer && $Trainer.female? text.gsub!(/\\pog/i, "\\b") if $player&.female?
text.gsub!(/\\pg/i, "") text.gsub!(/\\pg/i, "")
text.gsub!(/\\pog/i, "") text.gsub!(/\\pog/i, "")
text.gsub!(/\\b/i, "<c3=3050C8,D0D0C8>") text.gsub!(/\\b/i, "<c3=3050C8,D0D0C8>")
@@ -564,7 +464,7 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
next "" next ""
} }
isDarkSkin = isDarkWindowskin(msgwindow.windowskin) isDarkSkin = isDarkWindowskin(msgwindow.windowskin)
text.gsub!(/\\[Cc]\[([0-9]+)\]/) { text.gsub!(/\\c\[([0-9]+)\]/i) {
m = $1.to_i m = $1.to_i
next getSkinColor(msgwindow.windowskin, m, isDarkSkin) next getSkinColor(msgwindow.windowskin, m, isDarkSkin)
} }
@@ -582,8 +482,7 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
break if text == last_text break if text == last_text
end end
colortag = "" colortag = ""
if $game_system && $game_system.respond_to?("message_frame") && if $game_system && $game_system.message_frame != 0
$game_system.message_frame != 0
colortag = getSkinColor(msgwindow.windowskin, 0, true) colortag = getSkinColor(msgwindow.windowskin, 0, true)
else else
colortag = getSkinColor(msgwindow.windowskin, 0, isDarkSkin) colortag = getSkinColor(msgwindow.windowskin, 0, isDarkSkin)
@@ -602,11 +501,11 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
text = $~.post_match text = $~.post_match
end end
textchunks.push(text) textchunks.push(text)
for chunk in textchunks textchunks.each do |chunk|
chunk.gsub!(/\005/, "\\") chunk.gsub!(/\005/, "\\")
end end
textlen = 0 textlen = 0
for i in 0...controls.length controls.length.times do |i|
control = controls[i][0] control = controls[i][0]
case control case control
when "wt", "wtnp", ".", "|" when "wt", "wtnp", ".", "|"
@@ -617,12 +516,13 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
textlen += toUnformattedText(textchunks[i]).scan(/./m).length textlen += toUnformattedText(textchunks[i]).scan(/./m).length
controls[i][2] = textlen controls[i][2] = textlen
end end
text = textchunks.join("") text = textchunks.join
signWaitCount = 0 signWaitCount = 0
signWaitTime = Graphics.frame_rate / 2 signWaitTime = Graphics.frame_rate / 2
haveSpecialClose = false haveSpecialClose = false
specialCloseSE = "" specialCloseSE = ""
for i in 0...controls.length startSE = nil
controls.length.times do |i|
control = controls[i][0] control = controls[i][0]
param = controls[i][1] param = controls[i][1]
case control case control
@@ -633,10 +533,10 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
haveSpecialClose = true haveSpecialClose = true
specialCloseSE = param specialCloseSE = param
when "f" when "f"
facewindow.dispose if facewindow facewindow&.dispose
facewindow = PictureWindow.new("Graphics/Pictures/#{param}") facewindow = PictureWindow.new("Graphics/Pictures/#{param}")
when "ff" when "ff"
facewindow.dispose if facewindow facewindow&.dispose
facewindow = FaceWindowVX.new(param) facewindow = FaceWindowVX.new(param)
when "ch" when "ch"
cmds = param.clone cmds = param.clone
@@ -655,10 +555,10 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
end end
end end
end end
if startSE!=nil if startSE
pbSEPlay(pbStringToAudioFile(startSE)) pbSEPlay(pbStringToAudioFile(startSE))
elsif signWaitCount == 0 && letterbyletter elsif signWaitCount == 0 && letterbyletter
pbPlayDecisionSE() pbPlayDecisionSE
end end
########## Position message window ############## ########## Position message window ##############
pbRepositionMessageWindow(msgwindow, linecount) pbRepositionMessageWindow(msgwindow, linecount)
@@ -677,35 +577,35 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
if atTop if atTop
msgwindow.y = -msgwindow.height * signWaitCount / signWaitTime msgwindow.y = -msgwindow.height * signWaitCount / signWaitTime
else else
msgwindow.y = Graphics.height-msgwindow.height*(signWaitTime-signWaitCount)/signWaitTime msgwindow.y = Graphics.height - (msgwindow.height * (signWaitTime - signWaitCount) / signWaitTime)
end end
end end
for i in 0...controls.length controls.length.times do |i|
next if !controls[i] next if !controls[i]
next if controls[i][2] > msgwindow.position || msgwindow.waitcount != 0 next if controls[i][2] > msgwindow.position || msgwindow.waitcount != 0
control = controls[i][0] control = controls[i][0]
param = controls[i][1] param = controls[i][1]
case control case control
when "f" when "f"
facewindow.dispose if facewindow facewindow&.dispose
facewindow = PictureWindow.new("Graphics/Pictures/#{param}") facewindow = PictureWindow.new("Graphics/Pictures/#{param}")
pbPositionNearMsgWindow(facewindow, msgwindow, :left) pbPositionNearMsgWindow(facewindow, msgwindow, :left)
facewindow.viewport = msgwindow.viewport facewindow.viewport = msgwindow.viewport
facewindow.z = msgwindow.z facewindow.z = msgwindow.z
when "ff" when "ff"
facewindow.dispose if facewindow facewindow&.dispose
facewindow = FaceWindowVX.new(param) facewindow = FaceWindowVX.new(param)
pbPositionNearMsgWindow(facewindow, msgwindow, :left) pbPositionNearMsgWindow(facewindow, msgwindow, :left)
facewindow.viewport = msgwindow.viewport facewindow.viewport = msgwindow.viewport
facewindow.z = msgwindow.z facewindow.z = msgwindow.z
when "g" # Display gold window when "g" # Display gold window
goldwindow.dispose if goldwindow goldwindow&.dispose
goldwindow = pbDisplayGoldWindow(msgwindow) goldwindow = pbDisplayGoldWindow(msgwindow)
when "cn" # Display coins window when "cn" # Display coins window
coinwindow.dispose if coinwindow coinwindow&.dispose
coinwindow = pbDisplayCoinsWindow(msgwindow, goldwindow) coinwindow = pbDisplayCoinsWindow(msgwindow, goldwindow)
when "pt" # Display battle points window when "pt" # Display battle points window
battlepointswindow.dispose if battlepointswindow battlepointswindow&.dispose
battlepointswindow = pbDisplayBattlePointsWindow(msgwindow) battlepointswindow = pbDisplayBattlePointsWindow(msgwindow)
when "wu" when "wu"
msgwindow.y = 0 msgwindow.y = 0
@@ -723,7 +623,7 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
msgwindow.y = Graphics.height - msgwindow.height msgwindow.y = Graphics.height - msgwindow.height
msgback.y = msgwindow.y if msgback msgback.y = msgwindow.y if msgback
pbPositionNearMsgWindow(facewindow, msgwindow, :left) pbPositionNearMsgWindow(facewindow, msgwindow, :left)
msgwindow.y = Graphics.height-msgwindow.height*(signWaitTime-signWaitCount)/signWaitTime msgwindow.y = Graphics.height - (msgwindow.height * (signWaitTime - signWaitCount) / signWaitTime)
when "ts" # Change text speed when "ts" # Change text speed
msgwindow.textspeed = (param == "") ? -999 : param.to_i msgwindow.textspeed = (param == "") ? -999 : param.to_i
when "." # Wait 0.25 seconds when "." # Wait 0.25 seconds
@@ -749,7 +649,7 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
break if !letterbyletter break if !letterbyletter
Graphics.update Graphics.update
Input.update Input.update
facewindow.update if facewindow facewindow&.update
if autoresume && msgwindow.waitcount == 0 if autoresume && msgwindow.waitcount == 0
msgwindow.resume if msgwindow.busy? msgwindow.resume if msgwindow.busy?
break if !msgwindow.busy? break if !msgwindow.busy?
@@ -758,8 +658,8 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
if msgwindow.busy? if msgwindow.busy?
pbPlayDecisionSE if msgwindow.pausing? pbPlayDecisionSE if msgwindow.pausing?
msgwindow.resume msgwindow.resume
else elsif signWaitCount == 0
break if signWaitCount==0 break
end end
end end
pbUpdateSceneMap pbUpdateSceneMap
@@ -776,19 +676,19 @@ def pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
if commandProc if commandProc
ret = commandProc.call(msgwindow) ret = commandProc.call(msgwindow)
end end
msgback.dispose if msgback msgback&.dispose
goldwindow.dispose if goldwindow goldwindow&.dispose
coinwindow.dispose if coinwindow coinwindow&.dispose
battlepointswindow.dispose if battlepointswindow battlepointswindow&.dispose
facewindow.dispose if facewindow facewindow&.dispose
if haveSpecialClose if haveSpecialClose
pbSEPlay(pbStringToAudioFile(specialCloseSE)) pbSEPlay(pbStringToAudioFile(specialCloseSE))
atTop = (msgwindow.y == 0) atTop = (msgwindow.y == 0)
for i in 0..signWaitTime (0..signWaitTime).each do |i|
if atTop if atTop
msgwindow.y = -msgwindow.height * i / signWaitTime msgwindow.y = -msgwindow.height * i / signWaitTime
else else
msgwindow.y = Graphics.height-msgwindow.height*(signWaitTime-i)/signWaitTime msgwindow.y = Graphics.height - (msgwindow.height * (signWaitTime - i) / signWaitTime)
end end
Graphics.update Graphics.update
Input.update Input.update
@@ -851,7 +751,7 @@ def pbShowCommands(msgwindow,commands=nil,cmdIfCancel=0,defaultCmd=0)
Graphics.update Graphics.update
Input.update Input.update
cmdwindow.update cmdwindow.update
msgwindow.update if msgwindow msgwindow&.update
yield if block_given? yield if block_given?
if Input.trigger?(Input::BACK) if Input.trigger?(Input::BACK)
if cmdIfCancel > 0 if cmdIfCancel > 0
@@ -931,7 +831,7 @@ def pbMessageWaitForInput(msgwindow,frames,showPause=false)
frames.times do frames.times do
Graphics.update Graphics.update
Input.update Input.update
msgwindow.update if msgwindow msgwindow&.update
pbUpdateSceneMap pbUpdateSceneMap
if Input.trigger?(Input::USE) || Input.trigger?(Input::BACK) if Input.trigger?(Input::USE) || Input.trigger?(Input::BACK)
break break
@@ -962,7 +862,7 @@ def pbFreeText(msgwindow,currenttext,passwordbox,maxlength,width=240)
break break
end end
window.update window.update
msgwindow.update if msgwindow msgwindow&.update
yield if block_given? yield if block_given?
end end
Input.text_input = false Input.text_input = false

View File

@@ -2,7 +2,7 @@
# #
#=============================================================================== #===============================================================================
class CharacterEntryHelper class CharacterEntryHelper
attr_reader :text attr_accessor :text
attr_accessor :maxlength attr_accessor :maxlength
attr_reader :passwordChar attr_reader :passwordChar
attr_accessor :cursor attr_accessor :cursor
@@ -14,10 +14,6 @@ class CharacterEntryHelper
@cursor = text.scan(/./m).length @cursor = text.scan(/./m).length
end end
def text=(value)
@text=value
end
def textChars def textChars
chars = text.scan(/./m) chars = text.scan(/./m)
if @passwordChar != "" if @passwordChar != ""
@@ -27,7 +23,7 @@ class CharacterEntryHelper
end end
def passwordChar=(value) def passwordChar=(value)
@passwordChar=value ? value : "" @passwordChar = value || ""
end end
def length def length
@@ -45,7 +41,7 @@ class CharacterEntryHelper
return false if @maxlength >= 0 && chars.length >= @maxlength return false if @maxlength >= 0 && chars.length >= @maxlength
chars.insert(@cursor, ch) chars.insert(@cursor, ch)
@text = "" @text = ""
for ch in chars chars.each do |ch|
@text += ch if ch @text += ch if ch
end end
@cursor += 1 @cursor += 1
@@ -63,7 +59,7 @@ class CharacterEntryHelper
return false if chars.length <= 0 || @cursor <= 0 return false if chars.length <= 0 || @cursor <= 0
chars.delete_at(@cursor - 1) chars.delete_at(@cursor - 1)
@text = "" @text = ""
for ch in chars chars.each do |ch|
@text += ch if ch @text += ch if ch
end end
@cursor -= 1 @cursor -= 1
@@ -79,7 +75,7 @@ class CharacterEntryHelper
chars = chars[0, @maxlength] chars = chars[0, @maxlength]
end end
@text = "" @text = ""
for ch in chars chars.each do |ch|
@text += ch if ch @text += ch if ch
end end
end end
@@ -196,13 +192,13 @@ class Window_TextEntry < SpriteWindow_Base
@helper.cursor = 0 if @helper.cursor < 0 @helper.cursor = 0 if @helper.cursor < 0
startpos = @helper.cursor startpos = @helper.cursor
fromcursor = 0 fromcursor = 0
while (startpos>0) while startpos > 0
c = (@helper.passwordChar != "") ? @helper.passwordChar : textscan[startpos - 1] c = (@helper.passwordChar != "") ? @helper.passwordChar : textscan[startpos - 1]
fromcursor += bitmap.text_size(c).width fromcursor += bitmap.text_size(c).width
break if fromcursor > width - 4 break if fromcursor > width - 4
startpos -= 1 startpos -= 1
end end
for i in startpos...scanlength (startpos...scanlength).each do |i|
c = (@helper.passwordChar != "") ? @helper.passwordChar : textscan[i] c = (@helper.passwordChar != "") ? @helper.passwordChar : textscan[i]
textwidth = bitmap.text_size(c).width textwidth = bitmap.text_size(c).width
next if c == "\n" next if c == "\n"
@@ -230,7 +226,7 @@ class Window_TextEntry_Keyboard < Window_TextEntry
def update def update
@frame += 1 @frame += 1
@frame %= 20 @frame %= 20
self.refresh if ((@frame%10)==0) self.refresh if (@frame % 10) == 0
return if !self.active return if !self.active
# Moving cursor # Moving cursor
if Input.triggerex?(:LEFT) || Input.repeatex?(:LEFT) if Input.triggerex?(:LEFT) || Input.repeatex?(:LEFT)
@@ -352,13 +348,13 @@ class Window_MultilineTextEntry < SpriteWindow_Base
def getLineY(line) def getLineY(line)
textchars = getTextChars textchars = getTextChars
return 0 if textchars.length == 0 return 0 if textchars.length == 0
totallines=getTotalLines() totallines = getTotalLines
line = 0 if line < 0 line = 0 if line < 0
line = totallines - 1 if line >= totallines line = totallines - 1 if line >= totallines
maximumY = 0 maximumY = 0
for i in 0...textchars.length textchars.each do |text|
thisline=textchars[i][5] thisline = text[5]
y=textchars[i][2] y = text[2]
return y if thisline == line return y if thisline == line
maximumY = y if maximumY < y maximumY = y if maximumY < y
end end
@@ -368,13 +364,13 @@ class Window_MultilineTextEntry < SpriteWindow_Base
def getColumnsInLine(line) def getColumnsInLine(line)
textchars = getTextChars textchars = getTextChars
return 0 if textchars.length == 0 return 0 if textchars.length == 0
totallines=getTotalLines() totallines = getTotalLines
line = 0 if line < 0 line = 0 if line < 0
line = totallines - 1 if line >= totallines line = totallines - 1 if line >= totallines
endpos = 0 endpos = 0
for i in 0...textchars.length textchars.each do |text|
thisline=textchars[i][5] thisline = text[5]
thislength=textchars[i][8] thislength = text[8]
endpos += thislength if thisline == line endpos += thislength if thisline == line
end end
return endpos return endpos
@@ -383,15 +379,15 @@ class Window_MultilineTextEntry < SpriteWindow_Base
def getPosFromLineAndColumn(line, column) def getPosFromLineAndColumn(line, column)
textchars = getTextChars textchars = getTextChars
return 0 if textchars.length == 0 return 0 if textchars.length == 0
totallines=getTotalLines() totallines = getTotalLines
line = 0 if line < 0 line = 0 if line < 0
line = totallines - 1 if line >= totallines line = totallines - 1 if line >= totallines
endpos = 0 endpos = 0
for i in 0...textchars.length textchars.each do |text|
thisline=textchars[i][5] thisline = text[5]
thispos=textchars[i][6] thispos = text[6]
thiscolumn=textchars[i][7] thiscolumn = text[7]
thislength=textchars[i][8] thislength = text[8]
if thisline == line if thisline == line
endpos = thispos + thislength endpos = thispos + thislength
# echoln [endpos,thispos+(column-thiscolumn),textchars[i]] # echoln [endpos,thispos+(column-thiscolumn),textchars[i]]
@@ -409,7 +405,7 @@ class Window_MultilineTextEntry < SpriteWindow_Base
end end
def getLastVisibleLine def getLastVisibleLine
getTextChars() getTextChars
textheight = [1, self.contents.text_size("X").height].max textheight = [1, self.contents.text_size("X").height].max
lastVisible = @firstline + ((self.height - self.borderY) / textheight) - 1 lastVisible = @firstline + ((self.height - self.borderY) / textheight) - 1
return lastVisible return lastVisible
@@ -423,7 +419,7 @@ class Window_MultilineTextEntry < SpriteWindow_Base
self.refresh self.refresh
end end
@firstline = @cursorLine if @cursorLine < @firstline @firstline = @cursorLine if @cursorLine < @firstline
lastVisible=getLastVisibleLine() lastVisible = getLastVisibleLine
@firstline += (@cursorLine - lastVisible) if @cursorLine > lastVisible @firstline += (@cursorLine - lastVisible) if @cursorLine > lastVisible
end end
@@ -432,7 +428,7 @@ class Window_MultilineTextEntry < SpriteWindow_Base
# can affect line offset) # can affect line offset)
# echoln ["beforemoving",@cursorLine,@cursorColumn] # echoln ["beforemoving",@cursorLine,@cursorColumn]
totalColumns = getColumnsInLine(@cursorLine) # check current line totalColumns = getColumnsInLine(@cursorLine) # check current line
totalLines=getTotalLines() totalLines = getTotalLines
oldCursorLine = @cursorLine oldCursorLine = @cursorLine
oldCursorColumn = @cursorColumn oldCursorColumn = @cursorColumn
@cursorColumn += columnOffset @cursorColumn += columnOffset
@@ -457,17 +453,14 @@ class Window_MultilineTextEntry < SpriteWindow_Base
totalColumns = getColumnsInLine(@cursorLine) totalColumns = getColumnsInLine(@cursorLine)
@cursorColumn = totalColumns if @cursorColumn > totalColumns @cursorColumn = totalColumns if @cursorColumn > totalColumns
@cursorColumn = 0 if @cursorColumn < 0 # totalColumns can be 0 @cursorColumn = 0 if @cursorColumn < 0 # totalColumns can be 0
updateCursorPos( updateCursorPos(oldCursorLine != @cursorLine || oldCursorColumn != @cursorColumn)
oldCursorLine!=@cursorLine ||
oldCursorColumn!=@cursorColumn
)
# echoln ["aftermoving",@cursorLine,@cursorColumn] # echoln ["aftermoving",@cursorLine,@cursorColumn]
end end
def update def update
@frame += 1 @frame += 1
@frame %= 20 @frame %= 20
self.refresh if ((@frame%10)==0) self.refresh if (@frame % 10) == 0
return if !self.active return if !self.active
# Moving cursor # Moving cursor
if Input.triggerex?(:UP) || Input.repeatex?(:UP) if Input.triggerex?(:UP) || Input.repeatex?(:UP)
@@ -491,7 +484,7 @@ class Window_MultilineTextEntry < SpriteWindow_Base
return return
elsif Input.press?(Input::CTRL) && Input.triggerex?(:END) elsif Input.press?(Input::CTRL) && Input.triggerex?(:END)
# Move cursor to end # Move cursor to end
@cursorLine=getTotalLines()-1 @cursorLine = getTotalLines - 1
@cursorColumn = getColumnsInLine(@cursorLine) @cursorColumn = getColumnsInLine(@cursorLine)
updateCursorPos(true) updateCursorPos(true)
return return
@@ -515,42 +508,41 @@ class Window_MultilineTextEntry < SpriteWindow_Base
getTextChars getTextChars
height = self.height - self.borderY height = self.height - self.borderY
cursorcolor = Color.new(0, 0, 0) cursorcolor = Color.new(0, 0, 0)
textchars=getTextChars() textchars = getTextChars
startY = getLineY(@firstline) startY = getLineY(@firstline)
for i in 0...textchars.length textchars.each do |text|
thisline=textchars[i][5] thisline = text[5]
thiscolumn=textchars[i][7] thislength = text[8]
thislength=textchars[i][8] textY = text[2] - startY
textY=textchars[i][2]-startY
# Don't draw lines before the first or zero-length segments # Don't draw lines before the first or zero-length segments
next if thisline < @firstline || thislength == 0 next if thisline < @firstline || thislength == 0
# Don't draw lines beyond the window's height # Don't draw lines beyond the window's height
break if textY >= height break if textY >= height
c=textchars[i][0] c = text[0]
# Don't draw spaces # Don't draw spaces
next if c == " " next if c == " "
textwidth=textchars[i][3]+4 # add 4 to prevent draw_text from stretching text textwidth = text[3] + 4 # add 4 to prevent draw_text from stretching text
textheight=textchars[i][4] textheight = text[4]
# Draw text # Draw text
pbDrawShadowText(bitmap, textchars[i][1], textY, textwidth, textheight, c, @baseColor, @shadowColor) pbDrawShadowText(bitmap, text[1], textY, textwidth, textheight, c, @baseColor, @shadowColor)
end end
# Draw cursor # Draw cursor
if ((@frame / 10) & 1) == 0 if ((@frame / 10) & 1) == 0
textheight = bitmap.text_size("X").height textheight = bitmap.text_size("X").height
cursorY = (textheight * @cursorLine) - startY cursorY = (textheight * @cursorLine) - startY
cursorX = 0 cursorX = 0
for i in 0...textchars.length textchars.each do |text|
thisline=textchars[i][5] thisline = text[5]
thiscolumn=textchars[i][7] thiscolumn = text[7]
thislength=textchars[i][8] thislength = text[8]
if thisline == @cursorLine && @cursorColumn >= thiscolumn && if thisline == @cursorLine && @cursorColumn >= thiscolumn &&
@cursorColumn <= thiscolumn + thislength @cursorColumn <= thiscolumn + thislength
cursorY=textchars[i][2]-startY cursorY = text[2] - startY
cursorX=textchars[i][1] cursorX = text[1]
textheight=textchars[i][4] textheight = text[4]
posToCursor = @cursorColumn - thiscolumn posToCursor = @cursorColumn - thiscolumn
if posToCursor >= 0 if posToCursor >= 0
partialString=textchars[i][0].scan(/./m)[0,posToCursor].join("") partialString = text[0].scan(/./m)[0, posToCursor].join
cursorX += bitmap.text_size(partialString).width cursorX += bitmap.text_size(partialString).width
end end
break break

View File

@@ -4,7 +4,7 @@
$AtExitProcs = [] if !$AtExitProcs $AtExitProcs = [] if !$AtExitProcs
def exit(code = 0) def exit(code = 0)
for p in $AtExitProcs $AtExitProcs.each do |p|
p.call p.call
end end
raise SystemExit.new(code) raise SystemExit.new(code)
@@ -51,7 +51,7 @@ def oggfiletime(file)
i = -1 i = -1
pcmlengths = [] pcmlengths = []
rates = [] rates = []
for page in pages pages.each do |page|
header = page[0] header = page[0]
serial = header[10, 4].unpack("V") serial = header[10, 4].unpack("V")
frame = header[2, 8].unpack("C*") frame = header[2, 8].unpack("C*")
@@ -78,9 +78,7 @@ def oggfiletime(file)
pcmlengths[i] = frameno pcmlengths[i] = frameno
end end
ret = 0.0 ret = 0.0
for i in 0...pcmlengths.length pcmlengths.each_with_index { |length, i| ret += length.to_f / rates[i] }
ret += pcmlengths[i].to_f / rates[i].to_f
end
return ret * 256.0 return ret * 256.0
end end
@@ -110,36 +108,37 @@ def getPlayTime2(filename)
File.open(filename, "rb") { |file| File.open(filename, "rb") { |file|
file.pos = 0 file.pos = 0
fdw = fgetdw.call(file) fdw = fgetdw.call(file)
if fdw == 0x46464952 # "RIFF" case fdw
when 0x46464952 # "RIFF"
filesize = fgetdw.call(file) filesize = fgetdw.call(file)
wave = fgetdw.call(file) wave = fgetdw.call(file)
return -1 if wave != 0x45564157 # "WAVE" return -1 if wave != 0x45564157 # "WAVE"
fmt = fgetdw.call(file) fmt = fgetdw.call(file)
return -1 if fmt != 0x20746d66 # "fmt " return -1 if fmt != 0x20746d66 # "fmt "
fmtsize = fgetdw.call(file) fgetdw.call(file) # fmtsize
format = fgetw.call(file) fgetw.call(file) # format
channels = fgetw.call(file) fgetw.call(file) # channels
rate = fgetdw.call(file) fgetdw.call(file) # rate
bytessec = fgetdw.call(file) bytessec = fgetdw.call(file)
return -1 if bytessec == 0 return -1 if bytessec == 0
bytessample = fgetw.call(file) fgetw.call(file) # bytessample
bitssample = fgetw.call(file) fgetw.call(file) # bitssample
data = fgetdw.call(file) data = fgetdw.call(file)
return -1 if data != 0x61746164 # "data" return -1 if data != 0x61746164 # "data"
datasize = fgetdw.call(file) datasize = fgetdw.call(file)
time = (datasize*1.0)/bytessec time = datasize.to_f / bytessec
return time return time
elsif fdw == 0x5367674F # "OggS" when 0x5367674F # "OggS"
file.pos = 0 file.pos = 0
time = oggfiletime(file) time = oggfiletime(file)
return time return time
end end
file.pos = 0 file.pos = 0
# Find the length of an MP3 file # Find the length of an MP3 file
while true loop do
rstr = "" rstr = ""
ateof = false ateof = false
while !file.eof? until file.eof?
if (file.read(1)[0] rescue 0) == 0xFF if (file.read(1)[0] rescue 0) == 0xFF
begin begin
rstr = file.read(3) rstr = file.read(3)
@@ -152,15 +151,15 @@ def getPlayTime2(filename)
break if ateof || !rstr || rstr.length != 3 break if ateof || !rstr || rstr.length != 3
if rstr[0] == 0xFB if rstr[0] == 0xFB
t = rstr[1] >> 4 t = rstr[1] >> 4
next if t == 0 || t == 15 next if [0, 15].include?(t)
freqs = [44100, 22050, 11025, 48000] freqs = [44_100, 22_050, 11_025, 48_000]
bitrates = [32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320] bitrates = [32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320]
bitrate = bitrates[t] bitrate = bitrates[t]
t = (rstr[1] >> 2) & 3 t = (rstr[1] >> 2) & 3
freq = freqs[t] freq = freqs[t]
t = (rstr[1] >> 1) & 1 t = (rstr[1] >> 1) & 1
filesize = FileTest.size(filename) filesize = FileTest.size(filename)
frameLength = ((144000 * bitrate) / freq) + t frameLength = ((144_000 * bitrate) / freq) + t
numFrames = filesize / (frameLength + 4) numFrames = filesize / (frameLength + 4)
time = (numFrames * 1152.0 / freq) time = (numFrames * 1152.0 / freq)
break break

View File

@@ -53,12 +53,12 @@ def pbBGMPlay(param,volume=nil,pitch=nil)
return if !param return if !param
param = pbResolveAudioFile(param, volume, pitch) param = pbResolveAudioFile(param, volume, pitch)
if param.name && param.name != "" if param.name && param.name != ""
if $game_system && $game_system.respond_to?("bgm_play") if $game_system
$game_system.bgm_play(param) $game_system.bgm_play(param)
return return
elsif (RPG.const_defined?(:BGM) rescue false) elsif (RPG.const_defined?(:BGM) rescue false)
b = RPG::BGM.new(param.name, param.volume, param.pitch) b = RPG::BGM.new(param.name, param.volume, param.pitch)
if b && b.respond_to?("play") if b.respond_to?("play")
b.play b.play
return return
end end
@@ -72,10 +72,10 @@ def pbBGMFade(x=0.0); pbBGMStop(x);end
# Fades out or stops BGM playback. 'x' is the time in seconds to fade out. # Fades out or stops BGM playback. 'x' is the time in seconds to fade out.
def pbBGMStop(timeInSeconds = 0.0) def pbBGMStop(timeInSeconds = 0.0)
if $game_system && timeInSeconds>0.0 && $game_system.respond_to?("bgm_fade") if $game_system && timeInSeconds > 0.0
$game_system.bgm_fade(timeInSeconds) $game_system.bgm_fade(timeInSeconds)
return return
elsif $game_system && $game_system.respond_to?("bgm_stop") elsif $game_system
$game_system.bgm_stop $game_system.bgm_stop
return return
elsif (RPG.const_defined?(:BGM) rescue false) elsif (RPG.const_defined?(:BGM) rescue false)
@@ -103,13 +103,14 @@ def pbMEPlay(param,volume=nil,pitch=nil)
return if !param return if !param
param = pbResolveAudioFile(param, volume, pitch) param = pbResolveAudioFile(param, volume, pitch)
if param.name && param.name != "" if param.name && param.name != ""
if $game_system && $game_system.respond_to?("me_play") if $game_system
$game_system.me_play(param) $game_system.me_play(param)
return return
elsif (RPG.const_defined?(:ME) rescue false) elsif (RPG.const_defined?(:ME) rescue false)
b = RPG::ME.new(param.name, param.volume, param.pitch) b = RPG::ME.new(param.name, param.volume, param.pitch)
if b && b.respond_to?("play") if b.respond_to?("play")
b.play; return b.play
return
end end
end end
Audio.me_play(canonicalize("Audio/ME/" + param.name), param.volume, param.pitch) Audio.me_play(canonicalize("Audio/ME/" + param.name), param.volume, param.pitch)
@@ -124,7 +125,7 @@ def pbMEStop(timeInSeconds=0.0)
if $game_system && timeInSeconds > 0.0 && $game_system.respond_to?("me_fade") if $game_system && timeInSeconds > 0.0 && $game_system.respond_to?("me_fade")
$game_system.me_fade(timeInSeconds) $game_system.me_fade(timeInSeconds)
return return
elsif $game_system && $game_system.respond_to?("me_stop") elsif $game_system.respond_to?("me_stop")
$game_system.me_stop(nil) $game_system.me_stop(nil)
return return
elsif (RPG.const_defined?(:ME) rescue false) elsif (RPG.const_defined?(:ME) rescue false)
@@ -152,13 +153,14 @@ def pbBGSPlay(param,volume=nil,pitch=nil)
return if !param return if !param
param = pbResolveAudioFile(param, volume, pitch) param = pbResolveAudioFile(param, volume, pitch)
if param.name && param.name != "" if param.name && param.name != ""
if $game_system && $game_system.respond_to?("bgs_play") if $game_system
$game_system.bgs_play(param) $game_system.bgs_play(param)
return return
elsif (RPG.const_defined?(:BGS) rescue false) elsif (RPG.const_defined?(:BGS) rescue false)
b = RPG::BGS.new(param.name, param.volume, param.pitch) b = RPG::BGS.new(param.name, param.volume, param.pitch)
if b && b.respond_to?("play") if b.respond_to?("play")
b.play; return b.play
return
end end
end end
Audio.bgs_play(canonicalize("Audio/BGS/" + param.name), param.volume, param.pitch) Audio.bgs_play(canonicalize("Audio/BGS/" + param.name), param.volume, param.pitch)
@@ -170,10 +172,10 @@ def pbBGSFade(x=0.0); pbBGSStop(x);end
# Fades out or stops BGS playback. 'x' is the time in seconds to fade out. # Fades out or stops BGS playback. 'x' is the time in seconds to fade out.
def pbBGSStop(timeInSeconds = 0.0) def pbBGSStop(timeInSeconds = 0.0)
if $game_system && timeInSeconds>0.0 && $game_system.respond_to?("bgs_fade") if $game_system && timeInSeconds > 0.0
$game_system.bgs_fade(timeInSeconds) $game_system.bgs_fade(timeInSeconds)
return return
elsif $game_system && $game_system.respond_to?("bgs_play") elsif $game_system
$game_system.bgs_play(nil) $game_system.bgs_play(nil)
return return
elsif (RPG.const_defined?(:BGS) rescue false) elsif (RPG.const_defined?(:BGS) rescue false)
@@ -201,13 +203,13 @@ def pbSEPlay(param,volume=nil,pitch=nil)
return if !param return if !param
param = pbResolveAudioFile(param, volume, pitch) param = pbResolveAudioFile(param, volume, pitch)
if param.name && param.name != "" if param.name && param.name != ""
if $game_system && $game_system.respond_to?("se_play") if $game_system
$game_system.se_play(param) $game_system.se_play(param)
return return
end end
if (RPG.const_defined?(:SE) rescue false) if (RPG.const_defined?(:SE) rescue false)
b = RPG::SE.new(param.name, param.volume, param.pitch) b = RPG::SE.new(param.name, param.volume, param.pitch)
if b && b.respond_to?("play") if b.respond_to?("play")
b.play b.play
return return
end end
@@ -234,12 +236,8 @@ end
# Plays a sound effect that plays when the player moves the cursor. # Plays a sound effect that plays when the player moves the cursor.
def pbPlayCursorSE def pbPlayCursorSE
if $data_system && $data_system.respond_to?("cursor_se") && if !nil_or_empty?($data_system&.cursor_se&.name)
$data_system.cursor_se && $data_system.cursor_se.name!=""
pbSEPlay($data_system.cursor_se) pbSEPlay($data_system.cursor_se)
elsif $data_system && $data_system.respond_to?("sounds") &&
$data_system.sounds && $data_system.sounds[0] && $data_system.sounds[0].name!=""
pbSEPlay($data_system.sounds[0])
elsif FileTest.audio_exist?("Audio/SE/GUI sel cursor") elsif FileTest.audio_exist?("Audio/SE/GUI sel cursor")
pbSEPlay("GUI sel cursor", 80) pbSEPlay("GUI sel cursor", 80)
end end
@@ -247,12 +245,8 @@ end
# Plays a sound effect that plays when a decision is confirmed or a choice is made. # Plays a sound effect that plays when a decision is confirmed or a choice is made.
def pbPlayDecisionSE def pbPlayDecisionSE
if $data_system && $data_system.respond_to?("decision_se") && if !nil_or_empty?($data_system&.decision_se&.name)
$data_system.decision_se && $data_system.decision_se.name!=""
pbSEPlay($data_system.decision_se) pbSEPlay($data_system.decision_se)
elsif $data_system && $data_system.respond_to?("sounds") &&
$data_system.sounds && $data_system.sounds[1] && $data_system.sounds[1].name!=""
pbSEPlay($data_system.sounds[1])
elsif FileTest.audio_exist?("Audio/SE/GUI sel decision") elsif FileTest.audio_exist?("Audio/SE/GUI sel decision")
pbSEPlay("GUI sel decision", 80) pbSEPlay("GUI sel decision", 80)
end end
@@ -260,12 +254,8 @@ end
# Plays a sound effect that plays when a choice is canceled. # Plays a sound effect that plays when a choice is canceled.
def pbPlayCancelSE def pbPlayCancelSE
if $data_system && $data_system.respond_to?("cancel_se") && if !nil_or_empty?($data_system&.cancel_se&.name)
$data_system.cancel_se && $data_system.cancel_se.name!=""
pbSEPlay($data_system.cancel_se) pbSEPlay($data_system.cancel_se)
elsif $data_system && $data_system.respond_to?("sounds") &&
$data_system.sounds && $data_system.sounds[2] && $data_system.sounds[2].name!=""
pbSEPlay($data_system.sounds[2])
elsif FileTest.audio_exist?("Audio/SE/GUI sel cancel") elsif FileTest.audio_exist?("Audio/SE/GUI sel cancel")
pbSEPlay("GUI sel cancel", 80) pbSEPlay("GUI sel cancel", 80)
end end
@@ -273,12 +263,8 @@ end
# Plays a buzzer sound effect. # Plays a buzzer sound effect.
def pbPlayBuzzerSE def pbPlayBuzzerSE
if $data_system && $data_system.respond_to?("buzzer_se") && if !nil_or_empty?($data_system&.buzzer_se&.name)
$data_system.buzzer_se && $data_system.buzzer_se.name!=""
pbSEPlay($data_system.buzzer_se) pbSEPlay($data_system.buzzer_se)
elsif $data_system && $data_system.respond_to?("sounds") &&
$data_system.sounds && $data_system.sounds[3] && $data_system.sounds[3].name!=""
pbSEPlay($data_system.sounds[3])
elsif FileTest.audio_exist?("Audio/SE/GUI sel buzzer") elsif FileTest.audio_exist?("Audio/SE/GUI sel buzzer")
pbSEPlay("GUI sel buzzer", 80) pbSEPlay("GUI sel buzzer", 80)
end end

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ class PictureSprite < SpriteWrapper
end end
def dispose def dispose
@pictureBitmap.dispose if @pictureBitmap @pictureBitmap&.dispose
super super
end end
@@ -22,7 +22,7 @@ class PictureSprite < SpriteWrapper
def update def update
super super
@pictureBitmap.update if @pictureBitmap @pictureBitmap&.update
# If picture file name is different from current one # If picture file name is different from current one
if @customBitmap && @picture.name == "" if @customBitmap && @picture.name == ""
self.bitmap = (@customBitmapIsBitmap) ? @customBitmap : @customBitmap.bitmap self.bitmap = (@customBitmapIsBitmap) ? @customBitmap : @customBitmap.bitmap
@@ -32,13 +32,13 @@ class PictureSprite < SpriteWrapper
@hue = @picture.hue.to_i @hue = @picture.hue.to_i
# If file name is not empty # If file name is not empty
if @picture_name == "" if @picture_name == ""
@pictureBitmap.dispose if @pictureBitmap @pictureBitmap&.dispose
@pictureBitmap = nil @pictureBitmap = nil
self.visible = false self.visible = false
return return
end end
# Get picture graphic # Get picture graphic
@pictureBitmap.dispose if @pictureBitmap @pictureBitmap&.dispose
@pictureBitmap = AnimatedBitmap.new(@picture_name, @hue) @pictureBitmap = AnimatedBitmap.new(@picture_name, @hue)
self.bitmap = (@pictureBitmap) ? @pictureBitmap.bitmap : nil self.bitmap = (@pictureBitmap) ? @pictureBitmap.bitmap : nil
elsif @picture_name == "" elsif @picture_name == ""
@@ -55,7 +55,7 @@ end
def pbTextBitmap(text, maxwidth = Graphics.width) def pbTextBitmap(text, maxwidth = Graphics.width)
tmp = Bitmap.new(maxwidth, Graphics.height) tmp = Bitmap.new(maxwidth, Graphics.height)
pbSetSystemFont(tmp) pbSetSystemFont(tmp)
drawFormattedTextEx(tmp,0,0,maxwidth,text,Color.new(248,248,248),Color.new(168,184,184)) drawFormattedTextEx(tmp, 0, 4, maxwidth, text, Color.new(248, 248, 248), Color.new(168, 184, 184))
return tmp return tmp
end end
@@ -80,10 +80,10 @@ class EventScene
def dispose def dispose
return if disposed? return if disposed?
for sprite in @picturesprites @picturesprites.each do |sprite|
sprite.dispose sprite.dispose
end end
for sprite in @usersprites @usersprites.each do |sprite|
sprite.dispose sprite.dispose
end end
@onCTrigger.clear @onCTrigger.clear
@@ -143,7 +143,7 @@ class EventScene
def pictureWait(extraframes = 0) def pictureWait(extraframes = 0)
loop do loop do
hasRunning = false hasRunning = false
for pic in @pictures @pictures.each do |pic|
hasRunning = true if pic.running? hasRunning = true if pic.running?
end end
break if !hasRunning break if !hasRunning
@@ -156,13 +156,13 @@ class EventScene
return if disposed? return if disposed?
Graphics.update Graphics.update
Input.update Input.update
for picture in @pictures @pictures.each do |picture|
picture.update picture.update
end end
for sprite in @picturesprites @picturesprites.each do |sprite|
sprite.update sprite.update
end end
for sprite in @usersprites @usersprites.each do |sprite|
next if !sprite || sprite.disposed? || !sprite.is_a?(Sprite) next if !sprite || sprite.disposed? || !sprite.is_a?(Sprite)
sprite.update sprite.update
end end
@@ -175,7 +175,7 @@ class EventScene
end end
def main def main
while !disposed? until disposed?
update update
end end
end end

View File

@@ -26,9 +26,6 @@ module GameData
validate other => [Symbol, self, String, Integer] validate other => [Symbol, self, String, Integer]
return other if other.is_a?(self) return other if other.is_a?(self)
other = other.to_sym if other.is_a?(String) other = other.to_sym if other.is_a?(String)
# if other.is_a?(Integer)
# p "Please switch to symbols, thanks."
# end
raise "Unknown ID #{other}." unless self::DATA.has_key?(other) raise "Unknown ID #{other}." unless self::DATA.has_key?(other)
return self::DATA[other] return self::DATA[other]
end end
@@ -40,9 +37,6 @@ module GameData
validate other => [Symbol, self, String, Integer] validate other => [Symbol, self, String, Integer]
return other if other.is_a?(self) return other if other.is_a?(self)
other = other.to_sym if other.is_a?(String) other = other.to_sym if other.is_a?(String)
# if other.is_a?(Integer)
# p "Please switch to symbols, thanks."
# end
return (self::DATA.has_key?(other)) ? self::DATA[other] : nil return (self::DATA.has_key?(other)) ? self::DATA[other] : nil
end end
@@ -54,8 +48,12 @@ module GameData
# Yields all data in order of their id_number. # Yields all data in order of their id_number.
def each def each
keys = self::DATA.keys.sort { |a, b| self::DATA[a].id_number <=> self::DATA[b].id_number } sorted_keys = self::DATA.keys.sort { |a, b| self::DATA[a].id_number <=> self::DATA[b].id_number }
keys.each { |key| yield self::DATA[key] if !key.is_a?(Integer) } sorted_keys.each { |key| yield self::DATA[key] if !key.is_a?(Integer) }
end
def count
return self::DATA.length / 2
end end
def load def load
@@ -114,12 +112,21 @@ module GameData
return self::DATA.keys return self::DATA.keys
end end
# Yields all data in alphabetical order. # Yields all data in the order they were defined.
def each def each
self::DATA.each_value { |value| yield value }
end
# Yields all data in alphabetical order.
def each_alphabetically
keys = self::DATA.keys.sort { |a, b| self::DATA[a].real_name <=> self::DATA[b].real_name } keys = self::DATA.keys.sort { |a, b| self::DATA[a].real_name <=> self::DATA[b].real_name }
keys.each { |key| yield self::DATA[key] } keys.each { |key| yield self::DATA[key] }
end end
def count
return self::DATA.length
end
def load def load
const_set(:DATA, load_data("Data/#{self::DATA_FILENAME}")) const_set(:DATA, load_data("Data/#{self::DATA_FILENAME}"))
end end
@@ -177,6 +184,10 @@ module GameData
keys.each { |key| yield self::DATA[key] } keys.each { |key| yield self::DATA[key] }
end end
def count
return self::DATA.length
end
def load def load
const_set(:DATA, load_data("Data/#{self::DATA_FILENAME}")) const_set(:DATA, load_data("Data/#{self::DATA_FILENAME}"))
end end
@@ -196,13 +207,14 @@ module GameData
# @return [Boolean] whether other represents the same thing as this thing # @return [Boolean] whether other represents the same thing as this thing
def ==(other) def ==(other)
return false if other.nil? return false if other.nil?
if other.is_a?(Symbol) case other
when Symbol
return @id == other return @id == other
elsif other.is_a?(self.class) when self.class
return @id == other.id return @id == other.id
elsif other.is_a?(String) when String
return @id_number == other.to_sym return @id == other.to_sym
elsif other.is_a?(Integer) when Integer
return @id_number == other return @id_number == other
end end
return false return false
@@ -219,11 +231,14 @@ module GameData
Item.load Item.load
BerryPlant.load BerryPlant.load
Species.load Species.load
SpeciesMetrics.load
ShadowPokemon.load
Ribbon.load Ribbon.load
Encounter.load Encounter.load
TrainerType.load TrainerType.load
Trainer.load Trainer.load
Metadata.load Metadata.load
PlayerMetadata.load
MapMetadata.load MapMetadata.load
end end
end end

View File

@@ -64,7 +64,7 @@ module GameData
return ArgumentError.new("Exp amount #{level} is invalid.") if !exp || exp < 0 return ArgumentError.new("Exp amount #{level} is invalid.") if !exp || exp < 0
max = GrowthRate.max_level max = GrowthRate.max_level
return max if exp >= maximum_exp return max if exp >= maximum_exp
for level in 1..max (1..max).each do |level|
return level - 1 if exp < minimum_exp_for_level(level) return level - 1 if exp < minimum_exp_for_level(level)
end end
return max return max
@@ -133,7 +133,7 @@ GameData::GrowthRate.register({
765275, 804997, 834809, 877201, 908905, 954084, 987754, 1035837, 1071552, 1122660, 765275, 804997, 834809, 877201, 908905, 954084, 987754, 1035837, 1071552, 1122660,
1160499, 1214753, 1254796, 1312322, 1354652, 1415577, 1460276, 1524731, 1571884, 1640000], 1160499, 1214753, 1254796, 1312322, 1354652, 1415577, 1460276, 1524731, 1571884, 1640000],
:exp_formula => proc { |level| :exp_formula => proc { |level|
rate = [82 - (level - 100) / 2.0, 40].max rate = [82 - ((level - 100) / 2.0), 40].max
next (level**4) * rate / 5000 next (level**4) * rate / 5000
} }
}) })
@@ -152,7 +152,7 @@ GameData::GrowthRate.register({
360838, 377197, 394045, 411388, 429235, 447591, 466464, 485862, 505791, 526260, 360838, 377197, 394045, 411388, 429235, 447591, 466464, 485862, 505791, 526260,
547274, 568841, 590969, 613664, 636935, 660787, 685228, 710266, 735907, 762160, 547274, 568841, 590969, 613664, 636935, 660787, 685228, 710266, 735907, 762160,
789030, 816525, 844653, 873420, 902835, 932903, 963632, 995030, 1027103, 1059860], 789030, 816525, 844653, 873420, 902835, 932903, 963632, 995030, 1027103, 1059860],
:exp_formula => proc { |level| next ((level ** 3) * 6 / 5) - 15 * (level ** 2) + 100 * level - 140 } :exp_formula => proc { |level| next ((level**3) * 6 / 5) - (15 * (level**2)) + (100 * level) - 140 }
}) })
GameData::GrowthRate.register({ GameData::GrowthRate.register({

View File

@@ -26,6 +26,12 @@ module GameData
def name def name
return _INTL(@real_name) return _INTL(@real_name)
end end
# @return [Boolean] whether a Pokémon with this gender ratio can only ever
# be a single gender
def single_gendered?
return @female_chance.nil?
end
end end
end end

View File

@@ -1,17 +1,16 @@
# NOTE: The id_number is only used to determine the order that body shapes are # NOTE: The order these shapes are registered are the order they are listed in
# listed in the Pokédex search screen. Number 0 (:None) is ignored; they # the Pokédex search screen.
# start with shape 1.
# "Graphics/Pictures/Pokedex/icon_shapes.png" contains icons for these # "Graphics/Pictures/Pokedex/icon_shapes.png" contains icons for these
# shapes. # shapes.
module GameData module GameData
class BodyShape class BodyShape
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :icon_position # Where this shape's icon is within icon_shapes.png
DATA = {} DATA = {}
extend ClassMethods extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def self.load; end def self.load; end
@@ -19,8 +18,8 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
@icon_position = hash[:icon_position] || 0
end end
# @return [String] the translated name of this body shape # @return [String] the translated name of this body shape
@@ -34,84 +33,84 @@ end
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :Head, :id => :Head,
:id_number => 1, :name => _INTL("Head"),
:name => _INTL("Head") :icon_position => 0
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :Serpentine, :id => :Serpentine,
:id_number => 2, :name => _INTL("Serpentine"),
:name => _INTL("Serpentine") :icon_position => 1
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :Finned, :id => :Finned,
:id_number => 3, :name => _INTL("Finned"),
:name => _INTL("Finned") :icon_position => 2
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :HeadArms, :id => :HeadArms,
:id_number => 4, :name => _INTL("Head and arms"),
:name => _INTL("Head and arms") :icon_position => 3
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :HeadBase, :id => :HeadBase,
:id_number => 5, :name => _INTL("Head and base"),
:name => _INTL("Head and base") :icon_position => 4
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :BipedalTail, :id => :BipedalTail,
:id_number => 6, :name => _INTL("Bipedal with tail"),
:name => _INTL("Bipedal with tail") :icon_position => 5
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :HeadLegs, :id => :HeadLegs,
:id_number => 7, :name => _INTL("Head and legs"),
:name => _INTL("Head and legs") :icon_position => 6
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :Quadruped, :id => :Quadruped,
:id_number => 8, :name => _INTL("Quadruped"),
:name => _INTL("Quadruped") :icon_position => 7
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :Winged, :id => :Winged,
:id_number => 9, :name => _INTL("Winged"),
:name => _INTL("Winged") :icon_position => 8
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :Multiped, :id => :Multiped,
:id_number => 10, :name => _INTL("Multiped"),
:name => _INTL("Multiped") :icon_position => 9
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :MultiBody, :id => :MultiBody,
:id_number => 11, :name => _INTL("Multi Body"),
:name => _INTL("Multi Body") :icon_position => 10
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :Bipedal, :id => :Bipedal,
:id_number => 12, :name => _INTL("Bipedal"),
:name => _INTL("Bipedal") :icon_position => 11
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :MultiWinged, :id => :MultiWinged,
:id_number => 13, :name => _INTL("Multi Winged"),
:name => _INTL("Multi Winged") :icon_position => 12
}) })
GameData::BodyShape.register({ GameData::BodyShape.register({
:id => :Insectoid, :id => :Insectoid,
:id_number => 14, :name => _INTL("Insectoid"),
:name => _INTL("Insectoid") :icon_position => 13
}) })

View File

@@ -1,14 +1,13 @@
# NOTE: The id_number is only used to determine the order that body colors are # NOTE: The order these colors are registered are the order they are listed in
# listed in the Pokédex search screen. # the Pokédex search screen.
module GameData module GameData
class BodyColor class BodyColor
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
DATA = {} DATA = {}
extend ClassMethods extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def self.load; end def self.load; end
@@ -16,7 +15,6 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
end end
@@ -31,60 +29,50 @@ end
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Red, :id => :Red,
:id_number => 0,
:name => _INTL("Red") :name => _INTL("Red")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Blue, :id => :Blue,
:id_number => 1,
:name => _INTL("Blue") :name => _INTL("Blue")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Yellow, :id => :Yellow,
:id_number => 2,
:name => _INTL("Yellow") :name => _INTL("Yellow")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Green, :id => :Green,
:id_number => 3,
:name => _INTL("Green") :name => _INTL("Green")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Black, :id => :Black,
:id_number => 4,
:name => _INTL("Black") :name => _INTL("Black")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Brown, :id => :Brown,
:id_number => 5,
:name => _INTL("Brown") :name => _INTL("Brown")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Purple, :id => :Purple,
:id_number => 6,
:name => _INTL("Purple") :name => _INTL("Purple")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Gray, :id => :Gray,
:id_number => 7,
:name => _INTL("Gray") :name => _INTL("Gray")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :White, :id => :White,
:id_number => 8,
:name => _INTL("White") :name => _INTL("White")
}) })
GameData::BodyColor.register({ GameData::BodyColor.register({
:id => :Pink, :id => :Pink,
:id_number => 9,
:name => _INTL("Pink") :name => _INTL("Pink")
}) })

View File

@@ -7,6 +7,8 @@ module GameData
attr_reader :level_up_proc attr_reader :level_up_proc
attr_reader :use_item_proc attr_reader :use_item_proc
attr_reader :on_trade_proc attr_reader :on_trade_proc
attr_reader :after_battle_proc
attr_reader :event_proc
attr_reader :after_evolution_proc attr_reader :after_evolution_proc
DATA = {} DATA = {}
@@ -25,6 +27,8 @@ module GameData
@level_up_proc = hash[:level_up_proc] @level_up_proc = hash[:level_up_proc]
@use_item_proc = hash[:use_item_proc] @use_item_proc = hash[:use_item_proc]
@on_trade_proc = hash[:on_trade_proc] @on_trade_proc = hash[:on_trade_proc]
@after_battle_proc = hash[:after_battle_proc]
@event_proc = hash[:event_proc]
@after_evolution_proc = hash[:after_evolution_proc] @after_evolution_proc = hash[:after_evolution_proc]
end end
@@ -40,8 +44,16 @@ module GameData
return (@on_trade_proc) ? @on_trade_proc.call(*args) : nil return (@on_trade_proc) ? @on_trade_proc.call(*args) : nil
end end
def call_after_battle(*args)
return (@after_battle_proc) ? @after_battle_proc.call(*args) : nil
end
def call_event(*args)
return (@event_proc) ? @event_proc.call(*args) : nil
end
def call_after_evolution(*args) def call_after_evolution(*args)
@after_evolution_proc.call(*args) if @after_evolution_proc @after_evolution_proc&.call(*args)
end end
end end
end end
@@ -188,8 +200,7 @@ GameData::Evolution.register({
:id => :LevelDarkness, :id => :LevelDarkness,
:parameter => Integer, :parameter => Integer,
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
map_metadata = GameData::MapMetadata.try_get($game_map.map_id) next pkmn.level >= parameter && $game_map.metadata&.dark_map
next pkmn.level >= parameter && map_metadata && map_metadata.dark_map
} }
}) })
@@ -197,7 +208,7 @@ GameData::Evolution.register({
:id => :LevelDarkInParty, :id => :LevelDarkInParty,
:parameter => Integer, :parameter => Integer,
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next pkmn.level >= parameter && $Trainer.has_pokemon_of_type?(:DARK) next pkmn.level >= parameter && $player.has_pokemon_of_type?(:DARK)
} }
}) })
@@ -252,14 +263,11 @@ GameData::Evolution.register({
GameData::Evolution.register({ GameData::Evolution.register({
:id => :Shedinja, :id => :Shedinja,
:parameter => Integer, :parameter => Integer,
:level_up_proc => proc { |pkmn, parameter|
next false # This is a dummy proc and shouldn't next true
},
:after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species| :after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species|
next false if $Trainer.party_full? next false if $player.party_full?
next false if !$PokemonBag.pbHasItem?(:POKEBALL) next false if !$bag.has?(:POKEBALL)
PokemonEvolutionScene.pbDuplicatePokemon(pkmn, new_species) PokemonEvolutionScene.pbDuplicatePokemon(pkmn, new_species)
$PokemonBag.pbDeleteItem(:POKEBALL) $bag.remove(:POKEBALL)
next true next true
} }
}) })
@@ -268,7 +276,7 @@ GameData::Evolution.register({
:id => :Happiness, :id => :Happiness,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next pkmn.happiness >= 220 next pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220)
} }
}) })
@@ -276,7 +284,7 @@ GameData::Evolution.register({
:id => :HappinessMale, :id => :HappinessMale,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next pkmn.happiness >= 220 && pkmn.male? next pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220) && pkmn.male?
} }
}) })
@@ -284,7 +292,7 @@ GameData::Evolution.register({
:id => :HappinessFemale, :id => :HappinessFemale,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next pkmn.happiness >= 220 && pkmn.female? next pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220) && pkmn.female?
} }
}) })
@@ -292,7 +300,7 @@ GameData::Evolution.register({
:id => :HappinessDay, :id => :HappinessDay,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next pkmn.happiness >= 220 && PBDayNight.isDay? next pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220) && PBDayNight.isDay?
} }
}) })
@@ -300,7 +308,7 @@ GameData::Evolution.register({
:id => :HappinessNight, :id => :HappinessNight,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next pkmn.happiness >= 220 && PBDayNight.isNight? next pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220) && PBDayNight.isNight?
} }
}) })
@@ -309,7 +317,7 @@ GameData::Evolution.register({
:parameter => :Move, :parameter => :Move,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
if pkmn.happiness >= 220 if pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220)
next pkmn.moves.any? { |m| m && m.id == parameter } next pkmn.moves.any? { |m| m && m.id == parameter }
end end
} }
@@ -320,7 +328,7 @@ GameData::Evolution.register({
:parameter => :Type, :parameter => :Type,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
if pkmn.happiness >= 220 if pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220)
next pkmn.moves.any? { |m| m && m.type == parameter } next pkmn.moves.any? { |m| m && m.type == parameter }
end end
} }
@@ -331,7 +339,7 @@ GameData::Evolution.register({
:parameter => :Item, :parameter => :Item,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next pkmn.item == parameter && pkmn.happiness >= 220 next pkmn.item == parameter && pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220)
}, },
:after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species| :after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species|
next false if evo_species != new_species || !pkmn.hasItem?(parameter) next false if evo_species != new_species || !pkmn.hasItem?(parameter)
@@ -432,7 +440,7 @@ GameData::Evolution.register({
:parameter => :Item, :parameter => :Item,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next pkmn.item == parameter && pkmn.happiness >= 220 next pkmn.item == parameter && pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220)
}, },
:after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species| :after_evolution_proc => proc { |pkmn, new_species, parameter, evo_species|
next false if evo_species != new_species || !pkmn.hasItem?(parameter) next false if evo_species != new_species || !pkmn.hasItem?(parameter)
@@ -464,7 +472,7 @@ GameData::Evolution.register({
:parameter => :Species, :parameter => :Species,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
next $Trainer.has_species?(parameter) next $player.has_species?(parameter)
} }
}) })
@@ -477,14 +485,22 @@ GameData::Evolution.register({
} }
}) })
GameData::Evolution.register({
:id => :LocationFlag,
:parameter => String,
:minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter|
next $game_map.metadata&.has_flag?(parameter)
}
})
GameData::Evolution.register({ GameData::Evolution.register({
:id => :Region, :id => :Region,
:parameter => Integer, :parameter => Integer,
:minimum_level => 1, # Needs any level up :minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter| :level_up_proc => proc { |pkmn, parameter|
map_metadata = GameData::MapMetadata.try_get($game_map.map_id) map_metadata = $game_map.metadata
next map_metadata && map_metadata.town_map_position && next map_metadata&.town_map_position && map_metadata.town_map_position[0] == parameter
map_metadata.town_map_position[0] == parameter
} }
}) })
@@ -535,7 +551,7 @@ GameData::Evolution.register({
:id => :ItemHappiness, :id => :ItemHappiness,
:parameter => :Item, :parameter => :Item,
:use_item_proc => proc { |pkmn, parameter, item| :use_item_proc => proc { |pkmn, parameter, item|
next item == parameter && pkmn.happiness >= 220 next item == parameter && pkmn.happiness >= (Settings::APPLY_HAPPINESS_SOFT_CAP ? 160 : 220)
} }
}) })
@@ -597,3 +613,62 @@ GameData::Evolution.register({
next pkmn.species == parameter && !other_pkmn.hasItem?(:EVERSTONE) next pkmn.species == parameter && !other_pkmn.hasItem?(:EVERSTONE)
} }
}) })
#===============================================================================
# Evolution methods that are triggered after any battle
#===============================================================================
GameData::Evolution.register({
:id => :BattleDealCriticalHit,
:parameter => Integer,
:after_battle_proc => proc { |pkmn, party_index, parameter|
next $game_temp.party_critical_hits_dealt &&
$game_temp.party_critical_hits_dealt[party_index] &&
$game_temp.party_critical_hits_dealt[party_index] >= parameter
}
})
#===============================================================================
# Evolution methods that are triggered by an event
# Each event has its own number, which is the value of the parameter as defined
# in pokemon.txt/pokemon_forms.txt. It is also 'number' in def pbEvolutionEvent,
# which triggers evolution checks for a particular event number. 'value' in an
# event_proc is the number of the evolution event currently being triggered.
# Evolutions caused by different events should have different numbers. Used
# event numbers are:
# 1: Kubfu -> Urshifu
# 2: Galarian Yamask -> Runerigus
# These used event numbers are only used in pokemon.txt/pokemon_forms.txt and in
# map events that call pbEvolutionEvent, so they are relatively easy to change
# if you need to (no script changes are required). However, you could just
# ignore them instead if you don't want to use them.
#===============================================================================
def pbEvolutionEvent(number)
return if !$player
$player.able_party.each do |pkmn|
pkmn.trigger_event_evolution(number)
end
end
GameData::Evolution.register({
:id => :Event,
:parameter => Integer,
:event_proc => proc { |pkmn, parameter, value|
next value == parameter
}
})
GameData::Evolution.register({
:id => :EventAfterDamageTaken,
:parameter => Integer,
:after_battle_proc => proc { |pkmn, party_index, parameter|
if $game_temp.party_direct_damage_taken &&
$game_temp.party_direct_damage_taken[party_index] &&
$game_temp.party_direct_damage_taken[party_index] >= 49
pkmn.ready_to_evolve = true
end
next false
},
:event_proc => proc { |pkmn, parameter, value|
next value == parameter && pkmn.ready_to_evolve
}
})

View File

@@ -1,5 +1,3 @@
# The id_number value determines which order the stats are iterated through by
# the "each" methods.
# The pbs_order value determines the order in which the stats are written in # The pbs_order value determines the order in which the stats are written in
# several PBS files, where base stats/IVs/EVs/EV yields are defined. Only stats # several PBS files, where base stats/IVs/EVs/EV yields are defined. Only stats
# which are yielded by the "each_main" method can have stat numbers defined in # which are yielded by the "each_main" method can have stat numbers defined in
@@ -8,7 +6,6 @@
module GameData module GameData
class Stat class Stat
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :real_name_brief attr_reader :real_name_brief
attr_reader :type attr_reader :type
@@ -16,7 +13,7 @@ module GameData
DATA = {} DATA = {}
extend ClassMethods extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def self.load; end def self.load; end
@@ -39,7 +36,6 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
@real_name_brief = hash[:name_brief] || "None" @real_name_brief = hash[:name_brief] || "None"
@type = hash[:type] || :none @type = hash[:type] || :none
@@ -62,7 +58,6 @@ end
GameData::Stat.register({ GameData::Stat.register({
:id => :HP, :id => :HP,
:id_number => 0,
:name => _INTL("HP"), :name => _INTL("HP"),
:name_brief => _INTL("HP"), :name_brief => _INTL("HP"),
:type => :main, :type => :main,
@@ -71,7 +66,6 @@ GameData::Stat.register({
GameData::Stat.register({ GameData::Stat.register({
:id => :ATTACK, :id => :ATTACK,
:id_number => 1,
:name => _INTL("Attack"), :name => _INTL("Attack"),
:name_brief => _INTL("Atk"), :name_brief => _INTL("Atk"),
:type => :main_battle, :type => :main_battle,
@@ -80,7 +74,6 @@ GameData::Stat.register({
GameData::Stat.register({ GameData::Stat.register({
:id => :DEFENSE, :id => :DEFENSE,
:id_number => 2,
:name => _INTL("Defense"), :name => _INTL("Defense"),
:name_brief => _INTL("Def"), :name_brief => _INTL("Def"),
:type => :main_battle, :type => :main_battle,
@@ -89,7 +82,6 @@ GameData::Stat.register({
GameData::Stat.register({ GameData::Stat.register({
:id => :SPECIAL_ATTACK, :id => :SPECIAL_ATTACK,
:id_number => 3,
:name => _INTL("Special Attack"), :name => _INTL("Special Attack"),
:name_brief => _INTL("SpAtk"), :name_brief => _INTL("SpAtk"),
:type => :main_battle, :type => :main_battle,
@@ -98,7 +90,6 @@ GameData::Stat.register({
GameData::Stat.register({ GameData::Stat.register({
:id => :SPECIAL_DEFENSE, :id => :SPECIAL_DEFENSE,
:id_number => 4,
:name => _INTL("Special Defense"), :name => _INTL("Special Defense"),
:name_brief => _INTL("SpDef"), :name_brief => _INTL("SpDef"),
:type => :main_battle, :type => :main_battle,
@@ -107,7 +98,6 @@ GameData::Stat.register({
GameData::Stat.register({ GameData::Stat.register({
:id => :SPEED, :id => :SPEED,
:id_number => 5,
:name => _INTL("Speed"), :name => _INTL("Speed"),
:name_brief => _INTL("Spd"), :name_brief => _INTL("Spd"),
:type => :main_battle, :type => :main_battle,
@@ -116,7 +106,6 @@ GameData::Stat.register({
GameData::Stat.register({ GameData::Stat.register({
:id => :ACCURACY, :id => :ACCURACY,
:id_number => 6,
:name => _INTL("accuracy"), :name => _INTL("accuracy"),
:name_brief => _INTL("Acc"), :name_brief => _INTL("Acc"),
:type => :battle :type => :battle
@@ -124,7 +113,6 @@ GameData::Stat.register({
GameData::Stat.register({ GameData::Stat.register({
:id => :EVASION, :id => :EVASION,
:id_number => 7,
:name => _INTL("evasiveness"), :name => _INTL("evasiveness"),
:name_brief => _INTL("Eva"), :name_brief => _INTL("Eva"),
:type => :battle :type => :battle

View File

@@ -1,13 +1,12 @@
module GameData module GameData
class Nature class Nature
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :stat_changes attr_reader :stat_changes
DATA = {} DATA = {}
extend ClassMethods extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def self.load; end def self.load; end
@@ -15,7 +14,6 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
@stat_changes = hash[:stat_changes] || [] @stat_changes = hash[:stat_changes] || []
end end
@@ -31,170 +29,145 @@ end
GameData::Nature.register({ GameData::Nature.register({
:id => :HARDY, :id => :HARDY,
:id_number => 0,
:name => _INTL("Hardy") :name => _INTL("Hardy")
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :LONELY, :id => :LONELY,
:id_number => 1,
:name => _INTL("Lonely"), :name => _INTL("Lonely"),
:stat_changes => [[:ATTACK, 10], [:DEFENSE, -10]] :stat_changes => [[:ATTACK, 10], [:DEFENSE, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :BRAVE, :id => :BRAVE,
:id_number => 2,
:name => _INTL("Brave"), :name => _INTL("Brave"),
:stat_changes => [[:ATTACK, 10], [:SPEED, -10]] :stat_changes => [[:ATTACK, 10], [:SPEED, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :ADAMANT, :id => :ADAMANT,
:id_number => 3,
:name => _INTL("Adamant"), :name => _INTL("Adamant"),
:stat_changes => [[:ATTACK, 10], [:SPECIAL_ATTACK, -10]] :stat_changes => [[:ATTACK, 10], [:SPECIAL_ATTACK, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :NAUGHTY, :id => :NAUGHTY,
:id_number => 4,
:name => _INTL("Naughty"), :name => _INTL("Naughty"),
:stat_changes => [[:ATTACK, 10], [:SPECIAL_DEFENSE, -10]] :stat_changes => [[:ATTACK, 10], [:SPECIAL_DEFENSE, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :BOLD, :id => :BOLD,
:id_number => 5,
:name => _INTL("Bold"), :name => _INTL("Bold"),
:stat_changes => [[:DEFENSE, 10], [:ATTACK, -10]] :stat_changes => [[:DEFENSE, 10], [:ATTACK, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :DOCILE, :id => :DOCILE,
:id_number => 6,
:name => _INTL("Docile") :name => _INTL("Docile")
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :RELAXED, :id => :RELAXED,
:id_number => 7,
:name => _INTL("Relaxed"), :name => _INTL("Relaxed"),
:stat_changes => [[:DEFENSE, 10], [:SPEED, -10]] :stat_changes => [[:DEFENSE, 10], [:SPEED, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :IMPISH, :id => :IMPISH,
:id_number => 8,
:name => _INTL("Impish"), :name => _INTL("Impish"),
:stat_changes => [[:DEFENSE, 10], [:SPECIAL_ATTACK, -10]] :stat_changes => [[:DEFENSE, 10], [:SPECIAL_ATTACK, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :LAX, :id => :LAX,
:id_number => 9,
:name => _INTL("Lax"), :name => _INTL("Lax"),
:stat_changes => [[:DEFENSE, 10], [:SPECIAL_DEFENSE, -10]] :stat_changes => [[:DEFENSE, 10], [:SPECIAL_DEFENSE, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :TIMID, :id => :TIMID,
:id_number => 10,
:name => _INTL("Timid"), :name => _INTL("Timid"),
:stat_changes => [[:SPEED, 10], [:ATTACK, -10]] :stat_changes => [[:SPEED, 10], [:ATTACK, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :HASTY, :id => :HASTY,
:id_number => 11,
:name => _INTL("Hasty"), :name => _INTL("Hasty"),
:stat_changes => [[:SPEED, 10], [:DEFENSE, -10]] :stat_changes => [[:SPEED, 10], [:DEFENSE, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :SERIOUS, :id => :SERIOUS,
:id_number => 12,
:name => _INTL("Serious") :name => _INTL("Serious")
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :JOLLY, :id => :JOLLY,
:id_number => 13,
:name => _INTL("Jolly"), :name => _INTL("Jolly"),
:stat_changes => [[:SPEED, 10], [:SPECIAL_ATTACK, -10]] :stat_changes => [[:SPEED, 10], [:SPECIAL_ATTACK, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :NAIVE, :id => :NAIVE,
:id_number => 14,
:name => _INTL("Naive"), :name => _INTL("Naive"),
:stat_changes => [[:SPEED, 10], [:SPECIAL_DEFENSE, -10]] :stat_changes => [[:SPEED, 10], [:SPECIAL_DEFENSE, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :MODEST, :id => :MODEST,
:id_number => 15,
:name => _INTL("Modest"), :name => _INTL("Modest"),
:stat_changes => [[:SPECIAL_ATTACK, 10], [:ATTACK, -10]] :stat_changes => [[:SPECIAL_ATTACK, 10], [:ATTACK, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :MILD, :id => :MILD,
:id_number => 16,
:name => _INTL("Mild"), :name => _INTL("Mild"),
:stat_changes => [[:SPECIAL_ATTACK, 10], [:DEFENSE, -10]] :stat_changes => [[:SPECIAL_ATTACK, 10], [:DEFENSE, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :QUIET, :id => :QUIET,
:id_number => 17,
:name => _INTL("Quiet"), :name => _INTL("Quiet"),
:stat_changes => [[:SPECIAL_ATTACK, 10], [:SPEED, -10]] :stat_changes => [[:SPECIAL_ATTACK, 10], [:SPEED, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :BASHFUL, :id => :BASHFUL,
:id_number => 18,
:name => _INTL("Bashful") :name => _INTL("Bashful")
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :RASH, :id => :RASH,
:id_number => 19,
:name => _INTL("Rash"), :name => _INTL("Rash"),
:stat_changes => [[:SPECIAL_ATTACK, 10], [:SPECIAL_DEFENSE, -10]] :stat_changes => [[:SPECIAL_ATTACK, 10], [:SPECIAL_DEFENSE, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :CALM, :id => :CALM,
:id_number => 20,
:name => _INTL("Calm"), :name => _INTL("Calm"),
:stat_changes => [[:SPECIAL_DEFENSE, 10], [:ATTACK, -10]] :stat_changes => [[:SPECIAL_DEFENSE, 10], [:ATTACK, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :GENTLE, :id => :GENTLE,
:id_number => 21,
:name => _INTL("Gentle"), :name => _INTL("Gentle"),
:stat_changes => [[:SPECIAL_DEFENSE, 10], [:DEFENSE, -10]] :stat_changes => [[:SPECIAL_DEFENSE, 10], [:DEFENSE, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :SASSY, :id => :SASSY,
:id_number => 22,
:name => _INTL("Sassy"), :name => _INTL("Sassy"),
:stat_changes => [[:SPECIAL_DEFENSE, 10], [:SPEED, -10]] :stat_changes => [[:SPECIAL_DEFENSE, 10], [:SPEED, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :CAREFUL, :id => :CAREFUL,
:id_number => 23,
:name => _INTL("Careful"), :name => _INTL("Careful"),
:stat_changes => [[:SPECIAL_DEFENSE, 10], [:SPECIAL_ATTACK, -10]] :stat_changes => [[:SPECIAL_DEFENSE, 10], [:SPECIAL_ATTACK, -10]]
}) })
GameData::Nature.register({ GameData::Nature.register({
:id => :QUIRKY, :id => :QUIRKY,
:id_number => 24,
:name => _INTL("Quirky") :name => _INTL("Quirky")
}) })

View File

@@ -1,21 +1,19 @@
# NOTE: The id_number is only used to determine the order of the status icons in # NOTE: "Graphics/Pictures/statuses.png" also contains icons for being fainted
# the graphics containing them. Number 0 (:NONE) is ignored; they start
# with status 1.
# "Graphics/Pictures/statuses.png" also contains icons for being fainted
# and for having Pokérus, in that order, at the bottom of the graphic. # and for having Pokérus, in that order, at the bottom of the graphic.
# "Graphics/Pictures/Battle/icon_statuses.png" also contains an icon for # "Graphics/Pictures/Battle/icon_statuses.png" also contains an icon for
# bad poisoning (toxic), at the bottom of the graphic. # bad poisoning (toxic), at the bottom of the graphic.
# Both graphics automatically handle varying numbers of defined statuses. # Both graphics automatically handle varying numbers of defined statuses,
# as long as their extra icons remain at the bottom of them.
module GameData module GameData
class Status class Status
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :animation attr_reader :animation
attr_reader :icon_position # Where this status's icon is within statuses.png
DATA = {} DATA = {}
extend ClassMethods extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def self.load; end def self.load; end
@@ -23,9 +21,9 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number]
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
@animation = hash[:animation] @animation = hash[:animation]
@icon_position = hash[:icon_position] || 0
end end
# @return [String] the translated name of this status condition # @return [String] the translated name of this status condition
@@ -39,41 +37,40 @@ end
GameData::Status.register({ GameData::Status.register({
:id => :NONE, :id => :NONE,
:id_number => 0,
:name => _INTL("None") :name => _INTL("None")
}) })
GameData::Status.register({ GameData::Status.register({
:id => :SLEEP, :id => :SLEEP,
:id_number => 1,
:name => _INTL("Sleep"), :name => _INTL("Sleep"),
:animation => "Sleep" :animation => "Sleep",
:icon_position => 0
}) })
GameData::Status.register({ GameData::Status.register({
:id => :POISON, :id => :POISON,
:id_number => 2,
:name => _INTL("Poison"), :name => _INTL("Poison"),
:animation => "Poison" :animation => "Poison",
:icon_position => 1
}) })
GameData::Status.register({ GameData::Status.register({
:id => :BURN, :id => :BURN,
:id_number => 3,
:name => _INTL("Burn"), :name => _INTL("Burn"),
:animation => "Burn" :animation => "Burn",
:icon_position => 2
}) })
GameData::Status.register({ GameData::Status.register({
:id => :PARALYSIS, :id => :PARALYSIS,
:id_number => 4,
:name => _INTL("Paralysis"), :name => _INTL("Paralysis"),
:animation => "Paralysis" :animation => "Paralysis",
:icon_position => 3
}) })
GameData::Status.register({ GameData::Status.register({
:id => :FROZEN, :id => :FROZEN,
:id_number => 5,
:name => _INTL("Frozen"), :name => _INTL("Frozen"),
:animation => "Frozen" :animation => "Frozen",
:icon_position => 4
}) })

View File

@@ -170,8 +170,9 @@ GameData::TerrainTag.register({
:ignore_passability => true :ignore_passability => true
}) })
# NOTE: This is referenced by ID in an Events.onStepTakenFieldMovement proc that # NOTE: This is referenced by ID in the :pick_up_soot proc added to
# adds soot to the Soot Sack if the player walks over one of these tiles. # EventHandlers. It adds soot to the Soot Sack if the player walks over
# one of these tiles.
GameData::TerrainTag.register({ GameData::TerrainTag.register({
:id => :SootGrass, :id => :SootGrass,
:id_number => 14, :id_number => 14,
@@ -192,3 +193,8 @@ GameData::TerrainTag.register({
:battle_environment => :Puddle, :battle_environment => :Puddle,
:shows_reflections => true :shows_reflections => true
}) })
GameData::TerrainTag.register({
:id => :NoEffect,
:id_number => 17
})

View File

@@ -4,7 +4,6 @@ module GameData
attr_reader :real_name attr_reader :real_name
attr_reader :type # :land, :cave, :water, :fishing, :contest, :none attr_reader :type # :land, :cave, :water, :fishing, :contest, :none
attr_reader :trigger_chance attr_reader :trigger_chance
attr_reader :old_slots
DATA = {} DATA = {}
@@ -19,7 +18,6 @@ module GameData
@real_name = hash[:id].to_s || "Unnamed" @real_name = hash[:id].to_s || "Unnamed"
@type = hash[:type] || :none @type = hash[:type] || :none
@trigger_chance = hash[:trigger_chance] || 0 @trigger_chance = hash[:trigger_chance] || 0
@old_slots = hash[:old_slots]
end end
end end
end end
@@ -29,169 +27,144 @@ end
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :Land, :id => :Land,
:type => :land, :type => :land,
:trigger_chance => 21, :trigger_chance => 21
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :LandDay, :id => :LandDay,
:type => :land, :type => :land,
:trigger_chance => 21, :trigger_chance => 21
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :LandNight, :id => :LandNight,
:type => :land, :type => :land,
:trigger_chance => 21, :trigger_chance => 21
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :LandMorning, :id => :LandMorning,
:type => :land, :type => :land,
:trigger_chance => 21, :trigger_chance => 21
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :LandAfternoon, :id => :LandAfternoon,
:type => :land, :type => :land,
:trigger_chance => 21, :trigger_chance => 21
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :LandEvening, :id => :LandEvening,
:type => :land, :type => :land,
:trigger_chance => 21, :trigger_chance => 21
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :Cave, :id => :Cave,
:type => :cave, :type => :cave,
:trigger_chance => 5, :trigger_chance => 5
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :CaveDay, :id => :CaveDay,
:type => :cave, :type => :cave,
:trigger_chance => 5, :trigger_chance => 5
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :CaveNight, :id => :CaveNight,
:type => :cave, :type => :cave,
:trigger_chance => 5, :trigger_chance => 5
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :CaveMorning, :id => :CaveMorning,
:type => :cave, :type => :cave,
:trigger_chance => 5, :trigger_chance => 5
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :CaveAfternoon, :id => :CaveAfternoon,
:type => :cave, :type => :cave,
:trigger_chance => 5, :trigger_chance => 5
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :CaveEvening, :id => :CaveEvening,
:type => :cave, :type => :cave,
:trigger_chance => 5, :trigger_chance => 5
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :Water, :id => :Water,
:type => :water, :type => :water,
:trigger_chance => 2, :trigger_chance => 2
:old_slots => [60, 30, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :WaterDay, :id => :WaterDay,
:type => :water, :type => :water,
:trigger_chance => 2, :trigger_chance => 2
:old_slots => [60, 30, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :WaterNight, :id => :WaterNight,
:type => :water, :type => :water,
:trigger_chance => 2, :trigger_chance => 2
:old_slots => [60, 30, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :WaterMorning, :id => :WaterMorning,
:type => :water, :type => :water,
:trigger_chance => 2, :trigger_chance => 2
:old_slots => [60, 30, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :WaterAfternoon, :id => :WaterAfternoon,
:type => :water, :type => :water,
:trigger_chance => 2, :trigger_chance => 2
:old_slots => [60, 30, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :WaterEvening, :id => :WaterEvening,
:type => :water, :type => :water,
:trigger_chance => 2, :trigger_chance => 2
:old_slots => [60, 30, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :OldRod, :id => :OldRod,
:type => :fishing, :type => :fishing
:old_slots => [70, 30]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :GoodRod, :id => :GoodRod,
:type => :fishing, :type => :fishing
:old_slots => [60, 20, 20]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :SuperRod, :id => :SuperRod,
:type => :fishing, :type => :fishing
:old_slots => [40, 40, 15, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :RockSmash, :id => :RockSmash,
:type => :none, :type => :none,
:trigger_chance => 50, :trigger_chance => 50
:old_slots => [60, 30, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :HeadbuttLow, :id => :HeadbuttLow,
:type => :none, :type => :none
:old_slots => [30, 25, 20, 10, 5, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :HeadbuttHigh, :id => :HeadbuttHigh,
:type => :none, :type => :none
:old_slots => [30, 25, 20, 10, 5, 5, 4, 1]
}) })
GameData::EncounterType.register({ GameData::EncounterType.register({
:id => :BugContest, :id => :BugContest,
:type => :contest, :type => :contest,
:trigger_chance => 21, :trigger_chance => 21
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
}) })

View File

@@ -8,7 +8,6 @@
module GameData module GameData
class Target class Target
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :num_targets # 0, 1 or 2 (meaning 2+) attr_reader :num_targets # 0, 1 or 2 (meaning 2+)
attr_reader :targets_foe # Is able to target one or more foes attr_reader :targets_foe # Is able to target one or more foes
@@ -18,7 +17,7 @@ module GameData
DATA = {} DATA = {}
extend ClassMethods extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def self.load; end def self.load; end
@@ -54,20 +53,17 @@ end
# Bide, Counter, Metal Burst, Mirror Coat (calculate a target) # Bide, Counter, Metal Burst, Mirror Coat (calculate a target)
GameData::Target.register({ GameData::Target.register({
:id => :None, :id => :None,
:id_number => 1,
:name => _INTL("None") :name => _INTL("None")
}) })
GameData::Target.register({ GameData::Target.register({
:id => :User, :id => :User,
:id_number => 10,
:name => _INTL("User") :name => _INTL("User")
}) })
# Aromatic Mist, Helping Hand, Hold Hands # Aromatic Mist, Helping Hand, Hold Hands
GameData::Target.register({ GameData::Target.register({
:id => :NearAlly, :id => :NearAlly,
:id_number => 100,
:name => _INTL("Near Ally"), :name => _INTL("Near Ally"),
:num_targets => 1 :num_targets => 1
}) })
@@ -75,15 +71,22 @@ GameData::Target.register({
# Acupressure # Acupressure
GameData::Target.register({ GameData::Target.register({
:id => :UserOrNearAlly, :id => :UserOrNearAlly,
:id_number => 200,
:name => _INTL("User or Near Ally"), :name => _INTL("User or Near Ally"),
:num_targets => 1 :num_targets => 1
}) })
# Coaching
GameData::Target.register({
:id => :AllAllies,
:name => _INTL("All Allies"),
:num_targets => 2,
:targets_all => true,
:long_range => true
})
# Aromatherapy, Gear Up, Heal Bell, Life Dew, Magnetic Flux, Howl (in Gen 8+) # Aromatherapy, Gear Up, Heal Bell, Life Dew, Magnetic Flux, Howl (in Gen 8+)
GameData::Target.register({ GameData::Target.register({
:id => :UserAndAllies, :id => :UserAndAllies,
:id_number => 5,
:name => _INTL("User and Allies"), :name => _INTL("User and Allies"),
:num_targets => 2, :num_targets => 2,
:long_range => true :long_range => true
@@ -92,7 +95,6 @@ GameData::Target.register({
# Me First # Me First
GameData::Target.register({ GameData::Target.register({
:id => :NearFoe, :id => :NearFoe,
:id_number => 400,
:name => _INTL("Near Foe"), :name => _INTL("Near Foe"),
:num_targets => 1, :num_targets => 1,
:targets_foe => true :targets_foe => true
@@ -101,7 +103,6 @@ GameData::Target.register({
# Petal Dance, Outrage, Struggle, Thrash, Uproar # Petal Dance, Outrage, Struggle, Thrash, Uproar
GameData::Target.register({ GameData::Target.register({
:id => :RandomNearFoe, :id => :RandomNearFoe,
:id_number => 2,
:name => _INTL("Random Near Foe"), :name => _INTL("Random Near Foe"),
:num_targets => 1, :num_targets => 1,
:targets_foe => true :targets_foe => true
@@ -109,7 +110,6 @@ GameData::Target.register({
GameData::Target.register({ GameData::Target.register({
:id => :AllNearFoes, :id => :AllNearFoes,
:id_number => 4,
:name => _INTL("All Near Foes"), :name => _INTL("All Near Foes"),
:num_targets => 2, :num_targets => 2,
:targets_foe => true :targets_foe => true
@@ -118,7 +118,6 @@ GameData::Target.register({
# For throwing a Poké Ball # For throwing a Poké Ball
GameData::Target.register({ GameData::Target.register({
:id => :Foe, :id => :Foe,
:id_number => 9,
:name => _INTL("Foe"), :name => _INTL("Foe"),
:num_targets => 1, :num_targets => 1,
:targets_foe => true, :targets_foe => true,
@@ -128,7 +127,6 @@ GameData::Target.register({
# Unused # Unused
GameData::Target.register({ GameData::Target.register({
:id => :AllFoes, :id => :AllFoes,
:id_number => 6,
:name => _INTL("All Foes"), :name => _INTL("All Foes"),
:num_targets => 2, :num_targets => 2,
:targets_foe => true, :targets_foe => true,
@@ -137,7 +135,6 @@ GameData::Target.register({
GameData::Target.register({ GameData::Target.register({
:id => :NearOther, :id => :NearOther,
:id_number => 0,
:name => _INTL("Near Other"), :name => _INTL("Near Other"),
:num_targets => 1, :num_targets => 1,
:targets_foe => true :targets_foe => true
@@ -145,7 +142,6 @@ GameData::Target.register({
GameData::Target.register({ GameData::Target.register({
:id => :AllNearOthers, :id => :AllNearOthers,
:id_number => 8,
:name => _INTL("All Near Others"), :name => _INTL("All Near Others"),
:num_targets => 2, :num_targets => 2,
:targets_foe => true :targets_foe => true
@@ -154,7 +150,6 @@ GameData::Target.register({
# Most Flying-type moves, pulse moves (hits non-near targets) # Most Flying-type moves, pulse moves (hits non-near targets)
GameData::Target.register({ GameData::Target.register({
:id => :Other, :id => :Other,
:id_number => 3,
:name => _INTL("Other"), :name => _INTL("Other"),
:num_targets => 1, :num_targets => 1,
:targets_foe => true, :targets_foe => true,
@@ -164,7 +159,6 @@ GameData::Target.register({
# Flower Shield, Perish Song, Rototiller, Teatime # Flower Shield, Perish Song, Rototiller, Teatime
GameData::Target.register({ GameData::Target.register({
:id => :AllBattlers, :id => :AllBattlers,
:id_number => 7,
:name => _INTL("All Battlers"), :name => _INTL("All Battlers"),
:num_targets => 2, :num_targets => 2,
:targets_foe => true, :targets_foe => true,
@@ -174,21 +168,18 @@ GameData::Target.register({
GameData::Target.register({ GameData::Target.register({
:id => :UserSide, :id => :UserSide,
:id_number => 40,
:name => _INTL("User Side") :name => _INTL("User Side")
}) })
# Entry hazards # Entry hazards
GameData::Target.register({ GameData::Target.register({
:id => :FoeSide, :id => :FoeSide,
:id_number => 80,
:name => _INTL("Foe Side"), :name => _INTL("Foe Side"),
:affects_foe_side => true :affects_foe_side => true
}) })
GameData::Target.register({ GameData::Target.register({
:id => :BothSides, :id => :BothSides,
:id_number => 20,
:name => _INTL("Both Sides"), :name => _INTL("Both Sides"),
:affects_foe_side => true :affects_foe_side => true
}) })

View File

@@ -1,25 +1,23 @@
#=============================================================================== #===============================================================================
# Data caches. # Data caches.
#=============================================================================== #===============================================================================
class PokemonTemp class Game_Temp
attr_accessor :townMapData attr_accessor :town_map_data
attr_accessor :phoneData attr_accessor :phone_messages_data
attr_accessor :speciesShadowMovesets attr_accessor :regional_dexes_data
attr_accessor :regionalDexes attr_accessor :battle_animations_data
attr_accessor :battleAnims attr_accessor :move_to_battle_animation_data
attr_accessor :moveToAnim attr_accessor :map_infos
attr_accessor :mapInfos
end end
def pbClearData def pbClearData
if $PokemonTemp if $game_temp
$PokemonTemp.townMapData = nil $game_temp.town_map_data = nil
$PokemonTemp.phoneData = nil $game_temp.phone_messages_data = nil
$PokemonTemp.speciesShadowMovesets = nil $game_temp.regional_dexes_data = nil
$PokemonTemp.regionalDexes = nil $game_temp.battle_animations_data = nil
$PokemonTemp.battleAnims = nil $game_temp.move_to_battle_animation_data = nil
$PokemonTemp.moveToAnim = nil $game_temp.map_infos = nil
$PokemonTemp.mapInfos = nil
end end
MapFactoryHelper.clear MapFactoryHelper.clear
$PokemonEncounters.setup($game_map.map_id) if $game_map && $PokemonEncounters $PokemonEncounters.setup($game_map.map_id) if $game_map && $PokemonEncounters
@@ -32,76 +30,61 @@ end
# Method to get Town Map data. # Method to get Town Map data.
#=============================================================================== #===============================================================================
def pbLoadTownMapData def pbLoadTownMapData
$PokemonTemp = PokemonTemp.new if !$PokemonTemp $game_temp = Game_Temp.new if !$game_temp
if !$PokemonTemp.townMapData if !$game_temp.town_map_data
$PokemonTemp.townMapData = load_data("Data/town_map.dat") $game_temp.town_map_data = load_data("Data/town_map.dat")
end end
return $PokemonTemp.townMapData return $game_temp.town_map_data
end end
#=============================================================================== #===============================================================================
# Method to get phone call data. # Method to get phone call data.
#=============================================================================== #===============================================================================
def pbLoadPhoneData def pbLoadPhoneData
$PokemonTemp = PokemonTemp.new if !$PokemonTemp $game_temp = Game_Temp.new if !$game_temp
if !$PokemonTemp.phoneData if !$game_temp.phone_messages_data && pbRgssExists?("Data/phone.dat")
if pbRgssExists?("Data/phone.dat") $game_temp.phone_messages_data = load_data("Data/phone.dat")
$PokemonTemp.phoneData = load_data("Data/phone.dat")
end end
end return $game_temp.phone_messages_data
return $PokemonTemp.phoneData
end
#===============================================================================
# Method to get Shadow Pokémon moveset data.
#===============================================================================
def pbLoadShadowMovesets
$PokemonTemp = PokemonTemp.new if !$PokemonTemp
if !$PokemonTemp.speciesShadowMovesets
$PokemonTemp.speciesShadowMovesets = load_data("Data/shadow_movesets.dat") || []
end
return $PokemonTemp.speciesShadowMovesets
end end
#=============================================================================== #===============================================================================
# Method to get Regional Dexes data. # Method to get Regional Dexes data.
#=============================================================================== #===============================================================================
def pbLoadRegionalDexes def pbLoadRegionalDexes
$PokemonTemp = PokemonTemp.new if !$PokemonTemp $game_temp = Game_Temp.new if !$game_temp
if !$PokemonTemp.regionalDexes if !$game_temp.regional_dexes_data
$PokemonTemp.regionalDexes = load_data("Data/regional_dexes.dat") $game_temp.regional_dexes_data = load_data("Data/regional_dexes.dat")
end end
return $PokemonTemp.regionalDexes return $game_temp.regional_dexes_data
end end
#=============================================================================== #===============================================================================
# Methods relating to battle animations data. # Methods relating to battle animations data.
#=============================================================================== #===============================================================================
def pbLoadBattleAnimations def pbLoadBattleAnimations
$PokemonTemp = PokemonTemp.new if !$PokemonTemp $game_temp = Game_Temp.new if !$game_temp
if !$PokemonTemp.battleAnims if !$game_temp.battle_animations_data && pbRgssExists?("Data/PkmnAnimations.rxdata")
if pbRgssExists?("Data/PkmnAnimations.rxdata") $game_temp.battle_animations_data = load_data("Data/PkmnAnimations.rxdata")
$PokemonTemp.battleAnims = load_data("Data/PkmnAnimations.rxdata")
end end
end return $game_temp.battle_animations_data
return $PokemonTemp.battleAnims
end end
def pbLoadMoveToAnim def pbLoadMoveToAnim
$PokemonTemp = PokemonTemp.new if !$PokemonTemp $game_temp = Game_Temp.new if !$game_temp
if !$PokemonTemp.moveToAnim if !$game_temp.move_to_battle_animation_data
$PokemonTemp.moveToAnim = load_data("Data/move2anim.dat") || [] $game_temp.move_to_battle_animation_data = load_data("Data/move2anim.dat") || []
end end
return $PokemonTemp.moveToAnim return $game_temp.move_to_battle_animation_data
end end
#=============================================================================== #===============================================================================
# Method relating to map infos data. # Method relating to map infos data.
#=============================================================================== #===============================================================================
def pbLoadMapInfos def pbLoadMapInfos
$PokemonTemp = PokemonTemp.new if !$PokemonTemp $game_temp = Game_Temp.new if !$game_temp
if !$PokemonTemp.mapInfos if !$game_temp.map_infos
$PokemonTemp.mapInfos = load_data("Data/MapInfos.rxdata") $game_temp.map_infos = load_data("Data/MapInfos.rxdata")
end end
return $PokemonTemp.mapInfos return $game_temp.map_infos
end end

View File

@@ -22,10 +22,3 @@ class PhoneDatabase
@trainers = [] @trainers = []
end end
end end
module PhoneMsgType
Generic = 0
Greeting = 1
Body = 2
BattleRequest = 3
end

View File

@@ -1,52 +1,60 @@
module GameData module GameData
class Type class Type
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :special_type attr_reader :special_type
attr_reader :pseudo_type attr_reader :pseudo_type
attr_reader :flags
attr_reader :weaknesses attr_reader :weaknesses
attr_reader :resistances attr_reader :resistances
attr_reader :immunities attr_reader :immunities
attr_reader :icon_position # Where this type's icon is within types.png
DATA = {} DATA = {}
DATA_FILENAME = "types.dat" DATA_FILENAME = "types.dat"
SCHEMA = { SCHEMA = {
"Name" => [1, "s"], "Name" => [0, "s"],
"InternalName" => [2, "s"], "InternalName" => [0, "s"],
"IsPseudoType" => [3, "b"], "IsSpecialType" => [0, "b"],
"IsSpecialType" => [4, "b"], "IsPseudoType" => [0, "b"],
"Weaknesses" => [5, "*s"], "Flags" => [0, "*s"],
"Resistances" => [6, "*s"], "Weaknesses" => [0, "*s"],
"Immunities" => [7, "*s"] "Resistances" => [0, "*s"],
"Immunities" => [0, "*s"],
"IconPosition" => [0, "u"]
} }
extend ClassMethods extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
@pseudo_type = hash[:pseudo_type] || false
@special_type = hash[:special_type] || false @special_type = hash[:special_type] || false
@pseudo_type = hash[:pseudo_type] || false
@flags = hash[:flags] || []
@weaknesses = hash[:weaknesses] || [] @weaknesses = hash[:weaknesses] || []
@weaknesses = [@weaknesses] if !@weaknesses.is_a?(Array) @weaknesses = [@weaknesses] if !@weaknesses.is_a?(Array)
@resistances = hash[:resistances] || [] @resistances = hash[:resistances] || []
@resistances = [@resistances] if !@resistances.is_a?(Array) @resistances = [@resistances] if !@resistances.is_a?(Array)
@immunities = hash[:immunities] || [] @immunities = hash[:immunities] || []
@immunities = [@immunities] if !@immunities.is_a?(Array) @immunities = [@immunities] if !@immunities.is_a?(Array)
@icon_position = hash[:icon_position] || 0
end end
# @return [String] the translated name of this item # @return [String] the translated name of this item
def name def name
return pbGetMessage(MessageTypes::Types, @id_number) return pbGetMessageFromHash(MessageTypes::Types, @real_name)
end end
def physical?; return !@special_type; end def physical?; return !@special_type; end
def special?; return @special_type; end def special?; return @special_type; end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end
def effectiveness(other_type) def effectiveness(other_type)
return Effectiveness::NORMAL_EFFECTIVE_ONE if !other_type return Effectiveness::NORMAL_EFFECTIVE_ONE if !other_type
return Effectiveness::SUPER_EFFECTIVE_ONE if @weaknesses.include?(other_type) return Effectiveness::SUPER_EFFECTIVE_ONE if @weaknesses.include?(other_type)

View File

@@ -1,31 +1,41 @@
module GameData module GameData
class Ability class Ability
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :real_description attr_reader :real_description
attr_reader :flags
DATA = {} DATA = {}
DATA_FILENAME = "abilities.dat" DATA_FILENAME = "abilities.dat"
extend ClassMethods extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
SCHEMA = {
"Name" => [:name, "s"],
"Description" => [:description, "q"],
"Flags" => [:flags, "*s"]
}
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
@real_description = hash[:description] || "???" @real_description = hash[:description] || "???"
@flags = hash[:flags] || []
end end
# @return [String] the translated name of this ability # @return [String] the translated name of this ability
def name def name
return pbGetMessage(MessageTypes::Abilities, @id_number) return pbGetMessageFromHash(MessageTypes::Abilities, @real_name)
end end
# @return [String] the translated description of this ability # @return [String] the translated description of this ability
def description def description
return pbGetMessage(MessageTypes::AbilityDescs, @id_number) return pbGetMessageFromHash(MessageTypes::AbilityDescs, @real_description)
end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end end
end end
end end

View File

@@ -1,51 +1,70 @@
module GameData module GameData
class Move class Move
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :function_code
attr_reader :base_damage
attr_reader :type attr_reader :type
attr_reader :category attr_reader :category
attr_reader :base_damage
attr_reader :accuracy attr_reader :accuracy
attr_reader :total_pp attr_reader :total_pp
attr_reader :effect_chance
attr_reader :target attr_reader :target
attr_reader :priority attr_reader :priority
attr_reader :function_code
attr_reader :flags attr_reader :flags
attr_reader :effect_chance
attr_reader :real_description attr_reader :real_description
DATA = {} DATA = {}
DATA_FILENAME = "moves.dat" DATA_FILENAME = "moves.dat"
extend ClassMethods SCHEMA = {
"Name" => [:name, "s"],
"Type" => [:type, "e", :Type],
"Category" => [:category, "e", ["Physical", "Special", "Status"]],
"BaseDamage" => [:base_damage, "u"],
"Accuracy" => [:accuracy, "u"],
"TotalPP" => [:total_pp, "u"],
"Target" => [:target, "e", :Target],
"Priority" => [:priority, "i"],
"FunctionCode" => [:function_code, "s"],
"Flags" => [:flags, "*s"],
"EffectChance" => [:effect_chance, "u"],
"Description" => [:description, "q"]
}
extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def initialize(hash) def initialize(hash)
convert_move_data(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
@function_code = hash[:function_code] @type = hash[:type] || :NONE
@base_damage = hash[:base_damage] @category = hash[:category] || 2
@type = hash[:type] @base_damage = hash[:base_damage] || 0
@category = hash[:category] @accuracy = hash[:accuracy] || 100
@accuracy = hash[:accuracy] @total_pp = hash[:total_pp] || 5
@total_pp = hash[:total_pp] @target = hash[:target] || :None
@effect_chance = hash[:effect_chance] @priority = hash[:priority] || 0
@target = hash[:target] @function_code = hash[:function_code] || "None"
@priority = hash[:priority] @flags = hash[:flags] || []
@flags = hash[:flags] @flags = [@flags] if !@flags.is_a?(Array)
@effect_chance = hash[:effect_chance] || 0
@real_description = hash[:description] || "???" @real_description = hash[:description] || "???"
end end
# @return [String] the translated name of this move # @return [String] the translated name of this move
def name def name
return pbGetMessage(MessageTypes::Moves, @id_number) return pbGetMessageFromHash(MessageTypes::Moves, @real_name)
end end
# @return [String] the translated description of this move # @return [String] the translated description of this move
def description def description
return pbGetMessage(MessageTypes::MoveDescriptions, @id_number) return pbGetMessageFromHash(MessageTypes::MoveDescriptions, @real_description)
end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end end
def physical? def physical?
@@ -66,20 +85,729 @@ module GameData
end end
return false return false
end end
def display_type(pkmn, move = nil)
=begin
case @function_code
when "TypeDependsOnUserIVs"
return pbHiddenPower(pkmn)[0]
when "TypeAndPowerDependOnUserBerry"
type_array = {
:NORMAL => [:CHILANBERRY],
:FIRE => [:CHERIBERRY, :BLUKBERRY, :WATMELBERRY, :OCCABERRY],
:WATER => [:CHESTOBERRY, :NANABBERRY, :DURINBERRY, :PASSHOBERRY],
:ELECTRIC => [:PECHABERRY, :WEPEARBERRY, :BELUEBERRY, :WACANBERRY],
:GRASS => [:RAWSTBERRY, :PINAPBERRY, :RINDOBERRY, :LIECHIBERRY],
:ICE => [:ASPEARBERRY, :POMEGBERRY, :YACHEBERRY, :GANLONBERRY],
:FIGHTING => [:LEPPABERRY, :KELPSYBERRY, :CHOPLEBERRY, :SALACBERRY],
:POISON => [:ORANBERRY, :QUALOTBERRY, :KEBIABERRY, :PETAYABERRY],
:GROUND => [:PERSIMBERRY, :HONDEWBERRY, :SHUCABERRY, :APICOTBERRY],
:FLYING => [:LUMBERRY, :GREPABERRY, :COBABERRY, :LANSATBERRY],
:PSYCHIC => [:SITRUSBERRY, :TAMATOBERRY, :PAYAPABERRY, :STARFBERRY],
:BUG => [:FIGYBERRY, :CORNNBERRY, :TANGABERRY, :ENIGMABERRY],
:ROCK => [:WIKIBERRY, :MAGOSTBERRY, :CHARTIBERRY, :MICLEBERRY],
:GHOST => [:MAGOBERRY, :RABUTABERRY, :KASIBBERRY, :CUSTAPBERRY],
:DRAGON => [:AGUAVBERRY, :NOMELBERRY, :HABANBERRY, :JABOCABERRY],
:DARK => [:IAPAPABERRY, :SPELONBERRY, :COLBURBERRY, :ROWAPBERRY, :MARANGABERRY],
:STEEL => [:RAZZBERRY, :PAMTREBERRY, :BABIRIBERRY],
:FAIRY => [:ROSELIBERRY, :KEEBERRY]
}
if pkmn.hasItem?
type_array.each do |type, items|
return type if items.include?(pkmn.item_id) && GameData::Type.exists?(type)
end end
end end
when "TypeDependsOnUserPlate"
item_types = {
:FISTPLATE => :FIGHTING,
:SKYPLATE => :FLYING,
:TOXICPLATE => :POISON,
:EARTHPLATE => :GROUND,
:STONEPLATE => :ROCK,
:INSECTPLATE => :BUG,
:SPOOKYPLATE => :GHOST,
:IRONPLATE => :STEEL,
:FLAMEPLATE => :FIRE,
:SPLASHPLATE => :WATER,
:MEADOWPLATE => :GRASS,
:ZAPPLATE => :ELECTRIC,
:MINDPLATE => :PSYCHIC,
:ICICLEPLATE => :ICE,
:DRACOPLATE => :DRAGON,
:DREADPLATE => :DARK,
:PIXIEPLATE => :FAIRY
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
end
end
when "TypeDependsOnUserMemory"
item_types = {
:FIGHTINGMEMORY => :FIGHTING,
:FLYINGMEMORY => :FLYING,
:POISONMEMORY => :POISON,
:GROUNDMEMORY => :GROUND,
:ROCKMEMORY => :ROCK,
:BUGMEMORY => :BUG,
:GHOSTMEMORY => :GHOST,
:STEELMEMORY => :STEEL,
:FIREMEMORY => :FIRE,
:WATERMEMORY => :WATER,
:GRASSMEMORY => :GRASS,
:ELECTRICMEMORY => :ELECTRIC,
:PSYCHICMEMORY => :PSYCHIC,
:ICEMEMORY => :ICE,
:DRAGONMEMORY => :DRAGON,
:DARKMEMORY => :DARK,
:FAIRYMEMORY => :FAIRY
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
end
end
when "TypeDependsOnUserDrive"
item_types = {
:SHOCKDRIVE => :ELECTRIC,
:BURNDRIVE => :FIRE,
:CHILLDRIVE => :ICE,
:DOUSEDRIVE => :WATER
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
end
end
when "TypeIsUserFirstType"
return pkmn.types[0]
end
=end
return @type
end
#=============================================================================== def display_damage(pkmn, move = nil)
# Deprecated methods =begin
#=============================================================================== case @function_code
# @deprecated This alias is slated to be removed in v20. when "TypeDependsOnUserIVs"
def pbGetMoveData(move_id, move_data_type = -1) return pbHiddenPower(pkmn)[1]
Deprecation.warn_method('pbGetMoveData', 'v20', 'GameData::Move.get(move_id)') when "TypeAndPowerDependOnUserBerry"
return GameData::Move.get(move_id) damage_array = {
60 => [:CHERIBERRY, :CHESTOBERRY, :PECHABERRY, :RAWSTBERRY, :ASPEARBERRY,
:LEPPABERRY, :ORANBERRY, :PERSIMBERRY, :LUMBERRY, :SITRUSBERRY,
:FIGYBERRY, :WIKIBERRY, :MAGOBERRY, :AGUAVBERRY, :IAPAPABERRY,
:RAZZBERRY, :OCCABERRY, :PASSHOBERRY, :WACANBERRY, :RINDOBERRY,
:YACHEBERRY, :CHOPLEBERRY, :KEBIABERRY, :SHUCABERRY, :COBABERRY,
:PAYAPABERRY, :TANGABERRY, :CHARTIBERRY, :KASIBBERRY, :HABANBERRY,
:COLBURBERRY, :BABIRIBERRY, :CHILANBERRY, :ROSELIBERRY],
70 => [:BLUKBERRY, :NANABBERRY, :WEPEARBERRY, :PINAPBERRY, :POMEGBERRY,
:KELPSYBERRY, :QUALOTBERRY, :HONDEWBERRY, :GREPABERRY, :TAMATOBERRY,
:CORNNBERRY, :MAGOSTBERRY, :RABUTABERRY, :NOMELBERRY, :SPELONBERRY,
:PAMTREBERRY],
80 => [:WATMELBERRY, :DURINBERRY, :BELUEBERRY, :LIECHIBERRY, :GANLONBERRY,
:SALACBERRY, :PETAYABERRY, :APICOTBERRY, :LANSATBERRY, :STARFBERRY,
:ENIGMABERRY, :MICLEBERRY, :CUSTAPBERRY, :JABOCABERRY, :ROWAPBERRY,
:KEEBERRY, :MARANGABERRY]
}
if pkmn.hasItem?
damage_array.each do |dmg, items|
next if !items.include?(pkmn.item_id)
ret = dmg
ret += 20 if Settings::MECHANICS_GENERATION >= 6
return ret
end
end
when "ThrowUserItemAtTarget"
fling_powers = {
130 => [:IRONBALL
],
100 => [:HARDSTONE,:RAREBONE,
# Fossils
:ARMORFOSSIL,:CLAWFOSSIL,:COVERFOSSIL,:DOMEFOSSIL,:HELIXFOSSIL,
:JAWFOSSIL,:OLDAMBER,:PLUMEFOSSIL,:ROOTFOSSIL,:SAILFOSSIL,
:SKULLFOSSIL
],
90 => [:DEEPSEATOOTH,:GRIPCLAW,:THICKCLUB,
# Plates
:DRACOPLATE,:DREADPLATE,:EARTHPLATE,:FISTPLATE,:FLAMEPLATE,
:ICICLEPLATE,:INSECTPLATE,:IRONPLATE,:MEADOWPLATE,:MINDPLATE,
:PIXIEPLATE,:SKYPLATE,:SPLASHPLATE,:SPOOKYPLATE,:STONEPLATE,
:TOXICPLATE,:ZAPPLATE
],
80 => [:ASSAULTVEST,:CHIPPEDPOT,:CRACKEDPOT,:DAWNSTONE,:DUSKSTONE,
:ELECTIRIZER,:HEAVYDUTYBOOTS,:MAGMARIZER,:ODDKEYSTONE,:OVALSTONE,
:PROTECTOR,:QUICKCLAW,:RAZORCLAW,:SACHET,:SAFETYGOGGLES,
:SHINYSTONE,:STICKYBARB,:WEAKNESSPOLICY,:WHIPPEDDREAM
],
70 => [:DRAGONFANG,:POISONBARB,
# EV-training items (Macho Brace is 60)
:POWERANKLET,:POWERBAND,:POWERBELT,:POWERBRACER,:POWERLENS,
:POWERWEIGHT,
# Drives
:BURNDRIVE,:CHILLDRIVE,:DOUSEDRIVE,:SHOCKDRIVE
],
60 => [:ADAMANTORB,:DAMPROCK,:GRISEOUSORB,:HEATROCK,:LEEK,:LUSTROUSORB,
:MACHOBRACE,:ROCKYHELMET,:STICK,:TERRAINEXTENDER
],
50 => [:DUBIOUSDISC,:SHARPBEAK,
# Memories
:BUGMEMORY,:DARKMEMORY,:DRAGONMEMORY,:ELECTRICMEMORY,:FAIRYMEMORY,
:FIGHTINGMEMORY,:FIREMEMORY,:FLYINGMEMORY,:GHOSTMEMORY,
:GRASSMEMORY,:GROUNDMEMORY,:ICEMEMORY,:POISONMEMORY,
:PSYCHICMEMORY,:ROCKMEMORY,:STEELMEMORY,:WATERMEMORY
],
40 => [:EVIOLITE,:ICYROCK,:LUCKYPUNCH
],
30 => [:ABSORBBULB,:ADRENALINEORB,:AMULETCOIN,:BINDINGBAND,:BLACKBELT,
:BLACKGLASSES,:BLACKSLUDGE,:BOTTLECAP,:CELLBATTERY,:CHARCOAL,
:CLEANSETAG,:DEEPSEASCALE,:DRAGONSCALE,:EJECTBUTTON,:ESCAPEROPE,
:EXPSHARE,:FLAMEORB,:FLOATSTONE,:FLUFFYTAIL,:GOLDBOTTLECAP,
:HEARTSCALE,:HONEY,:KINGSROCK,:LIFEORB,:LIGHTBALL,:LIGHTCLAY,
:LUCKYEGG,:LUMINOUSMOSS,:MAGNET,:METALCOAT,:METRONOME,
:MIRACLESEED,:MYSTICWATER,:NEVERMELTICE,:PASSORB,:POKEDOLL,
:POKETOY,:PRISMSCALE,:PROTECTIVEPADS,:RAZORFANG,:SACREDASH,
:SCOPELENS,:SHELLBELL,:SHOALSALT,:SHOALSHELL,:SMOKEBALL,:SNOWBALL,
:SOULDEW,:SPELLTAG,:TOXICORB,:TWISTEDSPOON,:UPGRADE,
# Healing items
:ANTIDOTE,:AWAKENING,:BERRYJUICE,:BIGMALASADA,:BLUEFLUTE,
:BURNHEAL,:CASTELIACONE,:ELIXIR,:ENERGYPOWDER,:ENERGYROOT,:ETHER,
:FRESHWATER,:FULLHEAL,:FULLRESTORE,:HEALPOWDER,:HYPERPOTION,
:ICEHEAL,:LAVACOOKIE,:LEMONADE,:LUMIOSEGALETTE,:MAXELIXIR,
:MAXETHER,:MAXHONEY,:MAXPOTION,:MAXREVIVE,:MOOMOOMILK,:OLDGATEAU,
:PARALYZEHEAL,:PARLYZHEAL,:PEWTERCRUNCHIES,:POTION,:RAGECANDYBAR,
:REDFLUTE,:REVIVALHERB,:REVIVE,:SHALOURSABLE,:SODAPOP,
:SUPERPOTION,:SWEETHEART,:YELLOWFLUTE,
# Battle items
:XACCURACY,:XACCURACY2,:XACCURACY3,:XACCURACY6,
:XATTACK,:XATTACK2,:XATTACK3,:XATTACK6,
:XDEFEND,:XDEFEND2,:XDEFEND3,:XDEFEND6,
:XDEFENSE,:XDEFENSE2,:XDEFENSE3,:XDEFENSE6,
:XSPATK,:XSPATK2,:XSPATK3,:XSPATK6,
:XSPECIAL,:XSPECIAL2,:XSPECIAL3,:XSPECIAL6,
:XSPDEF,:XSPDEF2,:XSPDEF3,:XSPDEF6,
:XSPEED,:XSPEED2,:XSPEED3,:XSPEED6,
:DIREHIT,:DIREHIT2,:DIREHIT3,
:ABILITYURGE,:GUARDSPEC,:ITEMDROP,:ITEMURGE,:RESETURGE,
:MAXMUSHROOMS,
# Vitamins
:CALCIUM,:CARBOS,:HPUP,:IRON,:PPUP,:PPMAX,:PROTEIN,:ZINC,
:RARECANDY,
# Most evolution stones (see also 80)
:EVERSTONE,:FIRESTONE,:ICESTONE,:LEAFSTONE,:MOONSTONE,:SUNSTONE,
:THUNDERSTONE,:WATERSTONE,:SWEETAPPLE,:TARTAPPLE, :GALARICACUFF,
:GALARICAWREATH,
# Repels
:MAXREPEL,:REPEL,:SUPERREPEL,
# Mulches
:AMAZEMULCH,:BOOSTMULCH,:DAMPMULCH,:GOOEYMULCH,:GROWTHMULCH,
:RICHMULCH,:STABLEMULCH,:SURPRISEMULCH,
# Shards
:BLUESHARD,:GREENSHARD,:REDSHARD,:YELLOWSHARD,
# Valuables
:BALMMUSHROOM,:BIGMUSHROOM,:BIGNUGGET,:BIGPEARL,:COMETSHARD,
:NUGGET,:PEARL,:PEARLSTRING,:RELICBAND,:RELICCOPPER,:RELICCROWN,
:RELICGOLD,:RELICSILVER,:RELICSTATUE,:RELICVASE,:STARDUST,
:STARPIECE,:STRANGESOUVENIR,:TINYMUSHROOM,
# Exp Candies
:EXPCANDYXS, :EXPCANDYS, :EXPCANDYM, :EXPCANDYL, :EXPCANDYXL
],
20 => [# Feathers
:CLEVERFEATHER,:GENIUSFEATHER,:HEALTHFEATHER,:MUSCLEFEATHER,
:PRETTYFEATHER,:RESISTFEATHER,:SWIFTFEATHER,
:CLEVERWING,:GENIUSWING,:HEALTHWING,:MUSCLEWING,:PRETTYWING,
:RESISTWING,:SWIFTWING
],
10 => [:AIRBALLOON,:BIGROOT,:BRIGHTPOWDER,:CHOICEBAND,:CHOICESCARF,
:CHOICESPECS,:DESTINYKNOT,:DISCOUNTCOUPON,:EXPERTBELT,:FOCUSBAND,
:FOCUSSASH,:LAGGINGTAIL,:LEFTOVERS,:MENTALHERB,:METALPOWDER,
:MUSCLEBAND,:POWERHERB,:QUICKPOWDER,:REAPERCLOTH,:REDCARD,
:RINGTARGET,:SHEDSHELL,:SILKSCARF,:SILVERPOWDER,:SMOOTHROCK,
:SOFTSAND,:SOOTHEBELL,:WHITEHERB,:WIDELENS,:WISEGLASSES,:ZOOMLENS,
# Terrain seeds
:ELECTRICSEED,:GRASSYSEED,:MISTYSEED,:PSYCHICSEED,
# Nectar
:PINKNECTAR,:PURPLENECTAR,:REDNECTAR,:YELLOWNECTAR,
# Incenses
:FULLINCENSE,:LAXINCENSE,:LUCKINCENSE,:ODDINCENSE,:PUREINCENSE,
:ROCKINCENSE,:ROSEINCENSE,:SEAINCENSE,:WAVEINCENSE,
# Scarves
:BLUESCARF,:GREENSCARF,:PINKSCARF,:REDSCARF,:YELLOWSCARF,
# Mints
:LONELYMINT, :ADAMANTMINT, :NAUGHTYMINT, :BRAVEMINT, :BOLDMINT,
:IMPISHMINT, :LAXMINT, :RELAXEDMINT, :MODESTMINT, :MILDMINT,
:RASHMINT, :QUIETMINT, :CALMMINT, :GENTLEMINT, :CAREFULMINT,
:SASSYMINT, :TIMIDMINT, :HASTYMINT, :JOLLYMINT, :NAIVEMINT,
:SERIOUSMINT,
# Sweets
:STRAWBERRYSWEET, :LOVESWEET, :BERRYSWEET, :CLOVERSWEET,
:FLOWERSWEET, :STARSWEET, :RIBBONSWEET
]
}
return 0 if !pkmn.item
return 10 if pkmn.item.is_berry?
return 80 if pkmn.item.is_mega_stone?
if pkmn.item.is_TR?
ret = GameData::Move.get(pkmn.item.move).base_damage
ret = 10 if ret < 10
return ret
end
fling_powers.each do |power,items|
return power if items.include?(pkmn.item_id)
end
return 10
when "PowerHigherWithUserHP"
return [150 * pkmn.hp / pkmn.totalhp, 1].max
when "PowerLowerWithUserHP"
n = 48 * pkmn.hp / pkmn.totalhp
return 200 if n < 2
return 150 if n < 5
return 100 if n < 10
return 80 if n < 17
return 40 if n < 33
return 20
when "PowerHigherWithUserHappiness"
return [(pkmn.happiness * 2 / 5).floor, 1].max
when "PowerLowerWithUserHappiness"
return [((255 - pkmn.happiness) * 2 / 5).floor, 1].max
when "PowerHigherWithLessPP"
dmgs = [200, 80, 60, 50, 40]
ppLeft = [[(move&.pp || @total_pp) - 1, 0].max, dmgs.length - 1].min
return dmgs[ppLeft]
end
=end
return @base_damage
end end
# @deprecated This alias is slated to be removed in v20. def display_category(pkmn, move = nil); return @category; end
def pbIsHiddenMove?(move) def display_accuracy(pkmn, move = nil); return @accuracy; end
Deprecation.warn_method('pbIsHiddenMove?', 'v20', 'GameData::Move.get(move).hidden_move?')
return GameData::Move.get(move).hidden_move? def convert_move_data(data)
new_code = data[:function_code]
case data[:function_code]
when "000" then new_code = "None"
when "001" then new_code = "DoesNothingUnusableInGravity"
when "002" then new_code = "Struggle"
when "003"
if data[:id] == :RELICSONG
new_code = "SleepTargetChangeUserMeloettaForm"
elsif data[:id] == :DARKVOID && Settings::MECHANICS_GENERATION >= 7
new_code = "SleepTargetIfUserDarkrai"
else
new_code = "SleepTarget"
end
when "004" then new_code = "SleepTargetNextTurn"
when "005" then new_code = "PoisonTarget"
when "006" then new_code = "BadPoisonTarget"
when "007"
if data[:id] == :THUNDERWAVE
new_code = "ParalyzeTargetIfNotTypeImmune"
else
new_code = "ParalyzeTarget"
end
when "008" then new_code = "ParalyzeTargetAlwaysHitsInRainHitsTargetInSky"
when "009" then new_code = "ParalyzeFlinchTarget"
when "00A" then new_code = "BurnTarget"
when "00B" then new_code = "BurnFlinchTarget"
when "00C" then new_code = "FreezeTarget"
when "00D" then new_code = "FreezeTargetAlwaysHitsInHail"
when "00E" then new_code = "FreezeFlinchTarget"
when "00F", "010" then new_code = "FlinchTarget"
when "011" then new_code = "FlinchTargetFailsIfUserNotAsleep"
when "012" then new_code = "FlinchTargetFailsIfNotUserFirstTurn"
when "013", "014" then new_code = "ConfuseTarget"
when "015" then new_code = "ConfuseTargetAlwaysHitsInRainHitsTargetInSky"
when "016" then new_code = "AttractTarget"
when "017" then new_code = "ParalyzeBurnOrFreezeTarget"
when "018" then new_code = "CureUserBurnPoisonParalysis"
when "019" then new_code = "CureUserPartyStatus"
when "01A" then new_code = "StartUserSideImmunityToInflictedStatus"
when "01B" then new_code = "GiveUserStatusToTarget"
when "01C" then new_code = "RaiseUserAttack1"
when "01D" then new_code = "RaiseUserDefense1"
when "01E" then new_code = "RaiseUserDefense1CurlUpUser"
when "01F" then new_code = "RaiseUserSpeed1"
when "020" then new_code = "RaiseUserSpAtk1"
when "021" then new_code = "RaiseUserSpDef1PowerUpElectricMove"
when "022" then new_code = "RaiseUserEvasion1"
when "023" then new_code = "RaiseUserCriticalHitRate2"
when "024" then new_code = "RaiseUserAtkDef1"
when "025" then new_code = "RaiseUserAtkDefAcc1"
when "026" then new_code = "RaiseUserAtkSpd1"
when "027" then new_code = "RaiseUserAtkSpAtk1"
when "028" then new_code = "RaiseUserAtkSpAtk1Or2InSun"
when "029" then new_code = "RaiseUserAtkAcc1"
when "02A" then new_code = "RaiseUserDefSpDef1"
when "02B" then new_code = "RaiseUserSpAtkSpDefSpd1"
when "02C" then new_code = "RaiseUserSpAtkSpDef1"
when "02D" then new_code = "RaiseUserMainStats1"
when "02E" then new_code = "RaiseUserAttack2"
when "02F" then new_code = "RaiseUserDefense2"
when "030" then new_code = "RaiseUserSpeed2"
when "031" then new_code = "RaiseUserSpeed2LowerUserWeight"
when "032" then new_code = "RaiseUserSpAtk2"
when "033" then new_code = "RaiseUserSpDef2"
when "034" then new_code = "RaiseUserEvasion2MinimizeUser"
when "035" then new_code = "LowerUserDefSpDef1RaiseUserAtkSpAtkSpd2"
when "036" then new_code = "RaiseUserAtk1Spd2"
when "037" then new_code = "RaiseTargetRandomStat2"
when "038" then new_code = "RaiseUserDefense3"
when "039" then new_code = "RaiseUserSpAtk3"
when "03A" then new_code = "MaxUserAttackLoseHalfOfTotalHP"
when "03B" then new_code = "LowerUserAtkDef1"
when "03C" then new_code = "LowerUserDefSpDef1"
when "03D" then new_code = "LowerUserDefSpDefSpd1"
when "03E" then new_code = "LowerUserSpeed1"
when "03F" then new_code = "LowerUserSpAtk2"
when "040" then new_code = "RaiseTargetSpAtk1ConfuseTarget"
when "041" then new_code = "RaiseTargetAttack2ConfuseTarget"
when "042" then new_code = "LowerTargetAttack1"
when "043" then new_code = "LowerTargetDefense1"
when "044"
if data[:id] == :BULLDOZE
new_code = "LowerTargetSpeed1WeakerInGrassyTerrain"
else
new_code = "LowerTargetSpeed1"
end
when "045" then new_code = "LowerTargetSpAtk1"
when "046" then new_code = "LowerTargetSpDef1"
when "047" then new_code = "LowerTargetAccuracy1"
when "048"
if data[:id] == :SWEETSCENT && Settings::MECHANICS_GENERATION >= 6
new_code = "LowerTargetEvasion2"
else
new_code = "LowerTargetEvasion1"
end
when "049" then new_code = "LowerTargetEvasion1RemoveSideEffects"
when "04A" then new_code = "LowerTargetAtkDef1"
when "04B" then new_code = "LowerTargetAttack2"
when "04C" then new_code = "LowerTargetDefense2"
when "04D" then new_code = "LowerTargetSpeed2"
when "04E" then new_code = "LowerTargetSpAtk2IfCanAttract"
when "04F" then new_code = "LowerTargetSpDef2"
when "050" then new_code = "ResetTargetStatStages"
when "051" then new_code = "ResetAllBattlersStatStages"
when "052" then new_code = "UserTargetSwapAtkSpAtkStages"
when "053" then new_code = "UserTargetSwapDefSpDefStages"
when "054" then new_code = "UserTargetSwapStatStages"
when "055" then new_code = "UserCopyTargetStatStages"
when "056" then new_code = "StartUserSideImmunityToStatStageLowering"
when "057" then new_code = "UserSwapBaseAtkDef"
when "058" then new_code = "UserTargetAverageBaseAtkSpAtk"
when "059" then new_code = "UserTargetAverageBaseDefSpDef"
when "05A" then new_code = "UserTargetAverageHP"
when "05B" then new_code = "StartUserSideDoubleSpeed"
when "05C" then new_code = "ReplaceMoveThisBattleWithTargetLastMoveUsed"
when "05D" then new_code = "ReplaceMoveWithTargetLastMoveUsed"
when "05E" then new_code = "SetUserTypesToUserMoveType"
when "05F" then new_code = "SetUserTypesToResistLastAttack"
when "060" then new_code = "SetUserTypesBasedOnEnvironment"
when "061" then new_code = "SetTargetTypesToWater"
when "062" then new_code = "SetUserTypesToTargetTypes"
when "063" then new_code = "SetTargetAbilityToSimple"
when "064" then new_code = "SetTargetAbilityToInsomnia"
when "065" then new_code = "SetUserAbilityToTargetAbility"
when "066" then new_code = "SetTargetAbilityToUserAbility"
when "067" then new_code = "UserTargetSwapAbilities"
when "068" then new_code = "NegateTargetAbility"
when "069" then new_code = "TransformUserIntoTarget"
when "06A" then new_code = "FixedDamage20"
when "06B" then new_code = "FixedDamage40"
when "06C" then new_code = "FixedDamageHalfTargetHP"
when "06D" then new_code = "FixedDamageUserLevel"
when "06E" then new_code = "LowerTargetHPToUserHP"
when "06F" then new_code = "FixedDamageUserLevelRandom"
when "070"
if data[:id] == :FISSURE
new_code = "OHKOHitsUndergroundTarget"
elsif data[:id] == :SHEERCOLD && Settings::MECHANICS_GENERATION >= 7
new_code = "OHKOIce"
else
new_code = "OHKO"
end
when "071" then new_code = "CounterPhysicalDamage"
when "072" then new_code = "CounterSpecialDamage"
when "073" then new_code = "CounterDamagePlusHalf"
when "074" then new_code = "DamageTargetAlly"
when "075" then new_code = "DoublePowerIfTargetUnderwater"
when "076" then new_code = "DoublePowerIfTargetUnderground"
when "077" then new_code = "DoublePowerIfTargetInSky"
when "078" then new_code = "FlinchTargetDoublePowerIfTargetInSky"
when "079" then new_code = "DoublePowerAfterFusionFlare"
when "07A" then new_code = "DoublePowerAfterFusionBolt"
when "07B" then new_code = "DoublePowerIfTargetPoisoned"
when "07C" then new_code = "DoublePowerIfTargetParalyzedCureTarget"
when "07D" then new_code = "DoublePowerIfTargetAsleepCureTarget"
when "07E" then new_code = "DoublePowerIfUserPoisonedBurnedParalyzed"
when "07F" then new_code = "DoublePowerIfTargetStatusProblem"
when "080" then new_code = "DoublePowerIfTargetHPLessThanHalf"
when "081" then new_code = "DoublePowerIfUserLostHPThisTurn"
when "082" then new_code = "DoublePowerIfTargetLostHPThisTurn"
when "083" then new_code = "UsedAfterAllyRoundWithDoublePower"
when "084" then new_code = "DoublePowerIfTargetActed"
when "085" then new_code = "DoublePowerIfAllyFaintedLastTurn"
when "086" then new_code = "DoublePowerIfUserHasNoItem"
when "087" then new_code = "TypeAndPowerDependOnWeather"
when "088" then new_code = "PursueSwitchingFoe"
when "089" then new_code = "PowerHigherWithUserHappiness"
when "08A" then new_code = "PowerLowerWithUserHappiness"
when "08B" then new_code = "PowerHigherWithUserHP"
when "08C" then new_code = "PowerHigherWithTargetHP"
when "08D" then new_code = "PowerHigherWithTargetFasterThanUser"
when "08E" then new_code = "PowerHigherWithUserPositiveStatStages"
when "08F" then new_code = "PowerHigherWithTargetPositiveStatStages"
when "090" then new_code = "TypeDependsOnUserIVs"
when "091" then new_code = "PowerHigherWithConsecutiveUse"
when "092" then new_code = "PowerHigherWithConsecutiveUseOnUserSide"
when "093" then new_code = "StartRaiseUserAtk1WhenDamaged"
when "094" then new_code = "RandomlyDamageOrHealTarget"
when "095" then new_code = "RandomPowerDoublePowerIfTargetUnderground"
when "096" then new_code = "TypeAndPowerDependOnUserBerry"
when "097" then new_code = "PowerHigherWithLessPP"
when "098" then new_code = "PowerLowerWithUserHP"
when "099" then new_code = "PowerHigherWithUserFasterThanTarget"
when "09A" then new_code = "PowerHigherWithTargetWeight"
when "09B" then new_code = "PowerHigherWithUserHeavierThanTarget"
when "09C" then new_code = "PowerUpAllyMove"
when "09D" then new_code = "StartWeakenElectricMoves"
when "09E" then new_code = "StartWeakenFireMoves"
when "09F"
case data[:id]
when :MULTIATTACK
new_code = "TypeDependsOnUserMemory"
when :TECHNOBLAST
new_code = "TypeDependsOnUserDrive"
else
new_code = "TypeDependsOnUserPlate"
end
when "0A0" then new_code = "AlwaysCriticalHit"
when "0A1" then new_code = "StartPreventCriticalHitsAgainstUserSide"
when "0A2" then new_code = "StartWeakenPhysicalDamageAgainstUserSide"
when "0A3" then new_code = "StartWeakenSpecialDamageAgainstUserSide"
when "0A4" then new_code = "EffectDependsOnEnvironment"
when "0A5"
new_code = "None"
data[:accuracy] = 0
when "0A6" then new_code = "EnsureNextMoveAlwaysHits"
when "0A7" then new_code = "StartNegateTargetEvasionStatStageAndGhostImmunity"
when "0A8" then new_code = "StartNegateTargetEvasionStatStageAndDarkImmunity"
when "0A9" then new_code = "IgnoreTargetDefSpDefEvaStatStages"
when "0AA" then new_code = "ProtectUser"
when "0AB" then new_code = "ProtectUserSideFromPriorityMoves"
when "0AC" then new_code = "ProtectUserSideFromMultiTargetDamagingMoves"
when "0AD" then new_code = "RemoveProtections"
when "0AE" then new_code = "UseLastMoveUsedByTarget"
when "0AF" then new_code = "UseLastMoveUsed"
when "0B0" then new_code = "UseMoveTargetIsAboutToUse"
when "0B1" then new_code = "BounceBackProblemCausingStatusMoves"
when "0B2" then new_code = "StealAndUseBeneficialStatusMove"
when "0B3" then new_code = "UseMoveDependingOnEnvironment"
when "0B4" then new_code = "UseRandomUserMoveIfAsleep"
when "0B5" then new_code = "UseRandomMoveFromUserParty"
when "0B6" then new_code = "UseRandomMove"
when "0B7" then new_code = "DisableTargetUsingSameMoveConsecutively"
when "0B8" then new_code = "DisableTargetMovesKnownByUser"
when "0B9" then new_code = "DisableTargetLastMoveUsed"
when "0BA" then new_code = "DisableTargetStatusMoves"
when "0BB" then new_code = "DisableTargetHealingMoves"
when "0BC" then new_code = "DisableTargetUsingDifferentMove"
when "0BD" then new_code = "HitTwoTimes"
when "0BE" then new_code = "HitTwoTimesPoisonTarget"
when "0BF" then new_code = "HitThreeTimesPowersUpWithEachHit"
when "0C0"
if data[:id] == :WATERSHURIKEN
new_code = "HitTwoToFiveTimesOrThreeForAshGreninja"
else
new_code = "HitTwoToFiveTimes"
end
when "0C1" then new_code = "HitOncePerUserTeamMember"
when "0C2" then new_code = "AttackAndSkipNextTurn"
when "0C3" then new_code = "TwoTurnAttack"
when "0C4" then new_code = "TwoTurnAttackOneTurnInSun"
when "0C5" then new_code = "TwoTurnAttackParalyzeTarget"
when "0C6" then new_code = "TwoTurnAttackBurnTarget"
when "0C7" then new_code = "TwoTurnAttackFlinchTarget"
when "0C8" then new_code = "TwoTurnAttackChargeRaiseUserDefense1"
when "0C9" then new_code = "TwoTurnAttackInvulnerableInSky"
when "0CA" then new_code = "TwoTurnAttackInvulnerableUnderground"
when "0CB" then new_code = "TwoTurnAttackInvulnerableUnderwater"
when "0CC" then new_code = "TwoTurnAttackInvulnerableInSkyParalyzeTarget"
when "0CD" then new_code = "TwoTurnAttackInvulnerableRemoveProtections"
when "0CE" then new_code = "TwoTurnAttackInvulnerableInSkyTargetCannotAct"
when "0CF" then new_code = "BindTarget"
when "0D0" then new_code = "BindTargetDoublePowerIfTargetUnderwater"
when "0D1" then new_code = "MultiTurnAttackPreventSleeping"
when "0D2" then new_code = "MultiTurnAttackConfuseUserAtEnd"
when "0D3" then new_code = "MultiTurnAttackPowersUpEachTurn"
when "0D4" then new_code = "MultiTurnAttackBideThenReturnDoubleDamage"
when "0D5" then new_code = "HealUserHalfOfTotalHP"
when "0D6" then new_code = "HealUserHalfOfTotalHPLoseFlyingTypeThisTurn"
when "0D7" then new_code = "HealUserPositionNextTurn"
when "0D8" then new_code = "HealUserDependingOnWeather"
when "0D9" then new_code = "HealUserFullyAndFallAsleep"
when "0DA" then new_code = "StartHealUserEachTurn"
when "0DB" then new_code = "StartHealUserEachTurnTrapUserInBattle"
when "0DC" then new_code = "StartLeechSeedTarget"
when "0DD" then new_code = "HealUserByHalfOfDamageDone"
when "0DE" then new_code = "HealUserByHalfOfDamageDoneIfTargetAsleep"
when "0DF" then new_code = "HealTargetHalfOfTotalHP"
when "0E0" then new_code = "UserFaintsExplosive"
when "0E1" then new_code = "UserFaintsFixedDamageUserHP"
when "0E2" then new_code = "UserFaintsLowerTargetAtkSpAtk2"
when "0E3" then new_code = "UserFaintsHealAndCureReplacement"
when "0E4" then new_code = "UserFaintsHealAndCureReplacementRestorePP"
when "0E5" then new_code = "StartPerishCountsForAllBattlers"
when "0E6" then new_code = "SetAttackerMovePPTo0IfUserFaints"
when "0E7" then new_code = "AttackerFaintsIfUserFaints"
when "0E8" then new_code = "UserEnduresFaintingThisTurn"
when "0E9" then new_code = "CannotMakeTargetFaint"
when "0EA"
if Settings::MECHANICS_GENERATION >= 8
new_code = "SwitchOutUserStatusMove"
else
new_code = "FleeFromBattle"
end
when "0EB" then new_code = "SwitchOutTargetStatusMove"
when "0EC" then new_code = "SwitchOutTargetDamagingMove"
when "0ED" then new_code = "SwitchOutUserPassOnEffects"
when "0EE" then new_code = "SwitchOutUserDamagingMove"
when "0EF" then new_code = "TrapTargetInBattle"
when "0F0" then new_code = "RemoveTargetItem"
when "0F1" then new_code = "UserTakesTargetItem"
when "0F2" then new_code = "UserTargetSwapItems"
when "0F3" then new_code = "TargetTakesUserItem"
when "0F4" then new_code = "UserConsumeTargetBerry"
when "0F5" then new_code = "DestroyTargetBerryOrGem"
when "0F6" then new_code = "RestoreUserConsumedItem"
when "0F7" then new_code = "ThrowUserItemAtTarget"
when "0F8" then new_code = "StartTargetCannotUseItem"
when "0F9" then new_code = "StartNegateHeldItems"
when "0FA" then new_code = "RecoilQuarterOfDamageDealt"
when "0FB" then new_code = "RecoilThirdOfDamageDealt"
when "0FC" then new_code = "RecoilHalfOfDamageDealt"
when "0FD" then new_code = "RecoilThirdOfDamageDealtParalyzeTarget"
when "0FE" then new_code = "RecoilThirdOfDamageDealtBurnTarget"
when "0FF" then new_code = "StartSunWeather"
when "100" then new_code = "StartRainWeather"
when "101" then new_code = "StartSandstormWeather"
when "102" then new_code = "StartHailWeather"
when "103" then new_code = "AddSpikesToFoeSide"
when "104" then new_code = "AddToxicSpikesToFoeSide"
when "105" then new_code = "AddStealthRocksToFoeSide"
when "106" then new_code = "GrassPledge"
when "107" then new_code = "FirePledge"
when "108" then new_code = "WaterPledge"
when "109" then new_code = "AddMoneyGainedFromBattle"
when "10A" then new_code = "RemoveScreens"
when "10B" then new_code = "CrashDamageIfFailsUnusableInGravity"
when "10C" then new_code = "UserMakeSubstitute"
when "10D" then new_code = "CurseTargetOrLowerUserSpd1RaiseUserAtkDef1"
when "10E" then new_code = "LowerPPOfTargetLastMoveBy4"
when "10F" then new_code = "StartDamageTargetEachTurnIfTargetAsleep"
when "110" then new_code = "RemoveUserBindingAndEntryHazards"
when "111" then new_code = "AttackTwoTurnsLater"
when "112" then new_code = "UserAddStockpileRaiseDefSpDef1"
when "113" then new_code = "PowerDependsOnUserStockpile"
when "114" then new_code = "HealUserDependingOnUserStockpile"
when "115" then new_code = "FailsIfUserDamagedThisTurn"
when "116" then new_code = "FailsIfTargetActed"
when "117" then new_code = "RedirectAllMovesToUser"
when "118" then new_code = "StartGravity"
when "119" then new_code = "StartUserAirborne"
when "11A" then new_code = "StartTargetAirborneAndAlwaysHitByMoves"
when "11B" then new_code = "HitsTargetInSky"
when "11C" then new_code = "HitsTargetInSkyGroundsTarget"
when "11D" then new_code = "TargetActsNext"
when "11E" then new_code = "TargetActsLast"
when "11F" then new_code = "StartSlowerBattlersActFirst"
when "120" then new_code = "UserSwapsPositionsWithAlly"
when "121" then new_code = "UseTargetAttackInsteadOfUserAttack"
when "122" then new_code = "UseTargetDefenseInsteadOfTargetSpDef"
when "123" then new_code = "FailsUnlessTargetSharesTypeWithUser"
when "124" then new_code = "StartSwapAllBattlersBaseDefensiveStats"
when "125" then new_code = "FailsIfUserHasUnusedMove"
when "126" then new_code = "None"
when "127" then new_code = "ParalyzeTarget"
when "128" then new_code = "BurnTarget"
when "129" then new_code = "FreezeTarget"
when "12A" then new_code = "ConfuseTarget"
when "12B" then new_code = "LowerTargetDefense2"
when "12C" then new_code = "LowerTargetEvasion2"
when "12D" then new_code = "DoublePowerIfTargetUnderwater"
when "12E" then new_code = "AllBattlersLoseHalfHPUserSkipsNextTurn"
when "12F" then new_code = "TrapTargetInBattle"
when "130" then new_code = "UserLosesHalfHP"
when "131" then new_code = "StartShadowSkyWeather"
when "132" then new_code = "RemoveAllScreens"
when "133" then new_code = "DoesNothingFailsIfNoAlly"
when "134" then new_code = "DoesNothingCongratulations"
when "135" then new_code = "FreezeTargetSuperEffectiveAgainstWater"
when "136" then new_code = "RaiseUserDefense2"
when "137" then new_code = "RaisePlusMinusUserAndAlliesDefSpDef1"
when "138" then new_code = "RaiseTargetSpDef1"
when "139" then new_code = "LowerTargetAttack1BypassSubstitute"
when "13A" then new_code = "LowerTargetAtkSpAtk1"
when "13B" then new_code = "HoopaRemoveProtectionsBypassSubstituteLowerUserDef1"
when "13C" then new_code = "LowerTargetSpAtk1"
when "13D" then new_code = "LowerTargetSpAtk2"
when "13E" then new_code = "RaiseGroundedGrassBattlersAtkSpAtk1"
when "13F" then new_code = "RaiseGrassBattlersDef1"
when "140" then new_code = "LowerPoisonedTargetAtkSpAtkSpd1"
when "141" then new_code = "InvertTargetStatStages"
when "142" then new_code = "AddGhostTypeToTarget"
when "143" then new_code = "AddGrassTypeToTarget"
when "144" then new_code = "EffectivenessIncludesFlyingType"
when "145" then new_code = "TargetMovesBecomeElectric"
when "146" then new_code = "NormalMovesBecomeElectric"
when "147" then new_code = "RemoveProtectionsBypassSubstitute"
when "148" then new_code = "TargetNextFireMoveDamagesTarget"
when "149" then new_code = "ProtectUserSideFromDamagingMovesIfUserFirstTurn"
when "14A" then new_code = "ProtectUserSideFromStatusMoves"
when "14B" then new_code = "ProtectUserFromDamagingMovesKingsShield"
when "14C" then new_code = "ProtectUserFromTargetingMovesSpikyShield"
when "14D" then new_code = "TwoTurnAttackInvulnerableRemoveProtections"
when "14E" then new_code = "TwoTurnAttackRaiseUserSpAtkSpDefSpd2"
when "14F" then new_code = "HealUserByThreeQuartersOfDamageDone"
when "150" then new_code = "RaiseUserAttack3IfTargetFaints"
when "151" then new_code = "LowerTargetAtkSpAtk1SwitchOutUser"
when "152" then new_code = "TrapAllBattlersInBattleForOneTurn"
when "153" then new_code = "AddStickyWebToFoeSide"
when "154" then new_code = "StartElectricTerrain"
when "155" then new_code = "StartGrassyTerrain"
when "156" then new_code = "StartMistyTerrain"
when "157" then new_code = "DoubleMoneyGainedFromBattle"
when "158" then new_code = "FailsIfUserNotConsumedBerry"
when "159" then new_code = "PoisonTargetLowerTargetSpeed1"
when "15A" then new_code = "CureTargetBurn"
when "15B" then new_code = "CureTargetStatusHealUserHalfOfTotalHP"
when "15C" then new_code = "RaisePlusMinusUserAndAlliesAtkSpAtk1"
when "15D" then new_code = "UserStealTargetPositiveStatStages"
when "15E" then new_code = "EnsureNextCriticalHit"
when "15F" then new_code = "LowerUserDefense1"
when "160" then new_code = "HealUserByTargetAttackLowerTargetAttack1"
when "161" then new_code = "UserTargetSwapBaseSpeed"
when "162" then new_code = "UserLosesFireType"
when "163" then new_code = "IgnoreTargetAbility"
when "164" then new_code = "CategoryDependsOnHigherDamageIgnoreTargetAbility"
when "165" then new_code = "NegateTargetAbilityIfTargetActed"
when "166" then new_code = "DoublePowerIfUserLastMoveFailed"
when "167" then new_code = "StartWeakenDamageAgainstUserSideIfHail"
when "168" then new_code = "ProtectUserBanefulBunker"
when "169" then new_code = "TypeIsUserFirstType"
when "16A" then new_code = "RedirectAllMovesToTarget"
when "16B" then new_code = "TargetUsesItsLastUsedMoveAgain"
when "16C" then new_code = "DisableTargetSoundMoves"
when "16D" then new_code = "HealUserDependingOnSandstorm"
when "16E" then new_code = "HealTargetDependingOnGrassyTerrain"
when "16F" then new_code = "HealAllyOrDamageFoe"
when "170" then new_code = "UserLosesHalfOfTotalHPExplosive"
when "171" then new_code = "UsedAfterUserTakesPhysicalDamage"
when "172" then new_code = "BurnAttackerBeforeUserActs"
when "173" then new_code = "StartPsychicTerrain"
when "174" then new_code = "FailsIfNotUserFirstTurn"
when "175" then new_code = "HitTwoTimesFlinchTarget"
end
data[:function_code] = new_code
return data
end
end
end end

View File

@@ -1,21 +1,38 @@
module GameData module GameData
class Item class Item
attr_reader :id attr_reader :id
attr_reader :id_number
attr_reader :real_name attr_reader :real_name
attr_reader :real_name_plural attr_reader :real_name_plural
attr_reader :pocket attr_reader :pocket
attr_reader :price attr_reader :price
attr_reader :sell_price
attr_reader :real_description attr_reader :real_description
attr_reader :field_use attr_reader :field_use
attr_reader :battle_use attr_reader :battle_use
attr_reader :type attr_reader :consumable
attr_reader :flags
attr_reader :move attr_reader :move
DATA = {} DATA = {}
DATA_FILENAME = "items.dat" DATA_FILENAME = "items.dat"
extend ClassMethods SCHEMA = {
"Name" => [:name, "s"],
"NamePlural" => [:name_plural, "s"],
"Pocket" => [:pocket, "v"],
"Price" => [:price, "u"],
"SellPrice" => [:sell_price, "u"],
"Description" => [:description, "q"],
"FieldUse" => [:field_use, "e", { "OnPokemon" => 1, "Direct" => 2, "TM" => 3,
"HM" => 4, "TR" => 5 }],
"BattleUse" => [:battle_use, "e", { "OnPokemon" => 1, "OnMove" => 2, "OnBattler" => 3,
"OnFoe" => 4, "Direct" => 5 }],
"Consumable" => [:consumable, "b"],
"Flags" => [:flags, "*s"],
"Move" => [:move, "e", :Move]
}
extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def self.icon_filename(item) def self.icon_filename(item)
@@ -65,49 +82,55 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed" @real_name = hash[:name] || "Unnamed"
@real_name_plural = hash[:name_plural] || "Unnamed" @real_name_plural = hash[:name_plural] || "Unnamed"
@pocket = hash[:pocket] || 1 @pocket = hash[:pocket] || 1
@price = hash[:price] || 0 @price = hash[:price] || 0
@sell_price = hash[:sell_price] || (@price / 2)
@real_description = hash[:description] || "???" @real_description = hash[:description] || "???"
@field_use = hash[:field_use] || 0 @field_use = hash[:field_use] || 0
@battle_use = hash[:battle_use] || 0 @battle_use = hash[:battle_use] || 0
@type = hash[:type] || 0 @flags = hash[:flags] || []
@consumable = hash[:consumable]
@consumable = !is_important? if @consumable.nil?
@move = hash[:move] @move = hash[:move]
end end
# @return [String] the translated name of this item # @return [String] the translated name of this item
def name def name
return pbGetMessage(MessageTypes::Items, @id_number) return pbGetMessageFromHash(MessageTypes::Items, @real_name)
end end
# @return [String] the translated plural version of the name of this item # @return [String] the translated plural version of the name of this item
def name_plural def name_plural
return pbGetMessage(MessageTypes::ItemPlurals, @id_number) return pbGetMessageFromHash(MessageTypes::ItemPlurals, @real_name_plural)
end end
# @return [String] the translated description of this item # @return [String] the translated description of this item
def description def description
return pbGetMessage(MessageTypes::ItemDescriptions, @id_number) return pbGetMessageFromHash(MessageTypes::ItemDescriptions, @real_description)
end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end end
def is_TM?; return @field_use == 3; end def is_TM?; return @field_use == 3; end
def is_HM?; return @field_use == 4; end def is_HM?; return @field_use == 4; end
def is_TR?; return @field_use == 6; end def is_TR?; return @field_use == 5; end
def is_machine?; return is_TM? || is_HM? || is_TR?; end def is_machine?; return is_TM? || is_HM? || is_TR?; end
def is_mail?; return @type == 1 || @type == 2; end def is_mail?; return has_flag?("Mail") || has_flag?("IconMail"); end
def is_icon_mail?; return @type == 2; end def is_icon_mail?; return has_flag?("IconMail"); end
def is_poke_ball?; return @type == 3 || @type == 4; end def is_poke_ball?; return has_flag?("PokeBall") || has_flag?("SnagBall"); end
def is_snag_ball?; return @type == 3 || (@type == 4 && $Trainer.has_snag_machine); end def is_snag_ball?; return has_flag?("SnagBall") || (is_poke_ball? && $player.has_snag_machine); end
def is_berry?; return @type == 5; end def is_berry?; return has_flag?("Berry"); end
def is_key_item?; return @type == 6; end def is_key_item?; return has_flag?("KeyItem"); end
def is_evolution_stone?; return @type == 7; end def is_evolution_stone?; return has_flag?("EvolutionStone"); end
def is_fossil?; return @type == 8; end def is_fossil?; return has_flag?("Fossil"); end
def is_apricorn?; return @type == 9; end def is_apricorn?; return has_flag?("Apricorn"); end
def is_gem?; return @type == 10; end def is_gem?; return has_flag?("TypeGem"); end
def is_mulch?; return @type == 11; end def is_mulch?; return has_flag?("Mulch"); end
def is_mega_stone?; return @type == 12; end # Does NOT include Red Orb/Blue Orb def is_mega_stone?; return has_flag?("MegaStone"); end # Does NOT include Red Orb/Blue Orb
def is_important? def is_important?
return true if is_key_item? || is_HM? || is_TM? return true if is_key_item? || is_HM? || is_TM?
@@ -116,6 +139,10 @@ module GameData
def can_hold?; return !is_important?; end def can_hold?; return !is_important?; end
def consumed_after_use?
return !is_important? && @consumable
end
def unlosable?(species, ability) def unlosable?(species, ability)
return false if species == :ARCEUS && ability != :MULTITYPE return false if species == :ARCEUS && ability != :MULTITYPE
return false if species == :SILVALLY && ability != :RKSSYSTEM return false if species == :SILVALLY && ability != :RKSSYSTEM
@@ -157,156 +184,11 @@ module GameData
:GIRATINA => [:GRISEOUSORB], :GIRATINA => [:GRISEOUSORB],
:GENESECT => [:BURNDRIVE, :CHILLDRIVE, :DOUSEDRIVE, :SHOCKDRIVE], :GENESECT => [:BURNDRIVE, :CHILLDRIVE, :DOUSEDRIVE, :SHOCKDRIVE],
:KYOGRE => [:BLUEORB], :KYOGRE => [:BLUEORB],
:GROUDON => [:REDORB] :GROUDON => [:REDORB],
:ZACIAN => [:RUSTEDSWORD],
:ZAMAZENTA => [:RUSTEDSHIELD]
} }
return combos[species] && combos[species].include?(@id) return combos[species]&.include?(@id)
end end
end end
end end
#===============================================================================
# Deprecated methods
#===============================================================================
# @deprecated This alias is slated to be removed in v20.
def pbGetPocket(item)
Deprecation.warn_method('pbGetPocket', 'v20', 'GameData::Item.get(item).pocket')
return GameData::Item.get(item).pocket
end
# @deprecated This alias is slated to be removed in v20.
def pbGetPrice(item)
Deprecation.warn_method('pbGetPrice', 'v20', 'GameData::Item.get(item).price')
return GameData::Item.get(item).price
end
# @deprecated This alias is slated to be removed in v20.
def pbGetMachine(item)
Deprecation.warn_method('pbGetMachine', 'v20', 'GameData::Item.get(item).move')
return GameData::Item.get(item).move
end
# @deprecated This alias is slated to be removed in v20.
def pbIsTechnicalMachine?(item)
Deprecation.warn_method('pbIsTechnicalMachine?', 'v20', 'GameData::Item.get(item).is_TM?')
return GameData::Item.get(item).is_TM?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsHiddenMachine?(item)
Deprecation.warn_method('pbIsHiddenMachine?', 'v20', 'GameData::Item.get(item).is_HM?')
return GameData::Item.get(item).is_HM?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsMachine?(item)
Deprecation.warn_method('pbIsMachine?', 'v20', 'GameData::Item.get(item).is_machine?')
return GameData::Item.get(item).is_machine?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsMail?(item)
Deprecation.warn_method('pbIsMail?', 'v20', 'GameData::Item.get(item).is_mail?')
return GameData::Item.get(item).is_mail?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsMailWithPokemonIcons?(item)
Deprecation.warn_method('pbIsMailWithPokemonIcons?', 'v20', 'GameData::Item.get(item).is_icon_mail?')
return GameData::Item.get(item).is_icon_mail?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsPokeBall?(item)
Deprecation.warn_method('pbIsPokeBall?', 'v20', 'GameData::Item.get(item).is_poke_ball?')
return GameData::Item.get(item).is_poke_ball?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsSnagBall?(item)
Deprecation.warn_method('pbIsSnagBall?', 'v20', 'GameData::Item.get(item).is_snag_ball?')
return GameData::Item.get(item).is_snag_ball?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsBerry?(item)
Deprecation.warn_method('pbIsBerry?', 'v20', 'GameData::Item.get(item).is_berry?')
return GameData::Item.get(item).is_berry?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsKeyItem?(item)
Deprecation.warn_method('pbIsKeyItem?', 'v20', 'GameData::Item.get(item).is_key_item?')
return GameData::Item.get(item).is_key_item?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsEvolutionStone?(item)
Deprecation.warn_method('pbIsEvolutionStone?', 'v20', 'GameData::Item.get(item).is_evolution_stone?')
return GameData::Item.get(item).is_evolution_stone?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsFossil?(item)
Deprecation.warn_method('pbIsFossil?', 'v20', 'GameData::Item.get(item).is_fossil?')
return GameData::Item.get(item).is_fossil?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsApricorn?(item)
Deprecation.warn_method('pbIsApricorn?', 'v20', 'GameData::Item.get(item).is_apricorn?')
return GameData::Item.get(item).is_apricorn?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsGem?(item)
Deprecation.warn_method('pbIsGem?', 'v20', 'GameData::Item.get(item).is_gem?')
return GameData::Item.get(item).is_gem?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsMulch?(item)
Deprecation.warn_method('pbIsMulch?', 'v20', 'GameData::Item.get(item).is_mulch?')
return GameData::Item.get(item).is_mulch?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsMegaStone?(item)
Deprecation.warn_method('pbIsMegaStone?', 'v20', 'GameData::Item.get(item).is_mega_stone?')
return GameData::Item.get(item).is_mega_stone?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsImportantItem?(item)
Deprecation.warn_method('pbIsImportantItem?', 'v20', 'GameData::Item.get(item).is_important?')
return GameData::Item.get(item).is_important?
end
# @deprecated This alias is slated to be removed in v20.
def pbCanHoldItem?(item)
Deprecation.warn_method('pbCanHoldItem?', 'v20', 'GameData::Item.get(item).can_hold?')
return GameData::Item.get(item).can_hold?
end
# @deprecated This alias is slated to be removed in v20.
def pbIsUnlosableItem?(check_item, species, ability)
Deprecation.warn_method('pbIsUnlosableItem?', 'v20', 'GameData::Item.get(item).unlosable?')
return GameData::Item.get(check_item).unlosable?(species, ability)
end
# @deprecated This alias is slated to be removed in v20.
def pbItemIconFile(item)
Deprecation.warn_method('pbItemIconFile', 'v20', 'GameData::Item.icon_filename(item)')
return GameData::Item.icon_filename(item)
end
# @deprecated This alias is slated to be removed in v20.
def pbHeldItemIconFile(item)
Deprecation.warn_method('pbHeldItemIconFile', 'v20', 'GameData::Item.held_icon_filename(item)')
return GameData::Item.held_icon_filename(item)
end
# @deprecated This alias is slated to be removed in v20.
def pbMailBackFile(item)
Deprecation.warn_method('pbMailBackFile', 'v20', 'GameData::Item.mail_filename(item)')
return GameData::Item.mail_filename(item)
end

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