Project1

标题: “公共事件的战斗特效”完美版(附20个范例) [打印本页]

作者: SailCat    时间: 2006-9-27 06:41
标题: “公共事件的战斗特效”完美版(附20个范例)
最后更新: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

作者: SailCat    时间: 2006-9-27 06:41
标题: “公共事件的战斗特效”完美版(附20个范例)
本帖最后由 后知后觉 于 2009-12-13 17:42 编辑

重复内容
作者: SailCat    时间: 2006-9-27 07:06
范例工程中包含一个“十字斩”特效,其使用的脚本:
1.全体、全域化
2.消耗HP发动
3.自身最大HP比例伤害
4.HP吸收

分别放在了公共事件中对应的位置
实际应用中
大家也可以把成段的脚本写成独立的公共事件,若有多个技能需要该效果时,直接调用该公共事件即可,无需复制脚本。

作者: 九泪    时间: 2006-9-27 08:15
{/qiang}{/qiang}{/qiang}

抓住sailcat大姐.恩,问好~

要么不出现,一出现就是大手笔....惭愧中{/hx}
作者: 风雪优游    时间: 2006-9-27 20:23
谢谢了~~~收下,好好研究~~~~
作者: ikki    时间: 2006-9-27 21:46
{/fd}不知道这个好不好用,先试试。
作者: zhong    时间: 2006-9-28 02:25
有没有"金钱投掷"投掷范例,上面好现没有吧,可以象这个http://rpg.blue/web/htm/news19.htm那样设吗???这个是完美版的,我希望用他来实现投掷金钱的效果!!!!
作者: 柳柳    时间: 2006-9-28 02:27
金钱投掷还需要脚本么?{/fd}
减少金钱就行了啊
作者: coolsila    时间: 2006-9-28 18:08
呵呵,其实很多东西都不需要用到脚本的,不一定非脚本不可吧。这样很容易把简单的东西复杂化,我就基本很少用脚本。
作者: zhong    时间: 2006-9-30 04:22
金钱投掷还需要脚本么?
但是公共事件默认是放在招式执行之后啊,所以判断金钱和减少金钱都放在招式后面吧,我记得http://rpg.blue/web/htm/news19.htm这个也就是以前的版本就有投掷金钱的范例,现在脚本改进了,使用应该有改一点吧,所以问一下怎么用!!!!!!{/jy}
作者: 柳柳    时间: 2006-9-30 08:25
仔细看这个教学前面的文字部分,猫子已经写在里面了。
我就不提示了。{/wx}
作者: ⑩字绯影    时间: 2006-9-30 17:30
顶一下,有技术含量的帖子
作者: 嫁衣    时间: 2006-9-30 21:53
LZ强。。。收范例走人{/se}
作者: 柳柳    时间: 2006-10-27 09:41
发布完毕……(1个月了……)
VIP += 10




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1