Project1
标题: 默认战斗中调用公共事件 [打印本页]
作者: guoxiaomi 时间: 2017-3-7 21:33
标题: 默认战斗中调用公共事件
本帖最后由 guoxiaomi 于 2017-3-12 21:38 编辑
范例在 2 楼
仅对默认战斗有效。但是思路是可以拓展到其他的战斗里。我以为 1 个小时就能写完的……结果搞了快 3 个小时。。。
1 楼是行动前后调用公共事件
战斗前后调用在 7 楼
回合开始时调用公共事件在 8 楼
至此,给出了 5 个常见的需要调用公共事件的 “时间点”,可以对默认战斗进行方便又强力的改动。
修改在 Scene_Battle 4 的 71 行的 update_phase4 方法:
class Scene_Battle
attr_reader :active_battler
attr_reader :target_battlers
#--------------------------------------------------------------------------
# ● 刷新画面 (主回合)
#--------------------------------------------------------------------------
def update_phase4
case @phase4_step
when 1
update_phase4_step1
if @phase4_step == 2 && @active_battler.exist?
# 显示连续伤害时 执行 1 号公共事件
$game_system.battle_interpreter.setup($data_common_events[1].list, 0)
end
when 2
update_phase4_step2
when 3
update_phase4_step3
when 4
update_phase4_step4
when 5
update_phase4_step5
# 显示伤害数字时 执行 2 号公共事件
$game_system.battle_interpreter.setup($data_common_events[2].list, 0)
when 6
update_phase4_step6
end
end
end
class Scene_Battle
attr_reader :active_battler
attr_reader :target_battlers
#--------------------------------------------------------------------------
# ● 刷新画面 (主回合)
#--------------------------------------------------------------------------
def update_phase4
case @phase4_step
when 1
update_phase4_step1
if @phase4_step == 2 && @active_battler.exist?
# 显示连续伤害时 执行 1 号公共事件
$game_system.battle_interpreter.setup($data_common_events[1].list, 0)
end
when 2
update_phase4_step2
when 3
update_phase4_step3
when 4
update_phase4_step4
when 5
update_phase4_step5
# 显示伤害数字时 执行 2 号公共事件
$game_system.battle_interpreter.setup($data_common_events[2].list, 0)
when 6
update_phase4_step6
end
end
end
1. 选取的 2 个时机,都是显示伤害数字的时候,这样的话就可以顺利播放动画
2. 要保留原来显示的伤害数字,得在公共事件里添加等待命令让原来的伤害数字先显示完毕,再显示新的伤害数字(比如“伤害处理”)。否则新的伤害数字会立即覆盖掉正在显示的伤害数字。要判断是否有伤害数字待显示,用 battler.damage_pop
3. 第 1 处的公共事件,在角色行动前。
3.1 参见Scene_Battle 4 的 make_action_orders 中把所有的单位都加入了行动列表,所以每个行动者都会正常执行 phase4_step1 并进入 phase4_step2。
3.2 由于添加了 @active_battler.exist? 的判断,行动者被隐藏,或者死亡,第 1 处的公共事件就不会发动。不存在的此行动者在 phase4_step2 一开始就会立即结束自己的回合。
3.3 @hidden属性 = true 的角色被隐藏(比如中途出现的敌人),但是也会执行 phase4_step1 ,所以同样会受到“持续伤害”和“状态移除”的效果。
4. 第 2 处的公共事件,在角色行动后。再然后才是物品、技能的公共事件,在 phase4_step6 结束后执行
5. 使用 $scene.active_battler 和 $scene.target_battlers 获取行动者和目标对象数组,但是注意第 1 处是没有 $scene.target_battlers 的。
6. 尚不清楚与战斗事件各条件的先后顺序,待测试。适当设置事件触发条件应该无冲突都能触发。
需要播放动画、等待、显示文字的时候,公共事件比Ruby代码好使。在这里添加一些判断也可以制造特殊的战斗效果。
第 1 处行动前的公共事件的可能用途比较容易想到,比如角色每次行动时会回复HP/SP。此外,由于这里尚未执行行动,可以修改 @active_battler.current_action 使得接下来的行动方式、目标发生改变。
第 2 处行动后的公共事件,看上去似乎可以用物品、技能的公共事件代替。实际上并不是这样。这里举 2 个例子:
1. 在第 2 处行动后的公共事件的最前面添加事件脚本,可以消除原来的伤害数字,假设消除的是第一个目标身上的伤害数字:
@battler = $scene.target_battlers[0]
@battler.damage_pop = false
# 猜猜这行注释干什么用?
@battler = $scene.target_battlers[0]
@battler.damage_pop = false
# 猜猜这行注释干什么用?
然后紧接着一个脚本:
@battler.damage = '无可奉告'
@battler.damage_pop = true
@battler.damage = '无可奉告'
@battler.damage_pop = true
用来表示 BOSS 的深不可测
2. 不仅可以消除伤害数字,在第 2 处可以任意修改技能、物品的后续效果,比如:
$scene.target_battlers.each do |battler|
if battler.hp == 0 && battler.state?(10)
battler.hp = 1
end
end
$scene.target_battlers.each do |battler|
if battler.hp == 0 && battler.state?(10)
battler.hp = 1
end
end
这样就能使附加上 10 号状态的角色 hp 至少为 1,制造出“薄葬”的效果。
如果在物品、技能附带公共事件里添加这段代码,是没有“薄葬”效果的。原因是在 phase4_step5 结束后,尚未进入 phase4_step6 执行物品、技能公共事件就已经结算了hp = 0的死亡效果。
同样,在这里也可以轻易的给出击杀者,或者制造魔法盾等等丰富多彩的技能
关于这些想法,最初是从 sailcat 的脚本里得到启发。原帖见这里:https://rpg.blue/forum.php?mod=viewthread&tid=31747
作者: guoxiaomi 时间: 2017-3-8 20:55
本帖最后由 guoxiaomi 于 2017-4-3 22:44 编辑
继续说一点,Sailcat 前辈的脚本为了解决回血的问题——即在显示伤害数字(@phase4_step = 5)的时候目标的血量实际上已经扣除——将 phase4 的几个 step 位置移动了。我的这个脚本里没有这么做,所以对于减伤的技能效果,实现起来要困难一些。但是其他的效果也算是比较容易实现了。
下面会举一些例子,其实大部分实现方法跟 Sailcat 前辈差不多,所以我这里着重讲几个区别比较大的地方。
1. 连击(单回合多次行动)
连击的话,思路很清楚,在第 2 处公共事件里,或者在物品、技能的公共事件里,设置 $scene.phase4_step = 2。这样在 step = 5(或6) 结束后,会回到 step = 2,此时@active_battler没有改变,就会重复执行之前的行动。
所以要把 phase4_step 给拿出来,同时为了方便添加说明文字,把 help_window 也拿出来。
class Scene_Battle
attr_reader :help_window
attr_accessor :phase4_step
end
class Scene_Battle
attr_reader :help_window
attr_accessor :phase4_step
end
比如说,在技能 1 释放后会追加 1 次攻击。事件脚本:
@battler = $scene.active_battler
a = @battler.current_action
if a.kind == 1 && a.skill_id == 1
a.kind, a.basic = 0, 0
$scene.phase4_step = 2
$scene.help_window.set_text("追加攻击", 1)
$scene.help_window.visible = true
end
@battler = $scene.active_battler
a = @battler.current_action
if a.kind == 1 && a.skill_id == 1
a.kind, a.basic = 0, 0
$scene.phase4_step = 2
$scene.help_window.set_text("追加攻击", 1)
$scene.help_window.visible = true
end
2. 技能暴击(添加暴击字符串)
技能暴击,关键是要添加一个暴击字符串,然后修正对象HP。在第 2 处公共事件判断技能ID、概率决定后面的处理。添加以下的事件脚本,这里分成 2 个,其实写成 1 个也没问题。
@battler = $scene.active_battler
@targets = $scene.target_battlers
@battler = $scene.active_battler
@targets = $scene.target_battlers
a = @battler.current_action
if a.kind == 1 && a.skill_id == 57
@targets.each do |t|
if t.damage.is_a?(Numeric) && rand < 0.25
t.hp = [t.hp-t.damage,0].max
t.damage = t.damage * 2
t.critical = true
end
end
end
a = @battler.current_action
if a.kind == 1 && a.skill_id == 57
@targets.each do |t|
if t.damage.is_a?(Numeric) && rand < 0.25
t.hp = [t.hp-t.damage,0].max
t.damage = t.damage * 2
t.critical = true
end
end
end
则 57 号技能有 25% 的概率造成 2 倍伤害,并显示 Critical 字样。
3. 魔法盾(减伤+伤害SP)
减伤比较麻烦的地方在于,damage 里记录的是造成的伤害值,而不是 hp 的损失值。比如 damage > 现有 hp,直接致死,但是在第 2 处公共事件触发时 hp = 0,所以如果回血直接 hp += damage 就不对了。
有 2 种解决方案:
1. 在扣血前记录对象方 HP。
2. 附加状态防御以减伤。
第 1 种方法就不细说了,只要在第 1 处公共事件里记录下所有敌人、队友的HP值即可。
第 2 种方法的思路还是比较巧妙的:
要实现 60% 的伤害被 SP 吸收,首先保证实际造成的伤害不能高于 40%,否则对象方 hp < 0 再回血就BUG了。首先要做以下准备工作:
1. 设置技能附带属性和状态,假设是属性:[魔法攻击]和状态:[受到魔法伤害]
2. 设置 2 个状态,分别是[魔法盾],[减伤1],都能防御属性:[魔法攻击],持续 3 回合
3. 设置[魔法盾]状态,附加[减伤1] 这个状态
这样由于 2 重属性防御使得最终受到的伤害为 25% < 40%,从而确保此技能不会有伤害溢出。流程如下:
1. 发动攻击,属性[魔法攻击],对象方附加上状态[受到魔法伤害]
2. 由于对象方带有状态[魔法盾],[减伤1],所以对属性[魔法攻击] 2 次减伤,无 Miss 的情况下承受 25% 的伤害
3. 进入行动后公共事件,由于对象方带有状态[魔法盾],[受到魔法伤害],且伤害不为 Miss,魔法盾效果发动
4. 对象方再次承受 15% 的伤害,并且根据 SP 的量承受额外的伤害,以及损失 SP
5. 显示最终的伤害值,移除[受到魔法伤害]的状态
这里,状态 20 是[受到魔法伤害] 状态 21 是[魔法盾] 状态 22 是[减伤1]
@battler = $scene.active_battler
@targets = $scene.target_battlers
@battler = $scene.active_battler
@targets = $scene.target_battlers
@targets.each do |t|
next if not t.state?(21)
if t.damage.is_a?(Numeric) && t.state?(20)
t.damage = t.damage * 4
a = t.damage * 60/100 - t.sp
t.hp = t.hp - t.damage * 15/100
t.damage -= (a>0)? t.sp : t.damage*60/100
t.sp = (a>0)? 0 : -a
t.hp = (a>0)? t.hp - a : t.hp
end
end
@targets.each do |t|
next if not t.state?(21)
if t.damage.is_a?(Numeric) && t.state?(20)
t.damage = t.damage * 4
a = t.damage * 60/100 - t.sp
t.hp = t.hp - t.damage * 15/100
t.damage -= (a>0)? t.sp : t.damage*60/100
t.sp = (a>0)? 0 : -a
t.hp = (a>0)? t.hp - a : t.hp
end
end
@targets.each do |t|
t.remove_state(20)
end
@targets.each do |t|
t.remove_state(20)
end
4. 多合一范例
范例里十字斩可以200%暴击、追加随机攻击;魔法盾减少60%十字斩的伤害,不减少攻击伤害;敌人会自带魔法盾,和 5 回合的薄葬效果,并且每回合回复 100 HP。
公共事件里按照触发顺序依次是,关闭伤害显示 -> 判断暴击(施加伤害) -> 判断魔法盾(承受伤害) -> 显示伤害、移除标记 -> 判断薄葬 -> 判断连击
公共事件战斗.zip
(202.72 KB, 下载次数: 287)
5. 理想的设置
理想的设置是这样的:
1. 武器、技能会附带[物理伤害]、[魔法伤害]、[纯粹伤害]中的一种属性,并且给对象方施加[承受物理伤害]、[承受魔法伤害]、[承受纯粹伤害]的状态。
2. 魔法盾等伤害减免的效果,响应哪种类型的技能,就对此技能进行减伤,然后根据对象方身上承受伤害类型的状态来决定后续的处理。
3. 最后显示伤害数字,并且移除对象方[承受物理伤害]、[承受魔法伤害]、[承受纯粹伤害]的状态。
4. 目标受到的伤害数字 t.damage 会收到不同的技能效果而发生变化并传递给下一个技能效果,最终得到一个伤害数字,然后显示。
作者: fux2 时间: 2017-3-9 10:53
仅仅是作为自己使用的话,没什么问题,但这样不便于管理,效率也低。
其实战斗前后执行事件才是个比较棘手的问题,楼主或许可以试试23333
作者: guoxiaomi 时间: 2017-3-9 11:16
本帖最后由 guoxiaomi 于 2017-3-9 11:21 编辑
我其实一直以为战斗前后不是问题……我目前的想法是
战斗前:在队伍里设置 0+0回合 ~
战斗后:在战斗结束返回 Scene_Map 前修改 $game_temp.comment_event_id,或者打开一个开关
不知道这样会不会有什么BUG……
作者: fux2 时间: 2017-3-9 18:47
队伍里,难道所有队伍都添加一个事件页吗- -
战后,如果这场战斗本身就在事件指令中,战后的公共事件预约根本不会生效。
作者: jiushiainilip19 时间: 2017-3-9 19:02
很想用 等哪天有空就好好用一下,正好正在填坑的游戏需要战前自动释放一个技能。
就是开场就自动触发一个技能,就是怕卡{:2_248:}
作者: guoxiaomi 时间: 2017-3-10 00:16
本帖最后由 guoxiaomi 于 2017-3-10 01:29 编辑
战斗前后调用公共事件,这个目前看来没有BUG
战斗前:
修改 Scene_Battle 1 的第 21 行,原来是初始化解释器:
- $game_system.battle_interpreter.setup(nil, 0)
复制代码
改为执行第 3 号公共事件:
- $game_system.battle_interpreter.setup($data_common_events[3].list, 0)
复制代码
如果想在战斗前释放技能、执行动作,添加下面的事件脚本:
a = $game_actors[1].current_action
a.kind = 1
a.skill_id = 57
a.decide_random_target_for_actor
$scene.help_window.set_text("优先回合", 1)
$scene.help_window.visible = true
$game_temp.battle_turn = -1
$scene.start_phase4
a = $game_actors[1].current_action
a.kind = 1
a.skill_id = 57
a.decide_random_target_for_actor
$scene.help_window.set_text("优先回合", 1)
$scene.help_window.visible = true
$game_temp.battle_turn = -1
$scene.start_phase4
这里其实是分 3 段:
1. 设置角色要执行的技能(current_action),这里设置 1 号角色使用 57 号技能:十字斩。可以设置多个角色。
2. 设置help_window,显示一行说明文字,可以不要。
3. 设置回合数为 -1, 并跳转到 Scene Battle 的 Phase 4
注意:
1. 如此设置的执行顺序是,在此公共事件执行结束后,执行 0+0x 的战斗事件,然后跳转到 Scene Battle 的 Phase 4 开始行动。
2. 因为是正常的行动,行动前后会执行前面里设置的行动前、后公共事件。如果不想执行,判断 $game_temp.battle_turn != 0 即可。
战斗后:
在 battle_end 里面打开开关 2,然后设置 4 号公共事件并行处理,开关为 2。如此即可在战斗后回到地图中执行 4 号公共事件。
class Scene_Battle
alias _old_battle_end battle_end
def battle_end(result)
_old_battle_end(result)
# 打开开关 2
$game_switches[2] = true
end
end
class Scene_Battle
alias _old_battle_end battle_end
def battle_end(result)
_old_battle_end(result)
# 打开开关 2
$game_switches[2] = true
end
end
范例:
公共事件战斗1.zip
(191.51 KB, 下载次数: 184)
作者: guoxiaomi 时间: 2017-3-12 21:34
本帖最后由 guoxiaomi 于 2017-3-12 21:45 编辑
回合开始(队伍命令前)调用公共事件:
在 start_phase2 中加入公共事件的调用:
- class Scene_Battle
- alias _old_start_phase2 start_phase2
- def start_phase2
- _old_start_phase2
- # 执行公共事件 5
- $game_system.battle_interpreter.setup($data_common_events[5].list, 0)
- end
- end
复制代码
每个回合开始前调用公共事件 5,从第 1 回合开始才会调用,故不影响战斗前的公共事件,但是由于在 phase4 才会增加 $game_temp.battle_turn 的值,所以在此事件里的回合数是从 0 开始的。
到此为止,战斗前、回合开始、行动前、行动后、战斗后(地图画面)这 5 种时间点都可以调用公共事件,同时与原有的战斗事件兼容。
默认战斗用这种方法可以进行方便又强力的改动。
作者: ikki 时间: 2018-3-24 20:58
这些都是10年前我在研究的东东啊
作者: guoxiaomi 时间: 2018-4-16 11:42
最近在更新游戏的战斗系统,借(chao)鉴(xi)了dota2的各种设定。
dota2里的天赋很有趣,比如说“+900寒霜之足AOE”,“+175连锁闪电伤害”,“重生不消耗魔法”。这些都是对原来的技能进行修改的特性,RM的话,通常方案就是做2个技能,学了就换掉,但是如果大胆的操作,可以在战斗前or行动前直接修改$data_skills,战斗后or行动后改回来。
同样的也可以修改装备的武器($data_weapons)、防具数据($data_armors)甚至状态($data_states),因为RM会在每次计算攻击力、防御力的时候,都会读取这些数据,而不是在战斗一开始的时候读好缓存起来。
优点:
1. 几乎不与其他脚本冲突:因为绝大部分脚本都不会动数据库
2. 更加灵活:根据变化的值设置技能效果,比如技能伤害+变量1的值,或者给武器附上不同的属性。做多个技能的话,每个技能的数据仍然是固定不变的,后者需要设置多个武器。
缺点:
1. 需要对战斗系统有足够的了解,至少要知道这些数据在哪里被用到
作者: adssdass00 时间: 2019-1-14 20:15
打扰了,请问如果是要在使用特定技能时调用公共事件,应该怎么改呢?
想做成类似技能(必杀技)施放前会出现角色图片的那种
脚本渣求问
作者: guoxiaomi 时间: 2019-1-15 01:42
本帖最后由 guoxiaomi 于 2019-1-15 01:44 编辑
在战斗前的公共事件里判断当前的技能,类似这样打开10号开关:
- b = $scene.active_battler
- a = b.current_action
- if a.kind == 1 && a.skill_id == 10
- $game_switches[10] = true
- end
复制代码 然后后面接其他的事件指令,记得结束事件前关掉10号开关避免无限触发
作者: adssdass00 时间: 2019-1-15 07:43
非常感谢!请问这一段脚本是要插入到哪里呢?
插入在公共事件中或Scene_Battle 1里面都显示出错
作者: 十三点九进制 时间: 2020-3-4 04:42
你好大大,打扰了,我想请问一下,自己在做一个反击技能,搜索“反击”的时候找到大大的回答
3. 设置目标的行动为反击,对象为当前行动者,强制行动。
比较笨,没明白这个设置目标行动应该怎么设置,希望大大解答,谢谢
作者: Eevee伊布 时间: 2020-6-14 01:31
请问 mv怎么 回合开始时调用公共事件?
作者: soulsaga 时间: 2022-8-31 01:32
回合开始(队伍命令前)可以调用公共事件
但是强制行动还是在行动后才会执行..求解
欢迎光临 Project1 (https://rpg.blue/) |
Powered by Discuz! X3.1 |