• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

[Scripting Question] Custom Moves Assistance

  • 37
    Posts
    8
    Years
    • Seen Jan 21, 2021
    I'm trying to implement these moves; the first should raise the user's side Attack while lowering the opponents side. Currently it works for everything except the partner's Atk.
    Code:
    #===============================================================================
    # Victory Cry - raises Atk, lower foe's Atk
    #===============================================================================
    class PokeBattle_Move_304 < PokeBattle_TargetStatDownMove
      def initialize(battle,move)
        super
        @statDown = [PBStats::ATTACK,1]
      end
    
      def pbEffectGeneral(user)
        if user.pbCanRaiseStatStage?(PBStats::ATTACK,user,self)
          user.pbRaiseStatStage(PBStats::ATTACK,1,user)
        end
        showAnim = true
      end
    end

    The next one sacrifices 1/3 of the user's max Hp to heal the target by that same amount (like Wish does). The trouble is Wish has it's own weird mechanics where it affects the same battle.position rather than a target, as seen here:

    Spoiler:


    This is what I have so far (still need the proportional aspect):
    Code:
    #===============================================================================
    # Self Sacrifice - Heals target by 2/3 of its max HP, giving 1/3 of its own. 
    #===============================================================================
    class PokeBattle_Move_305 < PokeBattle_Move
      def healingMove?; return true; end
    
      def pbFailsAgainstTarget?(user,target)
        if target.hp==target.totalhp
          @battle.pbDisplay(_INTL("{1}'s HP is full!",target.pbThis))
          return true
        elsif !target.canHeal?
          @battle.pbDisplay(_INTL("{1} is unaffected!",target.pbThis))
          return true
        end
        return false
      end
    
      def pbEffectAgainstTarget(user,target)
        hpGain = (target.totalhp/1.5).round
        user.pbReduceHP(user.totalhp/3,false)
        user.pbItemHPHealCheck
        target.pbRecoverHP(hpGain)
        @battle.pbDisplay(_INTL("{1}'s HP was restored.",target.pbThis))
      end
    end

    The third move shouldn't be too hard; not sure what the issue is (t still works on sleeping foes). I just copied the section from Dream Eater for the second part. Does it have anything to do with also being a TargetStatDownMove?
    Code:
    #===============================================================================
    #  Blinding Beacon-  (may lower acc, no effect on sleeping foes (eyes closed)
    #===============================================================================
    class PokeBattle_Move_306 < PokeBattle_TargetStatDownMove
      def initialize(battle,move)
        super
        @statDown = [PBStats::ACCURACY,1]
      end
      
      def pbFailsAgainstTarget?(user,target)
        if !target.asleep?
          @battle.pbDisplay(_INTL("{1} wasn't affected!",target.pbThis))
          return true
        end
        return false
      end
    end

    Finally, and I'm pretty sure this one is a mess, I'm trying to script a move that affects all battlers and increases the Hp of Light types by 1/3 while decreasing the Hp of Dark and Ghost types by 1/3:
    Spoiler:


    I get this error when using it (and the Pokemon keeps trying to use the move after each identical error rather than the game shutting down)
    Spoiler:


    Any assistance is much appreciated.
     
    For Victory Cry, the code inside "pbEffectGeneral" is only affecting the user right now. To affect its allies, you can add the following code in between your current code:
    Code:
    if user.pbCanRaiseStatStage?(PBStats::ATTACK,user,self)
      user.pbRaiseStatStage(PBStats::ATTACK,1,user)
    end
    # Add this code in between
    user.eachAlly do |b|
      if b.pbCanRaiseStatStage?(PBStats::ATTACK,user,self)
        b.pbRaiseStatStage(PBStats::ATTACK,1,user)
      end
    end
    # End of addition
    showAnim = true

    For Self Sacrifice, I think the mechanics look right. The "hpGain" line can be changed to the following:
    Code:
    hpGain = user.totalhp/3

    For Blinding Beacon, look at what "pbFailsAgainstTarget?" does. It returns true if the move should fail. As you stated, you want the move to have no effect on sleeping foes. In other words, it should be checking if the target IS asleep, not if it isn't asleep:
    Code:
    if target.asleep?

    For Starlight, the function "pbHasType?" does not accept more than one argument, so you have to check for each type separately. Also, why have you split "pbEffectAgainstTarget" into two separate definitions? It doesn't do what you think it does - it will actually overwrite the first definition with the second, meaning it will only harm Dark and Ghost types. In that same function, you are healing "target" and harming "user", but those stay constant for the entire move. You're supposed to affect "b" instead - that refers to the battler that the "eachBattler" loop is currently on. Try this:
    Code:
    #===============================================================================
    # Starlight - increases Hp of Light Types and decreases Hp of Dark & Ghost Types by 1/3
    #===============================================================================
    class PokeBattle_Move_307 < PokeBattle_Move
      def pbMoveFailed?(user,targets)
        @validTargets = []
        @battle.eachBattler do |b|
          next if !b.pbHasType?(:LIGHT) && !b.pbHasType?(:DARK) && !b.pbHasType?(:GHOST)
          next if b.semiInvulnerable?
          @validTargets.push(b.index)
        end
        if @validTargets.length==0
          @battle.pbDisplay(_INTL("But it failed!"))
          return true
        end
        return false
      end
    
      def pbFailsAgainstTarget?(user,target)
        return false if @validTargets.include?(target.index)
        return true if !target.pbHasType?(:LIGHT) && !target.pbHasType?(:DARK) && !target.pbHasType?(:GHOST)
        return target.semiInvulnerable?
      end
    
      def pbEffectAgainstTarget(user,target)
        @battle.eachBattler do |b|
          next if !b.pbHasType?(:LIGHT) || b.semiInvulnerable?
          hpGain = (b.totalhp/1.5).round
          b.pbRecoverHP(hpGain)
          @battle.pbDisplay(_INTL("{1}'s HP was restored.",b.pbThis))
        end
        @battle.eachBattler do |b|
          next if !b.pbHasType?(:DARK) && !b.pbHasType?(:GHOST)
          next if b.semiInvulnerable?
          b.pbReduceHP(b.totalhp/3,false)
          b.pbItemHPHealCheck
        end
      end
    end
     
    For Starlight, the function "pbHasType?" does not accept more than one argument, so you have to check for each type separately. Also, why have you split "pbEffectAgainstTarget" into two separate definitions? It doesn't do what you think it does - it will actually overwrite the first definition with the second, meaning it will only harm Dark and Ghost types. In that same function, you are healing "target" and harming "user", but those stay constant for the entire move. You're supposed to affect "b" instead - that refers to the battler that the "eachBattler" loop is currently on. Try this:
    Code:
    #===============================================================================
    # Starlight - increases Hp of Light Types and decreases Hp of Dark & Ghost Types by 1/3
    #===============================================================================
    class PokeBattle_Move_307 < PokeBattle_Move
      def pbMoveFailed?(user,targets)
        @validTargets = []
        @battle.eachBattler do |b|
          next if !b.pbHasType?(:LIGHT) && !b.pbHasType?(:DARK) && !b.pbHasType?(:GHOST)
          next if b.semiInvulnerable?
          @validTargets.push(b.index)
        end
        if @validTargets.length==0
          @battle.pbDisplay(_INTL("But it failed!"))
          return true
        end
        return false
      end
    
      def pbFailsAgainstTarget?(user,target)
        return false if @validTargets.include?(target.index)
        return true if !target.pbHasType?(:LIGHT) && !target.pbHasType?(:DARK) && !target.pbHasType?(:GHOST)
        return target.semiInvulnerable?
      end
    
      def pbEffectAgainstTarget(user,target)
        @battle.eachBattler do |b|
          next if !b.pbHasType?(:LIGHT) || b.semiInvulnerable?
          hpGain = (b.totalhp/1.5).round
          b.pbRecoverHP(hpGain)
          @battle.pbDisplay(_INTL("{1}'s HP was restored.",b.pbThis))
        end
        @battle.eachBattler do |b|
          next if !b.pbHasType?(:DARK) && !b.pbHasType?(:GHOST)
          next if b.semiInvulnerable?
          b.pbReduceHP(b.totalhp/3,false)
          b.pbItemHPHealCheck
        end
      end
    end

    Thank you so much Netto; everything worked perfectly except for with Starlight - the move does both effects for every Light, Dark or Ghost type on the field. So it works properly with only one or the other, but with e.g. a Light type fighting a Dark type when used it will heal the user and damage the target, and then do the same thing again. This occurs even when fighting Sableye (rather than any more times). I tried rearranging a few things but only made things worse so far. Not sure if it would help but is there a way to script an "or" function as opposed to && being an "and"? Or do I need to do the ! for the opposite effect for each @battle.eachBattler do |b|?
     
    Thank you so much Netto; everything worked perfectly except for with Starlight - the move does both effects for every Light, Dark or Ghost type on the field. So it works properly with only one or the other, but with e.g. a Light type fighting a Dark type when used it will heal the user and damage the target, and then do the same thing again. This occurs even when fighting Sableye (rather than any more times). I tried rearranging a few things but only made things worse so far. Not sure if it would help but is there a way to script an "or" function as opposed to && being an "and"? Or do I need to do the ! for the opposite effect for each @battle.eachBattler do |b|?

    Regarding your last question, || means "or", but I'm not really sure what you're suggesting otherwise. In your moves PBS, have you defined Starlight as affecting all targets, or multiple targets? If so, then what's happening is that for each target that the move affects, it runs the code under "pbEffectAgainstTarget", which itself heals all Light types and harms Dark and Ghost types. I think instead of making use of "pbEffectAgainstTarget", which runs once for every target on the field, you can try to use "pbEffectGeneral", which only runs once entirely. In other words, replace:
    Code:
    def pbEffectAgainstTarget(user,target)
    with:
    Code:
    def pbEffectGeneral(user)
     
    Regarding your last question, || means "or", but I'm not really sure what you're suggesting otherwise. In your moves PBS, have you defined Starlight as affecting all targets, or multiple targets? If so, then what's happening is that for each target that the move affects, it runs the code under "pbEffectAgainstTarget", which itself heals all Light types and harms Dark and Ghost types. I think instead of making use of "pbEffectAgainstTarget", which runs once for every target on the field, you can try to use "pbEffectGeneral", which only runs once entirely. In other words, replace:
    Code:
    def pbEffectAgainstTarget(user,target)
    with:
    Code:
    def pbEffectGeneral(user)

    I had it defined as AllBattlers in the PBS, yes, but the change you suggested seems to have fixed everything. Thanks again and I hope you have an excellent Christmas!
     
    Back
    Top