Files
infinitefusion-e18/Data/Scripts/011_Battle/003_Move/001_Battle_Move.rb

204 lines
8.1 KiB
Ruby

#===============================================================================
#
#===============================================================================
class Battle::Move
attr_reader :battle
attr_reader :realMove
attr_accessor :id
attr_reader :name
attr_reader :function_code
attr_reader :power
attr_reader :type
attr_reader :category
attr_reader :accuracy
attr_accessor :pp
attr_writer :total_pp
attr_reader :addlEffect
attr_reader :target
attr_reader :priority
attr_reader :flags
attr_accessor :calcType
attr_accessor :powerBoost
attr_accessor :snatched
CRITICAL_HIT_RATIOS = (Settings::NEW_CRITICAL_HIT_RATE_MECHANICS) ? [24, 8, 2, 1] : [16, 8, 4, 3, 2]
#-----------------------------------------------------------------------------
# Creating a move.
#-----------------------------------------------------------------------------
def initialize(battle, move)
@battle = battle
@realMove = move
@id = move.id
@name = move.name # Get the move's name
# Get data on the move
@function_code = move.function_code
@power = move.power
@type = move.type
@category = move.category
@accuracy = move.accuracy
@pp = move.pp # Can be changed with Mimic/Transform
@target = move.target
@priority = move.priority
@flags = move.flags.clone
@addlEffect = move.effect_chance
@powerBoost = false # For Aerilate, Pixilate, Refrigerate, Galvanize
@snatched = false
end
# This is the code actually used to generate a Battle::Move object. The
# object generated is a subclass of this one which depends on the move's
# function code.
def self.from_pokemon_move(battle, move)
validate move => Pokemon::Move
code = move.function_code || "None"
if code[/^\d/] # Begins with a digit
class_name = sprintf("Battle::Move::Effect%s", code)
else
class_name = sprintf("Battle::Move::%s", code)
end
if Object.const_defined?(class_name)
return Object.const_get(class_name).new(battle, move)
end
return Battle::Move::Unimplemented.new(battle, move)
end
#-----------------------------------------------------------------------------
# About the move.
#-----------------------------------------------------------------------------
def pbTarget(_user); return GameData::Target.get(@target); end
def total_pp
return @total_pp if @total_pp && @total_pp > 0 # Usually undefined
return @realMove.total_pp if @realMove
return 0
end
# NOTE: This method is only ever called while using a move (and also by the
# AI), so using @calcType here is acceptable.
def physicalMove?(thisType = nil)
return (@category == 0) if Settings::MOVE_CATEGORY_PER_MOVE
thisType ||= @calcType
thisType ||= @type
return true if !thisType
return GameData::Type.get(thisType).physical?
end
# NOTE: This method is only ever called while using a move (and also by the
# AI), so using @calcType here is acceptable.
def specialMove?(thisType = nil)
return (@category == 1) if Settings::MOVE_CATEGORY_PER_MOVE
thisType ||= @calcType
thisType ||= @type
return false if !thisType
return GameData::Type.get(thisType).special?
end
def damagingMove?; return @category != 2; end
def statusMove?; return @category == 2; end
def pbPriority(user); return @priority; end
def usableWhenAsleep?; return false; end
def unusableInGravity?; return false; end
def healingMove?; return false; end
def recoilMove?; return false; end
def flinchingMove?; return false; end
def callsAnotherMove?; return false; end
# Whether the move can/will hit more than once in the same turn (including
# Beat Up which may instead hit just once). Not the same as pbNumHits>1.
def multiHitMove?; return false; end
def chargingTurnMove?; return false; end
def successCheckPerHit?; return false; end
def hitsFlyingTargets?; return false; end
def hitsDiggingTargets?; return false; end
def hitsDivingTargets?; return false; end
def ignoresReflect?; return false; end # For Brick Break
def targetsPosition?; return false; end # For Future Sight/Doom Desire
def cannotRedirect?; return false; end # For Snipe Shot
def worksWithNoTargets?; return false; end # For Explosion
def damageReducedByBurn?; return true; end # For Facade
def triggersHyperMode?; return false; end
def canSnatch?; return false; end
def canMagicCoat?; return false; end
def contactMove?; return @flags.any? { |f| f[/^Contact$/i] }; end
def canProtectAgainst?; return @flags.any? { |f| f[/^CanProtect$/i] }; end
def canMirrorMove?; return @flags.any? { |f| f[/^CanMirrorMove$/i] }; end
def thawsUser?; return @flags.any? { |f| f[/^ThawsUser$/i] }; end
def highCriticalRate?; return @flags.any? { |f| f[/^HighCriticalHitRate$/i] }; end
def bitingMove?; return @flags.any? { |f| f[/^Biting$/i] }; end
def punchingMove?; return @flags.any? { |f| f[/^Punching$/i] }; end
def soundMove?; return @flags.any? { |f| f[/^Sound$/i] }; end
def powderMove?; return @flags.any? { |f| f[/^Powder$/i] }; end
def pulseMove?; return @flags.any? { |f| f[/^Pulse$/i] }; end
def bombMove?; return @flags.any? { |f| f[/^Bomb$/i] }; end
def danceMove?; return @flags.any? { |f| f[/^Dance$/i] }; end
def slicingMove?; return @flags.any? { |f| f[/^Slicing$/i] }; end
def windMove?; return @flags.any? { |f| f[/^Wind$/i] }; end
# Causes perfect accuracy and double damage if target used Minimize. Perfect accuracy only with Gen 6+ mechanics.
def tramplesMinimize?; return @flags.any? { |f| f[/^TramplesMinimize$/i] }; end
def nonLethal?(_user, _target); return false; end # For False Swipe
def preventsBattlerConsumingHealingBerry?(battler, targets); return false; end # For Bug Bite/Pluck
# user is the Pokémon using this move.
def ignoresSubstitute?(user)
if Settings::MECHANICS_GENERATION >= 6
return true if soundMove?
return true if user&.hasActiveAbility?(:INFILTRATOR)
end
return false
end
def display_type(battler)
case @function_code
when "TypeDependsOnUserMorpekoFormRaiseUserSpeed1"
if battler.isSpecies?(:MORPEKO) || battler.effects[PBEffects::TransformSpecies] == :MORPEKO
return pbBaseType(battler)
end
# TODO: Make the below depend on a Setting rather than quoting it out.
=begin
when "TypeDependsOnUserPlate", "TypeDependsOnUserMemory",
"TypeDependsOnUserDrive", "TypeAndPowerDependOnUserBerry",
"TypeIsUserFirstType", "TypeAndPowerDependOnWeather",
"TypeAndPowerDependOnTerrain"
return pbBaseType(battler)
=end
end
return @realMove.display_type(battler.pokemon)
end
# TODO: Make the below depend on a Setting rather than quoting it out.
def display_damage(battler)
=begin
case @function_code
when "TypeAndPowerDependOnUserBerry"
return pbNaturalGiftBaseDamage(battler.item_id)
when "TypeAndPowerDependOnWeather", "TypeAndPowerDependOnTerrain",
"PowerHigherWithUserHP", "PowerLowerWithUserHP",
"PowerHigherWithUserHappiness", "PowerLowerWithUserHappiness",
"PowerHigherWithUserPositiveStatStages", "PowerDependsOnUserStockpile"
return pbBaseType(@power, battler, nil)
end
=end
return @realMove.display_damage(battler.pokemon)
end
# TODO: Make the below depend on a Setting rather than quoting it out.
def display_category(battler)
=begin
case @function_code
when "CategoryDependsOnHigherDamageIgnoreTargetAbility"
pbOnStartUse(user, nil)
return @calcCategory
end
=end
return @realMove.display_category(battler.pokemon)
end
def display_accuracy(battler); return @realMove.display_accuracy(battler.pokemon); end
end