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/
*.code-workspace
.idea/
*.mkproj
# Operating system generated files & folders
.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 #
# Version 19.1.dev #
# Version 20 #
# https://github.com/Maruno17/pokemon-essentials #
#==============================================================================#
module Settings
# 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
# 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
# single generation's mechanics. It's considered to be good enough. Only
# 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.
MAX_MONEY = 999_999
# The maximum number of Game Corner coins the player can have.
@@ -58,12 +30,114 @@ module Settings
MAX_PLAYER_NAME_SIZE = 10
# The maximum number of Pokémon that can be in the party.
MAX_PARTY_SIZE = 6
# 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
# Whether super shininess is enabled (uses a different shiny animation).
SUPER_SHINY = (MECHANICS_GENERATION >= 8)
# The odds of a wild Pokémon/bred egg having Pokérus (out of 65536).
POKERUS_CHANCE = 3
#=============================================================================
# A set of arrays each containing a trainer type followed by a Global 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.
# Whether outdoor maps should be shaded according to the time of day.
TIME_SHADING = true
# Whether poisoned Pokémon will lose HP while walking around in the field.
POISON_IN_FIELD = (MECHANICS_GENERATION <= 4)
# Whether poisoned Pokémon will faint while walking around in the field
# (true), or survive the poisoning with 1 HP (false).
POISON_FAINT_IN_FIELD = (MECHANICS_GENERATION <= 3)
# Whether planted berries grow according to Gen 4 mechanics (true) or Gen 3
# mechanics (false).
NEW_BERRY_PLANTS = (MECHANICS_GENERATION >= 4)
# Whether fishing automatically hooks the Pokémon (true), or whether there is
# a reaction test first (false).
FISHING_AUTO_HOOK = false
# The ID of the common event that runs when the player starts fishing (runs
# instead of showing the casting animation).
FISHING_BEGIN_COMMON_EVENT = -1
# The ID of the common event that runs when the player stops fishing (runs
# instead of showing the reeling in animation).
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).
SAFARI_STEPS = 600
# The number of seconds a Bug Catching Contest lasts for (0=infinite).
BUG_CONTEST_TIME = 20 * 60 # 20 minutes
#=============================================================================
# If a move taught by a TM/HM/TR replaces another move, this setting is
# 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 Move Relearner can also teach egg moves that the Pokémon knew
# when it hatched and moves that the Pokémon was once taught by a TR. Moves
# 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],
@@ -72,48 +146,6 @@ module Settings
#=============================================================================
# Whether outdoor maps should be shaded according to the time of day.
TIME_SHADING = true
#=============================================================================
# Whether poisoned Pokémon will lose HP while walking around in the field.
POISON_IN_FIELD = (MECHANICS_GENERATION <= 4)
# Whether poisoned Pokémon will faint while walking around in the field
# (true), or survive the poisoning with 1 HP (false).
POISON_FAINT_IN_FIELD = (MECHANICS_GENERATION <= 3)
# Whether planted berries grow according to Gen 4 mechanics (true) or Gen 3
# mechanics (false).
NEW_BERRY_PLANTS = (MECHANICS_GENERATION >= 4)
# Whether fishing automatically hooks the Pokémon (true), or whether there is
# a reaction test first (false).
FISHING_AUTO_HOOK = false
# The ID of the common event that runs when the player starts fishing (runs
# instead of showing the casting animation).
FISHING_BEGIN_COMMON_EVENT = -1
# The ID of the common event that runs when the player stops fishing (runs
# instead of showing the reeling in animation).
FISHING_END_COMMON_EVENT = -1
#=============================================================================
# The number of steps allowed before a Safari Zone game is over (0=infinite).
SAFARI_STEPS = 600
# The number of seconds a Bug Catching Contest lasts for (0=infinite).
BUG_CONTEST_TIME = 20 * 60 # 20 minutes
#=============================================================================
# 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 = []
#=============================================================================
# Whether you need at least a certain number of badges to use some hidden
# moves in the field (true), or whether you need one specific badge to use
# them (false). The amounts/specific badges are defined below.
@@ -135,34 +167,9 @@ module Settings
#=============================================================================
# If a move taught by a TM/HM/TR replaces another move, this setting is
# 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 ("").
# The names of each pocket of the Bag.
def self.bag_pocket_names
return ["",
return [
_INTL("Items"),
_INTL("Medicine"),
_INTL("Poké Balls"),
@@ -173,14 +180,20 @@ module Settings
_INTL("Key Items")
]
end
# The maximum number of slots per pocket (-1 means infinite number). Ignore
# the first number (0).
BAG_MAX_POCKET_SIZE = [0, -1, -1, -1, -1, -1, -1, -1, -1]
# The maximum number of slots per pocket (-1 means infinite number).
BAG_MAX_POCKET_SIZE = [-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.
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).
USE_CURRENT_REGION_DEX = false
# 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
# onto the end of this array (remember that you don't need to use it). This
# array's order is also the order of $Trainer.pokedex.unlocked_dexes, which
# records which Dexes have been unlocked (the first is unlocked by default).
# If an entry is just a name, then the region map shown in the Area page while
# viewing that Dex list will be the region map of the region the player is
# currently in. The National Dex entry should always behave like 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
# Dex list, no matter which region the player is currently in.
# file "regional_dexes.txt". The last name is for the National Dex and is
# added onto the end of this array (remember that you don't need to use it).
# This array's order is also the order of $player.pokedex.unlocked_dexes,
# which records which Dexes have been unlocked (the first is unlocked by
# default). If an entry is just a name, then the region map shown in the Area
# page while viewing that Dex list will be the region map of the region the
# player is currently in. The National Dex entry should always behave like
# this. If an entry is of the form [name, number], then the number is a region
# number, and that region's map will appear in the Area page while viewing
# that Dex list, no matter which region the player is currently in.
def self.pokedex_names
return [
[_INTL("Kanto Pokédex"), 0],
@@ -231,6 +244,20 @@ module Settings
[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
@@ -297,6 +324,10 @@ module Settings
# The Game Switch which, while ON, makes all Pokémon created considered to be
# met via a fateful encounter.
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
# file in the Data folder. Edit only if you have 2 or more languages to choose
# from.
@@ -393,6 +433,6 @@ end
# DO NOT EDIT THESE!
module Essentials
VERSION = "19.1.dev"
VERSION = "20"
ERROR_TEXT = ""
end

View File

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

View File

@@ -1,26 +1,23 @@
# To use the console, use the executable explicitly built
# with the console enabled on Windows. On Linux and macOS,
# just launch the executable directly from a terminal.
# To use the console, use the executable explicitly built with the console
# enabled on Windows. On Linux and macOS, just launch the executable directly
# from a terminal.
module Console
def self.setup_console
return unless $DEBUG
echoln "GPU Cache Max: #{Bitmap.max_size}"
echoln "--------------------------------"
echoln "-------------------------------------------------------------------------------"
echoln "#{System.game_title} Output Window"
echoln "--------------------------------"
echoln "If you are seeing this window, you are running"
echoln "#{System.game_title} in Debug Mode. This means"
echoln "that you're either playing a Debug Version, or"
echoln "you are playing from within RPG Maker XP."
echoln "-------------------------------------------------------------------------------"
echoln "If you can see this window, you are running the game in Debug Mode. This means"
echoln "that you're either playing a debug version of the game, or you're playing from"
echoln "within RPG Maker XP."
echoln ""
echoln "Closing this window will close the game. If"
echoln "you want to get rid of this window, run the"
echoln "program from the Shell, or download a Release"
echoln "version."
echoln "Closing this window will close the game. If you want to get rid of this window,"
echoln "run the program from the Shell, or download a release version of the game."
echoln ""
echoln "--------------------------------"
echoln "-------------------------------------------------------------------------------"
echoln "Debug Output:"
echoln "--------------------------------"
echoln "-------------------------------------------------------------------------------"
echoln ""
end
@@ -44,9 +41,187 @@ module Kernel
end
def echoln(string)
echo(string)
echo("\r\n")
echo string
echo "\r\n"
end
end
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
end
def pbGetExceptionMessage(e,_script="")
class EventScriptError < Exception
attr_accessor :event_message
def initialize(message)
super(nil)
@event_message = message
end
end
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.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."
elsif e.is_a?(Errno::ENOENT)
when Errno::ENOENT
filename = emessage.sub("No such file or directory - ", "")
emessage = "File #{filename} not found."
end
@@ -18,27 +29,26 @@ def pbGetExceptionMessage(e,_script="")
end
def pbPrintException(e)
emessage = ""
if $EVENTHANGUPMSG && $EVENTHANGUPMSG!=""
emessage = $EVENTHANGUPMSG # Message with map/event ID generated elsewhere
$EVENTHANGUPMSG = nil
else
emessage = pbGetExceptionMessage(e)
end
emessage = pbGetExceptionMessage(e)
# begin message formatting
message = "[Pokémon Essentials version #{Essentials::VERSION}]\r\n"
message += "#{Essentials::ERROR_TEXT}\r\n" # For third party scripts to add to
message += "Exception: #{e.class}\r\n"
message += "Message: #{emessage}\r\n"
# show last 10/25 lines of backtrace
message += "\r\nBacktrace:\r\n"
btrace = ""
if e.backtrace
maxlength = ($INTERNAL) ? 25 : 10
e.backtrace[0, maxlength].each { |i| btrace += "#{i}\r\n" }
if !e.is_a?(EventScriptError)
message += "Exception: #{e.class}\r\n"
message += "Message: "
end
message += emessage
# show last 10/25 lines of backtrace
if !e.is_a?(EventScriptError)
message += "\r\n\r\nBacktrace:\r\n"
backtrace_text = ""
if e.backtrace
maxlength = ($INTERNAL) ? 25 : 10
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
btrace.gsub!(/Section(\d+)/) { $RGSS_SCRIPTS[$1.to_i][1] } rescue nil
message += btrace
# output to log
errorlog = "errorlog.txt"
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.")
# Give a ~500ms coyote time to start holding Control
t = System.delta
until (System.delta - t) >= 500000
until (System.delta - t) >= 500_000
Input.update
if Input.press?(Input::CTRL)
Input.clipboard = message

View File

@@ -1,7 +1,7 @@
# The Kernel module is extended to include the validate method.
module Kernel
private
# Used to check whether method arguments are of a given class or respond to a method.
# @param value_pairs [Hash{Object => Class, Array<Class>, Symbol}] value pairs to validate
# @example Validate a class or method

View File

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

View File

@@ -1,18 +1,29 @@
# 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
Font.default_shadow = false if Font.respond_to?(:default_shadow)
Graphics.frame_rate = 40
Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::UTF_8
def pbSetWindowText(string)
System.set_window_title(string || System.game_title)
end
class Bitmap
attr_accessor :text_offset_y
alias mkxp_draw_text draw_text unless method_defined?(:mkxp_draw_text)
def draw_text(x, y, width, height, text, align = 0)
height = text_size(text).height
mkxp_draw_text(x, y, width, height, text, align)
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
mkxp_draw_text(x, y, width, height, text, align)
end
end
end

View File

@@ -9,8 +9,8 @@ class Dir
files = []
filters = [filters] if !filters.is_a?(Array)
self.chdir(dir) do
for filter in filters
self.glob(filter){ |f| files.push(full ? (dir + "/" + f) : f) }
filters.each do |filter|
self.glob(filter) { |f| files.push(full ? (dir + "/" + f) : f) }
end
end
return files.sort
@@ -22,7 +22,7 @@ class Dir
# sets variables for starting
files = []
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
if self.safe?(file) # Is a directory
subfolders += self.all(file, filters, full)
@@ -43,6 +43,42 @@ class Dir
return ret
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
@@ -56,7 +92,15 @@ class File
#-----------------------------------------------------------------------------
def self.safe?(file)
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
end
#-----------------------------------------------------------------------------
@@ -79,7 +123,7 @@ def safeExists?(f)
return FileTest.exist?(f) if f[/\A[\x20-\x7E]*\z/]
ret = false
begin
File.open(f,"rb") { ret = true }
File.open(f, "rb") { ret = true }
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES
ret = false
end
@@ -89,13 +133,13 @@ end
# Similar to "Dir.glob", but designed to work around a problem with accessing
# files if a path contains accent marks.
# "dir" is the directory path, "wildcard" is the filename pattern to match.
def safeGlob(dir,wildcard)
def safeGlob(dir, wildcard)
ret = []
afterChdir = false
begin
Dir.chdir(dir) {
afterChdir = true
Dir.glob(wildcard) { |f| ret.push(dir+"/"+f) }
Dir.glob(wildcard) { |f| ret.push(dir + "/" + f) }
}
rescue Errno::ENOENT
raise if afterChdir
@@ -108,8 +152,8 @@ end
def pbResolveAudioSE(file)
return nil if !file
if RTP.exists?("Audio/SE/"+file,["",".wav",".mp3",".ogg"])
return RTP.getPath("Audio/SE/"+file,["",".wav",".mp3",".ogg"])
if RTP.exists?("Audio/SE/" + file, ["", ".wav", ".ogg"]) # ".mp3"
return RTP.getPath("Audio/SE/" + file, ["", ".wav", ".ogg"]) # ".mp3"
end
return nil
end
@@ -118,18 +162,18 @@ end
# archives. Returns nil if the path can't be found.
def pbResolveBitmap(x)
return nil if !x
noext = x.gsub(/\.(bmp|png|gif|jpg|jpeg)$/,"")
noext = x.gsub(/\.(bmp|png|gif|jpg|jpeg)$/, "")
filename = nil
# RTP.eachPathFor(x) { |path|
# filename = pbTryString(path) if !filename
# filename = pbTryString(path+".gif") if !filename
# filename = pbTryString(path + ".gif") if !filename
# }
RTP.eachPathFor(noext) { |path|
filename = pbTryString(path+".png") if !filename
filename = pbTryString(path+".gif") if !filename
# filename = pbTryString(path+".jpg") if !filename
# filename = pbTryString(path+".jpeg") if !filename
# filename = pbTryString(path+".bmp") if !filename
filename = pbTryString(path + ".png") if !filename
filename = pbTryString(path + ".gif") if !filename
# filename = pbTryString(path + ".jpg") if !filename
# filename = pbTryString(path + ".jpeg") if !filename
# filename = pbTryString(path + ".bmp") if !filename
}
return filename
end
@@ -157,7 +201,7 @@ def canonicalize(c)
pos = -1
ret = []
retstr = ""
for x in csplit
csplit.each do |x|
if x == ".."
if pos >= 0
ret.delete_at(pos)
@@ -168,7 +212,7 @@ def canonicalize(c)
pos += 1
end
end
for i in 0...ret.length
ret.length.times do |i|
retstr += "/" if i > 0
retstr += ret[i]
end
@@ -180,31 +224,31 @@ end
module RTP
@rtpPaths = nil
def self.exists?(filename,extensions=[])
def self.exists?(filename, extensions = [])
return false if nil_or_empty?(filename)
eachPathFor(filename) { |path|
return true if safeExists?(path)
for ext in extensions
return true if safeExists?(path+ext)
extensions.each do |ext|
return true if safeExists?(path + ext)
end
}
return false
end
def self.getImagePath(filename)
return self.getPath(filename,["",".png",".gif"]) # ".jpg", ".jpeg", ".bmp"
return self.getPath(filename, ["", ".png", ".gif"]) # ".jpg", ".jpeg", ".bmp"
end
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
def self.getPath(filename,extensions=[])
def self.getPath(filename, extensions = [])
return filename if nil_or_empty?(filename)
eachPathFor(filename) { |path|
return path if safeExists?(path)
for ext in extensions
file = path+ext
extensions.each do |ext|
file = path + ext
return file if safeExists?(file)
end
}
@@ -220,10 +264,10 @@ module RTP
else
# relative path
RTP.eachPath { |path|
if path=="./"
if path == "./"
yield filename
else
yield path+filename
yield path + filename
end
}
end
@@ -237,11 +281,9 @@ module RTP
def self.eachPath
# XXX: Use "." instead of Dir.pwd because of problems retrieving files if
# the current directory contains an accent mark
yield ".".gsub(/[\/\\]/,"/").gsub(/[\/\\]$/,"")+"/"
yield ".".gsub(/[\/\\]/, "/").gsub(/[\/\\]$/, "") + "/"
end
private
def self.getSaveFileName(fileName)
File.join(getSaveFolder, fileName)
end
@@ -260,15 +302,15 @@ end
module FileTest
Image_ext = ['.png', '.gif'] # '.jpg', '.jpeg', '.bmp',
Audio_ext = ['.mp3', '.mid', '.midi', '.ogg', '.wav', '.wma']
IMAGE_EXTENSIONS = [".png", ".gif"] # ".jpg", ".jpeg", ".bmp",
AUDIO_EXTENSIONS = [".mid", ".midi", ".ogg", ".wav", ".wma"] # ".mp3"
def self.audio_exist?(filename)
return RTP.exists?(filename,Audio_ext)
return RTP.exists?(filename, AUDIO_EXTENSIONS)
end
def self.image_exist?(filename)
return RTP.exists?(filename,Image_ext)
return RTP.exists?(filename, IMAGE_EXTENSIONS)
end
end
@@ -277,11 +319,11 @@ end
# Used to determine whether a data file exists (rather than a graphics or
# 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
def pbRgssExists?(filename)
if safeExists?("./Game.rgssad")
return pbGetFileChar(filename)!=nil
return pbGetFileChar(filename) != nil
else
filename = canonicalize(filename)
return safeExists?(filename)
@@ -291,16 +333,16 @@ end
# Opens an IO, even if the file is in an encrypted archive.
# 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
def pbRgssOpen(file,mode=nil)
#File.open("debug.txt","ab") { |fw| fw.write([file,mode,Time.now.to_f].inspect+"\r\n") }
def pbRgssOpen(file, mode = nil)
# File.open("debug.txt","ab") { |fw| fw.write([file,mode,Time.now.to_f].inspect+"\r\n") }
if !safeExists?("./Game.rgssad")
if block_given?
File.open(file,mode) { |f| yield f }
File.open(file, mode) { |f| yield f }
return nil
else
return File.open(file,mode)
return File.open(file, mode)
end
end
file = canonicalize(file)
@@ -320,7 +362,7 @@ def pbGetFileChar(file)
canon_file = canonicalize(file)
if !safeExists?("./Game.rgssad")
return nil if !safeExists?(canon_file)
return nil if file.last == '/' # Is a directory
return nil if file.last == "/" # Is a directory
begin
File.open(canon_file, "rb") { |f| return f.read(1) } # read one byte
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES, Errno::EISDIR
@@ -338,20 +380,20 @@ end
def pbTryString(x)
ret = pbGetFileChar(x)
return (ret!=nil && ret!="") ? x : nil
return nil_or_empty?(ret) ? nil : x
end
# Gets the contents of a file. Doesn't check RTP, but does check
# 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
def pbGetFileString(file)
file = canonicalize(file)
if !safeExists?("./Game.rgssad")
return nil if !safeExists?(file)
begin
File.open(file,"rb") { |f| return f.read } # read all data
File.open(file, "rb") { |f| return f.read } # read all data
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES
return nil
end
@@ -374,13 +416,13 @@ class StringInput
include Enumerable
class << self
def new( str )
def new(str)
if block_given?
begin
f = super
yield f
ensure
f.close if f
f&.close
end
else
super
@@ -389,21 +431,21 @@ class StringInput
alias open new
end
def initialize( str )
def initialize(str)
@string = str
@pos = 0
@closed = false
@lineno = 0
end
attr_reader :lineno,:string
attr_reader :lineno, :string
def inspect
return "#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@string[0,30].inspect}>"
return "#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@string[0, 30].inspect}>"
end
def close
raise IOError, 'closed stream' if @closed
raise IOError, "closed stream" if @closed
@pos = nil
@closed = true
end
@@ -411,7 +453,7 @@ class StringInput
def closed?; @closed; end
def pos
raise IOError, 'closed stream' if @closed
raise IOError, "closed stream" if @closed
[@pos, @string.size].min
end
@@ -421,8 +463,8 @@ class StringInput
def pos=(value); seek(value); end
def seek(offset, whence=IO::SEEK_SET)
raise IOError, 'closed stream' if @closed
def seek(offset, whence = IO::SEEK_SET)
raise IOError, "closed stream" if @closed
case whence
when IO::SEEK_SET then @pos = offset
when IO::SEEK_CUR then @pos += offset
@@ -436,12 +478,12 @@ class StringInput
end
def eof?
raise IOError, 'closed stream' if @closed
raise IOError, "closed stream" if @closed
@pos > @string.size
end
def each( &block )
raise IOError, 'closed stream' if @closed
def each(&block)
raise IOError, "closed stream" if @closed
begin
@string.each(&block)
ensure
@@ -450,14 +492,15 @@ class StringInput
end
def gets
raise IOError, 'closed stream' if @closed
if idx = @string.index(?\n, @pos)
raise IOError, "closed stream" if @closed
idx = @string.index("\n", @pos)
if idx
idx += 1 # "\n".size
line = @string[ @pos ... idx ]
line = @string[@pos...idx]
@pos = idx
@pos += 1 if @pos == @string.size
else
line = @string[ @pos .. -1 ]
line = @string[@pos..-1]
@pos = @string.size + 1
end
@lineno += 1
@@ -465,18 +508,18 @@ class StringInput
end
def getc
raise IOError, 'closed stream' if @closed
raise IOError, "closed stream" if @closed
ch = @string[@pos]
@pos += 1
@pos += 1 if @pos == @string.size
ch
end
def read( len = nil )
raise IOError, 'closed stream' if @closed
def read(len = nil)
raise IOError, "closed stream" if @closed
if !len
return nil if eof?
rest = @string[@pos ... @string.size]
rest = @string[@pos...@string.size]
@pos = @string.size + 1
return rest
end
@@ -485,8 +528,6 @@ class StringInput
@pos += 1 if @pos == @string.size
str
end
def read_all; read(); end
alias read_all read
alias sysread read
end

View File

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

View File

@@ -3,19 +3,19 @@
# HTTP utility functions
#
#############################
def pbPostData(url, postdata, filename=nil, depth=0)
def pbPostData(url, postdata, filename = nil, depth = 0)
if url[/^http:\/\/([^\/]+)(.*)$/]
host = $1
path = $2
path = "/" if path.length==0
# path = $2
# 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"
body = postdata.map { |key, value|
keyString = key.to_s
valueString = value.to_s
keyString.gsub!(/[^a-zA-Z0-9_\.\-]/n) { |s| sprintf('%%%02x', s[0]) }
valueString.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]) }
next "#{keyString}=#{valueString}"
}.join('&')
}.join("&")
ret = HTTPLite.post_body(
url,
body,
@@ -31,7 +31,7 @@ def pbPostData(url, postdata, filename=nil, depth=0)
return ret if !ret.is_a?(Hash)
return "" if ret[:status] != 200
return ret[:body] if !filename
File.open(filename, "wb"){|f|f.write(ret[:body])}
File.open(filename, "wb") { |f| f.write(ret[:body]) }
return ""
end
return ""
@@ -63,7 +63,7 @@ end
def pbDownloadToFile(url, file)
begin
pbDownloadData(url,file)
pbDownloadData(url, file)
rescue
end
end
@@ -79,7 +79,7 @@ end
def pbPostToFile(url, postdata, file)
begin
pbPostData(url, postdata,file)
pbPostData(url, postdata, file)
rescue
end
end

View File

@@ -2,7 +2,7 @@
# class Object
#===============================================================================
class Object
alias full_inspect inspect
alias full_inspect inspect unless method_defined?(:full_inspect)
def inspect
return "#<#{self.class}>"
@@ -23,32 +23,21 @@ end
#===============================================================================
class String
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
def first(n = 1)
return self[0...n]
end
def first(n = 1); return self[0...n]; end
def last(n = 1)
return self[-n..-1] || self
end
def last(n = 1); return self[-n..-1] || self; end
def blank?
blank = true
s = self.scan(/./)
for l in s
blank = false if l != ""
end
return blank
end
def blank?; return self.strip.empty?; end
def cut(bitmap, width)
string = self
width -= bitmap.text_size("...").width
string_width = 0
text = []
for char in string.scan(/./)
string.scan(/./).each do |char|
wdh = bitmap.text_size(char).width
next if (wdh + string_width) > width
string_width += wdh
@@ -56,11 +45,15 @@ class String
end
text.push("...") if text.length < string.length
new_string = ""
for char in text
text.each do |char|
new_string += char
end
return new_string
end
def numeric?
return !self[/^[+-]?([0-9]+)(?:\.[0-9]+)?$/].nil?
end
end
#===============================================================================
@@ -89,7 +82,7 @@ end
#===============================================================================
class Array
def ^(other) # xor of two arrays
return (self|other) - (self&other)
return (self | other) - (self & other)
end
def swap(val1, val2)
@@ -100,6 +93,29 @@ class Array
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
#===============================================================================
@@ -111,6 +127,144 @@ module Enumerable
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
#===============================================================================

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
#==============================================================================#
# Plugin Manager #
# by Marin #
# support for external plugin scripts by Luka S.J. #
# tweaked by Maruno #
# Support for external plugin scripts by Luka S.J. #
# Tweaked by Maruno #
#------------------------------------------------------------------------------#
# Provides a simple interface that allows plugins to require dependencies #
# at specific versions, and to specify incompatibilities between plugins. #
@@ -12,152 +12,92 @@
#------------------------------------------------------------------------------#
# Usage: #
# #
# A Pokémon Essentials plugin should register itself using the PluginManager. #
# The simplest way to do so, for a plugin without dependencies, is as follows: #
# Each plugin should have its own folder in the "Plugins" folder found in the #
# 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. #
# #
# PluginManager.register({ #
# :name => "Basic Plugin", #
# :version => "1.0", #
# :link => "https://reliccastle.com/link-to-the-plugin/", #
# :credits => "Marin" #
# }) #
# 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. #
# #
# The link portion here is optional, but recommended. This will be shown in #
# the error message if the PluginManager detects that this plugin needs to be #
# updated. #
# Required lines: #
# #
# A plugin's version should be in the format X.Y.Z, but the number of digits #
# 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. #
# 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 #
# #
# 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: #
# 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. #
# #
# :credits => "Marin" #
# :credits => ["Marin", "Maruno"], #
# 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. #
# #
# Dependency: #
# 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. #
# #
# 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({ #
# :name => "Simple Extension", #
# :version => "1.0", #
# :link => "https://reliccastle.com/link-to-the-plugin/", #
# :credits => ["Marin", "Maruno"], #
# :dependencies => ["Basic Plugin"] #
# }) #
# #
# If there are multiple dependencies, they should be listed in an array. If #
# there is only one dependency, it does not need an array: #
# #
# :dependencies => "Basic Plugin" #
# #
# 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" #
# ] #
# }) #
# 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. #
# #
#------------------------------------------------------------------------------#
# Plugin folder: #
# The code behind plugins: #
# #
# 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. #
# 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: #
# #
# 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. #
# PluginManager.register({ #
# :name => "Basic Plugin", #
# :version => "1.0", #
# :essentials => "20", #
# :link => "https://reliccastle.com/link-to-the-plugin/", #
# :credits => ["Marin"] #
# }) #
# #
# 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. #
# The :link value is optional, but recommended. This will be shown in the #
# message if the PluginManager detects that this plugin needs to be updated. #
# #
# 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). #
# Here is the same example but also with dependencies and conflicts: #
# #
# The contents of meta.txt are as follows: #
# PluginManager.register({ #
# :name => "Basic Plugin", #
# :version => "1.0", #
# :essentials => "20", #
# :link => "https://reliccastle.com/link-to-the-plugin/", #
# :credits => ["Marin"], #
# :dependencies => ["Basic Plugin", #
# ["Useful Utils", "1.1"], #
# [:exact, "Scene Tweaks", "2"], #
# [:optional, "Extended Windows", "1.2"], #
# ], #
# :incompatibilities => ["Simple Extension"] #
# }) #
# #
# 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. #
# The example dependencies/conflict are the same as the examples shown above #
# 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 #
# "meta.txt". #
# #
#------------------------------------------------------------------------------#
# Please give credit when using this. #
@@ -172,21 +112,20 @@ module PluginManager
def self.register(options)
name = nil
version = nil
essentials = nil
link = nil
dependencies = nil
incompats = nil
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,
# by sorting the keys
keys = options.keys.sort do |a, b|
idx_a = order.index(a)
idx_a = order.size if idx_a == -1
idx_b = order.index(b)
idx_b = order.size if idx_b == -1
idx_a = order.index(a) || order.size
idx_b = order.index(b) || order.size
next idx_a <=> idx_b
end
for key in keys
keys.each do |key|
value = options[key]
case key
when :name # Plugin name
@@ -202,6 +141,8 @@ module PluginManager
self.error("Plugin version must be a string.")
end
version = value
when :essentials
essentials = value
when :link # Plugin website
if nil_or_empty?(value)
self.error("Plugin link must be a non-empty string.")
@@ -210,12 +151,13 @@ module PluginManager
when :dependencies # Plugin dependencies
dependencies = value
dependencies = [dependencies] if !dependencies.is_a?(Array) || !dependencies[0].is_a?(Array)
for dep in value
if dep.is_a?(String) # "plugin name"
value.each do |dep|
case dep
when String # "plugin name"
if !self.installed?(dep)
self.error("Plugin '#{name}' requires plugin '#{dep}' to be installed above it.")
end
elsif dep.is_a?(Array)
when Array
case dep.size
when 1 # ["plugin name"]
if dep[0].is_a?(String)
@@ -236,7 +178,8 @@ module PluginManager
if self.installed?(dep_name) # Have plugin but lower version
msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} or higher, " +
"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}'."
end
self.error(msg)
@@ -278,7 +221,8 @@ module PluginManager
msg = "Plugin '#{name}' requires plugin '#{dep_name}', if installed, to be version #{dep_version}"
msg << " or higher" if !exact
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}'."
end
self.error(msg)
@@ -288,16 +232,16 @@ module PluginManager
msg = "Plugin '#{name}' requires plugin '#{dep_name}' to be version #{dep_version}"
msg << " or later" if !exact
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}'."
end
self.error(msg)
else # Don't have plugin
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."
self.error(msg)
end
self.error(msg)
end
end
end
@@ -305,7 +249,7 @@ module PluginManager
when :incompatibilities # Plugin incompatibilities
incompats = value
incompats = [incompats] if !incompats.is_a?(Array)
for incompat in incompats
incompats.each do |incompat|
if self.installed?(incompat)
self.error("Plugin '#{name}' is incompatible with '#{incompat}'. " +
"They cannot both be used at the same time.")
@@ -314,11 +258,11 @@ module PluginManager
when :credits # Plugin credits
value = [value] if value.is_a?(String)
if value.is_a?(Array)
for entry in value
if !entry.is_a?(String)
self.error("Plugin '#{name}'s credits array contains a non-string value.")
else
value.each do |entry|
if entry.is_a?(String)
credits << entry
else
self.error("Plugin '#{name}'s credits array contains a non-string value.")
end
end
else
@@ -328,8 +272,8 @@ module PluginManager
self.error("Invalid plugin registry key '#{key}'.")
end
end
for plugin in @@Plugins.values
if plugin[:incompatibilities] && plugin[:incompatibilities].include?(name)
@@Plugins.each_value do |plugin|
if plugin[:incompatibilities]&.include?(name)
self.error("Plugin '#{plugin[:name]}' is incompatible with '#{name}'. " +
"They cannot both be used at the same time.")
end
@@ -338,6 +282,7 @@ module PluginManager
@@Plugins[name] = {
:name => name,
:version => version,
:essentials => essentials,
:link => link,
:dependencies => dependencies,
:incompatibilities => incompats,
@@ -350,8 +295,8 @@ module PluginManager
def self.error(msg)
Graphics.update
t = Thread.new do
echoln "Plugin Error:\r\n#{msg}"
p "Plugin Error: #{msg}"
Console.echo_error "Plugin Error:\r\n#{msg}"
print("Plugin Error:\r\n#{msg}")
Thread.exit
end
while t.status
@@ -408,21 +353,25 @@ module PluginManager
# -1 if v1 is lower than v2
#-----------------------------------------------------------------------------
def self.compare_versions(v1, v2)
d1 = v1.split("")
d1.insert(0, "0") if d1[0] == "." # Turn ".123" into "0.123"
while d1[-1] == "."; d1 = d1[0..-2]; end # Turn "123." into "123"
d2 = v2.split("")
d2.insert(0, "0") if d2[0] == "." # Turn ".123" into "0.123"
while d2[-1] == "."; d2 = d2[0..-2]; end # Turn "123." into "123"
for i in 0...[d1.size, d2.size].max # Compare each digit in turn
d1 = v1.chars
d1.insert(0, "0") if d1[0] == "." # Turn ".123" into "0.123"
while d1[-1] == "." # Turn "123." into "123"
d1 = d1[0..-2]
end
d2 = v2.chars
d2.insert(0, "0") if d2[0] == "." # Turn ".123" into "0.123"
while d2[-1] == "." # Turn "123." into "123"
d2 = d2[0..-2]
end
[d1.size, d2.size].max.times do |i| # Compare each digit in turn
c1 = d1[i]
c2 = d2[i]
if c1
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)
else
return -1 if c2
elsif c2
return -1
end
end
return 0
@@ -431,25 +380,17 @@ module PluginManager
# formats the error message
#-----------------------------------------------------------------------------
def self.pluginErrorMsg(name, script)
e = $!
# 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 += "Error in Plugin [#{name}]:\r\n"
message += "#{$!.class} occurred.\r\n"
# go through message content
for line in $!.message.split("\r\n")
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
message += "Error in Plugin: [#{name}]\r\n"
message += "Exception: #{e.class}\r\n"
message += "Message: "
message += e.message
# show last 10 lines of backtrace
message += "\r\nBacktrace:\r\n"
$!.backtrace[0, 10].each { |i| message += "#{i}\r\n" }
message += "\r\n\r\nBacktrace:\r\n"
e.backtrace[0, 10].each { |i| message += "#{i}\r\n" }
# output to log
errorlog = "errorlog.txt"
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.")
# Give a ~500ms coyote time to start holding Control
t = System.delta
until (System.delta - t) >= 500000
until (System.delta - t) >= 500_000
Input.update
if Input.press?(Input::CTRL)
Input.clipboard = message
@@ -487,11 +428,14 @@ module PluginManager
raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}", FileLineData.linereport)
end
property = $~[1].upcase
data = $~[2].split(',')
data = $~[2].split(",")
data.each_with_index { |value, i| data[i] = value.strip }
# begin formatting data hash
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]
if data.length < 2 # No version given, just push name of plugin dependency
meta[:dependencies].push(data[0])
@@ -501,23 +445,23 @@ module PluginManager
else # Push dependency type, name and version of plugin dependency
meta[:dependencies].push([data[2].downcase.to_sym, data[0], data[1]])
end
when 'EXACT'
when "EXACT"
next if data.length < 2 # Exact dependencies must have a version given; ignore if not
meta[:dependencies] = [] if !meta[:dependencies]
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
meta[:dependencies] = [] if !meta[:dependencies]
meta[:dependencies].push([:optional, data[0], data[1]])
when 'CONFLICTS'
when "CONFLICTS"
meta[:incompatibilities] = [] if !meta[:incompatibilities]
data.each { |value| meta[:incompatibilities].push(value) if value && !value.empty? }
when 'SCRIPTS'
when "SCRIPTS"
meta[:scripts] = [] if !meta[:scripts]
data.each { |scr| meta[:scripts].push(scr) }
when 'CREDITS'
when "CREDITS"
meta[:credits] = data
when 'LINK', 'WEBSITE'
when "LINK", "WEBSITE"
meta[:link] = data[0]
else
meta[property.downcase.to_sym] = data[0]
@@ -527,7 +471,7 @@ module PluginManager
# be loaded (files listed in the meta file are loaded first)
meta[:scripts] = [] if !meta[:scripts]
# get all script files from plugin Dir
for fl in Dir.all(dir)
Dir.all(dir).each do |fl|
next if !fl.include?(".rb")
meta[:scripts].push(fl.gsub("#{dir}/", ""))
end
@@ -555,7 +499,7 @@ module PluginManager
return nil if !meta[name] || !meta[name][:dependencies]
og = [name] if !og
# go through all dependencies
for dname in meta[name][:dependencies]
meta[name][:dependencies].each do |dname|
# clean the name to a simple string
dname = dname[0] if dname.is_a?(Array) && dname.length == 2
dname = dname[1] if dname.is_a?(Array) && dname.length == 3
@@ -572,14 +516,14 @@ module PluginManager
#-----------------------------------------------------------------------------
def self.sortLoadOrder(order, plugins)
# go through the load order
for o in order
order.each do |o|
next if !plugins[o] || !plugins[o][:dependencies]
# go through all dependencies
for dname in plugins[o][:dependencies]
plugins[o][:dependencies].each do |dname|
optional = false
# clean the name to a simple string
if dname.is_a?(Array)
optional = [:optional,:optional_exact].include?(dname[0])
optional = [:optional, :optional_exact].include?(dname[0])
dname = dname[dname.length - 2]
end
# catch missing dependency
@@ -604,7 +548,7 @@ module PluginManager
order = []
# Find all plugin folders that have a meta.txt and add them to the list of
# plugins.
for dir in self.listAll
self.listAll.each do |dir|
# skip if there is no meta file
next if !safeExists?(dir + "/meta.txt")
ndx = order.length
@@ -632,14 +576,14 @@ module PluginManager
return false if !$DEBUG || safeExists?("Game.rgssad")
return true if !safeExists?("Data/PluginScripts.rxdata")
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
mtime = File.mtime("Data/PluginScripts.rxdata")
for o in order
order.each do |o|
# go through all the registered plugin scripts
scr = plugins[o][:scripts]
dir = plugins[o][:dir]
for sc in scr
scr.each do |sc|
return true if File.mtime("#{dir}/#{sc}") > mtime
end
return true if File.mtime("#{dir}/meta.txt") > mtime
@@ -650,18 +594,18 @@ module PluginManager
# Check if plugins need compiling
#-----------------------------------------------------------------------------
def self.compilePlugins(order, plugins)
echo 'Compiling plugin scripts...'
Console.echo_li "Compiling plugin scripts..."
scripts = []
# go through the entire order one by one
for o in order
order.each do |o|
# save name, metadata and scripts array
meta = plugins[o].clone
meta.delete(:scripts)
meta.delete(:dir)
dat = [o, meta, []]
# iterate through each file to deflate
for file in plugins[o][:scripts]
File.open("#{plugins[o][:dir]}/#{file}", 'rb') do |f|
plugins[o][:scripts].each do |file|
File.open("#{plugins[o][:dir]}/#{file}", "rb") do |f|
dat[2].push([file, Zlib::Deflate.deflate(f.read)])
end
end
@@ -669,16 +613,17 @@ module PluginManager
scripts.push(dat)
end
# 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
GC.start
echoln ' done.'
echoln ''
Console.echo_done(true)
echoln "" if scripts.length == 0
end
#-----------------------------------------------------------------------------
# Check if plugins need compiling
#-----------------------------------------------------------------------------
def self.runPlugins
Console.echo_h1 "Checking plugins"
# get the order of plugins to interpret
order, plugins = self.getPluginOrder
# compile if necessary
@@ -686,24 +631,27 @@ module PluginManager
# load plugins
scripts = load_data("Data/PluginScripts.rxdata")
echoed_plugins = []
for plugin in scripts
scripts.each do |plugin|
# get the required data
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
self.register(meta)
# go through each script and interpret
for scr in script
script.each do |scr|
# turn code into plaintext
code = Zlib::Inflate.inflate(scr[1]).force_encoding(Encoding::UTF_8)
# get rid of tabs
code.gsub!("\t", " ")
# construct filename
sname = scr[0].gsub("\\","/").split("/")[-1]
sname = scr[0].gsub("\\", "/").split("/")[-1]
fname = "[#{name}] #{sname}"
# try to run the code
begin
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)
rescue Exception # format error message to display
self.pluginErrorMsg(name, sname)
@@ -711,7 +659,27 @@ module PluginManager
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

View File

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

View File

@@ -1,35 +1,54 @@
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.
RECALCULATE_TURN_ORDER_AFTER_MEGA_EVOLUTION = (MECHANICS_GENERATION >= 7)
# Whether turn order is recalculated after a Pokémon's Speed stat changes.
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
# damage and have 5 stages as in Gen 5 (false). Also determines whether
# critical hit rate can be copied by Transform/Psych Up.
NEW_CRITICAL_HIT_RATE_MECHANICS = (MECHANICS_GENERATION >= 6)
#=============================================================================
# Whether several effects apply relating to a Pokémon's type:
# * Electric-type immunity to paralysis
# * Ghost-type immunity to being trapped
# * Grass-type immunity to powder moves and Effect Spore
# * Poison-type Pokémon can't miss when using Toxic
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).
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
# (false).
X_STAT_ITEMS_RAISE_BY_TWO_STAGES = (MECHANICS_GENERATION >= 7)
# Whether some Poké Balls have catch rate multipliers from Gen 7 (true) or
# from earlier generations (false).
NEW_POKE_BALL_CATCH_RATES = (MECHANICS_GENERATION >= 7)
# Whether Soul Dew powers up Psychic and Dragon-type moves by 20% (true) or
# raises the holder's Special Attack and Special Defense by 50% (false).
SOUL_DEW_POWERS_UP_TYPES = (MECHANICS_GENERATION >= 7)
#=============================================================================
# Whether X items (X Attack, etc.) raise their stat by 2 stages (true) or 1
# (false).
X_STAT_ITEMS_RAISE_BY_TWO_STAGES = (MECHANICS_GENERATION >= 7)
# Whether some Poké Balls have catch rate multipliers from Gen 7 (true) or
# from earlier generations (false).
NEW_POKE_BALL_CATCH_RATES = (MECHANICS_GENERATION >= 7)
# Whether Soul Dew powers up Psychic and Dragon-type moves by 20% (true) or
# raises the holder's Special Attack and Special Defense by 50% (false).
SOUL_DEW_POWERS_UP_TYPES = (MECHANICS_GENERATION >= 7)
# 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
#=============================================================================
@@ -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
# Evolving even if they otherwise could.
NO_MEGA_EVOLUTION = 34
@@ -54,22 +70,32 @@ module Settings
# Whether the Exp gained from beating a Pokémon should be scaled depending on
# the gainer's level.
SCALED_EXP_FORMULA = (MECHANICS_GENERATION == 5 || MECHANICS_GENERATION >= 7)
SCALED_EXP_FORMULA = (MECHANICS_GENERATION == 5 || MECHANICS_GENERATION >= 7)
# Whether the Exp gained from beating a Pokémon should be divided equally
# between each participant (true), or whether each participant should gain
# that much Exp (false). This also applies to Exp gained via the Exp Share
# (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
# 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
# fewer species in your game.
ENABLE_CRITICAL_CAPTURES = (MECHANICS_GENERATION >= 5)
ENABLE_CRITICAL_CAPTURES = (MECHANICS_GENERATION >= 5)
# 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
# they lose a battle (they can still gain money from trainers for winning).
NO_MONEY_LOSS = 33
NO_MONEY_LOSS = 33
# Whether party Pokémon check whether they can evolve after all battles
# regardless of the outcome (true), or only after battles the player won (false).
CHECK_EVOLUTION_AFTER_ALL_BATTLES = (MECHANICS_GENERATION >= 6)

View File

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

View File

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

View File

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

View File

@@ -2,11 +2,11 @@
SaveData.register(:player) do
ensure_class :Player
save_value { $Trainer }
load_value { |value| $Trainer = value }
save_value { $player }
load_value { |value| $player = $Trainer = value }
new_game_value {
trainer_type = nil # Get the first defined trainer type as a placeholder
GameData::TrainerType.each { |t| trainer_type = t.id; break }
# Get the first defined trainer type as a placeholder
trainer_type = GameData::TrainerType.keys.first
Player.new("Unnamed", trainer_type)
}
from_old_format { |old_format| old_format[0] }
@@ -72,8 +72,8 @@ end
SaveData.register(:map_factory) do
ensure_class :PokemonMapFactory
save_value { $MapFactory }
load_value { |value| $MapFactory = value }
save_value { $map_factory }
load_value { |value| $map_factory = $MapFactory = value }
from_old_format { |old_format| old_format[9] }
end
@@ -103,8 +103,8 @@ end
SaveData.register(:bag) do
ensure_class :PokemonBag
save_value { $PokemonBag }
load_value { |value| $PokemonBag = value }
save_value { $bag }
load_value { |value| $bag = $PokemonBag = value }
new_game_value { PokemonBag.new }
from_old_format { |old_format| old_format[13] }
end
@@ -121,7 +121,7 @@ SaveData.register(:essentials_version) do
load_in_bootup
ensure_class :String
save_value { Essentials::VERSION }
load_value { |value| $SaveVersion = value }
load_value { |value| $save_engine_version = value }
new_game_value { Essentials::VERSION }
from_old_format { |old_format| old_format[15] }
end
@@ -130,6 +130,14 @@ SaveData.register(:game_version) do
load_in_bootup
ensure_class :String
save_value { Settings::GAME_VERSION }
load_value { |value| $game_version = value }
load_value { |value| $save_game_version = value }
new_game_value { Settings::GAME_VERSION }
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
essentials_version 19
display_title 'Adding game version and Essentials version to save data'
to_all do |save_data|
unless save_data.has_key?(:essentials_version)
save_data[:essentials_version] = Essentials::VERSION
end
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'
# Planted berries accidentally weren't converted in v19 to change their
# numerical IDs to symbolic IDs (for the berry planted and for mulch laid down).
# Since item numerical IDs no longer exist, this conversion needs to have a list
# of them in order to convert planted berry data properly.
SaveData.register_conversion(:v20_fix_planted_berry_numerical_ids) do
essentials_version 20
display_title "Fixing berry plant IDs data"
to_value :global_metadata do |global|
global.bridge ||= 0
global.encounter_version ||= 0
if global.pcItemStorage
global.pcItemStorage.items.each_with_index do |slot, i|
item_data = GameData::Item.try_get(slot[0])
if item_data
slot[0] = item_data.id
else
global.pcItemStorage.items[i] = nil
end
berry_conversion = {
389 => :CHERIBERRY,
390 => :CHESTOBERRY,
391 => :PECHABERRY,
392 => :RAWSTBERRY,
393 => :ASPEARBERRY,
394 => :LEPPABERRY,
395 => :ORANBERRY,
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
global.pcItemStorage.items.compact!
end
if global.mailbox
global.mailbox.each_with_index do |mail, i|
global.mailbox[i] = PokemonMail.convert(mail) if mail
if var[7] && !var[7].is_a?(Symbol) # Mulch
var[7] = mulch_conversion[var[7]]
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
#===============================================================================
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|
if global.eventvars
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
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
#===============================================================================
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(:v19_1_fix_phone_contacts) do
essentials_version 19.1
display_title 'Fixing phone contacts data'
to_value :global_metadata do |global|
global.phoneNumbers.each do |contact|
contact[1] = GameData::TrainerType.get(contact[1]).id if contact && contact.length == 8
end
end
end
#===============================================================================
SaveData.register_conversion(:v19_convert_bag) do
essentials_version 19
display_title 'Converting item IDs in Bag'
SaveData.register_conversion(:v20_rename_bag_variables) do
essentials_version 20
display_title "Renaming Bag variables"
to_value :bag do |bag|
bag.instance_eval do
for pocket in self.pockets
pocket.each_with_index do |item, i|
next if !item || !item[0] || item[0] == 0
item_data = GameData::Item.try_get(item[0])
if item_data
item[0] = item_data.id
else
pocket[i] = nil
end
end
pocket.compact!
if !@lastpocket.nil?
@last_viewed_pocket = @lastpocket
@lastPocket = nil
end
self.registeredIndex # Just to ensure this data exists
self.registeredItems.each_with_index do |item, i|
next if !item
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
if !@choices.nil?
@last_pocket_selections = @choices.clone
@choices = nil
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)
if !@registeredItems.nil?
@registered_items = @registeredItems || []
@registeredItems = nil
end
if !@registeredIndex.nil?
@ready_menu_selection = @registeredIndex || [0, 0, 1]
@registeredIndex = nil
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
#===============================================================================
SaveData.register_conversion(:v20_increment_player_character_id) do
essentials_version 20
display_title "Incrementing player character ID"
to_value :player do |player|
player.character_ID += 1
end
end
#===============================================================================
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
self.unlockedWallpapers # Just to ensure this data exists
end # storage.instance_eval
end # to_value
end
SaveData.register_conversion(:v19_convert_game_player) do
essentials_version 19
display_title 'Converting game player character'
to_value :game_player do |game_player|
game_player.width = 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
SaveData.register_conversion(:v19_convert_game_screen) do
essentials_version 19
display_title 'Converting game screen'
#===============================================================================
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|
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

View File

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

View File

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

View File

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

View File

@@ -126,6 +126,7 @@ class Interpreter
#-----------------------------------------------------------------------------
def command_end
@list = nil
end_follower_overrides
# If main map event and event ID are valid, unlock event
if @main && @event_id > 0 && $game_map.events[@event_id]
$game_map.events[@event_id].unlock
@@ -158,7 +159,7 @@ class Interpreter
return false if $game_temp.message_window_showing
message = @list[@index].parameters[0]
message_end = ""
commands = nil
choices = nil
number_input_variable = nil
number_input_max_digits = nil
# Check the next command(s) for things to add on to this text
@@ -174,8 +175,8 @@ class Interpreter
when 101 # Show Text
message_end = "\1"
when 102 # Show Choices
commands = @list[next_index].parameters
@index = next_index
choices = setup_choices(@list[@index].parameters)
when 103 # Input Number
number_input_variable = @list[next_index].parameters[0]
number_input_max_digits = @list[next_index].parameters[1]
@@ -185,15 +186,11 @@ class Interpreter
end
# Translate the text
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
if commands
cmd_texts = []
for cmd in commands[0]
cmd_texts.push(_MAPINTL($game_map.map_id, cmd))
end
command = pbMessage(message + message_end, cmd_texts, commands[1])
@branch[@list[@index].indent] = command
if choices
command = pbMessage(message + message_end, choices[0], choices[1])
@branch[@list[@index].indent] = choices[2][command] || command
elsif number_input_variable
params = ChooseNumberParams.new
params.setMaxDigits(number_input_max_digits)
@@ -210,17 +207,93 @@ class Interpreter
# * Show Choices
#-----------------------------------------------------------------------------
def command_102
choices = setup_choices(@list[@index].parameters)
@message_waiting = true
command = pbShowCommands(nil, @list[@index].parameters[0], @list[@index].parameters[1])
command = pbShowCommands(nil, choices[0], choices[1])
@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
return true
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 [**]
#-----------------------------------------------------------------------------
def command_402
# @parameters[0] is 0/1/2/3 for Choice 1/2/3/4 respectively
if @branch[@list[@index].indent] == @parameters[0]
@branch.delete(@list[@index].indent)
return true
@@ -231,7 +304,8 @@ class Interpreter
# * When Cancel
#-----------------------------------------------------------------------------
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)
return true
end
@@ -271,7 +345,7 @@ class Interpreter
Input.update
pbUpdateSceneMap
# 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)
end
break if ret != 0
@@ -343,7 +417,7 @@ class Interpreter
character = get_character(@parameters[1])
result = (character.direction == @parameters[2]) if character
when 7 # gold
gold = $Trainer.money
gold = $player.money
result = (@parameters[2] == 0) ? (gold >= @parameters[1]) : (gold <= @parameters[1])
# when 8, 9, 10 # item, weapon, armor
when 11 # button
@@ -413,8 +487,8 @@ class Interpreter
#-----------------------------------------------------------------------------
def command_116
if @event_id > 0
$game_map.events[@event_id].erase if $game_map.events[@event_id]
$PokemonMap.addErasedEvent(@event_id) if $PokemonMap
$game_map.events[@event_id]&.erase
$PokemonMap&.addErasedEvent(@event_id)
end
@index += 1
return false
@@ -459,7 +533,7 @@ class Interpreter
#-----------------------------------------------------------------------------
def command_121
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)
$game_switches[i] = (@parameters[2] == 0)
should_refresh = true
@@ -496,8 +570,8 @@ class Interpreter
when 7 # other
case @parameters[4]
when 0 then value = $game_map.map_id # map ID
when 1 then value = $Trainer.pokemon_party.length # party members
when 2 then value = $Trainer.money # gold
when 1 then value = $player.pokemon_party.length # party members
when 2 then value = $player.money # gold
# when 3 # steps
when 4 then value = Graphics.frame_count / Graphics.frame_rate # play time
when 5 then value = $game_system.timer / Graphics.frame_rate # timer
@@ -505,29 +579,29 @@ class Interpreter
end
end
# 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]
when 0 # set
next if $game_variables[i] == value
$game_variables[i] = value
when 1 # add
next if $game_variables[i] >= 99999999
next if $game_variables[i] >= 99_999_999
$game_variables[i] += value
when 2 # subtract
next if $game_variables[i] <= -99999999
next if $game_variables[i] <= -99_999_999
$game_variables[i] -= value
when 3 # multiply
next if value == 1
$game_variables[i] *= value
when 4 # divide
next if value == 1 || value == 0
next if [0, 1].include?(value)
$game_variables[i] /= value
when 5 # remainder
next if value == 1 || value == 0
next if [0, 1].include?(value)
$game_variables[i] %= value
end
$game_variables[i] = 99999999 if $game_variables[i] > 99999999
$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] = -99_999_999 if $game_variables[i] < -99_999_999
$game_map.need_refresh = true
end
return true
@@ -560,7 +634,7 @@ class Interpreter
def command_125
value = (@parameters[1] == 0) ? @parameters[2] : $game_variables[@parameters[2]]
value = -value if @parameters[0] == 1 # Decrease
$Trainer.money += value
$player.money += value
return true
end
@@ -572,7 +646,7 @@ class Interpreter
# * Change Windowskin
#-----------------------------------------------------------------------------
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]
$PokemonSystem.textskin = i
MessageConfig.pbSetSpeechFrame("Graphics/Windowskins/" + Settings::SPEECH_WINDOWSKINS[i])
@@ -590,10 +664,7 @@ class Interpreter
#-----------------------------------------------------------------------------
# * Change Battle End ME
#-----------------------------------------------------------------------------
def command_133
($PokemonGlobal.nextBattleME = @parameters[0]) ? @parameters[0].clone : nil
return true
end
def command_133; command_dummy; end
#-----------------------------------------------------------------------------
# * Change Save Access
#-----------------------------------------------------------------------------
@@ -630,13 +701,12 @@ class Interpreter
$game_temp.player_new_map_id = @parameters[1]
$game_temp.player_new_x = @parameters[2]
$game_temp.player_new_y = @parameters[3]
$game_temp.player_new_direction = @parameters[4]
else # Appoint with variables
$game_temp.player_new_map_id = $game_variables[@parameters[1]]
$game_temp.player_new_x = $game_variables[@parameters[2]]
$game_temp.player_new_y = $game_variables[@parameters[3]]
$game_temp.player_new_direction = @parameters[4]
end
$game_temp.player_new_direction = @parameters[4]
@index += 1
# If transition happens with a fade, do the fade
if @parameters[5] == 0
@@ -654,9 +724,10 @@ class Interpreter
character = get_character(@parameters[0])
return true if character.nil?
# Move the character
if @parameters[1] == 0 # Direct appointment
case @parameters[1]
when 0 # Direct appointment
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]])
else # Exchange with another event
character2 = get_character(@parameters[2])
@@ -726,6 +797,11 @@ class Interpreter
#-----------------------------------------------------------------------------
def command_207
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?
character.animation_id = @parameters[1]
return true
@@ -742,6 +818,11 @@ class Interpreter
#-----------------------------------------------------------------------------
def command_209
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?
character.force_move_route(@parameters[1])
return true
@@ -805,7 +886,7 @@ class Interpreter
y = $game_variables[@parameters[5]]
end
$game_screen.pictures[number].show(@parameters[1], @parameters[2],
x, y, @parameters[6], @parameters[7], @parameters[8], @parameters[9])
x, y, @parameters[6], @parameters[7], @parameters[8], @parameters[9])
return true
end
#-----------------------------------------------------------------------------
@@ -821,7 +902,7 @@ class Interpreter
y = $game_variables[@parameters[5]]
end
$game_screen.pictures[number].move(@parameters[1] * Graphics.frame_rate / 20,
@parameters[2], x, y, @parameters[6], @parameters[7], @parameters[8], @parameters[9])
@parameters[2], x, y, @parameters[6], @parameters[7], @parameters[8], @parameters[9])
return true
end
#-----------------------------------------------------------------------------
@@ -838,7 +919,7 @@ class Interpreter
def command_234
number = @parameters[0] + ($game_temp.in_battle ? 50 : 0)
$game_screen.pictures[number].start_tone_change(@parameters[1],
@parameters[2] * Graphics.frame_rate / 20)
@parameters[2] * Graphics.frame_rate / 20)
return true
end
#-----------------------------------------------------------------------------
@@ -931,18 +1012,19 @@ class Interpreter
# * Name Input Processing
#-----------------------------------------------------------------------------
def command_303
if $Trainer
$Trainer.name = pbEnterPlayerName(_INTL("Your name?"), 1, @parameters[1], $Trainer.name)
if $player
$player.name = pbEnterPlayerName(_INTL("Your name?"), 1, @parameters[1], $player.name)
return true
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
pbFadeOutIn {
sscene = PokemonEntryScene.new
sscreen = PokemonEntry.new(sscene)
$game_actors[@parameters[0]].name = sscreen.pbStartScreen(
_INTL("Enter {1}'s name.", $game_actors[@parameters[0]].name),
1, @parameters[1], $game_actors[@parameters[0]].name)
_INTL("Enter {1}'s name.", $game_actors[@parameters[0]].name),
1, @parameters[1], $game_actors[@parameters[0]].name
)
}
end
return true
@@ -955,7 +1037,13 @@ class Interpreter
# * Recover All
#-----------------------------------------------------------------------------
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
end
@@ -1006,7 +1094,7 @@ class Interpreter
# * Return to Title Screen
#-----------------------------------------------------------------------------
def command_354
$game_temp.to_title = true
$game_temp.title_screen_calling = true
return false
end
#-----------------------------------------------------------------------------
@@ -1017,7 +1105,7 @@ class Interpreter
# Look for more script commands or a continuation of one, and add them to script
loop do
break if ![355, 655].include?(@list[@index + 1].code)
script += @list[@index+1].parameters[0] + "\n"
script += @list[@index + 1].parameters[0] + "\n"
@index += 1
end
# Run the script

View File

@@ -13,21 +13,15 @@ class Event
end
# Removes an event handler procedure from the event.
def -(method)
for i in 0...@callbacks.length
next if @callbacks[i]!=method
@callbacks.delete_at(i)
break
end
def -(other)
@callbacks.delete(other)
return self
end
# Adds an event handler procedure from the event.
def +(method)
for i in 0...@callbacks.length
return self if @callbacks[i]==method
end
@callbacks.push(method)
def +(other)
return self if @callbacks.include?(other)
@callbacks.push(other)
return self
end
@@ -44,13 +38,13 @@ class Event
# proc { |sender,params| } where params is an array of the other parameters, and
# proc { |sender,arg0,arg1,...| }
def trigger(*arg)
arglist = arg[1,arg.length]
for callback in @callbacks
if callback.arity>2 && arg.length==callback.arity
arglist = arg[1, arg.length]
@callbacks.each do |callback|
if callback.arity > 2 && arg.length == callback.arity
# Retrofitted for callbacks that take three or more arguments
callback.call(*arg)
else
callback.call(arg[0],arglist)
callback.call(arg[0], arglist)
end
end
end
@@ -59,14 +53,45 @@ class Event
# by the code where the event occurred. The first argument is the sender of
# the event, the other arguments are the event's parameters.
def trigger2(*arg)
for callback in @callbacks
@callbacks.each do |callback|
callback.call(*arg)
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
def initialize(mod)
@@ -89,8 +114,8 @@ class HandlerHash
return ret if ret
mod = Object.const_get(@mod) rescue nil
return nil if !mod
for key in mod.constants
next if mod.const_get(key)!=sym
mod.constants.each do |key|
next if mod.const_get(key) != sym
ret = key.to_sym
@symbolCache[sym] = ret
break
@@ -98,15 +123,15 @@ class HandlerHash
return ret
end
def addIf(conditionProc,handler=nil,&handlerBlock)
if ![Proc,Hash].include?(handler.class) && !block_given?
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
@addIfs.push([conditionProc,handler || handlerBlock])
@addIfs.push([conditionProc, handler || handlerBlock])
end
def add(sym,handler=nil,&handlerBlock) # 'sym' can be an ID or symbol
if ![Proc,Hash].include?(handler.class) && !block_given?
def add(sym, handler = nil, &handlerBlock) # 'sym' can be an ID or symbol
if ![Proc, Hash].include?(handler.class) && !block_given?
raise ArgumentError, "#{self.class.name} for #{sym.inspect} has no valid handler (#{handler.inspect} was given)"
end
id = fromSymbol(sym)
@@ -115,11 +140,11 @@ class HandlerHash
@hash[symbol] = handler || handlerBlock if symbol
end
def copy(src,*dests)
def copy(src, *dests)
handler = self[src]
if handler
for dest in dests
self.add(dest,handler)
dests.each do |dest|
self.add(dest, handler)
end
end
end
@@ -131,16 +156,16 @@ class HandlerHash
symbol = toSymbol(sym)
ret = @hash[symbol] if symbol && @hash[symbol] # Symbol or string
unless ret
for addif in @addIfs
@addIfs.each do |addif|
return addif[1] if addif[0].call(id)
end
end
return ret
end
def trigger(sym,*args)
def trigger(sym, *args)
handler = self[sym]
return (handler) ? handler.call(fromSymbol(sym),*args) : nil
return (handler) ? handler.call(fromSymbol(sym), *args) : nil
end
def clear
@@ -150,7 +175,8 @@ end
#===============================================================================
# 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
def initialize
@@ -161,19 +187,12 @@ class HandlerHash2
def [](sym)
sym = sym.id if !sym.is_a?(Symbol) && sym.respond_to?("id")
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)
end
return nil
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)
if ![Proc, Hash].include?(handler.class) && !block_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
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)
handler = self[src]
return if !handler
for dest in dests
self.add(dest, handler)
end
dests.each { |dest| add(dest, handler) }
end
def remove(key)
@hash.delete(key)
end
def clear
@@ -196,7 +224,7 @@ class HandlerHash2
def trigger(sym, *args)
sym = sym.id if !sym.is_a?(Symbol) && sym.respond_to?("id")
handler = self[sym]
return (handler) ? handler.call(sym, *args) : nil
return handler&.call(sym, *args)
end
end
@@ -206,32 +234,26 @@ end
#===============================================================================
class HandlerHashBasic
def initialize
@ordered_keys = []
@hash = {}
@addIfs = []
@hash = {}
@addIfs = []
end
def [](entry)
ret = nil
ret = @hash[entry] if entry && @hash[entry]
unless ret
for addif in @addIfs
@addIfs.each do |addif|
return addif[1] if addif[0].call(entry)
end
end
return ret
end
def each
@ordered_keys.each { |key| yield key, @hash[key] }
end
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)"
end
return if !entry || entry.empty?
@ordered_keys.push(entry) if !@ordered_keys.include?(entry)
@hash[entry] = handler || handlerBlock
end
@@ -245,17 +267,28 @@ class HandlerHashBasic
def copy(src, *dests)
handler = self[src]
return if !handler
dests.each { |dest| self.add(dest, handler) }
dests.each { |dest| add(dest, handler) }
end
def remove(key)
@hash.delete(key)
end
def 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
def trigger(entry, *args)
handler = self[entry]
return (handler) ? handler.call(*args) : nil
return handler&.call(*args)
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_max # max number of weather sprites
attr_accessor :weather_duration # ticks in which the weather should fade in
#-----------------------------------------------------------------------------
# * Object Initialization
#-----------------------------------------------------------------------------
@@ -35,10 +36,10 @@ class Game_Screen
@shake_direction = 1
@shake = 0
@pictures = [nil]
for i in 1..100
(1..100).each do |i|
@pictures.push(Game_Picture.new(i))
end
@weather_type = 0
@weather_type = :None
@weather_max = 0.0
@weather_duration = 0
end
@@ -89,46 +90,46 @@ class Game_Screen
# * Frame Update
#-----------------------------------------------------------------------------
def update
if @fadeout_duration && @fadeout_duration>=1
if @fadeout_duration && @fadeout_duration >= 1
d = @fadeout_duration
@brightness = (@brightness*(d-1))/d
@brightness = (@brightness * (d - 1)) / d
@fadeout_duration -= 1
end
if @fadein_duration && @fadein_duration>=1
if @fadein_duration && @fadein_duration >= 1
d = @fadein_duration
@brightness = (@brightness*(d-1)+255)/d
@brightness = ((@brightness * (d - 1)) + 255) / d
@fadein_duration -= 1
end
if @tone_duration>=1
if @tone_duration >= 1
d = @tone_duration
@tone.red = (@tone.red*(d-1)+@tone_target.red)/d
@tone.green = (@tone.green*(d-1)+@tone_target.green)/d
@tone.blue = (@tone.blue*(d-1)+@tone_target.blue)/d
@tone.gray = (@tone.gray*(d-1)+@tone_target.gray)/d
@tone.red = ((@tone.red * (d - 1)) + @tone_target.red) / d
@tone.green = ((@tone.green * (d - 1)) + @tone_target.green) / d
@tone.blue = ((@tone.blue * (d - 1)) + @tone_target.blue) / d
@tone.gray = ((@tone.gray * (d - 1)) + @tone_target.gray) / d
@tone_duration -= 1
end
if @flash_duration>=1
if @flash_duration >= 1
d = @flash_duration
@flash_color.alpha = @flash_color.alpha*(d-1)/d
@flash_color.alpha = @flash_color.alpha * (d - 1) / d
@flash_duration -= 1
end
if @shake_duration>=1 || @shake!=0
delta = (@shake_power*@shake_speed*@shake_direction)/10.0
if @shake_duration<=1 && @shake*(@shake+delta)<0
if @shake_duration >= 1 || @shake != 0
delta = (@shake_power * @shake_speed * @shake_direction) / 10.0
if @shake_duration <= 1 && @shake * (@shake + delta) < 0
@shake = 0
else
@shake += delta
end
@shake_direction = -1 if @shake>@shake_power*2
@shake_direction = 1 if @shake<-@shake_power*2
@shake_duration -= 1 if @shake_duration>=1
@shake_direction = -1 if @shake > @shake_power * 2
@shake_direction = 1 if @shake < -@shake_power * 2
@shake_duration -= 1 if @shake_duration >= 1
end
if $game_temp.in_battle
for i in 51..100
(51..100).each do |i|
@pictures[i].update
end
else
for i in 1..50
(1..50).each do |i|
@pictures[i].update
end
end
@@ -138,17 +139,17 @@ end
#===============================================================================
#
#===============================================================================
def pbToneChangeAll(tone,duration)
$game_screen.start_tone_change(tone,duration*Graphics.frame_rate/20)
for picture in $game_screen.pictures
picture.start_tone_change(tone,duration*Graphics.frame_rate/20) if picture
def pbToneChangeAll(tone, duration)
$game_screen.start_tone_change(tone, duration * Graphics.frame_rate / 20)
$game_screen.pictures.each do |picture|
picture&.start_tone_change(tone, duration * Graphics.frame_rate / 20)
end
end
def pbShake(power,speed,frames)
$game_screen.start_shake(power,speed,frames*Graphics.frame_rate/20)
def pbShake(power, speed, frames)
$game_screen.start_shake(power, speed, frames * Graphics.frame_rate / 20)
end
def pbFlash(color,frames)
$game_screen.start_flash(color,frames*Graphics.frame_rate/20)
def pbFlash(color, frames)
$game_screen.start_flash(color, frames * Graphics.frame_rate / 20)
end

View File

@@ -5,51 +5,86 @@
# Refer to "$game_temp" for the instance of this class.
#===============================================================================
class Game_Temp
attr_accessor :message_window_showing # message window showing
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
# Flags requesting something to happen
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 :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_new_map_id # player destination: map ID
attr_accessor :player_new_x # player destination: x-coordinate
attr_accessor :player_new_y # player destination: y-coordinate
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_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 :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
#-----------------------------------------------------------------------------
# * Object Initialization
#-----------------------------------------------------------------------------
def initialize
@message_window_showing = false
@common_event_id = 0
@in_battle = false
@battle_abort = false
@battleback_name = ''
@in_menu = false
@menu_beep = false
# Flags requesting something to happen
@menu_calling = false
@ready_menu_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_new_map_id = 0
@player_new_x = 0
@player_new_y = 0
@player_new_direction = 0
# Transitions
@transition_processing = false
@transition_name = ""
@to_title = false
@fadestate = 0
@background_bitmap = nil
@message_window_showing = false
@transition_processing = false
# Other
@begun_new_game = false
@menu_beep = false
@memorized_bgm = nil
@memorized_bgm_position = 0
@menu_last_choice = 0
@mart_prices = {}
end

View File

@@ -16,7 +16,7 @@ class Game_Switches
# switch_id : 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
end
#-----------------------------------------------------------------------------

View File

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

View File

@@ -44,28 +44,27 @@ class Game_System
def bgm_play(bgm)
old_pos = @bgm_position
@bgm_position = 0
bgm_play_internal(bgm,0)
bgm_play_internal(bgm, 0)
@bgm_position = old_pos
end
def bgm_play_internal2(name,volume,pitch,position) # :nodoc:
def bgm_play_internal2(name, volume, pitch, position) # :nodoc:
vol = volume
vol *= $PokemonSystem.bgmvolume/100.0
vol *= $PokemonSystem.bgmvolume / 100.0
vol = vol.to_i
begin
Audio.bgm_play(name,vol,pitch,position)
Audio.bgm_play(name, vol, pitch, position)
rescue ArgumentError
Audio.bgm_play(name,vol,pitch)
Audio.bgm_play(name, vol, pitch)
end
end
def bgm_play_internal(bgm,position) # :nodoc:
def bgm_play_internal(bgm, position) # :nodoc:
@bgm_position = position if !@bgm_paused
@playing_bgm = (bgm==nil) ? nil : bgm.clone
if bgm!=nil && bgm.name!=""
if FileTest.audio_exist?("Audio/BGM/"+bgm.name)
bgm_play_internal2("Audio/BGM/"+bgm.name,
bgm.volume,bgm.pitch,@bgm_position) if !@defaultBGM
@playing_bgm = bgm&.clone
if bgm && bgm.name != ""
if !@defaultBGM && FileTest.audio_exist?("Audio/BGM/" + bgm.name)
bgm_play_internal2("Audio/BGM/" + bgm.name, bgm.volume, bgm.pitch, @bgm_position)
end
else
@bgm_position = position if !@bgm_paused
@@ -73,15 +72,15 @@ class Game_System
Audio.bgm_stop if !@defaultBGM
end
if @defaultBGM
bgm_play_internal2("Audio/BGM/"+@defaultBGM.name,
@defaultBGM.volume,@defaultBGM.pitch,@bgm_position)
bgm_play_internal2("Audio/BGM/" + @defaultBGM.name,
@defaultBGM.volume, @defaultBGM.pitch, @bgm_position)
end
Graphics.frame_reset
end
def bgm_pause(fadetime=0.0) # :nodoc:
def bgm_pause(fadetime = 0.0) # :nodoc:
pos = Audio.bgm_pos rescue 0
self.bgm_fade(fadetime) if fadetime>0.0
self.bgm_fade(fadetime) if fadetime > 0.0
@bgm_position = pos
@bgm_paused = true
end
@@ -93,7 +92,7 @@ class Game_System
def bgm_resume(bgm) # :nodoc:
if @bgm_paused
self.bgm_play_internal(bgm,@bgm_position)
self.bgm_play_internal(bgm, @bgm_position)
@bgm_position = 0
@bgm_paused = false
end
@@ -108,7 +107,7 @@ class Game_System
def bgm_fade(time) # :nodoc:
@bgm_position = 0 if !@bgm_paused
@playing_bgm = nil
Audio.bgm_fade((time*1000).floor) if !@defaultBGM
Audio.bgm_fade((time * 1000).floor) if !@defaultBGM
end
def playing_bgm
@@ -130,14 +129,13 @@ class Game_System
return (@playing_bgm) ? @playing_bgm.clone : nil
end
def setDefaultBGM(bgm,volume=80,pitch=100)
bgm = RPG::AudioFile.new(bgm,volume,pitch) if bgm.is_a?(String)
if bgm!=nil && bgm.name!=""
@defaultBGM = nil
def setDefaultBGM(bgm, volume = 80, pitch = 100)
bgm = RPG::AudioFile.new(bgm, volume, pitch) if bgm.is_a?(String)
@defaultBGM = nil
if bgm && bgm.name != ""
self.bgm_play(bgm)
@defaultBGM = bgm.clone
else
@defaultBGM = nil
self.bgm_play(@playing_bgm)
end
end
@@ -146,12 +144,12 @@ class Game_System
def me_play(me)
me = RPG::AudioFile.new(me) if me.is_a?(String)
if me!=nil && me.name!=""
if FileTest.audio_exist?("Audio/ME/"+me.name)
if me && me.name != ""
if FileTest.audio_exist?("Audio/ME/" + me.name)
vol = me.volume
vol *= $PokemonSystem.bgmvolume/100.0
vol *= $PokemonSystem.bgmvolume / 100.0
vol = vol.to_i
Audio.me_play("Audio/ME/"+me.name,vol,me.pitch)
Audio.me_play("Audio/ME/" + me.name, vol, me.pitch)
end
else
Audio.me_stop
@@ -162,13 +160,13 @@ class Game_System
################################################################################
def bgs_play(bgs)
@playing_bgs = (bgs==nil) ? nil : bgs.clone
if bgs!=nil && bgs.name!=""
if FileTest.audio_exist?("Audio/BGS/"+bgs.name)
@playing_bgs = (bgs.nil?) ? nil : bgs.clone
if bgs && bgs.name != ""
if FileTest.audio_exist?("Audio/BGS/" + bgs.name)
vol = bgs.volume
vol *= $PokemonSystem.sevolume/100.0
vol *= $PokemonSystem.sevolume / 100.0
vol = vol.to_i
Audio.bgs_play("Audio/BGS/"+bgs.name,vol,bgs.pitch)
Audio.bgs_play("Audio/BGS/" + bgs.name, vol, bgs.pitch)
end
else
@bgs_position = 0
@@ -178,8 +176,8 @@ class Game_System
Graphics.frame_reset
end
def bgs_pause(fadetime=0.0) # :nodoc:
if fadetime>0.0
def bgs_pause(fadetime = 0.0) # :nodoc:
if fadetime > 0.0
self.bgs_fade(fadetime)
else
self.bgs_stop
@@ -207,7 +205,7 @@ class Game_System
def bgs_fade(time)
@bgs_position = 0
@playing_bgs = nil
Audio.bgs_fade((time*1000).floor)
Audio.bgs_fade((time * 1000).floor)
end
def playing_bgs
@@ -230,11 +228,11 @@ class Game_System
def se_play(se)
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 *= $PokemonSystem.sevolume/100.0
vol *= $PokemonSystem.sevolume / 100.0
vol = vol.to_i
Audio.se_play("Audio/SE/"+se.name,vol,se.pitch)
Audio.se_play("Audio/SE/" + se.name, vol, se.pitch)
end
end
@@ -248,37 +246,31 @@ class Game_System
return (@battle_bgm) ? @battle_bgm : $data_system.battle_bgm
end
def battle_bgm=(battle_bgm)
@battle_bgm = battle_bgm
end
attr_writer :battle_bgm
def battle_end_me
return (@battle_end_me) ? @battle_end_me : $data_system.battle_end_me
end
def battle_end_me=(battle_end_me)
@battle_end_me = battle_end_me
end
attr_writer :battle_end_me
################################################################################
def windowskin_name
if @windowskin_name==nil
if @windowskin_name.nil?
return $data_system.windowskin_name
else
return @windowskin_name
end
end
def windowskin_name=(windowskin_name)
@windowskin_name = windowskin_name
end
attr_writer :windowskin_name
def update
@timer -= 1 if @timer_working && @timer>0
if Input.trigger?(Input::SPECIAL) && pbCurrentEventCommentInput(1,"Cut Scene")
event = @map_interpreter.get_character(0)
@map_interpreter.pbSetSelfSwitch(event.id,"A",true)
@timer -= 1 if @timer_working && @timer > 0
if Input.trigger?(Input::SPECIAL) && pbCurrentEventCommentInput(1, "Cut Scene")
event = @map_interpreter.get_self
@map_interpreter.pbSetSelfSwitch(event.id, "A", true)
@map_interpreter.command_end
event.start
end

View File

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

View File

@@ -43,8 +43,8 @@ class Game_Map
end
def setup(map_id)
@map_id = map_id
@map = load_data(sprintf("Data/Map%03d.rxdata",map_id))
@map_id = map_id
@map = load_data(sprintf("Data/Map%03d.rxdata", map_id))
tileset = $data_tilesets[@map.tileset_id]
updateTileset
@fog_ox = 0
@@ -57,13 +57,13 @@ class Game_Map
self.display_x = 0
self.display_y = 0
@need_refresh = false
Events.onMapCreate.trigger(self,map_id,@map,tileset)
EventHandlers.trigger(:on_game_map_setup, map_id, @map, tileset)
@events = {}
for i in @map.events.keys
@events[i] = Game_Event.new(@map_id, @map.events[i],self)
@map.events.each_key do |i|
@events[i] = Game_Event.new(@map_id, @map.events[i], self)
end
@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)
end
@scroll_direction = 2
@@ -95,57 +95,56 @@ class Game_Map
def encounter_list; return @map.encounter_list; end
def encounter_step; return @map.encounter_step; end
def data; return @map.data; end
def tileset_id; return @map.tileset_id; end
def bgm; return @map.bgm; end
def name
ret = pbGetMessage(MessageTypes::MapNames,@map_id)
ret.gsub!(/\\PN/,$Trainer.name) if $Trainer
return ret
return pbGetMapNameFromId(@map_id)
end
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
#-----------------------------------------------------------------------------
# * Autoplays background music
# Plays music called "[normal BGM]_n" if it's night time and it exists
#-----------------------------------------------------------------------------
def autoplayAsCue
if @map.autoplay_bgm
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/"+ @map.bgm.name+ "_n")
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
pbCueBGM(bgm_name, 1.0, @map.bgm.volume, @map.bgm.pitch) if @map.autoplay_bgm
pbBGSPlay(@map.bgs) if @map.autoplay_bgs
end
#-----------------------------------------------------------------------------
# * Plays background music
# Plays music called "[normal BGM]_n" if it's night time and it exists
#-----------------------------------------------------------------------------
def autoplay
if @map.autoplay_bgm
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/"+ @map.bgm.name+ "_n")
pbBGMPlay(@map.bgm.name+"_n",@map.bgm.volume,@map.bgm.pitch)
else
pbBGMPlay(@map.bgm)
end
end
if @map.autoplay_bgs
pbBGSPlay(@map.bgs)
end
pbBGMPlay(bgm_name, @map.bgm.volume, @map.bgm.pitch) if @map.autoplay_bgm
pbBGSPlay(@map.bgs) if @map.autoplay_bgs
end
def valid?(x, y)
return x>=0 && x<width && y>=0 && y<height
return x >= 0 && x < width && y >= 0 && y < height
end
def validLax?(x, y)
return x>=-10 && x<=width+10 && y>=-10 && y<=height+10
return x >= -10 && x <= width + 10 && y >= -10 && y <= height + 10
end
def passable?(x, y, d, self_event = nil)
return false if !valid?(x, y)
bit = (1 << (d / 2 - 1)) & 0x0f
for event in events.values
bit = (1 << ((d / 2) - 1)) & 0x0f
events.each_value do |event|
next if event.tile_id <= 0
next if event == self_event
next if !event.at_coordinate?(x, y)
@@ -156,7 +155,7 @@ class Game_Map
return false if passage & 0x0f == 0x0f
return true if @priorities[event.tile_id] == 0
end
return playerPassable?(x, y, d, self_event) if self_event==$game_player
return playerPassable?(x, y, d, self_event) if self_event == $game_player
# All other events
newx = x
newy = y
@@ -183,14 +182,14 @@ class Game_Map
newy -= 1
end
return false if !valid?(newx, newy)
for i in [2, 1, 0]
[2, 1, 0].each do |i|
tile_id = data[x, y, i]
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
# If already on water, only allow movement to another water tile
if self_event != nil && terrain.can_surf_freely
for j in [2, 1, 0]
if self_event && terrain.can_surf_freely
[2, 1, 0].each do |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])
if facing_terrain.id != :None && !facing_terrain.ignore_passability
return facing_terrain.can_surf_freely
@@ -200,29 +199,28 @@ class Game_Map
# Can't walk onto ice
elsif terrain.ice
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
for j in [2, 1, 0]
[2, 1, 0].each do |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])
return false if facing_terrain.ledge
break if facing_terrain.id != :None && !facing_terrain.ignore_passability
end
end
next if terrain&.ignore_passability
# Regular passability checks
if !terrain || !terrain.ignore_passability
passage = @passages[tile_id]
return false if passage & bit != 0 || passage & 0x0f == 0x0f
return true if @priorities[tile_id] == 0
end
passage = @passages[tile_id]
return false if passage & bit != 0 || passage & 0x0f == 0x0f
return true if @priorities[tile_id] == 0
end
return true
end
def playerPassable?(x, y, d, self_event = nil)
bit = (1 << (d / 2 - 1)) & 0x0f
for i in [2, 1, 0]
bit = (1 << ((d / 2) - 1)) & 0x0f
[2, 1, 0].each do |i|
tile_id = data[x, y, i]
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
passage = @passages[tile_id]
@@ -238,11 +236,10 @@ class Game_Map
return (passage & bit == 0 && passage & 0x0f != 0x0f)
end
end
next if terrain&.ignore_passability
# Regular passability checks
if !terrain || !terrain.ignore_passability
return false if passage & bit != 0 || passage & 0x0f == 0x0f
return true if @priorities[tile_id] == 0
end
return false if passage & bit != 0 || passage & 0x0f == 0x0f
return true if @priorities[tile_id] == 0
end
return true
end
@@ -251,14 +248,14 @@ class Game_Map
# event there, and the tile is fully passable in all directions)
def passableStrict?(x, y, d, self_event = nil)
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.at_coordinate?(x, y)
next if GameData::TerrainTag.try_get(@terrain_tags[event.tile_id]).ignore_passability
return false if @passages[event.tile_id] & 0x0f != 0
return true if @priorities[event.tile_id] == 0
end
for i in [2, 1, 0]
[2, 1, 0].each do |i|
tile_id = data[x, y, i]
next if GameData::TerrainTag.try_get(@terrain_tags[tile_id]).ignore_passability
return false if @passages[tile_id] & 0x0f != 0
@@ -267,8 +264,8 @@ class Game_Map
return true
end
def bush?(x,y)
for i in [2, 1, 0]
def bush?(x, y)
[2, 1, 0].each do |i|
tile_id = data[x, y, i]
return false if GameData::TerrainTag.try_get(@terrain_tags[tile_id]).bridge &&
$PokemonGlobal.bridge > 0
@@ -277,8 +274,8 @@ class Game_Map
return false
end
def deepBush?(x,y)
for i in [2, 1, 0]
def deepBush?(x, y)
[2, 1, 0].each do |i|
tile_id = data[x, y, i]
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
return false if terrain.bridge && $PokemonGlobal.bridge > 0
@@ -287,8 +284,8 @@ class Game_Map
return false
end
def counter?(x,y)
for i in [2, 1, 0]
def counter?(x, y)
[2, 1, 0].each do |i|
tile_id = data[x, y, i]
passage = @passages[tile_id]
return true if passage & 0x80 == 0x80
@@ -296,9 +293,9 @@ class Game_Map
return false
end
def terrain_tag(x,y,countBridge=false)
def terrain_tag(x, y, countBridge = false)
if valid?(x, y)
for i in [2, 1, 0]
[2, 1, 0].each do |i|
tile_id = data[x, y, i]
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
next if terrain.id == :None || terrain.ignore_passability
@@ -310,8 +307,8 @@ class Game_Map
end
# Unused.
def check_event(x,y)
for event in self.events.values
def check_event(x, y)
self.events.each_value do |event|
return event.id if event.at_coordinate?(x, y)
end
end
@@ -319,21 +316,21 @@ class Game_Map
def display_x=(value)
return if @display_x == value
@display_x = value
if GameData::MapMetadata.exists?(self.map_id) && GameData::MapMetadata.get(self.map_id).snap_edges
max_x = (self.width - Graphics.width*1.0/TILE_WIDTH) * REAL_RES_X
if metadata&.snap_edges
max_x = (self.width - (Graphics.width.to_f / TILE_WIDTH)) * REAL_RES_X
@display_x = [0, [@display_x, max_x].min].max
end
$MapFactory.setMapsInRange if $MapFactory
$map_factory&.setMapsInRange
end
def display_y=(value)
return if @display_y == value
@display_y = value
if GameData::MapMetadata.exists?(self.map_id) && GameData::MapMetadata.get(self.map_id).snap_edges
max_y = (self.height - Graphics.height*1.0/TILE_HEIGHT) * REAL_RES_Y
if metadata&.snap_edges
max_y = (self.height - (Graphics.height.to_f / TILE_HEIGHT)) * REAL_RES_Y
@display_y = [0, [@display_y, max_y].min].max
end
$MapFactory.setMapsInRange if $MapFactory
$map_factory&.setMapsInRange
end
def scroll_up(distance)
@@ -354,7 +351,7 @@ class Game_Map
def start_scroll(direction, distance, speed)
@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
else
@scroll_rest = distance * REAL_RES_X
@@ -366,7 +363,7 @@ class Game_Map
return @scroll_rest > 0
end
def start_fog_tone_change(tone,duration)
def start_fog_tone_change(tone, duration)
@fog_tone_target = tone.clone
@fog_tone_duration = duration
if @fog_tone_duration == 0
@@ -374,19 +371,27 @@ class Game_Map
end
end
def start_fog_opacity_change(opacity,duration)
@fog_opacity_target = opacity*1.0
def start_fog_opacity_change(opacity, duration)
@fog_opacity_target = opacity.to_f
@fog_opacity_duration = duration
if @fog_opacity_duration==0
if @fog_opacity_duration == 0
@fog_opacity = @fog_opacity_target
end
end
def set_tile(x, y, layer, id = 0)
self.data[x, y, layer] = id
end
def erase_tile(x, y, layer)
set_tile(x, y, layer, 0)
end
def refresh
for event in @events.values
@events.each_value do |event|
event.refresh
end
for common_event in @common_events.values
@common_events.each_value do |common_event|
common_event.refresh
end
@need_refresh = false
@@ -394,16 +399,16 @@ class Game_Map
def update
# refresh maps if necessary
if $MapFactory
for i in $MapFactory.maps
if $map_factory
$map_factory.maps.each do |i|
i.refresh if i.need_refresh
end
$MapFactory.setCurrentMap
$map_factory.setCurrentMap
end
# If scrolling
if @scroll_rest>0
distance = (1<<@scroll_speed)*40.0/Graphics.frame_rate
distance = @scroll_rest if distance>@scroll_rest
if @scroll_rest > 0
distance = (1 << @scroll_speed) * 40.0 / Graphics.frame_rate
distance = @scroll_rest if distance > @scroll_rest
case @scroll_direction
when 2 then scroll_down(distance)
when 4 then scroll_left(distance)
@@ -413,28 +418,28 @@ class Game_Map
@scroll_rest -= distance
end
# Only update events that are on-screen
for event in @events.values
@events.each_value do |event|
event.update
end
# Update common events
for common_event in @common_events.values
@common_events.each_value do |common_event|
common_event.update
end
# Update fog
@fog_ox -= @fog_sx/8.0
@fog_oy -= @fog_sy/8.0
if @fog_tone_duration>=1
@fog_ox -= @fog_sx / 8.0
@fog_oy -= @fog_sy / 8.0
if @fog_tone_duration >= 1
d = @fog_tone_duration
target = @fog_tone_target
@fog_tone.red = (@fog_tone.red * (d - 1) + target.red) / 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.gray = (@fog_tone.gray * (d - 1) + target.gray) / 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.blue = ((@fog_tone.blue * (d - 1)) + target.blue) / d
@fog_tone.gray = ((@fog_tone.gray * (d - 1)) + target.gray) / d
@fog_tone_duration -= 1
end
if @fog_opacity_duration >= 1
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
end
end
@@ -443,8 +448,8 @@ end
#===============================================================================
#
#===============================================================================
def pbScrollMap(direction,distance,speed)
if speed==0
def pbScrollMap(direction, distance, speed)
if speed == 0
case direction
when 2 then $game_map.scroll_down(distance * Game_Map::REAL_RES_Y)
when 4 then $game_map.scroll_left(distance * Game_Map::REAL_RES_X)
@@ -460,7 +465,7 @@ def pbScrollMap(direction,distance,speed)
Input.update
break if !$game_map.scrolling?
pbUpdateSceneMap
break if $game_map.display_x==oldx && $game_map.display_y==oldy
break if $game_map.display_x == oldx && $game_map.display_y == oldy
oldx = $game_map.display_x
oldy = $game_map.display_y
end

View File

@@ -77,23 +77,38 @@ class Interpreter
# y : y coordinate to scroll to and center on
# speed : (optional) scroll speed (from 1-6, default being 4)
#-----------------------------------------------------------------------------
def autoscroll(x,y,speed=SCROLL_SPEED_DEFAULT)
def autoscroll(x, y, speed = SCROLL_SPEED_DEFAULT)
if $game_map.scrolling?
return false
elsif !$game_map.valid?(x,y)
print 'Map Autoscroll: given x,y is invalid'
elsif !$game_map.valid?(x, y)
print "Map Autoscroll: given x,y is invalid"
return command_skip
elsif !(1..6).include?(speed)
print 'Map Autoscroll: invalid speed (1-6 only)'
print "Map Autoscroll: invalid speed (1-6 only)"
return command_skip
end
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
max_x = ($game_map.width - Graphics.width*1.0/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
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
if !@diag
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
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.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_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
@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
dir = nil
if count_x > 0
@@ -109,37 +124,18 @@ class Interpreter
dir = 3
end
end
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
count = [count_x.abs, count_y.abs].min
end
$game_map.start_scroll(dir, count, speed) if dir
return !@diag
end
#-----------------------------------------------------------------------------
# * Map Autoscroll (to Player)
# speed : (optional) scroll speed (from 1-6, default being 4)
#-----------------------------------------------------------------------------
def autoscroll_player(speed=SCROLL_SPEED_DEFAULT)
autoscroll($game_player.x,$game_player.y,speed)
def autoscroll_player(speed = SCROLL_SPEED_DEFAULT)
autoscroll($game_player.x, $game_player.y, speed)
end
end
@@ -148,20 +144,20 @@ end
class Game_Map
def scroll_downright(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,
(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
def scroll_downleft(distance)
@display_x = [@display_x - distance, 0].max
@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
def scroll_upright(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
end
@@ -174,8 +170,8 @@ class Game_Map
# If scrolling
if @scroll_rest > 0
# Change from scroll speed to distance in map coordinates
distance = (1<<@scroll_speed)*40/Graphics.frame_rate
distance = @scroll_rest if distance>@scroll_rest
distance = (1 << @scroll_speed) * 40 / Graphics.frame_rate
distance = @scroll_rest if distance > @scroll_rest
# Execute scrolling
case @scroll_direction
when 1 then scroll_downleft(distance)

View File

@@ -19,7 +19,7 @@ class PokemonMapFactory
@maps[0] = Game_Map.new
@mapIndex = 0
oldID = ($game_map) ? $game_map.map_id : 0
setMapChanging(id,@maps[0]) if oldID!=0 && oldID!=@maps[0].map_id
setMapChanging(id, @maps[0]) if oldID != 0 && oldID != @maps[0].map_id
$game_map = @maps[0]
@maps[0].setup(id)
setMapsInRange
@@ -27,33 +27,33 @@ class PokemonMapFactory
end
def map
@mapIndex = 0 if !@mapIndex || @mapIndex<0
@mapIndex = 0 if !@mapIndex || @mapIndex < 0
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]
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]
end
raise "No maps in save file... (all maps empty; mapIndex=#{@mapIndex})"
end
def hasMap?(id)
for map in @maps
return true if map.map_id==id
@maps.each do |map|
return true if map.map_id == id
end
return false
end
def getMapIndex(id)
for i in 0...@maps.length
return i if @maps[i].map_id==id
@maps.length.times do |i|
return i if @maps[i].map_id == id
end
return -1
end
def getMap(id,add=true)
for map in @maps
return map if map.map_id==id
def getMap(id, add = true)
@maps.each do |map|
return map if map.map_id == id
end
map = Game_Map.new
map.setup(id)
@@ -62,31 +62,28 @@ class PokemonMapFactory
end
def getMapNoAdd(id)
return getMap(id,false)
return getMap(id, false)
end
def getNewMap(playerX,playerY)
def getNewMap(playerX, playerY)
id = $game_map.map_id
conns = MapFactoryHelper.getMapConnections
if conns[id]
for conn in conns[id]
mapidB = nil
newx = 0
newy = 0
if conn[0] == id
mapidB = conn[3]
mapB = MapFactoryHelper.getMapDims(conn[3])
newx = conn[4] - conn[1] + playerX
newy = conn[5] - conn[2] + playerY
else
mapidB = conn[0]
mapB = MapFactoryHelper.getMapDims(conn[0])
newx = conn[1] - conn[4] + playerX
newy = conn[2] - conn[5] + playerY
end
if newx >= 0 && newx < mapB[0] && newy >= 0 && newy < mapB[1]
return [getMap(mapidB), newx, newy]
end
MapFactoryHelper.eachConnectionForMap(id) do |conn|
mapidB = nil
newx = 0
newy = 0
if conn[0] == id
mapidB = conn[3]
mapB = MapFactoryHelper.getMapDims(conn[3])
newx = conn[4] - conn[1] + playerX
newy = conn[5] - conn[2] + playerY
else
mapidB = conn[0]
mapB = MapFactoryHelper.getMapDims(conn[0])
newx = conn[1] - conn[4] + playerX
newy = conn[2] - conn[5] + playerY
end
if newx >= 0 && newx < mapB[0] && newy >= 0 && newy < mapB[1]
return [getMap(mapidB), newx, newy]
end
end
return nil
@@ -96,16 +93,16 @@ class PokemonMapFactory
# their transfer to that map.
def setCurrentMap
return if $game_player.moving?
return if $game_map.valid?($game_player.x,$game_player.y)
newmap = getNewMap($game_player.x,$game_player.y)
return if $game_map.valid?($game_player.x, $game_player.y)
newmap = getNewMap($game_player.x, $game_player.y)
return if !newmap
oldmap=$game_map.map_id
if oldmap!=0 && oldmap!=newmap[0].map_id
setMapChanging(newmap[0].map_id,newmap[0])
oldmap = $game_map.map_id
if oldmap != 0 && oldmap != newmap[0].map_id
setMapChanging(newmap[0].map_id, newmap[0])
end
$game_map = newmap[0]
@mapIndex = getMapIndex($game_map.map_id)
$game_player.moveto(newmap[1],newmap[2])
$game_player.moveto(newmap[1], newmap[2])
$game_map.update
pbAutoplayOnTransition
$game_map.refresh
@@ -117,44 +114,41 @@ class PokemonMapFactory
return if @fixup
@fixup = true
id = $game_map.map_id
conns = MapFactoryHelper.getMapConnections
if conns[id]
for conn in conns[id]
if conn[0] == id
mapA = getMap(conn[0])
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
if hasMap?(conn[3]) || MapFactoryHelper.mapInRangeById?(conn[3], newdispx, newdispy)
mapB = getMap(conn[3])
mapB.display_x = newdispx if mapB.display_x != newdispx
mapB.display_y = newdispy if mapB.display_y != newdispy
end
else
mapA = getMap(conn[3])
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
if hasMap?(conn[0]) || MapFactoryHelper.mapInRangeById?(conn[0], newdispx, newdispy)
mapB = getMap(conn[0])
mapB.display_x = newdispx if mapB.display_x != newdispx
mapB.display_y = newdispy if mapB.display_y != newdispy
end
MapFactoryHelper.eachConnectionForMap(id) do |conn|
if conn[0] == id
mapA = getMap(conn[0])
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
if hasMap?(conn[3]) || MapFactoryHelper.mapInRangeById?(conn[3], newdispx, newdispy)
mapB = getMap(conn[3])
mapB.display_x = newdispx if mapB.display_x != newdispx
mapB.display_y = newdispy if mapB.display_y != newdispy
end
else
mapA = getMap(conn[3])
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
if hasMap?(conn[0]) || MapFactoryHelper.mapInRangeById?(conn[0], newdispx, newdispy)
mapB = getMap(conn[0])
mapB.display_x = newdispx if mapB.display_x != newdispx
mapB.display_y = newdispy if mapB.display_y != newdispy
end
end
end
@fixup = false
end
def setMapChanging(newID,newMap)
Events.onMapChanging.trigger(self,newID,newMap)
def setMapChanging(newID, newMap)
EventHandlers.trigger(:on_leave_map, newID, newMap)
end
def setMapChanged(prevMap)
Events.onMapChange.trigger(self,prevMap)
EventHandlers.trigger(:on_enter_map, prevMap)
@mapChanged = true
end
def setSceneStarted(scene)
Events.onMapSceneChange.trigger(self,scene,@mapChanged)
EventHandlers.trigger(:on_map_or_spriteset_change, scene, @mapChanged)
@mapChanged = false
end
@@ -175,90 +169,85 @@ class PokemonMapFactory
# Check passability of tile
if thisEvent.is_a?(Game_Player)
return false unless ($DEBUG && Input.press?(Input::CTRL)) ||
map.passable?(x, y, 0, thisEvent)
map.passable?(x, y, 0, thisEvent)
else
return false unless map.passable?(x, y, 0, thisEvent)
end
# 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)
return false if !event.through && event.character_name != ""
end
# Check passability of player
if !thisEvent.is_a?(Game_Player)
if $game_map.map_id == mapID && $game_player.x == x && $game_player.y == y
return false if !$game_player.through && $game_player.character_name != ""
end
if !thisEvent.is_a?(Game_Player) &&
$game_map.map_id == mapID && $game_player.x == x && $game_player.y == y &&
!$game_player.through && $game_player.character_name != ""
return false
end
return true
end
# Only used by dependent events
def isPassableStrict?(mapID,x,y,thisEvent=nil)
def isPassableStrict?(mapID, x, y, thisEvent = nil)
thisEvent = $game_player if !thisEvent
map = getMapNoAdd(mapID)
return false if !map
return false if !map.valid?(x,y)
return false if !map.valid?(x, y)
return true if thisEvent.through
if thisEvent==$game_player
if !($DEBUG && Input.press?(Input::CTRL))
return false if !map.passableStrict?(x,y,0,thisEvent)
if thisEvent == $game_player
if !($DEBUG && Input.press?(Input::CTRL)) && !map.passableStrict?(x, y, 0, thisEvent)
return false
end
else
return false if !map.passableStrict?(x,y,0,thisEvent)
elsif !map.passableStrict?(x, y, 0, thisEvent)
return false
end
for event in map.events.values
map.events.each_value do |event|
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
return true
end
def getTerrainTag(mapid,x,y,countBridge=false)
def getTerrainTag(mapid, x, y, countBridge = false)
map = getMapNoAdd(mapid)
return map.terrain_tag(x,y,countBridge)
return map.terrain_tag(x, y, countBridge)
end
# NOTE: Assumes the event is 1x1 tile in size. Only returns one terrain tag.
def getFacingTerrainTag(dir=nil,event=nil)
tile = getFacingTile(dir,event)
def getFacingTerrainTag(dir = nil, event = nil)
tile = getFacingTile(dir, event)
return GameData::TerrainTag.get(:None) if !tile
return getTerrainTag(tile[0],tile[1],tile[2])
return getTerrainTag(tile[0], tile[1], tile[2])
end
def getTerrainTagFromCoords(mapid,x,y,countBridge=false)
tile = getRealTilePos(mapid,x,y)
def getTerrainTagFromCoords(mapid, x, y, countBridge = false)
tile = getRealTilePos(mapid, x, y)
return GameData::TerrainTag.get(:None) if !tile
return getTerrainTag(tile[0],tile[1],tile[2])
return getTerrainTag(tile[0], tile[1], tile[2])
end
def areConnected?(mapID1, mapID2)
return true if mapID1 == mapID2
conns = MapFactoryHelper.getMapConnections
if conns[mapID1]
for conn in conns[mapID1]
return true if conn[0] == mapID2 || conn[3] == mapID2
end
MapFactoryHelper.eachConnectionForMap(mapID1) do |conn|
return true if conn[0] == mapID2 || conn[3] == mapID2
end
return false
end
# Returns the coordinate change to go from this position to other position
def getRelativePos(thisMapID, thisX, thisY, otherMapID, otherX, otherY)
if thisMapID == otherMapID # Both events share the same map
return [otherX - thisX, otherY - thisY]
end
conns = MapFactoryHelper.getMapConnections
if conns[thisMapID]
for conn in conns[thisMapID]
if conn[0] == otherMapID
posX = thisX + conn[1] - conn[4] + otherX
posY = thisY + conn[2] - conn[5] + otherY
return [posX, posY]
elsif conn[1] == otherMapID
posX = thisX + conn[4] - conn[1] + otherX
posY = thisY + conn[5] - conn[2] + otherY
return [posX, posY]
end
MapFactoryHelper.eachConnectionForMap(thisMapID) do |conn|
if conn[0] == otherMapID
posX = conn[4] - conn[1] + otherX - thisX
posY = conn[5] - conn[2] + otherY - thisY
return [posX, posY]
elsif conn[3] == otherMapID
posX = conn[1] - conn[4] + otherX - thisX
posY = conn[2] - conn[5] + otherY - thisY
return [posX, posY]
end
end
return [0, 0]
@@ -267,38 +256,37 @@ class PokemonMapFactory
# Gets the distance from this event to another event. Example: If this event's
# coordinates are (2,5) and the other event's coordinates are (5,1), returns
# the array (3,-4), because (5-2=3) and (1-5=-4).
def getThisAndOtherEventRelativePos(thisEvent,otherEvent)
return [0,0] if !thisEvent || !otherEvent
return getRelativePos(
thisEvent.map.map_id,thisEvent.x,thisEvent.y,
otherEvent.map.map_id,otherEvent.x,otherEvent.y)
def getThisAndOtherEventRelativePos(thisEvent, otherEvent)
return [0, 0] if !thisEvent || !otherEvent
return getRelativePos(thisEvent.map.map_id, thisEvent.x, thisEvent.y,
otherEvent.map.map_id, otherEvent.x, otherEvent.y)
end
def getThisAndOtherPosRelativePos(thisEvent,otherMapID,otherX,otherY)
return [0,0] if !thisEvent
return getRelativePos(
thisEvent.map.map_id,thisEvent.x,thisEvent.y,otherMapID,otherX,otherY)
def getThisAndOtherPosRelativePos(thisEvent, otherMapID, otherX, otherY)
return [0, 0] if !thisEvent
return getRelativePos(thisEvent.map.map_id, thisEvent.x, thisEvent.y,
otherMapID, otherX, otherY)
end
# Unused
def getOffsetEventPos(event,xOffset,yOffset)
def getOffsetEventPos(event, xOffset, yOffset)
event = $game_player if !event
return nil if !event
return getRealTilePos(event.map.map_id,event.x+xOffset,event.y+yOffset)
return getRealTilePos(event.map.map_id, event.x + xOffset, event.y + yOffset)
end
# NOTE: Assumes the event is 1x1 tile in size. Only returns one tile.
def getFacingTile(direction=nil,event=nil,steps=1)
event = $game_player if event==nil
return [0,0,0] if !event
def getFacingTile(direction = nil, event = nil, steps = 1)
event = $game_player if event.nil?
return [0, 0, 0] if !event
x = event.x
y = event.y
id = event.map.map_id
direction = event.direction if direction==nil
return getFacingTileFromPos(id,x,y,direction,steps)
direction = event.direction if direction.nil?
return getFacingTileFromPos(id, x, y, direction, steps)
end
def getFacingTileFromPos(mapID,x,y,direction=0,steps=1)
def getFacingTileFromPos(mapID, x, y, direction = 0, steps = 1)
id = mapID
case direction
when 1
@@ -322,38 +310,35 @@ class PokemonMapFactory
x += steps
y -= steps
else
return [id,x,y]
return [id, x, y]
end
return getRealTilePos(mapID,x,y)
return getRealTilePos(mapID, x, y)
end
def getRealTilePos(mapID, x, y)
id = mapID
return [id, x, y] if getMapNoAdd(id).valid?(x, y)
conns = MapFactoryHelper.getMapConnections
if conns[id]
for conn in conns[id]
if conn[0] == id
newX = x + conn[4] - conn[1]
newY = y + conn[5] - conn[2]
next if newX < 0 || newY < 0
dims = MapFactoryHelper.getMapDims(conn[3])
next if newX >= dims[0] || newY >= dims[1]
return [conn[3], newX, newY]
else
newX = x + conn[1] - conn[4]
newY = y + conn[2] - conn[5]
next if newX < 0 || newY < 0
dims = MapFactoryHelper.getMapDims(conn[0])
next if newX >= dims[0] || newY >= dims[1]
return [conn[0], newX, newY]
end
MapFactoryHelper.eachConnectionForMap(id) do |conn|
if conn[0] == id
newX = x + conn[4] - conn[1]
newY = y + conn[5] - conn[2]
next if newX < 0 || newY < 0
dims = MapFactoryHelper.getMapDims(conn[3])
next if newX >= dims[0] || newY >= dims[1]
return [conn[3], newX, newY]
else
newX = x + conn[1] - conn[4]
newY = y + conn[2] - conn[5]
next if newX < 0 || newY < 0
dims = MapFactoryHelper.getMapDims(conn[0])
next if newX >= dims[0] || newY >= dims[1]
return [conn[0], newX, newY]
end
end
return nil
end
def getFacingCoords(x,y,direction=0,steps=1)
def getFacingCoords(x, y, direction = 0, steps = 1)
case direction
when 1
x -= steps
@@ -376,36 +361,26 @@ class PokemonMapFactory
x += steps
y -= steps
end
return [x,y]
return [x, y]
end
def updateMaps(scene)
updateMapsInternal
$MapFactory.setSceneStarted(scene) if @mapChanged
$map_factory.setSceneStarted(scene) if @mapChanged
end
def updateMapsInternal
return if $game_player.moving?
if !MapFactoryHelper.hasConnections?($game_map.map_id)
return if @maps.length==1
for i in 0...@maps.length
@maps[i] = nil if $game_map.map_id!=@maps[i].map_id
end
@maps.compact!
return if @maps.length == 1
@maps.delete_if { |map| $game_map.map_id != map.map_id }
@mapIndex = getMapIndex($game_map.map_id)
return
end
setMapsInRange
deleted = false
for i in 0...@maps.length
next if MapFactoryHelper.mapInRange?(@maps[i])
@maps[i] = nil
deleted = true
end
if deleted
@maps.compact!
@mapIndex = getMapIndex($game_map.map_id)
end
old_num_maps = @maps.length
@maps.delete_if { |map| !MapFactoryHelper.mapInRange?(map) }
@mapIndex = getMapIndex($game_map.map_id) if @maps.length != old_num_maps
end
end
@@ -465,6 +440,12 @@ module MapFactoryHelper
return conns[id] ? true : false
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
def self.getMapDims(id)
# Create cache if doesn't exist
@@ -473,9 +454,9 @@ module MapFactoryHelper
if !@@MapDims[id]
begin
map = load_data(sprintf("Data/Map%03d.rxdata", id))
@@MapDims[id] = [map.width,map.height]
@@MapDims[id] = [map.width, map.height]
rescue
@@MapDims[id] = [0,0]
@@MapDims[id] = [0, 0]
end
end
# Return map in cache
@@ -484,11 +465,11 @@ module MapFactoryHelper
# Returns the X or Y coordinate of an edge on the map with id.
# Considers the special strings "N","W","E","S"
def self.getMapEdge(id,edge)
return 0 if edge=="N" || edge=="W"
def self.getMapEdge(id, edge)
return 0 if ["N", "W"].include?(edge)
dims = getMapDims(id) # Get dimensions
return dims[0] if edge=="E"
return dims[1] if edge=="S"
return dims[0] if edge == "E"
return dims[1] if edge == "S"
return dims[0] # real dimension (use width)
end
@@ -498,18 +479,18 @@ module MapFactoryHelper
dispy = map.display_y
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 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 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 true
end
def self.mapInRangeById?(id,dispx,dispy)
def self.mapInRangeById?(id, dispx, dispy)
range = 6 # Number of tiles
dims = MapFactoryHelper.getMapDims(id)
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 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 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 true
end
end
@@ -519,8 +500,8 @@ end
#===============================================================================
# Unused
def updateTilesets
maps = $MapFactory.maps
for map in maps
map.updateTileset if map
maps = $map_factory.maps
maps.each do |map|
map&.updateTileset
end
end

View File

@@ -6,13 +6,15 @@ class Game_Character
attr_reader :y
attr_reader :real_x
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 :height
attr_accessor :sprite_size
attr_reader :tile_id
attr_accessor :character_name
attr_accessor :character_hue
attr_reader :opacity
attr_accessor :opacity
attr_reader :blend_type
attr_accessor :direction
attr_accessor :pattern
@@ -26,7 +28,7 @@ class Game_Character
attr_accessor :walk_anime
attr_writer :bob_height
def initialize(map=nil)
def initialize(map = nil)
@map = map
@id = 0
@original_x = 0
@@ -35,6 +37,8 @@ class Game_Character
@y = 0
@real_x = 0
@real_y = 0
@x_offset = 0
@y_offset = 0
@width = 1
@height = 1
@sprite_size = [Game_Map::TILE_WIDTH, Game_Map::TILE_HEIGHT]
@@ -73,10 +77,14 @@ class Game_Character
@bob_height = 0
@wait_count = 0
@moved_this_frame = false
@moveto_happened = false
@locked = false
@prelock_direction = 0
end
def x_offset; return @x_offset || 0; end
def y_offset; return @y_offset || 0; end
def at_coordinate?(check_x, check_y)
return check_x >= @x && check_x < @x + @width &&
check_y > @y - @height && check_y <= @y
@@ -88,15 +96,15 @@ class Game_Character
end
def each_occupied_tile
for i in @x...(@x + @width)
for j in (@y - @height + 1)..@y
(@x...(@x + @width)).each do |i|
((@y - @height + 1)..@y).each do |j|
yield i, j
end
end
end
def move_speed=(val)
return if val==@move_speed
return if val == @move_speed
@move_speed = val
# @move_speed_real is the number of quarter-pixels to move each frame. There
# are 128 quarter-pixels per tile. By default, it is calculated from
@@ -107,7 +115,7 @@ class Game_Character
# 4 => 25.6 # 5 frames per tile - running speed (2x walking speed)
# 5 => 32 # 4 frames per tile - cycling speed (1.25x running speed)
# 6 => 64 # 2 frames per tile
self.move_speed_real = (val == 6) ? 64 : (val == 5) ? 32 : (2 ** (val + 1)) * 0.8
self.move_speed_real = (val == 6) ? 64 : (val == 5) ? 32 : (2**(val + 1)) * 0.8
end
def move_speed_real
@@ -120,7 +128,7 @@ class Game_Character
end
def jump_speed_real
self.jump_speed_real = (2 ** (3 + 1)) * 0.8 if !@jump_speed_real # 3 is walking speed
self.jump_speed_real = (2**(3 + 1)) * 0.8 if !@jump_speed_real # 3 is walking speed
return @jump_speed_real
end
@@ -129,7 +137,7 @@ class Game_Character
end
def move_frequency=(val)
return if val==@move_frequency
return if val == @move_frequency
@move_frequency = val
# @move_frequency_real is the number of frames to wait between each action
# in a move route (not forced). Specifically, this is the number of frames
@@ -142,7 +150,7 @@ class Game_Character
# 4 => 64 # 1.6 seconds
# 5 => 30 # 0.75 seconds
# 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
def move_frequency_real
@@ -199,19 +207,30 @@ class Game_Character
def calculate_bush_depth
if @tile_id > 0 || @always_on_top || jumping?
@bush_depth = 0
else
deep_bush = regular_bush = false
xbehind = @x + (@direction == 4 ? 1 : @direction == 6 ? -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)
if this_map[0].deepBush?(this_map[1], this_map[2]) && self.map.deepBush?(xbehind, ybehind)
@bush_depth = Game_Map::TILE_HEIGHT
elsif !moving? && this_map[0].bush?(this_map[1], this_map[2])
@bush_depth = 12
else
@bush_depth = 0
end
return
end
xbehind = @x + (@direction == 4 ? 1 : @direction == 6 ? -1 : 0)
ybehind = @y + (@direction == 8 ? 1 : @direction == 2 ? -1 : 0)
this_map = (self.map.valid?(@x, @y)) ? [self.map, @x, @y] : $map_factory&.getNewMap(@x, @y)
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
elsif this_map && this_map[0].bush?(this_map[1], this_map[2]) && !moving?
@bush_depth = 12
else
@bush_depth = 0
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
#=============================================================================
@@ -229,12 +248,13 @@ class Game_Character
return false unless self.map.passable?(x, y, d, self)
return false unless self.map.passable?(new_x, new_y, 10 - d, self)
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
return false if self != $game_player || event.character_name != ""
end
if $game_player.x == new_x && $game_player.y == new_y
return false if !$game_player.through && @character_name != ""
if $game_player.x == new_x && $game_player.y == new_y &&
!$game_player.through && @character_name != ""
return false
end
return true
end
@@ -243,24 +263,24 @@ class Game_Character
case dir
when 2, 8 # Down, up
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)
end
return true
when 4, 6 # Left, right
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)
end
return true
when 1, 3 # Down diagonals
# Treated as moving down first and then horizontally, because that
# 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)
end
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)
end
return true
@@ -268,12 +288,12 @@ class Game_Character
# Treated as moving horizontally first and then up, because that describes
# which tiles the character's feet touch
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)
end
x_offset = (dir == 9) ? 1 : -1
for i in start_x...(start_x + @width)
return false if !passable?(i + x_offset, start_y - @height + 1, 8, strict)
x_tile_offset = (dir == 9) ? 1 : -1
(start_x...(start_x + @width)).each do |i|
return false if !passable?(i + x_tile_offset, start_y - @height + 1, 8, strict)
end
return true
end
@@ -288,13 +308,14 @@ class Game_Character
# Screen position of the character
#=============================================================================
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 += self.x_offset
return ret
end
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
return ret
end
@@ -307,8 +328,9 @@ class Game_Character
else
jump_fraction = ((@jump_distance_left / @jump_distance) - 0.5).abs # 0.5 to 0 to 0.5
end
ret += @jump_peak * (4 * jump_fraction**2 - 1)
ret += @jump_peak * ((4 * (jump_fraction**2)) - 1)
end
ret += self.y_offset
return ret
end
@@ -317,7 +339,7 @@ class Game_Character
z = screen_y_ground
if @tile_id > 0
begin
return z + self.map.priorities[@tile_id] * 32
return z + (self.map.priorities[@tile_id] * 32)
rescue
raise "Event's graphic is an out-of-range tile (event #{@id}, map #{self.map.map_id})"
end
@@ -345,7 +367,7 @@ class Game_Character
end
def force_move_route(move_route)
if @original_move_route == nil
if @original_move_route.nil?
@original_move_route = @move_route
@original_move_route_index = @move_route_index
end
@@ -363,14 +385,15 @@ class Game_Character
@real_x = @x * Game_Map::REAL_RES_X
@real_y = @y * Game_Map::REAL_RES_Y
@prelock_direction = 0
@moveto_happened = true
calculate_bush_depth
triggerLeaveTile
end
def triggerLeaveTile
if @oldX && @oldY && @oldMap &&
(@oldX!=self.x || @oldY!=self.y || @oldMap!=self.map.map_id)
Events.onLeaveTile.trigger(self,self,@oldMap,@oldX,@oldY)
(@oldX != self.x || @oldY != self.y || @oldMap != self.map.map_id)
EventHandlers.trigger(:on_leave_tile, self, @oldMap, @oldX, @oldY)
end
@oldX = self.x
@oldY = self.y
@@ -394,8 +417,8 @@ class Game_Character
end
def move_type_toward_player
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)
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))
if sx.abs + sy.abs >= 20
move_random
return
@@ -617,21 +640,23 @@ class Game_Character
end
end
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
if xrange<0
dirs.push(1); dirs.push(2)
elsif xrange>0
if xrange < 0
dirs.push(1)
dirs.push(2)
elsif xrange > 0
dirs.push(1) if @x > @original_x - xrange
dirs.push(2) if @x < @original_x + xrange
end
if yrange<0
dirs.push(0); dirs.push(3)
elsif yrange>0
if yrange < 0
dirs.push(0)
dirs.push(3)
elsif yrange > 0
dirs.push(0) if @y < @original_y + yrange
dirs.push(3) if @y > @original_y - yrange
end
return if dirs.length==0
return if dirs.length == 0
case dirs[rand(dirs.length)]
when 0 then move_down(false)
when 1 then move_left(false)
@@ -640,17 +665,17 @@ class Game_Character
end
end
def move_random_UD(range=-1)
move_random_range(0,range)
def move_random_UD(range = -1)
move_random_range(0, range)
end
def move_random_LR(range=-1)
move_random_range(range,0)
def move_random_LR(range = -1)
move_random_range(range, 0)
end
def move_toward_player
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)
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))
return if sx == 0 && sy == 0
abs_sx = sx.abs
abs_sy = sy.abs
@@ -671,8 +696,8 @@ class Game_Character
end
def move_away_from_player
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)
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))
return if sx == 0 && sy == 0
abs_sx = sx.abs
abs_sy = sy.abs
@@ -724,7 +749,7 @@ class Game_Character
end
@x = @x + x_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
@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
@@ -736,27 +761,24 @@ class Game_Character
@jump_count = Game_Map::REAL_RES_X / jump_speed_real # Number of frames to jump one tile
end
@stop_count = 0
if self.is_a?(Game_Player)
$PokemonTemp.dependentEvents.pbMoveDependentEvents
end
triggerLeaveTile
end
def jumpForward
case self.direction
when 2 then jump(0,1) # down
when 4 then jump(-1,0) # left
when 6 then jump(1,0) # right
when 8 then jump(0,-1) # up
when 2 then jump(0, 1) # down
when 4 then jump(-1, 0) # left
when 6 then jump(1, 0) # right
when 8 then jump(0, -1) # up
end
end
def jumpBackward
case self.direction
when 2 then jump(0,-1) # down
when 4 then jump(1,0) # left
when 6 then jump(-1,0) # right
when 8 then jump(0,1) # up
when 2 then jump(0, -1) # down
when 4 then jump(1, 0) # left
when 6 then jump(-1, 0) # right
when 8 then jump(0, 1) # up
end
end
@@ -814,8 +836,8 @@ class Game_Character
end
def turn_toward_player
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)
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))
return if sx == 0 && sy == 0
if sx.abs > sy.abs
(sx > 0) ? turn_left : turn_right
@@ -825,8 +847,8 @@ class Game_Character
end
def turn_away_from_player
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)
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))
return if sx == 0 && sy == 0
if sx.abs > sy.abs
(sx > 0) ? turn_right : turn_left
@@ -841,6 +863,8 @@ class Game_Character
def update
@moved_last_frame = @moved_this_frame
@stopped_last_frame = @stopped_this_frame
@moved_this_frame = false
@stopped_this_frame = false
if !$game_temp.in_menu
# Update command
update_command
@@ -905,12 +929,11 @@ class Game_Character
end
# End of a step, so perform events that happen at this time
if !jumping? && !moving?
Events.onStepTakenFieldMovement.trigger(self, self)
EventHandlers.trigger(:on_step_taken, self)
calculate_bush_depth
@stopped_this_frame = true
elsif !@moved_last_frame || @stopped_last_frame # Started a new step
calculate_bush_depth
@stopped_this_frame = false
end
# Increment animation counter
@anime_count += 1 if @walk_anime || @step_anime
@@ -920,8 +943,6 @@ class Game_Character
def update_stop
@anime_count += 1 if @step_anime
@stop_count += 1 if !@starting && !lock?
@moved_this_frame = false
@stopped_this_frame = false
end
def update_pattern

View File

@@ -6,7 +6,7 @@ class Game_Event < Game_Character
attr_reader :tempSwitches # Temporary self-switches
attr_accessor :need_refresh
def initialize(map_id, event, map=nil)
def initialize(map_id, event, map = nil)
super(map)
@map_id = map_id
@event = event
@@ -54,7 +54,7 @@ class Game_Event < Game_Character
end
def tsOn?(c)
return @tempSwitches && @tempSwitches[c]==true
return @tempSwitches && @tempSwitches[c] == true
end
def tsOff?(c)
@@ -62,17 +62,17 @@ class Game_Event < Game_Character
end
def setTempSwitchOn(c)
@tempSwitches[c]=true
@tempSwitches[c] = true
refresh
end
def setTempSwitchOff(c)
@tempSwitches[c]=false
@tempSwitches[c] = false
refresh
end
def isOff?(c)
return !$game_self_switches[[@map_id,@event.id,c]]
return !$game_self_switches[[@map_id, @event.id, c]]
end
def switchIsOn?(id)
@@ -87,31 +87,31 @@ class Game_Event < Game_Character
def variable
return nil if !$PokemonGlobal.eventvars
return $PokemonGlobal.eventvars[[@map_id,@event.id]]
return $PokemonGlobal.eventvars[[@map_id, @event.id]]
end
def setVariable(variable)
$PokemonGlobal.eventvars[[@map_id,@event.id]]=variable
$PokemonGlobal.eventvars[[@map_id, @event.id]] = variable
end
def varAsInt
return 0 if !$PokemonGlobal.eventvars
return $PokemonGlobal.eventvars[[@map_id,@event.id]].to_i
return $PokemonGlobal.eventvars[[@map_id, @event.id]].to_i
end
def expired?(secs=86400)
ontime=self.variable
time=pbGetTimeNow
return ontime && (time.to_i>ontime+secs)
def expired?(secs = 86_400)
ontime = self.variable
time = pbGetTimeNow
return ontime && (time.to_i > ontime + secs)
end
def expiredDays?(days=1)
ontime=self.variable.to_i
def expiredDays?(days = 1)
ontime = self.variable.to_i
return false if !ontime
now=pbGetTimeNow
elapsed=(now.to_i-ontime)/86400
elapsed+=1 if (now.to_i-ontime)%86400>(now.hour*3600+now.min*60+now.sec)
return elapsed>=days
now = pbGetTimeNow
elapsed = (now.to_i - ontime) / 86_400
elapsed += 1 if (now.to_i - ontime) % 86_400 > ((now.hour * 3600) + (now.min * 60) + now.sec)
return elapsed >= days
end
def cooledDown?(seconds)
@@ -141,12 +141,12 @@ class Game_Event < Game_Character
def pbCheckEventTriggerAfterTurning
return if $game_system.map_interpreter.running? || @starting
if @event.name[/trainer\((\d+)\)/i]
distance = $~[1].to_i
if @trigger==2 && pbEventCanReachPlayer?(self,$game_player,distance)
start if !jumping? && !over_trigger?
end
end
return if @trigger != 2 # Event touch
return if !@event.name[/(?:sight|trainer)\((\d+)\)/i]
distance = $~[1].to_i
return if !pbEventCanReachPlayer?(self, $game_player, distance)
return if jumping? || over_trigger?
start
end
def check_event_trigger_touch(dir)
@@ -168,11 +168,12 @@ class Game_Event < Game_Character
end
def check_event_trigger_auto
if @trigger == 2 # Event touch
if at_coordinate?($game_player.x, $game_player.y)
start if !jumping? && over_trigger?
case @trigger
when 2 # Event touch
if at_coordinate?($game_player.x, $game_player.y) && !jumping? && over_trigger?
start
end
elsif @trigger == 3 # Autorun
when 3 # Autorun
start
end
end
@@ -180,7 +181,7 @@ class Game_Event < Game_Character
def refresh
new_page = nil
unless @erased
for page in @event.pages.reverse
@event.pages.reverse.each do |page|
c = page.condition
next if c.switch1_valid && !switchIsOn?(c.switch1_id)
next if c.switch2_valid && !switchIsOn?(c.switch2_id)
@@ -196,7 +197,7 @@ class Game_Event < Game_Character
return if new_page == @page
@page = new_page
clear_starting
if @page == nil
if @page.nil?
@tile_id = 0
@character_name = ""
@character_hue = 0
@@ -242,15 +243,15 @@ class Game_Event < Game_Character
check_event_trigger_auto
end
def should_update?(recalc=false)
def should_update?(recalc = false)
return @to_update if !recalc
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]
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 < -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_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_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 true
end
@@ -258,6 +259,7 @@ class Game_Event < Game_Character
def update
@to_update = should_update?(true)
return if !@to_update
@moveto_happened = false
last_moving = moving?
super
if !moving? && last_moving
@@ -268,7 +270,7 @@ class Game_Event < Game_Character
refresh
end
check_event_trigger_auto
if @interpreter != nil
if @interpreter
unless @interpreter.running?
@interpreter.setup(@list, @event.id, @map_id)
end

View File

@@ -10,14 +10,16 @@ class Game_Player < Game_Character
attr_accessor :charsetData
attr_accessor :encounter_count
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_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
@@bobFrameSpeed = 1.0 / 15
def initialize(*arg)
super(*arg)
@lastdir=0
@lastdirframe=0
@bump_se=0
@lastdir = 0
@lastdirframe = 0
@bump_se = 0
end
def map
@@ -25,77 +27,190 @@ class Game_Player < Game_Character
return $game_map
end
def pbHasDependentEvents?
return $PokemonGlobal.dependentEvents.length>0
def map_id
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
def bump_into_object
return if @bump_se && @bump_se>0
pbSEPlay("Player bump")
@bump_se = Graphics.frame_rate/4
return if @bump_se && @bump_se > 0
pbSEPlay("Player bump") if !@move_route_forcing
@bump_se = Graphics.frame_rate / 4
end
def move_generic(dir, turn_enabled = true)
turn_generic(dir, true) if turn_enabled
if !$PokemonTemp.encounterTriggered
if !$game_temp.encounter_triggered
if can_move_in_direction?(dir)
x_offset = (dir == 4) ? -1 : (dir == 6) ? 1 : 0
y_offset = (dir == 8) ? -1 : (dir == 2) ? 1 : 0
return if pbLedge(x_offset, y_offset)
return if pbEndSurf(x_offset, y_offset)
turn_generic(dir, true)
if !$PokemonTemp.encounterTriggered
if !$game_temp.encounter_triggered
@x += x_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
end
elsif !check_event_trigger_touch(dir)
bump_into_object
end
end
$PokemonTemp.encounterTriggered = false
$game_temp.encounter_triggered = false
end
def turn_generic(dir, keep_enc_indicator = false)
old_direction = @direction
super(dir)
if @direction != old_direction && !@move_route_forcing && !pbMapInterpreterRunning?
Events.onChangeDirection.trigger(self, self)
$PokemonTemp.encounterTriggered = false if !keep_enc_indicator
EventHandlers.trigger(:on_player_change_direction)
$game_temp.encounter_triggered = false if !keep_enc_indicator
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 = []
# If event is running
return result if checkIfRunning && $game_system.map_interpreter.running?
# All event loops
for event in $game_map.events.values
next if !event.name[/trainer\((\d+)\)/i]
$game_map.events.each_value do |event|
next if !triggers.include?(event.trigger)
next if !event.name[/trainer\((\d+)\)/i] && (trainer_only || !event.name[/sight\((\d+)\)/i])
distance = $~[1].to_i
# If event coordinates and triggers are consistent
if pbEventCanReachPlayer?(event,self,distance) && triggers.include?(event.trigger)
# If starting determinant is front event (other than jumping)
result.push(event) if !event.jumping? && !event.over_trigger?
end
next if !pbEventCanReachPlayer?(event, self, distance)
next if event.jumping? || event.over_trigger?
result.push(event)
end
return result
end
def pbTriggeredCounterEvents(triggers,checkIfRunning=true)
def pbTriggeredCounterEvents(triggers, checkIfRunning = true)
result = []
# If event is running
return result if checkIfRunning && $game_system.map_interpreter.running?
# 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]
distance = $~[1].to_i
# If event coordinates and triggers are consistent
if pbEventFacesPlayer?(event,self,distance) && triggers.include?(event.trigger)
# If starting determinant is front event (other than jumping)
result.push(event) if !event.jumping? && !event.over_trigger?
end
next if !pbEventFacesPlayer?(event, self, distance)
next if event.jumping? || event.over_trigger?
result.push(event)
end
return result
end
@@ -105,25 +220,25 @@ class Game_Player < Game_Character
def pbCheckEventTriggerFromDistance(triggers)
ret = pbTriggeredTrainerEvents(triggers)
ret.concat(pbTriggeredCounterEvents(triggers))
return false if ret.length==0
for event in ret
return false if ret.length == 0
ret.each do |event|
event.start
end
return true
end
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)
end
def pbFacingEvent(ignoreInterpreter=false)
def pbFacingEvent(ignoreInterpreter = false)
return nil if $game_system.map_interpreter.running? && !ignoreInterpreter
# Check the tile in front of the player for events
new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
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.jumping? || event.over_trigger?
return event
@@ -132,7 +247,7 @@ class Game_Player < Game_Character
if $game_map.counter?(new_x, new_y)
new_x += (@direction == 6 ? 1 : @direction == 4 ? -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.jumping? || event.over_trigger?
return event
@@ -143,7 +258,7 @@ class Game_Player < Game_Character
def pbFacingTerrainTag(dir = nil)
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)
return $game_map.terrain_tag(facing[1], facing[2])
end
@@ -162,8 +277,8 @@ class Game_Player < Game_Character
# If coordinates are outside of map
return false if !$game_map.validLax?(new_x, new_y)
if !$game_map.valid?(new_x, new_y)
return false if !$MapFactory
return $MapFactory.isPassableFromEdge?(new_x, new_y)
return false if !$map_factory
return $map_factory.isPassableFromEdge?(new_x, new_y)
end
# If debug mode is ON and Ctrl key was pressed
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
#-----------------------------------------------------------------------------
def center(x, y)
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_x = (x * Game_Map::REAL_RES_X) - SCREEN_CENTER_X
self.map.display_y = (y * Game_Map::REAL_RES_Y) - SCREEN_CENTER_Y
end
#-----------------------------------------------------------------------------
@@ -185,9 +300,7 @@ class Game_Player < Game_Character
#-----------------------------------------------------------------------------
def moveto(x, y)
super
# Centering
center(x, y)
# Make encounter count
make_encounter_count
end
@@ -219,7 +332,7 @@ class Game_Player < Game_Character
# If event is running
return result if $game_system.map_interpreter.running?
# All event loops
for event in $game_map.events.values
$game_map.events.each_value do |event|
# If event coordinates and triggers are consistent
next if !event.at_coordinate?(@x, @y)
next if !triggers.include?(event.trigger)
@@ -243,33 +356,30 @@ class Game_Player < Game_Character
new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
return false if !$game_map.valid?(new_x, new_y)
# 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
next if !event.at_coordinate?(new_x, new_y)
next if !triggers.include?(event.trigger)
# If starting determinant is front event (other than jumping)
next if event.jumping? || event.over_trigger?
event.start
result = true
end
# If fitting event is not found
if result == false
# If front tile is a counter
if $game_map.counter?(new_x, new_y)
# Calculate coordinates of 1 tile further away
new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
return false if !$game_map.valid?(new_x, new_y)
# All event loops
for event in $game_map.events.values
# If event coordinates and triggers are consistent
next if !event.at_coordinate?(new_x, new_y)
next if !triggers.include?(event.trigger)
# If starting determinant is front event (other than jumping)
next if event.jumping? || event.over_trigger?
event.start
result = true
end
if result == false && $game_map.counter?(new_x, new_y)
# Calculate coordinates of 1 tile further away
new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
return false if !$game_map.valid?(new_x, new_y)
# All event loops
$game_map.events.each_value do |event|
next if !triggers.include?(event.trigger)
# If event coordinates and triggers are consistent
next if !event.at_coordinate?(new_x, new_y)
# If starting determinant is front event (other than jumping)
next if event.jumping? || event.over_trigger?
event.start
result = true
end
end
return result
@@ -284,16 +394,16 @@ class Game_Player < Game_Character
# All event loops
x_offset = (dir == 4) ? -1 : (dir == 6) ? 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
# If event coordinates and triggers are consistent
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
next if !pbEventCanReachPlayer?(event,self,distance)
next if !pbEventCanReachPlayer?(event, self, distance)
elsif event.name[/counter\((\d+)\)/i]
distance = $~[1].to_i
next if !pbEventFacesPlayer?(event,self,distance)
next if !pbEventFacesPlayer?(event, self, distance)
end
# If starting determinant is front event (other than jumping)
next if event.jumping? || event.over_trigger?
@@ -312,14 +422,18 @@ class Game_Player < Game_Character
super
update_screen_position(last_real_x, last_real_y)
# 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
@bump_se -= 1 if @bump_se && @bump_se>0
@bump_se -= 1 if @bump_se && @bump_se > 0
# Finish up dismounting from surfing
if $PokemonTemp.endSurf && !moving?
if $game_temp.ending_surf && !moving?
pbCancelVehicles
$PokemonTemp.surfJump = nil
$PokemonTemp.endSurf = false
$game_temp.surf_base_coords = nil
$game_temp.ending_surf = false
end
update_event_triggering
end
@@ -327,7 +441,7 @@ class Game_Player < Game_Character
def update_command_new
dir = Input.dir4
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
if @moved_last_frame ||
(dir > 0 && dir == @lastdir && Graphics.frame_count - @lastdirframe > Graphics.frame_rate / 20)
@@ -351,6 +465,64 @@ class Game_Player < Game_Character
@lastdir = dir
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
def update_screen_position(last_real_x, last_real_y)
return if self.map.scrolling? || !(@moved_last_frame || @moved_this_frame)
@@ -362,57 +534,57 @@ class Game_Player < Game_Character
return if moving?
# Try triggering events upon walking into them/in front of them
if @moved_this_frame
$PokemonTemp.dependentEvents.pbTurnDependentEvents
$game_temp.followers.turn_followers
result = pbCheckEventTriggerFromDistance([2])
# Event determinant is via touch of same position event
result |= check_event_trigger_here([1,2])
result |= check_event_trigger_here([1, 2])
# No events triggered, try other event triggers upon finishing a step
pbOnStepTaken(result)
end
# 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
check_event_trigger_here([0])
check_event_trigger_there([0,2])
check_event_trigger_there([0, 2])
end
end
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
if $game_player && $game_player.charsetData && !force
return nil if $game_player.charsetData[0] == $Trainer.character_ID &&
$game_player.charsetData[1] == charset &&
$game_player.charsetData[2] == outfit
end
$game_player.charsetData = [$Trainer.character_ID,charset,outfit] if $game_player
ret = meta[charset]
ret = meta[1] if nil_or_empty?(ret)
if pbResolveBitmap("Graphics/Characters/"+ret+"_"+outfit.to_s)
ret = ret+"_"+outfit.to_s
return nil if !force && $game_player&.charsetData &&
$game_player.charsetData[0] == trainer.character_ID &&
$game_player.charsetData[1] == charset &&
$game_player.charsetData[2] == outfit
$game_player.charsetData = [trainer.character_ID, charset, outfit] if $game_player
ret = charset
if pbResolveBitmap("Graphics/Characters/" + ret + "_" + outfit.to_s)
ret = ret + "_" + outfit.to_s
end
return ret
end
def pbUpdateVehicle
meta = GameData::Metadata.get_player($Trainer.character_ID)
if meta
charset = 1 # Regular graphic
if $PokemonGlobal.diving; charset = 5 # Diving graphic
elsif $PokemonGlobal.surfing; charset = 3 # Surfing graphic
elsif $PokemonGlobal.bicycle; charset = 2 # Bicycle graphic
end
newCharName = pbGetPlayerCharset(meta,charset)
$game_player.character_name = newCharName if newCharName
if $PokemonGlobal&.diving
$game_player.set_movement_type(:diving)
elsif $PokemonGlobal&.surfing
$game_player.set_movement_type(:surfing)
elsif $PokemonGlobal&.bicycle
$game_player.set_movement_type(:cycling)
else
$game_player.set_movement_type(:walking)
end
end
def pbCancelVehicles(destination=nil)
$PokemonGlobal.surfing = false
$PokemonGlobal.diving = false
def pbCancelVehicles(destination = nil, cancel_swimming = true)
$PokemonGlobal.surfing = false if cancel_swimming
$PokemonGlobal.diving = false if cancel_swimming
$PokemonGlobal.bicycle = false if !destination || !pbCanUseBike?(destination)
pbUpdateVehicle
end
@@ -420,14 +592,13 @@ end
def pbCanUseBike?(map_id)
map_metadata = GameData::MapMetadata.try_get(map_id)
return false if !map_metadata
return true if map_metadata.always_bicycle
val = map_metadata.can_bicycle || map_metadata.outdoor_map
return (val) ? true : false
return map_metadata.always_bicycle || map_metadata.can_bicycle || map_metadata.outdoor_map
end
def pbMountBike
return if $PokemonGlobal.bicycle
$PokemonGlobal.bicycle = true
$stats.cycle_count += 1
pbUpdateVehicle
bike_bgm = GameData::Metadata.get.bicycle_BGM
pbCueBGM(bike_bgm, 0.5) if bike_bgm

View File

@@ -56,7 +56,7 @@ class Game_CommonEvent
def refresh
# Create an interpreter for parallel process if necessary
if self.trigger == 2 && switchIsOn?(self.switch_id)
if @interpreter == nil
if @interpreter.nil?
@interpreter = Interpreter.new
end
else
@@ -67,15 +67,10 @@ class Game_CommonEvent
# * Frame Update
#-----------------------------------------------------------------------------
def update
# If parallel process is valid
if @interpreter != nil
# If not running
unless @interpreter.running?
# Set up event
@interpreter.setup(self.list, 0)
end
# Update interpreter
@interpreter.update
end
return if !@interpreter
# Set up event if interpreter is not running
@interpreter.setup(self.list, 0) if !@interpreter.running?
# Update interpreter
@interpreter.update
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
def dispose
@sprite.dispose if @sprite
@sprite&.dispose
end
def update
@sprite.update if @sprite
@sprite&.update
# If picture file name is different from current one
if @picture_name != @picture.name
# Remember file name to instance variables
@@ -19,16 +19,16 @@ class Sprite_Picture
# If file name is not empty
if @picture_name != ""
# Get picture graphic
@sprite=IconSprite.new(0,0,@viewport) if !@sprite
@sprite.setBitmap("Graphics/Pictures/"+@picture_name)
@sprite = IconSprite.new(0, 0, @viewport) if !@sprite
@sprite.setBitmap("Graphics/Pictures/" + @picture_name)
end
end
# If file name is empty
if @picture_name == ""
# Set sprite to invisible
if @sprite
@sprite.dispose if @sprite
@sprite=nil
@sprite&.dispose
@sprite = nil
end
return
end

View File

@@ -1,15 +1,15 @@
class Sprite_Timer
def initialize(viewport=nil)
@viewport=viewport
@timer=nil
@total_sec=nil
@disposed=false
def initialize(viewport = nil)
@viewport = viewport
@timer = nil
@total_sec = nil
@disposed = false
end
def dispose
@timer.dispose if @timer
@timer=nil
@disposed=true
@timer&.dispose
@timer = nil
@disposed = true
end
def disposed?
@@ -21,14 +21,14 @@ class Sprite_Timer
if $game_system.timer_working
@timer.visible = true if @timer
if !@timer
@timer=Window_AdvancedTextPokemon.newWithSize("",Graphics.width-120,0,120,64)
@timer.width=@timer.borderX+96
@timer.x=Graphics.width-@timer.width
@timer.viewport=@viewport
@timer.z=99998
@timer = Window_AdvancedTextPokemon.newWithSize("", Graphics.width - 120, 0, 120, 64)
@timer.width = @timer.borderX + 96
@timer.x = Graphics.width - @timer.width
@timer.viewport = @viewport
@timer.z = 99998
end
curtime=$game_system.timer / Graphics.frame_rate
curtime=0 if curtime<0
curtime = $game_system.timer / Graphics.frame_rate
curtime = 0 if curtime < 0
if curtime != @total_sec
# Calculate total number of seconds
@total_sec = curtime
@@ -38,8 +38,8 @@ class Sprite_Timer
@timer.text = _ISPRINTF("<ac>{1:02d}:{2:02d}", min, sec)
end
@timer.update
else
@timer.visible=false if @timer
elsif @timer
@timer.visible = false
end
end
end

View File

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

View File

@@ -2,17 +2,15 @@ class Sprite_Reflection
attr_reader :visible
attr_accessor :event
def initialize(sprite,event,viewport=nil)
def initialize(sprite, event, viewport = nil)
@rsprite = sprite
@sprite = nil
@event = event
@height = 0
@fixedheight = false
if @event && @event!=$game_player
if @event.name[/reflection\((\d+)\)/i]
@height = $~[1].to_i || 0
@fixedheight = true
end
if @event && @event != $game_player && @event.name[/reflection\((\d+)\)/i]
@height = $~[1].to_i || 0
@fixedheight = true
end
@viewport = viewport
@disposed = false
@@ -21,7 +19,7 @@ class Sprite_Reflection
def dispose
if !@disposed
@sprite.dispose if @sprite
@sprite&.dispose
@sprite = nil
@disposed = true
end
@@ -50,34 +48,35 @@ class Sprite_Reflection
# Just-in-time creation of sprite
@sprite = Sprite.new(@viewport) if !@sprite
if @sprite
x = @rsprite.x-@rsprite.ox
y = @rsprite.y-@rsprite.oy
x = @rsprite.x - @rsprite.ox
y = @rsprite.y - @rsprite.oy
y -= 32 if @rsprite.character.character_name[/offset/i]
@height = $PokemonGlobal.bridge if !@fixedheight
y += @height*16
y += @height * 16
width = @rsprite.src_rect.width
height = @rsprite.src_rect.height
@sprite.x = x+width/2
@sprite.y = y+height+height/2
@sprite.ox = width/2
@sprite.oy = height/2-2 # Hard-coded 2 pixel shift up
@sprite.oy -= @rsprite.character.bob_height*2
@sprite.x = x + (width / 2)
@sprite.y = y + height + (height / 2)
@sprite.ox = width / 2
@sprite.oy = (height / 2) - 2 # Hard-coded 2 pixel shift up
@sprite.oy -= @rsprite.character.bob_height * 2
@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_y = @rsprite.zoom_y
frame = (Graphics.frame_count%40)/10
frame = (Graphics.frame_count % 40) / 10
@sprite.zoom_x *= [1.0, 0.95, 1.0, 1.05][frame]
@sprite.angle = 180.0
@sprite.mirror = true
@sprite.bitmap = @rsprite.bitmap
@sprite.tone = @rsprite.tone
if @height>0
@sprite.color = Color.new(48,96,160,255) # Dark still water
if @height > 0
@sprite.color = Color.new(48, 96, 160, 255) # Dark still water
@sprite.opacity = @rsprite.opacity
@sprite.visible = !Settings::TIME_SHADING # Can't time-tone a colored sprite
else
@sprite.color = Color.new(224,224,224,96)
@sprite.opacity = @rsprite.opacity*3/4
@sprite.color = Color.new(224, 224, 224, 96)
@sprite.opacity = @rsprite.opacity * 3 / 4
@sprite.visible = true
end
@sprite.src_rect = @rsprite.src_rect

View File

@@ -2,7 +2,7 @@ class Sprite_SurfBase
attr_reader :visible
attr_accessor :event
def initialize(sprite,event,viewport=nil)
def initialize(sprite, event, viewport = nil)
@rsprite = sprite
@sprite = nil
@event = event
@@ -12,16 +12,16 @@ class Sprite_SurfBase
@divebitmap = AnimatedBitmap.new("Graphics/Characters/base_dive")
RPG::Cache.retain("Graphics/Characters/base_surf")
RPG::Cache.retain("Graphics/Characters/base_dive")
@cws = @surfbitmap.width/4
@chs = @surfbitmap.height/4
@cwd = @divebitmap.width/4
@chd = @divebitmap.height/4
@cws = @surfbitmap.width / 4
@chs = @surfbitmap.height / 4
@cwd = @divebitmap.width / 4
@chd = @divebitmap.height / 4
update
end
def dispose
return if @disposed
@sprite.dispose if @sprite
@sprite&.dispose
@sprite = nil
@surfbitmap.dispose
@divebitmap.dispose
@@ -59,20 +59,20 @@ class Sprite_SurfBase
cw = @cwd
ch = @chd
end
sx = @event.pattern_surf*cw
sy = ((@event.direction-2)/2)*ch
@sprite.src_rect.set(sx,sy,cw,ch)
if $PokemonTemp.surfJump
@sprite.x = ($PokemonTemp.surfJump[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
sx = @event.pattern_surf * cw
sy = ((@event.direction - 2) / 2) * ch
@sprite.src_rect.set(sx, sy, cw, ch)
if $game_temp.surf_base_coords
@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 = ((($game_temp.surf_base_coords[1] * Game_Map::REAL_RES_Y) - @event.map.display_y + 3) / 4) + (Game_Map::TILE_HEIGHT / 2) + 16
else
@sprite.x = @rsprite.x
@sprite.y = @rsprite.y
end
@sprite.ox = cw/2
@sprite.oy = ch-16 # Assume base needs offsetting
@sprite.ox = cw / 2
@sprite.oy = ch - 16 # Assume base needs offsetting
@sprite.oy -= @event.bob_height
@sprite.z = @event.screen_z(ch)-1
@sprite.z = @event.screen_z(ch) - 1
@sprite.zoom_x = @rsprite.zoom_x
@sprite.zoom_y = @rsprite.zoom_y
@sprite.tone = @rsprite.tone

View File

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

View File

@@ -1,29 +1,30 @@
# Unused
class ClippableSprite < Sprite_Character
def initialize(viewport,event,tilemap)
def initialize(viewport, event, tilemap)
@tilemap = tilemap
@_src_rect = Rect.new(0,0,0,0)
super(viewport,event)
@_src_rect = Rect.new(0, 0, 0, 0)
super(viewport, event)
end
def update
super
@_src_rect = self.src_rect
tmright = @tilemap.map_data.xsize*Game_Map::TILE_WIDTH-@tilemap.ox
echoln("x=#{self.x},ox=#{self.ox},tmright=#{tmright},tmox=#{@tilemap.ox}")
if @tilemap.ox-self.ox<-self.x
tmright = (@tilemap.map_data.xsize * Game_Map::TILE_WIDTH) - @tilemap.ox
echoln "x=#{self.x},ox=#{self.ox},tmright=#{tmright},tmox=#{@tilemap.ox}"
if @tilemap.ox - self.ox < -self.x
# clipped on left
diff = -self.x-@tilemap.ox+self.ox
self.src_rect = Rect.new(@_src_rect.x+diff,@_src_rect.y,
@_src_rect.width-diff,@_src_rect.height)
echoln("clipped out left: #{diff} #{@tilemap.ox-self.ox} #{self.x}")
elsif tmright-self.ox<self.x
diff = -self.x - @tilemap.ox + self.ox
self.src_rect = Rect.new(@_src_rect.x + diff, @_src_rect.y,
@_src_rect.width - diff, @_src_rect.height)
echoln "clipped out left: #{diff} #{@tilemap.ox - self.ox} #{self.x}"
elsif tmright - self.ox < self.x
# clipped on right
diff = self.x-tmright+self.ox
self.src_rect = Rect.new(@_src_rect.x,@_src_rect.y,
@_src_rect.width-diff,@_src_rect.height)
echoln("clipped out right: #{diff} #{tmright+self.ox} #{self.x}")
diff = self.x - tmright + self.ox
self.src_rect = Rect.new(@_src_rect.x, @_src_rect.y,
@_src_rect.width - diff, @_src_rect.height)
echoln "clipped out right: #{diff} #{tmright + self.ox} #{self.x}"
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
@@ -32,7 +33,7 @@ end
class Spriteset_Map
attr_reader :map
attr_accessor :tilemap
@@viewport0 = Viewport.new(0, 0, Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT) # Panorama
@@viewport0.z = -100
@@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.z = 500
def Spriteset_Map.viewport # For access by Spriteset_Global
def self.viewport # For access by Spriteset_Global
return @@viewport1
end
def initialize(map=nil)
def initialize(map = nil)
@map = (map) ? map : $game_map
@tilemap = TilemapLoader.new(@@viewport1)
@tilemap.tileset = pbGetTileset(@map.tileset_name)
for i in 0...7
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
$scene.map_renderer.add_tileset(@map.tileset_name)
@map.autotile_names.each { |filename| $scene.map_renderer.add_autotile(filename) }
$scene.map_renderer.add_extra_autotiles(@map.tileset_id)
@panorama = AnimatedPlane.new(@@viewport0)
@fog = AnimatedPlane.new(@@viewport1)
@fog.z = 3000
@character_sprites = []
for i in @map.events.keys.sort
sprite = Sprite_Character.new(@@viewport1,@map.events[i])
@map.events.keys.sort.each do |i|
sprite = Sprite_Character.new(@@viewport1, @map.events[i])
@character_sprites.push(sprite)
end
@weather = RPG::Weather.new(@@viewport1)
pbOnSpritesetCreate(self,@@viewport1)
EventHandlers.trigger(:on_new_spriteset_map, self, @@viewport1)
update
end
def dispose
@tilemap.tileset.dispose
for i in 0...7
@tilemap.autotiles[i].dispose
if $scene.is_a?(Scene_Map)
$scene.map_renderer.remove_tileset(@map.tileset_name)
@map.autotile_names.each { |filename| $scene.map_renderer.remove_autotile(filename) }
$scene.map_renderer.remove_extra_autotiles(@map.tileset_id)
end
@tilemap.dispose
@panorama.dispose
@fog.dispose
for sprite in @character_sprites
sprite.dispose
end
@character_sprites.each { |sprite| sprite.dispose }
@weather.dispose
@tilemap = nil
@panorama = nil
@fog = nil
@character_sprites.clear
@@ -96,47 +88,44 @@ class Spriteset_Map
end
def update
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_hue = @map.panorama_hue
@panorama.setPanorama(nil) if @panorama.bitmap!=nil
@panorama.setPanorama(@panorama_name,@panorama_hue) if @panorama_name!=""
@panorama.set_panorama(nil) if !@panorama.bitmap.nil?
@panorama.set_panorama(@panorama_name, @panorama_hue) if !nil_or_empty?(@panorama_name)
Graphics.frame_reset
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_hue = @map.fog_hue
@fog.setFog(nil) if @fog.bitmap!=nil
@fog.setFog(@fog_name,@fog_hue) if @fog_name!=""
@fog.set_fog(nil) if !@fog.bitmap.nil?
@fog.set_fog(@fog_name, @fog_hue) if !nil_or_empty?(@fog_name)
Graphics.frame_reset
end
tmox = (@map.display_x/Game_Map::X_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)
tmox = (@map.display_x / Game_Map::X_SUBPIXELS).round
tmoy = (@map.display_y / Game_Map::Y_SUBPIXELS).round
@@viewport1.rect.set(0, 0, Graphics.width, Graphics.height)
@@viewport1.ox = 0
@@viewport1.oy = 0
@@viewport1.ox += $game_screen.shake
@tilemap.update
@panorama.ox = tmox/2
@panorama.oy = tmoy/2
@fog.ox = tmox+@map.fog_ox
@fog.oy = tmoy+@map.fog_oy
@fog.zoom_x = @map.fog_zoom/100.0
@fog.zoom_y = @map.fog_zoom/100.0
@panorama.ox = tmox / 2
@panorama.oy = tmoy / 2
@fog.ox = tmox + @map.fog_ox
@fog.oy = tmoy + @map.fog_oy
@fog.zoom_x = @map.fog_zoom / 100.0
@fog.zoom_y = @map.fog_zoom / 100.0
@fog.opacity = @map.fog_opacity
@fog.blend_type = @map.fog_blend_type
@fog.tone = @map.fog_tone
@panorama.update
@fog.update
for sprite in @character_sprites
@character_sprites.each do |sprite|
sprite.update
end
if self.map!=$game_map
@weather.fade_in(:None, 0, 20)
else
if self.map == $game_map
@weather.fade_in($game_screen.weather_type, $game_screen.weather_max, $game_screen.weather_duration)
else
@weather.fade_in(:None, 0, 20)
end
@weather.ox = tmox
@weather.oy = tmoy

View File

@@ -5,7 +5,7 @@ automatically when its animation is finished.
Used for grass rustling and so forth.
=end
class AnimationSprite < RPG::Sprite
def initialize(animID,map,tileX,tileY,viewport=nil,tinting=false,height=3)
def initialize(animID, map, tileX, tileY, viewport = nil, tinting = false, height = 3)
super(viewport)
@tileX = tileX
@tileY = tileY
@@ -14,13 +14,13 @@ class AnimationSprite < RPG::Sprite
@map = map
setCoords
pbDayNightTint(self) if tinting
self.animation($data_animations[animID],true,height)
self.animation($data_animations[animID], true, height)
end
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.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
end
@@ -41,46 +41,39 @@ end
class Spriteset_Map
alias _animationSprite_initialize initialize
alias _animationSprite_update update
alias _animationSprite_dispose dispose
alias _animationSprite_initialize initialize unless private_method_defined?(:_animationSprite_initialize)
alias _animationSprite_update update unless method_defined?(:_animationSprite_update)
alias _animationSprite_dispose dispose unless method_defined?(:_animationSprite_dispose)
def initialize(map=nil)
@usersprites=[]
def initialize(map = nil)
@usersprites = []
_animationSprite_initialize(map)
end
def addUserAnimation(animID,x,y,tinting=false,height=3)
sprite=AnimationSprite.new(animID,$game_map,x,y,@@viewport1,tinting,height)
def addUserAnimation(animID, x, y, tinting = false, height = 3)
sprite = AnimationSprite.new(animID, self.map, x, y, @@viewport1, tinting, height)
addUserSprite(sprite)
return sprite
end
def addUserSprite(sprite)
for i in 0...@usersprites.length
if @usersprites[i]==nil || @usersprites[i].disposed?
@usersprites[i]=sprite
return
end
def addUserSprite(new_sprite)
@usersprites.each_with_index do |sprite, i|
next if sprite && !sprite.disposed?
@usersprites[i] = new_sprite
return
end
@usersprites.push(sprite)
@usersprites.push(new_sprite)
end
def dispose
_animationSprite_dispose
for i in 0...@usersprites.length
@usersprites[i].dispose
end
@usersprites.each { |sprite| sprite.dispose }
@usersprites.clear
end
def update
return if @tilemap.disposed?
pbDayNightTint(@tilemap)
@@viewport3.tone.set(0,0,0,0)
@@viewport3.tone.set(0, 0, 0, 0)
_animationSprite_update
for i in 0...@usersprites.length
@usersprites[i].update if !@usersprites[i].disposed?
end
@usersprites.each { |sprite| sprite.update if !sprite.disposed? }
end
end

View File

@@ -7,19 +7,19 @@
class Sprite_Shadow < RPG::Sprite
attr_accessor :character
def initialize(viewport, character = nil,params=[])
def initialize(viewport, character = nil, params = [])
super(viewport)
@source = params[0]
@anglemin = (params.size>1) ? params[1] : 0
@anglemax = (params.size>2) ? params[2] : 0
@self_opacity = (params.size>4) ? params[4] : 100
@distancemax = (params.size>3) ? params[3] : 350
@anglemin = (params.size > 1) ? params[1] : 0
@anglemax = (params.size > 2) ? params[2] : 0
@self_opacity = (params.size > 4) ? params[4] : 100
@distancemax = (params.size > 3) ? params[3] : 350
@character = character
update
end
def dispose
@chbitmap.dispose if @chbitmap
@chbitmap&.dispose
super
end
@@ -35,19 +35,18 @@ class Sprite_Shadow < RPG::Sprite
@tile_id = @character.tile_id
@character_name = @character.character_name
@character_hue = @character.character_hue
@chbitmap&.dispose
if @tile_id >= 384
@chbitmap.dispose if @chbitmap
@chbitmap = pbGetTileBitmap(@character.map.tileset_name,
@tile_id, @character.character_hue)
@tile_id, @character.character_hue)
self.src_rect.set(0, 0, 32, 32)
@ch = 32
@cw = 32
self.ox = 16
self.oy = 32
else
@chbitmap.dispose if @chbitmap
@chbitmap = AnimatedBitmap.new(
'Graphics/Characters/'+@character.character_name,@character.character_hue)
@chbitmap = AnimatedBitmap.new("Graphics/Characters/" + @character.character_name,
@character.character_hue)
@cw = @chbitmap.width / 4
@ch = @chbitmap.height / 4
self.ox = @cw / 2
@@ -75,8 +74,8 @@ class Sprite_Shadow < RPG::Sprite
self.src_rect.set(sx, sy, @cw, @ch)
end
self.x = ScreenPosHelper.pbScreenX(@character)
self.y = ScreenPosHelper.pbScreenY(@character)-5
self.z = ScreenPosHelper.pbScreenZ(@character,@ch)-1
self.y = ScreenPosHelper.pbScreenY(@character) - 5
self.z = ScreenPosHelper.pbScreenZ(@character, @ch) - 1
self.zoom_x = ScreenPosHelper.pbScreenZoomX(@character)
self.zoom_y = ScreenPosHelper.pbScreenZoomY(@character)
self.blend_type = @character.blend_type
@@ -89,10 +88,10 @@ class Sprite_Shadow < RPG::Sprite
@deltax = ScreenPosHelper.pbScreenX(@source) - self.x
@deltay = ScreenPosHelper.pbScreenY(@source) - self.y
self.color = Color.new(0, 0, 0)
@distance = ((@deltax ** 2) + (@deltay ** 2))
self.opacity = @self_opacity * 13000 / ((@distance * 370 / @distancemax) + 6000)
@distance = ((@deltax**2) + (@deltay**2))
self.opacity = @self_opacity * 13_000 / ((@distance * 370 / @distancemax) + 6000)
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
if @anglemin != 0 || @anglemax != 0
if (@angle_trigo < @anglemin || @angle_trigo > @anglemax) && @anglemin < @anglemax
@@ -124,7 +123,7 @@ end
# ? CLASS Sprite_Character edit
#===================================================
class Sprite_Character < RPG::Sprite
alias :shadow_initialize :initialize
alias shadow_initialize initialize unless private_method_defined?(:shadow_initialize)
def initialize(viewport, character = nil)
@ombrelist = []
@@ -132,37 +131,33 @@ class Sprite_Character < RPG::Sprite
shadow_initialize(viewport, @character)
end
def setShadows(map,shadows)
def setShadows(map, shadows)
if character.is_a?(Game_Event) && shadows.length > 0
params = XPML_read(map,"Shadow",@character,4)
if params != nil
for i in 0...shadows.size
@ombrelist.push(Sprite_Shadow.new(viewport, @character, shadows[i]))
params = XPML_read(map, "Shadow", @character, 4)
if params
shadows.each do |shadow|
@ombrelist.push(Sprite_Shadow.new(viewport, @character, shadows))
end
end
end
if character.is_a?(Game_Player) && shadows.length > 0
for i in 0...shadows.size
@ombrelist.push(Sprite_Shadow.new(viewport, $game_player, shadows[i]))
shadows.each do |shadow|
@ombrelist.push(Sprite_Shadow.new(viewport, $game_player, shadow))
end
end
update
end
def clearShadows
@ombrelist.each { |s| s.dispose if s }
@ombrelist.each { |s| s&.dispose }
@ombrelist.clear
end
alias shadow_update update
alias shadow_update update unless method_defined?(:shadow_update)
def update
shadow_update
if @ombrelist.length>0
for i in 0...@ombrelist.size
@ombrelist[i].update
end
end
@ombrelist.each { |ombre| ombre.update }
end
end
@@ -183,24 +178,24 @@ end
class Spriteset_Map
attr_accessor :shadows
alias shadow_initialize initialize
def initialize(map=nil)
alias shadow_initialize initialize unless private_method_defined?(:shadow_initialize)
def initialize(map = nil)
@shadows = []
warn = false
map = $game_map if !map
for k in map.events.keys.sort
map.events.keys.sort.each do |k|
ev = map.events[k]
warn = true if (ev.list != nil && ev.list.length > 0 &&
ev.list[0].code == 108 &&
(ev.list[0].parameters == ["s"] || ev.list[0].parameters == ["o"]))
params = XPML_read(map,"Shadow Source", ev, 4)
@shadows.push([ev] + params) if params != nil
warn = true if ev.list && ev.list.length > 0 && ev.list[0].code == 108 &&
(ev.list[0].parameters == ["s"] || ev.list[0].parameters == ["o"])
params = XPML_read(map, "Shadow Source", ev, 4)
@shadows.push([ev] + params) if params
end
if warn == true
p "Warning : At least one event on this map uses the obsolete way to add shadows"
end
shadow_initialize(map)
for sprite in @character_sprites
@character_sprites.each do |sprite|
sprite.setShadows(map, @shadows)
end
$scene.spritesetGlobal.playersprite.setShadows(map, @shadows)
@@ -228,31 +223,24 @@ end
# p XPML_read("third", event_id) -> [3]
# p XPML_read("forth", event_id) -> nil
#===================================================
def XPML_read(map,markup,event,max_param_number=0)
def XPML_read(map, markup, event, max_param_number = 0)
parameter_list = nil
return nil if !event || event.list == nil
for i in 0...event.list.size
if event.list[i].code == 108 &&
event.list[i].parameters[0].downcase == "begin " + markup.downcase
parameter_list = [] if parameter_list == nil
for j in i+1...event.list.size
if event.list[j].code == 108
parts = event.list[j].parameters[0].split
if parts.size != 1 && parts[0].downcase != "begin"
if parts[1].to_i != 0 || parts[1] == "0"
parameter_list.push(parts[1].to_i)
else
parameter_list.push(parts[1])
end
else
return parameter_list
end
else
return parameter_list
end
return parameter_list if max_param_number != 0 && j == i + max_param_number
end
return nil if !event || event.list.nil?
event.list.size.times do |i|
next unless event.list[i].code == 108 &&
event.list[i].parameters[0].downcase == "begin " + markup.downcase
parameter_list = [] if parameter_list.nil?
((i + 1)...event.list.size).each do |j|
return parameter_list if event.list[j].code != 108
parts = event.list[j].parameters[0].split
return parameter_list if parts.size == 1 || parts[0].downcase == "begin"
if parts[1].to_i != 0 || parts[1] == "0"
parameter_list.push(parts[1].to_i)
else
parameter_list.push(parts[1])
end
return parameter_list if max_param_number != 0 && j == i + max_param_number
end
end
return parameter_list
end

View File

@@ -2,36 +2,36 @@
# Based on version 2 by Near Fantastica, 04.01.06
# In turn based on the Particle Engine designed by PinkMan
class Particle_Engine
def initialize(viewport=nil,map=nil)
def initialize(viewport = nil, map = nil)
@map = (map) ? map : $game_map
@viewport = viewport
@effect = []
@disposed = false
@firsttime = true
@effects = {
# PinkMan's Effects
"fire" => Particle_Engine::Fire,
"smoke" => Particle_Engine::Smoke,
"teleport" => Particle_Engine::Teleport,
"spirit" => Particle_Engine::Spirit,
"explosion" => Particle_Engine::Explosion,
"aura" => Particle_Engine::Aura,
# BlueScope's Effects
"soot" => Particle_Engine::Soot,
"sootsmoke" => Particle_Engine::SootSmoke,
"rocket" => Particle_Engine::Rocket,
"fixteleport" => Particle_Engine::FixedTeleport,
"smokescreen" => Particle_Engine::Smokescreen,
"flare" => Particle_Engine::Flare,
"splash" => Particle_Engine::Splash,
# By Peter O.
"starteleport" => Particle_Engine::StarTeleport
# PinkMan's Effects
"fire" => Particle_Engine::Fire,
"smoke" => Particle_Engine::Smoke,
"teleport" => Particle_Engine::Teleport,
"spirit" => Particle_Engine::Spirit,
"explosion" => Particle_Engine::Explosion,
"aura" => Particle_Engine::Aura,
# BlueScope's Effects
"soot" => Particle_Engine::Soot,
"sootsmoke" => Particle_Engine::SootSmoke,
"rocket" => Particle_Engine::Rocket,
"fixteleport" => Particle_Engine::FixedTeleport,
"smokescreen" => Particle_Engine::Smokescreen,
"flare" => Particle_Engine::Flare,
"splash" => Particle_Engine::Splash,
# By Peter O.
"starteleport" => Particle_Engine::StarTeleport
}
end
def dispose
return if disposed?
for particle in @effect
@effect.each do |particle|
next if particle.nil?
particle.dispose
end
@@ -54,47 +54,46 @@ class Particle_Engine
@effect.delete_at(event.id)
end
def realloc_effect(event,particle)
def realloc_effect(event, particle)
type = pbEventCommentInput(event, 1, "Particle Engine Type")
if type.nil?
particle.dispose if particle
particle&.dispose
return nil
end
type = type[0].downcase
cls = @effects[type]
if cls.nil?
particle.dispose if particle
particle&.dispose
return nil
end
if !particle || !particle.is_a?(cls)
particle.dispose if particle
particle = cls.new(event,@viewport)
particle&.dispose
particle = cls.new(event, @viewport)
end
return particle
end
def pbParticleEffect(event)
return realloc_effect(event,nil)
return realloc_effect(event, nil)
end
def update
if @firsttime
@firsttime = false
for event in @map.events.values
@map.events.each_value do |event|
remove_effect(event)
add_effect(event)
end
end
for i in 0...@effect.length
particle = @effect[i]
@effect.each_with_index do |particle, i|
next if particle.nil?
if particle.event.pe_refresh
event = particle.event
event.pe_refresh = false
particle = realloc_effect(event,particle)
particle = realloc_effect(event, particle)
@effect[i] = particle
end
particle.update if particle
particle&.update
end
end
end
@@ -136,7 +135,7 @@ class ParticleSprite
end
def dispose
@sprite.dispose if @sprite
@sprite&.dispose
end
def bitmap=(value)
@@ -153,21 +152,21 @@ class ParticleSprite
def update
w = Graphics.width
h = Graphics.height
if !@sprite && @x>=@minleft && @y>=@mintop && @x<w && @y<h
if !@sprite && @x >= @minleft && @y >= @mintop && @x < w && @y < h
@sprite = Sprite.new(@viewport)
elsif @sprite && (@x<@minleft || @y<@mintop || @x>=w || @y>=h)
elsif @sprite && (@x < @minleft || @y < @mintop || @x >= w || @y >= h)
@sprite.dispose
@sprite = nil
end
if @sprite
@sprite.x = @x if @sprite.x!=@x
@sprite.x = @x if @sprite.x != @x
@sprite.x -= @ox
@sprite.y = @y if @sprite.y!=@y
@sprite.y = @y if @sprite.y != @y
@sprite.y -= @oy
@sprite.z = @z if @sprite.z!=@z
@sprite.opacity = @opacity if @sprite.opacity!=@opacity
@sprite.blend_type = @blend_type if @sprite.blend_type!=@blend_type
@sprite.bitmap = @bitmap if @sprite.bitmap!=@bitmap
@sprite.z = @z if @sprite.z != @z
@sprite.opacity = @opacity if @sprite.opacity != @opacity
@sprite.blend_type = @blend_type if @sprite.blend_type != @blend_type
@sprite.bitmap = @bitmap if @sprite.bitmap != @bitmap
end
end
end
@@ -177,7 +176,7 @@ end
class ParticleEffect_Event < ParticleEffect
attr_accessor :event
def initialize(event,viewport=nil)
def initialize(event, viewport = nil)
@event = event
@viewport = viewport
@particles = []
@@ -185,24 +184,24 @@ class ParticleEffect_Event < ParticleEffect
end
def setParameters(params)
@randomhue,@leftright,@fade,
@maxparticless,@hue,@slowdown,
@ytop,@ybottom,@xleft,@xright,
@xgravity,@ygravity,@xoffset,@yoffset,
@opacityvar,@originalopacity = params
@randomhue, @leftright, @fade,
@maxparticless, @hue, @slowdown,
@ytop, @ybottom, @xleft, @xright,
@xgravity, @ygravity, @xoffset, @yoffset,
@opacityvar, @originalopacity = params
end
def loadBitmap(filename,hue)
key = [filename,hue]
def loadBitmap(filename, hue)
key = [filename, hue]
bitmap = @bitmaps[key]
if !bitmap || bitmap.disposed?
bitmap = AnimatedBitmap.new("Graphics/Fogs/"+filename,hue).deanimate
bitmap = AnimatedBitmap.new("Graphics/Fogs/" + filename, hue).deanimate
@bitmaps[key] = bitmap
end
return bitmap
end
def initParticles(filename,opacity,zOffset=0,blendtype=1)
def initParticles(filename, opacity, zOffset = 0, blendtype = 1)
@particles = []
@particlex = []
@particley = []
@@ -217,20 +216,20 @@ class ParticleEffect_Event < ParticleEffect
@zoffset = zOffset
@bmwidth = 32
@bmheight = 32
for i in 0...@maxparticless
@maxparticless.times do |i|
@particlex[i] = -@xoffset
@particley[i] = -@yoffset
@particles[i] = ParticleSprite.new(@viewport)
@particles[i].bitmap = loadBitmap(filename, @hue) if filename
if i==0 && @particles[i].bitmap
if i == 0 && @particles[i].bitmap
@bmwidth = @particles[i].bitmap.width
@bmheight = @particles[i].bitmap.height
end
@particles[i].blend_type = blendtype
@particles[i].y = @startingy
@particles[i].x = @startingx
@particles[i].z = self.z+zOffset
@opacity[i] = rand(opacity/4)
@particles[i].z = self.z + zOffset
@opacity[i] = rand(opacity / 4)
@particles[i].opacity = @opacity[i]
@particles[i].update
end
@@ -253,29 +252,29 @@ class ParticleEffect_Event < ParticleEffect
newRealY = @event.real_y
@startingx = selfX + @xoffset
@startingy = selfY + @yoffset
@__offsetx = (@real_x==newRealX) ? 0 : selfX-@screen_x
@__offsety = (@real_y==newRealY) ? 0 : selfY-@screen_y
@__offsetx = (@real_x == newRealX) ? 0 : selfX - @screen_x
@__offsety = (@real_y == newRealY) ? 0 : selfY - @screen_y
@screen_x = selfX
@screen_y = selfY
@real_x = newRealX
@real_y = newRealY
if @opacityvar>0 && @viewport
opac = 255.0/@opacityvar
minX = opac*(-@xgravity*1.0 / @slowdown).floor + @startingx
maxX = opac*(@xgravity*1.0 / @slowdown).floor + @startingx
minY = opac*(-@ygravity*1.0 / @slowdown).floor + @startingy
if @opacityvar > 0 && @viewport
opac = 255.0 / @opacityvar
minX = (opac * (-@xgravity.to_f / @slowdown).floor) + @startingx
maxX = (opac * (@xgravity.to_f / @slowdown).floor) + @startingx
minY = (opac * (-@ygravity.to_f / @slowdown).floor) + @startingy
maxY = @startingy
minX -= @bmwidth
minY -= @bmheight
maxX += @bmwidth
maxY += @bmheight
if maxX<0 || maxY<0 || minX>=Graphics.width || minY>=Graphics.height
if maxX < 0 || maxY < 0 || minX >= Graphics.width || minY >= Graphics.height
# echo "skipped"
return
end
end
particleZ = selfZ+@zoffset
for i in 0...@maxparticless
particleZ = selfZ + @zoffset
@maxparticless.times do |i|
@particles[i].z = particleZ
if @particles[i].y <= @ytop
@particles[i].y = @startingy + @yoffset
@@ -309,14 +308,12 @@ class ParticleEffect_Event < ParticleEffect
@particlex[i] = 0.0
@particley[i] = 0.0
end
else
if @opacity[i] <= 0
@opacity[i] = 250
@particles[i].y = @startingy + @yoffset
@particles[i].x = @startingx + @xoffset
@particlex[i] = 0.0
@particley[i] = 0.0
end
elsif @opacity[i] <= 0
@opacity[i] = 250
@particles[i].y = @startingy + @yoffset
@particles[i].x = @startingx + @xoffset
@particlex[i] = 0.0
@particley[i] = 0.0
end
calcParticlePos(i)
if @randomhue == 1
@@ -333,26 +330,26 @@ class ParticleEffect_Event < ParticleEffect
def calcParticlePos(i)
@leftright = rand(2)
if @leftright == 1
xo = -@xgravity*1.0 / @slowdown
xo = -@xgravity.to_f / @slowdown
else
xo = @xgravity*1.0 / @slowdown
xo = @xgravity.to_f / @slowdown
end
yo = -@ygravity*1.0 / @slowdown
yo = -@ygravity.to_f / @slowdown
@particlex[i] += xo
@particley[i] += yo
@particlex[i] -= @__offsetx
@particley[i] -= @__offsety
@particlex[i] = @particlex[i].floor
@particley[i] = @particley[i].floor
@particles[i].x = @particlex[i]+@startingx+@xoffset
@particles[i].y = @particley[i]+@startingy+@yoffset
@particles[i].x = @particlex[i] + @startingx + @xoffset
@particles[i].y = @particley[i] + @startingy + @yoffset
end
def dispose
for particle in @particles
@particles.each do |particle|
particle.dispose
end
for bitmap in @bitmaps.values
@bitmaps.each_value do |bitmap|
bitmap.dispose
end
@particles.clear
@@ -363,34 +360,34 @@ end
class Particle_Engine::Fire < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,1,20,40,0.5,-64,
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-13,30,0])
initParticles("particle",250)
setParameters([0, 0, 1, 20, 40, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -13, 30, 0])
initParticles("particle", 250)
end
end
class Particle_Engine::Smoke < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,0,80,20,0.5,-64,
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-15,5,80])
initParticles("smoke",250)
setParameters([0, 0, 0, 80, 20, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -15, 5, 80])
initParticles("smoke", 250)
end
end
class Particle_Engine::Teleport < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([1,1,1,10,rand(360),1,-64,
Graphics.height,-64,Graphics.width,0,3,-8,-15,20,0])
initParticles("wideportal",250)
for i in 0...@maxparticless
setParameters([1, 1, 1, 10, rand(360), 1, -64,
Graphics.height, -64, Graphics.width, 0, 3, -8, -15, 20, 0])
initParticles("wideportal", 250)
@maxparticless.times do |i|
@particles[i].ox = 16
@particles[i].oy = 16
end
@@ -400,56 +397,56 @@ end
class Particle_Engine::Spirit < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([1,0,1,20,rand(360),0.5,-64,
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-13,30,0])
initParticles("particle",250)
setParameters([1, 0, 1, 20, rand(360), 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -13, 30, 0])
initParticles("particle", 250)
end
end
class Particle_Engine::Explosion < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,1,20,0,0.5,-64,
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-13,30,0])
initParticles("explosion",250)
setParameters([0, 0, 1, 20, 0, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -13, 30, 0])
initParticles("explosion", 250)
end
end
class Particle_Engine::Aura < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,1,20,0,1,-64,
Graphics.height,-64,Graphics.width,2,2,-5,-13,30,0])
initParticles("particle",250)
setParameters([0, 0, 1, 20, 0, 1, -64,
Graphics.height, -64, Graphics.width, 2, 2, -5, -13, 30, 0])
initParticles("particle", 250)
end
end
class Particle_Engine::Soot < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,0,20,0,0.5,-64,
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-15,5,80])
initParticles("smoke",100,0,2)
setParameters([0, 0, 0, 20, 0, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -15, 5, 80])
initParticles("smoke", 100, 0, 2)
end
end
class Particle_Engine::SootSmoke < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,0,30,0,0.5,-64,
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-15,5,80])
initParticles("smoke",100,0)
for i in 0...@maxparticless
setParameters([0, 0, 0, 30, 0, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0.10, -5, -15, 5, 80])
initParticles("smoke", 100, 0)
@maxparticless.times do |i|
@particles[i].blend_type = rand(6) < 3 ? 1 : 2
end
end
@@ -458,23 +455,23 @@ end
class Particle_Engine::Rocket < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,0,60,0,0.5,-64,
Graphics.height,-64,Graphics.width,0.5,0,-5,-15,5,80])
initParticles("smoke",100,-1)
setParameters([0, 0, 0, 60, 0, 0.5, -64,
Graphics.height, -64, Graphics.width, 0.5, 0, -5, -15, 5, 80])
initParticles("smoke", 100, -1)
end
end
class Particle_Engine::FixedTeleport < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([1,0,1,10,rand(360),1,
-Graphics.height,Graphics.height,0,Graphics.width,0,3,-8,-15,20,0])
initParticles("wideportal",250)
for i in 0...@maxparticless
setParameters([1, 0, 1, 10, rand(360), 1,
-Graphics.height, Graphics.height, 0, Graphics.width, 0, 3, -8, -15, 20, 0])
initParticles("wideportal", 250)
@maxparticless.times do |i|
@particles[i].ox = 16
@particles[i].oy = 16
end
@@ -485,12 +482,12 @@ end
# By Peter O.
class Particle_Engine::StarTeleport < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,1,10,0,1,
-Graphics.height,Graphics.height,0,Graphics.width,0,3,-8,-15,10,0])
initParticles("star",250)
for i in 0...@maxparticless
setParameters([0, 0, 1, 10, 0, 1,
-Graphics.height, Graphics.height, 0, Graphics.width, 0, 3, -8, -15, 10, 0])
initParticles("star", 250)
@maxparticless.times do |i|
@particles[i].ox = 48
@particles[i].oy = 48
end
@@ -500,64 +497,64 @@ end
class Particle_Engine::Smokescreen < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,0,250,0,0.2,-64,
Graphics.height,-64,Graphics.width,0.8,0.8,-5,-15,5,80])
initParticles(nil,100)
for i in 0...@maxparticless
setParameters([0, 0, 0, 250, 0, 0.2, -64,
Graphics.height, -64, Graphics.width, 0.8, 0.8, -5, -15, 5, 80])
initParticles(nil, 100)
@maxparticless.times do |i|
rnd = rand(3)
@opacity[i] = (rnd==0) ? 1 : 100
filename = (rnd==0) ? "explosionsmoke" : "smoke"
@opacity[i] = (rnd == 0) ? 1 : 100
filename = (rnd == 0) ? "explosionsmoke" : "smoke"
@particles[i].bitmap = loadBitmap(filename, @hue)
end
end
def calcParticlePos(i)
if @randomhue==1
filename = (rand(3)==0) ? "explosionsmoke" : "smoke"
if @randomhue == 1
filename = (rand(3) == 0) ? "explosionsmoke" : "smoke"
@particles[i].bitmap = loadBitmap(filename, @hue)
end
multiple = 1.7
xgrav = @xgravity*multiple/@slowdown
xgrav = -xgrav if (rand(2)==1)
ygrav = @ygravity*multiple/@slowdown
ygrav = -ygrav if (rand(2)==1)
xgrav = @xgravity * multiple / @slowdown
xgrav = -xgrav if rand(2) == 1
ygrav = @ygravity * multiple / @slowdown
ygrav = -ygrav if rand(2) == 1
@particlex[i] += xgrav
@particley[i] += ygrav
@particlex[i] -= @__offsetx
@particley[i] -= @__offsety
@particlex[i] = @particlex[i].floor
@particley[i] = @particley[i].floor
@particles[i].x = @particlex[i]+@startingx+@xoffset
@particles[i].y = @particley[i]+@startingy+@yoffset
@particles[i].x = @particlex[i] + @startingx + @xoffset
@particles[i].y = @particley[i] + @startingy + @yoffset
end
end
class Particle_Engine::Flare < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,1,30,10,1,-64,
Graphics.height,-64,Graphics.width,2,2,-5,-12,30,0])
initParticles("particle",255)
setParameters([0, 0, 1, 30, 10, 1, -64,
Graphics.height, -64, Graphics.width, 2, 2, -5, -12, 30, 0])
initParticles("particle", 255)
end
end
class Particle_Engine::Splash < ParticleEffect_Event
def initialize(event,viewport)
def initialize(event, viewport)
super
setParameters([0,0,1,30,255,1,-64,
Graphics.height,-64,Graphics.width,4,2,-5,-12,30,0])
initParticles("smoke",50)
setParameters([0, 0, 1, 30, 255, 1, -64,
Graphics.height, -64, Graphics.width, 4, 2, -5, -12, 30, 0])
initParticles("smoke", 50)
end
def update
super
for i in 0...@maxparticless
@maxparticless.times do |i|
@particles[i].opacity = 50
@particles[i].update
end
@@ -569,8 +566,9 @@ end
class Game_Event < Game_Character
attr_accessor :pe_refresh
alias nf_particles_game_map_initialize initialize
def initialize(map_id,event,map=nil)
alias nf_particles_game_map_initialize initialize unless private_method_defined?(:nf_particles_game_map_initialize)
def initialize(map_id, event, map = nil)
@pe_refresh = false
begin
nf_particles_game_map_initialize(map_id, event, map)
@@ -579,7 +577,8 @@ class Game_Event < Game_Character
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
nf_particles_game_map_refresh
@pe_refresh = true

View File

@@ -1,71 +1,75 @@
class PictureOrigin
TopLeft = 0
Center = 1
TopRight = 2
BottomLeft = 3
LowerLeft = 3
BottomRight = 4
LowerRight = 4
Top = 5
Bottom = 6
Left = 7
Right = 8
TOP_LEFT = 0
CENTER = 1
TOP_RIGHT = 2
BOTTOM_LEFT = 3
LOWER_LEFT = 3
BOTTOM_RIGHT = 4
LOWER_RIGHT = 4
TOP = 5
BOTTOM = 6
LEFT = 7
RIGHT = 8
end
class Processes
XY = 0
DeltaXY = 1
Z = 2
Curve = 3
Zoom = 4
Angle = 5
Tone = 6
Color = 7
Hue = 8
Opacity = 9
Visible = 10
BlendType = 11
SE = 12
Name = 13
Origin = 14
Src = 15
SrcSize = 16
CropBottom = 17
XY = 0
DELTA_XY = 1
Z = 2
CURVE = 3
ZOOM = 4
ANGLE = 5
TONE = 6
COLOR = 7
HUE = 8
OPACITY = 9
VISIBLE = 10
BLEND_TYPE = 11
SE = 12
NAME = 13
ORIGIN = 14
SRC = 15
SRC_SIZE = 16
CROP_BOTTOM = 17
end
def getCubicPoint2(src,t)
x0 = src[0]; y0 = src[1]
cx0 = src[2]; cy0 = src[3]
cx1 = src[4]; cy1 = src[5]
x1 = src[6]; y1 = src[7]
def getCubicPoint2(src, t)
x0 = src[0]
y0 = src[1]
cx0 = src[2]
cy0 = src[3]
cx1 = src[4]
cy1 = src[5]
x1 = src[6]
y1 = src[7]
x1 = cx1+(x1-cx1)*t
x0 = x0+(cx0-x0)*t
cx0 = cx0+(cx1-cx0)*t
cx1 = cx0+(x1-cx0)*t
cx0 = x0+(cx0-x0)*t
cx = cx0+(cx1-cx0)*t
x1 = cx1 + ((x1 - cx1) * t)
x0 = x0 + ((cx0 - x0) * t)
cx0 = cx0 + ((cx1 - cx0) * t)
cx1 = cx0 + ((x1 - cx0) * t)
cx0 = x0 + ((cx0 - x0) * t)
cx = cx0 + ((cx1 - cx0) * t)
# a = x1 - 3 * cx1 + 3 * cx0 - x0
# b = 3 * (cx1 - 2 * cx0 + x0)
# c = 3 * (cx0 - x0)
# d = x0
# cx = a*t*t*t + b*t*t + c*t + d
y1 = cy1+(y1-cy1)*t
y0 = y0+(cy0-y0)*t
cy0 = cy0+(cy1-cy0)*t
cy1 = cy0+(y1-cy0)*t
cy0 = y0+(cy0-y0)*t
cy = cy0+(cy1-cy0)*t
y1 = cy1 + ((y1 - cy1) * t)
y0 = y0 + ((cy0 - y0) * t)
cy0 = cy0 + ((cy1 - cy0) * t)
cy1 = cy0 + ((y1 - cy0) * t)
cy0 = y0 + ((cy0 - y0) * t)
cy = cy0 + ((cy1 - cy0) * t)
# a = y1 - 3 * cy1 + 3 * cy0 - y0
# b = 3 * (cy1 - 2 * cy0 + y0)
# c = 3 * (cy0 - y0)
# d = y0
# cy = a*t*t*t + b*t*t + c*t + d
return [cx,cy]
return [cx, cy]
end
@@ -110,43 +114,47 @@ class PictureEx
@visible = true
@blend_type = 0
@name = ""
@origin = PictureOrigin::TopLeft
@src_rect = Rect.new(0,0,-1,-1)
@origin = PictureOrigin::TOP_LEFT
@src_rect = Rect.new(0, 0, -1, -1)
@cropBottom = -1
@frameUpdates = []
end
def callback(cb)
if cb.is_a?(Proc); cb.call(self)
elsif cb.is_a?(Array); cb[0].method(cb[1]).call(self)
elsif cb.is_a?(Method); cb.call(self)
case cb
when Proc
cb.call(self)
when Array
cb[0].method(cb[1]).call(self, *cb[2])
when Method
cb.call(self)
end
end
def setCallback(delay, cb=nil)
def setCallback(delay, cb = nil)
delay = ensureDelayAndDuration(delay)
@processes.push([nil,delay,0,0,cb])
@processes.push([nil, delay, 0, 0, cb])
end
def running?
return @processes.length>0
return @processes.length > 0
end
def totalDuration
ret = 0
for process in @processes
dur = process[1]+process[2]
ret = dur if dur>ret
@processes.each do |process|
dur = process[1] + process[2]
ret = dur if dur > ret
end
ret *= 20.0/Graphics.frame_rate
ret *= 20.0 / Graphics.frame_rate
return ret.to_i
end
def ensureDelayAndDuration(delay, duration=nil)
delay = self.totalDuration if delay<0
delay *= Graphics.frame_rate/20.0
def ensureDelayAndDuration(delay, duration = nil)
delay = self.totalDuration if delay < 0
delay *= Graphics.frame_rate / 20.0
if !duration.nil?
duration *= Graphics.frame_rate/20.0
duration *= Graphics.frame_rate / 20.0
return delay.to_i, duration.to_i
end
return delay.to_i
@@ -162,8 +170,10 @@ class PictureEx
# point. If you make a sprite auto-rotate, you should not try to alter
# the angle another way too.
def rotate(speed)
@rotate_speed = speed*20.0/Graphics.frame_rate
while @rotate_speed<0; @rotate_speed += 360; end
@rotate_speed = speed * 20.0 / Graphics.frame_rate
while @rotate_speed < 0
@rotate_speed += 360
end
@rotate_speed %= 360
end
@@ -176,8 +186,8 @@ class PictureEx
end
def adjustPosition(xOffset, yOffset)
for process in @processes
next if process[0]!=Processes::XY
@processes.each do |process|
next if process[0] != Processes::XY
process[5] += xOffset
process[6] += yOffset
process[7] += xOffset
@@ -185,262 +195,262 @@ class PictureEx
end
end
def move(delay, duration, origin, x, y, zoom_x=100.0, zoom_y=100.0, opacity=255)
setOrigin(delay,duration,origin)
moveXY(delay,duration,x,y)
moveZoomXY(delay,duration,zoom_x,zoom_y)
moveOpacity(delay,duration,opacity)
def move(delay, duration, origin, x, y, zoom_x = 100.0, zoom_y = 100.0, opacity = 255)
setOrigin(delay, duration, origin)
moveXY(delay, duration, x, y)
moveZoomXY(delay, duration, zoom_x, zoom_y)
moveOpacity(delay, duration, opacity)
end
def moveXY(delay, duration, x, y, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
@processes.push([Processes::XY,delay,duration,0,cb,@x,@y,x,y])
def moveXY(delay, duration, x, y, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::XY, delay, duration, 0, cb, @x, @y, x, y])
end
def setXY(delay, x, y, cb=nil)
moveXY(delay,0,x,y,cb)
def setXY(delay, x, y, cb = nil)
moveXY(delay, 0, x, y, cb)
end
def moveCurve(delay, duration, x1, y1, x2, y2, x3, y3, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
@processes.push([Processes::Curve,delay,duration,0,cb,[@x,@y,x1,y1,x2,y2,x3,y3]])
def moveCurve(delay, duration, x1, y1, x2, y2, x3, y3, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::CURVE, delay, duration, 0, cb, [@x, @y, x1, y1, x2, y2, x3, y3]])
end
def moveDelta(delay, duration, x, y, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
@processes.push([Processes::DeltaXY,delay,duration,0,cb,@x,@y,x,y])
def moveDelta(delay, duration, x, y, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::DELTA_XY, delay, duration, 0, cb, @x, @y, x, y])
end
def setDelta(delay, x, y, cb=nil)
moveDelta(delay,0,x,y,cb)
def setDelta(delay, x, y, cb = nil)
moveDelta(delay, 0, x, y, cb)
end
def moveZ(delay, duration, z, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
@processes.push([Processes::Z,delay,duration,0,cb,@z,z])
def moveZ(delay, duration, z, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::Z, delay, duration, 0, cb, @z, z])
end
def setZ(delay, z, cb=nil)
moveZ(delay,0,z,cb)
def setZ(delay, z, cb = nil)
moveZ(delay, 0, z, cb)
end
def moveZoomXY(delay, duration, zoom_x, zoom_y, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
@processes.push([Processes::Zoom,delay,duration,0,cb,@zoom_x,@zoom_y,zoom_x,zoom_y])
def moveZoomXY(delay, duration, zoom_x, zoom_y, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::ZOOM, delay, duration, 0, cb, @zoom_x, @zoom_y, zoom_x, zoom_y])
end
def setZoomXY(delay, zoom_x, zoom_y, cb=nil)
moveZoomXY(delay,0,zoom_x,zoom_y,cb)
def setZoomXY(delay, zoom_x, zoom_y, cb = nil)
moveZoomXY(delay, 0, zoom_x, zoom_y, cb)
end
def moveZoom(delay, duration, zoom, cb=nil)
moveZoomXY(delay,duration,zoom,zoom,cb)
def moveZoom(delay, duration, zoom, cb = nil)
moveZoomXY(delay, duration, zoom, zoom, cb)
end
def setZoom(delay, zoom, cb=nil)
moveZoomXY(delay,0,zoom,zoom,cb)
def setZoom(delay, zoom, cb = nil)
moveZoomXY(delay, 0, zoom, zoom, cb)
end
def moveAngle(delay, duration, angle, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
@processes.push([Processes::Angle,delay,duration,0,cb,@angle,angle])
def moveAngle(delay, duration, angle, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::ANGLE, delay, duration, 0, cb, @angle, angle])
end
def setAngle(delay, angle, cb=nil)
moveAngle(delay,0,angle,cb)
def setAngle(delay, angle, cb = nil)
moveAngle(delay, 0, angle, cb)
end
def moveTone(delay, duration, tone, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
target = (tone) ? tone.clone : Tone.new(0,0,0,0)
@processes.push([Processes::Tone,delay,duration,0,cb,@tone.clone,target])
def moveTone(delay, duration, tone, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
target = (tone) ? tone.clone : Tone.new(0, 0, 0, 0)
@processes.push([Processes::TONE, delay, duration, 0, cb, @tone.clone, target])
end
def setTone(delay, tone, cb=nil)
moveTone(delay,0,tone,cb)
def setTone(delay, tone, cb = nil)
moveTone(delay, 0, tone, cb)
end
def moveColor(delay, duration, color, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
target = (color) ? color.clone : Color.new(0,0,0,0)
@processes.push([Processes::Color,delay,duration,0,cb,@color.clone,target])
def moveColor(delay, duration, color, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
target = (color) ? color.clone : Color.new(0, 0, 0, 0)
@processes.push([Processes::COLOR, delay, duration, 0, cb, @color.clone, target])
end
def setColor(delay, color, cb=nil)
moveColor(delay,0,color,cb)
def setColor(delay, color, cb = nil)
moveColor(delay, 0, color, cb)
end
# Hue changes don't actually work.
def moveHue(delay, duration, hue, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
@processes.push([Processes::Hue,delay,duration,0,cb,@hue,hue])
def moveHue(delay, duration, hue, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::HUE, delay, duration, 0, cb, @hue, hue])
end
# Hue changes don't actually work.
def setHue(delay, hue, cb=nil)
moveHue(delay,0,hue,cb)
def setHue(delay, hue, cb = nil)
moveHue(delay, 0, hue, cb)
end
def moveOpacity(delay, duration, opacity, cb=nil)
delay, duration = ensureDelayAndDuration(delay,duration)
@processes.push([Processes::Opacity,delay,duration,0,cb,@opacity,opacity])
def moveOpacity(delay, duration, opacity, cb = nil)
delay, duration = ensureDelayAndDuration(delay, duration)
@processes.push([Processes::OPACITY, delay, duration, 0, cb, @opacity, opacity])
end
def setOpacity(delay, opacity, cb=nil)
moveOpacity(delay,0,opacity,cb)
def setOpacity(delay, opacity, cb = nil)
moveOpacity(delay, 0, opacity, cb)
end
def setVisible(delay, visible, cb=nil)
def setVisible(delay, visible, cb = nil)
delay = ensureDelay(delay)
@processes.push([Processes::Visible,delay,0,0,cb,visible])
@processes.push([Processes::VISIBLE, delay, 0, 0, cb, visible])
end
# 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)
@processes.push([Processes::BlendType,delay,0,0,cb,blend])
@processes.push([Processes::BLEND_TYPE, delay, 0, 0, cb, blend])
end
def setSE(delay, seFile, volume=nil, pitch=nil, cb=nil)
def setSE(delay, seFile, volume = nil, pitch = nil, cb = nil)
delay = ensureDelay(delay)
@processes.push([Processes::SE,delay,0,0,cb,seFile,volume,pitch])
@processes.push([Processes::SE, delay, 0, 0, cb, seFile, volume, pitch])
end
def setName(delay, name, cb=nil)
def setName(delay, name, cb = nil)
delay = ensureDelay(delay)
@processes.push([Processes::Name,delay,0,0,cb,name])
@processes.push([Processes::NAME, delay, 0, 0, cb, name])
end
def setOrigin(delay, origin, cb=nil)
def setOrigin(delay, origin, cb = nil)
delay = ensureDelay(delay)
@processes.push([Processes::Origin,delay,0,0,cb,origin])
@processes.push([Processes::ORIGIN, delay, 0, 0, cb, origin])
end
def setSrc(delay, srcX, srcY, cb=nil)
def setSrc(delay, srcX, srcY, cb = nil)
delay = ensureDelay(delay)
@processes.push([Processes::Src,delay,0,0,cb,srcX,srcY])
@processes.push([Processes::SRC, delay, 0, 0, cb, srcX, srcY])
end
def setSrcSize(delay, srcWidth, srcHeight, cb=nil)
def setSrcSize(delay, srcWidth, srcHeight, cb = nil)
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
# 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)
@processes.push([Processes::CropBottom,delay,0,0,cb,y])
@processes.push([Processes::CROP_BOTTOM, delay, 0, 0, cb, y])
end
def update
procEnded = false
@frameUpdates.clear
for i in 0...@processes.length
process = @processes[i]
@processes.each_with_index do |process, i|
# 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
if process[1]==0
if process[1] == 0
case process[0]
when Processes::XY
process[5] = @x
process[6] = @y
when Processes::DeltaXY
when Processes::DELTA_XY
process[5] = @x
process[6] = @y
process[7] += @x
process[8] += @y
when Processes::Curve
when Processes::CURVE
process[5][0] = @x
process[5][1] = @y
when Processes::Z
process[5] = @z
when Processes::Zoom
when Processes::ZOOM
process[5] = @zoom_x
process[6] = @zoom_y
when Processes::Angle
when Processes::ANGLE
process[5] = @angle
when Processes::Tone
when Processes::TONE
process[5] = @tone.clone
when Processes::Color
when Processes::COLOR
process[5] = @color.clone
when Processes::Hue
when Processes::HUE
process[5] = @hue
when Processes::Opacity
when Processes::OPACITY
process[5] = @opacity
end
end
# Decrease delay counter
process[1] -= 1
# Process hasn't started yet, skip to the next one
next if process[1]>=0
next if process[1] >= 0
end
# Update process
@frameUpdates.push(process[0]) if !@frameUpdates.include?(process[0])
fra = (process[2]==0) ? 1 : process[3] # Frame counter
dur = (process[2]==0) ? 1 : process[2] # Total duration of process
fra = (process[2] == 0) ? 1 : process[3] # Frame counter
dur = (process[2] == 0) ? 1 : process[2] # Total duration of process
case process[0]
when Processes::XY, Processes::DeltaXY
@x = process[5] + fra * (process[7] - process[5]) / dur
@y = process[6] + fra * (process[8] - process[6]) / dur
when Processes::Curve
@x, @y = getCubicPoint2(process[5],fra.to_f/dur)
when Processes::XY, Processes::DELTA_XY
@x = process[5] + (fra * (process[7] - process[5]) / dur)
@y = process[6] + (fra * (process[8] - process[6]) / dur)
when Processes::CURVE
@x, @y = getCubicPoint2(process[5], fra.to_f / dur)
when Processes::Z
@z = process[5] + fra * (process[6] - process[5]) / dur
when Processes::Zoom
@zoom_x = process[5] + fra * (process[7] - process[5]) / dur
@zoom_y = process[6] + fra * (process[8] - process[6]) / dur
when Processes::Angle
@angle = process[5] + fra * (process[6] - process[5]) / dur
when Processes::Tone
@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.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
when Processes::Color
@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.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
when Processes::Hue
@z = process[5] + (fra * (process[6] - process[5]) / dur)
when Processes::ZOOM
@zoom_x = process[5] + (fra * (process[7] - process[5]) / dur)
@zoom_y = process[6] + (fra * (process[8] - process[6]) / dur)
when Processes::ANGLE
@angle = process[5] + (fra * (process[6] - process[5]) / dur)
when Processes::TONE
@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.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)
when Processes::COLOR
@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.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)
when Processes::HUE
@hue = (process[6] - process[5]).to_f / dur
when Processes::Opacity
@opacity = process[5] + fra * (process[6] - process[5]) / dur
when Processes::Visible
when Processes::OPACITY
@opacity = process[5] + (fra * (process[6] - process[5]) / dur)
when Processes::VISIBLE
@visible = process[5]
when Processes::BlendType
when Processes::BLEND_TYPE
@blend_type = process[5]
when Processes::SE
pbSEPlay(process[5],process[6],process[7])
when Processes::Name
pbSEPlay(process[5], process[6], process[7])
when Processes::NAME
@name = process[5]
when Processes::Origin
when Processes::ORIGIN
@origin = process[5]
when Processes::Src
when Processes::SRC
@src_rect.x = process[5]
@src_rect.y = process[6]
when Processes::SrcSize
when Processes::SRC_SIZE
@src_rect.width = process[5]
@src_rect.height = process[6]
when Processes::CropBottom
when Processes::CROP_BOTTOM
@cropBottom = process[5]
end
# Increase frame counter
process[3] += 1
if process[3]>process[2]
# Process has ended, erase it
callback(process[4]) if process[4]
@processes[i] = nil
procEnded = true
end
next if process[3] <= process[2]
# Process has ended, erase it
callback(process[4]) if process[4]
@processes[i] = nil
procEnded = true
end
# Clear out empty spaces in @processes array caused by finished processes
@processes.compact! if procEnded
# Add the constant rotation speed
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
while @angle<0; @angle += 360; end
while @angle < 0
@angle += 360
end
@angle %= 360
end
end
@@ -451,69 +461,69 @@ end
#===============================================================================
#
#===============================================================================
def setPictureSprite(sprite, picture, iconSprite=false)
return if picture.frameUpdates.length==0
for i in 0...picture.frameUpdates.length
case picture.frameUpdates[i]
when Processes::XY, Processes::DeltaXY
def setPictureSprite(sprite, picture, iconSprite = false)
return if picture.frameUpdates.length == 0
picture.frameUpdates.each do |type|
case type
when Processes::XY, Processes::DELTA_XY
sprite.x = picture.x.round
sprite.y = picture.y.round
when Processes::Z
sprite.z = picture.z
when Processes::Zoom
when Processes::ZOOM
sprite.zoom_x = picture.zoom_x / 100.0
sprite.zoom_y = picture.zoom_y / 100.0
when Processes::Angle
when Processes::ANGLE
sprite.angle = picture.angle
when Processes::Tone
when Processes::TONE
sprite.tone = picture.tone
when Processes::Color
when Processes::COLOR
sprite.color = picture.color
when Processes::Hue
when Processes::HUE
# This doesn't do anything.
when Processes::BlendType
when Processes::BLEND_TYPE
sprite.blend_type = picture.blend_type
when Processes::Opacity
when Processes::OPACITY
sprite.opacity = picture.opacity
when Processes::Visible
when Processes::VISIBLE
sprite.visible = picture.visible
when Processes::Name
when Processes::NAME
sprite.name = picture.name if iconSprite && sprite.name != picture.name
when Processes::Origin
when Processes::ORIGIN
case picture.origin
when PictureOrigin::TopLeft, PictureOrigin::Left, PictureOrigin::BottomLeft
when PictureOrigin::TOP_LEFT, PictureOrigin::LEFT, PictureOrigin::BOTTOM_LEFT
sprite.ox = 0
when PictureOrigin::Top, PictureOrigin::Center, PictureOrigin::Bottom
sprite.ox = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.width/2 : 0
when PictureOrigin::TopRight, PictureOrigin::Right, PictureOrigin::BottomRight
when PictureOrigin::TOP, PictureOrigin::CENTER, PictureOrigin::BOTTOM
sprite.ox = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.width / 2 : 0
when PictureOrigin::TOP_RIGHT, PictureOrigin::RIGHT, PictureOrigin::BOTTOM_RIGHT
sprite.ox = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.width : 0
end
case picture.origin
when PictureOrigin::TopLeft, PictureOrigin::Top, PictureOrigin::TopRight
when PictureOrigin::TOP_LEFT, PictureOrigin::TOP, PictureOrigin::TOP_RIGHT
sprite.oy = 0
when PictureOrigin::Left, PictureOrigin::Center, PictureOrigin::Right
sprite.oy = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.height/2 : 0
when PictureOrigin::BottomLeft, PictureOrigin::Bottom, PictureOrigin::BottomRight
when PictureOrigin::LEFT, PictureOrigin::CENTER, PictureOrigin::RIGHT
sprite.oy = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.height / 2 : 0
when PictureOrigin::BOTTOM_LEFT, PictureOrigin::BOTTOM, PictureOrigin::BOTTOM_RIGHT
sprite.oy = (sprite.bitmap && !sprite.bitmap.disposed?) ? sprite.src_rect.height : 0
end
when Processes::Src
when Processes::SRC
next unless iconSprite && sprite.src_rect
sprite.src_rect.x = picture.src_rect.x
sprite.src_rect.y = picture.src_rect.y
when Processes::SrcSize
when Processes::SRC_SIZE
next unless iconSprite && sprite.src_rect
sprite.src_rect.width = picture.src_rect.width
sprite.src_rect.height = picture.src_rect.height
end
end
if iconSprite && sprite.src_rect && picture.cropBottom>=0
spriteBottom = sprite.y-sprite.oy+sprite.src_rect.height
if spriteBottom>picture.cropBottom
sprite.src_rect.height = [picture.cropBottom-sprite.y+sprite.oy,0].max
if iconSprite && sprite.src_rect && picture.cropBottom >= 0
spriteBottom = sprite.y - sprite.oy + sprite.src_rect.height
if spriteBottom > picture.cropBottom
sprite.src_rect.height = [picture.cropBottom - sprite.y + sprite.oy, 0].max
end
end
end
def setPictureIconSprite(sprite, picture)
setPictureSprite(sprite,picture,true)
setPictureSprite(sprite, picture, true)
end

View File

@@ -19,31 +19,30 @@ class Interpolator
return @tweening
end
def tween(sprite,items,frames)
def tween(sprite, items, frames)
@tweensteps = []
if sprite && !sprite.disposed? && frames>0
if sprite && !sprite.disposed? && frames > 0
@frames = frames
@step = 0
@sprite = sprite
for item in items
items.each do |item|
case item[0]
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]
when ZOOM_Y
@tweensteps[item[0]] = [sprite.zoom_y,item[1]-sprite.zoom_y]
@tweensteps[item[0]] = [sprite.zoom_y, item[1] - sprite.zoom_y]
when X
@tweensteps[item[0]] = [sprite.x,item[1]-sprite.x]
@tweensteps[item[0]] = [sprite.x, item[1] - sprite.x]
when Y
@tweensteps[item[0]] = [sprite.y,item[1]-sprite.y]
@tweensteps[item[0]] = [sprite.y, item[1] - sprite.y]
when OPACITY
@tweensteps[item[0]] = [sprite.opacity,item[1]-sprite.opacity]
@tweensteps[item[0]] = [sprite.opacity, item[1] - sprite.opacity]
when COLOR
@tweensteps[item[0]] = [sprite.color.clone,Color.new(
item[1].red-sprite.color.red,
item[1].green-sprite.color.green,
item[1].blue-sprite.color.blue,
item[1].alpha-sprite.color.alpha
)]
@tweensteps[item[0]] = [sprite.color.clone,
Color.new(item[1].red - sprite.color.red,
item[1].green - sprite.color.green,
item[1].blue - sprite.color.blue,
item[1].alpha - sprite.color.alpha)]
end
end
@tweening = true
@@ -52,32 +51,30 @@ class Interpolator
def update
if @tweening
t = (@step*1.0)/@frames
for i in 0...@tweensteps.length
t = @step.to_f / @frames
@tweensteps.length.times do |i|
item = @tweensteps[i]
next if !item
case i
when ZOOM_X
@sprite.zoom_x = item[0]+item[1]*t
@sprite.zoom_x = item[0] + (item[1] * t)
when ZOOM_Y
@sprite.zoom_y = item[0]+item[1]*t
@sprite.zoom_y = item[0] + (item[1] * t)
when X
@sprite.x = item[0]+item[1]*t
@sprite.x = item[0] + (item[1] * t)
when Y
@sprite.y = item[0]+item[1]*t
@sprite.y = item[0] + (item[1] * t)
when OPACITY
@sprite.opacity = item[0]+item[1]*t
@sprite.opacity = item[0] + (item[1] * t)
when COLOR
@sprite.color = Color.new(
item[0].red+item[1].red*t,
item[0].green+item[1].green*t,
item[0].blue+item[1].blue*t,
item[0].alpha+item[1].alpha*t
)
@sprite.color = Color.new(item[0].red + (item[1].red * t),
item[0].green + (item[1].green * t),
item[0].blue + (item[1].blue * t),
item[0].alpha + (item[1].alpha * t))
end
end
@step += 1
if @step==@frames
if @step == @frames
@step = 0
@frames = 0
@tweening = false
@@ -89,46 +86,46 @@ end
class RectInterpolator
def initialize(oldrect,newrect,frames)
restart(oldrect,newrect,frames)
def initialize(oldrect, newrect, frames)
restart(oldrect, newrect, frames)
end
def restart(oldrect,newrect,frames)
def restart(oldrect, newrect, frames)
@oldrect = oldrect
@newrect = newrect
@frames = [frames,1].max
@frames = [frames, 1].max
@curframe = 0
@rect = oldrect.clone
end
def set(rect)
rect.set(@rect.x,@rect.y,@rect.width,@rect.height)
rect.set(@rect.x, @rect.y, @rect.width, @rect.height)
end
def done?
@curframe>@frames
@curframe > @frames
end
def update
return if done?
t = (@curframe*1.0/@frames)
t = @curframe.to_f / @frames
x1 = @oldrect.x
x2 = @newrect.x
x = x1+t*(x2-x1)
x = x1 + (t * (x2 - x1))
y1 = @oldrect.y
y2 = @newrect.y
y = y1+t*(y2-y1)
rx1 = @oldrect.x+@oldrect.width
rx2 = @newrect.x+@newrect.width
rx = rx1+t*(rx2-rx1)
ry1 = @oldrect.y+@oldrect.height
ry2 = @newrect.y+@newrect.height
ry = ry1+t*(ry2-ry1)
minx = x<rx ? x : rx
maxx = x>rx ? x : rx
miny = y<ry ? y : ry
maxy = y>ry ? y : ry
@rect.set(minx,miny,maxx-minx,maxy-miny)
y = y1 + (t * (y2 - y1))
rx1 = @oldrect.x + @oldrect.width
rx2 = @newrect.x + @newrect.width
rx = rx1 + (t * (rx2 - rx1))
ry1 = @oldrect.y + @oldrect.height
ry2 = @newrect.y + @newrect.height
ry = ry1 + (t * (ry2 - ry1))
minx = x < rx ? x : rx
maxx = x > rx ? x : rx
miny = y < ry ? y : ry
maxy = y > ry ? y : ry
@rect.set(minx, miny, maxx - minx, maxy - miny)
@curframe += 1
end
end
@@ -139,11 +136,11 @@ class PointInterpolator
attr_reader :x
attr_reader :y
def initialize(oldx,oldy,newx,newy,frames)
restart(oldx,oldy,newx,newy,frames)
def initialize(oldx, oldy, newx, newy, frames)
restart(oldx, oldy, newx, newy, frames)
end
def restart(oldx,oldy,newx,newy,frames)
def restart(oldx, oldy, newx, newy, frames)
@oldx = oldx
@oldy = oldy
@newx = newx
@@ -155,18 +152,18 @@ class PointInterpolator
end
def done?
@curframe>@frames
@curframe > @frames
end
def update
return if done?
t = (@curframe*1.0/@frames)
t = @curframe.to_f / @frames
rx1 = @oldx
rx2 = @newx
@x = rx1+t*(rx2-rx1)
@x = rx1 + (t * (rx2 - rx1))
ry1 = @oldy
ry2 = @newy
@y = ry1+t*(ry2-ry1)
@y = ry1 + (t * (ry2 - ry1))
@curframe += 1
end
end

View File

@@ -1,10 +1,10 @@
module ScreenPosHelper
def self.pbScreenZoomX(ch)
return Game_Map::TILE_WIDTH/32.0
return Game_Map::TILE_WIDTH / 32.0
end
def self.pbScreenZoomY(ch)
return Game_Map::TILE_HEIGHT/32.0
return Game_Map::TILE_HEIGHT / 32.0
end
def self.pbScreenX(ch)
@@ -15,29 +15,29 @@ module ScreenPosHelper
return ch.screen_y
end
@heightcache={}
@heightcache = {}
def self.bmHeight(bm)
h=@heightcache[bm]
h = @heightcache[bm]
if !h
bmap=AnimatedBitmap.new("Graphics/Characters/"+bm,0)
h=bmap.height
@heightcache[bm]=h
bmap = AnimatedBitmap.new("Graphics/Characters/" + bm, 0)
h = bmap.height
@heightcache[bm] = h
bmap.dispose
end
return h
end
def self.pbScreenZ(ch,height=nil)
if height==nil
height=0
def self.pbScreenZ(ch, height = nil)
if height.nil?
height = 0
if ch.tile_id > 0
height=32
elsif ch.character_name!=""
height=bmHeight(ch.character_name)/4
height = 32
elsif ch.character_name != ""
height = bmHeight(ch.character_name) / 4
end
end
ret=ch.screen_z(height)
ret = ch.screen_z(height)
return ret
end
end

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)
return nil if !@cache.include?(i)
obj = @cache[i]
return nil if obj && obj.disposed?
return nil if obj&.disposed?
return obj
end

View File

@@ -4,11 +4,14 @@ module MessageConfig
DARK_TEXT_MAIN_COLOR = Color.new(80, 80, 88)
DARK_TEXT_SHADOW_COLOR = Color.new(160, 160, 168)
FONT_NAME = "Power Green"
FONT_SIZE = 29
FONT_SIZE = 27
FONT_Y_OFFSET = 8
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_SIZE = 29
NARROW_FONT_SIZE = 27
NARROW_FONT_Y_OFFSET = 8
# 0 = Pause cursor is displayed at end of text
# 1 = Pause cursor is displayed at bottom right
# 2 = Pause cursor is displayed at lower middle side
@@ -40,39 +43,39 @@ module MessageConfig
end
def self.pbDefaultWindowskin
skin=($data_system) ? $data_system.windowskin_name : nil
if skin && skin!=""
skin=pbResolveBitmap("Graphics/Windowskins/"+skin) || ""
skin = ($data_system) ? $data_system.windowskin_name : nil
if skin && skin != ""
skin = pbResolveBitmap("Graphics/Windowskins/" + skin) || ""
end
skin=pbResolveBitmap("Graphics/System/Window") if nil_or_empty?(skin)
skin=pbResolveBitmap("Graphics/Windowskins/001-Blue01") if nil_or_empty?(skin)
skin = pbResolveBitmap("Graphics/System/Window") if nil_or_empty?(skin)
skin = pbResolveBitmap("Graphics/Windowskins/001-Blue01") if nil_or_empty?(skin)
return skin || ""
end
def self.pbGetSystemFrame
if !@@systemFrame
skin=MessageConfig.pbDefaultSystemFrame
skin=MessageConfig.pbDefaultWindowskin if nil_or_empty?(skin)
@@systemFrame=skin || ""
skin = MessageConfig.pbDefaultSystemFrame
skin = MessageConfig.pbDefaultWindowskin if nil_or_empty?(skin)
@@systemFrame = skin || ""
end
return @@systemFrame
end
def self.pbGetSpeechFrame
if !@@defaultTextSkin
skin=MessageConfig.pbDefaultSpeechFrame
skin=MessageConfig.pbDefaultWindowskin if nil_or_empty?(skin)
@@defaultTextSkin=skin || ""
skin = MessageConfig.pbDefaultSpeechFrame
skin = MessageConfig.pbDefaultWindowskin if nil_or_empty?(skin)
@@defaultTextSkin = skin || ""
end
return @@defaultTextSkin
end
def self.pbSetSystemFrame(value)
@@systemFrame=pbResolveBitmap(value) || ""
@@systemFrame = pbResolveBitmap(value) || ""
end
def self.pbSetSpeechFrame(value)
@@defaultTextSkin=pbResolveBitmap(value) || ""
@@defaultTextSkin = pbResolveBitmap(value) || ""
end
#-----------------------------------------------------------------------------
@@ -82,12 +85,12 @@ module MessageConfig
end
def self.pbGetTextSpeed
@@textSpeed=pbDefaultTextSpeed if !@@textSpeed
@@textSpeed = pbDefaultTextSpeed if !@@textSpeed
return @@textSpeed
end
def self.pbSetTextSpeed(value)
@@textSpeed=value
@@textSpeed = value
end
def self.pbSettingToTextSpeed(speed)
@@ -144,12 +147,13 @@ module MessageConfig
end
def self.pbTryFonts(*args)
for a in args
args.each do |a|
next if !a
if a.is_a?(String)
case a
when String
return a if Font.exist?(a)
elsif a.is_a?(Array)
for aa in a
when Array
a.each do |aa|
ret = MessageConfig.pbTryFonts(aa)
return ret if ret != ""
end
@@ -165,110 +169,106 @@ end
# Position a window
#===============================================================================
def pbBottomRight(window)
window.x=Graphics.width-window.width
window.y=Graphics.height-window.height
window.x = Graphics.width - window.width
window.y = Graphics.height - window.height
end
def pbBottomLeft(window)
window.x=0
window.y=Graphics.height-window.height
window.x = 0
window.y = Graphics.height - window.height
end
def pbBottomLeftLines(window,lines,width=nil)
window.x=0
window.width=width ? width : Graphics.width
window.height=(window.borderY rescue 32)+lines*32
window.y=Graphics.height-window.height
def pbBottomLeftLines(window, lines, width = nil)
window.x = 0
window.width = width || Graphics.width
window.height = (window.borderY rescue 32) + (lines * 32)
window.y = Graphics.height - window.height
end
def pbPositionFaceWindow(facewindow,msgwindow)
def pbPositionFaceWindow(facewindow, msgwindow)
return if !facewindow
if msgwindow
if facewindow.height<=msgwindow.height
facewindow.y=msgwindow.y
if facewindow.height <= msgwindow.height
facewindow.y = msgwindow.y
else
facewindow.y=msgwindow.y+msgwindow.height-facewindow.height
facewindow.y = msgwindow.y + msgwindow.height - facewindow.height
end
facewindow.x=Graphics.width-facewindow.width
msgwindow.x=0
msgwindow.width=Graphics.width-facewindow.width
facewindow.x = Graphics.width - facewindow.width
msgwindow.x = 0
msgwindow.width = Graphics.width - facewindow.width
else
facewindow.height=Graphics.height if facewindow.height>Graphics.height
facewindow.x=0
facewindow.y=0
facewindow.height = Graphics.height if facewindow.height > Graphics.height
facewindow.x = 0
facewindow.y = 0
end
end
def pbPositionNearMsgWindow(cmdwindow,msgwindow,side)
def pbPositionNearMsgWindow(cmdwindow, msgwindow, side)
return if !cmdwindow
if msgwindow
height=[cmdwindow.height,Graphics.height-msgwindow.height].min
if cmdwindow.height!=height
cmdwindow.height=height
height = [cmdwindow.height, Graphics.height - msgwindow.height].min
if cmdwindow.height != height
cmdwindow.height = height
end
cmdwindow.y=msgwindow.y-cmdwindow.height
if cmdwindow.y<0
cmdwindow.y=msgwindow.y+msgwindow.height
if cmdwindow.y+cmdwindow.height>Graphics.height
cmdwindow.y=msgwindow.y-cmdwindow.height
cmdwindow.y = msgwindow.y - cmdwindow.height
if cmdwindow.y < 0
cmdwindow.y = msgwindow.y + msgwindow.height
if cmdwindow.y + cmdwindow.height > Graphics.height
cmdwindow.y = msgwindow.y - cmdwindow.height
end
end
case side
when :left
cmdwindow.x=msgwindow.x
cmdwindow.x = msgwindow.x
when :right
cmdwindow.x=msgwindow.x+msgwindow.width-cmdwindow.width
cmdwindow.x = msgwindow.x + msgwindow.width - cmdwindow.width
else
cmdwindow.x=msgwindow.x+msgwindow.width-cmdwindow.width
cmdwindow.x = msgwindow.x + msgwindow.width - cmdwindow.width
end
else
cmdwindow.height=Graphics.height if cmdwindow.height>Graphics.height
cmdwindow.x=0
cmdwindow.y=0
cmdwindow.height = Graphics.height if cmdwindow.height > Graphics.height
cmdwindow.x = 0
cmdwindow.y = 0
end
end
# internal function
def pbRepositionMessageWindow(msgwindow, linecount=2)
msgwindow.height=32*linecount+msgwindow.borderY
msgwindow.y=(Graphics.height)-(msgwindow.height)
if $game_system && $game_system.respond_to?("message_position")
def pbRepositionMessageWindow(msgwindow, linecount = 2)
msgwindow.height = (32 * linecount) + msgwindow.borderY
msgwindow.y = (Graphics.height) - (msgwindow.height)
if $game_system
case $game_system.message_position
when 0 # up
msgwindow.y=0
msgwindow.y = 0
when 1 # middle
msgwindow.y=(Graphics.height/2)-(msgwindow.height/2)
msgwindow.y = (Graphics.height / 2) - (msgwindow.height / 2)
when 2
msgwindow.y=(Graphics.height)-(msgwindow.height)
end
end
if $game_system && $game_system.respond_to?("message_frame")
if $game_system.message_frame != 0
msgwindow.opacity = 0
msgwindow.y = (Graphics.height) - (msgwindow.height)
end
msgwindow.opacity = 0 if $game_system.message_frame != 0
end
end
# internal function
def pbUpdateMsgWindowPos(msgwindow,event,eventChanged=false)
def pbUpdateMsgWindowPos(msgwindow, event, eventChanged = false)
if event
if eventChanged
msgwindow.resizeToFit2(msgwindow.text,Graphics.width*2/3,msgwindow.height)
msgwindow.resizeToFit2(msgwindow.text, Graphics.width * 2 / 3, msgwindow.height)
end
msgwindow.y=event.screen_y-48-msgwindow.height
if msgwindow.y<0
msgwindow.y=event.screen_y+24
msgwindow.y = event.screen_y - 48 - msgwindow.height
if msgwindow.y < 0
msgwindow.y = event.screen_y + 24
end
msgwindow.x=event.screen_x-(msgwindow.width/2)
msgwindow.x=0 if msgwindow.x<0
if msgwindow.x>Graphics.width-msgwindow.width
msgwindow.x=Graphics.width-msgwindow.width
msgwindow.x = event.screen_x - (msgwindow.width / 2)
msgwindow.x = 0 if msgwindow.x < 0
if msgwindow.x > Graphics.width - msgwindow.width
msgwindow.x = Graphics.width - msgwindow.width
end
else
curwidth=msgwindow.width
if curwidth!=Graphics.width
msgwindow.width=Graphics.width
msgwindow.width=Graphics.width
curwidth = msgwindow.width
if curwidth != Graphics.width
msgwindow.width = Graphics.width
msgwindow.width = Graphics.width
end
end
end
@@ -276,24 +276,24 @@ end
#===============================================================================
# Determine the colour of a background
#===============================================================================
def isDarkBackground(background,rect=nil)
def isDarkBackground(background, rect = nil)
return true if !background || background.disposed?
rect = background.rect if !rect
return true if rect.width<=0 || rect.height<=0
xSeg = (rect.width/16)
xLoop = (xSeg==0) ? 1 : 16
xStart = (xSeg==0) ? rect.x+(rect.width/2) : rect.x+xSeg/2
ySeg = (rect.height/16)
yLoop = (ySeg==0) ? 1 : 16
yStart = (ySeg==0) ? rect.y+(rect.height/2) : rect.y+ySeg/2
return true if rect.width <= 0 || rect.height <= 0
xSeg = (rect.width / 16)
xLoop = (xSeg == 0) ? 1 : 16
xStart = (xSeg == 0) ? rect.x + (rect.width / 2) : rect.x + (xSeg / 2)
ySeg = (rect.height / 16)
yLoop = (ySeg == 0) ? 1 : 16
yStart = (ySeg == 0) ? rect.y + (rect.height / 2) : rect.y + (ySeg / 2)
count = 0
y = yStart
r = 0; g = 0; b = 0
r = g = b = 0
yLoop.times do
x = xStart
xLoop.times do
clr = background.get_pixel(x,y)
if clr.alpha!=0
clr = background.get_pixel(x, y)
if clr.alpha != 0
r += clr.red
g += clr.green
b += clr.blue
@@ -303,51 +303,51 @@ def isDarkBackground(background,rect=nil)
end
y += ySeg
end
return true if count==0
return true if count == 0
r /= count
g /= 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
def isDarkWindowskin(windowskin)
return true if !windowskin || windowskin.disposed?
if windowskin.width==192 && windowskin.height==128
return isDarkBackground(windowskin,Rect.new(0,0,128,128))
elsif windowskin.width==128 && windowskin.height==128
return isDarkBackground(windowskin,Rect.new(0,0,64,64))
elsif windowskin.width==96 && windowskin.height==48
return isDarkBackground(windowskin,Rect.new(32,16,16,16))
if windowskin.width == 192 && windowskin.height == 128
return isDarkBackground(windowskin, Rect.new(0, 0, 128, 128))
elsif windowskin.width == 128 && windowskin.height == 128
return isDarkBackground(windowskin, Rect.new(0, 0, 64, 64))
elsif windowskin.width == 96 && windowskin.height == 48
return isDarkBackground(windowskin, Rect.new(32, 16, 16, 16))
else
clr = windowskin.get_pixel(windowskin.width/2, windowskin.height/2)
return (clr.red*0.299+clr.green*0.587+clr.blue*0.114)<160
clr = windowskin.get_pixel(windowskin.width / 2, windowskin.height / 2)
return ((clr.red * 0.299) + (clr.green * 0.587) + (clr.blue * 0.114)) < 160
end
end
#===============================================================================
# Determine which text colours to use based on the darkness of the background
#===============================================================================
def getSkinColor(windowskin,color,isDarkSkin)
def getSkinColor(windowskin, color, isDarkSkin)
if !windowskin || windowskin.disposed? ||
windowskin.width!=128 || windowskin.height!=128
windowskin.width != 128 || windowskin.height != 128
# Base color, shadow color (these are reversed on dark windowskins)
textcolors = [
"0070F8","78B8E8", # 1 Blue
"E82010","F8A8B8", # 2 Red
"60B048","B0D090", # 3 Green
"48D8D8","A8E0E0", # 4 Cyan
"D038B8","E8A0E0", # 5 Magenta
"E8D020","F8E888", # 6 Yellow
"A0A0A8","D0D0D8", # 7 Grey
"F0F0F8","C8C8D0", # 8 White
"9040E8","B8A8E0", # 9 Purple
"F89818","F8C898", # 10 Orange
colorToRgb32(MessageConfig::DARK_TEXT_MAIN_COLOR),
colorToRgb32(MessageConfig::DARK_TEXT_SHADOW_COLOR), # 11 Dark default
colorToRgb32(MessageConfig::LIGHT_TEXT_MAIN_COLOR),
colorToRgb32(MessageConfig::LIGHT_TEXT_SHADOW_COLOR) # 12 Light default
"0070F8", "78B8E8", # 1 Blue
"E82010", "F8A8B8", # 2 Red
"60B048", "B0D090", # 3 Green
"48D8D8", "A8E0E0", # 4 Cyan
"D038B8", "E8A0E0", # 5 Magenta
"E8D020", "F8E888", # 6 Yellow
"A0A0A8", "D0D0D8", # 7 Grey
"F0F0F8", "C8C8D0", # 8 White
"9040E8", "B8A8E0", # 9 Purple
"F89818", "F8C898", # 10 Orange
colorToRgb32(MessageConfig::DARK_TEXT_MAIN_COLOR),
colorToRgb32(MessageConfig::DARK_TEXT_SHADOW_COLOR), # 11 Dark default
colorToRgb32(MessageConfig::LIGHT_TEXT_MAIN_COLOR),
colorToRgb32(MessageConfig::LIGHT_TEXT_SHADOW_COLOR) # 12 Light default
]
if color==0 || color>textcolors.length/2 # No special colour, use default
if color == 0 || color > textcolors.length / 2 # No special colour, use default
if isDarkSkin # Dark background, light text
return shadowc3tag(MessageConfig::LIGHT_TEXT_MAIN_COLOR, MessageConfig::LIGHT_TEXT_SHADOW_COLOR)
end
@@ -355,15 +355,15 @@ def getSkinColor(windowskin,color,isDarkSkin)
return shadowc3tag(MessageConfig::DARK_TEXT_MAIN_COLOR, MessageConfig::DARK_TEXT_SHADOW_COLOR)
end
# Special colour as listed above
if isDarkSkin && color!=12 # Dark background, light text
return sprintf("<c3=%s,%s>",textcolors[2*(color-1)+1],textcolors[2*(color-1)])
if isDarkSkin && color != 12 # Dark background, light text
return sprintf("<c3=%s,%s>", textcolors[(2 * (color - 1)) + 1], textcolors[2 * (color - 1)])
end
# 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
color = 0 if color>=32
x = 64 + (color % 8) * 8
y = 96 + (color / 8) * 8
color = 0 if color >= 32
x = 64 + ((color % 8) * 8)
y = 96 + ((color / 8) * 8)
pixel = windowskin.get_pixel(x, y)
return shadowctagFromColor(pixel)
end
@@ -371,7 +371,7 @@ end
def getDefaultTextColors(windowskin)
if !windowskin || windowskin.disposed? ||
windowskin.width!=128 || windowskin.height!=128
windowskin.width != 128 || windowskin.height != 128
if isDarkWindowskin(windowskin)
return [MessageConfig::LIGHT_TEXT_MAIN_COLOR, MessageConfig::LIGHT_TEXT_SHADOW_COLOR] # White
else
@@ -380,26 +380,26 @@ def getDefaultTextColors(windowskin)
else # VX windowskin
color = windowskin.get_pixel(64, 96)
shadow = nil
isDark = (color.red+color.green+color.blue)/3 < 128
isDark = (color.red + color.green + color.blue) / 3 < 128
if isDark
shadow = Color.new(color.red+64,color.green+64,color.blue+64)
shadow = Color.new(color.red + 64, color.green + 64, color.blue + 64)
else
shadow = Color.new(color.red-64,color.green-64,color.blue-64)
shadow = Color.new(color.red - 64, color.green - 64, color.blue - 64)
end
return [color,shadow]
return [color, shadow]
end
end
#===============================================================================
# Makes sure a bitmap exists
#===============================================================================
def pbDoEnsureBitmap(bitmap,dwidth,dheight)
if !bitmap || bitmap.disposed? || bitmap.width<dwidth || bitmap.height<dheight
def pbDoEnsureBitmap(bitmap, dwidth, dheight)
if !bitmap || bitmap.disposed? || bitmap.width < dwidth || bitmap.height < dheight
oldfont = (bitmap && !bitmap.disposed?) ? bitmap.font : nil
bitmap.dispose if bitmap
bitmap = Bitmap.new([1,dwidth].max,[1,dheight].max)
bitmap&.dispose
bitmap = Bitmap.new([1, dwidth].max, [1, dheight].max)
(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
return bitmap
end
@@ -411,63 +411,66 @@ end
def pbSetSystemFont(bitmap)
bitmap.font.name = MessageConfig.pbGetSystemFontName
bitmap.font.size = MessageConfig::FONT_SIZE
bitmap.text_offset_y = MessageConfig::FONT_Y_OFFSET
end
# Sets a bitmap's font to the system small font.
def pbSetSmallFont(bitmap)
bitmap.font.name = MessageConfig.pbGetSmallFontName
bitmap.font.size = MessageConfig::SMALL_FONT_SIZE
bitmap.text_offset_y = MessageConfig::SMALL_FONT_Y_OFFSET
end
# Sets a bitmap's font to the system narrow font.
def pbSetNarrowFont(bitmap)
bitmap.font.name = MessageConfig.pbGetNarrowFontName
bitmap.font.size = MessageConfig::NARROW_FONT_SIZE
bitmap.text_offset_y = MessageConfig::NARROW_FONT_Y_OFFSET
end
#===============================================================================
# Blend colours, set the colour of all bitmaps in a sprite hash
#===============================================================================
def pbAlphaBlend(dstColor,srcColor)
r=(255*(srcColor.red-dstColor.red)/255)+dstColor.red
g=(255*(srcColor.green-dstColor.green)/255)+dstColor.green
b=(255*(srcColor.blue-dstColor.blue)/255)+dstColor.blue
a=(255*(srcColor.alpha-dstColor.alpha)/255)+dstColor.alpha
return Color.new(r,g,b,a)
def pbAlphaBlend(dstColor, srcColor)
r = (255 * (srcColor.red - dstColor.red) / 255) + dstColor.red
g = (255 * (srcColor.green - dstColor.green) / 255) + dstColor.green
b = (255 * (srcColor.blue - dstColor.blue) / 255) + dstColor.blue
a = (255 * (srcColor.alpha - dstColor.alpha) / 255) + dstColor.alpha
return Color.new(r, g, b, a)
end
def pbSrcOver(dstColor,srcColor)
er=srcColor.red*srcColor.alpha/255
eg=srcColor.green*srcColor.alpha/255
eb=srcColor.blue*srcColor.alpha/255
iea=255-srcColor.alpha
cr=dstColor.red*dstColor.alpha/255
cg=dstColor.green*dstColor.alpha/255
cb=dstColor.blue*dstColor.alpha/255
ica=255-dstColor.alpha
a=255-(iea*ica)/255
r=(iea*cr)/255+er
g=(iea*cg)/255+eg
b=(iea*cb)/255+eb
r=(a==0) ? 0 : r*255/a
g=(a==0) ? 0 : g*255/a
b=(a==0) ? 0 : b*255/a
return Color.new(r,g,b,a)
def pbSrcOver(dstColor, srcColor)
er = srcColor.red * srcColor.alpha / 255
eg = srcColor.green * srcColor.alpha / 255
eb = srcColor.blue * srcColor.alpha / 255
iea = 255 - srcColor.alpha
cr = dstColor.red * dstColor.alpha / 255
cg = dstColor.green * dstColor.alpha / 255
cb = dstColor.blue * dstColor.alpha / 255
ica = 255 - dstColor.alpha
a = 255 - ((iea * ica) / 255)
r = ((iea * cr) / 255) + er
g = ((iea * cg) / 255) + eg
b = ((iea * cb) / 255) + eb
r = (a == 0) ? 0 : r * 255 / a
g = (a == 0) ? 0 : g * 255 / a
b = (a == 0) ? 0 : b * 255 / a
return Color.new(r, g, b, a)
end
def pbSetSpritesToColor(sprites,color)
def pbSetSpritesToColor(sprites, color)
return if !sprites || !color
colors={}
for i in sprites
colors = {}
sprites.each do |i|
next if !i[1] || pbDisposed?(i[1])
colors[i[0]]=i[1].color.clone
i[1].color=pbSrcOver(i[1].color,color)
colors[i[0]] = i[1].color.clone
i[1].color = pbSrcOver(i[1].color, color)
end
Graphics.update
Input.update
for i in colors
colors.each do |i|
next if !sprites[i[0]]
sprites[i[0]].color=i[1]
sprites[i[0]].color = i[1]
end
end
@@ -483,8 +486,8 @@ def using(window)
end
def pbUpdateSpriteHash(windows)
for i in windows
window=i[1]
windows.each do |i|
window = i[1]
if window
if window.is_a?(Sprite) || window.is_a?(Window)
window.update if !pbDisposed?(window)
@@ -506,15 +509,15 @@ end
# Disposes all objects in the specified hash.
def pbDisposeSpriteHash(sprites)
return if !sprites
for i in sprites.keys
pbDisposeSprite(sprites,i)
sprites.each_key do |i|
pbDisposeSprite(sprites, i)
end
sprites.clear
end
# Disposes the specified graphics object within the specified hash. Basically
# like: sprites[id].dispose
def pbDisposeSprite(sprites,id)
def pbDisposeSprite(sprites, id)
sprite = sprites[id]
sprite.dispose if sprite && !pbDisposed?(sprite)
sprites[id] = nil
@@ -535,41 +538,43 @@ end
# Fades and window activations for sprite hashes
#===============================================================================
def pbPushFade
$game_temp.fadestate = [$game_temp.fadestate+1,0].max if $game_temp
$game_temp.fadestate = [$game_temp.fadestate + 1, 0].max if $game_temp
end
def pbPopFade
$game_temp.fadestate = [$game_temp.fadestate-1,0].max if $game_temp
$game_temp.fadestate = [$game_temp.fadestate - 1, 0].max if $game_temp
end
def pbIsFaded?
return ($game_temp) ? $game_temp.fadestate>0 : false
return ($game_temp) ? $game_temp.fadestate > 0 : false
end
# pbFadeOutIn(z) { block }
# Fades out the screen before a block is run and fades it back in after the
# block exits. z indicates the z-coordinate of the viewport used for this effect
def pbFadeOutIn(z=99999,nofadeout=false)
col=Color.new(0,0,0,0)
viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
viewport.z=z
numFrames = (Graphics.frame_rate*0.4).floor
alphaDiff = (255.0/numFrames).ceil
for j in 0..numFrames
col.set(0,0,0,j*alphaDiff)
viewport.color=col
def pbFadeOutIn(z = 99999, nofadeout = false)
col = Color.new(0, 0, 0, 0)
viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
viewport.z = z
numFrames = (Graphics.frame_rate * 0.4).floor
alphaDiff = (255.0 / numFrames).ceil
(0..numFrames).each do |j|
col.set(0, 0, 0, j * alphaDiff)
viewport.color = col
Graphics.update
Input.update
end
pbPushFade
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
pbPopFade
if !nofadeout
for j in 0..numFrames
col.set(0,0,0,(numFrames-j)*alphaDiff)
viewport.color=col
(0..numFrames).each do |j|
col.set(0, 0, 0, (numFrames - j) * alphaDiff)
viewport.color = col
Graphics.update
Input.update
end
@@ -578,15 +583,15 @@ def pbFadeOutIn(z=99999,nofadeout=false)
end
end
def pbFadeOutInWithUpdate(z,sprites,nofadeout=false)
col=Color.new(0,0,0,0)
viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
viewport.z=z
numFrames = (Graphics.frame_rate*0.4).floor
alphaDiff = (255.0/numFrames).ceil
for j in 0..numFrames
col.set(0,0,0,j*alphaDiff)
viewport.color=col
def pbFadeOutInWithUpdate(z, sprites, nofadeout = false)
col = Color.new(0, 0, 0, 0)
viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
viewport.z = z
numFrames = (Graphics.frame_rate * 0.4).floor
alphaDiff = (255.0 / numFrames).ceil
(0..numFrames).each do |j|
col.set(0, 0, 0, j * alphaDiff)
viewport.color = col
pbUpdateSpriteHash(sprites)
Graphics.update
Input.update
@@ -597,9 +602,9 @@ def pbFadeOutInWithUpdate(z,sprites,nofadeout=false)
ensure
pbPopFade
if !nofadeout
for j in 0..numFrames
col.set(0,0,0,(numFrames-j)*alphaDiff)
viewport.color=col
(0..numFrames).each do |j|
col.set(0, 0, 0, (numFrames - j) * alphaDiff)
viewport.color = col
pbUpdateSpriteHash(sprites)
Graphics.update
Input.update
@@ -611,31 +616,31 @@ end
# Similar to pbFadeOutIn, but pauses the music as it fades out.
# Requires scripts "Audio" (for bgm_pause) and "SpriteWindow" (for pbFadeOutIn).
def pbFadeOutInWithMusic(zViewport=99999)
def pbFadeOutInWithMusic(zViewport = 99999)
playingBGS = $game_system.getPlayingBGS
playingBGM = $game_system.getPlayingBGM
$game_system.bgm_pause(1.0)
$game_system.bgs_pause(1.0)
pos = $game_system.bgm_position
pbFadeOutIn(zViewport) {
yield
$game_system.bgm_position = pos
$game_system.bgm_resume(playingBGM)
$game_system.bgs_resume(playingBGS)
yield
$game_system.bgm_position = pos
$game_system.bgm_resume(playingBGM)
$game_system.bgs_resume(playingBGS)
}
end
def pbFadeOutAndHide(sprites)
visiblesprites = {}
numFrames = (Graphics.frame_rate*0.4).floor
alphaDiff = (255.0/numFrames).ceil
numFrames = (Graphics.frame_rate * 0.4).floor
alphaDiff = (255.0 / numFrames).ceil
pbDeactivateWindows(sprites) {
for j in 0..numFrames
pbSetSpritesToColor(sprites,Color.new(0,0,0,j*alphaDiff))
(0..numFrames).each do |j|
pbSetSpritesToColor(sprites, Color.new(0, 0, 0, j * alphaDiff))
(block_given?) ? yield : pbUpdateSpriteHash(sprites)
end
}
for i in sprites
sprites.each do |i|
next if !i[1]
next if pbDisposed?(i[1])
visiblesprites[i[0]] = true if i[1].visible
@@ -644,19 +649,19 @@ def pbFadeOutAndHide(sprites)
return visiblesprites
end
def pbFadeInAndShow(sprites,visiblesprites=nil)
def pbFadeInAndShow(sprites, visiblesprites = nil)
if visiblesprites
for i in visiblesprites
visiblesprites.each do |i|
if i[1] && sprites[i[0]] && !pbDisposed?(sprites[i[0]])
sprites[i[0]].visible = true
end
end
end
numFrames = (Graphics.frame_rate*0.4).floor
alphaDiff = (255.0/numFrames).ceil
numFrames = (Graphics.frame_rate * 0.4).floor
alphaDiff = (255.0 / numFrames).ceil
pbDeactivateWindows(sprites) {
for j in 0..numFrames
pbSetSpritesToColor(sprites,Color.new(0,0,0,((numFrames-j)*alphaDiff)))
(0..numFrames).each do |j|
pbSetSpritesToColor(sprites, Color.new(0, 0, 0, ((numFrames - j) * alphaDiff)))
(block_given?) ? yield : pbUpdateSpriteHash(sprites)
end
}
@@ -664,11 +669,11 @@ end
# Restores which windows are active for the given sprite hash.
# _activeStatuses_ is the result of a previous call to pbActivateWindows
def pbRestoreActivations(sprites,activeStatuses)
def pbRestoreActivations(sprites, activeStatuses)
return if !sprites || !activeStatuses
for k in activeStatuses.keys
if sprites[k] && sprites[k].is_a?(Window) && !pbDisposed?(sprites[k])
sprites[k].active=activeStatuses[k] ? true : false
activeStatuses.each_key do |k|
if sprites[k].is_a?(Window) && !pbDisposed?(sprites[k])
sprites[k].active = activeStatuses[k] ? true : false
end
end
end
@@ -677,29 +682,29 @@ end
# runs the code in the block, and reactivates them.
def pbDeactivateWindows(sprites)
if block_given?
pbActivateWindow(sprites,nil) { yield }
pbActivateWindow(sprites, nil) { yield }
else
pbActivateWindow(sprites,nil)
pbActivateWindow(sprites, nil)
end
end
# Activates a specific window of a sprite hash. _key_ is the key of the window
# in the sprite hash. If a code block is given, deactivates all windows except
# the specified window, runs the code in the block, and reactivates them.
def pbActivateWindow(sprites,key)
def pbActivateWindow(sprites, key)
return if !sprites
activeStatuses={}
for i in sprites
if i[1] && i[1].is_a?(Window) && !pbDisposed?(i[1])
activeStatuses[i[0]]=i[1].active
i[1].active=(i[0]==key)
activeStatuses = {}
sprites.each do |i|
if i[1].is_a?(Window) && !pbDisposed?(i[1])
activeStatuses[i[0]] = i[1].active
i[1].active = (i[0] == key)
end
end
if block_given?
begin
yield
ensure
pbRestoreActivations(sprites,activeStatuses)
pbRestoreActivations(sprites, activeStatuses)
end
return {}
else
@@ -715,18 +720,18 @@ end
# _background_ is a filename within the Graphics/Pictures/ folder and can be
# an animated image.
# _viewport_ is a viewport to place the background in.
def addBackgroundPlane(sprites,planename,background,viewport=nil)
sprites[planename]=AnimatedPlane.new(viewport)
bitmapName=pbResolveBitmap("Graphics/Pictures/#{background}")
if bitmapName==nil
def addBackgroundPlane(sprites, planename, background, viewport = nil)
sprites[planename] = AnimatedPlane.new(viewport)
bitmapName = pbResolveBitmap("Graphics/Pictures/#{background}")
if bitmapName.nil?
# Plane should exist in any case
sprites[planename].bitmap=nil
sprites[planename].visible=false
sprites[planename].bitmap = nil
sprites[planename].visible = false
else
sprites[planename].setBitmap(bitmapName)
for spr in sprites.values
sprites.each_value do |spr|
if spr.is_a?(Window)
spr.windowskin=nil
spr.windowskin = nil
end
end
end
@@ -738,17 +743,17 @@ end
# an animated image.
# _color_ is the color to use if the background can't be found.
# _viewport_ is a viewport to place the background in.
def addBackgroundOrColoredPlane(sprites,planename,background,color,viewport=nil)
bitmapName=pbResolveBitmap("Graphics/Pictures/#{background}")
if bitmapName==nil
def addBackgroundOrColoredPlane(sprites, planename, background, color, viewport = nil)
bitmapName = pbResolveBitmap("Graphics/Pictures/#{background}")
if bitmapName.nil?
# Plane should exist in any case
sprites[planename]=ColoredPlane.new(color,viewport)
sprites[planename] = ColoredPlane.new(color, viewport)
else
sprites[planename]=AnimatedPlane.new(viewport)
sprites[planename] = AnimatedPlane.new(viewport)
sprites[planename].setBitmap(bitmapName)
for spr in sprites.values
sprites.each_value do |spr|
if spr.is_a?(Window)
spr.windowskin=nil
spr.windowskin = nil
end
end
end
@@ -772,9 +777,9 @@ end
if !defined?(_INTL)
def _INTL(*args)
string=args[0].clone
for i in 1...args.length
string.gsub!(/\{#{i}\}/,"#{args[i]}")
string = args[0].clone
(1...args.length).each do |i|
string.gsub!(/\{#{i}\}/, args[i].to_s)
end
return string
end
@@ -782,10 +787,10 @@ end
if !defined?(_ISPRINTF)
def _ISPRINTF(*args)
string=args[0].clone
for i in 1...args.length
string = args[0].clone
(1...args.length).each do |i|
string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m|
next sprintf("%"+$1,args[i])
next sprintf("%" + $1, args[i])
}
end
return string
@@ -794,9 +799,9 @@ end
if !defined?(_MAPINTL)
def _MAPINTL(*args)
string=args[1].clone
for i in 2...args.length
string.gsub!(/\{#{i}\}/,"#{args[i+1]}")
string = args[1].clone
(2...args.length).each do |i|
string.gsub!(/\{#{i}\}/, args[i + 1].to_s)
end
return string
end

View File

@@ -6,7 +6,6 @@ class WindowCursorRect < Rect
def empty
return unless needs_update?(0, 0, 0, 0)
set(0, 0, 0, 0)
end
@@ -16,9 +15,7 @@ class WindowCursorRect < Rect
def set(x, y, width, height)
return unless needs_update?(x, y, width, height)
super(x, y, width, height)
@window.width = @window.width
end
@@ -78,108 +75,108 @@ class Window
@_windowskin
end
def initialize(viewport=nil)
@sprites={}
@spritekeys=[
"back",
"corner0","side0","scroll0",
"corner1","side1","scroll1",
"corner2","side2","scroll2",
"corner3","side3","scroll3",
"cursor","contents","pause"
def initialize(viewport = nil)
@sprites = {}
@spritekeys = [
"back",
"corner0", "side0", "scroll0",
"corner1", "side1", "scroll1",
"corner2", "side2", "scroll2",
"corner3", "side3", "scroll3",
"cursor", "contents", "pause"
]
@sidebitmaps=[nil,nil,nil,nil]
@cursorbitmap=nil
@bgbitmap=nil
@viewport=viewport
for i in @spritekeys
@sprites[i]=Sprite.new(@viewport)
@sidebitmaps = [nil, nil, nil, nil]
@cursorbitmap = nil
@bgbitmap = nil
@viewport = viewport
@spritekeys.each do |i|
@sprites[i] = Sprite.new(@viewport)
end
@disposed=false
@tone=Tone.new(0,0,0)
@color=Color.new(0,0,0,0)
@blankcontents=Bitmap.new(1,1) # RGSS2 requires this
@contents=@blankcontents
@_windowskin=nil
@rpgvx=false # Set to true to emulate RPGVX windows
@x=0
@y=0
@width=0
@openness=255
@height=0
@ox=0
@oy=0
@z=0
@stretch=true
@visible=true
@active=true
@blend_type=0
@contents_blend_type=0
@opacity=255
@back_opacity=255
@contents_opacity=255
@cursor_rect=WindowCursorRect.new(self)
@cursorblink=0
@cursoropacity=255
@pause=false
@pauseopacity=255
@pauseframe=0
@disposed = false
@tone = Tone.new(0, 0, 0)
@color = Color.new(0, 0, 0, 0)
@blankcontents = Bitmap.new(1, 1) # RGSS2 requires this
@contents = @blankcontents
@_windowskin = nil
@rpgvx = false # Set to true to emulate RPGVX windows
@x = 0
@y = 0
@width = 0
@openness = 255
@height = 0
@ox = 0
@oy = 0
@z = 0
@stretch = true
@visible = true
@active = true
@blend_type = 0
@contents_blend_type = 0
@opacity = 255
@back_opacity = 255
@contents_opacity = 255
@cursor_rect = WindowCursorRect.new(self)
@cursorblink = 0
@cursoropacity = 255
@pause = false
@pauseopacity = 255
@pauseframe = 0
privRefresh(true)
end
def dispose
if !self.disposed?
for i in @sprites
i[1].dispose if i[1]
@sprites[i[0]]=nil
@sprites.each do |i|
i[1]&.dispose
@sprites[i[0]] = nil
end
for i in 0...@sidebitmaps.length
@sidebitmaps[i].dispose if @sidebitmaps[i]
@sidebitmaps[i]=nil
@sidebitmaps.each_with_index do |bitmap, i|
bitmap&.dispose
@sidebitmaps[i] = nil
end
@blankcontents.dispose
@cursorbitmap.dispose if @cursorbitmap
@backbitmap.dispose if @backbitmap
@cursorbitmap&.dispose
@backbitmap&.dispose
@sprites.clear
@sidebitmaps.clear
@_windowskin=nil
@_contents=nil
@disposed=true
@_windowskin = nil
@_contents = nil
@disposed = true
end
end
def openness=(value)
@openness=value
@openness=0 if @openness<0
@openness=255 if @openness>255
@openness = value
@openness = 0 if @openness < 0
@openness = 255 if @openness > 255
privRefresh
end
def stretch=(value)
@stretch=value
@stretch = value
privRefresh(true)
end
def visible=(value)
@visible=value
@visible = value
privRefresh
end
def viewport=(value)
@viewport=value
for i in @spritekeys
@viewport = value
@spritekeys.each do |i|
@sprites[i].dispose
if @sprites[i].is_a?(Sprite)
@sprites[i]=Sprite.new(@viewport)
@sprites[i] = Sprite.new(@viewport)
else
@sprites[i]=nil
@sprites[i] = nil
end
end
privRefresh(true)
end
def z=(value)
@z=value
@z = value
privRefresh
end
@@ -188,417 +185,414 @@ class Window
end
def contents=(value)
@contents=value
@contents = value
privRefresh
end
def windowskin=(value)
@_windowskin=value
if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128
@rpgvx=true
@_windowskin = value
if value.is_a?(Bitmap) && !value.disposed? && value.width == 128
@rpgvx = true
else
@rpgvx=false
@rpgvx = false
end
privRefresh(true)
end
def ox=(value)
@ox=value
@ox = value
privRefresh
end
def active=(value)
@active=value
@active = value
privRefresh(true)
end
def cursor_rect=(value)
if !value
@cursor_rect.empty
if value
@cursor_rect.set(value.x, value.y, value.width, value.height)
else
@cursor_rect.set(value.x,value.y,value.width,value.height)
@cursor_rect.empty
end
end
def oy=(value)
@oy=value
@oy = value
privRefresh
end
def width=(value)
@width=value
@width = value
privRefresh(true)
end
def height=(value)
@height=value
@height = value
privRefresh(true)
end
def pause=(value)
@pause=value
@pauseopacity=0 if !value
@pause = value
@pauseopacity = 0 if !value
privRefresh
end
def x=(value)
@x=value
@x = value
privRefresh
end
def y=(value)
@y=value
@y = value
privRefresh
end
def opacity=(value)
@opacity=value
@opacity=0 if @opacity<0
@opacity=255 if @opacity>255
@opacity = value
@opacity = 0 if @opacity < 0
@opacity = 255 if @opacity > 255
privRefresh
end
def back_opacity=(value)
@back_opacity=value
@back_opacity=0 if @back_opacity<0
@back_opacity=255 if @back_opacity>255
@back_opacity = value
@back_opacity = 0 if @back_opacity < 0
@back_opacity = 255 if @back_opacity > 255
privRefresh
end
def contents_opacity=(value)
@contents_opacity=value
@contents_opacity=0 if @contents_opacity<0
@contents_opacity=255 if @contents_opacity>255
@contents_opacity = value
@contents_opacity = 0 if @contents_opacity < 0
@contents_opacity = 255 if @contents_opacity > 255
privRefresh
end
def tone=(value)
@tone=value
@tone = value
privRefresh
end
def color=(value)
@color=value
@color = value
privRefresh
end
def blend_type=(value)
@blend_type=value
@blend_type = value
privRefresh
end
def flash(color,duration)
def flash(color, duration)
return if disposed?
for i in @sprites
i[1].flash(color,duration)
@sprites.each do |i|
i[1].flash(color, duration)
end
end
def update
return if disposed?
mustchange=false
mustchange = false
if @active
if @cursorblink==0
@cursoropacity-=8
@cursorblink=1 if @cursoropacity<=128
if @cursorblink == 0
@cursoropacity -= 8
@cursorblink = 1 if @cursoropacity <= 128
else
@cursoropacity+=8
@cursorblink=0 if @cursoropacity>=255
@cursoropacity += 8
@cursorblink = 0 if @cursoropacity >= 255
end
mustchange=true if !@cursor_rect.empty?
mustchange = true if !@cursor_rect.empty?
else
mustchange=true if @cursoropacity!=128
@cursoropacity=128
mustchange = true if @cursoropacity != 128
@cursoropacity = 128
end
if @pause
@pauseframe=(Graphics.frame_count / 8) % 4
@pauseopacity=[@pauseopacity+64,255].min
mustchange=true
@pauseframe = (Graphics.frame_count / 8) % 4
@pauseopacity = [@pauseopacity + 64, 255].min
mustchange = true
end
privRefresh if mustchange
for i in @sprites
@sprites.each do |i|
i[1].update
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)
def ensureBitmap(bitmap, dwidth, dheight)
if !bitmap || bitmap.disposed? || bitmap.width < dwidth || bitmap.height < dheight
bitmap&.dispose
bitmap = Bitmap.new([1, dwidth].max, [1, dheight].max)
end
return bitmap
end
def tileBitmap(dstbitmap,dstrect,srcbitmap,srcrect)
def tileBitmap(dstbitmap, dstrect, srcbitmap, srcrect)
return if !srcbitmap || srcbitmap.disposed?
left=dstrect.x
top=dstrect.y
y=0;loop do break unless y<dstrect.height
x=0;loop do break unless x<dstrect.width
dstbitmap.blt(x+left,y+top,srcbitmap,srcrect)
x+=srcrect.width
left = dstrect.x
top = dstrect.y
y = 0
loop do
break unless y < dstrect.height
x = 0
loop do
break unless x < dstrect.width
dstbitmap.blt(x + left, y + top, srcbitmap, srcrect)
x += srcrect.width
end
y+=srcrect.height
y += srcrect.height
end
end
def privRefresh(changeBitmap=false)
def privRefresh(changeBitmap = false)
return if self.disposed?
backopac=self.back_opacity*self.opacity/255
contopac=self.contents_opacity
cursoropac=@cursoropacity*contopac/255
for i in 0...4
@sprites["corner#{i}"].bitmap=@_windowskin
@sprites["scroll#{i}"].bitmap=@_windowskin
backopac = self.back_opacity * self.opacity / 255
contopac = self.contents_opacity
cursoropac = @cursoropacity * contopac / 255
4.times do |i|
@sprites["corner#{i}"].bitmap = @_windowskin
@sprites["scroll#{i}"].bitmap = @_windowskin
end
@sprites["pause"].bitmap=@_windowskin
@sprites["contents"].bitmap=@contents
@sprites["pause"].bitmap = @_windowskin
@sprites["contents"].bitmap = @contents
if @_windowskin && !@_windowskin.disposed?
for i in 0...4
@sprites["corner#{i}"].opacity=@opacity
@sprites["corner#{i}"].tone=@tone
@sprites["corner#{i}"].color=@color
@sprites["corner#{i}"].blend_type=@blend_type
@sprites["corner#{i}"].visible=@visible
@sprites["side#{i}"].opacity=@opacity
@sprites["side#{i}"].tone=@tone
@sprites["side#{i}"].color=@color
@sprites["side#{i}"].blend_type=@blend_type
@sprites["side#{i}"].visible=@visible
@sprites["scroll#{i}"].opacity=@opacity
@sprites["scroll#{i}"].tone=@tone
@sprites["scroll#{i}"].blend_type=@blend_type
@sprites["scroll#{i}"].color=@color
@sprites["scroll#{i}"].visible=@visible
4.times do |i|
@sprites["corner#{i}"].opacity = @opacity
@sprites["corner#{i}"].tone = @tone
@sprites["corner#{i}"].color = @color
@sprites["corner#{i}"].blend_type = @blend_type
@sprites["corner#{i}"].visible = @visible
@sprites["side#{i}"].opacity = @opacity
@sprites["side#{i}"].tone = @tone
@sprites["side#{i}"].color = @color
@sprites["side#{i}"].blend_type = @blend_type
@sprites["side#{i}"].visible = @visible
@sprites["scroll#{i}"].opacity = @opacity
@sprites["scroll#{i}"].tone = @tone
@sprites["scroll#{i}"].blend_type = @blend_type
@sprites["scroll#{i}"].color = @color
@sprites["scroll#{i}"].visible = @visible
end
for i in ["back","cursor","pause","contents"]
@sprites[i].color=@color
@sprites[i].tone=@tone
@sprites[i].blend_type=@blend_type
["back", "cursor", "pause", "contents"].each do |i|
@sprites[i].color = @color
@sprites[i].tone = @tone
@sprites[i].blend_type = @blend_type
end
@sprites["contents"].blend_type=@contents_blend_type
@sprites["back"].opacity=backopac
@sprites["contents"].opacity=contopac
@sprites["cursor"].opacity=cursoropac
@sprites["pause"].opacity=@pauseopacity
@sprites["back"].visible=@visible
@sprites["contents"].visible=@visible && @openness==255
@sprites["pause"].visible=@visible && @pause
@sprites["cursor"].visible=@visible && @openness==255
hascontents=(@contents && !@contents.disposed?)
@sprites["contents"].blend_type = @contents_blend_type
@sprites["back"].opacity = backopac
@sprites["contents"].opacity = contopac
@sprites["cursor"].opacity = cursoropac
@sprites["pause"].opacity = @pauseopacity
@sprites["back"].visible = @visible
@sprites["contents"].visible = @visible && @openness == 255
@sprites["pause"].visible = @visible && @pause
@sprites["cursor"].visible = @visible && @openness == 255
hascontents = (@contents && !@contents.disposed?)
@sprites["scroll0"].visible = @visible && hascontents && @oy > 0
@sprites["scroll1"].visible = @visible && hascontents && @ox > 0
@sprites["scroll2"].visible = @visible && hascontents &&
(@contents.width - @ox) > @width-32
(@contents.width - @ox) > @width - 32
@sprites["scroll3"].visible = @visible && hascontents &&
(@contents.height - @oy) > @height-32
(@contents.height - @oy) > @height - 32
else
for i in 0...4
@sprites["corner#{i}"].visible=false
@sprites["side#{i}"].visible=false
@sprites["scroll#{i}"].visible=false
4.times do |i|
@sprites["corner#{i}"].visible = false
@sprites["side#{i}"].visible = false
@sprites["scroll#{i}"].visible = false
end
@sprites["contents"].visible=@visible && @openness==255
@sprites["contents"].color=@color
@sprites["contents"].tone=@tone
@sprites["contents"].blend_type=@contents_blend_type
@sprites["contents"].opacity=contopac
@sprites["back"].visible=false
@sprites["pause"].visible=false
@sprites["cursor"].visible=false
@sprites["contents"].visible = @visible && @openness == 255
@sprites["contents"].color = @color
@sprites["contents"].tone = @tone
@sprites["contents"].blend_type = @contents_blend_type
@sprites["contents"].opacity = contopac
@sprites["back"].visible = false
@sprites["pause"].visible = false
@sprites["cursor"].visible = false
end
for i in @sprites
i[1].z=@z
@sprites.each do |i|
i[1].z = @z
end
if @rpgvx
@sprites["cursor"].z=@z # For Compatibility
@sprites["contents"].z=@z # For Compatibility
@sprites["pause"].z=@z # For Compatibility
@sprites["cursor"].z = @z # For Compatibility
@sprites["contents"].z = @z # For Compatibility
@sprites["pause"].z = @z # For Compatibility
else
@sprites["cursor"].z=@z+1 # For Compatibility
@sprites["contents"].z=@z+2 # For Compatibility
@sprites["pause"].z=@z+2 # For Compatibility
@sprites["cursor"].z = @z + 1 # For Compatibility
@sprites["contents"].z = @z + 2 # For Compatibility
@sprites["pause"].z = @z + 2 # For Compatibility
end
if @rpgvx
trimX=64
trimY=0
backRect=Rect.new(0,0,64,64)
blindsRect=Rect.new(0,64,64,64)
trimX = 64
trimY = 0
backRect = Rect.new(0, 0, 64, 64)
blindsRect = Rect.new(0, 64, 64, 64)
else
trimX=128
trimY=0
backRect=Rect.new(0,0,128,128)
blindsRect=nil
trimX = 128
trimY = 0
backRect = Rect.new(0, 0, 128, 128)
blindsRect = nil
end
@sprites["corner0"].src_rect.set(trimX,trimY+0,16,16);
@sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16);
@sprites["corner2"].src_rect.set(trimX,trimY+48,16,16);
@sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16);
@sprites["scroll0"].src_rect.set(trimX+24, trimY+16, 16, 8) # up
@sprites["scroll3"].src_rect.set(trimX+24, trimY+40, 16, 8) # down
@sprites["scroll1"].src_rect.set(trimX+16, trimY+24, 8, 16) # left
@sprites["scroll2"].src_rect.set(trimX+40, trimY+24, 8, 16) # right
cursorX=trimX
cursorY=trimY+64
sideRects=[
Rect.new(trimX+16,trimY+0,32,16),
Rect.new(trimX,trimY+16,16,32),
Rect.new(trimX+48,trimY+16,16,32),
Rect.new(trimX+16,trimY+48,32,16)
@sprites["corner0"].src_rect.set(trimX, trimY + 0, 16, 16)
@sprites["corner1"].src_rect.set(trimX + 48, trimY + 0, 16, 16)
@sprites["corner2"].src_rect.set(trimX, trimY + 48, 16, 16)
@sprites["corner3"].src_rect.set(trimX + 48, trimY + 48, 16, 16)
@sprites["scroll0"].src_rect.set(trimX + 24, trimY + 16, 16, 8) # up
@sprites["scroll3"].src_rect.set(trimX + 24, trimY + 40, 16, 8) # down
@sprites["scroll1"].src_rect.set(trimX + 16, trimY + 24, 8, 16) # left
@sprites["scroll2"].src_rect.set(trimX + 40, trimY + 24, 8, 16) # right
cursorX = trimX
cursorY = trimY + 64
sideRects = [
Rect.new(trimX + 16, trimY + 0, 32, 16),
Rect.new(trimX, trimY + 16, 16, 32),
Rect.new(trimX + 48, trimY + 16, 16, 32),
Rect.new(trimX + 16, trimY + 48, 32, 16)
]
if @width>32 && @height>32
@sprites["contents"].src_rect.set(@ox,@oy,@width-32,@height-32)
if @width > 32 && @height > 32
@sprites["contents"].src_rect.set(@ox, @oy, @width - 32, @height - 32)
else
@sprites["contents"].src_rect.set(0,0,0,0)
@sprites["contents"].src_rect.set(0, 0, 0, 0)
end
pauseRects=[
trimX+32,trimY+64,
trimX+48,trimY+64,
trimX+32,trimY+80,
trimX+48,trimY+80,
pauseRects = [
trimX + 32, trimY + 64,
trimX + 48, trimY + 64,
trimX + 32, trimY + 80,
trimX + 48, trimY + 80
]
pauseWidth=16
pauseHeight=16
@sprites["pause"].src_rect.set(
pauseRects[@pauseframe*2],
pauseRects[@pauseframe*2+1],
pauseWidth,pauseHeight
)
@sprites["pause"].x=@x+(@width/2)-(pauseWidth/2)
@sprites["pause"].y=@y+@height-16 # 16 refers to skin margin
@sprites["contents"].x=@x+16
@sprites["contents"].y=@y+16
@sprites["corner0"].x=@x
@sprites["corner0"].y=@y
@sprites["corner1"].x=@x+@width-16
@sprites["corner1"].y=@y
@sprites["corner2"].x=@x
@sprites["corner2"].y=@y+@height-16
@sprites["corner3"].x=@x+@width-16
@sprites["corner3"].y=@y+@height-16
@sprites["side0"].x=@x+16
@sprites["side0"].y=@y
@sprites["side1"].x=@x
@sprites["side1"].y=@y+16
@sprites["side2"].x=@x+@width-16
@sprites["side2"].y=@y+16
@sprites["side3"].x=@x+16
@sprites["side3"].y=@y+@height-16
@sprites["scroll0"].x = @x+@width / 2 - 8
@sprites["scroll0"].y = @y+8
@sprites["scroll1"].x = @x+8
@sprites["scroll1"].y = @y+@height / 2 - 8
@sprites["scroll2"].x = @x+@width - 16
@sprites["scroll2"].y = @y+@height / 2 - 8
@sprites["scroll3"].x = @x+@width / 2 - 8
@sprites["scroll3"].y = @y+@height - 16
@sprites["back"].x=@x+2
@sprites["back"].y=@y+2
@sprites["cursor"].x=@x+16+@cursor_rect.x
@sprites["cursor"].y=@y+16+@cursor_rect.y
pauseWidth = 16
pauseHeight = 16
@sprites["pause"].src_rect.set(pauseRects[@pauseframe * 2],
pauseRects[(@pauseframe * 2) + 1],
pauseWidth,
pauseHeight)
@sprites["pause"].x = @x + (@width / 2) - (pauseWidth / 2)
@sprites["pause"].y = @y + @height - 16 # 16 refers to skin margin
@sprites["contents"].x = @x + 16
@sprites["contents"].y = @y + 16
@sprites["corner0"].x = @x
@sprites["corner0"].y = @y
@sprites["corner1"].x = @x + @width - 16
@sprites["corner1"].y = @y
@sprites["corner2"].x = @x
@sprites["corner2"].y = @y + @height - 16
@sprites["corner3"].x = @x + @width - 16
@sprites["corner3"].y = @y + @height - 16
@sprites["side0"].x = @x + 16
@sprites["side0"].y = @y
@sprites["side1"].x = @x
@sprites["side1"].y = @y + 16
@sprites["side2"].x = @x + @width - 16
@sprites["side2"].y = @y + 16
@sprites["side3"].x = @x + 16
@sprites["side3"].y = @y + @height - 16
@sprites["scroll0"].x = @x + (@width / 2) - 8
@sprites["scroll0"].y = @y + 8
@sprites["scroll1"].x = @x + 8
@sprites["scroll1"].y = @y + (@height / 2) - 8
@sprites["scroll2"].x = @x + @width - 16
@sprites["scroll2"].y = @y + (@height / 2) - 8
@sprites["scroll3"].x = @x + (@width / 2) - 8
@sprites["scroll3"].y = @y + @height - 16
@sprites["back"].x = @x + 2
@sprites["back"].y = @y + 2
@sprites["cursor"].x = @x + 16 + @cursor_rect.x
@sprites["cursor"].y = @y + 16 + @cursor_rect.y
if changeBitmap && @_windowskin && !@_windowskin.disposed?
width=@cursor_rect.width
height=@cursor_rect.height
width = @cursor_rect.width
height = @cursor_rect.height
if width > 0 && height > 0
cursorrects=[
# sides
Rect.new(cursorX+2, cursorY+0, 28, 2),
Rect.new(cursorX+0, cursorY+2, 2, 28),
Rect.new(cursorX+30, cursorY+2, 2, 28),
Rect.new(cursorX+2, cursorY+30, 28, 2),
# corners
Rect.new(cursorX+0, cursorY+0, 2, 2),
Rect.new(cursorX+30, cursorY+0, 2, 2),
Rect.new(cursorX+0, cursorY+30, 2, 2),
Rect.new(cursorX+30, cursorY+30, 2, 2),
# back
Rect.new(cursorX+2, cursorY+2, 28, 28)
cursorrects = [
# sides
Rect.new(cursorX + 2, cursorY + 0, 28, 2),
Rect.new(cursorX + 0, cursorY + 2, 2, 28),
Rect.new(cursorX + 30, cursorY + 2, 2, 28),
Rect.new(cursorX + 2, cursorY + 30, 28, 2),
# corners
Rect.new(cursorX + 0, cursorY + 0, 2, 2),
Rect.new(cursorX + 30, cursorY + 0, 2, 2),
Rect.new(cursorX + 0, cursorY + 30, 2, 2),
Rect.new(cursorX + 30, cursorY + 30, 2, 2),
# back
Rect.new(cursorX + 2, cursorY + 2, 28, 28)
]
margin=2
fullmargin=4
margin = 2
fullmargin = 4
@cursorbitmap = ensureBitmap(@cursorbitmap, width, height)
@cursorbitmap.clear
@sprites["cursor"].bitmap=@cursorbitmap
@sprites["cursor"].src_rect.set(0,0,width,height)
rect = Rect.new(margin,margin,
width - fullmargin, height - fullmargin)
@sprites["cursor"].bitmap = @cursorbitmap
@sprites["cursor"].src_rect.set(0, 0, width, height)
rect = Rect.new(margin, margin, width - fullmargin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8])
@cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4])# top left
@cursorbitmap.blt(width-margin, 0, @_windowskin, cursorrects[5]) # top right
@cursorbitmap.blt(0, height-margin, @_windowskin, cursorrects[6]) # bottom right
@cursorbitmap.blt(width-margin, height-margin, @_windowskin, cursorrects[7]) # bottom left
rect = Rect.new(margin, 0,
width - fullmargin, margin)
@cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4]) # top left
@cursorbitmap.blt(width - margin, 0, @_windowskin, cursorrects[5]) # top right
@cursorbitmap.blt(0, height - margin, @_windowskin, cursorrects[6]) # bottom right
@cursorbitmap.blt(width - margin, height - margin, @_windowskin, cursorrects[7]) # bottom left
rect = Rect.new(margin, 0, width - fullmargin, margin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0])
rect = Rect.new(0, margin,
margin, height - fullmargin)
rect = Rect.new(0, margin, margin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1])
rect = Rect.new(width - margin, margin,
margin, height - fullmargin)
rect = Rect.new(width - margin, margin, margin, height - fullmargin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2])
rect = Rect.new(margin, height-margin,
width - fullmargin, margin)
rect = Rect.new(margin, height - margin, width - fullmargin, margin)
@cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3])
else
@sprites["cursor"].visible=false
@sprites["cursor"].src_rect.set(0,0,0,0)
@sprites["cursor"].visible = false
@sprites["cursor"].src_rect.set(0, 0, 0, 0)
end
for i in 0...4
dwidth = (i==0 || i==3) ? @width-32 : 16
dheight = (i==0 || i==3) ? 16 : @height-32
@sidebitmaps[i]=ensureBitmap(@sidebitmaps[i],dwidth,dheight)
@sprites["side#{i}"].bitmap=@sidebitmaps[i]
@sprites["side#{i}"].src_rect.set(0,0,dwidth,dheight)
4.times do |i|
dwidth = [0, 3].include?(i) ? @width - 32 : 16
dheight = [0, 3].include?(i) ? 16 : @height - 32
@sidebitmaps[i] = ensureBitmap(@sidebitmaps[i], dwidth, dheight)
@sprites["side#{i}"].bitmap = @sidebitmaps[i]
@sprites["side#{i}"].src_rect.set(0, 0, dwidth, dheight)
@sidebitmaps[i].clear
if sideRects[i].width>0 && sideRects[i].height>0
@sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect,
@_windowskin,sideRects[i])
if sideRects[i].width > 0 && sideRects[i].height > 0
@sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect, @_windowskin, sideRects[i])
end
end
backwidth=@width-4
backheight=@height-4
if backwidth>0 && backheight>0
@backbitmap=ensureBitmap(@backbitmap,backwidth,backheight)
@sprites["back"].bitmap=@backbitmap
@sprites["back"].src_rect.set(0,0,backwidth,backheight)
backwidth = @width - 4
backheight = @height - 4
if backwidth > 0 && backheight > 0
@backbitmap = ensureBitmap(@backbitmap, backwidth, backheight)
@sprites["back"].bitmap = @backbitmap
@sprites["back"].src_rect.set(0, 0, backwidth, backheight)
@backbitmap.clear
if @stretch
@backbitmap.stretch_blt(@sprites["back"].src_rect,@_windowskin,backRect)
@backbitmap.stretch_blt(@sprites["back"].src_rect, @_windowskin, backRect)
else
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,backRect)
tileBitmap(@backbitmap, @sprites["back"].src_rect, @_windowskin, backRect)
end
if blindsRect
tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,blindsRect)
tileBitmap(@backbitmap, @sprites["back"].src_rect, @_windowskin, blindsRect)
end
else
@sprites["back"].visible=false
@sprites["back"].src_rect.set(0,0,0,0)
@sprites["back"].visible = false
@sprites["back"].src_rect.set(0, 0, 0, 0)
end
end
if @openness!=255
opn=@openness/255.0
for k in @spritekeys
sprite=@sprites[k]
ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height
sprite.zoom_y=opn
sprite.oy=0
sprite.y=(@y+(@height/2.0)+(@height*ratio*opn)-(@height/2*opn)).floor
if @openness == 255
@spritekeys.each do |k|
sprite = @sprites[k]
sprite.zoom_y = 1.0
end
else
for k in @spritekeys
sprite=@sprites[k]
sprite.zoom_y=1.0
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.oy = 0
sprite.y = (@y + (@height / 2.0) + (@height * ratio * opn) - (@height / 2 * opn)).floor
end
end
i=0
i = 0
# Ensure Z order
for k in @spritekeys
sprite=@sprites[k]
y=sprite.y
sprite.y=i
sprite.oy=(sprite.zoom_y<=0) ? 0 : (i-y)/sprite.zoom_y
@spritekeys.each do |k|
sprite = @sprites[k]
y = sprite.y
sprite.y = i
sprite.oy = (sprite.zoom_y <= 0) ? 0 : (i - y) / sprite.zoom_y
end
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -4,16 +4,16 @@
class IconWindow < SpriteWindow_Base
attr_reader :name
def initialize(x,y,width,height,viewport=nil)
super(x,y,width,height)
self.viewport=viewport
self.contents=nil
@name=""
@_iconbitmap=nil
def initialize(x, y, width, height, viewport = nil)
super(x, y, width, height)
self.viewport = viewport
self.contents = nil
@name = ""
@_iconbitmap = nil
end
def dispose
clearBitmaps()
clearBitmaps
super
end
@@ -21,14 +21,14 @@ class IconWindow < SpriteWindow_Base
super
if @_iconbitmap
@_iconbitmap.update
self.contents=@_iconbitmap.bitmap
self.contents = @_iconbitmap.bitmap
end
end
def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap=nil
self.contents=nil if !self.disposed?
@_iconbitmap&.dispose
@_iconbitmap = nil
self.contents = nil if !self.disposed?
end
# Sets the icon's filename. Alias for setBitmap.
@@ -37,16 +37,16 @@ class IconWindow < SpriteWindow_Base
end
# Sets the icon's filename.
def setBitmap(file,hue=0)
clearBitmaps()
@name=file
return if file==nil
if file!=""
@_iconbitmap=AnimatedBitmap.new(file,hue)
# for compatibility
self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil
def setBitmap(file, hue = 0)
clearBitmaps
@name = file
return if file.nil?
if file == ""
@_iconbitmap = nil
else
@_iconbitmap=nil
@_iconbitmap = AnimatedBitmap.new(file, hue)
# for compatibility
self.contents = @_iconbitmap ? @_iconbitmap.bitmap : nil
end
end
end
@@ -59,15 +59,15 @@ end
#===============================================================================
class PictureWindow < SpriteWindow_Base
def initialize(pathOrBitmap)
super(0,0,32,32)
self.viewport=viewport
self.contents=nil
@_iconbitmap=nil
super(0, 0, 32, 32)
self.viewport = viewport
self.contents = nil
@_iconbitmap = nil
setBitmap(pathOrBitmap)
end
def dispose
clearBitmaps()
clearBitmaps
super
end
@@ -75,47 +75,46 @@ class PictureWindow < SpriteWindow_Base
super
if @_iconbitmap
if @_iconbitmap.is_a?(Bitmap)
self.contents=@_iconbitmap
self.contents = @_iconbitmap
else
@_iconbitmap.update
self.contents=@_iconbitmap.bitmap
self.contents = @_iconbitmap.bitmap
end
end
end
def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap=nil
self.contents=nil if !self.disposed?
@_iconbitmap&.dispose
@_iconbitmap = nil
self.contents = nil if !self.disposed?
end
# Sets the icon's bitmap or filename. (hue parameter
# is ignored unless pathOrBitmap is a filename)
def setBitmap(pathOrBitmap,hue=0)
clearBitmaps()
if pathOrBitmap!=nil && pathOrBitmap!=""
if pathOrBitmap.is_a?(Bitmap)
@_iconbitmap=pathOrBitmap
self.contents=@_iconbitmap
self.width=@_iconbitmap.width+self.borderX
self.height=@_iconbitmap.height+self.borderY
elsif pathOrBitmap.is_a?(AnimatedBitmap)
@_iconbitmap=pathOrBitmap
self.contents=@_iconbitmap.bitmap
self.width=@_iconbitmap.bitmap.width+self.borderX
self.height=@_iconbitmap.bitmap.height+self.borderY
def setBitmap(pathOrBitmap, hue = 0)
clearBitmaps
if pathOrBitmap && pathOrBitmap != ""
case pathOrBitmap
when Bitmap
@_iconbitmap = pathOrBitmap
self.contents = @_iconbitmap
self.width = @_iconbitmap.width + self.borderX
self.height = @_iconbitmap.height + self.borderY
when AnimatedBitmap
@_iconbitmap = pathOrBitmap
self.contents = @_iconbitmap.bitmap
self.width = @_iconbitmap.bitmap.width + self.borderX
self.height = @_iconbitmap.bitmap.height + self.borderY
else
@_iconbitmap=AnimatedBitmap.new(pathOrBitmap,hue)
self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil
self.width=@_iconbitmap ? @_iconbitmap.bitmap.width+self.borderX :
32+self.borderX
self.height=@_iconbitmap ? @_iconbitmap.bitmap.height+self.borderY :
32+self.borderY
@_iconbitmap = AnimatedBitmap.new(pathOrBitmap, hue)
self.contents = @_iconbitmap&.bitmap
self.width = self.borderX + (@_iconbitmap&.bitmap&.width || 32)
self.height = self.borderY + (@_iconbitmap&.bitmap&.height || 32)
end
else
@_iconbitmap=nil
self.width=32+self.borderX
self.height=32+self.borderY
@_iconbitmap = nil
self.width = 32 + self.borderX
self.height = 32 + self.borderY
end
end
end

View File

@@ -2,52 +2,52 @@
# SpriteWrapper is a class which wraps (most of) Sprite's properties.
#===============================================================================
class SpriteWrapper
def initialize(viewport=nil)
def initialize(viewport = nil)
@sprite = Sprite.new(viewport)
end
def dispose; @sprite.dispose; end
def disposed?; return @sprite.disposed?; end
def viewport; return @sprite.viewport; end
def flash(color,duration); return @sprite.flash(color,duration); end
def update; return @sprite.update; end
def x; @sprite.x; end
def x=(value); @sprite.x = value; end
def y; @sprite.y; end
def y=(value); @sprite.y = value; end
def bitmap; @sprite.bitmap; end
def bitmap=(value); @sprite.bitmap = value; end
def src_rect; @sprite.src_rect; end
def src_rect=(value); @sprite.src_rect = value; end
def visible; @sprite.visible; end
def visible=(value); @sprite.visible = value; end
def z; @sprite.z; end
def z=(value); @sprite.z = value; end
def ox; @sprite.ox; end
def ox=(value); @sprite.ox = value; end
def oy; @sprite.oy; end
def oy=(value); @sprite.oy = value; end
def zoom_x; @sprite.zoom_x; end
def zoom_x=(value); @sprite.zoom_x = value; end
def zoom_y; @sprite.zoom_y; end
def zoom_y=(value); @sprite.zoom_y = value; end
def angle; @sprite.angle; end
def angle=(value); @sprite.angle = value; end
def mirror; @sprite.mirror; end
def mirror=(value); @sprite.mirror = value; end
def bush_depth; @sprite.bush_depth; end
def bush_depth=(value); @sprite.bush_depth = value; end
def opacity; @sprite.opacity; end
def opacity=(value); @sprite.opacity = value; end
def blend_type; @sprite.blend_type; end
def blend_type=(value); @sprite.blend_type = value; end
def color; @sprite.color; end
def color=(value); @sprite.color = value; end
def tone; @sprite.tone; end
def tone=(value); @sprite.tone = value; end
def dispose; @sprite.dispose; end
def disposed?; return @sprite.disposed?; end
def viewport; return @sprite.viewport; end
def flash(color, duration); return @sprite.flash(color, duration); end
def update; return @sprite.update; end
def x; @sprite.x; end
def x=(value); @sprite.x = value; end
def y; @sprite.y; end
def y=(value); @sprite.y = value; end
def bitmap; @sprite.bitmap; end
def bitmap=(value); @sprite.bitmap = value; end
def src_rect; @sprite.src_rect; end
def src_rect=(value); @sprite.src_rect = value; end
def visible; @sprite.visible; end
def visible=(value); @sprite.visible = value; end
def z; @sprite.z; end
def z=(value); @sprite.z = value; end
def ox; @sprite.ox; end
def ox=(value); @sprite.ox = value; end
def oy; @sprite.oy; end
def oy=(value); @sprite.oy = value; end
def zoom_x; @sprite.zoom_x; end
def zoom_x=(value); @sprite.zoom_x = value; end
def zoom_y; @sprite.zoom_y; end
def zoom_y=(value); @sprite.zoom_y = value; end
def angle; @sprite.angle; end
def angle=(value); @sprite.angle = value; end
def mirror; @sprite.mirror; end
def mirror=(value); @sprite.mirror = value; end
def bush_depth; @sprite.bush_depth; end
def bush_depth=(value); @sprite.bush_depth = value; end
def opacity; @sprite.opacity; end
def opacity=(value); @sprite.opacity = value; end
def blend_type; @sprite.blend_type; end
def blend_type=(value); @sprite.blend_type = value; end
def color; @sprite.color; end
def color=(value); @sprite.color = value; end
def tone; @sprite.tone; end
def tone=(value); @sprite.tone = value; end
def viewport=(value)
return if self.viewport==value
return if self.viewport == value
bitmap = @sprite.bitmap
src_rect = @sprite.src_rect
visible = @sprite.visible
@@ -94,10 +94,10 @@ end
# This bitmap can't be changed to a different one.
#===============================================================================
class BitmapSprite < SpriteWrapper
def initialize(width,height,viewport=nil)
def initialize(width, height, viewport = nil)
super(viewport)
self.bitmap=Bitmap.new(width,height)
@initialized=true
self.bitmap = Bitmap.new(width, height)
@initialized = true
end
def bitmap=(value)
@@ -122,82 +122,82 @@ class AnimatedSprite < SpriteWrapper
attr_reader :framecount
attr_reader :animname
def initializeLong(animname,framecount,framewidth,frameheight,frameskip)
@animname=pbBitmapName(animname)
@realframes=0
@frameskip=[1,frameskip].max
@frameskip *= Graphics.frame_rate/20
raise _INTL("Frame width is 0") if framewidth==0
raise _INTL("Frame height is 0") if frameheight==0
def initializeLong(animname, framecount, framewidth, frameheight, frameskip)
@animname = pbBitmapName(animname)
@realframes = 0
@frameskip = [1, frameskip].max
@frameskip *= Graphics.frame_rate / 20
raise _INTL("Frame width is 0") if framewidth == 0
raise _INTL("Frame height is 0") if frameheight == 0
begin
@animbitmap=AnimatedBitmap.new(animname).deanimate
@animbitmap = AnimatedBitmap.new(animname).deanimate
rescue
@animbitmap=Bitmap.new(framewidth,frameheight)
@animbitmap = Bitmap.new(framewidth, frameheight)
end
if @animbitmap.width%framewidth!=0
if @animbitmap.width % framewidth != 0
raise _INTL("Bitmap's width ({1}) is not a multiple of frame width ({2}) [Bitmap={3}]",
@animbitmap.width,framewidth,animname)
@animbitmap.width, framewidth, animname)
end
if @animbitmap.height%frameheight!=0
if @animbitmap.height % frameheight != 0
raise _INTL("Bitmap's height ({1}) is not a multiple of frame height ({2}) [Bitmap={3}]",
@animbitmap.height,frameheight,animname)
@animbitmap.height, frameheight, animname)
end
@framecount=framecount
@framewidth=framewidth
@frameheight=frameheight
@framesperrow=@animbitmap.width/@framewidth
@playing=false
self.bitmap=@animbitmap
self.src_rect.width=@framewidth
self.src_rect.height=@frameheight
self.frame=0
@framecount = framecount
@framewidth = framewidth
@frameheight = frameheight
@framesperrow = @animbitmap.width / @framewidth
@playing = false
self.bitmap = @animbitmap
self.src_rect.width = @framewidth
self.src_rect.height = @frameheight
self.frame = 0
end
# Shorter version of AnimationSprite. All frames are placed on a single row
# of the bitmap, so that the width and height need not be defined beforehand
def initializeShort(animname,framecount,frameskip)
@animname=pbBitmapName(animname)
@realframes=0
@frameskip=[1,frameskip].max
@frameskip *= Graphics.frame_rate/20
def initializeShort(animname, framecount, frameskip)
@animname = pbBitmapName(animname)
@realframes = 0
@frameskip = [1, frameskip].max
@frameskip *= Graphics.frame_rate / 20
begin
@animbitmap=AnimatedBitmap.new(animname).deanimate
@animbitmap = AnimatedBitmap.new(animname).deanimate
rescue
@animbitmap=Bitmap.new(framecount*4,32)
@animbitmap = Bitmap.new(framecount * 4, 32)
end
if @animbitmap.width%framecount!=0
if @animbitmap.width % framecount != 0
raise _INTL("Bitmap's width ({1}) is not a multiple of frame count ({2}) [Bitmap={3}]",
@animbitmap.width,framewidth,animname)
@animbitmap.width, framewidth, animname)
end
@framecount=framecount
@framewidth=@animbitmap.width/@framecount
@frameheight=@animbitmap.height
@framesperrow=framecount
@playing=false
self.bitmap=@animbitmap
self.src_rect.width=@framewidth
self.src_rect.height=@frameheight
self.frame=0
@framecount = framecount
@framewidth = @animbitmap.width / @framecount
@frameheight = @animbitmap.height
@framesperrow = framecount
@playing = false
self.bitmap = @animbitmap
self.src_rect.width = @framewidth
self.src_rect.height = @frameheight
self.frame = 0
end
def initialize(*args)
if args.length==1
if args.length == 1
super(args[0][3])
initializeShort(args[0][0],args[0][1],args[0][2])
initializeShort(args[0][0], args[0][1], args[0][2])
else
super(args[5])
initializeLong(args[0],args[1],args[2],args[3],args[4])
initializeLong(args[0], args[1], args[2], args[3], args[4])
end
end
def self.create(animname,framecount,frameskip,viewport=nil)
return self.new([animname,framecount,frameskip,viewport])
def self.create(animname, framecount, frameskip, viewport = nil)
return self.new([animname, framecount, frameskip, viewport])
end
def dispose
return if disposed?
@animbitmap.dispose
@animbitmap=nil
@animbitmap = nil
super
end
@@ -206,31 +206,31 @@ class AnimatedSprite < SpriteWrapper
end
def frame=(value)
@frame=value
@realframes=0
self.src_rect.x=@frame%@framesperrow*@framewidth
self.src_rect.y=@frame/@framesperrow*@frameheight
@frame = value
@realframes = 0
self.src_rect.x = @frame % @framesperrow * @framewidth
self.src_rect.y = @frame / @framesperrow * @frameheight
end
def start
@playing=true
@realframes=0
@playing = true
@realframes = 0
end
alias play start
def stop
@playing=false
@playing = false
end
def update
super
if @playing
@realframes+=1
if @realframes==@frameskip
@realframes=0
self.frame+=1
self.frame%=self.framecount
@realframes += 1
if @realframes == @frameskip
@realframes = 0
self.frame += 1
self.frame %= self.framecount
end
end
end
@@ -245,27 +245,28 @@ class IconSprite < SpriteWrapper
attr_reader :name
def initialize(*args)
if args.length==0
case args.length
when 0
super(nil)
self.bitmap=nil
elsif args.length==1
self.bitmap = nil
when 1
super(args[0])
self.bitmap=nil
elsif args.length==2
self.bitmap = nil
when 2
super(nil)
self.x=args[0]
self.y=args[1]
self.x = args[0]
self.y = args[1]
else
super(args[2])
self.x=args[0]
self.y=args[1]
self.x = args[0]
self.y = args[1]
end
@name=""
@_iconbitmap=nil
@name = ""
@_iconbitmap = nil
end
def dispose
clearBitmaps()
clearBitmaps
super
end
@@ -275,35 +276,35 @@ class IconSprite < SpriteWrapper
end
# Sets the icon's filename.
def setBitmap(file,hue=0)
oldrc=self.src_rect
clearBitmaps()
@name=file
return if file==nil
if file!=""
@_iconbitmap=AnimatedBitmap.new(file,hue)
# for compatibility
self.bitmap=@_iconbitmap ? @_iconbitmap.bitmap : nil
self.src_rect=oldrc
def setBitmap(file, hue = 0)
oldrc = self.src_rect
clearBitmaps
@name = file
return if file.nil?
if file == ""
@_iconbitmap = nil
else
@_iconbitmap=nil
@_iconbitmap = AnimatedBitmap.new(file, hue)
# for compatibility
self.bitmap = @_iconbitmap ? @_iconbitmap.bitmap : nil
self.src_rect = oldrc
end
end
def clearBitmaps
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap=nil
self.bitmap=nil if !self.disposed?
@_iconbitmap&.dispose
@_iconbitmap = nil
self.bitmap = nil if !self.disposed?
end
def update
super
return if !@_iconbitmap
@_iconbitmap.update
if self.bitmap!=@_iconbitmap.bitmap
oldrc=self.src_rect
self.bitmap=@_iconbitmap.bitmap
self.src_rect=oldrc
if self.bitmap != @_iconbitmap.bitmap
oldrc = self.src_rect
self.bitmap = @_iconbitmap.bitmap
self.src_rect = oldrc
end
end
end
@@ -315,7 +316,7 @@ end
#===============================================================================
class GifSprite < IconSprite
def initialize(path)
super(0,0)
super(0, 0)
setBitmap(path)
end
end
@@ -326,7 +327,7 @@ end
# SpriteWrapper that stores multiple bitmaps, and displays only one at once.
#===============================================================================
class ChangelingSprite < SpriteWrapper
def initialize(x=0,y=0,viewport=nil)
def initialize(x = 0, y = 0, viewport = nil)
super(viewport)
self.x = x
self.y = y
@@ -334,8 +335,8 @@ class ChangelingSprite < SpriteWrapper
@currentBitmap = nil
end
def addBitmap(key,path)
@bitmaps[key].dispose if @bitmaps[key]
def addBitmap(key, path)
@bitmaps[key]&.dispose
@bitmaps[key] = AnimatedBitmap.new(path)
end
@@ -346,14 +347,14 @@ class ChangelingSprite < SpriteWrapper
def dispose
return if disposed?
for bm in @bitmaps.values; bm.dispose; end
@bitmaps.each_value { |bm| bm.dispose }
@bitmaps.clear
super
end
def update
return if disposed?
for bm in @bitmaps.values; bm.update; end
@bitmaps.each_value { |bm| bm.update }
self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil
end
end

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,32 +2,28 @@
#
#===============================================================================
class CharacterEntryHelper
attr_reader :text
attr_accessor :text
attr_accessor :maxlength
attr_reader :passwordChar
attr_accessor :cursor
def initialize(text)
@maxlength=-1
@text=text
@passwordChar=""
@cursor=text.scan(/./m).length
end
def text=(value)
@text=value
@maxlength = -1
@text = text
@passwordChar = ""
@cursor = text.scan(/./m).length
end
def textChars
chars=text.scan(/./m)
if @passwordChar!=""
chars = text.scan(/./m)
if @passwordChar != ""
chars.length.times { |i| chars[i] = @passwordChar }
end
return chars
end
def passwordChar=(value)
@passwordChar=value ? value : ""
@passwordChar = value || ""
end
def length
@@ -35,52 +31,52 @@ class CharacterEntryHelper
end
def canInsert?
chars=self.text.scan(/./m)
return false if @maxlength>=0 && chars.length>=@maxlength
chars = self.text.scan(/./m)
return false if @maxlength >= 0 && chars.length >= @maxlength
return true
end
def insert(ch)
chars=self.text.scan(/./m)
return false if @maxlength>=0 && chars.length>=@maxlength
chars.insert(@cursor,ch)
@text=""
for ch in chars
@text+=ch if ch
chars = self.text.scan(/./m)
return false if @maxlength >= 0 && chars.length >= @maxlength
chars.insert(@cursor, ch)
@text = ""
chars.each do |ch|
@text += ch if ch
end
@cursor+=1
@cursor += 1
return true
end
def canDelete?
chars=self.text.scan(/./m)
return false if chars.length<=0 || @cursor<=0
chars = self.text.scan(/./m)
return false if chars.length <= 0 || @cursor <= 0
return true
end
def delete
chars=self.text.scan(/./m)
return false if chars.length<=0 || @cursor<=0
chars.delete_at(@cursor-1)
@text=""
for ch in chars
@text+=ch if ch
chars = self.text.scan(/./m)
return false if chars.length <= 0 || @cursor <= 0
chars.delete_at(@cursor - 1)
@text = ""
chars.each do |ch|
@text += ch if ch
end
@cursor-=1
@cursor -= 1
return true
end
private
def ensure
return if @maxlength<0
chars=self.text.scan(/./m)
if chars.length>@maxlength && @maxlength>=0
chars=chars[0,@maxlength]
return if @maxlength < 0
chars = self.text.scan(/./m)
if chars.length > @maxlength && @maxlength >= 0
chars = chars[0, @maxlength]
end
@text=""
for ch in chars
@text+=ch if ch
@text = ""
chars.each do |ch|
@text += ch if ch
end
end
end
@@ -91,19 +87,19 @@ end
#
#===============================================================================
class Window_TextEntry < SpriteWindow_Base
def initialize(text,x,y,width,height,heading=nil,usedarkercolor=false)
super(x,y,width,height)
colors=getDefaultTextColors(self.windowskin)
@baseColor=colors[0]
@shadowColor=colors[1]
def initialize(text, x, y, width, height, heading = nil, usedarkercolor = false)
super(x, y, width, height)
colors = getDefaultTextColors(self.windowskin)
@baseColor = colors[0]
@shadowColor = colors[1]
if usedarkercolor
@baseColor=Color.new(16,24,32)
@shadowColor=Color.new(168,184,184)
@baseColor = Color.new(16, 24, 32)
@shadowColor = Color.new(168, 184, 184)
end
@helper=CharacterEntryHelper.new(text)
@heading=heading
self.active=true
@frame=0
@helper = CharacterEntryHelper.new(text)
@heading = heading
self.active = true
@frame = 0
refresh
end
@@ -120,23 +116,23 @@ class Window_TextEntry < SpriteWindow_Base
end
def text=(value)
@helper.text=value
@helper.text = value
self.refresh
end
def passwordChar=(value)
@helper.passwordChar=value
@helper.passwordChar = value
refresh
end
def maxlength=(value)
@helper.maxlength=value
@helper.maxlength = value
self.refresh
end
def insert(ch)
if @helper.insert(ch)
@frame=0
@frame = 0
self.refresh
return true
end
@@ -145,7 +141,7 @@ class Window_TextEntry < SpriteWindow_Base
def delete
if @helper.delete
@frame=0
@frame = 0
self.refresh
return true
end
@@ -155,7 +151,7 @@ class Window_TextEntry < SpriteWindow_Base
def update
@frame += 1
@frame %= 20
self.refresh if (@frame%10)==0
self.refresh if (@frame % 10) == 0
return if !self.active
# Moving cursor
if Input.repeat?(Input::LEFT) && Input.press?(Input::ACTION)
@@ -176,47 +172,47 @@ class Window_TextEntry < SpriteWindow_Base
end
def refresh
self.contents=pbDoEnsureBitmap(self.contents,self.width-self.borderX,
self.height-self.borderY)
bitmap=self.contents
self.contents = pbDoEnsureBitmap(self.contents, self.width - self.borderX,
self.height - self.borderY)
bitmap = self.contents
bitmap.clear
x=0
y=0
x = 0
y = 0
if @heading
textwidth=bitmap.text_size(@heading).width
pbDrawShadowText(bitmap,x,y, textwidth+4, 32, @heading,@baseColor,@shadowColor)
y+=32
textwidth = bitmap.text_size(@heading).width
pbDrawShadowText(bitmap, x, y, textwidth + 4, 32, @heading, @baseColor, @shadowColor)
y += 32
end
x+=4
width=self.width-self.borderX
cursorcolor=Color.new(16,24,32)
textscan=self.text.scan(/./m)
scanlength=textscan.length
@helper.cursor=scanlength if @helper.cursor>scanlength
@helper.cursor=0 if @helper.cursor<0
startpos=@helper.cursor
fromcursor=0
while (startpos>0)
c=(@helper.passwordChar!="") ? @helper.passwordChar : textscan[startpos-1]
fromcursor+=bitmap.text_size(c).width
break if fromcursor>width-4
startpos-=1
x += 4
width = self.width - self.borderX
cursorcolor = Color.new(16, 24, 32)
textscan = self.text.scan(/./m)
scanlength = textscan.length
@helper.cursor = scanlength if @helper.cursor > scanlength
@helper.cursor = 0 if @helper.cursor < 0
startpos = @helper.cursor
fromcursor = 0
while startpos > 0
c = (@helper.passwordChar != "") ? @helper.passwordChar : textscan[startpos - 1]
fromcursor += bitmap.text_size(c).width
break if fromcursor > width - 4
startpos -= 1
end
for i in startpos...scanlength
c=(@helper.passwordChar!="") ? @helper.passwordChar : textscan[i]
textwidth=bitmap.text_size(c).width
next if c=="\n"
(startpos...scanlength).each do |i|
c = (@helper.passwordChar != "") ? @helper.passwordChar : textscan[i]
textwidth = bitmap.text_size(c).width
next if c == "\n"
# Draw text
pbDrawShadowText(bitmap,x,y, textwidth+4, 32, c,@baseColor,@shadowColor)
pbDrawShadowText(bitmap, x, y, textwidth + 4, 32, c, @baseColor, @shadowColor)
# Draw cursor if necessary
if ((@frame/10)&1) == 0 && i==@helper.cursor
bitmap.fill_rect(x,y+4,2,24,cursorcolor)
if ((@frame / 10) & 1) == 0 && i == @helper.cursor
bitmap.fill_rect(x, y + 4, 2, 24, cursorcolor)
end
# Add x to drawn text width
x += textwidth
end
if ((@frame/10)&1) == 0 && textscan.length==@helper.cursor
bitmap.fill_rect(x,y+4,2,24,cursorcolor)
if ((@frame / 10) & 1) == 0 && textscan.length == @helper.cursor
bitmap.fill_rect(x, y + 4, 2, 24, cursorcolor)
end
end
end
@@ -228,27 +224,27 @@ end
#===============================================================================
class Window_TextEntry_Keyboard < Window_TextEntry
def update
@frame+=1
@frame%=20
self.refresh if ((@frame%10)==0)
@frame += 1
@frame %= 20
self.refresh if (@frame % 10) == 0
return if !self.active
# Moving cursor
if Input.triggerex?(:LEFT) || Input.repeatex?(:LEFT)
if @helper.cursor > 0
@helper.cursor-=1
@frame=0
@helper.cursor -= 1
@frame = 0
self.refresh
end
return
elsif Input.triggerex?(:RIGHT) || Input.repeatex?(:RIGHT)
if @helper.cursor < self.text.scan(/./m).length
@helper.cursor+=1
@frame=0
@helper.cursor += 1
@frame = 0
self.refresh
end
return
elsif Input.triggerex?(:BACKSPACE) || Input.repeatex?(:BACKSPACE)
self.delete if @helper.cursor>0
self.delete if @helper.cursor > 0
return
elsif Input.triggerex?(:RETURN) || Input.triggerex?(:ESCAPE)
return
@@ -263,17 +259,17 @@ end
#
#===============================================================================
class Window_MultilineTextEntry < SpriteWindow_Base
def initialize(text,x,y,width,height)
super(x,y,width,height)
colors=getDefaultTextColors(self.windowskin)
@baseColor=colors[0]
@shadowColor=colors[1]
@helper=CharacterEntryHelper.new(text)
@firstline=0
@cursorLine=0
@cursorColumn=0
@frame=0
self.active=true
def initialize(text, x, y, width, height)
super(x, y, width, height)
colors = getDefaultTextColors(self.windowskin)
@baseColor = colors[0]
@shadowColor = colors[1]
@helper = CharacterEntryHelper.new(text)
@firstline = 0
@cursorLine = 0
@cursorColumn = 0
@frame = 0
self.active = true
refresh
end
@@ -281,12 +277,12 @@ class Window_MultilineTextEntry < SpriteWindow_Base
attr_reader :shadowColor
def baseColor=(value)
@baseColor=value
@baseColor = value
refresh
end
def shadowColor=(value)
@shadowColor=value
@shadowColor = value
refresh
end
@@ -299,23 +295,23 @@ class Window_MultilineTextEntry < SpriteWindow_Base
end
def text=(value)
@helper.text=value
@textchars=nil
@helper.text = value
@textchars = nil
self.refresh
end
def maxlength=(value)
@helper.maxlength=value
@textchars=nil
@helper.maxlength = value
@textchars = nil
self.refresh
end
def insert(ch)
@helper.cursor=getPosFromLineAndColumn(@cursorLine,@cursorColumn)
@helper.cursor = getPosFromLineAndColumn(@cursorLine, @cursorColumn)
if @helper.insert(ch)
@frame=0
@textchars=nil
moveCursor(0,1)
@frame = 0
@textchars = nil
moveCursor(0, 1)
self.refresh
return true
end
@@ -323,11 +319,11 @@ class Window_MultilineTextEntry < SpriteWindow_Base
end
def delete
@helper.cursor=getPosFromLineAndColumn(@cursorLine,@cursorColumn)
@helper.cursor = getPosFromLineAndColumn(@cursorLine, @cursorColumn)
if @helper.delete
@frame=0
moveCursor(0,-1) # use old textchars
@textchars=nil
@frame = 0
moveCursor(0, -1) # use old textchars
@textchars = nil
self.refresh
return true
end
@@ -336,67 +332,67 @@ class Window_MultilineTextEntry < SpriteWindow_Base
def getTextChars
if !@textchars
@textchars=getLineBrokenText(self.contents,@helper.text,
self.contents.width,nil)
@textchars = getLineBrokenText(self.contents, @helper.text,
self.contents.width, nil)
end
return @textchars
end
def getTotalLines
textchars=getTextChars
return 1 if textchars.length==0
tchar=textchars[textchars.length-1]
return tchar[5]+1
textchars = getTextChars
return 1 if textchars.length == 0
tchar = textchars[textchars.length - 1]
return tchar[5] + 1
end
def getLineY(line)
textchars=getTextChars
return 0 if textchars.length==0
totallines=getTotalLines()
line=0 if line<0
line=totallines-1 if line>=totallines
maximumY=0
for i in 0...textchars.length
thisline=textchars[i][5]
y=textchars[i][2]
return y if thisline==line
maximumY=y if maximumY<y
textchars = getTextChars
return 0 if textchars.length == 0
totallines = getTotalLines
line = 0 if line < 0
line = totallines - 1 if line >= totallines
maximumY = 0
textchars.each do |text|
thisline = text[5]
y = text[2]
return y if thisline == line
maximumY = y if maximumY < y
end
return maximumY
end
def getColumnsInLine(line)
textchars=getTextChars
return 0 if textchars.length==0
totallines=getTotalLines()
line=0 if line<0
line=totallines-1 if line>=totallines
endpos=0
for i in 0...textchars.length
thisline=textchars[i][5]
thislength=textchars[i][8]
endpos+=thislength if thisline==line
textchars = getTextChars
return 0 if textchars.length == 0
totallines = getTotalLines
line = 0 if line < 0
line = totallines - 1 if line >= totallines
endpos = 0
textchars.each do |text|
thisline = text[5]
thislength = text[8]
endpos += thislength if thisline == line
end
return endpos
end
def getPosFromLineAndColumn(line,column)
textchars=getTextChars
return 0 if textchars.length==0
totallines=getTotalLines()
line=0 if line<0
line=totallines-1 if line>=totallines
endpos=0
for i in 0...textchars.length
thisline=textchars[i][5]
thispos=textchars[i][6]
thiscolumn=textchars[i][7]
thislength=textchars[i][8]
if thisline==line
endpos=thispos+thislength
def getPosFromLineAndColumn(line, column)
textchars = getTextChars
return 0 if textchars.length == 0
totallines = getTotalLines
line = 0 if line < 0
line = totallines - 1 if line >= totallines
endpos = 0
textchars.each do |text|
thisline = text[5]
thispos = text[6]
thiscolumn = text[7]
thislength = text[8]
if thisline == line
endpos = thispos + thislength
# echoln [endpos,thispos+(column-thiscolumn),textchars[i]]
if column>=thiscolumn && column<=thiscolumn+thislength && thislength>0
return thispos+(column-thiscolumn)
if column >= thiscolumn && column <= thiscolumn + thislength && thislength > 0
return thispos + (column - thiscolumn)
end
end
end
@@ -409,90 +405,87 @@ class Window_MultilineTextEntry < SpriteWindow_Base
end
def getLastVisibleLine
getTextChars()
textheight=[1,self.contents.text_size("X").height].max
lastVisible=@firstline+((self.height-self.borderY)/textheight)-1
getTextChars
textheight = [1, self.contents.text_size("X").height].max
lastVisible = @firstline + ((self.height - self.borderY) / textheight) - 1
return lastVisible
end
def updateCursorPos(doRefresh)
# Calculate new cursor position
@helper.cursor=getPosFromLineAndColumn(@cursorLine,@cursorColumn)
@helper.cursor = getPosFromLineAndColumn(@cursorLine, @cursorColumn)
if doRefresh
@frame=0
@frame = 0
self.refresh
end
@firstline=@cursorLine if @cursorLine<@firstline
lastVisible=getLastVisibleLine()
@firstline+=(@cursorLine-lastVisible) if @cursorLine>lastVisible
@firstline = @cursorLine if @cursorLine < @firstline
lastVisible = getLastVisibleLine
@firstline += (@cursorLine - lastVisible) if @cursorLine > lastVisible
end
def moveCursor(lineOffset, columnOffset)
# Move column offset first, then lines (since column offset
# can affect line offset)
# echoln ["beforemoving",@cursorLine,@cursorColumn]
totalColumns=getColumnsInLine(@cursorLine) # check current line
totalLines=getTotalLines()
oldCursorLine=@cursorLine
oldCursorColumn=@cursorColumn
@cursorColumn+=columnOffset
if @cursorColumn<0 && @cursorLine>0
totalColumns = getColumnsInLine(@cursorLine) # check current line
totalLines = getTotalLines
oldCursorLine = @cursorLine
oldCursorColumn = @cursorColumn
@cursorColumn += columnOffset
if @cursorColumn < 0 && @cursorLine > 0
# Will happen if cursor is moved left from the beginning of a line
@cursorLine-=1
@cursorColumn=getColumnsInLine(@cursorLine)
elsif @cursorColumn>totalColumns && @cursorLine<totalLines-1
@cursorLine -= 1
@cursorColumn = getColumnsInLine(@cursorLine)
elsif @cursorColumn > totalColumns && @cursorLine < totalLines - 1
# Will happen if cursor is moved right from the end of a line
@cursorLine+=1
@cursorColumn=0
@cursorLine += 1
@cursorColumn = 0
end
# Ensure column bounds
totalColumns=getColumnsInLine(@cursorLine)
@cursorColumn=totalColumns if @cursorColumn>totalColumns
@cursorColumn=0 if @cursorColumn<0 # totalColumns can be 0
totalColumns = getColumnsInLine(@cursorLine)
@cursorColumn = totalColumns if @cursorColumn > totalColumns
@cursorColumn = 0 if @cursorColumn < 0 # totalColumns can be 0
# Move line offset
@cursorLine+=lineOffset
@cursorLine=0 if @cursorLine<0
@cursorLine=totalLines-1 if @cursorLine>=totalLines
@cursorLine += lineOffset
@cursorLine = 0 if @cursorLine < 0
@cursorLine = totalLines - 1 if @cursorLine >= totalLines
# Ensure column bounds again
totalColumns=getColumnsInLine(@cursorLine)
@cursorColumn=totalColumns if @cursorColumn>totalColumns
@cursorColumn=0 if @cursorColumn<0 # totalColumns can be 0
updateCursorPos(
oldCursorLine!=@cursorLine ||
oldCursorColumn!=@cursorColumn
)
totalColumns = getColumnsInLine(@cursorLine)
@cursorColumn = totalColumns if @cursorColumn > totalColumns
@cursorColumn = 0 if @cursorColumn < 0 # totalColumns can be 0
updateCursorPos(oldCursorLine != @cursorLine || oldCursorColumn != @cursorColumn)
# echoln ["aftermoving",@cursorLine,@cursorColumn]
end
def update
@frame+=1
@frame%=20
self.refresh if ((@frame%10)==0)
@frame += 1
@frame %= 20
self.refresh if (@frame % 10) == 0
return if !self.active
# Moving cursor
if Input.triggerex?(:UP) || Input.repeatex?(:UP)
moveCursor(-1,0)
moveCursor(-1, 0)
return
elsif Input.triggerex?(:DOWN) || Input.repeatex?(:DOWN)
moveCursor(1,0)
moveCursor(1, 0)
return
elsif Input.triggerex?(:LEFT) || Input.repeatex?(:LEFT)
moveCursor(0,-1)
moveCursor(0, -1)
return
elsif Input.triggerex?(:RIGHT) || Input.repeatex?(:RIGHT)
moveCursor(0,1)
moveCursor(0, 1)
return
end
if Input.press?(Input::CTRL) && Input.triggerex?(:HOME)
# Move cursor to beginning
@cursorLine=0
@cursorColumn=0
@cursorLine = 0
@cursorColumn = 0
updateCursorPos(true)
return
elsif Input.press?(Input::CTRL) && Input.triggerex?(:END)
# Move cursor to end
@cursorLine=getTotalLines()-1
@cursorColumn=getColumnsInLine(@cursorLine)
@cursorLine = getTotalLines - 1
@cursorColumn = getColumnsInLine(@cursorLine)
updateCursorPos(true)
return
elsif Input.triggerex?(:RETURN) || Input.repeatex?(:RETURN)
@@ -502,63 +495,62 @@ class Window_MultilineTextEntry < SpriteWindow_Base
self.delete
return
end
Input.gets.each_char{|c|insert(c)}
Input.gets.each_char { |c| insert(c) }
end
def refresh
newContents=pbDoEnsureBitmap(self.contents,self.width-self.borderX,
self.height-self.borderY)
@textchars=nil if self.contents!=newContents
self.contents=newContents
bitmap=self.contents
newContents = pbDoEnsureBitmap(self.contents, self.width - self.borderX,
self.height - self.borderY)
@textchars = nil if self.contents != newContents
self.contents = newContents
bitmap = self.contents
bitmap.clear
getTextChars
height=self.height-self.borderY
cursorcolor=Color.new(0,0,0)
textchars=getTextChars()
startY=getLineY(@firstline)
for i in 0...textchars.length
thisline=textchars[i][5]
thiscolumn=textchars[i][7]
thislength=textchars[i][8]
textY=textchars[i][2]-startY
height = self.height - self.borderY
cursorcolor = Color.new(0, 0, 0)
textchars = getTextChars
startY = getLineY(@firstline)
textchars.each do |text|
thisline = text[5]
thislength = text[8]
textY = text[2] - startY
# 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
break if textY >= height
c=textchars[i][0]
c = text[0]
# Don't draw spaces
next if c==" "
textwidth=textchars[i][3]+4 # add 4 to prevent draw_text from stretching text
textheight=textchars[i][4]
next if c == " "
textwidth = text[3] + 4 # add 4 to prevent draw_text from stretching text
textheight = text[4]
# Draw text
pbDrawShadowText(bitmap, textchars[i][1], textY, textwidth, textheight, c, @baseColor, @shadowColor)
pbDrawShadowText(bitmap, text[1], textY, textwidth, textheight, c, @baseColor, @shadowColor)
end
# Draw cursor
if ((@frame/10)&1) == 0
textheight=bitmap.text_size("X").height
cursorY=(textheight*@cursorLine)-startY
cursorX=0
for i in 0...textchars.length
thisline=textchars[i][5]
thiscolumn=textchars[i][7]
thislength=textchars[i][8]
if thisline==@cursorLine && @cursorColumn>=thiscolumn &&
@cursorColumn<=thiscolumn+thislength
cursorY=textchars[i][2]-startY
cursorX=textchars[i][1]
textheight=textchars[i][4]
posToCursor=@cursorColumn-thiscolumn
if posToCursor>=0
partialString=textchars[i][0].scan(/./m)[0,posToCursor].join("")
cursorX+=bitmap.text_size(partialString).width
if ((@frame / 10) & 1) == 0
textheight = bitmap.text_size("X").height
cursorY = (textheight * @cursorLine) - startY
cursorX = 0
textchars.each do |text|
thisline = text[5]
thiscolumn = text[7]
thislength = text[8]
if thisline == @cursorLine && @cursorColumn >= thiscolumn &&
@cursorColumn <= thiscolumn + thislength
cursorY = text[2] - startY
cursorX = text[1]
textheight = text[4]
posToCursor = @cursorColumn - thiscolumn
if posToCursor >= 0
partialString = text[0].scan(/./m)[0, posToCursor].join
cursorX += bitmap.text_size(partialString).width
end
break
end
end
cursorY+=4
cursorHeight=[4,textheight-4,bitmap.text_size("X").height-4].max
bitmap.fill_rect(cursorX,cursorY,2,cursorHeight,cursorcolor)
cursorY += 4
cursorHeight = [4, textheight - 4, bitmap.text_size("X").height - 4].max
bitmap.fill_rect(cursorX, cursorY, 2, cursorHeight, cursorcolor)
end
end
end

View File

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

View File

@@ -3,13 +3,13 @@ def pbStringToAudioFile(str)
file = $1
volume = $2.to_i
pitch = $3.to_i
return RPG::AudioFile.new(file,volume,pitch)
return RPG::AudioFile.new(file, volume, pitch)
elsif str[/^(.*)\:\s*(\d+)\s*$/] # Of the format "XXX: ###"
file = $1
volume = $2.to_i
return RPG::AudioFile.new(file,volume,100)
return RPG::AudioFile.new(file, volume, 100)
else
return RPG::AudioFile.new(str,100,100)
return RPG::AudioFile.new(str, 100, 100)
end
end
@@ -21,7 +21,7 @@ end
# filename:volume:pitch
# volume -- Volume of the file, up to 100
# pitch -- Pitch of the file, normally 100
def pbResolveAudioFile(str,volume=nil,pitch=nil)
def pbResolveAudioFile(str, volume = nil, pitch = nil)
if str.is_a?(String)
str = pbStringToAudioFile(str)
str.volume = volume || 100
@@ -29,8 +29,8 @@ def pbResolveAudioFile(str,volume=nil,pitch=nil)
end
if str.is_a?(RPG::AudioFile)
if volume || pitch
return RPG::AudioFile.new(str.name,volume || str.volume || 100 ,
pitch || str.pitch || 100)
return RPG::AudioFile.new(str.name, volume || str.volume || 100,
pitch || str.pitch || 100)
else
return str
end
@@ -49,43 +49,43 @@ end
# filename:volume:pitch
# volume -- Volume of the file, up to 100
# pitch -- Pitch of the file, normally 100
def pbBGMPlay(param,volume=nil,pitch=nil)
def pbBGMPlay(param, volume = nil, pitch = nil)
return if !param
param=pbResolveAudioFile(param,volume,pitch)
if param.name && param.name!=""
if $game_system && $game_system.respond_to?("bgm_play")
param = pbResolveAudioFile(param, volume, pitch)
if param.name && param.name != ""
if $game_system
$game_system.bgm_play(param)
return
elsif (RPG.const_defined?(:BGM) rescue false)
b=RPG::BGM.new(param.name,param.volume,param.pitch)
if b && b.respond_to?("play")
b = RPG::BGM.new(param.name, param.volume, param.pitch)
if b.respond_to?("play")
b.play
return
end
end
Audio.bgm_play(canonicalize("Audio/BGM/"+param.name),param.volume,param.pitch)
Audio.bgm_play(canonicalize("Audio/BGM/" + param.name), param.volume, param.pitch)
end
end
# Fades out or stops BGM playback. 'x' is the time in seconds to fade out.
def pbBGMFade(x=0.0); pbBGMStop(x);end
def pbBGMFade(x = 0.0); pbBGMStop(x); end
# Fades out or stops BGM playback. 'x' is the time in seconds to fade out.
def pbBGMStop(timeInSeconds=0.0)
if $game_system && timeInSeconds>0.0 && $game_system.respond_to?("bgm_fade")
def pbBGMStop(timeInSeconds = 0.0)
if $game_system && timeInSeconds > 0.0
$game_system.bgm_fade(timeInSeconds)
return
elsif $game_system && $game_system.respond_to?("bgm_stop")
elsif $game_system
$game_system.bgm_stop
return
elsif (RPG.const_defined?(:BGM) rescue false)
begin
(timeInSeconds>0.0) ? RPG::BGM.fade((timeInSeconds*1000).floor) : RPG::BGM.stop
(timeInSeconds > 0.0) ? RPG::BGM.fade((timeInSeconds * 1000).floor) : RPG::BGM.stop
return
rescue
end
end
(timeInSeconds>0.0) ? Audio.bgm_fade((timeInSeconds*1000).floor) : Audio.bgm_stop
(timeInSeconds > 0.0) ? Audio.bgm_fade((timeInSeconds * 1000).floor) : Audio.bgm_stop
end
################################################################################
@@ -99,42 +99,43 @@ end
# filename:volume:pitch
# volume -- Volume of the file, up to 100
# pitch -- Pitch of the file, normally 100
def pbMEPlay(param,volume=nil,pitch=nil)
def pbMEPlay(param, volume = nil, pitch = nil)
return if !param
param=pbResolveAudioFile(param,volume,pitch)
if param.name && param.name!=""
if $game_system && $game_system.respond_to?("me_play")
param = pbResolveAudioFile(param, volume, pitch)
if param.name && param.name != ""
if $game_system
$game_system.me_play(param)
return
elsif (RPG.const_defined?(:ME) rescue false)
b=RPG::ME.new(param.name,param.volume,param.pitch)
if b && b.respond_to?("play")
b.play; return
b = RPG::ME.new(param.name, param.volume, param.pitch)
if b.respond_to?("play")
b.play
return
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)
end
end
# Fades out or stops ME playback. 'x' is the time in seconds to fade out.
def pbMEFade(x=0.0); pbMEStop(x);end
def pbMEFade(x = 0.0); pbMEStop(x); end
# Fades out or stops ME playback. 'x' is the time in seconds to fade out.
def pbMEStop(timeInSeconds=0.0)
if $game_system && timeInSeconds>0.0 && $game_system.respond_to?("me_fade")
def pbMEStop(timeInSeconds = 0.0)
if $game_system && timeInSeconds > 0.0 && $game_system.respond_to?("me_fade")
$game_system.me_fade(timeInSeconds)
return
elsif $game_system && $game_system.respond_to?("me_stop")
elsif $game_system.respond_to?("me_stop")
$game_system.me_stop(nil)
return
elsif (RPG.const_defined?(:ME) rescue false)
begin
(timeInSeconds>0.0) ? RPG::ME.fade((timeInSeconds*1000).floor) : RPG::ME.stop
(timeInSeconds > 0.0) ? RPG::ME.fade((timeInSeconds * 1000).floor) : RPG::ME.stop
return
rescue
end
end
(timeInSeconds>0.0) ? Audio.me_fade((timeInSeconds*1000).floor) : Audio.me_stop
(timeInSeconds > 0.0) ? Audio.me_fade((timeInSeconds * 1000).floor) : Audio.me_stop
end
################################################################################
@@ -148,42 +149,43 @@ end
# filename:volume:pitch
# volume -- Volume of the file, up to 100
# pitch -- Pitch of the file, normally 100
def pbBGSPlay(param,volume=nil,pitch=nil)
def pbBGSPlay(param, volume = nil, pitch = nil)
return if !param
param=pbResolveAudioFile(param,volume,pitch)
if param.name && param.name!=""
if $game_system && $game_system.respond_to?("bgs_play")
param = pbResolveAudioFile(param, volume, pitch)
if param.name && param.name != ""
if $game_system
$game_system.bgs_play(param)
return
elsif (RPG.const_defined?(:BGS) rescue false)
b=RPG::BGS.new(param.name,param.volume,param.pitch)
if b && b.respond_to?("play")
b.play; return
b = RPG::BGS.new(param.name, param.volume, param.pitch)
if b.respond_to?("play")
b.play
return
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)
end
end
# Fades out or stops BGS playback. 'x' is the time in seconds to fade out.
def pbBGSFade(x=0.0); pbBGSStop(x);end
def pbBGSFade(x = 0.0); pbBGSStop(x); end
# Fades out or stops BGS playback. 'x' is the time in seconds to fade out.
def pbBGSStop(timeInSeconds=0.0)
if $game_system && timeInSeconds>0.0 && $game_system.respond_to?("bgs_fade")
def pbBGSStop(timeInSeconds = 0.0)
if $game_system && timeInSeconds > 0.0
$game_system.bgs_fade(timeInSeconds)
return
elsif $game_system && $game_system.respond_to?("bgs_play")
elsif $game_system
$game_system.bgs_play(nil)
return
elsif (RPG.const_defined?(:BGS) rescue false)
begin
(timeInSeconds>0.0) ? RPG::BGS.fade((timeInSeconds*1000).floor) : RPG::BGS.stop
(timeInSeconds > 0.0) ? RPG::BGS.fade((timeInSeconds * 1000).floor) : RPG::BGS.stop
return
rescue
end
end
(timeInSeconds>0.0) ? Audio.bgs_fade((timeInSeconds*1000).floor) : Audio.bgs_stop
(timeInSeconds > 0.0) ? Audio.bgs_fade((timeInSeconds * 1000).floor) : Audio.bgs_stop
end
################################################################################
@@ -197,30 +199,30 @@ end
# filename:volume:pitch
# volume -- Volume of the file, up to 100
# pitch -- Pitch of the file, normally 100
def pbSEPlay(param,volume=nil,pitch=nil)
def pbSEPlay(param, volume = nil, pitch = nil)
return if !param
param = pbResolveAudioFile(param,volume,pitch)
if param.name && param.name!=""
if $game_system && $game_system.respond_to?("se_play")
param = pbResolveAudioFile(param, volume, pitch)
if param.name && param.name != ""
if $game_system
$game_system.se_play(param)
return
end
if (RPG.const_defined?(:SE) rescue false)
b = RPG::SE.new(param.name,param.volume,param.pitch)
if b && b.respond_to?("play")
b = RPG::SE.new(param.name, param.volume, param.pitch)
if b.respond_to?("play")
b.play
return
end
end
Audio.se_play(canonicalize("Audio/SE/"+param.name),param.volume,param.pitch)
Audio.se_play(canonicalize("Audio/SE/" + param.name), param.volume, param.pitch)
end
end
# Stops SE playback.
def pbSEFade(x=0.0); pbSEStop(x);end
def pbSEFade(x = 0.0); pbSEStop(x); end
# Stops SE playback.
def pbSEStop(_timeInSeconds=0.0)
def pbSEStop(_timeInSeconds = 0.0)
if $game_system
$game_system.se_stop
elsif (RPG.const_defined?(:SE) rescue false)
@@ -234,59 +236,43 @@ end
# Plays a sound effect that plays when the player moves the cursor.
def pbPlayCursorSE
if $data_system && $data_system.respond_to?("cursor_se") &&
$data_system.cursor_se && $data_system.cursor_se.name!=""
if !nil_or_empty?($data_system&.cursor_se&.name)
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")
pbSEPlay("GUI sel cursor",80)
pbSEPlay("GUI sel cursor", 80)
end
end
# Plays a sound effect that plays when a decision is confirmed or a choice is made.
def pbPlayDecisionSE
if $data_system && $data_system.respond_to?("decision_se") &&
$data_system.decision_se && $data_system.decision_se.name!=""
if !nil_or_empty?($data_system&.decision_se&.name)
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")
pbSEPlay("GUI sel decision",80)
pbSEPlay("GUI sel decision", 80)
end
end
# Plays a sound effect that plays when a choice is canceled.
def pbPlayCancelSE
if $data_system && $data_system.respond_to?("cancel_se") &&
$data_system.cancel_se && $data_system.cancel_se.name!=""
if !nil_or_empty?($data_system&.cancel_se&.name)
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")
pbSEPlay("GUI sel cancel",80)
pbSEPlay("GUI sel cancel", 80)
end
end
# Plays a buzzer sound effect.
def pbPlayBuzzerSE
if $data_system && $data_system.respond_to?("buzzer_se") &&
$data_system.buzzer_se && $data_system.buzzer_se.name!=""
if !nil_or_empty?($data_system&.buzzer_se&.name)
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")
pbSEPlay("GUI sel buzzer",80)
pbSEPlay("GUI sel buzzer", 80)
end
end
# Plays a sound effect that plays when the player moves the cursor.
def pbPlayCloseMenuSE
if FileTest.audio_exist?("Audio/SE/GUI menu close")
pbSEPlay("GUI menu close",80)
pbSEPlay("GUI menu close", 80)
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ class PictureSprite < SpriteWrapper
end
def dispose
@pictureBitmap.dispose if @pictureBitmap
@pictureBitmap&.dispose
super
end
@@ -22,23 +22,23 @@ class PictureSprite < SpriteWrapper
def update
super
@pictureBitmap.update if @pictureBitmap
@pictureBitmap&.update
# If picture file name is different from current one
if @customBitmap && @picture.name==""
if @customBitmap && @picture.name == ""
self.bitmap = (@customBitmapIsBitmap) ? @customBitmap : @customBitmap.bitmap
elsif @picture_name != @picture.name || @picture.hue.to_i != @hue.to_i
elsif @picture_name != @picture.name || @picture.hue.to_i != @hue.to_i
# Remember file name to instance variables
@picture_name = @picture.name
@hue = @picture.hue.to_i
# If file name is not empty
if @picture_name == ""
@pictureBitmap.dispose if @pictureBitmap
@pictureBitmap&.dispose
@pictureBitmap = nil
self.visible = false
return
end
# Get picture graphic
@pictureBitmap.dispose if @pictureBitmap
@pictureBitmap&.dispose
@pictureBitmap = AnimatedBitmap.new(@picture_name, @hue)
self.bitmap = (@pictureBitmap) ? @pictureBitmap.bitmap : nil
elsif @picture_name == ""
@@ -46,16 +46,16 @@ class PictureSprite < SpriteWrapper
self.visible = false
return
end
setPictureSprite(self,@picture)
setPictureSprite(self, @picture)
end
end
def pbTextBitmap(text, maxwidth=Graphics.width)
tmp = Bitmap.new(maxwidth,Graphics.height)
def pbTextBitmap(text, maxwidth = Graphics.width)
tmp = Bitmap.new(maxwidth, Graphics.height)
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
end
@@ -65,9 +65,9 @@ end
# EventScene
#===============================================================================
class EventScene
attr_accessor :onCTrigger,:onBTrigger,:onUpdate
attr_accessor :onCTrigger, :onBTrigger, :onUpdate
def initialize(viewport=nil)
def initialize(viewport = nil)
@viewport = viewport
@onCTrigger = Event.new
@onBTrigger = Event.new
@@ -80,10 +80,10 @@ class EventScene
def dispose
return if disposed?
for sprite in @picturesprites
@picturesprites.each do |sprite|
sprite.dispose
end
for sprite in @usersprites
@usersprites.each do |sprite|
sprite.dispose
end
@onCTrigger.clear
@@ -105,26 +105,26 @@ class EventScene
# EventScene doesn't take ownership of the passed-in bitmap
num = @pictures.length
picture = PictureEx.new(num)
picture.setXY(0,x,y)
picture.setVisible(0,true)
picture.setXY(0, x, y)
picture.setVisible(0, true)
@pictures[num] = picture
@picturesprites[num] = PictureSprite.new(@viewport,picture)
@picturesprites[num] = PictureSprite.new(@viewport, picture)
@picturesprites[num].setCustomBitmap(bitmap)
return picture
end
def addLabel(x, y, width, text)
addBitmap(x,y,pbTextBitmap(text,width))
addBitmap(x, y, pbTextBitmap(text, width))
end
def addImage(x, y, name)
num = @pictures.length
picture = PictureEx.new(num)
picture.name = name
picture.setXY(0,x,y)
picture.setVisible(0,true)
picture.setXY(0, x, y)
picture.setVisible(0, true)
@pictures[num] = picture
@picturesprites[num] = PictureSprite.new(@viewport,picture)
@picturesprites[num] = PictureSprite.new(@viewport, picture)
return picture
end
@@ -140,10 +140,10 @@ class EventScene
frames.times { update }
end
def pictureWait(extraframes=0)
def pictureWait(extraframes = 0)
loop do
hasRunning = false
for pic in @pictures
@pictures.each do |pic|
hasRunning = true if pic.running?
end
break if !hasRunning
@@ -156,13 +156,13 @@ class EventScene
return if disposed?
Graphics.update
Input.update
for picture in @pictures
@pictures.each do |picture|
picture.update
end
for sprite in @picturesprites
@picturesprites.each do |sprite|
sprite.update
end
for sprite in @usersprites
@usersprites.each do |sprite|
next if !sprite || sprite.disposed? || !sprite.is_a?(Sprite)
sprite.update
end
@@ -175,7 +175,7 @@ class EventScene
end
def main
while !disposed?
until disposed?
update
end
end
@@ -188,7 +188,7 @@ end
#===============================================================================
def pbEventScreen(cls)
pbFadeOutIn {
viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
viewport.z = 99999
PBDebug.logonerr {
cls.new(viewport).main

View File

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

View File

@@ -64,7 +64,7 @@ module GameData
return ArgumentError.new("Exp amount #{level} is invalid.") if !exp || exp < 0
max = GrowthRate.max_level
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)
end
return max
@@ -78,17 +78,17 @@ GameData::GrowthRate.register({
:id => :Medium, # Also known as Medium Fast
:name => _INTL("Medium"),
:exp_values => [-1,
0, 8, 27, 64, 125, 216, 343, 512, 729, 1000,
1331, 1728, 2197, 2744, 3375, 4096, 4913, 5832, 6859, 8000,
9261, 10648, 12167, 13824, 15625, 17576, 19683, 21952, 24389, 27000,
29791, 32768, 35937, 39304, 42875, 46656, 50653, 54872, 59319, 64000,
68921, 74088, 79507, 85184, 91125, 97336, 103823, 110592, 117649, 125000,
132651, 140608, 148877, 157464, 166375, 175616, 185193, 195112, 205379, 216000,
226981, 238328, 250047, 262144, 274625, 287496, 300763, 314432, 328509, 343000,
357911, 373248, 389017, 405224, 421875, 438976, 456533, 474552, 493039, 512000,
531441, 551368, 571787, 592704, 614125, 636056, 658503, 681472, 704969, 729000,
753571, 778688, 804357, 830584, 857375, 884736, 912673, 941192, 970299, 1000000],
:exp_formula => proc { |level| next level ** 3 }
0, 8, 27, 64, 125, 216, 343, 512, 729, 1000,
1331, 1728, 2197, 2744, 3375, 4096, 4913, 5832, 6859, 8000,
9261, 10648, 12167, 13824, 15625, 17576, 19683, 21952, 24389, 27000,
29791, 32768, 35937, 39304, 42875, 46656, 50653, 54872, 59319, 64000,
68921, 74088, 79507, 85184, 91125, 97336, 103823, 110592, 117649, 125000,
132651, 140608, 148877, 157464, 166375, 175616, 185193, 195112, 205379, 216000,
226981, 238328, 250047, 262144, 274625, 287496, 300763, 314432, 328509, 343000,
357911, 373248, 389017, 405224, 421875, 438976, 456533, 474552, 493039, 512000,
531441, 551368, 571787, 592704, 614125, 636056, 658503, 681472, 704969, 729000,
753571, 778688, 804357, 830584, 857375, 884736, 912673, 941192, 970299, 1000000],
:exp_formula => proc { |level| next level**3 }
})
# Erratic (600000):
@@ -101,17 +101,17 @@ GameData::GrowthRate.register({
:id => :Erratic,
:name => _INTL("Erratic"),
:exp_values => [-1,
0, 15, 52, 122, 237, 406, 637, 942, 1326, 1800,
2369, 3041, 3822, 4719, 5737, 6881, 8155, 9564, 11111, 12800,
14632, 16610, 18737, 21012, 23437, 26012, 28737, 31610, 34632, 37800,
41111, 44564, 48155, 51881, 55737, 59719, 63822, 68041, 72369, 76800,
81326, 85942, 90637, 95406, 100237, 105122, 110052, 115015, 120001, 125000,
131324, 137795, 144410, 151165, 158056, 165079, 172229, 179503, 186894, 194400,
202013, 209728, 217540, 225443, 233431, 241496, 249633, 257834, 267406, 276458,
286328, 296358, 305767, 316074, 326531, 336255, 346965, 357812, 367807, 378880,
390077, 400293, 411686, 423190, 433572, 445239, 457001, 467489, 479378, 491346,
501878, 513934, 526049, 536557, 548720, 560922, 571333, 583539, 591882, 600000],
:exp_formula => proc { |level| next (level ** 4) * 3 / 500 }
0, 15, 52, 122, 237, 406, 637, 942, 1326, 1800,
2369, 3041, 3822, 4719, 5737, 6881, 8155, 9564, 11111, 12800,
14632, 16610, 18737, 21012, 23437, 26012, 28737, 31610, 34632, 37800,
41111, 44564, 48155, 51881, 55737, 59719, 63822, 68041, 72369, 76800,
81326, 85942, 90637, 95406, 100237, 105122, 110052, 115015, 120001, 125000,
131324, 137795, 144410, 151165, 158056, 165079, 172229, 179503, 186894, 194400,
202013, 209728, 217540, 225443, 233431, 241496, 249633, 257834, 267406, 276458,
286328, 296358, 305767, 316074, 326531, 336255, 346965, 357812, 367807, 378880,
390077, 400293, 411686, 423190, 433572, 445239, 457001, 467489, 479378, 491346,
501878, 513934, 526049, 536557, 548720, 560922, 571333, 583539, 591882, 600000],
:exp_formula => proc { |level| next (level**4) * 3 / 500 }
})
# Fluctuating (1640000):
@@ -122,19 +122,19 @@ GameData::GrowthRate.register({
:id => :Fluctuating,
:name => _INTL("Fluctuating"),
:exp_values => [-1,
0, 4, 13, 32, 65, 112, 178, 276, 393, 540,
745, 967, 1230, 1591, 1957, 2457, 3046, 3732, 4526, 5440,
6482, 7666, 9003, 10506, 12187, 14060, 16140, 18439, 20974, 23760,
26811, 30146, 33780, 37731, 42017, 46656, 50653, 55969, 60505, 66560,
71677, 78533, 84277, 91998, 98415, 107069, 114205, 123863, 131766, 142500,
151222, 163105, 172697, 185807, 196322, 210739, 222231, 238036, 250562, 267840,
281456, 300293, 315059, 335544, 351520, 373744, 390991, 415050, 433631, 459620,
479600, 507617, 529063, 559209, 582187, 614566, 639146, 673863, 700115, 737280,
765275, 804997, 834809, 877201, 908905, 954084, 987754, 1035837, 1071552, 1122660,
1160499, 1214753, 1254796, 1312322, 1354652, 1415577, 1460276, 1524731, 1571884, 1640000],
0, 4, 13, 32, 65, 112, 178, 276, 393, 540,
745, 967, 1230, 1591, 1957, 2457, 3046, 3732, 4526, 5440,
6482, 7666, 9003, 10506, 12187, 14060, 16140, 18439, 20974, 23760,
26811, 30146, 33780, 37731, 42017, 46656, 50653, 55969, 60505, 66560,
71677, 78533, 84277, 91998, 98415, 107069, 114205, 123863, 131766, 142500,
151222, 163105, 172697, 185807, 196322, 210739, 222231, 238036, 250562, 267840,
281456, 300293, 315059, 335544, 351520, 373744, 390991, 415050, 433631, 459620,
479600, 507617, 529063, 559209, 582187, 614566, 639146, 673863, 700115, 737280,
765275, 804997, 834809, 877201, 908905, 954084, 987754, 1035837, 1071552, 1122660,
1160499, 1214753, 1254796, 1312322, 1354652, 1415577, 1460276, 1524731, 1571884, 1640000],
:exp_formula => proc { |level|
rate = [82 - (level - 100) / 2.0, 40].max
next (level ** 4) * rate / 5000
rate = [82 - ((level - 100) / 2.0), 40].max
next (level**4) * rate / 5000
}
})
@@ -142,49 +142,49 @@ GameData::GrowthRate.register({
:id => :Parabolic, # Also known as Medium Slow
:name => _INTL("Parabolic"),
:exp_values => [-1,
0, 9, 57, 96, 135, 179, 236, 314, 419, 560,
742, 973, 1261, 1612, 2035, 2535, 3120, 3798, 4575, 5460,
6458, 7577, 8825, 10208, 11735, 13411, 15244, 17242, 19411, 21760,
24294, 27021, 29949, 33084, 36435, 40007, 43808, 47846, 52127, 56660,
61450, 66505, 71833, 77440, 83335, 89523, 96012, 102810, 109923, 117360,
125126, 133229, 141677, 150476, 159635, 169159, 179056, 189334, 199999, 211060,
222522, 234393, 246681, 259392, 272535, 286115, 300140, 314618, 329555, 344960,
360838, 377197, 394045, 411388, 429235, 447591, 466464, 485862, 505791, 526260,
547274, 568841, 590969, 613664, 636935, 660787, 685228, 710266, 735907, 762160,
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 }
0, 9, 57, 96, 135, 179, 236, 314, 419, 560,
742, 973, 1261, 1612, 2035, 2535, 3120, 3798, 4575, 5460,
6458, 7577, 8825, 10208, 11735, 13411, 15244, 17242, 19411, 21760,
24294, 27021, 29949, 33084, 36435, 40007, 43808, 47846, 52127, 56660,
61450, 66505, 71833, 77440, 83335, 89523, 96012, 102810, 109923, 117360,
125126, 133229, 141677, 150476, 159635, 169159, 179056, 189334, 199999, 211060,
222522, 234393, 246681, 259392, 272535, 286115, 300140, 314618, 329555, 344960,
360838, 377197, 394045, 411388, 429235, 447591, 466464, 485862, 505791, 526260,
547274, 568841, 590969, 613664, 636935, 660787, 685228, 710266, 735907, 762160,
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 }
})
GameData::GrowthRate.register({
:id => :Fast,
:name => _INTL("Fast"),
:exp_values => [-1,
0, 6, 21, 51, 100, 172, 274, 409, 583, 800,
1064, 1382, 1757, 2195, 2700, 3276, 3930, 4665, 5487, 6400,
7408, 8518, 9733, 11059, 12500, 14060, 15746, 17561, 19511, 21600,
23832, 26214, 28749, 31443, 34300, 37324, 40522, 43897, 47455, 51200,
55136, 59270, 63605, 68147, 72900, 77868, 83058, 88473, 94119, 100000,
106120, 112486, 119101, 125971, 133100, 140492, 148154, 156089, 164303, 172800,
181584, 190662, 200037, 209715, 219700, 229996, 240610, 251545, 262807, 274400,
286328, 298598, 311213, 324179, 337500, 351180, 365226, 379641, 394431, 409600,
425152, 441094, 457429, 474163, 491300, 508844, 526802, 545177, 563975, 583200,
602856, 622950, 643485, 664467, 685900, 707788, 730138, 752953, 776239, 800000],
:exp_formula => proc { |level| (level ** 3) * 4 / 5 }
0, 6, 21, 51, 100, 172, 274, 409, 583, 800,
1064, 1382, 1757, 2195, 2700, 3276, 3930, 4665, 5487, 6400,
7408, 8518, 9733, 11059, 12500, 14060, 15746, 17561, 19511, 21600,
23832, 26214, 28749, 31443, 34300, 37324, 40522, 43897, 47455, 51200,
55136, 59270, 63605, 68147, 72900, 77868, 83058, 88473, 94119, 100000,
106120, 112486, 119101, 125971, 133100, 140492, 148154, 156089, 164303, 172800,
181584, 190662, 200037, 209715, 219700, 229996, 240610, 251545, 262807, 274400,
286328, 298598, 311213, 324179, 337500, 351180, 365226, 379641, 394431, 409600,
425152, 441094, 457429, 474163, 491300, 508844, 526802, 545177, 563975, 583200,
602856, 622950, 643485, 664467, 685900, 707788, 730138, 752953, 776239, 800000],
:exp_formula => proc { |level| (level**3) * 4 / 5 }
})
GameData::GrowthRate.register({
:id => :Slow,
:name => _INTL("Slow"),
:exp_values => [-1,
0, 10, 33, 80, 156, 270, 428, 640, 911, 1250,
1663, 2160, 2746, 3430, 4218, 5120, 6141, 7290, 8573, 10000,
11576, 13310, 15208, 17280, 19531, 21970, 24603, 27440, 30486, 33750,
37238, 40960, 44921, 49130, 53593, 58320, 63316, 68590, 74148, 80000,
86151, 92610, 99383, 106480, 113906, 121670, 129778, 138240, 147061, 156250,
165813, 175760, 186096, 196830, 207968, 219520, 231491, 243890, 256723, 270000,
283726, 297910, 312558, 327680, 343281, 359370, 375953, 393040, 410636, 428750,
447388, 466560, 486271, 506530, 527343, 548720, 570666, 593190, 616298, 640000,
664301, 689210, 714733, 740880, 767656, 795070, 823128, 851840, 881211, 911250,
941963, 973360, 1005446, 1038230, 1071718, 1105920, 1140841, 1176490, 1212873, 1250000],
:exp_formula => proc { |level| (level ** 3) * 5 / 4 }
0, 10, 33, 80, 156, 270, 428, 640, 911, 1250,
1663, 2160, 2746, 3430, 4218, 5120, 6141, 7290, 8573, 10000,
11576, 13310, 15208, 17280, 19531, 21970, 24603, 27440, 30486, 33750,
37238, 40960, 44921, 49130, 53593, 58320, 63316, 68590, 74148, 80000,
86151, 92610, 99383, 106480, 113906, 121670, 129778, 138240, 147061, 156250,
165813, 175760, 186096, 196830, 207968, 219520, 231491, 243890, 256723, 270000,
283726, 297910, 312558, 327680, 343281, 359370, 375953, 393040, 410636, 428750,
447388, 466560, 486271, 506530, 527343, 548720, 570666, 593190, 616298, 640000,
664301, 689210, 714733, 740880, 767656, 795070, 823128, 851840, 881211, 911250,
941963, 973360, 1005446, 1038230, 1071718, 1105920, 1140841, 1176490, 1212873, 1250000],
:exp_formula => proc { |level| (level**3) * 5 / 4 }
})

View File

@@ -26,6 +26,12 @@ module GameData
def name
return _INTL(@real_name)
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

View File

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

View File

@@ -7,6 +7,8 @@ module GameData
attr_reader :level_up_proc
attr_reader :use_item_proc
attr_reader :on_trade_proc
attr_reader :after_battle_proc
attr_reader :event_proc
attr_reader :after_evolution_proc
DATA = {}
@@ -25,6 +27,8 @@ module GameData
@level_up_proc = hash[:level_up_proc]
@use_item_proc = hash[:use_item_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]
end
@@ -40,8 +44,16 @@ module GameData
return (@on_trade_proc) ? @on_trade_proc.call(*args) : nil
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)
@after_evolution_proc.call(*args) if @after_evolution_proc
@after_evolution_proc&.call(*args)
end
end
end
@@ -188,8 +200,7 @@ GameData::Evolution.register({
:id => :LevelDarkness,
:parameter => Integer,
:level_up_proc => proc { |pkmn, parameter|
map_metadata = GameData::MapMetadata.try_get($game_map.map_id)
next pkmn.level >= parameter && map_metadata && map_metadata.dark_map
next pkmn.level >= parameter && $game_map.metadata&.dark_map
}
})
@@ -197,7 +208,7 @@ GameData::Evolution.register({
:id => :LevelDarkInParty,
:parameter => Integer,
: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({
:id => :Shedinja,
: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|
next false if $Trainer.party_full?
next false if !$PokemonBag.pbHasItem?(:POKEBALL)
next false if $player.party_full?
next false if !$bag.has?(:POKEBALL)
PokemonEvolutionScene.pbDuplicatePokemon(pkmn, new_species)
$PokemonBag.pbDeleteItem(:POKEBALL)
$bag.remove(:POKEBALL)
next true
}
})
@@ -268,7 +276,7 @@ GameData::Evolution.register({
:id => :Happiness,
:minimum_level => 1, # Needs any level up
: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,
:minimum_level => 1, # Needs any level up
: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,
:minimum_level => 1, # Needs any level up
: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,
:minimum_level => 1, # Needs any level up
: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,
:minimum_level => 1, # Needs any level up
: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,
:minimum_level => 1, # Needs any level up
: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 }
end
}
@@ -320,7 +328,7 @@ GameData::Evolution.register({
:parameter => :Type,
:minimum_level => 1, # Needs any level up
: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 }
end
}
@@ -331,7 +339,7 @@ GameData::Evolution.register({
:parameter => :Item,
:minimum_level => 1, # Needs any level up
: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|
next false if evo_species != new_species || !pkmn.hasItem?(parameter)
@@ -432,7 +440,7 @@ GameData::Evolution.register({
:parameter => :Item,
:minimum_level => 1, # Needs any level up
: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|
next false if evo_species != new_species || !pkmn.hasItem?(parameter)
@@ -464,7 +472,7 @@ GameData::Evolution.register({
:parameter => :Species,
:minimum_level => 1, # Needs any level up
: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({
:id => :Region,
:parameter => Integer,
:minimum_level => 1, # Needs any level up
:level_up_proc => proc { |pkmn, parameter|
map_metadata = GameData::MapMetadata.try_get($game_map.map_id)
next map_metadata && map_metadata.town_map_position &&
map_metadata.town_map_position[0] == parameter
map_metadata = $game_map.metadata
next map_metadata&.town_map_position && map_metadata.town_map_position[0] == parameter
}
})
@@ -535,7 +551,7 @@ GameData::Evolution.register({
:id => :ItemHappiness,
: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)
}
})
#===============================================================================
# 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
# 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
@@ -8,7 +6,6 @@
module GameData
class Stat
attr_reader :id
attr_reader :id_number
attr_reader :real_name
attr_reader :real_name_brief
attr_reader :type
@@ -16,7 +13,7 @@ module GameData
DATA = {}
extend ClassMethods
extend ClassMethodsSymbols
include InstanceMethods
def self.load; end
@@ -39,7 +36,6 @@ module GameData
def initialize(hash)
@id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed"
@real_name_brief = hash[:name_brief] || "None"
@type = hash[:type] || :none
@@ -62,7 +58,6 @@ end
GameData::Stat.register({
:id => :HP,
:id_number => 0,
:name => _INTL("HP"),
:name_brief => _INTL("HP"),
:type => :main,
@@ -71,7 +66,6 @@ GameData::Stat.register({
GameData::Stat.register({
:id => :ATTACK,
:id_number => 1,
:name => _INTL("Attack"),
:name_brief => _INTL("Atk"),
:type => :main_battle,
@@ -80,7 +74,6 @@ GameData::Stat.register({
GameData::Stat.register({
:id => :DEFENSE,
:id_number => 2,
:name => _INTL("Defense"),
:name_brief => _INTL("Def"),
:type => :main_battle,
@@ -89,7 +82,6 @@ GameData::Stat.register({
GameData::Stat.register({
:id => :SPECIAL_ATTACK,
:id_number => 3,
:name => _INTL("Special Attack"),
:name_brief => _INTL("SpAtk"),
:type => :main_battle,
@@ -98,7 +90,6 @@ GameData::Stat.register({
GameData::Stat.register({
:id => :SPECIAL_DEFENSE,
:id_number => 4,
:name => _INTL("Special Defense"),
:name_brief => _INTL("SpDef"),
:type => :main_battle,
@@ -107,7 +98,6 @@ GameData::Stat.register({
GameData::Stat.register({
:id => :SPEED,
:id_number => 5,
:name => _INTL("Speed"),
:name_brief => _INTL("Spd"),
:type => :main_battle,
@@ -116,7 +106,6 @@ GameData::Stat.register({
GameData::Stat.register({
:id => :ACCURACY,
:id_number => 6,
:name => _INTL("accuracy"),
:name_brief => _INTL("Acc"),
:type => :battle
@@ -124,7 +113,6 @@ GameData::Stat.register({
GameData::Stat.register({
:id => :EVASION,
:id_number => 7,
:name => _INTL("evasiveness"),
:name_brief => _INTL("Eva"),
:type => :battle

View File

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

View File

@@ -1,31 +1,29 @@
# NOTE: The id_number is only used to determine the order of the status icons in
# the graphics containing them. Number 0 (:NONE) is ignored; they start
# with status 1.
# "Graphics/Pictures/statuses.png" also contains icons for being fainted
# NOTE: "Graphics/Pictures/statuses.png" also contains icons for being fainted
# 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
# 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
class Status
attr_reader :id
attr_reader :id_number
attr_reader :real_name
attr_reader :animation
attr_reader :icon_position # Where this status's icon is within statuses.png
DATA = {}
extend ClassMethods
extend ClassMethodsSymbols
include InstanceMethods
def self.load; end
def self.save; end
def initialize(hash)
@id = hash[:id]
@id_number = hash[:id_number]
@real_name = hash[:name] || "Unnamed"
@animation = hash[:animation]
@id = hash[:id]
@real_name = hash[:name] || "Unnamed"
@animation = hash[:animation]
@icon_position = hash[:icon_position] || 0
end
# @return [String] the translated name of this status condition
@@ -38,42 +36,41 @@ end
#===============================================================================
GameData::Status.register({
:id => :NONE,
:id_number => 0,
:name => _INTL("None")
:id => :NONE,
:name => _INTL("None")
})
GameData::Status.register({
:id => :SLEEP,
:id_number => 1,
:name => _INTL("Sleep"),
:animation => "Sleep"
:id => :SLEEP,
:name => _INTL("Sleep"),
:animation => "Sleep",
:icon_position => 0
})
GameData::Status.register({
:id => :POISON,
:id_number => 2,
:name => _INTL("Poison"),
:animation => "Poison"
:id => :POISON,
:name => _INTL("Poison"),
:animation => "Poison",
:icon_position => 1
})
GameData::Status.register({
:id => :BURN,
:id_number => 3,
:name => _INTL("Burn"),
:animation => "Burn"
:id => :BURN,
:name => _INTL("Burn"),
:animation => "Burn",
:icon_position => 2
})
GameData::Status.register({
:id => :PARALYSIS,
:id_number => 4,
:name => _INTL("Paralysis"),
:animation => "Paralysis"
:id => :PARALYSIS,
:name => _INTL("Paralysis"),
:animation => "Paralysis",
:icon_position => 3
})
GameData::Status.register({
:id => :FROZEN,
:id_number => 5,
:name => _INTL("Frozen"),
:animation => "Frozen"
:id => :FROZEN,
:name => _INTL("Frozen"),
:animation => "Frozen",
:icon_position => 4
})

View File

@@ -170,8 +170,9 @@ GameData::TerrainTag.register({
:ignore_passability => true
})
# NOTE: This is referenced by ID in an Events.onStepTakenFieldMovement proc that
# adds soot to the Soot Sack if the player walks over one of these tiles.
# NOTE: This is referenced by ID in the :pick_up_soot proc added to
# EventHandlers. It adds soot to the Soot Sack if the player walks over
# one of these tiles.
GameData::TerrainTag.register({
:id => :SootGrass,
:id_number => 14,
@@ -192,3 +193,8 @@ GameData::TerrainTag.register({
:battle_environment => :Puddle,
: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 :type # :land, :cave, :water, :fishing, :contest, :none
attr_reader :trigger_chance
attr_reader :old_slots
DATA = {}
@@ -19,7 +18,6 @@ module GameData
@real_name = hash[:id].to_s || "Unnamed"
@type = hash[:type] || :none
@trigger_chance = hash[:trigger_chance] || 0
@old_slots = hash[:old_slots]
end
end
end
@@ -29,169 +27,144 @@ end
GameData::EncounterType.register({
:id => :Land,
:type => :land,
:trigger_chance => 21,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 21
})
GameData::EncounterType.register({
:id => :LandDay,
:type => :land,
:trigger_chance => 21,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 21
})
GameData::EncounterType.register({
:id => :LandNight,
:type => :land,
:trigger_chance => 21,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 21
})
GameData::EncounterType.register({
:id => :LandMorning,
:type => :land,
:trigger_chance => 21,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 21
})
GameData::EncounterType.register({
:id => :LandAfternoon,
:type => :land,
:trigger_chance => 21,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 21
})
GameData::EncounterType.register({
:id => :LandEvening,
:type => :land,
:trigger_chance => 21,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 21
})
GameData::EncounterType.register({
:id => :Cave,
:type => :cave,
:trigger_chance => 5,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 5
})
GameData::EncounterType.register({
:id => :CaveDay,
:type => :cave,
:trigger_chance => 5,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 5
})
GameData::EncounterType.register({
:id => :CaveNight,
:type => :cave,
:trigger_chance => 5,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 5
})
GameData::EncounterType.register({
:id => :CaveMorning,
:type => :cave,
:trigger_chance => 5,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 5
})
GameData::EncounterType.register({
:id => :CaveAfternoon,
:type => :cave,
:trigger_chance => 5,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 5
})
GameData::EncounterType.register({
:id => :CaveEvening,
:type => :cave,
:trigger_chance => 5,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 5
})
GameData::EncounterType.register({
:id => :Water,
:type => :water,
:trigger_chance => 2,
:old_slots => [60, 30, 5, 4, 1]
:trigger_chance => 2
})
GameData::EncounterType.register({
:id => :WaterDay,
:type => :water,
:trigger_chance => 2,
:old_slots => [60, 30, 5, 4, 1]
:trigger_chance => 2
})
GameData::EncounterType.register({
:id => :WaterNight,
:type => :water,
:trigger_chance => 2,
:old_slots => [60, 30, 5, 4, 1]
:trigger_chance => 2
})
GameData::EncounterType.register({
:id => :WaterMorning,
:type => :water,
:trigger_chance => 2,
:old_slots => [60, 30, 5, 4, 1]
:trigger_chance => 2
})
GameData::EncounterType.register({
:id => :WaterAfternoon,
:type => :water,
:trigger_chance => 2,
:old_slots => [60, 30, 5, 4, 1]
:trigger_chance => 2
})
GameData::EncounterType.register({
:id => :WaterEvening,
:type => :water,
:trigger_chance => 2,
:old_slots => [60, 30, 5, 4, 1]
:trigger_chance => 2
})
GameData::EncounterType.register({
:id => :OldRod,
:type => :fishing,
:old_slots => [70, 30]
:type => :fishing
})
GameData::EncounterType.register({
:id => :GoodRod,
:type => :fishing,
:old_slots => [60, 20, 20]
:type => :fishing
})
GameData::EncounterType.register({
:id => :SuperRod,
:type => :fishing,
:old_slots => [40, 40, 15, 4, 1]
:type => :fishing
})
GameData::EncounterType.register({
:id => :RockSmash,
:type => :none,
:trigger_chance => 50,
:old_slots => [60, 30, 5, 4, 1]
:trigger_chance => 50
})
GameData::EncounterType.register({
:id => :HeadbuttLow,
:type => :none,
:old_slots => [30, 25, 20, 10, 5, 5, 4, 1]
:type => :none
})
GameData::EncounterType.register({
:id => :HeadbuttHigh,
:type => :none,
:old_slots => [30, 25, 20, 10, 5, 5, 4, 1]
:type => :none
})
GameData::EncounterType.register({
:id => :BugContest,
:type => :contest,
:trigger_chance => 21,
:old_slots => [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
:trigger_chance => 21
})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,51 +1,70 @@
module GameData
class Move
attr_reader :id
attr_reader :id_number
attr_reader :real_name
attr_reader :function_code
attr_reader :base_damage
attr_reader :type
attr_reader :category
attr_reader :base_damage
attr_reader :accuracy
attr_reader :total_pp
attr_reader :effect_chance
attr_reader :target
attr_reader :priority
attr_reader :function_code
attr_reader :flags
attr_reader :effect_chance
attr_reader :real_description
DATA = {}
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
def initialize(hash)
convert_move_data(hash)
@id = hash[:id]
@id_number = hash[:id_number] || -1
@real_name = hash[:name] || "Unnamed"
@function_code = hash[:function_code]
@base_damage = hash[:base_damage]
@type = hash[:type]
@category = hash[:category]
@accuracy = hash[:accuracy]
@total_pp = hash[:total_pp]
@effect_chance = hash[:effect_chance]
@target = hash[:target]
@priority = hash[:priority]
@flags = hash[:flags]
@real_description = hash[:description] || "???"
@real_name = hash[:name] || "Unnamed"
@type = hash[:type] || :NONE
@category = hash[:category] || 2
@base_damage = hash[:base_damage] || 0
@accuracy = hash[:accuracy] || 100
@total_pp = hash[:total_pp] || 5
@target = hash[:target] || :None
@priority = hash[:priority] || 0
@function_code = hash[:function_code] || "None"
@flags = hash[:flags] || []
@flags = [@flags] if !@flags.is_a?(Array)
@effect_chance = hash[:effect_chance] || 0
@real_description = hash[:description] || "???"
end
# @return [String] the translated name of this move
def name
return pbGetMessage(MessageTypes::Moves, @id_number)
return pbGetMessageFromHash(MessageTypes::Moves, @real_name)
end
# @return [String] the translated description of this move
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
def physical?
@@ -66,20 +85,729 @@ module GameData
end
return false
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
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)
=begin
case @function_code
when "TypeDependsOnUserIVs"
return pbHiddenPower(pkmn)[1]
when "TypeAndPowerDependOnUserBerry"
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
def display_category(pkmn, move = nil); return @category; end
def display_accuracy(pkmn, move = nil); return @accuracy; end
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
#===============================================================================
# Deprecated methods
#===============================================================================
# @deprecated This alias is slated to be removed in v20.
def pbGetMoveData(move_id, move_data_type = -1)
Deprecation.warn_method('pbGetMoveData', 'v20', 'GameData::Move.get(move_id)')
return GameData::Move.get(move_id)
end
# @deprecated This alias is slated to be removed in v20.
def pbIsHiddenMove?(move)
Deprecation.warn_method('pbIsHiddenMove?', 'v20', 'GameData::Move.get(move).hidden_move?')
return GameData::Move.get(move).hidden_move?
end

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