查看: 16|回复: 0

[原创发布] 仿FGO式多血条

[复制链接]
梦石
0
星屑
2802
在线时间
140 小时
注册时间
2018-6-29
回帖
19

R考场第七期纪念奖

发表于 5 小时前 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 1103123301 于 2026-10-9 00:59 编辑

我说,多血条是好文明(,你还在因为平衡不了伤害导致玩家过于强大秒掉你多阶段又机制美的BOSS么?你还在为大后期设计的BOSS血条已经亿万起步而发愁?这个东西或许能解决燃眉之急(大概)

FGO玩多了试着做着玩下,脚本什么的大部分靠AI帮助,有些多余代码也在所难免…………(比如CP 走条是因为测试时用的《XRXS_BP 1. CP半即时》脚本)

功能:敌人HP为0时会立即满血,就算是“即死”状态也要走破条流程,同时减少1个“生命击破”,待“生命击破”全部失去即可击败敌人,在每个“生命击破”时可以设置机制

注意:由于敌人HP为0时会立即满血,如果事件页设置类似[敌人的HP 5%以下]可能会由于玩家伤害过高的原因无法触发。

  1. #==============================================================================
  2. # ■ FGO 多血条系统 (RPG Maker XP / RGSS1)
  3. #    全部整合在 Window_Help 文件内
  4. #==============================================================================
  5. #可自由转载或使用 萝x婭
  6. #--------------------------------------------------------------------------
  7. # ● 配置区
  8. #--------------------------------------------------------------------------
  9. module FGO_MULTI_HP
  10.   DEFAULT_BARS = 1   # 没配置到的默认 1 管血(即无击破条)
  11. =begin
  12.   HP_BARS = {
  13.   
  14. #++++++++++++++++++++
  15.     #设置ID为33敌人队伍的血管
  16.     33 => {
  17.       1 => 10,   # 1号位敌人 9 管血
  18.       2 => 2,   # 1号位敌人 1 管血
  19.     },
  20.    
  21.    
  22.   #设置ID为34敌人队伍的血管
  23.   34 => {
  24.       1 => 2,   # 1号位敌人 1 管血
  25.       2 => 5,    # 2号位敌人 4 管血
  26.   },
  27.     # 其他战斗继续加,troop_id 去数据库「队伍」页看
  28. #++++++++++++++++++++

  29.   }


  30.   BREAK_ACTIONS = {
  31.   
  32.   #++++++++++++++++++++
  33.   #设置ID为33敌人队伍的破条机制
  34.       33 => {
  35.       1 => [
  36.         proc { |enemy|
  37.         
  38.         $game_party.lose_item(67,9999) #67物品-9999个
  39.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  40.         },   # 1号位第1管击破
  41.         proc { |enemy|
  42.         
  43.         $game_switches[33] = true #开关打开
  44.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  45.         },   # 1号位第2管击破
  46.       ],
  47.         2 => [
  48.         proc { |enemy|
  49.         
  50.         $game_party.gain_item(67,9999) #67物品+9999个
  51.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  52.         },   # 2号位第1管击破
  53.       ],
  54.     },
  55.     #设置ID为34敌人队伍的破条机制
  56.       34 => {
  57.       1 => [
  58.         proc { |enemy|
  59.         
  60.         $game_switches[33] = true #开关打开
  61.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  62.         },   # 1号位第1管击破
  63.         proc { |enemy|
  64.         
  65.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  66.         },   # 1号位第2管击破
  67.       ],
  68.         2 => [
  69.         proc { |enemy|
  70.         
  71.         $game_party.gain_item(67,9999) #67物品+9999个
  72.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  73.         },   # 2号位第1管击破
  74.       ],
  75.     },
  76.   #++++++++++++++++++++
  77.   }
  78. =end


  79.   HP_BARS = {
  80.   
  81. #++++++++++++++++++++
  82.     #设置ID为1敌人队伍的血管
  83.     1 => {
  84.       1 => 10,   # 1号位敌人 9 管血
  85.       2 => 2,   # 1号位敌人 1 管血
  86.     },
  87.    
  88.    
  89.   #设置ID为2敌人队伍的血管
  90.   2 => {
  91.       1 => 2,   # 1号位敌人 1 管血
  92.       2 => 5,    # 2号位敌人 4 管血
  93.   },
  94.     # 其他战斗继续加,troop_id 去数据库「队伍」页看
  95. #++++++++++++++++++++

  96.   }


  97.   BREAK_ACTIONS = {
  98.   
  99.   #++++++++++++++++++++
  100.   #设置ID为1敌人队伍的破条机制
  101.       1 => {
  102.       1 => [
  103.         proc { |enemy|
  104.         
  105.         $game_party.lose_item(67,9999) #67物品-9999个
  106.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  107.         },   # 1号位第1管击破
  108.         proc { |enemy|
  109.         
  110.         $game_switches[33] = true #开关打开
  111.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  112.         },   # 1号位第2管击破
  113.       ],
  114.         2 => [
  115.         proc { |enemy|
  116.         
  117.         $game_party.gain_item(67,9999) #67物品+9999个
  118.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  119.         },   # 2号位第1管击破
  120.       ],
  121.     },
  122.     #设置ID为2敌人队伍的破条机制
  123.       2 => {
  124.       1 => [
  125.         proc { |enemy|
  126.         
  127.         $game_switches[33] = true #开关打开
  128.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  129.         },   # 1号位第1管击破
  130.         proc { |enemy|
  131.         
  132.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  133.         },   # 1号位第2管击破
  134.       ],
  135.         2 => [
  136.         proc { |enemy|
  137.         
  138.         $game_party.gain_item(67,9999) #67物品+9999个
  139.         $scene.start_break_image if $scene.respond_to?(:start_break_image)

  140.         },   # 2号位第1管击破
  141.       ],
  142.     },
  143.   #++++++++++++++++++++
  144.   }
  145.   
  146.   REFILL_HP = true
  147. end
  148. #--------------------------------------------------------------------------
  149. # ● Game_Enemy 扩展:多血条逻辑
  150. #--------------------------------------------------------------------------
  151. class Game_Enemy < Game_Battler
  152.   attr_reader :hp_bars
  153.   attr_reader :max_hp_bars
  154.   attr_reader :fgo_position   # ← 新增

  155.   alias_method :fgo_multi_hp_initialize, :initialize
  156.   def initialize(index, enemy_id)
  157.     fgo_multi_hp_initialize(index, enemy_id)
  158.     @fgo_position = index + 1
  159.     @fgo_troop_id = 0
  160.     @max_hp_bars  = FGO_MULTI_HP::DEFAULT_BARS
  161.     @hp_bars      = @max_hp_bars
  162.   end

  163.   # 由 Game_Troop#setup 调用,传入真实的 troop_id 和位置
  164.   def setup_multi_hp(troop_id, position)
  165.     @fgo_troop_id = troop_id
  166.     @fgo_position = position
  167.     troop_bars = FGO_MULTI_HP::HP_BARS[troop_id]
  168.     @max_hp_bars = (troop_bars && troop_bars[position]) ||
  169.                    FGO_MULTI_HP::DEFAULT_BARS
  170.     @hp_bars = @max_hp_bars
  171.   end

  172. alias_method :fgo_original_hp_eq, :hp=
  173.   def hp=(value)
  174.     if value <= 0 && @hp_bars > 1
  175.       @hp_bars -= 1
  176.       self.fgo_original_hp_eq(FGO_MULTI_HP::REFILL_HP ? maxhp : 1)
  177.       ($fgo_break_queue ||= []) << { :enemy => self, :remain => @hp_bars - 1 }
  178.       run_break_action
  179.     else
  180.       self.fgo_original_hp_eq(value)
  181.     end
  182.   end
  183.   
  184.   #--------------------------------------------------------------------------
  185.   # ● 附加状态:即死类走多血条流程,不直接杀死敌人
  186.   #--------------------------------------------------------------------------
  187.   alias_method :fgo_multi_hp_add_state, :add_state
  188.   def add_state(state_id, force = false)
  189.     st = $data_states[state_id]
  190.     if st && st.zero_hp && @hp_bars > 1
  191.       # 判断这个状态能不能真的附加上(已有该状态 / 被抗性挡住 → 不能)
  192.       can_add = force
  193.       unless can_add
  194.         can_add = !@states.include?(state_id)
  195.         if can_add
  196.           # 兼容不同引擎版本的方法名
  197.           if respond_to?(:state_guard?)
  198.             can_add = !state_guard?(state_id)
  199.           elsif respond_to?(:state_guard)
  200.             can_add = !state_guard(state_id)
  201.           end
  202.           # 两个方法都不存在 → 不检查抗性,直接当能加上
  203.         end
  204.       end

  205.       if can_add
  206.         # 不调原版 add_state(它会 @hp = 0 / self.hp = 0 直接杀死敌人)
  207.         # 改为走一次多血条击破:血条 -1、回满、入队
  208.         @hp_bars -= 1
  209.         self.fgo_original_hp_eq(FGO_MULTI_HP::REFILL_HP ? maxhp : 1)
  210.         ($fgo_break_queue ||= []) << { :enemy => self, :remain => @hp_bars - 1 }
  211.         run_break_action
  212.         return
  213.       end
  214.     end
  215.     fgo_multi_hp_add_state(state_id, force)
  216.   end

  217.   def broken_count
  218.     @max_hp_bars - @hp_bars
  219.   end

  220.   def run_break_action
  221.     troop_actions = FGO_MULTI_HP::BREAK_ACTIONS[@fgo_troop_id]
  222.     return unless troop_actions
  223.     actions = troop_actions[@fgo_position]
  224.     return unless actions
  225.     action = actions[broken_count - 1]
  226.     action.call(self) if action
  227.   end
  228. end

  229. #==============================================================================
  230. # ■ Window_Help
  231. #==============================================================================
  232. class Window_Help < Window_Base
  233.    attr_reader :fgo_enemy
  234.   def fgo_showing_enemy?
  235.     @fgo_showing_enemy == true
  236.   end
  237.   def fgo_force_refresh
  238.     @fgo_last_key = nil
  239.   end
  240.   #--------------------------------------------------------------------------
  241.   # ● 强制指定某个敌人显示的 HP(击破动画期间显示 0)
  242.   #--------------------------------------------------------------------------
  243.   def set_hp_override(enemy, value)
  244.     return if @fgo_hp_override_enemy == enemy && @fgo_hp_override_value == value
  245.     @fgo_hp_override_enemy = enemy
  246.     @fgo_hp_override_value = value
  247.     @fgo_last_key = nil
  248.     # 如果当前正在显示敌人,立刻按 override 值重绘
  249.     if @fgo_showing_enemy && @fgo_enemy
  250.       set_enemy(@fgo_enemy)
  251.     end
  252.   end
  253.   #--------------------------------------------------------------------------
  254.   # ● 显示敌人信息(光标选中敌人时调用)
  255.   #--------------------------------------------------------------------------
  256.   def set_enemy(actor)
  257.     if $scene.is_a?(Scene_Battle)
  258.       st     = $scene.instance_variable_get(:@break_state)
  259.       target = $scene.instance_variable_get(:@break_target)
  260.       q      = $fgo_break_queue || []
  261.       ew     = $scene.instance_variable_get(:@enemy_window)

  262.       if st && target
  263.         # 击破流程进行中 → 锁在正在被击破的敌人身上
  264.         return if actor != target
  265.       elsif !q.empty?
  266.         # 队列非空但还没开始播 → 锁到队列里下一个要播的敌人
  267.         pending = q.min_by { |it|
  268.           [it[:enemy].fgo_position.to_i, -it[:remain].to_i]
  269.         }
  270.         return if pending && actor != pending[:enemy]
  271.       elsif $scene.instance_variable_get(:@phase) != 3
  272.         # 不在 phase3(选敌人/输入指令阶段)→ 不显示窗口
  273.         self.visible = false
  274.         @fgo_showing_enemy = false
  275.         return
  276.       end
  277.     end

  278.     @fgo_showing_enemy = true
  279.     @fgo_enemy = actor
  280.     self.contents.clear
  281.     draw_actor_name(actor, 4, 0)
  282.     draw_actor_state(actor, 140, 0)
  283.     carol3_draw_hp_bar(actor, 284, 0)
  284.     carol3_draw_sp_bar(actor, 460, 0)
  285.     [url=home.php?mod=space&uid=2725481]@text[/url] = nil
  286.     self.visible = true
  287.   end
  288.   #--------------------------------------------------------------------------
  289.   # ● 拦截标准 set_text(显示技能/物品描述时走这里)
  290.   #--------------------------------------------------------------------------
  291.   alias_method :fgo_original_set_text, :set_text
  292.   def set_text(*args)
  293.     @fgo_showing_enemy = false
  294.     fgo_original_set_text(*args)   # 原封不动把所有参数传下去
  295.   end
  296.   #--------------------------------------------------------------------------
  297.   # ● 绘制 HP 条
  298.   #--------------------------------------------------------------------------
  299.   def carol3_draw_hp_bar(actor, x, y, width = 128)
  300.     # 显示值:默认用真实 HP;如果被 override 就按 override 画
  301.     hp_value = actor.hp
  302.     if @fgo_hp_override_enemy && @fgo_hp_override_enemy == actor
  303.       hp_value = @fgo_hp_override_value
  304.     end

  305.     self.contents.font.color = system_color
  306.     w = width * hp_value / [actor.maxhp, 1].max
  307.     if actor.maxhp != 0
  308.       rate = hp_value.to_f / actor.maxhp
  309.     else
  310.       rate = 0
  311.     end
  312.     color1 = Color.new(240 - 72 * rate, 240 * rate, 62 * rate, 150)
  313.     self.contents.fill_rect(x+1, y+15, width+2, 1, Color.new(0, 0, 0, 255))
  314.     self.contents.fill_rect(x+1, y+16, width+2, 1, Color.new(255, 255, 192, 192))
  315.     self.contents.fill_rect(x+1, y+17, w, 6, color1)
  316.     self.contents.fill_rect(x+1, y+23, width+2, 1, Color.new(255, 255, 192, 192))
  317.     self.contents.fill_rect(x+1, y+24, width+2, 1, Color.new(0, 0, 0, 255))
  318.     self.contents.fill_rect(x, y+16, 1, 8, Color.new(255, 255, 192, 192))
  319.     self.contents.fill_rect(x-1, y+15, 1, 10, Color.new(0, 0, 0, 255))
  320.     self.contents.fill_rect(x+129, y+16, 1, 8, Color.new(255, 255, 192, 192))
  321.     self.contents.fill_rect(x+130, y+15, 1, 10, Color.new(0, 0, 0, 255))
  322.     self.contents.draw_text(x-53, y, 128, 32, $data_system.words.hp, 1)
  323.     if hp_value > actor.maxhp / 3
  324.       self.contents.font.color = Color.new(255, 255, 255, 250)
  325.     end
  326.     if hp_value >= actor.maxhp / 6 and actor.maxhp / 3 > hp_value
  327.       self.contents.font.color = Color.new(200, 200, 0, 255)
  328.     end
  329.     if actor.maxhp / 6 > hp_value
  330.       self.contents.font.color = Color.new(200, 0, 0, 255)
  331.     end
  332.     self.contents.draw_text(x+47, y, 128, 32, hp_value.to_s, 1)
  333.   end
  334.   #--------------------------------------------------------------------------
  335.   # ● 绘制 SP 条
  336.   #--------------------------------------------------------------------------
  337.   def carol3_draw_sp_bar(actor, x, y, width = 128)
  338.     self.contents.font.color = system_color
  339.     if actor.maxsp != 0
  340.       rate = actor.sp.to_f / actor.maxsp
  341.     else
  342.       rate = 0
  343.     end
  344.     color2 = Color.new(62 * rate, 240 - 72 * rate, 240 * rate, 192)
  345.     w = width * actor.sp / [actor.maxsp,1].max
  346.     self.contents.fill_rect(x+1, y+15, width+2,1, Color.new(0, 0, 0, 255))
  347.     self.contents.fill_rect(x+1, y+16, width+2,1, Color.new(255, 255, 192, 192))
  348.     self.contents.fill_rect(x+1, y+17, w,6,color2)
  349.     self.contents.fill_rect(x+1, y+23, width+2,1, Color.new(255, 255, 192, 192))
  350.     self.contents.fill_rect(x+1, y+24, width+2,1, Color.new(0, 0, 0, 255))
  351.     self.contents.fill_rect(x, y+16, 1,8, Color.new(255, 255, 192, 192))
  352.     self.contents.fill_rect(x-1, y+15, 1,10, Color.new(0, 0, 0, 255))
  353.     self.contents.fill_rect(x+129, y+16, 1,8, Color.new(255, 255, 192, 192))
  354.     self.contents.fill_rect(x+130, y+15, 1,10, Color.new(0, 0, 0, 255))
  355.     self.contents.draw_text(x-53,y,128,32,$data_system.words.sp,1)
  356.     if actor.hp>actor.maxsp/3
  357.       self.contents.font.color = Color.new(255, 255, 255, 250)
  358.     end
  359.     if actor.hp>=actor.maxsp/6 and actor.maxsp/3>actor.sp
  360.       self.contents.font.color = Color.new(200, 200, 0, 255)
  361.     end
  362.     if actor.maxsp/6>actor.sp
  363.       self.contents.font.color = Color.new(200, 0, 0, 255)
  364.     end
  365.     self.contents.draw_text(x+47,y,128,32,actor.sp.to_s,1)
  366.   end

  367.   #--------------------------------------------------------------------------
  368.   # ● 战斗中自动刷新(只在“正在显示敌人”且数据变化时重绘)
  369.   #--------------------------------------------------------------------------
  370.   def refresh_enemy
  371.     return unless @fgo_showing_enemy   # 不在显示敌人时,什么都不做
  372.     return unless @fgo_enemy
  373.     e = @fgo_enemy
  374.     return unless e.respond_to?(:hp)
  375.     key = [e.hp, e.sp, (e.respond_to?(:hp_bars) ? e.hp_bars : 0)]
  376.     return if @fgo_last_key == key
  377.     @fgo_last_key = key
  378.     set_enemy(e)
  379.   end
  380. end

  381. class Scene_Battle
  382.   BREAK_WINDOW_HOLD = 40   # 击破动画结束后,窗口再显示多少帧(0=立即隐藏)

  383.   #--------------------------------------------------------------------------
  384.   # ● 一轮行动完全结束时,才允许处理击破队列
  385.   #--------------------------------------------------------------------------
  386.   alias_method :fgo_original_update_phase4_step1, :update_phase4_step1
  387.   def update_phase4_step1
  388.     # 队列里还有击破没播完 / 正在播 → 不重置标志,等全部播完再交给下一轮
  389.     queue_busy = ($fgo_break_queue && !$fgo_break_queue.empty?) ||
  390.                  @break_state == :playing || @break_state == :hold
  391.     @break_can_process = false unless queue_busy
  392.     fgo_original_update_phase4_step1
  393.   end
  394.   alias_method :fgo_original_update_phase4_step6, :update_phase4_step6
  395.   def update_phase4_step6
  396.     fgo_original_update_phase4_step6
  397.     @break_can_process = true
  398.   end
  399.   #--------------------------------------------------------------------------
  400.   # ● 检测战斗中是否还有技能/物品动画在播放
  401.   #--------------------------------------------------------------------------
  402.   def animation_playing?
  403.     return false unless @spriteset
  404.     es = @spriteset.instance_variable_get(:@enemy_sprites) || []
  405.     as = @spriteset.instance_variable_get(:@actor_sprites) || []
  406.     (es + as).any? { |s| s.respond_to?(:animation?) && s.animation? }
  407.   end
  408.   
  409.   
  410.   alias_method :fgo_multi_hp_update, :update
  411.   def update
  412.     update_break_cp_control

  413.     fgo_multi_hp_update

  414.     # 队列里有内容 → 本帧刚发生击破,先跳过刷新,等 override 生效
  415.     queue_pending = $fgo_break_queue && !$fgo_break_queue.empty?

  416.     if @help_window && @help_window.respond_to?(:refresh_enemy) &&
  417.        !@break_freeze_help && !queue_pending
  418.       @help_window.refresh_enemy
  419.     end

  420.     update_break_icons
  421.     update_break_window_hide

  422.     update_break_cp_control

  423.     if @help_window && @break_hide_timer && @break_hide_timer > 0
  424.       @help_window.visible = true
  425.     end
  426.   end

  427.   
  428.   #--------------------------------------------------------------------------
  429.   # ● 击破动画播放期间,暂停战斗流程(phase4 不推进)
  430.   #--------------------------------------------------------------------------
  431.   alias_method :fgo_original_update_phase4, :update_phase4
  432.   def update_phase4
  433.     # 只判断「正在播 / 刚播完保持中」;队列非空不算 busy,
  434.     # 让 phase4 走完当前轮,step6 里设 @break_can_process = true
  435.     busy = @break_state || (@break_hide_timer && @break_hide_timer > 0)
  436.     return if busy
  437.     fgo_original_update_phase4
  438.   end
  439.   #--------------------------------------------------------------------------
  440.   # ● 击破动画期间暂停 CP 走条,结束后恢复原状态
  441.   #    注意:XRXS_BP 的 Scene_Battle_CP#stop 是会 join 线程的方法,
  442.   #    不能用 @cp_thread.stop 去读/写,只能直接操作内部变量 @stop
  443.   #--------------------------------------------------------------------------
  444.   def update_break_cp_control
  445.     return unless @cp_thread

  446.     if @break_state == :playing ||
  447.        @break_state == :recover ||
  448.        (@break_hide_timer && @break_hide_timer > 0)
  449.       unless @break_cp_stopped
  450.         # 记录进入时的原状态,避免和 XRXS_BP 自己的暂停冲突
  451.         @break_cp_prev_stop = @cp_thread.instance_variable_get(:@stop)
  452.         @break_cp_stopped   = true
  453.       end
  454.       @cp_thread.instance_variable_set(:@stop, true)
  455.     elsif @break_cp_stopped
  456.       @cp_thread.instance_variable_set(:@stop, @break_cp_prev_stop)
  457.       @break_cp_stopped = false
  458.     end
  459.   end

  460.   #--------------------------------------------------------------------------
  461.   # ● 击破动画结束后:保持窗口显示一段时间,然后隐藏
  462.   #--------------------------------------------------------------------------
  463.   def update_break_window_hide
  464.     return unless @break_hide_timer && @break_hide_timer > 0
  465.     @break_hide_timer -= 1
  466.     if @break_hide_timer <= 0
  467.       @break_hide_timer = nil
  468.       @break_state     = nil
  469.       # 队列里还有没播的击破 → 不隐藏,接着播下一个
  470.       if $fgo_break_queue && !$fgo_break_queue.empty?
  471.         return
  472.       end
  473.       @help_window.visible = false if @help_window
  474.       @break_icons.each { |s| s.visible = false } if @break_icons
  475.     end
  476.   end

  477.   #--------------------------------------------------------------------------
  478.   # ● 击破图标:播放中 / 常驻显示
  479.   #--------------------------------------------------------------------------
  480.   def update_break_icons
  481.     @break_icons ||= []
  482.     @break_anim  ||= {}
  483.     $fgo_break_queue ||= []

  484.     #开始一个新的击破动画
  485.     if @break_state.nil? && !$fgo_break_queue.empty? && @break_can_process
  486.       # 排序:先按敌人位置(1号位→2号位→3号位…),同位置按 remain 降序(先被击破的先播)
  487.       $fgo_break_queue.sort! { |a, b|
  488.         pa = a[:enemy].fgo_position.to_i
  489.         pb = b[:enemy].fgo_position.to_i
  490.         if pa == pb
  491.           b[:remain] <=> a[:remain]
  492.         else
  493.           pa <=> pb
  494.         end
  495.       }
  496.       item      = $fgo_break_queue.shift
  497.       enemy     = item[:enemy]
  498.       anim_idx  = item[:remain]      # ← 这次击破要闪的图标索引(固定值)

  499.       @break_target      = enemy
  500.       @break_remain      = item[:remain]   # ← 固定住这次击破后的剩余数
  501.       @break_state       = :playing
  502.       @break_freeze_help = true

  503.       if @help_window
  504.         @help_window.set_enemy(enemy)
  505.         @help_window.visible = true
  506.       end

  507.       @break_icons.each { |s| s.visible = false; s.tone = Tone.new(0,0,0,0) }
  508.       @break_anim.clear

  509.       total = enemy.max_hp_bars - 1
  510.       while @break_icons.size < total
  511.         spr = Sprite.new
  512.         begin
  513.           spr.bitmap = Bitmap.new("Graphics/Pictures/生命击破")
  514.         rescue
  515.           spr.dispose
  516.           return
  517.         end
  518.         spr.z = 9999
  519.         spr.visible = false
  520.         @break_icons << spr
  521.       end

  522.       if anim_idx >= 0 && @break_icons[anim_idx]
  523.         @break_icons[anim_idx].visible = true
  524.         @break_icons[anim_idx].tone = Tone.new(255, 0, 0, 0)
  525.         @break_anim[anim_idx] = { :phase => 0, :timer => 0 }
  526.       end
  527.     end

  528.     # 击破动画播放中 → 窗口显示 0 血
  529.     # 全部播完后 → 从 0 逐渐回复到满
  530.     if @help_window && @help_window.respond_to?(:set_hp_override)
  531.       case @break_state
  532.       when :playing
  533.         @help_window.set_hp_override(@break_target, 0)
  534.       when :hold
  535.         if @break_keep_zero
  536.           @help_window.set_hp_override(@break_target, 0)
  537.         else
  538.           @help_window.set_hp_override(nil, nil)
  539.         end
  540.       when :recover
  541.         @help_window.set_hp_override(@break_target, @break_recover_hp)
  542.       else
  543.         @help_window.set_hp_override(nil, nil)
  544.       end
  545.     end
  546.    
  547.     # 动画中强制窗口可见
  548.     if @break_state == :playing && @help_window
  549.       @help_window.visible = true
  550.     end

  551.     # ============================================================
  552.     # 分支 A:不在播放 → 常驻显示(跟随帮助窗口当前显示的敌人)
  553.     # ============================================================
  554.     if @break_state.nil?
  555.       # 帮助窗口没在显示敌人(选技能/物品/按 Esc)→ 全部隐藏
  556.       unless @help_window &&
  557.              @help_window.visible &&
  558.              @help_window.respond_to?(:fgo_showing_enemy?) &&
  559.              @help_window.fgo_showing_enemy?
  560.         @break_icons.each { |s| s.visible = false }
  561.         return
  562.       end

  563.       enemy = @help_window.fgo_enemy
  564.       unless enemy && enemy.respond_to?(:max_hp_bars) && enemy.max_hp_bars > 1
  565.         @break_icons.each { |s| s.visible = false }
  566.         return
  567.       end

  568.       total  = enemy.max_hp_bars - 1
  569.       remain = enemy.hp_bars - 1

  570.       while @break_icons.size < total
  571.         spr = Sprite.new
  572.         begin
  573.           spr.bitmap = Bitmap.new("Graphics/Pictures/生命击破")
  574.         rescue
  575.           spr.dispose
  576.           return
  577.         end
  578.         spr.z = 9999
  579.         spr.visible = false
  580.         @break_icons << spr
  581.       end

  582.       base_x = 0
  583.       base_y = 65
  584.       gap    = 2

  585.       @break_icons.each_with_index do |spr, i|
  586.         if i < remain
  587.           spr.visible = true
  588.           spr.tone = Tone.new(0, 0, 0, 0)
  589.           spr.x = base_x + i * (spr.bitmap.width + gap)
  590.           spr.y = base_y
  591.         else
  592.           spr.visible = false
  593.         end
  594.       end
  595.       return
  596.     end

  597.     # ============================================================
  598.     # 分支 B:播放动画中
  599.     # ============================================================
  600.     enemy  = @break_target
  601.     total  = enemy.max_hp_bars - 1
  602.     remain = @break_remain     # ← 用这次击破时固定下来的值

  603.     base_x = 0
  604.     base_y = 65
  605.     gap    = 2

  606.     @break_icons.each_with_index do |spr, i|
  607.       anim = @break_anim[i]

  608.       if anim
  609.         spr.visible = true
  610.         anim[:timer] += 1
  611.         if anim[:timer] >= 10
  612.           anim[:timer] = 0
  613.           anim[:phase] += 1
  614.           case anim[:phase]
  615.           when 1, 3, 5
  616.             spr.tone = Tone.new(0, 0, 0, 0)       # 暗
  617.           when 2, 4
  618.             spr.tone = Tone.new(255, 0, 0, 0)     # 红
  619.           when 6
  620.             Audio.se_play("Audio/SE/玻璃碎-L", 80, 100)
  621.             spr.tone = Tone.new(0, 0, 0, 0)
  622.             spr.visible = false
  623.             @break_anim.delete(i)
  624.           end
  625.         end
  626.       elsif i < remain
  627.         spr.visible = true
  628.         spr.tone = Tone.new(0, 0, 0, 0)
  629.       else
  630.         spr.visible = false
  631.       end

  632.       if spr.visible
  633.         spr.x = base_x + i * (spr.bitmap.width + gap)
  634.         spr.y = base_y
  635.       end
  636.     end
  637.     # 动画结束 → 一律进入 recover,让当前敌人 HP 从 0 涨满
  638.     if @break_state == :playing && @break_anim.empty?
  639.       @break_state        = :recover
  640.       @break_freeze_help  = false
  641.       @break_keep_zero    = false
  642.       @break_recover_hp   = 0
  643.       @break_recover_step = [(@break_target.maxhp / 30.0).ceil, 1].max
  644.       Audio.se_play("Audio/SE/紫技回3", 80, 100)   # ← 新增:回血前播一次
  645.       if @help_window
  646.         @help_window.visible = true
  647.         @help_window.fgo_force_refresh if @help_window.respond_to?(:fgo_force_refresh)
  648.         @help_window.refresh_enemy    if @help_window.respond_to?(:refresh_enemy)
  649.       end
  650.     end

  651.     # recover 阶段:每帧把 HP 往上加
  652.     if @break_state == :recover && @break_target
  653.       @break_recover_hp += @break_recover_step
  654.       if @break_recover_hp >= @break_target.maxhp
  655.         @break_recover_hp = @break_target.maxhp
  656.         if $fgo_break_queue && !$fgo_break_queue.empty?
  657.           # 队列还有下一个敌人 → 短暂 hold 后立即处理
  658.           @break_state      = :hold
  659.           @break_keep_zero  = false
  660.           @break_hide_timer = BREAK_WINDOW_HOLD
  661.         else
  662.           # 全部播完 → 进入最终 hold,窗口保持一段时间再隐藏
  663.           @break_state      = :hold
  664.           @break_keep_zero  = false
  665.           @break_hide_timer = BREAK_WINDOW_HOLD
  666.         end
  667.       end
  668.     end
  669.     # 队列和动画都清空后,复位标志,等下个 step6 再开启
  670.     if $fgo_break_queue.empty? && @break_state.nil? && @break_anim.empty?
  671.       @break_can_process = false
  672.     end
  673.   end
  674. end

  675. class Game_Troop
  676.   alias_method :fgo_multi_hp_setup, :setup
  677.   def setup(troop_id)
  678.     fgo_multi_hp_setup(troop_id)
  679.     # 此时 @troop_id 和 @enemies 都已就绪
  680.     @enemies.each_with_index do |enemy, i|
  681.       enemy.setup_multi_hp(troop_id, i + 1)
  682.     end
  683.   end
  684. end
  685. #==============================================================================
  686. # 本脚本来自www.66RPG.com,使用和转载请保留此信息
  687. #==============================================================================
复制代码


击破回复.rar

588.54 KB, 下载次数: 0

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

本版积分规则

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

在本版发帖返回顶部