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

Project1

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

用公共事件实现战斗特殊效果(理论)

2005-10-14 00:00| 发布者: 柳柳| 查看: 5113| 评论: 0|原作者: 66RPG

摘要:    作者   SailCat(中国大陆)  版本与更新 本理论的实践部分点此进入  相关网址    范例工程 不提供  教程内容 说明:这个并不是什么自创的办法,因为
 

 作者

  SailCat(中国大陆)

 版本与更新

本理论的实践部分点此进入

 相关网址

 

 范例工程

不提供



 教程内容

说明:这个并不是什么自创的办法,因为已经有无数无数人采用过了,我在这里只是把它说明的更清楚更具体一些而已,对于脚本都给了清楚的注释,新手也能看懂。

主站上有一个通过自定义属性来实现战斗特殊效果的脚本,但是那个不但局限性很大,牵涉了大量的字符串解读处理,而且由于完全覆写了属性并大规模改写了内核脚本,使得一旦使用这个脚本后,根本再没有办法实现其他的战斗效果,例如即时动画、ATB战斗等,因为它会和几乎所有的战斗类脚本冲突。

那么有必要兴师动众地去这么做吗?实际上,技能附带公共事件是一个非常有效的设定,通过不同的公共事件,我们甚至可以完全不修改内核脚本而整个覆写掉一个技能的效果。

以下,通过定义公共事件,可以实现站上那个战斗特殊效果脚本中绝大部分的内容,自由度更大,但是没有任何冲突,也完全不用更改属性、状态之类的设定。对于系统脚本的修改,仅仅是很微小的一部分,并且只有添加,没有更改和删除原本的语句。

首先看一下公共事件的机理,在Scene_Battle 4这个定义里。第420-451行(如果你没有
自己改过的话)可以找到以下的内容:
  #--------------------------------------------------------------------------
  # ● 刷新画面 (主回合步骤 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
    # 移至步骤 6
    @phase4_step = 6
  end
  #--------------------------------------------------------------------------
  # ● 刷新画面 (主回合步骤 6 : 刷新)
  #--------------------------------------------------------------------------
  def update_phase4_step6
    # 清除强制行动对像的战斗者
    $game_temp.forcing_battler = nil
    # 公共事件 ID 有效的情况下
    if @common_event_id > 0
      # 设置事件
      common_event = $data_common_events[@common_event_id]
      $game_system.battle_interpreter.setup(common_event.list, 0)
    end
    # 移至步骤 1
    @phase4_step = 1
  end
即使你看不懂脚本,脚本里的注释总该能看懂吧。步骤5是显示伤害值,步骤6是刷新并调用公共事件。以前看到有人问用公共事件设置的伤害值,总会在弹出伤害值之前先弹出一个Miss,其实只要改换这两步的顺序,就不会再出现这种恼人的问题了。改变的办法是:复制第443-448行,然后粘贴到426行之前即可。变成下面这个样子:
  #--------------------------------------------------------------------------
  # ● 刷新画面 (主回合步骤 5 : 显示伤害)
  #--------------------------------------------------------------------------
  def update_phase4_step5
    # 隐藏帮助窗口
    @help_window.visible = false
    # 公共事件 ID 有效的情况下
    if @common_event_id > 0
      # 设置事件
      common_event = $data_common_events[@common_event_id]
      $game_system.battle_interpreter.setup(common_event.list, 0)
    end
    # 刷新状态窗口
    @status_window.refresh
    # 显示伤害
    for target in @target_battlers
      if target.damage != nil
        target.damage_pop = true
      end
    end
    # 移至步骤 6
    @phase4_step = 6
  end
  #--------------------------------------------------------------------------
  # ● 刷新画面 (主回合步骤 6 : 刷新)
  #--------------------------------------------------------------------------
  def update_phase4_step6
    # 清除强制行动对像的战斗者
    $game_temp.forcing_battler = nil
    # 移至步骤 1
    @phase4_step = 1
  end
这样,调用公共事件将在刷新状态栏(也就是技能效果后的敌我情况)之前进行,并视你对伤害值的设置来弹出伤害值。这一步搞定后,下面就是用公共事件来自定义技能效果……且慢。

大家知道,每个技能都会有自己的一个默认效果,也就是在系统内部进行伤害值公式计算之后得到的诸如HP损伤值、状态变化值之类的设定,这个计算在主回合步骤2进行,调用的是Game_Battler的定义。这里摘录一段和我们的解释内容相关的部分:
      # HP 的伤害减法运算
      last_hp = self.hp
      self.hp -= self.damage
      effective |= self.hp != last_hp
      # 威力为 0 的场合
      if power == 0
        # 伤害设置为空的字串
        self.damage = ""
        # 状态没有变化的情况下
        unless @state_changed
          # 伤害设置为 "Miss"
          self.damage = "Miss"
        end
      end
前面的计算不管它了,反正我们也用不到。状态变化也不用管,因为特殊技能的附带状态是用公共事件来完成,数据库里是设置为空的。关键的有这么两个:
self.damage <--- 这个是计算出来的HP伤害。
self.hp <--- 这个操作被施技能者的HP,减掉伤害值。
last_hp <--- 这个是被施技能者在技能生效之前的HP。

为什么要提到上面这一步(而不是跳过它),主要是因为一些特殊效果并不是追加而是覆写(比如从伤害HP改为伤害SP,或比例伤害HP等),既然要覆写,就必须先还原默认计算造成的伤害。可能最容易想到的是:
self.hp += self.damage
且慢,这个时候伤害字符串可能已经被设置成Miss了(如果你把技能攻击力填写为0)会出错的,而且即使不提出错的事情,临界HP的变化你也不能用这个方法来还原(就是说加HP超过最大值和减HP低于0的情况)。正确的办法是使用last_hp来还原,把这个变量全局化。方法如下(具体我就不解释原理了):
在Game_Battler 1的定义部分,加上:
  attr_reader   :last_hp                  # 以前的HP
然后在Game_Battler 3里搜索
"last_hp",替换为"@last_hp",即可。不会对已有功能产生任何影响。

至此,对于脚本的修改基本上完成,下面就是公共事件。之所以说“基本上”,是因为公共事件是一个相对独立的东西,它并不从属于任何场景,因此,在公共事件中调用技能动作的执行者、施受者和技能本身,不修改脚本是做不到的(当然,carol3大人提出的状态法是一个办法,而且那个也只能调用出施受者)。
在Scene_Battle 1的第一个def之前,定义实例变量(这个类本来没有任何实例变量)。
默认在第8行,之前插入以下三行:
  attr_accessor :target_battlers            # 技能施受者(集合)
  attr_accessor :active_battler             # 技能执行者(battler)
  attr_reader   :skill                      # 具体技能(skill)
有了这三行,你就可以在公共事件中很方便地取得你需要的三个参数。同样,因为是插入的东西,而且是不会被解释执行的脚本,对原有功能不构成任何影响。这三行在公共
事件里的调用方法是:
$scene.target_battlers    # 获得技能施受者
$scene.active_battler     # 获得技能执行者
$scene.skill              # 获得具体技能

好了,废话这么多,切入正题。公共事件的设置不难,就是插入一段脚本就行,你要是真的不会脚本,就用一堆变量和开关倒来倒去也成。
下面以自定义一个"重力术"和一个"吸魂术"为例,来说明一下具体的步骤:
设想效果:
重力术:固定造成现有HP的33%伤害,但是,对类型为“蛇”(属性10)的怪物,无效。
吸魂术:伤害计算同一般技能,额外效果是技能执行者会增加等同于伤害值的HP,但是对类型为“不死”(属性9)的怪物,效果是倒过来的,即执行者减HP,施受者加HP。

数据库设定:
重力术:名称“重力术”(这个很重要,如果你不想用ID来进行识别,就把名称固定)
效果值:33,其他的都默认,公共事件设为“重力”
吸魂术:名称“吸魂术”,效果值:你想要造成的伤害值设定,其他的都默认,公共事
件设为“吸魂”。

公共事件1:重力术(这个名称倒无所谓)

解析:重力术除了覆写伤害值效果之外没有其他附加作用,三个参数中只需要获得谁被用了重力术,以及重力术的效果值(33)就行了。由于重力术是覆写原技能的伤害值效果,所以第一步先要还原:(请注意:在粘贴以下脚本之前,请务必把注释行去掉,那个窗口寸土寸金的说)

# 重赋值,减少变量长度(这点很重要)
@s = $scene.skill
# 技能施用者集合 循环实例
for t in $scene.target_battlers
  # 把HP还原成被施用技能之前的HP
  t.hp=t.last_hp

然后就是计算实际的伤害值。

  # 如果对象是“蛇”
  if t.element_rate(10)>=150
    # 无效
    t.damage="Miss"
  # 不是的场合
  else
    # 计算HP伤害
    t.damage=t.hp*@s.power/100
  end

最后是来操作HP减掉这个伤害。

  # HP的伤害减法运算
  t.hp-=t.damage
# 结束循环
end

完整的一个脚本如下(去掉注释),贴到公共事件里就行了。

@s = $scene.skill
for t in $scene.target_battlers
  t.hp=t.last_hp
  if t.element_rate(10)>=150
    t.damage="Miss"
  else
    t.damage=t.hp*@s.power/100
  end
  t.hp-=t.damage
end

公共事件2:吸魂术,这个我解释的少一点,通过上例以及注释,大家应该不难看懂。

吸魂术由于对执行者也要操作,但效果值是默认的,所以三个参数中需要前两个。先把参数繁杂的写法缩短:
@a = $scene.active_battler
之所以写成@a而不是a,是怕如果一个脚本框写不下拖到下一个框时变量会失效。

然后是开始进行效果操作:
for t in $scene.target_battlers
  # 如果对象是“不死”
  if t.element_rate(9)>=150
    # 对象增加HP
    t.hp=t.last_hp+t.damage
    # 执行者减少HP
    @a.damage=t.damage
    @[email protected]
    # 对象的伤害值取反
    t.damage=-t.damage
  # 不是的情况下
  else
    # 执行者增加HP
    @a.damage=-t.damage
    @[email protected]
  # 分歧结束
  end
# 循环结束
end
# 把临时变量赋给实例
$scene.active_battler = @a
$scene.active_battler.damage_pop=true

完整的脚本:

@a = $scene.active_battler
for t in $scene.target_battlers
  if t.element_rate(9)>=150
    t.hp=t.last_hp+t.damage
    @a.damage=t.damage
    @[email protected];t.damage=-t.damage
  else
    @a.damage=-t.damage;@[email protected]
  end
end
$scene.active_battler = @a
$scene.active_battler.damage_pop=true

只要稍微知道操作中几个变量的关系,你可以任何的写出你想要的战斗技能特殊效果。

那么,如果有十多,二十多个特殊效果的技能,每个写一个公共事件不是非常占内存么能不能整合在一个公共事件里?当然可以。用条件分歧就可以了,在条件里使用脚本,写入
$scene.skill.name == 技能名称
比如
$scene.skill.name == "吸魂术"
然后在分歧里写下那个脚本即可,不管多少特效,一个公共事件搞定。


 

教程的通用说明

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

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


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

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

GMT+8, 2025-4-6 00:29

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

返回顶部