#==============================================================================
# ■ 技能装备系统 for RGSS1 by:VIPArcher
#==============================================================================
$VIPArcherScript ||= {};$VIPArcherScript[:battle_skill] = 20150717
module VIPArcher end
module VIPArcher::Battle_Skill
SKILL_SLOT_NAME_PREFIX = '技能槽'
SKILL_OCCASION = ['平时', '战斗中', '菜单中', '不能使用']
SKILL_SCOPE = ['无', '敌单体', '敌全体', '己方单体', '己方全体',
'己方单体(战斗不能)', '己方全体(战斗不能)', '使用者']
BLANK_TEXT = '- 空技能槽 -'
BLANK_HELP = '空的技能槽,可以装备战斗技能。'
RELEASE_ICON = '047-Skill04'
RELEASE_HELP = '卸下已装备的技能。'
RELEASE_TEXT = '[卸下技能]'
end
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
#==============================================================================
# ■ Game_Actor
#==============================================================================
class Game_Actor < Game_Battler
include VIPArcher::Battle_Skill
attr_reader :battle_skill
alias battle_skill_initialize initialize
def initialize(actor_id)
@battle_skill = []
@last_variable2 = 0
battle_skill_initialize(actor_id)
adjust_battle_skill_slots
end
def skill_slot_limit
n = $game_variables[2].to_i
return 99 if n <= 0
return n
end
# 调整技能槽数量和内容
def adjust_battle_skill_slots
limit = skill_slot_limit
current_var = $game_variables[2].to_i
# 从无限制切换到有限制 → 清空所有槽位
if @last_variable2 <= 0 && current_var > 0
@battle_skill = Array.new(limit) { nil }
else
# 调整数组长度
if @battle_skill.size < limit
(@battle_skill.size...limit).each { @battle_skill << nil }
elsif @battle_skill.size > limit
@battle_skill = @battle_skill[0, limit]
end
# 清理已失效的技能
@battle_skill.map! { |sid| sid && skill_learn?(sid) ? sid : nil }
end
# 无限制模式下不需要强制填充
@last_variable2 = current_var
end
def skill_slot_names
(1..skill_slot_limit).map { |i| "#{SKILL_SLOT_NAME_PREFIX}#{i}" }
end
def add_battle_skill(skill, id)
@battle_skill[id] = nil if skill.zero?
return if @battle_skill.include?(skill)
@battle_skill[id] = skill if skills.include?(skill)
end
alias battle_skill_learn_skill learn_skill
def learn_skill(skill_id)
battle_skill_learn_skill(skill_id)
adjust_battle_skill_slots
# 仅当有限制模式才自动装备到空槽
if $game_variables[2].to_i > 0
auto_add_battle_skill(skill_id) unless @battle_skill.include?(skill_id)
end
end
def auto_add_battle_skill(skill_id)
@battle_skill.each_index do |index|
return @battle_skill[index] = skill_id if @battle_skill[index].nil?
end
end
alias battle_skill_forget_skill forget_skill
def forget_skill(skill_id)
battle_skill_forget_skill(skill_id)
if @battle_skill.include?(skill_id)
@battle_skill[@battle_skill.index(skill_id)] = nil
end
adjust_battle_skill_slots
end
def refresh_battle_skill_slots
adjust_battle_skill_slots
end
end
#==============================================================================
# ■ Window_Selectable
#==============================================================================
class Window_Selectable < Window_Base
def create_contents
self.contents.dispose if self.contents
self.contents = Bitmap.new(width - 32, row_max * 32)
end
end
#==============================================================================
# ■ Window_EquipSkillLeft
#==============================================================================
class Window_EquipSkillLeft < Window_Base
include VIPArcher::Battle_Skill
def initialize(actor, skill = nil)
super(0, 64, 272, 192)
self.contents = Bitmap.new(width - 32, height - 32)
@actor, @skill = actor, skill
refresh
end
def refresh
self.contents.clear
draw_actor_name(@actor, 4, 0)
draw_actor_level(@actor, 132, 0)
draw_skill_info unless @skill.nil?
end
def set_skill(skill)
@skill = skill
refresh
end
def draw_skill_info
self.contents.font.color = system_color
self.contents.draw_text(0, 32, 128, 32, '使用场合')
self.contents.font.color = normal_color
self.contents.draw_text(32, 64, 128, 32, SKILL_OCCASION[@skill.occasion])
self.contents.font.color = system_color
self.contents.draw_text(0, 96, 128, 32, '效果范围')
self.contents.font.color = normal_color
self.contents.draw_text(32, 128, 320, 32, SKILL_SCOPE[@skill.scope])
end
end
#==============================================================================
# ■ Window_EquipSkillSlot
#==============================================================================
class Window_EquipSkillSlot < Window_Selectable
include VIPArcher::Battle_Skill
attr_writer :skill_info_window
VISIBLE_ROW = 5 # 固定显示行数
def initialize(actor, skill_index = 0)
@slot_count = actor.battle_skill.size
h = VISIBLE_ROW * 32 + 32
super(272, 64, 368, h)
@actor = actor
@item_max = @slot_count
self.index = skill_index
refresh
end
# 总行数 = 实际槽数
def row_max
@item_max
end
def data
@actor.battle_skill
end
def item
data[self.index] ? $data_skills[data[self.index]] : nil
end
def refresh
@item_max = data.size
# 手动更新内容位图
if self.contents.nil? || self.contents.height < @item_max * 32
self.contents.dispose if self.contents
self.contents = Bitmap.new(width - 32, @item_max * 32)
end
self.contents.clear
names = @actor.skill_slot_names
# 绘制所有槽
(0...@item_max).each do |id|
rect = item_rect(id)
skill_id = data[id]
self.contents.font.color = system_color
self.contents.draw_text(rect.x + 4, rect.y, 92, 32, names[id] || '')
if skill_id.nil?
self.contents.font.color = normal_color
self.contents.draw_text(rect.x + 128, rect.y, 192, 32, BLANK_TEXT)
else
draw_item_name($data_skills[skill_id], rect.x + 128, rect.y)
end
end
end
# 每行的原始矩形
def item_rect(index)
Rect.new(0, index * 32, 328, 32)
end
def update_help
@help_window.set_text(item.nil? ? BLANK_HELP : item.description)
@skill_info_window.set_skill(item) if @skill_info_window
end
end
#==============================================================================
# ■ Window_SkillItem
#==============================================================================
class Window_SkillItem < Window_Selectable
include VIPArcher::Battle_Skill
attr_writer :skill_info_window
def initialize(actor)
super(0, 256, 640, 224)
@actor, @column_max, self.active, self.index = actor, 2, false, -1
refresh
end
def item
@data[self.index] ? $data_skills[@data[self.index]] : nil
end
def refresh
@data = []
skills = @actor.skills.select { |skill| !@actor.battle_skill.include?(skill) }
skills.each { |skill| @data.push(skill) }
@data.push(nil)
@item_max = @data.size
create_contents
@data.each_index { |index| draw_item(index) }
end
def draw_item(index)
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
self.contents.font.color = normal_color
if @data[index]
skill = $data_skills[@data[index]]
bitmap = RPG::Cache.icon(skill.icon_name)
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24))
self.contents.draw_text(x + 28, y, 212, 32, skill.name)
else
bitmap = RPG::Cache.icon(RELEASE_ICON) if RELEASE_ICON
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24)) if bitmap
self.contents.draw_text(x + 28, y, 212, 32, RELEASE_TEXT)
end
end
def update_help
@help_window.set_text(item.nil? ? RELEASE_HELP : item.description)
@skill_info_window.set_skill(item) if @skill_info_window
end
end
#==============================================================================
# ■ Window_Skill
#==============================================================================
class Window_Skill < Window_Selectable
# 刷新技能列表
def refresh
@data = []
if $scene.instance_of?(Scene_Battle)
if $game_variables[2].to_i <= 0
# 无限制:显示所有已学技能
@actor.skills.each do |id|
skill = $data_skills[id]
@data.push(skill) if skill
end
else
# 有限制:显示已装备技能
@actor.battle_skill.each do |id|
next if id.nil?
skill = $data_skills[id]
@data.push(skill) if skill
end
end
else
# 非战斗场景:显示所有已学技能
@actor.skills.each do |id|
skill = $data_skills[id]
@data.push(skill) if skill
end
end
@item_max = @data.size
# 只有当有技能时才创建内容位图
if @item_max > 0
self.contents.dispose if self.contents
self.contents = Bitmap.new(width - 32, @item_max * 32)
@data.each_index { |index| draw_item(index) }
else
self.contents.dispose if self.contents
self.contents = Bitmap.new(width - 32, 1)
end
end
# 描绘单个技能
def draw_item(index)
skill = @data[index]
return if skill.nil?
if @actor.skill_can_use?(skill.id)
self.contents.font.color = normal_color
else
self.contents.font.color = disabled_color
end
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(skill.icon_name)
opacity = self.contents.font.color == normal_color ? 255 : 128
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
self.contents.draw_text(x + 232, y, 48, 32, skill.sp_cost.to_s, 2)
end
end
#==============================================================================
# ■ Scene_SetEquipSkill
#==============================================================================
class Scene_SetEquipSkill
def initialize(actor_index = 0, skill_index = 0)
@actor_index, @skill_index = actor_index, skill_index
end
def main
@actor = $game_party.actors[@actor_index]
@actor.adjust_battle_skill_slots
create_all_window
Graphics.transition
[Graphics, Input, self].map(&:update) while $scene.equal?(self)
Graphics.freeze
dispose_all_window
end
def create_all_window
@help_window = Window_Help.new
@right_window = Window_EquipSkillSlot.new(@actor, @skill_index)
@left_window = Window_EquipSkillLeft.new(@actor, @right_window.item)
slot_window_bottom = @right_window.y + @right_window.height
@skillitem_window = Window_SkillItem.new(@actor)
@skillitem_window.y = slot_window_bottom
@skillitem_window.height = 480 - slot_window_bottom
@right_window.help_window = @help_window
@skillitem_window.help_window = @help_window
@right_window.skill_info_window = @left_window
@skillitem_window.skill_info_window = @left_window
end
def update
update_all_windows
return update_right if @right_window.active
return update_item if @skillitem_window.active
end
def update_right
return scene_return if Input.trigger?(Input::B)
return on_slot_ok if Input.trigger?(Input::C)
return process_pagedown if Input.trigger?(Input::RIGHT)
return process_pageup if Input.trigger?(Input::LEFT)
return process_pageup if Input.trigger?(Input::L) # Q键
end
def update_item
return on_item_cancel if Input.trigger?(Input::B)
return on_item_ok if Input.trigger?(Input::C)
end
def on_item_ok
$game_system.se_play($data_system.equip_se)
skill = @skillitem_window.item
@actor.add_battle_skill(skill.nil? ? 0 : skill.id, @right_window.index)
@right_window.active = true
@skillitem_window.active = false
@skillitem_window.index = -1
@right_window.refresh
@skillitem_window.refresh
end
def on_item_cancel
$game_system.se_play($data_system.cancel_se)
@right_window.active = true
@skillitem_window.active = false
@skillitem_window.index = -1
end
def scene_return
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
end
def on_slot_ok
$game_system.se_play($data_system.decision_se)
@right_window.active = false
@skillitem_window.active = true
@skillitem_window.index = 0
end
def process_pageup
$game_system.se_play($data_system.cursor_se)
@actor_index += $game_party.actors.size - 1
@actor_index %= $game_party.actors.size
$scene = Scene_SetEquipSkill.new(@actor_index, 0)
end
def process_pagedown
$game_system.se_play($data_system.cursor_se)
@actor_index += 1
@actor_index %= $game_party.actors.size
$scene = Scene_SetEquipSkill.new(@actor_index, 0)
end
def update_all_windows
instance_variables.each do |varname|
ivar = instance_variable_get(varname)
ivar.update if ivar.is_a?(Window)
end
end
def dispose_all_window
instance_variables.each do |varname|
ivar = instance_variable_get(varname)
ivar.dispose if ivar.is_a?(Window)
end
end
end
#==============================================================================
# ■ Interpreter
#==============================================================================
class Interpreter
alias battle_skill_command_111 command_111
def command_111
result = false
if [@parameters[0], @parameters[2]] == [4, 2]
actor = $game_actors[@parameters[1]]
if actor != nil
if $scene.instance_of?(Scene_Battle)
result = (actor.battle_skill.include?(@parameters[3]))
else
result = (actor.skill_learn?(@parameters[3]))
end
end
@branch[@list[@index].indent] = result
if @branch[@list[@index].indent] == true
@branch.delete(@list[@index].indent)
return true
end
return command_skip
else
battle_skill_command_111
end
end
end