○ ESS20仅限 【特性】添加几个特性的教程

本帖是网友@w15174289601 提问,由于问题较多,在原帖回复不方便,故单独开一帖。
这七个特性除了第5个之外,我都写出来了,不过我写的并不一定就好,如有错误还请批评指正。

(希望大家在询问怎么添加特性的时候,也能够像这样尽量详细的描述出来。)
1693111276163.png

首先是PBS,在PBS/abilities.txt的最下方粘贴。
代码:
#-------------------------------
[ENHANCEDREBIRTH]
Name = 磐涅
Description = 每场战斗首次倒下时以最大HP 的50%复活,并提高特攻和速度。
#-------------------------------
[PPSAVE]
Name = 节省
Description = 使用招式时有30%的概率 不消耗PP值。
#-------------------------------
[ENERGYABSORB]
Name = 能量吸收
Description = 受到特殊招式攻击时不会受 到伤害,而是大幅提高特攻。
#-------------------------------
[LIFEREGENATION]
Name = 生命再生
Description = 每回合结束时回复 自身最大HP的16%。
#-------------------------------
[GRATEFULHEART]
Name = 感恩的决心
Description = 出场时,与训练家的亲密度 越高,越容易提高能力。
#-------------------------------
[PREDATION]
Name = 掠食
Description = 打倒对手时, 回复自身最大HP的20%。
 
最后编辑:

ES泽洛

世末鸽者
管理员
元老
2022-08-04
227
14
287
2,116
23
安徽
www.esplus.club

脚本部分

1.磐涅(这是代码最多的一个)

Battle的第90行附近粘贴
Ruby:
attr_reader   :enhancedRebirth  #磐涅
1693111928186.png
Battle的第159行附近粘贴
Ruby:
@enhancedRebirth   = [Array.new(@party1.length, false), Array.new(@party2.length, false)]
1693111905982.png
Battle_Battler的685行附近粘贴
Ruby:
  def reborn?
    return @battle.enhancedRebirth[@index & 1][@pokemonIndex]
  end
  def setReborn
    @battle.enhancedRebirth[@index & 1][@pokemonIndex] = true
  end
1693111995097.png
Battle_Scene_Animations的685行附近粘贴
Ruby:
#===============================================================================
# Shows a Pokémon reboring  复活
#===============================================================================
class Battle::Scene::Animation::BattlerReborn1 < Battle::Scene::Animation
  def initialize(sprites,viewport,idxBattler,battle)
    @idxBattler = idxBattler
    @battle     = battle
    super(sprites,viewport)
  end

  def createProcesses
    batSprite = @sprites["pokemon_#{@idxBattler}"]
    shaSprite = @sprites["shadow_#{@idxBattler}"]
    # Set up battler/shadow sprite
    battler = addSprite(batSprite,PictureOrigin::BOTTOM)
    shadow  = addSprite(shaSprite,PictureOrigin::CENTER)
    # Animation
    # Play cry
    delay = 10
    cry = GameData::Species.cry_filename_from_pokemon(batSprite.pkmn, "_faint")
    if cry   # Play a specific faint cry
      battler.setSE(0, cry)
      delay = (GameData::Species.cry_length(batSprite.pkmn, nil, nil, "_faint") * 20).ceil
    else
      cry = GameData::Species.cry_filename_from_pokemon(batSprite.pkmn)
      if cry   # Play the regular cry at a lower pitch (75)
        battler.setSE(0, cry, nil, 75)
        delay = (GameData::Species.cry_length(batSprite.pkmn, nil, 75) * 20).ceil
      end
    end
    shadow.setVisible(0,false)
    battler.setSE(delay,"Pkmn faint")
    16.times do
      batSprite.opacity -= 16
      pbWait(2)
    end
    batSprite.opacity = 0
    battler.setVisible(delay,false)
  end
end

class Battle::Scene::Animation::BattlerReborn2 < Battle::Scene::Animation
  def initialize(sprites,viewport,idxBattler,battle)
    @idxBattler = idxBattler
    @battle     = battle
    super(sprites,viewport)
  end

  def createProcesses
    batSprite = @sprites["pokemon_#{@idxBattler}"]
    shaSprite = @sprites["shadow_#{@idxBattler}"]
    battler = addSprite(batSprite,PictureOrigin::BOTTOM)
    shadow  = addSprite(shaSprite,PictureOrigin::CENTER)
    delay = 10
    cry = GameData::Species.cry_filename_from_pokemon(batSprite.pkmn)
    if cry   # Play a specific faint cry
      battler.setSE(0, cry)
      delay = (GameData::Species.cry_length(batSprite.pkmn) * 20).ceil
    else
      cry = GameData::Species.cry_filename_from_pokemon(batSprite.pkmn)
      if cry   # Play the regular cry at a lower pitch (75)
        battler.setSE(0, cry, nil, 75)
        delay = (GameData::Species.cry_length(batSprite.pkmn, nil, 75) * 20).ceil
      end
    end
    battler.setVisible(0,true)
    batSprite.opacity = 0
    16.times do
      batSprite.opacity += 16
      batSprite.color.set(batSprite.opacity,0,0,128)
      pbWait(2)
    end
    batSprite.opacity = 255
    battler.setSE(0,cry,nil,60) if cry
    shadow.setVisible(0,true)
  end
end
1693112588792.png
Scene_PlayAnimations的第330行附近粘贴
Ruby:
 #=============================================================================
  # Animates a Pokémon reborn
  #=============================================================================
  def pbReborn1Battler(battler)
    @briefMessage = false
    rebornAnim   = Animation::BattlerReborn1.new(@sprites, @viewport, battler.index, @battle)
    dataBoxAnim = Animation::DataBoxDisappear.new(@sprites, @viewport, battler.index)
    loop do
      rebornAnim.update
      dataBoxAnim.update
      pbUpdate
      break if rebornAnim.animDone? && dataBoxAnim.animDone?
    end
    rebornAnim.dispose
    dataBoxAnim.dispose
  end

  def pbReborn2Battler(battler)
    @briefMessage = false
    rebornAnim   = Animation::BattlerReborn2.new(@sprites,@viewport,battler.index,@battle)
    dataBoxAnim = Animation::DataBoxAppear.new(@sprites, @viewport, battler.index)
    loop do
      rebornAnim.update
      dataBoxAnim.update
      pbUpdate
      break if rebornAnim.animDone? && dataBoxAnim.animDone?
    end
    rebornAnim.dispose
    dataBoxAnim.dispose
  end
1693112367014.png
Battle_AbilityEffects的最下方粘贴
Ruby:
#磐涅
Battle::AbilityEffects::OnBeingHit.add(:ENHANCEDREBIRTH,
  proc { |ability, user, target, move, battle|
    next if !target.fainted?
    next if target.reborn?
    if !battle.moldBreaker
      target.setReborn
      battle.scene.pbReborn1Battler(target)
      battle.pbDisplayPaused(_INTL("{1}倒下了...?", target.pbThis))
      pbWait(20)
      
      battle.pbShowAbilitySplash(target)
      battle.scene.pbReborn2Battler(target)
      
      target.pbRecoverHP(target.totalhp / 2, false)
      target.pbCureStatus(false)
      target.pbCureConfusion
      
      battle.pbDisplay(_INTL("<c=FF0000FF>{1}从濒死中复活了!</c>", target.pbThis))
      target.pbRaiseStatStage(:SPECIAL_ATTACK, 1, target)
      target.pbRaiseStatStage(:SPEED, 1, target)
      
      battle.pbHideAbilitySplash(target)
    end
  }
)
1693112193070.png

2.节省

Battler_UseMove的第254行附近粘贴
Ruby:
pp_save = move.pp + 1 if user.hasActiveAbility?(:PPSAVE)  # 节省
Battler_UseMove的第270行附近粘贴
Ruby:
    # 节省
    if user.hasActiveAbility?(:PPSAVE) && rand(100) < 30
      user.pbSetPP(move, pp_save)
    end
1693113120674.png

3.能量吸收

Battle_AbilityEffects的最下方粘贴
Ruby:
#能量吸收
Battle::AbilityEffects::MoveImmunity.add(:ENERGYABSORB,
  proc { |ability, user, target, move, type, battle, show_message|
    next false if user.index == target.index
    next false if !move.specialMove?
    if show_message
      battle.pbShowAbilitySplash(target)
      if target.pbCanRaiseStatStage?(:SPECIAL_ATTACK, target)
        target.pbRaiseStatStage(:SPECIAL_ATTACK, 2, target)
      elsif Battle::Scene::USE_ABILITY_SPLASH
        battle.pbDisplay(_INTL("这对{1}没有效果...", target.pbThis))
      else
        battle.pbDisplay(_INTL("{1}的{2}使{3}无效化了!", target.pbThis, target.abilityName, move.name))
      end
      battle.pbHideAbilitySplash(target)
    end
    next true
  }
)
1693112251057.png

4.生命再生

Battle_AbilityEffects的最下方粘贴
Ruby:
#生命再生
Battle::AbilityEffects::EndOfRoundEffect.add(:LIFEREGENATION,
  proc { |ability, battler, battle|
    next if !battler.canHeal?
    battle.pbShowAbilitySplash(battler)
    battler.pbRecoverHP(battler.totalhp / 100 * 16)
    if Battle::Scene::USE_ABILITY_SPLASH
      battle.pbDisplay(_INTL("{1}的HP回复了!", battler.pbThis))
    else
      battle.pbDisplay(_INTL("{1}的{2}回复了它的HP。", battler.pbThis, battler.abilityName))
    end
    battle.pbHideAbilitySplash(battler)
  }
)
1693113205511.png

5.感恩的决心

Battle_AbilityEffects的最下方粘贴
Ruby:
#感恩的决心
Battle::AbilityEffects::OnSwitchIn.add(:GRATEFULHEART,
  proc { |ability, battler, battle, switch_in|
    happiness = battler.happiness
    next if happiness < 155
    battle.pbShowAbilitySplash(battler)
    if happiness == 255
      stats = [:ATTACK, :DEFENSE, :SPECIAL_ATTACK, :SPECIAL_DEFENSE, :SPEED]
      randUp = stats.shuffle.slice(0, 3)
      randUp.each do |stat|
        battler.pbRaiseStatStage(stat, 1, battler)
      end
    elsif happiness >= 200
      stats = [:ATTACK, :DEFENSE, :SPECIAL_ATTACK, :SPECIAL_DEFENSE]
      randUp = stats.shuffle.slice(0, 2)
      randUp.each do |stat|
        battler.pbRaiseStatStage(stat, 1, battler)
      end
    else
      randUp = [:DEFENSE, :SPECIAL_DEFENSE]
      stat = randUp[rand(randUp.length)]
      battler.pbRaiseStatStage(stat, 1, battler)
    end
    battle.pbHideAbilitySplash(battler)
  }
)
1693113279250.png

6.掠食

Battle_AbilityEffects的最下方粘贴
Ruby:
#掠食
Battle::AbilityEffects::OnEndOfUsingMove.add(:PREDATION,
  proc { |ability, user, targets, move, battle|
    next if !user.canHeal?
    next if battle.pbAllFainted?(user.idxOpposingSide)
    numFainted = 0
    targets.each { |b|
      numFainted += 1 if b.damageState.fainted
    }
    next if numFainted == 0
    battle.pbShowAbilitySplash(user)
    user.pbRecoverHP(user.totalhp / 5 * numFainted)
    battle.pbHideAbilitySplash(user)
  }
)

如果只是想实现这些效果,看到这里跟着操作就可以了,下面会逐个展开讲解。
 

ES泽洛

世末鸽者
管理员
元老
2022-08-04
227
14
287
2,116
23
安徽
www.esplus.club

讲解

建议开两个网页标签或者分屏两个浏览器软件,同时打开本帖,左右对照着看。

1.磐涅

每场战斗首次倒下时以最大HP 的50%复活,并提高特攻和速度。​

Battle的第90行附近粘贴的这一行,是新增一个名字叫enhancedRebirth的属性。
Battle的第159行附近粘贴的这一行,是为前面的属性开辟一片数组空间。
Battle_Battler的685行附近粘贴的这一段,是两个函数,def reborn?用于判断宝可梦是否已经复活过了,另一个def setReborn用于设置宝可梦已复活。

一开始我是打算用PBEffects做的,但是这样下场再上场状态就会重置,可以继续触发特性,所以不行,用这个属性就可以实现一次战斗只触发一次,下场再上场不会重置。
Battle_Scene_Animations的685行附近粘贴的这一大段,是写倒下和复活的2段动画效果的类。
Scene_PlayAnimations的第330行附近粘贴的这一大段,是写两个函数,分别创建上面类的对象,并调用对象的动画效果函数,播放这些动画。

Battle_AbilityEffects的最下方粘贴的这一段,才是真正的特性触发时执行的代码,上面做的那么多,都是准备工作,不做行吗?不行。
那么这一段,别的不管,看add。add是什么意思?添加。左边一长串管它是牛是马阿猫阿狗,反正add,就是把我们自己写的特性添加到里面呗。具体什么意思呢?就是把自己写的磐涅特性,添加到“战斗 特性效果 受到攻击时”这个类里面,说人话就是:这个特性会在受到攻击时触发。
proc这一行,user是打人的人,target是被打的人,被打死复活,所以这个特性应该作用于target。
next,下一个,如果目标没有倒下。意思就是被打的人没有被打死,那就跳过,下面的代码不会执行。
next,下一个,如果目标已经复活过了,那么OK抱歉你不能再复活了,跳过。
下面if判断,如果攻击方没有破格之类的特性,那么你这个复活特性才能触发,不然不好意思,拿捏。
好,如果一切顺利,就能进到if里面,先设为已复活,然后播放倒下消失的动画,然后给个文本提示,等待20帧。然后播放目标的特性条动画,再播放复活出现的动画。然后回一半血、治疗异常状态一通操作,你以为我倒下了,其实我没有,这还不算完,我还要提高特攻、速度,最后隐藏特性条动画,结束。
1693117934019.png
 
最后编辑:

ES泽洛

世末鸽者
管理员
元老
2022-08-04
227
14
287
2,116
23
安徽
www.esplus.club

2.节省

使用招式时有30%的概率 不消耗PP值。​

Battler_UseMove的第254行附近粘贴的这一行,就是先临时存一下招式剩余的PP,至于为什么要+1,因为不加会是扣过PP后剩余的,究竟是为什么,咱也不知道,咱也不敢问,总之这样没问题。
Battler_UseMove的第270行附近粘贴的这一段,就是判断两个条件,一是招式使用者有没有可以生效的节省特性,你特性不是节省或者你节省特性被ban掉了那肯定就不行,二是在0~99这一百个数字(取到0取不到100)中随机看结果是不是小于30(0~29三十个数字),说人话就是随机30%概率。
如果两个条件都满足,那么就把之前临时存的PP再赋值回去。
扣没扣?扣了,但是我又加回去了,相当于没扣,如扣。
 

ES泽洛

世末鸽者
管理员
元老
2022-08-04
227
14
287
2,116
23
安徽
www.esplus.club

3.能量吸收

受到特殊招式攻击时不会受 到伤害,而是大幅提高特攻。​

Battle_AbilityEffects的最下方粘贴的这一段,诶就只有这一段,比前面几个简单多了。
根据我们在第一个特性讲解里知道的,这里就是把我们的特性添加到招式免疫时触发的特性效果里面去。
proc这一行就不讲了,直接看下面。
下一个,假,如果使用者位置等于目标位置。意思就是,自己打自己不会触发这个特性,并且还要给一个结果“假”,告诉别的地方的程序,招式没有被免疫。
下一个,假,如果招式不是特殊招式。同上。
show_message不用管,正常应该肯定会进这个if。
先显示目标的特性条动画,然后判断,目标的特攻还能不能提高?能提高就提高,不能提高就只提示没有效果,下面那个elsif也不用管,然后隐藏目标的特性条动画。
最后next true告诉别的地方的程序,招式真的被免疫了。
 

ES泽洛

世末鸽者
管理员
元老
2022-08-04
227
14
287
2,116
23
安徽
www.esplus.club

4.生命再生

每回合结束时回复 自身最大HP的16%。​

Battle_AbilityEffects的最下方粘贴的这一段,依然和上面的差不多。
EndOfRoundEffect就是回合结束时触发特性效果。
下一个,如果不能回复,比如说本来就是满血,或者被下了回复禁止,那就跳过,下面代码不触发。
一切顺利就向下执行,显示自己的特性条动画,给自己回血,再给个提示文本,隐藏特性条动画,结束,so easy~
 

ES泽洛

世末鸽者
管理员
元老
2022-08-04
227
14
287
2,116
23
安徽
www.esplus.club

5.感恩的决心

出场时,与训练家的亲密度 越高,越容易提高能力。​

Battle_AbilityEffects的最下方粘贴的这一段,OnSwitchIn是入场时触发的特性。
先获取自己的亲密度,赋值给一个临时变量。
根据原帖的描述,亲密度低于155时没有效果,所以这里直接next。
然后若顺利则显示自己的特性条动画,接着分别判断不同情况。

当亲密度等于255时,随机攻击,防御,特攻,特防,速度其中的三项提升1级。
好嘛,随机,是最烦人的东西,写的不好就成屎山代码了,也不知道我这个屎山不屎山。
先写一个数组stats用于存放攻击,防御,特攻,特防,速度,然后对数组进行shuffle操作,什么意思?就是洗牌(随机排序),当然也可以记成“舒服了”,随你。随机排序之后,再截取前3个元素作为子数组randUp。
之后遍历这个randUp数组,什么叫遍历?就是里面的东西有一个算一个,全都叫上。这3项能力每项都提高一级。

当亲密度大于等于200时,随机攻击,防御,特攻,特防其中的两项提升1级。
一样的,写一个数组stats存放攻击,防御,特攻,特防,然后舒服了,截取前2个元素,再遍历,再提高一级。
诶?只要判断大于200不用判断小于255吗?不用,因为亲密度不会超过255,而等于255时就进了上面的if,不会执行到下面的elsif。

当亲密度大于等于155时,随机提升防御或特防1级。
最后else,上面都不满足,隐含的条件就是155~199之间,这个就不用舒服了,两个里面随便抽一个还不好抽,我这个写法也不唯一,既然上面用数组了,那我这里也用数组。
最后隐藏特性条动画,结束。
 
最后编辑:
  • 支持
反馈: LQWU

ES泽洛

世末鸽者
管理员
元老
2022-08-04
227
14
287
2,116
23
安徽
www.esplus.club

6.掠食

打倒对手时, 回复自身最大HP的20%。​

Battle_AbilityEffects的最下方粘贴的这一段,是在使用完招式时触发的特性效果。
下一个,如果不能回复,那就跳过,下面代码不触发。
下一个,如果对方全队都死完了,战斗结束,也不触发,比如如果对方只有1只宝可梦,那么就没法触发。
写一个变量,初始值为0,用于统计这回合、这次招式、这一下打死了几个对手,打死一个变量+1。
然后回血,打死一个回自身最大HP的20%,打死两个就40%。
然后就是显示、隐藏特性条和回血操作,结束。

1693121809338.png
 
  • 支持
反馈: LQWU

ES泽洛

世末鸽者
管理员
元老
2022-08-04
227
14
287
2,116
23
安徽
www.esplus.club
楼主你好,我也点也不懂编程相关的东西,看了大半个小时,总算是大概顺下来了,楼主实在是太厉害了,有个问题想要请教您。
OnBeingHit是受到攻击就会触发,想知道这个“Hit”是否包含天气中毒岩钉等等的这些“非直接的技能攻击伤害”所导致的fainted?
不包括
 

在线成员

现在没有会员在线。

论坛统计

主题
342
消息
1,571
会员
2,325
最新会员
风见幽香

关于我们

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