• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • 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] Move that changes type based on the opponent's type weaknesses?

OverusedNameHere

Head Dev - Pokémon Throne
  • 23
    Posts
    5
    Years
    Does anyone know how to make a move that changes its type based on what the foe is weaker to? I'm trying to fix up Flying Press to change it from having horrible coverage and high base power to a move that is either Fighting-type or Flying-type, depending on which the opponent is weaker to. I'm fairly new to coding, so any help really is appreciated. Here is my current code for Flying Press:

    Code:
    class PokeBattle_Move_144 < PokeBattle_Move
      def tramplesMinimize?(param=1)
        return true if param==1 && Settings::MECHANICS_GENERATION >= 6   # Perfect accuracy
        return true if param==2   # Double damage
        return super
      end
    
      def pbCalcTypeModSingle(moveType,defType,user,target)
        targetTypes = target.pbTypes(true)
        type1 = targetTypes[0]
        type2 = targetTypes[1] || type1
        type3 = targetTypes[2] || type2
        flyingEff = 0
        #Calc flying-type effectiveness
        attack_type = :FLYING
        if Effectiveness.not_very_effective_type?(attack_type,type1,type2,type3)
          flyingEff += 1
        end
        if Effectiveness.normal_type?(attack_type,type1,type2,type3)
          flyingEff += 1
        end
        if Effectiveness.super_effective_type?(attack_type,type1,type2,type3)
          flyingEff = 4
        end
        #Turns flying-type based on effectiveness of fighting-type
        attack_type = :FIGHTING
        #Opponent is ineffected by the Fighting-type
        if Effectiveness.ineffective_type?(attack_type,type1,type2,type3) && flyingEff >= 1
          @battle.pbDisplay(_INTL("{1}'s Flying Press became Flying-type!",user.pbThis))
          moveType = :FLYING if GameData::Type.exists?(:FLYING)
        else
          #Opponent is resistant to the Fighting-type
          if Effectiveness.not_very_effective_type?(attack_type,type1,type2,type3) && flyingEff >= 2
            @battle.pbDisplay(_INTL("{1}'s Flying Press became Flying-type!",user.pbThis))
            moveType = :FLYING if GameData::Type.exists?(:FLYING)
          else
            #Opponent is normally affected by the Fighting-type
            if Effectiveness.normal_type?(attack_type,type1,type2,type3) && flyingEff == 4
              @battle.pbDisplay(_INTL("{1}'s Flying Press became Flying-type!",user.pbThis))
              moveType = :FLYING if GameData::Type.exists?(:FLYING)
            end
          end
        end
      end
    end

    As such with my little knowledge of Ruby, when the move is selected in battle, I get the following error:

    [Pokémon Essentials version 19.1]
    [Generation 8 Project v1.1.0]
    [v19.1 Hotfixes 1.0.7]
    [EBDX v1.2.3]

    Exception: TypeError
    Message: nil can't be coerced into Integer

    Backtrace:
    163:Move_Usage_Calculations:85:in `*'
    163:Move_Usage_Calculations:85:in `block in pbCalcTypeMod'
    163:Move_Usage_Calculations:85:in `each'
    163:Move_Usage_Calculations:85:in `pbCalcTypeMod'
    157:Battler_UseMove_SuccessChecks:308:in `pbSuccessCheckAgainstTarget'
    155:Battler_UseMove:406:in `block in pbUseMove'
    155:Battler_UseMove:403:in `each'
    155:Battler_UseMove:403:in `pbUseMove'
    [Elite Battle: DX] Scripted Battles.rb:65:in `pbUseMove'
    155:Battler_UseMove:60:in `block in pbProcessTurn'

    I have zero clue what the issue is and have been going at this, trial and error, for hours. Again, any help is appreciated. (And for those who care, Hawlucha is a monster so I'd be nerfing the BP back down to 80 should this become working)
     
    The error comes from the fact that you don't return something at the end of the pbCalcTypeModSingle function; you are supposed to return the computed effectiveness, which you don't compute here.

    So, concerning your issue, I wouldn't change this function.

    Now, I don't use v19, so I'm not sure how to write it, but here is my idea.
    Erase this function "pbCalcTypeModSingle". What you want to do is compute the type of the move, based on the greatest effectiveness to a target. So, you want to compute the type effectiveness of Flying-type on the target on the one side, and Fighting-type on the target on the other side. Then you compare both, and whichever effectiveness is higher changes the type of the move.
    Now, there are not many moves that change types, and there are no moves that change types based on the target. However, there is Shell Side Arm, which changes category based on the target. So whichever function Sheel Side Arm uses to change its properties, could be used for Flying Press.
    It turns out that the category of Shell Side Arm is computed in the function:
    Code:
      def pbOnStartUse(user,targets)

    Here is a draft, it's probably not v19-compatible though.

    Code:
      def pbOnStartUse(user,targets)
        # Beware: here, "targets" is a list of targets. 
        # For Flying Press, this list will contain only one element though.
        
        # First step: compute both effectivenesses.
        flyingEff = pbCalcTypeMod(:FLYING,user,targets[0])
        fightingEff = pbCalcTypeMod(:FIGHTING,user,targets[0])
        
        # Second step: choose the best type.
        if flyingEff < fightingEff 
          @type = :FIGHTING
        else 
          # If flyingEff == fightingEff then keep the Flying-type.
          @type = :FLYING
        end 
      end
     
    Alright, so I did what you put, but it made the move always normally effective, no matter the opponent. So I fixed it up a little and it looks like this now:

    Code:
      def pbOnStartUse(user,targets)
        # First step: compute both effectivenesses.
        flyingEff = pbCalcTypeMod(:FLYING,user,targets[0])
        fightingEff = pbCalcTypeMod(:FIGHTING,user,targets[0])
        
        # Second step: choose the best type.
        if flyingEff < fightingEff 
          @type = :FIGHTING
          user.effects[PBEffects::FlyingPress] = 0
          @battle.pbDisplay(_INTL("Flying Press became Fighting-type!")) #Testing purposes
        else 
          # If flyingEff == fightingEff then keep the Flying-type.
          @type = :FLYING
          user.effects[PBEffects::FlyingPress] = 1
          @battle.pbDisplay(_INTL("Flying Press became Flying-type!")) #Testing purposes
        end 
      end
      
      def pbCalcTypeMod(moveType,user,target)
        if user.effects[PBEffects::FlyingPress] == 1
          moveType = :FLYING
        else
          moveType = :FIGHTING
        end
        tTypes = target.pbTypes(true)
        typeMods = [Effectiveness::NORMAL_EFFECTIVE_ONE] * 3   # 3 types max
          tTypes.each_with_index do |type,i|
            typeMods[i] = pbCalcTypeModSingle(moveType,type,user,target)
          end
        ret = 1
        typeMods.each { |m| ret *= m }
        return ret
      end
    I created an effect called ":FlyingPress" as seen above to let pbCalcTypeMod read which type is stronger, 1 if Flying and 0 if Fighting.

    So with this the move handles effectiveness as normal, but the issue now is that the move doesn't choose the stronger typing. I tested this against a few Steel types (my type effectivenesses are the same as base essentials here). Flying Press always became a Flying move :/
     
    Really, you don't need to rewrite "pbCalcTypeMod". The code inside "pbOnStartUse" handles the change of type already, and it is stored until later. The "moveType" parameter that pbCalcTypeMode uses is exactly @type (with some tricks due to the effect of some abilities that may change the type, like Pixilate, but that's none of our concerns for Flying Press).

    As you are new to coding, I have to ask this question: is it the whole code that you posted? The complete code should be:

    Code:
    class PokeBattle_Move_144 < PokeBattle_Move # Note the class here. 
      def tramplesMinimize?(param=1)
        return true if param==1 && Settings::MECHANICS_GENERATION >= 6   # Perfect accuracy
        return true if param==2   # Double damage
        return super
      end
    
      def pbOnStartUse(user,targets)
        # Beware: here, "targets" is a list of targets. 
        # For Flying Press, this list will contain only one element though.
        
        # First step: compute both effectivenesses.
        flyingEff = pbCalcTypeMod(:FLYING,user,targets[0])
        fightingEff = pbCalcTypeMod(:FIGHTING,user,targets[0])
        
        # Second step: choose the best type.
        if flyingEff < fightingEff 
          @type = :FIGHTING
        else 
          # If flyingEff == fightingEff then keep the Flying-type.
          @type = :FLYING
        end 
      end
    
      # NO pbCalcTypeMod
    end
     
    Really, you don't need to rewrite "pbCalcTypeMod". The code inside "pbOnStartUse" handles the change of type already, and it is stored until later. The "moveType" parameter that pbCalcTypeMode uses is exactly @type (with some tricks due to the effect of some abilities that may change the type, like Pixilate, but that's none of our concerns for Flying Press).

    As you are new to coding, I have to ask this question: is it the whole code that you posted? The complete code should be:

    Code:
    class PokeBattle_Move_144 < PokeBattle_Move # Note the class here. 
      def tramplesMinimize?(param=1)
        return true if param==1 && Settings::MECHANICS_GENERATION >= 6   # Perfect accuracy
        return true if param==2   # Double damage
        return super
      end
    
      def pbOnStartUse(user,targets)
        # Beware: here, "targets" is a list of targets. 
        # For Flying Press, this list will contain only one element though.
        
        # First step: compute both effectivenesses.
        flyingEff = pbCalcTypeMod(:FLYING,user,targets[0])
        fightingEff = pbCalcTypeMod(:FIGHTING,user,targets[0])
        
        # Second step: choose the best type.
        if flyingEff < fightingEff 
          @type = :FIGHTING
        else 
          # If flyingEff == fightingEff then keep the Flying-type.
          @type = :FLYING
        end 
      end
    
      # NO pbCalcTypeMod
    end

    Update: under this code, i find that the move alternates between types. i faced a pidgeot and it 2hko'd being flying first then fighting, then i 2hko'd a venusaur with the same turn order type as before -- first flying then fighting
     
    Update: under this code, i find that the move alternates between types. i faced a pidgeot and it 2hko'd being flying first then fighting, then i 2hko'd a venusaur with the same turn order type as before -- first flying then fighting

    You made me test my code DX

    The error is that the type is computed before the use of pbOnStartUse, and it is stored in @calcType, not in @type!

    Code:
      def pbOnStartUse(user,targets)
        # Beware: here, "targets" is a list of targets. 
        # For Flying Press, this list will contain only one element though.
        
        # First step: compute both effectivenesses.
        flyingEff = pbCalcTypeMod(:FLYING,user,targets[0])
        fightingEff = pbCalcTypeMod(:FIGHTING,user,targets[0])
        
        # Second step: choose the best type.
        if flyingEff < fightingEff 
          @calcType = :FIGHTING
          @battle.pbDisplay(_INTL("Flying Press became Fighting-type!")) #Testing purposes
        else 
          # If flyingEff == fightingEff then keep the Flying-type.
          @calcType = :FLYING
          @battle.pbDisplay(_INTL("Flying Press became Flying-type!")) #Testing purposes
        end 
      end
     
    You made me test my code DX

    The error is that the type is computed before the use of pbOnStartUse, and it is stored in @calcType, not in @type!

    Code:
      def pbOnStartUse(user,targets)
        # Beware: here, "targets" is a list of targets. 
        # For Flying Press, this list will contain only one element though.
        
        # First step: compute both effectivenesses.
        flyingEff = pbCalcTypeMod(:FLYING,user,targets[0])
        fightingEff = pbCalcTypeMod(:FIGHTING,user,targets[0])
        
        # Second step: choose the best type.
        if flyingEff < fightingEff 
          @calcType = :FIGHTING
          @battle.pbDisplay(_INTL("Flying Press became Fighting-type!")) #Testing purposes
        else 
          # If flyingEff == fightingEff then keep the Flying-type.
          @calcType = :FLYING
          @battle.pbDisplay(_INTL("Flying Press became Flying-type!")) #Testing purposes
        end 
      end

    AAAAAA TYSM IT WORKS 🙏🙏🙏
     
    Back
    Top