014 Example:Passing
这期教程,我们来讲解特性实例。
特别注意,在我们讲解特性实例的时候,我并不会使用伪代码。
为了能够显示中文,从这期教程开始,我已经安装了Zpix字体,当然并不是原本的Zpix,我自己已经修改过了一些东西。
那么,这期教程我们要讲的是遗志。
遗志(Passing):自身濒死时,将自身的能力等级传递给下一个登场者。
首先是PBS部分——
![1721641264810.png 1721641264810.png](https://bbs.pokefans.cn/data/attachments/2/2564-e32a626addd2b1a9c7037a0b5d325792.jpg)
接着是思考,如何才能实现我们的要求呢?
这个特性是自身濒死时发动的,所以特性Handler一定是OnSelfFainting,那么接着呢?
这个特性,其实就相当于,把一个精灵的能力等级,复制给另一个精灵。
那么思考一下,哪里有类似的呢?
其实百变怪的变身就有这个效果。
那我们就搜索一下变身——
![1721641280317.png 1721641280317.png](https://bbs.pokefans.cn/data/attachments/2/2565-f8d48d07fcd7b3f894fba0a0e502b332.jpg)
可以看出来,就是pbTransform这个方法,那我们再搜索一下这个方法——
![1721641292505.png 1721641292505.png](https://bbs.pokefans.cn/data/attachments/2/2566-20ec3e4f68c5074ec111b1ae26170448.jpg)
可以发现,我们需要的就是这一行代码——
![1721641307282.png 1721641307282.png](https://bbs.pokefans.cn/data/attachments/2/2567-ccfb5790dc1391d2c57ef19b9edca334.jpg)
就是这一行代码,让百变怪的能力等级,和被变身的精灵的能力等级一样。
也就是说,能力等级相关的信息,是存储在stages里的。
所以,我们需要在这个特性发动的时候,复制一份这个精灵当前的能力等级,并且把它存储到一个变量里。
那么,是基于battle的变量,还是基于battler的变量呢?
答案是基于battle的变量,我希望你知道为什么,如果不清楚的话请去看之前的教程。
那我们就这样——
![1721641322643.png 1721641322643.png](https://bbs.pokefans.cn/data/attachments/2/2568-41424215f54f8f8a1ccd759c0fe2c4c6.jpg)
再初始化——
![1721641338210.png 1721641338210.png](https://bbs.pokefans.cn/data/attachments/2/2569-d31f3991c1de4e1557e4438047affe8d.jpg)
初始化到nil,nil就是没有,也就是说刚开始passedStages并不会存储任何东西。
我们就用passedStages来存储当这个特性发动时的当前精灵的能力等级。
接着,我们就可以直接这样写了——
![1721641349914.png 1721641349914.png](https://bbs.pokefans.cn/data/attachments/2/2570-642f23d6349855b9b4c23972f52afcdd.jpg)
首先判断passedStages是否已经有存储数据了,有的话就直接跳过;
接着出特性条;
接着将当前精灵的能力等级存储到passedStages中;
接着出现一个提示的文字;
最后特性条消失。
这样,我们就把能力等级存储方面的代码全部完成了。
这里的话需要注意一下battler.stages.clone,这里有个clone,你暂时不需要去管clone到底是什么,你只需要记住,当你想用变量存储某一个东西,而这个东西并不是单独的一个数值的话,你需要用到clone。
这主要是因为,我们前面也已经是说过了,它其实是引用,而不是真的等于,或者说赋值。
这里其实我们思考一下就能知道,能力等级,有很多能力的能力等级,它肯定是多个数,不可能是单独的一个数,比如说物攻的能力等级,特攻的能力等级,等等。
这是思考的逻辑,所以你其实并不需要真的知道stage到底存储了什么东西,你只需要知道stage存储的是哪一类东西。
到这里还没结束,现在我们只是存储了能力等级,我们还需要对新上场的精灵应用存储的能力等级。
那么在哪里应用呢?
思考一下,不难想到,只要在精灵出场时应用就好了。
所以应用的地方,应该和精灵出场时会发动的特性的Handler接入战斗系统中的地方,是一样的。
所以我们搜索一下就好了——
![1721641426398.png 1721641426398.png](https://bbs.pokefans.cn/data/attachments/2/2571-ec439e9a36385d413f5da385048ad3a5.jpg)
![1721641433137.png 1721641433137.png](https://bbs.pokefans.cn/data/attachments/2/2572-bb63ee00e717f4c052daf499ee6f3067.jpg)
就是这里,那么我们就让应用,在新上场的精灵的自身的特性发动之前应用——
![1721641448516.png 1721641448516.png](https://bbs.pokefans.cn/data/attachments/2/2573-07ce8c00bb595674004ae873344edd44.jpg)
我们新写了一个pbPassStatsStages方法来应用——
![1721641468763.png 1721641468763.png](https://bbs.pokefans.cn/data/attachments/2/2574-2b66b350a0e03207663a9d3e716316bc.jpg)
这个方法会先检查@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方法的格式。
那我们就把原本的改成这样的格式——
可以看到,同时,这个方法传递了一个参数battler,这个就不用解释了吧,因为这个方法是写在Battle里的,所以需要传递一下是battle里的哪一个battler。
![1721641518176.png 1721641518176.png](https://bbs.pokefans.cn/data/attachments/2/2575-beb170149d10c07fa658b88c7438678f.jpg)
看前面的代码我们就能知道,这里的battler就是前面的b,也就是新上场的那一个battler。
应用完能力等级之后,在这个方法的最后面,通过@passedStages = nil,清除了@passedStages里存储的数据,保证应用只会发生一次。
到这里就全部完成了,那我们就进游戏测试一下——
![1721641549636.png 1721641549636.png](https://bbs.pokefans.cn/data/attachments/2/2576-a6c49d0a00b0814971197a6a3e6b7ad2.jpg)
![1721641562113.png 1721641562113.png](https://bbs.pokefans.cn/data/attachments/2/2577-73debe0f9d57a22ec2c31a1ad9a21d95.jpg)
让皮卡丘在第一个回合使用影子分身,然后濒死,接着我们只需要看一下新上场的精灵的信息就好了。
![1721641576657.png 1721641576657.png](https://bbs.pokefans.cn/data/attachments/2/2578-eeaf53decac562e8fe7156a81fc6d8b3.jpg)
![1721641583975.png 1721641583975.png](https://bbs.pokefans.cn/data/attachments/2/2579-24decd77c7ed40dfd6ee8a71a7f9892f.jpg)
![1721641595199.png 1721641595199.png](https://bbs.pokefans.cn/data/attachments/2/2580-e457a7234e00c220becaec552cd2b237.jpg)
![1721641602720.png 1721641602720.png](https://bbs.pokefans.cn/data/attachments/2/2581-b64260903e42f6799e3eced88d010e0f.jpg)
![1721641609945.png 1721641609945.png](https://bbs.pokefans.cn/data/attachments/2/2582-97fb5ed79f705b410fc917041b5f117c.jpg)
可以看到,比比鸟接受了皮卡丘传递的能力等级。
这里还是要强调一下,目前这样的写法,并不会检查皮卡丘本身是否有能力等级变化,只要皮卡丘濒死了,这个特性就会发动。
同时,是让皮卡丘濒死之后上场的那一个精灵,接受皮卡丘的能力等级,不论新上场的精灵是我方的,还是对方的,所以,会更加有趣一点。
关于怎么让皮卡丘有能力等级变化的时候才发动这个特性,没有能力等级变化就不发动这个特性呢?
这样就好了——
关于这个额外的检查,我就不解释了。
其实,为了让你的代码更加严谨,你还应该加上,当皮卡丘后面没有任何精灵的时候,这个特性也不应该发动,因为没有精灵可以传递能力等级了——
关于这个额外的检查,我也不解释了,这些额外的检查,无非是让代码更加健壮,没有这些检查其实也并不会影响到这个特性本身的功能。
那么这期教程就到此为止。
视频预览(0722)——
浏览附件2024-07-22 21-26-48.mp4
感谢阅读。
这期教程,我们来讲解特性实例。
特别注意,在我们讲解特性实例的时候,我并不会使用伪代码。
为了能够显示中文,从这期教程开始,我已经安装了Zpix字体,当然并不是原本的Zpix,我自己已经修改过了一些东西。
那么,这期教程我们要讲的是遗志。
遗志(Passing):自身濒死时,将自身的能力等级传递给下一个登场者。
首先是PBS部分——
![1721641264810.png 1721641264810.png](https://bbs.pokefans.cn/data/attachments/2/2564-e32a626addd2b1a9c7037a0b5d325792.jpg)
接着是思考,如何才能实现我们的要求呢?
这个特性是自身濒死时发动的,所以特性Handler一定是OnSelfFainting,那么接着呢?
这个特性,其实就相当于,把一个精灵的能力等级,复制给另一个精灵。
那么思考一下,哪里有类似的呢?
其实百变怪的变身就有这个效果。
那我们就搜索一下变身——
![1721641280317.png 1721641280317.png](https://bbs.pokefans.cn/data/attachments/2/2565-f8d48d07fcd7b3f894fba0a0e502b332.jpg)
可以看出来,就是pbTransform这个方法,那我们再搜索一下这个方法——
![1721641292505.png 1721641292505.png](https://bbs.pokefans.cn/data/attachments/2/2566-20ec3e4f68c5074ec111b1ae26170448.jpg)
可以发现,我们需要的就是这一行代码——
![1721641307282.png 1721641307282.png](https://bbs.pokefans.cn/data/attachments/2/2567-ccfb5790dc1391d2c57ef19b9edca334.jpg)
就是这一行代码,让百变怪的能力等级,和被变身的精灵的能力等级一样。
也就是说,能力等级相关的信息,是存储在stages里的。
所以,我们需要在这个特性发动的时候,复制一份这个精灵当前的能力等级,并且把它存储到一个变量里。
那么,是基于battle的变量,还是基于battler的变量呢?
答案是基于battle的变量,我希望你知道为什么,如果不清楚的话请去看之前的教程。
那我们就这样——
![1721641322643.png 1721641322643.png](https://bbs.pokefans.cn/data/attachments/2/2568-41424215f54f8f8a1ccd759c0fe2c4c6.jpg)
再初始化——
![1721641338210.png 1721641338210.png](https://bbs.pokefans.cn/data/attachments/2/2569-d31f3991c1de4e1557e4438047affe8d.jpg)
初始化到nil,nil就是没有,也就是说刚开始passedStages并不会存储任何东西。
我们就用passedStages来存储当这个特性发动时的当前精灵的能力等级。
接着,我们就可以直接这样写了——
![1721641349914.png 1721641349914.png](https://bbs.pokefans.cn/data/attachments/2/2570-642f23d6349855b9b4c23972f52afcdd.jpg)
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中;
接着出现一个提示的文字;
最后特性条消失。
这样,我们就把能力等级存储方面的代码全部完成了。
这里的话需要注意一下battler.stages.clone,这里有个clone,你暂时不需要去管clone到底是什么,你只需要记住,当你想用变量存储某一个东西,而这个东西并不是单独的一个数值的话,你需要用到clone。
这主要是因为,我们前面也已经是说过了,它其实是引用,而不是真的等于,或者说赋值。
这里其实我们思考一下就能知道,能力等级,有很多能力的能力等级,它肯定是多个数,不可能是单独的一个数,比如说物攻的能力等级,特攻的能力等级,等等。
这是思考的逻辑,所以你其实并不需要真的知道stage到底存储了什么东西,你只需要知道stage存储的是哪一类东西。
到这里还没结束,现在我们只是存储了能力等级,我们还需要对新上场的精灵应用存储的能力等级。
那么在哪里应用呢?
思考一下,不难想到,只要在精灵出场时应用就好了。
所以应用的地方,应该和精灵出场时会发动的特性的Handler接入战斗系统中的地方,是一样的。
所以我们搜索一下就好了——
![1721641426398.png 1721641426398.png](https://bbs.pokefans.cn/data/attachments/2/2571-ec439e9a36385d413f5da385048ad3a5.jpg)
![1721641433137.png 1721641433137.png](https://bbs.pokefans.cn/data/attachments/2/2572-bb63ee00e717f4c052daf499ee6f3067.jpg)
就是这里,那么我们就让应用,在新上场的精灵的自身的特性发动之前应用——
![1721641448516.png 1721641448516.png](https://bbs.pokefans.cn/data/attachments/2/2573-07ce8c00bb595674004ae873344edd44.jpg)
我们新写了一个pbPassStatsStages方法来应用——
![1721641468763.png 1721641468763.png](https://bbs.pokefans.cn/data/attachments/2/2574-2b66b350a0e03207663a9d3e716316bc.jpg)
Ruby:
def pbPassStatsStages(battler)
return if !@passedStages
GameData::Stat.each_battle { |s| battler.stages[s.id] = @passedStages[s.id] }
@passedStages = nil
end
如果@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 1721641518176.png](https://bbs.pokefans.cn/data/attachments/2/2575-beb170149d10c07fa658b88c7438678f.jpg)
看前面的代码我们就能知道,这里的battler就是前面的b,也就是新上场的那一个battler。
应用完能力等级之后,在这个方法的最后面,通过@passedStages = nil,清除了@passedStages里存储的数据,保证应用只会发生一次。
到这里就全部完成了,那我们就进游戏测试一下——
![1721641549636.png 1721641549636.png](https://bbs.pokefans.cn/data/attachments/2/2576-a6c49d0a00b0814971197a6a3e6b7ad2.jpg)
![1721641562113.png 1721641562113.png](https://bbs.pokefans.cn/data/attachments/2/2577-73debe0f9d57a22ec2c31a1ad9a21d95.jpg)
让皮卡丘在第一个回合使用影子分身,然后濒死,接着我们只需要看一下新上场的精灵的信息就好了。
![1721641576657.png 1721641576657.png](https://bbs.pokefans.cn/data/attachments/2/2578-eeaf53decac562e8fe7156a81fc6d8b3.jpg)
![1721641583975.png 1721641583975.png](https://bbs.pokefans.cn/data/attachments/2/2579-24decd77c7ed40dfd6ee8a71a7f9892f.jpg)
![1721641595199.png 1721641595199.png](https://bbs.pokefans.cn/data/attachments/2/2580-e457a7234e00c220becaec552cd2b237.jpg)
![1721641602720.png 1721641602720.png](https://bbs.pokefans.cn/data/attachments/2/2581-b64260903e42f6799e3eced88d010e0f.jpg)
![1721641609945.png 1721641609945.png](https://bbs.pokefans.cn/data/attachments/2/2582-97fb5ed79f705b410fc917041b5f117c.jpg)
可以看到,比比鸟接受了皮卡丘传递的能力等级。
这里还是要强调一下,目前这样的写法,并不会检查皮卡丘本身是否有能力等级变化,只要皮卡丘濒死了,这个特性就会发动。
同时,是让皮卡丘濒死之后上场的那一个精灵,接受皮卡丘的能力等级,不论新上场的精灵是我方的,还是对方的,所以,会更加有趣一点。
关于怎么让皮卡丘有能力等级变化的时候才发动这个特性,没有能力等级变化就不发动这个特性呢?
这样就好了——
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
感谢阅读。
最后编辑: