赞 | 342 |
VIP | 10 |
好人卡 | 8 |
积分 | 262 |
经验 | 235776 |
最后登录 | 2024-9-23 |
在线时间 | 2387 小时 |
Lv5.捕梦者 (版主) 遠航の猫咪
- 梦石
- 3
- 星屑
- 23186
- 在线时间
- 2387 小时
- 注册时间
- 2005-10-15
- 帖子
- 1166
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
最后更新: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
|
|