# @taroxd metadata 1.0
# @display 游戏常数设置
# @require taroxd_core
# @id const
module Taroxd::Const
# 游戏常数设置区域(如果要用默认值,可以设置为 false 或直接删除)
SAVEFILE_MAX = 16 # 存档文件的最大个数
ESCAPE_RATIO_UP = 0.1 # 撤退失败后,撤退成功率提升值
MAX_TP = 100 # TP 的最大值
ATTACK_SKILL_ID = 1 # 默认攻击技能 ID
GUARD_SKILL_ID = 2 # 默认防御技能 ID
DEATH_STATE_ID = 1 # 默认死亡状态 ID
PARAM_LIMIT = 999999 # 能力值的最大值
PRESERVE_TP = false # 是否永远特技专注
LUK_EFFECT_RATE = 0.001 # 幸运值影响程度
CRITICAL_RATE = 3 # 关键一击伤害倍率
STEPS_FOR_RUN = 20 # 地图上多少步等于一回合
BASIC_FLOOR_DAMAGE = 10 # 地形伤害的基础值
MAX_BATTLE_MEMBERS = 4 # 参战角色的最大数
MAX_GOLD = 99999999 # 持有金钱的最大值
MAX_ITEM_NUMBER = 99 # 物品的最大持有数
BUSH_DEPTH = 8 # 流体地形的深度
BUSH_OPACITY = 128 # 流体地形的不透明度
PLAYER_INITIAL_DIRECTION = 2 # 角色初始朝向
SUBSTITUTE_HP_RATE = 0.25 # HP 比率达到多少以下会触发保护弱者
Font.default_name = 'nsimsun' # 默认字体名称
Font.default_size = 24 # 默认字体大小
def self.[](sym)
const_defined?(sym, false) && const_get(sym)
end
end
def DataManager.savefile_max
Taroxd::Const::SAVEFILE_MAX
end if Taroxd::Const[:SAVEFILE_MAX]
def BattleManager.process_escape
$game_message.add(sprintf(Vocab::EscapeStart, $game_party.name))
success = @preemptive ? true : (rand < @escape_ratio)
Sound.play_escape
if success
process_abort
else
@escape_ratio += Taroxd::Const::ESCAPE_RATIO_UP
$game_message.add('\.' + Vocab::EscapeFailure)
$game_party.clear_actions
end
wait_for_message
success
end if Taroxd::Const[:ESCAPE_RATIO_UP]
class Game_BattlerBase
def max_tp
Taroxd::Const::MAX_TP
end if Taroxd::Const[:MAX_TP]
def attack_skill_id
Taroxd::Const::ATTACK_SKILL_ID
end if Taroxd::Const[:ATTACK_SKILL_ID]
def guard_skill_id
Taroxd::Const::GUARD_SKILL_ID
end if Taroxd::Const[:GUARD_SKILL_ID]
def death_state_id
Taroxd::Const::DEATH_STATE_ID
end if Taroxd::Const[:DEATH_STATE_ID]
def param_min(_)
0
end if Taroxd::Const[:PARAM_LIMIT]
def param_max(_)
Taroxd::Const::PARAM_LIMIT
end if Taroxd::Const[:PARAM_LIMIT]
def preserve_tp?
true
end if Taroxd::Const[:PRESERVE_TP]
end
class Game_Battler < Game_BattlerBase
def luk_effect_rate(user)
[1.0 + (user.luk - luk) * Taroxd::Const::LUK_EFFECT_RATE, 0.0].max
end if Taroxd::Const[:LUK_EFFECT_RATE]
def apply_critical(damage)
damage * Taroxd::Const::CRITICAL_RATE
end if Taroxd::Const[:CRITICAL_RATE]
end
class Game_Actor < Game_Battler
remove_method :param_max if Taroxd::Const[:PARAM_LIMIT]
def steps_for_turn
Taroxd::Const::STEPS_FOR_RUN
end if Taroxd::Const[:STEPS_FOR_RUN]
def basic_floor_damage
Taroxd::Const::BASIC_FLOOR_DAMAGE
end if Taroxd::Const[:BASIC_FLOOR_DAMAGE]
end
class Game_Party < Game_Unit
def max_battle_members
Taroxd::Const::MAX_BATTLE_MEMBERS
end if Taroxd::Const[:MAX_BATTLE_MEMBERS]
def max_gold
Taroxd::Const::MAX_GOLD
end if Taroxd::Const[:MAX_GOLD]
def max_item_number(_)
Taroxd::Const::MAX_ITEM_NUMBER
end if Taroxd::Const[:MAX_ITEM_NUMBER]
end
class Game_CharacterBase
def update_bush_depth
if normal_priority? && !object_character? && bush? && !jumping?
@bush_depth = Taroxd::Const::BUSH_DEPTH unless moving?
else
@bush_depth = 0
end
end if Taroxd::Const[:BUSH_DEPTH]
end
class Sprite_Character < Sprite_Base
def_after :initialize do |_, _ = nil|
self.bush_opacity = Taroxd::Const::BUSH_OPACITY
end if Taroxd::Const[:BUSH_OPACITY]
end
class Game_Player < Game_Character
def_after :initialize do
@direction = Taroxd::Const::PLAYER_INITIAL_DIRECTION
end if Taroxd::Const[:PLAYER_INITIAL_DIRECTION]
end
class Scene_Battle < Scene_Base
def check_substitute(target, item)
target.hp_rate < Taroxd::Const::SUBSTITUTE_HP_RATE &&
(!item || !item.certain?)
end if Taroxd::Const[:SUBSTITUTE_HP_RATE]
end
游戏常数设置
简易调试控制台
# @taroxd metadata 1.0
# @id console
# @require taroxd_core
# @require fast_forward
# @display 简易调试控制台
# 感谢 Fux2 提供的 gets 修复脚本。
if $TEST
module Taroxd::Console
KEY = :F5
HOOK_STDIN = true # 使得在新版控制台中也可以输入
exit_help = 'exit 为真时,返回游戏。'
# @help
HELP = <<-EOF.gsub(/^ {4}/, '')
在控制台中可以执行任意脚本。下面是一些预定义的方法。
exit
退出控制台并返回游戏。
help
显示这段帮助。
_ (变量)
上一次执行的结果。
recover(exit = true)
完全恢复。#{exit_help}
save(index = 0, exit = true)
存档到指定位置。#{exit_help}
load(index = 0, exit = true)
从指定位置读档。#{exit_help}
kill(hp = 0, exit = true)
将敌方全体的 HP 设为 hp。仅战斗中可用。#{exit_help}
suicide(hp = 0, exit = true)
将己方全体的 HP 设为 hp。#{exit_help}
fast_forward(*args)
调用 Taroxd::FastForward。
ff(*args)
调用 Taroxd::FastForward 并返回游戏。
EOF
class << self
EXIT_IDENTIFIER = Object.new # 返回该值时,退出控制台并回到游戏
# 获取窗口句柄
console = Win32API.new('Kernel32', 'GetConsoleWindow', '', 'L').call
game = Win32API.new('user32', 'GetActiveWindow', '', 'L').call
hwnd = game
set_window_pos = Win32API.new('user32', 'SetWindowPos', 'LLLLLLL', 'L')
# 切换窗口
define_method :switch_window do
hwnd = hwnd == game ? console : game
set_window_pos.call(hwnd, 0, 0, 0, 0, 0, 3)
end
# 如果按下按键,则进入控制台
def update
start if Input.trigger?(KEY)
end
alias_method :get_binding, :binding
# 进入控制台
def start
switch_window
binding = get_binding
begin
while (line = gets)
next unless line[/\S/]
_ = eval(line, binding)
if _.equal?(EXIT_IDENTIFIER)
switch_window
Input.update # 防止按下的 Enter 被游戏判定
break
end
print '=> '
p _
end
rescue => e
p e
retry
end
end
def exit
EXIT_IDENTIFIER
end
def help
puts HELP
end
def recover(to_exit = true)
$game_party.recover_all
!to_exit || exit
end
def save(index = 0, to_exit = true)
Sound.play_save
DataManager.save_game_without_rescue(index)
!to_exit || exit
end
def load(index = 0, to_exit = true)
DataManager.load_game_without_rescue(index)
Sound.play_load
$game_system.on_after_load
SceneManager.goto(Scene_Map)
!to_exit || exit
end
def kill(hp = 0, to_exit = true)
return to_exit && exit unless $game_party.in_battle
$game_troop.each { |a| a.hp = hp }
!to_exit || exit
end
def suicide(hp = 0, to_exit = true)
$game_party.each { |a| a.hp = hp }
!to_exit || exit
end
define_method :fast_forward, Taroxd::FastForward
def ff(*args)
fast_forward(*args)
exit
end
end
module ReadFileHooker
ReadProcessMemory = Win32API.new('kernel32', 'ReadProcessMemory', 'llpll', 'l')
WriteProcessMemory = Win32API.new('kernel32', 'WriteProcessMemory', 'llpll', 'l')
VirtualProtect = Win32API.new('kernel32', 'VirtualProtect', 'lllp', 'l')
GetModuleHandle = Win32API.new('kernel32', 'GetModuleHandle', 'p', 'l')
GetProcAddress = Win32API.new('kernel32', 'GetProcAddress', 'lp' , 'l')
GetCurrentProcess = Win32API.new('kernel32', 'GetCurrentProcess', 'v', 'l')
def self.hook
hook_addr = CAD - PROC - 5
writemem(CAD + CAL - 6, @origin_code_readfile, 6)
writemem(PROC, [0xE9, hook_addr, 0x90].pack("ClC"), 6)
yield
ensure
writemem(PROC, @origin_code_readfile, 6)
end
class << ::Taroxd::Console
def gets
ReadFileHooker.hook { STDIN.gets }
end
end
private
def self.readmem(addr, buf, len)
ReadProcessMemory.call(@hProc, addr, buf, len, 0)
end
def self.writemem(addr, buf, len)
WriteProcessMemory.call(@hProc, addr, buf, len, 0)
end
def self.unprotect(addr, len)
VirtualProtect.call(addr, len, 0x40, "\0" * 4)
end
def self.getmodule(name)
GetModuleHandle.call(name)
end
def self.getaddr(dll, name)
GetProcAddress.call(dll, name)
end
@hProc = GetCurrentProcess.call
raise "cannot open process" if @hProc == 0
HookCode = [0xC7,0x44,0x24,0x0C,0x12,0x05,0x00,0x00,*[0]*6].pack("C*")
CAD = [HookCode].pack("p").unpack("L").first
CAL = HookCode.bytes.count
dll = getmodule("kernel32")
PROC = getaddr(dll, "ReadFile")
@origin_code_readfile = "\0" * 6
readmem(PROC, @origin_code_readfile, 6)
unprotect(CAD, CAL)
end if HOOK_STDIN
end
Scene_Base.send :def_after, :update, Taroxd::Console.method(:update)
end # if $TEST
全局配置管理器
# @taroxd metadata 1.0
# @display 全局配置管理器
# @id config_manager
module Taroxd
module ConfigManager
SAVEFILE_NAME = 'config.rvdata2'
if File.exist?(SAVEFILE_NAME)
@data = load_data(SAVEFILE_NAME)
else
@data = {}
end
def self.[](key)
@data[key]
end
def self.[]=(key, value)
@data[key] = value
on_change
end
def self.on_change
save_data @data, SAVEFILE_NAME
end
# This method can be used for consecutive value changes,
# so that the file is written only once.
# The methods defined in Hash can be used for data manipulation.
def self.data
if block_given?
begin
yield @data
ensure
on_change
end
else
@data
end
end
end
end