✓ ESS21仅限 【TA】【特性】014 Passing(0617)

TAAAAAAA

天王
成员
2024-06-16
173
1
27
1,110
014 Example:Passing

这期教程,我们来讲解特性实例。

特别注意,在我们讲解特性实例的时候,我并不会使用伪代码。

为了能够显示中文,从这期教程开始,我已经安装了Zpix字体,当然并不是原本的Zpix,我自己已经修改过了一些东西。

那么,这期教程我们要讲的是遗志。
遗志(Passing):自身濒死时,将自身的能力等级传递给下一个登场者。

首先是PBS部分——
1721641264810.png

接着是思考,如何才能实现我们的要求呢?
这个特性是自身濒死时发动的,所以特性Handler一定是OnSelfFainting,那么接着呢?
这个特性,其实就相当于,把一个精灵的能力等级,复制给另一个精灵。
那么思考一下,哪里有类似的呢?

其实百变怪的变身就有这个效果。
那我们就搜索一下变身——
1721641280317.png
可以看出来,就是pbTransform这个方法,那我们再搜索一下这个方法——
1721641292505.png
可以发现,我们需要的就是这一行代码——
1721641307282.png
就是这一行代码,让百变怪的能力等级,和被变身的精灵的能力等级一样。
也就是说,能力等级相关的信息,是存储在stages里的。

所以,我们需要在这个特性发动的时候,复制一份这个精灵当前的能力等级,并且把它存储到一个变量里。
那么,是基于battle的变量,还是基于battler的变量呢?
答案是基于battle的变量,我希望你知道为什么,如果不清楚的话请去看之前的教程。
那我们就这样——
1721641322643.png
再初始化——
1721641338210.png
初始化到nil,nil就是没有,也就是说刚开始passedStages并不会存储任何东西。
我们就用passedStages来存储当这个特性发动时的当前精灵的能力等级。

接着,我们就可以直接这样写了——
1721641349914.png
Ruby:
Battle::AbilityEffects::OnSelfFainting.add(:PASSING,
  proc { |ability, battler, battle|
    next if battle.passedStages
    battle.pbShowAbilitySplash(battler)
    battle.passedStages = battler.stages.clone
    battle.pbDisplay(_INTL("{1}将自己的能力等级传递给了后来者!", battler.pbThis))
    battle.pbHideAbilitySplash(battler)
  }
)
首先判断passedStages是否已经有存储数据了,有的话就直接跳过;
接着出特性条;
接着将当前精灵的能力等级存储到passedStages中;
接着出现一个提示的文字;
最后特性条消失。

这样,我们就把能力等级存储方面的代码全部完成了。

这里的话需要注意一下battler.stages.clone,这里有个clone,你暂时不需要去管clone到底是什么,你只需要记住,当你想用变量存储某一个东西,而这个东西并不是单独的一个数值的话,你需要用到clone。
这主要是因为,我们前面也已经是说过了,它其实是引用,而不是真的等于,或者说赋值。
这里其实我们思考一下就能知道,能力等级,有很多能力的能力等级,它肯定是多个数,不可能是单独的一个数,比如说物攻的能力等级,特攻的能力等级,等等。
这是思考的逻辑,所以你其实并不需要真的知道stage到底存储了什么东西,你只需要知道stage存储的是哪一类东西。

到这里还没结束,现在我们只是存储了能力等级,我们还需要对新上场的精灵应用存储的能力等级。
那么在哪里应用呢?
思考一下,不难想到,只要在精灵出场时应用就好了。
所以应用的地方,应该和精灵出场时会发动的特性的Handler接入战斗系统中的地方,是一样的。
所以我们搜索一下就好了——
1721641426398.png
1721641433137.png
就是这里,那么我们就让应用,在新上场的精灵的自身的特性发动之前应用——
1721641448516.png
我们新写了一个pbPassStatsStages方法来应用——
1721641468763.png
Ruby:
  def pbPassStatsStages(battler)
    return if !@passedStages
    GameData::Stat.each_battle { |s| battler.stages[s.id] = @passedStages[s.id] }
    @passedStages = nil
  end
这个方法会先检查@passedStages是否存储了数据,如果没有的话,就直接返回了,不进行任何处理。
如果@passedStages存储了数据的话,就执行应用。
我们只需要把原本变身里的这行GameData::Stat.each_battle { |s| @stages[s.id] = target.stages[s.id] }稍微修改一下,变成GameData::Stat.each_battle { |s| battler.stages[s.id] = @passedStages[s.id] }就好了。
原本是当前精灵复制目标的能力等级,现在是当前精灵复制之前存储的能力等级。
原本是这样@stages[s.id] = target.stages[s.id],现在是这样battler.stages[s.id] = @passedStages[s.id],这样的写法你看不懂的话,你也可以把它改成——
原本这样self.stages[s.id] = target.stages[s.id],也就是原本是自身的stages等于目标的stages;
现在这样battler.stages[s.id] = self.passedStages[s.id],也就是自身的stages等于之前保存的stages,关于自身的这个self,我们已经在之前的教程中说过了,简单说就是在哪一级,self就是什么,比如说在Battle,那self就代表battle,在Battler,self就当表battler。
原本变身的方法是写在Battler里的,所以原本的self就是battler;
现在这个pbPassStatsStages(battler)方法是写在Battle里的,所以它的self就是battle,并且,passedStages就是基于battle的变量。
也就是说,当指向自身,也就是self的时候,self可以省略,并且后面的“.”后面的方法,需要加个@,当然此时@后面的方法就不是方法了,而是变量。
简单的说就是,你可以通过对self调用某个方法,来获取一个变量;或者,你可以直接获取变量。

还是要强调一下,当你这样写的时候self.stages,是对self调用stages方法,通过stages方法,对stages这个变量做一定的处理;
而当你这样写的时候,@stages,是直接对这个变量做一定的处理。

如果你要问这样写有什么区别的话,我只能说,有点复杂,你也基本不需要去了解。
为了以防万一,保证你自己绝对不会出错的话,我建议你都用xxx.yyy这样的格式来写代码,也就是对xxx调用yyy方法的格式。
那我们就把原本的改成这样的格式——
Ruby:
  def pbPassStatsStages(battler)
    return if !@passedStages
    GameData::Stat.each_battle { |s| battler.stages[s.id] = self.passedStages[s.id] }
    @passedStages = nil
  end

可以看到,同时,这个方法传递了一个参数battler,这个就不用解释了吧,因为这个方法是写在Battle里的,所以需要传递一下是battle里的哪一个battler。
1721641518176.png
看前面的代码我们就能知道,这里的battler就是前面的b,也就是新上场的那一个battler。

应用完能力等级之后,在这个方法的最后面,通过@passedStages = nil,清除了@passedStages里存储的数据,保证应用只会发生一次。

到这里就全部完成了,那我们就进游戏测试一下——
1721641549636.png
1721641562113.png
让皮卡丘在第一个回合使用影子分身,然后濒死,接着我们只需要看一下新上场的精灵的信息就好了。
1721641576657.png
1721641583975.png
1721641595199.png
1721641602720.png
1721641609945.png
可以看到,比比鸟接受了皮卡丘传递的能力等级。

这里还是要强调一下,目前这样的写法,并不会检查皮卡丘本身是否有能力等级变化,只要皮卡丘濒死了,这个特性就会发动。
同时,是让皮卡丘濒死之后上场的那一个精灵,接受皮卡丘的能力等级,不论新上场的精灵是我方的,还是对方的,所以,会更加有趣一点。

关于怎么让皮卡丘有能力等级变化的时候才发动这个特性,没有能力等级变化就不发动这个特性呢?
这样就好了——
Ruby:
Battle::AbilityEffects::OnSelfFainting.add(:PASSING,
  proc { |ability, battler, battle|
    next if battle.passedStages
    trigger = false
    GameData::Stat.each_battle do |s|
      if battler.stages[s.id] != 0
        trigger = true
        break
      end
    end
    next if !trigger
    battle.pbShowAbilitySplash(battler)
    battle.passedStages = battler.stages.clone
    battle.pbDisplay(_INTL("{1}将自己的能力等级传递给了后来者!", battler.pbThis))
    battle.pbHideAbilitySplash(battler)
  }
)
关于这个额外的检查,我就不解释了。

其实,为了让你的代码更加严谨,你还应该加上,当皮卡丘后面没有任何精灵的时候,这个特性也不应该发动,因为没有精灵可以传递能力等级了——
Ruby:
Battle::AbilityEffects::OnSelfFainting.add(:PASSING,
  proc { |ability, battler, battle|
    next if battle.passedStages
    next if battle.pbAllFainted?(battler.idxOwnSide) || battle.pbAllFainted?(battler.idxOpposingSide)
    trigger = false
    GameData::Stat.each_battle do |s|
      if battler.stages[s.id] != 0
        trigger = true
        break
      end
    end
    next if !trigger
    battle.pbShowAbilitySplash(battler)
    battle.passedStages = battler.stages.clone
    battle.pbDisplay(_INTL("{1}将自己的能力等级传递给了后来者!", battler.pbThis))
    battle.pbHideAbilitySplash(battler)
  }
)
关于这个额外的检查,我也不解释了,这些额外的检查,无非是让代码更加健壮,没有这些检查其实也并不会影响到这个特性本身的功能。

那么这期教程就到此为止。

视频预览(0722)——

浏览附件2024-07-22 21-26-48.mp4

感谢阅读。
 
最后编辑:

在线成员

论坛统计

主题
458
消息
2,072
会员
2,854
最新会员
jiuchuan

关于我们

  • 宝可梦以及其他相关名称是任天堂的商标,版权归宝可梦公司所有。宝可饭堂是一个同人游戏中文社区,不隶属于宝可梦公司。在宝可饭堂上的粉丝游戏亦未获得其授权,请支持正版游戏。
© 2022- pokefans.cn
点此延长宝可饭堂生命