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

Project1

 找回密码
 注册会员
搜索
Project1 查看内容

“公共事件的战斗特效”完美版(附范例)

2006-10-27 00:00| 发布者: 柳柳| 查看: 11470| 评论: 0|原作者: SailCat

摘要:   作者 SailCat 版本 2006-10 相关网址 范例工程 点击下载 教程内容 距“公共事件的战斗特效”上个版本放出有一年了,直到现在我仍然认为这个是最灵活,可扩展性最强的战
 

作者

SailCat

版本

2006-10

相关网址

范例工程

点击下载



教程内容

距“公共事件的战斗特效”上个版本放出有一年了,直到现在我仍然认为这个是最灵活,可扩展性最强的战斗特效系统。无他,利用公共事件可以避免和很多脚本的冲突。
然而,每次调用战斗特效都要还原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[i]
 t1=@d[i]
 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

 


 

教程的通用说明

本站发布的教程,大多经过一些测试,应该都能够实现相应功能。但不保证所有的教程都是最优化的制作方法。

相关问题,点击发布贴进行讨论。谢谢您的鼓励与支持。

4

鲜花

刚表态过的朋友 (4 人)

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

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

GMT+8, 2024-11-21 20:16

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

返回顶部