<commit_before>{Attachment, Status} = require './attachment'
{Weather} = require './weather'
{Protocol} = require '../../shared/protocol'
Query = require('./queries')
util = require './util'

# A single Move in the Pokemon engine. Move objects are constructed in
# data/VERSION/moves.coffee, with only one instance per move (for example,
# there is only one Flamethrower). These instances are retrieved by the battle
# engine.
class @Move
  criticalMultiplier: 2

  constructor: (@name, attributes = {}) ->
    @accuracy = attributes.accuracy || 0
    @priority = attributes.priority || 0
    @power = attributes.power
    @target = attributes.target
    @type = attributes.type || '???'
    @spectra = attributes.damage || '???'
    @chLevel = attributes.criticalHitLevel || 1
    @flags = attributes.flags
    @flinchChance = (attributes.flinchChance || 0)
    @ailmentChance = (attributes.ailmentChance || 0)
    @ailmentId = attributes.ailmentId
    @boostChance = attributes.boostChance || 0
    @boostStats = attributes.boostStats
    @boostTarget = attributes.boostTarget
    @pp = attributes.pp
    @recoil = attributes.recoil
    {@minHits, @maxHits} = attributes

  isPhysical: ->
    @spectra == 'physical'

  isSpecial: ->
    @spectra == 'special'

  isNonDamaging: ->
    @spectra == 'non-damaging'

  hasFlag: (flagName) ->
    flagName in @flags

  # A secondary effect also includes flinching.
  hasSecondaryEffect: ->
    (@ailmentChance > 0 && @ailmentId != "none") ||
      @flinchChance > 0 || @boostChance > 0

  # Executes this move on several targets.
  # Only override this method if the move does not need to be
  # recorded on the enemy pokemon.
  execute: (battle, user, targets) ->
    # TODO: Test the below 3 lines.
    if targets.length == 0
      battle.message "But there was no target..."
      return

    targetsHit = []
    for target in targets
      continue  if target.shouldBlockExecution(this, user) == true
      continue  if @use(battle, user, target, hitNumber) == false
      targetsHit.push(target)
      numHits = @calculateNumberOfHits(battle, user, targets)
      for hitNumber in [1..numHits]
        @hit(battle, user, target, hitNumber)

    # If the move hit 1+ times, query the user's afterAllHits event.
    # If the user is affected by Sheer Force, these are all ignored.
    if targetsHit.length > 0 &&
        (!user.hasAbility("Sheer Force") || !@hasSecondaryEffect())
      @afterAllHits(battle, user)
      for target in targetsHit
        target.afterAllHitsTarget(this, user)
      user.afterAllHits(this)

  # A hook with a default implementation of returning false on a type immunity.
  # If `use` returns false, the `afterSuccessfulHit` hook is never called.
  use: (battle, user, target, hitNumber) ->
    if @willMiss(battle, user, target)
      @afterMiss(battle, user, target)
      return false

    if target.isImmune(@getType(battle, user, target), this)
      battle.message "But it doesn't affect #{target.name}..."
      return false

  # Actually deals damage and runs hooks after hit.
  hit: (battle, user, target, hitNumber) ->
    damage = @calculateDamage(battle, user, target, hitNumber)
    if damage > 0<commit_msg>Sim: Change ordering of afterAllHits events.<commit_after>{Attachment, Status} = require './attachment'
{Weather} = require './weather'
{Protocol} = require '../../shared/protocol'
Query = require('./queries')
util = require './util'

# A single Move in the Pokemon engine. Move objects are constructed in
# data/VERSION/moves.coffee, with only one instance per move (for example,
# there is only one Flamethrower). These instances are retrieved by the battle
# engine.
class @Move
  criticalMultiplier: 2

  constructor: (@name, attributes = {}) ->
    @accuracy = attributes.accuracy || 0
    @priority = attributes.priority || 0
    @power = attributes.power
    @target = attributes.target
    @type = attributes.type || '???'
    @spectra = attributes.damage || '???'
    @chLevel = attributes.criticalHitLevel || 1
    @flags = attributes.flags
    @flinchChance = (attributes.flinchChance || 0)
    @ailmentChance = (attributes.ailmentChance || 0)
    @ailmentId = attributes.ailmentId
    @boostChance = attributes.boostChance || 0
    @boostStats = attributes.boostStats
    @boostTarget = attributes.boostTarget
    @pp = attributes.pp
    @recoil = attributes.recoil
    {@minHits, @maxHits} = attributes

  isPhysical: ->
    @spectra == 'physical'

  isSpecial: ->
    @spectra == 'special'

  isNonDamaging: ->
    @spectra == 'non-damaging'

  hasFlag: (flagName) ->
    flagName in @flags

  # A secondary effect also includes flinching.
  hasSecondaryEffect: ->
    (@ailmentChance > 0 && @ailmentId != "none") ||
      @flinchChance > 0 || @boostChance > 0

  # Executes this move on several targets.
  # Only override this method if the move does not need to be
  # recorded on the enemy pokemon.
  execute: (battle, user, targets) ->
    # TODO: Test the below 3 lines.
    if targets.length == 0
      battle.message "But there was no target..."
      return

    targetsHit = []
    for target in targets
      continue  if target.shouldBlockExecution(this, user) == true
      continue  if @use(battle, user, target, hitNumber) == false
      targetsHit.push(target)
      numHits = @calculateNumberOfHits(battle, user, targets)
      for hitNumber in [1..numHits]
        @hit(battle, user, target, hitNumber)

    # If the move hit 1+ times, query the user's afterAllHits event.
    # If the user is affected by Sheer Force, these are all ignored.
    if targetsHit.length > 0 &&
        (!user.hasAbility("Sheer Force") || !@hasSecondaryEffect())
      user.afterAllHits(this)
      @afterAllHits(battle, user)
      for target in targetsHit
        target.afterAllHitsTarget(this, user)

  # A hook with a default implementation of returning false on a type immunity.
  # If `use` returns false, the `afterSuccessfulHit` hook is never called.
  use: (battle, user, target, hitNumber) ->
    if @willMiss(battle, user, target)
      @afterMiss(battle, user, target)
      return false

    if target.isImmune(@getType(battle, user, target), this)
      battle.message "But it doesn't affect #{target.name}..."
      return false

  # Actually deals damage and runs hooks after hit.
  hit: (battle, user, target, hitNumber) ->
    damage = @calculateDamage(battle, user, target, hitNumber)
    if damage > 0
{'fraction_non_alphanumeric': 0.11503186693611069, 'fraction_numerical': 0.004974351002642624, 'mean_word_length': 3.2412656558998023, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5485627', 'n_tokens_mistral': 1976, 'n_tokens_neox': 1911, 'n_words': 620}