扫描二维码关注官方公众号
返回列表
+ 发新帖
查看: 107|回复: 0

[转载发布] “公共事件的战斗特效”完美版(附20个范例)

[复制链接]
累计送礼:
0 个
累计收礼:
0 个
  • TA的每日心情
    开心
    昨天 18:01
  • 签到天数: 114 天

    连续签到: 4 天

    [LV.6]常住居民II

    2338

    主题

    403

    回帖

    1万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    6
    卡币
    10622
    OK点
    16
    推广点
    0
    同能卷
    0
    积分
    13391

    灌水之王

    发表于 2024-4-19 16:14:09 | 显示全部楼层 |阅读模式
    最后更新:2006-9-26
    范例工程:http://rpg.blue/upload_program/files/Project7.zip

    距“公共事件的战斗特效”上个版本放出有一年了,直到现在我仍然认为这个是最灵活,可扩展性最强的战斗特效系统。无他,利用公共事件可以避免和很多脚本的冲突。
    然而,每次调用战斗特效都要还原HP很麻烦,而且还原HP有时不是能完全恢复原样的。要真的让公共事件达到想怎么用就怎么用的程度,只能从改变RGSS的执行顺序上作文章。
    这次修改,我最后达到的状况是:
    ·对所有RGSS的修改,仅限于Scene_Battle类,且改动很少,对诸如Game_Battler类等绝无一丝改动。
    ·在保证Phase4完整顺序的前提下,更改其内部执行顺序,100%完美化视觉效果,并简化公共事件中的脚本书写复杂度。
    ·纯插件制作,可以插入默认的战斗系统或CP制战斗系统。但是RTAB不适用。

    理论:
    考查Scene_Battle中Phase4的执行顺序:
    Step1:开始
    Step2:应用行动效果
    Step3:行动方动画
    Step4:对象方动画
    Step5:伤害处理
    Step6:刷新
    以前的公共事件战斗特效要还原HP,是因为HP已经在Step2发生了改动(技能被实际应用了),自然想到
    如果不让技能在那么早就被应用,不是可以省去一堆麻烦事了?
    那么就来想想技能应用最晚可以放在哪里——
    Step3是行动方动画,技能成功与否,对行动方的动画是没有影响的。
    Step4是对象方动画,这里需要调用到技能行动的结果——是否命中,所以无论如何,对象方动画肯定只能在技能应用的后面
    也就是说技能最晚可以是在Step3和Step4之间才应用。
    那么只要将make_skill_action_result中的相关项移到该位置,并外包条件判断以免影响不相干的动作,即可。
    即然技能应用放在这里了,而之前技能的公共事件ID已经被调用,我们当然可以用公共事件ID来做判断:
    有公共事件——直接调用公共事件
    无公共事件——通常应用技能效果
    这就意味着有些利用了通常技能效果(改其他东西)的特效,其应用步骤要放在公共事件里。这样对公共事件中的执行顺序提出了要求。好在这并不是太大的问题。
    强烈推荐将所有技能调用的公共事件放在同一个事件里的方法,用条件分歧框住每一个特殊效果。
    另外,这个插件把状态窗口每执行一条事件指令就刷新的功能禁止了,默认情况下是每执行完一个事件才刷新,为了避免刷新不畅的问题,定义了$scene.status_refresh方法,可以在公共事件中手工刷新。

    实践:
    将以下脚本插入到Main的前面。然后看公共事件的脚本书写方法。
    class Scene_Battle
      attr_reader   :active_battler
      attr_reader   :skill
      attr_accessor :target_battlers
      attr_accessor :animation2_id
      #--------------------------------------------------------------------------
      # ● 刷新画面
      #--------------------------------------------------------------------------
      def update
        # 执行战斗事件中的情况下
        if $game_system.battle_interpreter.running?
          # 刷新解释器
          $game_system.battle_interpreter.update
          # 强制行动的战斗者不存在的情况下
          if $game_temp.forcing_battler == nil
            # 执行战斗事件结束的情况下
            unless $game_system.battle_interpreter.running?
              # 继续战斗的情况下、再执行战斗事件的设置
              if @common_event_id == 0
                unless judge
                  setup_battle_event
                end
              end
            end
            # 如果不是结束战斗回合的情况下
            if @phase != 5 and @common_event_id == 0
              # 刷新状态窗口
              @status_window.refresh
            end
          end
        end
        # 系统 (计时器)、刷新画面
        $game_system.update
        $game_screen.update
        # 计时器为 0 的情况下
        if $game_system.timer_working and $game_system.timer == 0
          # 中断战斗
          $game_temp.battle_abort = true
        end
        # 刷新窗口
        @help_window.update
        @party_command_window.update
        @actor_command_window.update
        @status_window.update
        @message_window.update
        # 刷新活动块
        @spriteset.update
        # 处理过渡中的情况下
        if $game_temp.transition_processing
          # 清除处理过渡中标志
          $game_temp.transition_processing = false
          # 执行过渡
          if $game_temp.transition_name == ""
            Graphics.transition(20)
          else
            Graphics.transition(40, "Graphics/Transitions/" +
              $game_temp.transition_name)
          end
        end
        # 显示信息窗口中的情况下
        if $game_temp.message_window_showing
          return
        end
        # 显示效果中的情况下
        if @spriteset.effect?
          return
        end
        # 游戏结束的情况下
        if $game_temp.gameover
          # 切换到游戏结束画面
          $scene = Scene_Gameover.new
          return
        end
        # 返回标题画面的情况下
        if $game_temp.to_title
          # 切换到标题画面
          $scene = Scene_Title.new
          return
        end
        # 中断战斗的情况下
        if $game_temp.battle_abort
          # 还原为战斗前的 BGM
          $game_system.bgm_play($game_temp.map_bgm)
          # 战斗结束
          battle_end(1)
          return
        end
        # 等待中的情况下
        if @wait_count > 0
          # 减少等待计数
          @wait_count -= 1
          return
        end
        # 强制行动的角色存在、
        # 并且战斗事件正在执行的情况下
        if $game_temp.forcing_battler == nil and
           $game_system.battle_interpreter.running?
          return
        end
        # 回合分支
        case @phase
        when 1  # 自由战斗回合
          update_phase1
        when 2  # 同伴命令回合
          update_phase2
        when 3  # 角色命令回合
          update_phase3
        when 4  # 主回合
          update_phase4
        when 5  # 战斗结束回合
          update_phase5
        end
      end
      #--------------------------------------------------------------------------
      # ● 生成特技行动结果
      #--------------------------------------------------------------------------
      def make_skill_action_result
        # 获取特技
        @skill = $data_skills[@active_battler.current_action.skill_id]
        # 如果不是强制行动
        unless @active_battler.current_action.forcing
          # 因为 SP 耗尽而无法使用的情况下
          unless @active_battler.skill_can_use?(@skill.id)
            # 清除强制行动对像的战斗者
            $game_temp.forcing_battler = nil
            # 移至步骤 1
            @phase4_step = 1
            return
          end
        end
        # 在帮助窗口显示特技名
        @help_window.set_text(@skill.name, 1)
        # 设置动画 ID
        @animation1_id = @skill.animation1_id
        @animation2_id = @skill.animation2_id
        # 设置公共事件 ID
        @common_event_id = @skill.common_event_id
        # 设置对像侧战斗者
        set_target_battlers(@skill.scope)
      end
      #--------------------------------------------------------------------------
      # ● 一般特技效果应用(公共事件用)
      #--------------------------------------------------------------------------
      def normal_skill_effect
        # 应用特技效果
        for target in @target_battlers
          target.skill_effect(@active_battler, @skill)
        end
      end
      #--------------------------------------------------------------------------
      # ● 特技的状态变化应用(公共事件用)
      #--------------------------------------------------------------------------
      def state_apply
        # 应用状态变化
        for target in @target_battlers
          target.states_plus(@skill.plus_state_set)
          target.states_minus(@skill.minus_state_set)
        end
      end
      #--------------------------------------------------------------------------
      # ● 状态窗口刷新(公共事件用)
      #--------------------------------------------------------------------------
      def status_refresh
        # 刷新状态窗口
        @status_window.refresh
      end
      #--------------------------------------------------------------------------
      # ● 刷新画面 (主回合步骤 4 : 对像方动画)
      #--------------------------------------------------------------------------
      def update_phase4_step4
        # 公共事件 ID 有效的情况下
        if @common_event_id > 0
          # 设置事件
          common_event = $data_common_events[@common_event_id]
          $game_system.battle_interpreter.setup(common_event.list, 0)
          @common_event_id = -1
          return
        # 公共事件 ID 无效的情况下
        elsif @common_event_id == 0
          # 一般特技效果应用
          if @active_battler.current_action.kind == 1
            @active_battler.sp -= @skill.sp_cost
            normal_skill_effect
          end
        end
        # 对像方动画
        for target in @target_battlers
          target.animation_id = @animation2_id
          target.animation_hit = (target.damage != "Miss")
        end
        # 限制动画长度、最低 8 帧
        @wait_count = 8
        # 移至步骤 5
        @phase4_step = 5
      end
      #--------------------------------------------------------------------------
      # ● 刷新画面 (主回合步骤 5 : 显示伤害)
      #--------------------------------------------------------------------------
      def update_phase4_step5
        # 隐藏帮助窗口
        @help_window.visible = false
        # 刷新状态窗口
        @status_window.refresh
        # 显示伤害
        for target in @target_battlers
          if target.damage != nil
            target.damage_pop = true
          end
        end
        if @active_battler.damage != nil
          @active_battler.damage_pop = true
        end
        # 移至步骤 6
        @phase4_step = 6
      end
      #--------------------------------------------------------------------------
      # ● 刷新画面 (主回合步骤 6 : 刷新)
      #--------------------------------------------------------------------------
      def update_phase4_step6
        # 清除强制行动对像的战斗者
        $game_temp.forcing_battler = nil
        # 移至步骤 1
        @phase4_step = 1
      end
    end

    公共事件脚本书写需知:

    关于“前趋”“SP覆写”“覆写”和“后继”的说明:

    前趋处理:这些脚本(含外包的条件分歧)总是放在公共事件靠前的位置,它们在技能没有实际起作用时就被改写,通常是改变攻击对象的效果。

    后继处理:这些脚本(含外包的条件分歧)总是放在公共事件靠后的位置,它们在技能生效后追加一些效果,通常是一些特殊的效果,比如追加伤害,强制会心一击,HP吸收等。

    由于战斗特效操作对象的不同,以及一些相关共性,我们在公共事件中插入三条通用脚本:

    脚本1:$scene.active_battler.sp-=\
           $scene.skill.sp_cost
    脚本2:$scene.status_refresh
    脚本3:$scene.normal_skill_effect

    细心的读者会发现,这三条脚本执行的就是在RGSS中,当技能不附带公共事件时所执行的东西,只不过这里换了个写法而已。

    这三个脚本不能放在任何条件分歧里,作为默认应用技能的步骤,脚本2的前后各跟一个标签事件
    实际写法如下:

    (所有的前趋脚本)
    脚本:$scene.active_battler.sp-=\
          $scene.skill.sp_cost
    标签:SP消耗结束
    脚本:$scene.status_refresh
    脚本:$scene.normal_skill_effect
    标签:伤害计算结束
    (所有的后继脚本)

    凡是不按照常规方法消耗SP,但是伤害计算通式的技能效果脚本(比如消耗HP代替SP,或特定状态下半减SP消耗),计为“覆写SP”,应当插入在脚本1的前面(在前趋脚本之后),其后跟标签跳转事件,跳转到“SP消耗结束”处

    凡是不按照常规公式计算伤害值的技能效果脚本(比如比例伤害),应当插入在脚本2与脚本3之间,其后跟标签跳转事件,跳转到“伤害计算结束”处。

    若有既不常规消耗SP,也不常规计算伤害的效果脚本,则插入到脚本1之前,但是标签跳转到脚本2以后,但请注意手工刷新状态窗口。也可以拆成两个脚本按上面的方法处理。

    举例如下:
    [前趋脚本]
    条件分歧:........
      脚本:....(特殊方法SP消耗的脚本)
      标签跳转:SP消耗结束
    分歧结束
    脚本:$scene.active_battler.sp-=\
          $scene.skill.sp_cost
    标签:SP消耗结束
    条件分歧:........
      脚本:....(特殊计算伤害值的脚本)
      标签跳转:伤害计算结束
    分歧结束
    脚本:$scene.normal_skill_effect
    标签:伤害计算结束
    [后继脚本]

    公共事件特效范例:

    一、全体化/全域化
    效果:当技能范围为敌单体时,攻击敌全体;
    当技能范围为我方单体或自身时,攻击我方全体;
    当技能范围为我方单体HP0时,攻击我方全体HP0;
    当技能范围为无时,攻击战场上所有对象。
    处理:前趋
    脚本:
    s=$scene.skill.scope
    $scene.target_battlers=[]
    $scene.set_target_battlers(2) if s==1
    $scene.set_target_battlers(4) if s%4==3
    $scene.set_target_battlers(6) if s==5
    (t=$game_troop.enemies+$game_party.actors
    for battler in t.clone
      t.delete(battler) if not battler.exist?
    end
    $scene.target_battlers=t) if s==0

    二、敌/己/全方随机对象
    效果:当技能范围为敌单或敌全时,随机选定敌方单体;
    当技能范围为我单或我全时,随机选定我方单体;
    当技能范围为我单或我全HP0时,随机选定我方单体HP0;
    当技能范围为无时,随机选定战场上一个对象;
    当技能范围为自身时,不作处理。
    处理:前趋
    条件分歧:$scene.active_battler.is_a?(Game_Enemy)
      脚本:
      s=($scene.skill.scope+1)/2
      t=$game_party.random_target_actor if s==1
      t=$game_troop.random_target_enemy if s==2
      t=$game_troop.random_target_enemy(true) if s==3
      (x=$game_party.actors+$game_troop.enemies
      t=x[rand(x.size)]) if s==0
      $scene.target_battlers=[t]
    除此以外的情况下
      脚本:
      s=($scene.skill.scope+1)/2
      t=$game_troop.random_target_enemy if s==1
      t=$game_party.random_target_actor if s==2
      t=$game_party.random_target_actor(true) if s==3
      (x=$game_troop.enemies+$game_party.actors
      t=x[rand(x.size)]) if s==0
      $scene.target_battlers=[t]
    分歧结束

    三、HP吸收
    效果:攻击者增加等同于伤害值的HP
    处理:后继
    脚本:
    a=$scene.active_battler
    a.damage=0
    for t in $scene.target_battlers
      if t.damage.is_a?(Numeric)
        a.damage -= t.damage
        a.hp += t.damage
      end
    end

    四、SP伤害
    效果:本来伤害对方HP,改成伤害对方SP
    处理:覆写
    脚本:
    a=$scene.active_battler
    s=$scene.skill
    for t in $scene.target_battlers
      t1=t.clone.skill_effect(a,s)
      if t1.damage.is_a?(Numeric)
        t.damage=t1.damage
        t.sp-=t.damage
      end
    end
    $scene.state_apply

    五、SP吸收
    效果:攻击者增加等同于伤害值的SP。
    处理:后继
    脚本:
    a=$scene.active_battler
    a.damage=0
    for t in $scene.target_battlers
      if t.damage.is_a?(Numeric)
        a.damage -= t.damage
        a.sp += t.damage
      end
    end

    六、SP同等伤害
    效果:攻击对象损失等同于HP损失的SP。
    处理:后继
    脚本:
    for t in $scene.target_battlers
      t.sp-=t.damage if t.damage.is_a?(Numeric)
    end

    七、反馈
    效果:攻击对象损失所有的SP,并损失相当于其SP损失量的HP(参考Starcraft的Feedback)。
    处理:覆写
    脚本:
    s=$scene.skill
    for t in $scene.target_battlers
      t.damage=t.sp
      t.sp=0
      t.hp-=t.damage
    end
    $scene.state_apply

    八、消耗HP发动
    效果:本来是消耗SP发动的技能变成消耗HP发动,如果HP不足则发动后死亡。
    处理:SP覆写
    脚本:
    s=$scene.skill
    $scene.active_battler.hp-=s.sp_cost


    九、SP节约
    效果:中了特定状态(例为22)发动技能只消耗常规一半的SP,中了另一状态(23)则无差别消耗1点SP。
    处理:SP覆写
    脚本:
    s=$scene.skill
    a=$scene.active_battler
    if a.state?(22)
      a.sp-=s.sp_cost/2
    elsif a.state?(23)
      a.sp-=[s.sp_cost,1].min
    end

    十、现有HP比例伤害
    效果:按照技能的威力设置,和攻击对象的HP,计算损害百分比的HP,属性和防御修正有效。
    处理:覆写
    脚本:
    s=$scene.skill
    for t in $scene.target_battlers
      e=t.element_correct(s.element_set)
      t.damage=t.hp*s.power*e/10000
      t.damage/=2 if t.guarding?
      t.hp-=t.damage
    end
    $scene.state_apply

    十一、现有HP差分比例伤害
    效果:按照技能的威力设置,和攻击对象的HP与其最大HP的差值,计算损害百分比的HP,属性和防御修正无效。
    处理:覆写
    脚本:
    s=$scene.skill
    for t in $scene.target_battlers
      t.damage=(t.maxhp-t.hp)*s.power/100
      t.hp-=t.damage
    end
    $scene.state_apply

    十二、最大HP比例伤害
    效果:按照技能的威力设置,和攻击对象的最大HP,计算损害百分比的HP,属性有效,无视防御修正。
    处理:覆写
    脚本:
    s=$scene.skill
    for t in $scene.target_battlers
      e=t.element_correct(s.element_set)
      t.damage=t.maxhp*s.power*e/10000
      t.hp-=t.damage
    end
    $scene.state_apply

    十三、自身HP比例伤害
    效果:按照技能的威力设置,和攻击者的HP,计算损害百分比的HP,属性和防御修正有效。
    处理:覆写
    脚本:
    s=$scene.skill
    a=$scene.active_battler
    for t in $scene.target_battlers
      e=t.element_correct(s.element_set)
      t.damage=a.hp*s.power*e/10000
      t.damage/=2 if t.guarding?
      t.hp-=t.damage
    end
    $scene.state_apply

    十四、自身HP差分比例伤害
    效果:按照技能的威力设置,和攻击者的HP与其最大HP的差值,计算损害百分比的HP,属性有效,无视防御修正。
    处理:覆写
    脚本:
    s=$scene.skill
    a=$scene.active_battler
    for t in $scene.target_battlers
      e=t.element_correct(s.element_set)
      t.damage=(a.maxhp-a.hp)*s.power*e/10000
      t.hp-=t.damage
    end
    $scene.state_apply

    十五、自身最大HP比例伤害
    效果:按照技能的威力设置,和攻击者的最大HP,计算损害百分比的HP,属性和防御修正无效。
    处理:覆写
    脚本:
    s=$scene.skill
    a=$scene.active_battler
    for t in $scene.target_battlers
      t.damage=a.maxhp*s.power/100
      t.hp-=t.damage
    end
    $scene.state_apply

    十六、舍命一击
    效果:攻击者攻击后死亡。
    处理:后继
    脚本:
    $scene.active_battler.hp=0
    $scene.active_battler.damage=""

    十七、强制会心一击
    效果:强制造成会心一击(伤害值2倍)。
    处理:后继
    脚本:
    for t in $scene.target_battlers
      if t.damage.is_a?(Numeric)
        t.hp-=t.damage
        t.damage*=2
      end
    end

    十八、技能反射
    效果:攻击对象有特定状态(24)时,技能被反射到另外一方的随机对象。
    处理:前趋+后继
    脚本(前趋):
    x=$scene.target_battlers
    x1=x.clone
    for t in x1
      if t.state?(24)
        x.delete(t)
        c=(t.is_a?(Game_Actor) ?
          $game_troop.random_target_enemy :
          $game_party.random_target_actor)
        x.push(c)
      end
    end
    @d=x.clone
    脚本(后继):
    for i in [email protected]
      t=$scene.target_battlers
      t1=@d
      t.damage=t1.hp-t.hp
    end

    十九、复活对不死系反效果(即死)
    效果:用复活类技能攻击对象为不死系(属性9)时,造成敌人无条件即死。
    处理:覆写
    脚本:
    a=$scene.active_battler
    s=$scene.skill
    for t in $scene.target_battlers
      if t.element_rate(9)>=150
        t.add_state(1)
      else
        t.skill_effect(a,s)
      end
    end

    二十、即死对不死系反效果(完全回复)
    效果:用即死类技能攻击对象为不死系时,造成敌人完全回复。
    处理:覆写
    脚本:
    a=$scene.active_battler
    s=$scene.skill
    for t in $scene.target_battlers
      if t.element_rate(9)>=150
        t.recover_all
      else
        t.skill_effect(a,s)
      end
    end

                 本帖来自P1论坛作者九泪,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=31747  若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2025-3-15 00:05 , Processed in 0.141102 second(s), 53 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

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