查看: 467|回复: 5

[有事请教] XP的技能CP系统脚本

[复制链接]
梦石
0
星屑
1353
在线时间
170 小时
注册时间
2023-6-4
回帖
8

极短28参与

发表于 2026-7-19 09:22:00 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
如何实现角色技能可像装备那样装卸,用以设定在战斗中所携带的技能?
(想到该功能的初衷是注意到游戏流程中很多战斗都是仅需要每个角色只使用少数甚至一种技能,但每次都需要光标移过根本不会用到的大部分技能)
站内已有类似脚本,如【让技能像装备一样装备吧~技能SP系统】(https://rpg.blue/thread-376363-1-1.html)(不仅能实现该功能,还可以灵活地限制技能携带),但是VA脚本;图书馆收录的技能装备系统(7F,13号:https://rpg.blue/forum.php?mod=v ... p;page=1#pid2603195),但是限死了角色可携带技能的最大数量。
如何使后一脚本中技能槽数量可以灵活设定,或者可否进一步,将前一脚本功能移植至XP?

素材区好人

梦石
5
星屑
12559
在线时间
4345 小时
注册时间
2011-7-21
回帖
2264

超评测参与极短28参与极短27参与极短26参与极短25参与极短24参与极短23参与极短22参与极短21参与

发表于 2026-7-20 05:40:01 | 显示全部楼层
本帖最后由 无忧谷主幻 于 2026-7-20 09:47 编辑

装备槽数量可控,变量2数值就是装备槽的数量,如果变量2等于0,角色自动装备所有技能
输入
[pre lang="ruby"]$scene = Scene_SetEquipSkill.new(0, 0)[/pre]
调出技能装备菜单
Q切换角色
水平较低,有错误告诉我
[fold=技能装备系统][pre lang="ruby"]#==============================================================================
# ■ 技能装备系统 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 = []
    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
    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
    if $game_variables[2].to_i <= 0
      @battle_skill = skills.map(&:id)
    else
      @battle_skill.map! { |sid| sid && skill_learn?(sid) ? sid : nil }
    end
  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
    auto_add_battle_skill(skill_id) unless @battle_skill.include?(skill_id)
  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   # 窗口高度保持5行+边框
    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, @right_window.index)
  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, @right_window.index)
  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[/pre][/fold]
回复

使用道具 举报

梦石
0
星屑
1353
在线时间
170 小时
注册时间
2023-6-4
回帖
8

极短28参与

 楼主| 发表于 2026-7-20 06:29:38 | 显示全部楼层
无忧谷主幻 发表于 2026-7-20 05:40
装备槽数量可控,变量2数值就是装备槽的数量,如果变量2等于0,角色自动装备所有技能
输入
$scene = Scene_ ...

变量2设置为0时有一些问题 有的角色会自动装备上未习得的技能(技能槽数量确实与角色技能数一致,槽并不满),有的角色不会自动装备上技能(这两种情况不会影响战斗中确实携带着所有技能);存在技能槽为空时不显示“-  空技能槽  -”在该槽位置卸下技能后才会显示;切换角色时若切换前角色技能数量多于后者且光标在多出的技能槽部分,切换后光标就会停留在原本不能移动到的位置,在这种位置上还可以进行装备技能操作
这里是一个可以复现上述情形的工程 Project1 - 副本.rar (446.95 KB, 下载次数: 1)
回复

使用道具 举报

素材区好人

梦石
5
星屑
12559
在线时间
4345 小时
注册时间
2011-7-21
回帖
2264

超评测参与极短28参与极短27参与极短26参与极短25参与极短24参与极短23参与极短22参与极短21参与

发表于 2026-7-20 09:18:31 | 显示全部楼层
本帖最后由 无忧谷主幻 于 2026-7-20 10:56 编辑
Imotti 发表于 2026-7-20 06:29
变量2设置为0时有一些问题 有的角色会自动装备上未习得的技能(技能槽数量确实与角色技能数一致,槽并不 ...


修复了一下,变量等于0时,若还打开技能槽会显示99个,当然这其实没意义,因为这时候战斗时角色会自动装备所有技能
按下Q键切换技能槽时,光标也会直接回到第一个技能槽
[pre lang="ruby"]#==============================================================================
# ■ 技能装备系统 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[/pre]
回复

使用道具 举报

梦石
0
星屑
1353
在线时间
170 小时
注册时间
2023-6-4
回帖
8

极短28参与

 楼主| 发表于 2026-7-20 10:41:23 | 显示全部楼层
无忧谷主幻 发表于 2026-7-20 09:18
修复了一下,变量等于0时,若还打开技能槽会显示99个,当然这其实没意义,因为这时候战斗时角色会自动装 ...

除了技能槽数量较多时略微卡顿外,设想中的功能确实能实现了,感谢回复解答(417行似乎少了一个end,不过无伤大雅)

点评

不小心误删了,已经修改  发表于 2026-7-20 10:57
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部