设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 72|回复: 5
打印 上一主题 下一主题

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

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1162
在线时间
139 小时
注册时间
2023-6-4
帖子
9

极短28参与

跳转到指定楼层
1
发表于 昨天 09:22 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

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

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

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

Lv3.寻梦者

梦石
0
星屑
1162
在线时间
139 小时
注册时间
2023-6-4
帖子
9

极短28参与

5
 楼主| 发表于 8 小时前 | 只看该作者
无忧谷主幻 发表于 2026-7-20 09:18
修复了一下,变量等于0时,若还打开技能槽会显示99个,当然这其实没意义,因为这时候战斗时角色会自动装 ...

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

点评

不小心误删了,已经修改  发表于 8 小时前
回复 支持 反对

使用道具 举报

Lv4.逐梦者

素材区好人

梦石
3
星屑
11798
在线时间
4280 小时
注册时间
2011-7-21
帖子
2557

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

4
发表于 10 小时前 | 只看该作者
本帖最后由 无忧谷主幻 于 2026-7-20 10:56 编辑
Imotti 发表于 2026-7-20 06:29
变量2设置为0时有一些问题 有的角色会自动装备上未习得的技能(技能槽数量确实与角色技能数一致,槽并不 ...


修复了一下,变量等于0时,若还打开技能槽会显示99个,当然这其实没意义,因为这时候战斗时角色会自动装备所有技能
按下Q键切换技能槽时,光标也会直接回到第一个技能槽
RUBY 代码复制
  1. #==============================================================================
  2. # ■ 技能装备系统 for RGSS1 by:VIPArcher
  3. #==============================================================================
  4. $VIPArcherScript ||= {};$VIPArcherScript[:battle_skill] = 20150717
  5.  
  6. module VIPArcher end
  7.  
  8. module VIPArcher::Battle_Skill
  9.   SKILL_SLOT_NAME_PREFIX = '技能槽'
  10.   SKILL_OCCASION   = ['平时', '战斗中', '菜单中', '不能使用']
  11.   SKILL_SCOPE      = ['无', '敌单体', '敌全体', '己方单体', '己方全体',
  12.                       '己方单体(战斗不能)', '己方全体(战斗不能)', '使用者']
  13.   BLANK_TEXT   = '-  空技能槽  -'
  14.   BLANK_HELP   = '空的技能槽,可以装备战斗技能。'
  15.   RELEASE_ICON = '047-Skill04'
  16.   RELEASE_HELP = '卸下已装备的技能。'
  17.   RELEASE_TEXT = '[卸下技能]'
  18. end
  19.  
  20. class Symbol
  21.   def to_proc
  22.     Proc.new { |*args| args.shift.__send__(self, *args) }
  23.   end
  24. end
  25.  
  26. #==============================================================================
  27. # ■ Game_Actor
  28. #==============================================================================
  29. class Game_Actor < Game_Battler
  30.   include VIPArcher::Battle_Skill
  31.  
  32.   attr_reader :battle_skill
  33.  
  34.   alias battle_skill_initialize initialize
  35.   def initialize(actor_id)
  36.     @battle_skill = []
  37.     @last_variable2 = 0         
  38.     battle_skill_initialize(actor_id)
  39.     adjust_battle_skill_slots
  40.   end
  41.  
  42.   def skill_slot_limit
  43.     n = $game_variables[2].to_i
  44.     return 99 if n <= 0
  45.     return n
  46.   end
  47.  
  48.   # 调整技能槽数量和内容
  49.   def adjust_battle_skill_slots
  50.     limit = skill_slot_limit
  51.     current_var = $game_variables[2].to_i
  52.     # 从无限制切换到有限制 → 清空所有槽位
  53.     if @last_variable2 <= 0 && current_var > 0
  54.       @battle_skill = Array.new(limit) { nil }
  55.     else
  56.       # 调整数组长度
  57.       if @battle_skill.size < limit
  58.         (@battle_skill.size...limit).each { @battle_skill << nil }
  59.       elsif @battle_skill.size > limit
  60.         @battle_skill = @battle_skill[0, limit]
  61.       end
  62.       # 清理已失效的技能
  63.       @battle_skill.map! { |sid| sid && skill_learn?(sid) ? sid : nil }
  64.     end
  65.     # 无限制模式下不需要强制填充
  66.     @last_variable2 = current_var
  67.   end
  68.  
  69.   def skill_slot_names
  70.     (1..skill_slot_limit).map { |i| "#{SKILL_SLOT_NAME_PREFIX}#{i}" }
  71.   end
  72.  
  73.   def add_battle_skill(skill, id)
  74.     @battle_skill[id] = nil if skill.zero?
  75.     return if @battle_skill.include?(skill)
  76.     @battle_skill[id] = skill if skills.include?(skill)
  77.   end
  78.  
  79.   alias battle_skill_learn_skill learn_skill
  80.   def learn_skill(skill_id)
  81.     battle_skill_learn_skill(skill_id)
  82.     adjust_battle_skill_slots
  83.     # 仅当有限制模式才自动装备到空槽
  84.     if $game_variables[2].to_i > 0
  85.       auto_add_battle_skill(skill_id) unless @battle_skill.include?(skill_id)
  86.     end
  87.   end
  88.  
  89.   def auto_add_battle_skill(skill_id)
  90.     @battle_skill.each_index do |index|
  91.       return @battle_skill[index] = skill_id if @battle_skill[index].nil?
  92.     end
  93.   end
  94.  
  95.   alias battle_skill_forget_skill forget_skill
  96.   def forget_skill(skill_id)
  97.     battle_skill_forget_skill(skill_id)
  98.     if @battle_skill.include?(skill_id)
  99.       @battle_skill[@battle_skill.index(skill_id)] = nil
  100.     end
  101.     adjust_battle_skill_slots
  102.   end
  103.  
  104.   def refresh_battle_skill_slots
  105.     adjust_battle_skill_slots
  106.   end
  107. end
  108.  
  109. #==============================================================================
  110. # ■ Window_Selectable
  111. #==============================================================================
  112. class Window_Selectable < Window_Base
  113.   def create_contents
  114.     self.contents.dispose if self.contents
  115.     self.contents = Bitmap.new(width - 32, row_max * 32)
  116.   end
  117. end
  118.  
  119. #==============================================================================
  120. # ■ Window_EquipSkillLeft
  121. #==============================================================================
  122. class Window_EquipSkillLeft < Window_Base
  123.   include VIPArcher::Battle_Skill
  124.   def initialize(actor, skill = nil)
  125.     super(0, 64, 272, 192)
  126.     self.contents = Bitmap.new(width - 32, height - 32)
  127.     @actor, @skill = actor, skill
  128.     refresh
  129.   end
  130.   def refresh
  131.     self.contents.clear
  132.     draw_actor_name(@actor, 4, 0)
  133.     draw_actor_level(@actor, 132, 0)
  134.     draw_skill_info unless @skill.nil?
  135.   end
  136.   def set_skill(skill)
  137.     @skill = skill
  138.     refresh
  139.   end
  140.   def draw_skill_info
  141.     self.contents.font.color = system_color
  142.     self.contents.draw_text(0, 32, 128, 32, '使用场合')
  143.     self.contents.font.color = normal_color
  144.     self.contents.draw_text(32, 64, 128, 32, SKILL_OCCASION[@skill.occasion])
  145.     self.contents.font.color = system_color
  146.     self.contents.draw_text(0, 96, 128, 32, '效果范围')
  147.     self.contents.font.color = normal_color
  148.     self.contents.draw_text(32, 128, 320, 32, SKILL_SCOPE[@skill.scope])
  149.   end
  150. end
  151.  
  152. #==============================================================================
  153. # ■ Window_EquipSkillSlot
  154. #==============================================================================
  155. class Window_EquipSkillSlot < Window_Selectable
  156.   include VIPArcher::Battle_Skill
  157.   attr_writer :skill_info_window
  158.  
  159.   VISIBLE_ROW = 5  # 固定显示行数
  160.  
  161.   def initialize(actor, skill_index = 0)
  162.     @slot_count = actor.battle_skill.size
  163.     h = VISIBLE_ROW * 32 + 32   
  164.     super(272, 64, 368, h)
  165.     @actor = actor
  166.     @item_max = @slot_count
  167.     self.index = skill_index
  168.     refresh
  169.   end
  170.  
  171.   # 总行数 = 实际槽数
  172.   def row_max
  173.     @item_max
  174.   end
  175.  
  176.   def data
  177.     @actor.battle_skill
  178.   end
  179.  
  180.   def item
  181.     data[self.index] ? $data_skills[data[self.index]] : nil
  182.   end
  183.  
  184.   def refresh
  185.     @item_max = data.size
  186.     # 手动更新内容位图
  187.     if self.contents.nil? || self.contents.height < @item_max * 32
  188.       self.contents.dispose if self.contents
  189.       self.contents = Bitmap.new(width - 32, @item_max * 32)
  190.     end
  191.     self.contents.clear
  192.     names = @actor.skill_slot_names
  193.     # 绘制所有槽
  194.     (0...@item_max).each do |id|
  195.       rect = item_rect(id)
  196.       skill_id = data[id]
  197.       self.contents.font.color = system_color
  198.       self.contents.draw_text(rect.x + 4, rect.y, 92, 32, names[id] || '')
  199.       if skill_id.nil?
  200.         self.contents.font.color = normal_color
  201.         self.contents.draw_text(rect.x + 128, rect.y, 192, 32, BLANK_TEXT)
  202.       else
  203.         draw_item_name($data_skills[skill_id], rect.x + 128, rect.y)
  204.       end
  205.     end
  206.   end
  207.  
  208.   # 每行的原始矩形
  209.   def item_rect(index)
  210.     Rect.new(0, index * 32, 328, 32)
  211.   end
  212.  
  213.   def update_help
  214.     @help_window.set_text(item.nil? ? BLANK_HELP : item.description)
  215.     @skill_info_window.set_skill(item) if @skill_info_window
  216.   end
  217. end
  218.  
  219. #==============================================================================
  220. # ■ Window_SkillItem
  221. #==============================================================================
  222. class Window_SkillItem < Window_Selectable
  223.   include VIPArcher::Battle_Skill
  224.   attr_writer :skill_info_window
  225.  
  226.   def initialize(actor)
  227.     super(0, 256, 640, 224)
  228.     @actor, @column_max, self.active, self.index = actor, 2, false, -1
  229.     refresh
  230.   end
  231.  
  232.   def item
  233.     @data[self.index] ? $data_skills[@data[self.index]] : nil
  234.   end
  235.  
  236.   def refresh
  237.     @data  = []
  238.     skills = @actor.skills.select { |skill| !@actor.battle_skill.include?(skill) }
  239.     skills.each { |skill| @data.push(skill) }
  240.     @data.push(nil)
  241.     @item_max = @data.size
  242.     create_contents
  243.     @data.each_index { |index| draw_item(index) }
  244.   end
  245.  
  246.   def draw_item(index)
  247.     x = 4 + index % 2 * (288 + 32)
  248.     y = index / 2 * 32
  249.     self.contents.font.color = normal_color
  250.     if @data[index]
  251.       skill  = $data_skills[@data[index]]
  252.       bitmap = RPG::Cache.icon(skill.icon_name)
  253.       self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24))
  254.       self.contents.draw_text(x + 28, y, 212, 32, skill.name)
  255.     else
  256.       bitmap = RPG::Cache.icon(RELEASE_ICON) if RELEASE_ICON
  257.       self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24)) if bitmap
  258.       self.contents.draw_text(x + 28, y, 212, 32, RELEASE_TEXT)
  259.     end
  260.   end
  261.  
  262.   def update_help
  263.     @help_window.set_text(item.nil? ? RELEASE_HELP : item.description)
  264.     @skill_info_window.set_skill(item) if @skill_info_window
  265.   end
  266. end
  267.  
  268. #==============================================================================
  269. # ■ Window_Skill
  270. #==============================================================================
  271. class Window_Skill < Window_Selectable
  272.   # 刷新技能列表
  273.   def refresh
  274.     @data = []
  275.     if $scene.instance_of?(Scene_Battle)
  276.       if $game_variables[2].to_i <= 0
  277.         # 无限制:显示所有已学技能
  278.         @actor.skills.each do |id|
  279.           skill = $data_skills[id]
  280.           @data.push(skill) if skill
  281.         end
  282.       else
  283.         # 有限制:显示已装备技能
  284.         @actor.battle_skill.each do |id|
  285.           next if id.nil?
  286.           skill = $data_skills[id]
  287.           @data.push(skill) if skill
  288.         end
  289.       end
  290.     else
  291.       # 非战斗场景:显示所有已学技能
  292.       @actor.skills.each do |id|
  293.         skill = $data_skills[id]
  294.         @data.push(skill) if skill
  295.       end
  296.     end
  297.     @item_max = @data.size
  298.     # 只有当有技能时才创建内容位图
  299.     if @item_max > 0
  300.       self.contents.dispose if self.contents
  301.       self.contents = Bitmap.new(width - 32, @item_max * 32)
  302.       @data.each_index { |index| draw_item(index) }
  303.     else
  304.       self.contents.dispose if self.contents
  305.       self.contents = Bitmap.new(width - 32, 1)
  306.     end
  307.   end
  308.  
  309.   # 描绘单个技能
  310.   def draw_item(index)
  311.     skill = @data[index]
  312.     return if skill.nil?  
  313.  
  314.     if @actor.skill_can_use?(skill.id)
  315.       self.contents.font.color = normal_color
  316.     else
  317.       self.contents.font.color = disabled_color
  318.     end
  319.     x = 4 + index % 2 * (288 + 32)
  320.     y = index / 2 * 32
  321.     rect = Rect.new(x, y, self.width / @column_max - 32, 32)
  322.     self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
  323.     bitmap = RPG::Cache.icon(skill.icon_name)
  324.     opacity = self.contents.font.color == normal_color ? 255 : 128
  325.     self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
  326.     self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
  327.     self.contents.draw_text(x + 232, y, 48, 32, skill.sp_cost.to_s, 2)
  328.   end
  329. end
  330.  
  331. #==============================================================================
  332. # ■ Scene_SetEquipSkill
  333. #==============================================================================
  334. class Scene_SetEquipSkill
  335.   def initialize(actor_index = 0, skill_index = 0)
  336.     @actor_index, @skill_index = actor_index, skill_index
  337.   end
  338.  
  339.   def main
  340.     @actor = $game_party.actors[@actor_index]
  341.     @actor.adjust_battle_skill_slots
  342.     create_all_window
  343.     Graphics.transition
  344.     [Graphics, Input, self].map(&:update) while $scene.equal?(self)
  345.     Graphics.freeze
  346.     dispose_all_window
  347.   end
  348.  
  349.   def create_all_window
  350.     @help_window      = Window_Help.new
  351.     @right_window     = Window_EquipSkillSlot.new(@actor, @skill_index)
  352.     @left_window      = Window_EquipSkillLeft.new(@actor, @right_window.item)
  353.     slot_window_bottom = @right_window.y + @right_window.height
  354.     @skillitem_window = Window_SkillItem.new(@actor)
  355.     @skillitem_window.y = slot_window_bottom
  356.     @skillitem_window.height = 480 - slot_window_bottom
  357.     @right_window.help_window      = @help_window
  358.     @skillitem_window.help_window  = @help_window
  359.     @right_window.skill_info_window     = @left_window
  360.     @skillitem_window.skill_info_window = @left_window
  361.   end
  362.  
  363.   def update
  364.     update_all_windows
  365.     return update_right if @right_window.active
  366.     return update_item  if @skillitem_window.active
  367.   end
  368.  
  369.   def update_right
  370.     return scene_return     if Input.trigger?(Input::B)
  371.     return on_slot_ok       if Input.trigger?(Input::C)
  372.     return process_pagedown if Input.trigger?(Input::RIGHT)
  373.     return process_pageup   if Input.trigger?(Input::LEFT)
  374.     return process_pageup   if Input.trigger?(Input::L)   # Q键
  375.   end
  376.  
  377.   def update_item
  378.     return on_item_cancel if Input.trigger?(Input::B)
  379.     return on_item_ok     if Input.trigger?(Input::C)
  380.   end
  381.  
  382.   def on_item_ok
  383.     $game_system.se_play($data_system.equip_se)
  384.     skill = @skillitem_window.item
  385.     @actor.add_battle_skill(skill.nil? ? 0 : skill.id, @right_window.index)
  386.     @right_window.active     = true
  387.     @skillitem_window.active = false
  388.     @skillitem_window.index  = -1
  389.     @right_window.refresh
  390.     @skillitem_window.refresh
  391.   end
  392.  
  393.   def on_item_cancel
  394.     $game_system.se_play($data_system.cancel_se)
  395.     @right_window.active     = true
  396.     @skillitem_window.active = false
  397.     @skillitem_window.index  = -1
  398.   end
  399.  
  400.   def scene_return
  401.     $game_system.se_play($data_system.cancel_se)
  402.     $scene = Scene_Map.new
  403.   end
  404.  
  405.   def on_slot_ok
  406.     $game_system.se_play($data_system.decision_se)
  407.     @right_window.active     = false
  408.     @skillitem_window.active = true
  409.     @skillitem_window.index  = 0
  410.   end
  411.  
  412.   def process_pageup
  413.     $game_system.se_play($data_system.cursor_se)
  414.     @actor_index += $game_party.actors.size - 1
  415.     @actor_index %= $game_party.actors.size
  416.     $scene = Scene_SetEquipSkill.new(@actor_index, 0)  
  417.   end
  418.   def process_pagedown
  419.     $game_system.se_play($data_system.cursor_se)
  420.     @actor_index += 1
  421.     @actor_index %= $game_party.actors.size
  422.     $scene = Scene_SetEquipSkill.new(@actor_index, 0)  
  423.   end
  424.  
  425.   def update_all_windows
  426.     instance_variables.each do |varname|
  427.       ivar = instance_variable_get(varname)
  428.       ivar.update if ivar.is_a?(Window)
  429.     end
  430.   end
  431.  
  432.   def dispose_all_window
  433.     instance_variables.each do |varname|
  434.       ivar = instance_variable_get(varname)
  435.       ivar.dispose if ivar.is_a?(Window)
  436.     end
  437.   end
  438. end
  439.  
  440. #==============================================================================
  441. # ■ Interpreter
  442. #==============================================================================
  443. class Interpreter
  444.   alias battle_skill_command_111 command_111
  445.   def command_111
  446.     result = false
  447.     if [@parameters[0], @parameters[2]] == [4, 2]
  448.       actor = $game_actors[@parameters[1]]
  449.       if actor != nil
  450.         if $scene.instance_of?(Scene_Battle)
  451.           result = (actor.battle_skill.include?(@parameters[3]))
  452.         else
  453.           result = (actor.skill_learn?(@parameters[3]))
  454.         end
  455.       end
  456.       @branch[@list[@index].indent] = result
  457.       if @branch[@list[@index].indent] == true
  458.         @branch.delete(@list[@index].indent)
  459.         return true
  460.       end
  461.       return command_skip
  462.     else
  463.       battle_skill_command_111
  464.     end
  465.   end
  466. end
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1162
在线时间
139 小时
注册时间
2023-6-4
帖子
9

极短28参与

3
 楼主| 发表于 13 小时前 | 只看该作者
无忧谷主幻 发表于 2026-7-20 05:40
装备槽数量可控,变量2数值就是装备槽的数量,如果变量2等于0,角色自动装备所有技能
输入
$scene = Scene_ ...

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

使用道具 举报

Lv4.逐梦者

素材区好人

梦石
3
星屑
11798
在线时间
4280 小时
注册时间
2011-7-21
帖子
2557

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

2
发表于 13 小时前 | 只看该作者
本帖最后由 无忧谷主幻 于 2026-7-20 09:47 编辑

装备槽数量可控,变量2数值就是装备槽的数量,如果变量2等于0,角色自动装备所有技能
输入
RUBY 代码复制
  1. $scene = Scene_SetEquipSkill.new(0, 0)

调出技能装备菜单
Q切换角色
水平较低,有错误告诉我
技能装备系统
回复 支持 反对

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2026-7-20 19:34

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表