Class: Battle::Logic

Inherits:
Object show all
Defined in:
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00102 Actions.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00400 MegaEvolve.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00103 Critical_hit.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/02000 ExpHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01008 FleeHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01009 CatchHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00000 Battle Info/00010 Background.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01000 ChangeHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01004 DamageHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01005 SwitchHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00000 Battle Info/00001 Battle_Info.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01006 EndTurnHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01011 BattleEndHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01013 TransformHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01001 StatChangeHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01002 ItemChangeHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01003 StatusChangeHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01007 WeatherChangeHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01010 AbilityChangeHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00104 end of battle phase & switch choice.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01012 FTerrainChangeHandler.rb,
scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00001 Handlers/01011 BattleEndHandlerConstants.rb

Overview

Logic part of Pokemon Battle

This class helps to access to the battle information & to process some part of the battle

Defined Under Namespace

Classes: AbilityChangeHandler, BattleEndHandler, BattleInfo, CatchHandler, ChangeHandlerBase, DamageHandler, EndTurnHandler, ExpHandler, FTerrainChangeHandler, FleeHandler, ItemChangeHandler, MegaEvolve, StatChangeHandler, StatusChangeHandler, SwitchHandler, TransformHandler, WeatherChangeHandler

Constant Summary collapse

MOVE_PRIORITY_OFFSET =

Constant giving an offset for the move priority : In RH moves start their priority from 0 (-7) and end at 14 (+7)

-7
# Priority of pursuit when a switch will occur
PURSUIT_PRIORITY =

Priority of pursuit when a switch will occur

7
MEGA_PRIORITY =

Priority of MEGA

8
OTHER_PRIORITY =

Priority of other things

6
ITEM_PRIORITY_BOOST_IN_PRIORITY =

List of move first handler by item held

{
  quick_claw: :check_priority_trigger_quick_claw,
  custap_berry: :check_priority_trigger_custap_berry
}
ABILITY_PRIORITY_BOOST_IN_PRIORITY =

List of move first handler by ability

{
  quick_draw: :check_priority_trigger_quick_draw
}
VAL_0_25 =

Value that contains 0.25

0.25
CRITICAL_RATES =

List of critical rates according to the current critical count

{
  0 => 0,
  1 => 6_250,
  2 => 12_500,
  3 => 50_000
}
NO_CRITICAL_ABILITIES =

List of ability preventing the critical hit from happening

%i[battle_armor shell_armor]
UNCONDITIONAL_CRITICAL_ITEMS =
%i[razor_claw scope_lens]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scene) ⇒ Logic

Create a new Logic instance

Parameters:

  • scene (Scene)

    scene that hold the logic object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 51

def initialize(scene)
  @scene = scene
  @battle_info = scene.battle_info
  Message.setup(self)
  @messages = []
  # @type [Array<Actions::Base>]
  @actions = []
  # @type [Array<Actions::Base>]
  @turn_actions = []
  @bags = @battle_info.bags
  # @type [Array<Array<PFM::PokemonBattler>>]
  @battlers = []
  init_effects
  # Mega Evolve helper
  @mega_evolve = MegaEvolve.new(scene)
  # TODO: Remove global_states bank_states
  @global_states = {}
  @bank_states = Hash.new({})
  @battle_result = -1
  @switch_request = []
  @evolve_request = []
  $game_temp.battle_turn = 0
  $bag.last_ball_used_db_symbol = :__undef__
  @ball_fetch_on_field = []
end

Instance Attribute Details

#actionsArray<Actions::Base> (readonly)

Returns list of the current actions to proccess during the scene.

Returns:

  • (Array<Actions::Base>)

    list of the current actions to proccess during the scene



9
10
11
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 9

def actions
  @actions
end

#bagsArray<Array<PFM::Bag>> (readonly)

Returns bags of each banks.

Returns:

  • (Array<Array<PFM::Bag>>)

    bags of each banks



16
17
18
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 16

def bags
  @bags
end

#ball_fetch_on_fieldArray<PFM::PokemonBattler>

All the Pokemon with Ball Fetch on the field sorted by decreasing speed when the player fails the capture

Returns:



47
48
49
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 47

def ball_fetch_on_field
  @ball_fetch_on_field
end

#bank_effectsArray<Effects::EffectsHandler> (readonly)

Get the bank effects

Returns:



8
9
10
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 8

def bank_effects
  @bank_effects
end

#battle_infoBattle::Logic::BattleInfo (readonly)



18
19
20
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 18

def battle_info
  @battle_info
end

#battle_resultInteger

0 : Victory, 1 : Flee, 2 : Defeat, -1 : undef

Returns:

  • (Integer)


14
15
16
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 14

def battle_result
  @battle_result
end

#debug_end_of_battle

If the battle is in debug and forcing the end of it



44
45
46
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 44

def debug_end_of_battle
  @debug_end_of_battle
end

#evolve_requestArray<PFM::PokemonBattler> (readonly)

Get the evolve requests

Returns:



21
22
23
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 21

def evolve_request
  @evolve_request
end

#field_terrainSymbol

Get or set the current field terrain type

Returns:

  • (Symbol)


14
15
16
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 14

def field_terrain
  @field_terrain
end

#generic_rngRandom (readonly)

Get the generic rng

Returns:



42
43
44
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 42

def generic_rng
  @generic_rng
end

#mega_evolveMegaEvolve (readonly)

Get the Mega Evolve helper

Returns:



24
25
26
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 24

def mega_evolve
  @mega_evolve
end

#messagesArray<Array> (readonly)

Returns list of messages to send to an interpreter (AI/Scene).

Returns:

  • (Array<Array>)

    list of messages to send to an interpreter (AI/Scene)



7
8
9
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 7

def messages
  @messages
end

#move_accuracy_rngRandom (readonly)

Get the move accuracy rng

Returns:



39
40
41
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 39

def move_accuracy_rng
  @move_accuracy_rng
end

#move_critical_rngRandom (readonly)

Get the move critical rng

Returns:



36
37
38
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 36

def move_critical_rng
  @move_critical_rng
end

#move_damage_rngRandom (readonly)

Get the move damage rng

Returns:



33
34
35
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 33

def move_damage_rng
  @move_damage_rng
end

#position_effectsArray<Array<Battle::Effects::EffectsHandler>> (readonly)

Get the position effects

Returns:



11
12
13
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 11

def position_effects
  @position_effects
end

#sceneBattle::Scene (readonly)

Get the scene used to instanciate this Logic instance

Returns:



30
31
32
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 30

def scene
  @scene
end

#switch_requestArray<Hash> (readonly)

Get the switch requests

Returns:

  • (Array<Hash>)


27
28
29
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 27

def switch_request
  @switch_request
end

#terrain_effectsEffects::EffectsHandler (readonly)

Get the terrain effects



5
6
7
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 5

def terrain_effects
  @terrain_effects
end

#turn_actionsArray<Actions::Base>

Returns list of all actions that occurs within the current turn.

Returns:

  • (Array<Actions::Base>)

    list of all actions that occurs within the current turn



11
12
13
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 11

def turn_actions
  @turn_actions
end

Instance Method Details

#ability_change_handlerBattle::Logic::AbilityChangeHandler

Get the ability change handler



65
66
67
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 65

def ability_change_handler
  return AbilityChangeHandler.new(self, @scene)
end

#add_actions(actions)

Add actions to process in the next step

Parameters:



24
25
26
27
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00102 Actions.rb', line 24

def add_actions(actions)
  # Select the usefull action & merge them
  @actions.concat(actions.select(&:valid?))
end

#add_bank_effect(effect)

Add an effect on a bank



59
60
61
62
63
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 59

def add_bank_effect(effect)
  bank = effect.bank
  @bank_effects[bank] ||= Effects::EffectsHandler.new
  @bank_effects[bank].add(effect)
end

#add_position_effect(effect)

Add an effect on a position



48
49
50
51
52
53
54
55
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 48

def add_position_effect(effect)
  bank = effect.bank
  position = effect.position
  # Safety code
  @position_effects[bank] ||= []
  @position_effects[bank][position] ||= Effects::EffectsHandler.new
  @position_effects[bank][position].add(effect)
end

#adjacent_allies_of(pokemon) ⇒ Array<PFM::PokemonBattler>

Return the adjacent allies

Parameters:

Returns:



49
50
51
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 49

def adjacent_allies_of(pokemon)
  allies_of(pokemon, true)
end

#adjacent_foes_of(pokemon) ⇒ Array<PFM::PokemonBattler>

Return the adjacent foes

Parameters:

Returns:



25
26
27
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 25

def adjacent_foes_of(pokemon)
  foes_of(pokemon, true)
end

#alive_battlers(bank) ⇒ Array<PFM::PokemonBattler>

Return all the alive battler of a bank

Parameters:

  • bank (Integer)

Returns:



69
70
71
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 69

def alive_battlers(bank)
  return @battlers[bank].select(&:can_fight?)
end

#alive_battlers_without_check(bank) ⇒ Array<PFM::PokemonBattler>

Return all the alive battler of a bank but don't check can_fight?

Parameters:

  • bank (Integer)

Returns:



76
77
78
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 76

def alive_battlers_without_check(bank)
  return @battlers[bank].select(&:alive?)
end

#all_alive_battlersArray<PFM::PokemonBattler>

Return all alive battlers

Returns:



82
83
84
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 82

def all_alive_battlers
  return @battlers.each_index.flat_map { |bank| alive_battlers(bank) }
end

#all_battlers {|battler| ... } ⇒ Enumerable<PFM::PokemonBattler>

Iterate through all battlers

Yield Parameters:

Returns:



172
173
174
175
176
177
178
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 172

def all_battlers
  if block_given?
    @battlers.flatten.each { |battler| yield(battler) }
  else
    return @battlers.flatten.each
  end
end

#allies_of(pokemon, check_adjacent = false) ⇒ Array<PFM::PokemonBattler>

Return the allies (excluding the pokemon)

Parameters:

Returns:



57
58
59
60
61
62
63
64
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 57

def allies_of(pokemon, check_adjacent = false)
  return [] if pokemon.position.nil? || pokemon.position >= @battle_info.vs_type

  position = pokemon.position
  return @battlers[pokemon.bank].select.with_index do |ally, ally_position|
    next ally_position != position && ally.can_fight? && (!check_adjacent || (ally_position - position).abs <= 1)
  end
end

#any_field_ability_active?(db_symbol) ⇒ Array<PFM::PokemonBattler>

Check active abilities on the field

Returns:



201
202
203
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 201

def any_field_ability_active?(db_symbol)
  return @battlers.any? { |battlers| battlers.any? { |battler| battler.has_ability?(db_symbol) } }
end

#bank_countInteger

Return the number of bank in the current battle

Returns:

  • (Integer)


85
86
87
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 85

def bank_count
  return @battlers.size
end

#battle_end_handlerBattle::Logic::BattleEndHandler

Get the battle end handler



71
72
73
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 71

def battle_end_handler
  return BattleEndHandler.new(self, @scene)
end

#battle_phase_end

Function that distribute the exp to all Pokemon and switch dead pokemon



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00104 end of battle phase & switch choice.rb', line 4

def battle_phase_end
  log_debug('Entering battle_phase_end')
  end_turn_handler.process_events
  log_debug('end_turn_handler called')
  # Add all dead enemy to the switch request
  @switch_request.concat(dead_enemy_battler_during_this_turn.map { |battler| { who: battler } })
  log_data("Number of switch request (ennemy) : #{@switch_request.size}")
  @switch_request.concat(dead_friend_battler_during_this_turn.map { |battler| { who: battler } })
  log_data("Number of switch request (friend) : #{@switch_request.size}")
  # Add all dead actors to switch request
  turn = $game_temp.battle_turn
  @switch_request.concat(
    trainer_battlers.select { |battler| battler.last_battle_turn == turn && battler.dead? }.map { |battler| { who: battler } }
  )
  log_data("Number of switch request (enemy + actors) : #{@switch_request.size}")
  @switch_request.uniq! { |h| h[:who] }
  @switch_request.select! { |h| h[:who].position&.between?(0, @battle_info.vs_type - 1) }
  battle_phase_switch_exp_check
  log_debug('battle_phase_switch_exp_check called')
  all_alive_battlers.each { |pokemon| pokemon.switching = false }
end

#battle_phase_end_caught

Function that process the battle end when Pokemon was caught



61
62
63
64
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00104 end of battle phase & switch choice.rb', line 61

def battle_phase_end_caught
  pokemon = alive_battlers(1).find { |enemy| @battle_info.caught_pokemon == enemy }
  @scene.visual.show_exp_distribution(exp_handler.distribute_exp_for(pokemon))
end

#battle_phase_exp

Function that test the experience distribution



27
28
29
30
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00104 end of battle phase & switch choice.rb', line 27

def battle_phase_exp
  exp_distributions = exp_handler.distribute_exp_grouped(dead_enemy_battler_during_this_turn)
  @scene.visual.show_exp_distribution(exp_distributions) if exp_distributions.any?
end

#battle_phase_switch_execute(who:, with: nil)

Function that executes the switch request

Parameters:



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00104 end of battle phase & switch choice.rb', line 45

def battle_phase_switch_execute(who:, with: nil)
  return Actions::Switch.new(@scene, who, with).execute if who && with

  log_data("Attempting to switch #{who}")
  return unless can_battler_be_replaced?(who)

  with = switch_choose_with(who)
  log_data("Pokemon switched with #{who} : #{with}")
  return unless with

  during_end_of_turn = @actions.empty?
  request_switch_to_trainer(with) if who.bank != 0 && who.dead? && during_end_of_turn && !@scene.force_ia_switch?
  Actions::Switch.new(@scene, who, with).execute
end

#battle_phase_switch_exp_check

Function that process the switches and give exp



33
34
35
36
37
38
39
40
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00104 end of battle phase & switch choice.rb', line 33

def battle_phase_switch_exp_check
  return unless can_battle_continue?

  log_debug('battle_phase_switch_exp_check working')
  battle_phase_exp
  @switch_request.each { |h| battle_phase_switch_execute(**h) }
  @switch_request.clear
end

#battler(bank, position) ⇒ PFM::PokemonBattler?

Return the battler of a bank

Parameters:

  • bank (Integer)

    bank where the Pokemon is

  • position (Integer)

    position of the Pokemon in the bank

Returns:



7
8
9
10
11
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 7

def battler(bank, position)
  return nil if position < 0

  return @battlers.dig(bank, position)
end

#battler_attacks_after?(battler, other) ⇒ Boolean

Test if the battler attacks after another

Parameters:

Returns:

  • (Boolean)


134
135
136
137
138
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 134

def battler_attacks_after?(battler, other)
  return false unless battler.attack_order&.integer? && other.attack_order&.integer?

  return battler.attack_order > other.attack_order
end

#battler_attacks_before?(battler, other) ⇒ Boolean

Test if the battler attacks before another

Parameters:

Returns:

  • (Boolean)


123
124
125
126
127
128
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 123

def battler_attacks_before?(battler, other)
  return false unless battler.attack_order&.integer? && other.attack_order&.integer?
  return false if other.dead?

  return battler.attack_order < other.attack_order
end

#battler_attacks_first?(battler) ⇒ Boolean

Test if the battler attacks first

Parameters:

Returns:

  • (Boolean)


143
144
145
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 143

def battler_attacks_first?(battler)
  return battler.attack_order == 0
end

#battler_attacks_last?(battler) ⇒ Boolean

Test if the battler attacks last

Parameters:

Returns:

  • (Boolean)


150
151
152
153
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 150

def battler_attacks_last?(battler)
  last_order = all_alive_battlers.map(&:attack_order).reject { |i| i == Float::INFINITY }.compact.max
  return battler.attack_order == last_order
end

#battler_count(bank) ⇒ Integer

Return the number of battler (alive) in one bank

Parameters:

  • bank (Integer)

Returns:

  • (Integer)


16
17
18
19
20
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 16

def battler_count(bank)
  count = 0
  $game_temp.vs_type.times { |i| count += 1 if battler(bank, i)&.dead? == false }
  return count
end

#calc_critical_count(user, target, initial_critical_count) ⇒ Integer

Calculate the critical count (to get the right critical propability)

Parameters:

Returns:

  • (Integer)


33
34
35
36
37
38
39
40
41
42
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00103 Critical_hit.rb', line 33

def calc_critical_count(user, target, initial_critical_count)
  return 0 if user.can_be_lowered_or_canceled?(NO_CRITICAL_ABILITIES.include?(target.battle_ability_db_symbol))

  critical_count = initial_critical_count
  critical_count += 2 if user.effects.has?(:focus_energy)
  critical_count += 1 if user.has_ability?(:super_luck)
  critical_count += 1 if calc_critical_count_item(user)
  critical_count += 1 if user.effects.has?(:lansat_berry)
  return critical_count
end

#calc_critical_count_item(user) ⇒ Boolean

Tell if the user has an item that increase the critical count

Parameters:

Returns:

  • (Boolean)


48
49
50
51
52
53
54
55
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00103 Critical_hit.rb', line 48

def calc_critical_count_item(user)
  item = user.battle_item_db_symbol
  return true if UNCONDITIONAL_CRITICAL_ITEMS.include?(item)
  return true if item == :leek && user.db_symbol == :farfetch_d
  return true if item == :lucky_punch && user.db_symbol == :chansey

  return false
end

#calc_critical_hit(user, target, initial_critical_count) ⇒ Boolean

Calculate if the current action will be a critical hit

Parameters:

Returns:

  • (Boolean)


16
17
18
19
20
21
22
23
24
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00103 Critical_hit.rb', line 16

def calc_critical_hit(user, target, initial_critical_count)
  return false if bank_effects[target.bank].has?(:lucky_chant)
  return true if user.has_ability?(:merciless) && (target.poisoned? || target.toxic?)
  return true if user.effects.has?(:laser_focus)

  # 100_000 = 100%
  current_value = @move_critical_rng.rand(100_000)
  return current_value < CRITICAL_RATES[calc_critical_count(user, target, initial_critical_count)]
end

#can_battle_continue?Boolean

Tell if the battle can continue

Returns:

  • (Boolean)


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 91

def can_battle_continue?
  return false if @battle_result >= 0

  if all_battlers.any?(&:from_party?) && all_battlers.select(&:from_party?).all?(&:dead?) && !$game_switches[Yuki::Sw::BT_AI_CAN_WIN]
    @battle_result = 2
    return false
  end
  banks_that_can_fight = @battlers.map.with_index { |battlers, bank| battlers.any?(&:alive?) ? bank : nil }.compact
  # It's a victory if the player still have a Pokemon on its bank
  if banks_that_can_fight.size <= 1
    @battle_result = banks_that_can_fight.include?(0) ? 0 : 2
    return false
  end
  return true
end

#can_battler_be_replaced?(who) ⇒ Boolean

Test if the battler can be replaced

Parameters:

Returns:

  • (Boolean)


183
184
185
186
187
188
189
190
191
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 183

def can_battler_be_replaced?(who)
  return false if who.effects.has?(&:force_next_turn_action?) && who.alive?

  bank = who.bank
  party_id = who.party_id
  allies = allies_of(who)
  number = all_battlers.count { |pokemon| pokemon != who && pokemon.alive? && pokemon.bank == bank && pokemon.party_id == party_id && !allies.include?(pokemon) }
  return number > 0
end

#catch_handlerBattle::Logic::CatchHandler

Get the catch handler



59
60
61
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 59

def catch_handler
  return CatchHandler.new(self, @scene)
end

#damage_handlerBattle::Logic::DamageHandler

Get a new damage handler



23
24
25
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 23

def damage_handler
  return DamageHandler.new(self, @scene)
end

#delete_dead_effects

Delete all the dead effect by updating counters & removing them



66
67
68
69
70
71
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 66

def delete_dead_effects
  @terrain_effects.update_counter
  @bank_effects.each(&:update_counter)
  @position_effects.each { |bank| bank.each { |position| position&.update_counter } }
  all_alive_battlers.map(&:effects).each(&:update_counter)
end

#each_effects(*pokemons) {|| ... } ⇒ Array<Effects::EffectBase>, ...

Note:

This returns an enumerator if no block is given

Note:

If the block returns a Symbol, this methods returns this symbol immediately without processing the other effects

Execute a block on each effect depending on what to select as effect

Parameters:

  • pokemons (Array<PFM::PokemonBattler>)

    list of battlers we want to see their effect executed

Yield Parameters:

Returns:

  • (Array<Effects::EffectBase>, Symbol, Integer, nil)

    the first block return that was a symbol



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 22

def each_effects(*pokemons)
  return to_enum(__method__, *pokemons) unless block_given?

  # Define the proc that will ensure effects are properly called and stop the function if the result is a Symbol
  yielder = proc do |e|
    r = yield(e)
    return r if r.is_a?(Symbol)
  end
  pokemons = pokemons.compact.uniq # Sometimes launcher is nil, it's easier to handle that here
  # Terrain effect
  @terrain_effects.each(&yielder)
  yielder.call(weather_effect)
  yielder.call(field_terrain_effect)
  # Effect on Pokemon & their position
  pokemons.each { |pokemon| pokemon.evaluate_effects(yielder) }
  # Ability effect from allies
  allies = pokemons.flat_map { |pokemon| @scene.logic.allies_of(pokemon).select { |ally| ally.ability_effect.affect_allies } }.uniq
  allies.reject! { |pokemon| pokemons.include?(pokemon) } # <= Ability effect might already have been evaluated if the pokemon is in the list
  allies.each { |pokemon| yielder.call(pokemon.ability_effect) }
  # Effect on banks
  pokemons.compact.map(&:bank).uniq.each { |bank| @bank_effects[bank]&.each(&yielder) }
  return nil
end

#end_turn_handlerBattle::Logic::EndTurnHandler

Get a new switch handler



35
36
37
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 35

def end_turn_handler
  return EndTurnHandler.new(self, @scene)
end

#exp_handlerBattle::Logic::ExpHandler

Get the exp handler



77
78
79
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 77

def exp_handler
  return ExpHandler.new(self)
end

#field_terrain_effectEffects::FieldTerrain

Get the field terrain effect



84
85
86
87
88
89
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 84

def field_terrain_effect
  if !@field_terrain_effect || @field_terrain_effect.db_symbol != @field_terrain
    @field_terrain_effect = Battle::Effects::FieldTerrain.new(self, @field_terrain)
  end
  return @field_terrain_effect
end

#flee_handlerBattle::Logic::FleeHandler

Get the flee handler



53
54
55
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 53

def flee_handler
  return FleeHandler.new(self, @scene)
end

#foes_of(pokemon, check_adjacent = false) ⇒ Array<PFM::PokemonBattler>

Return the foes

Parameters:

Returns:



33
34
35
36
37
38
39
40
41
42
43
44
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 33

def foes_of(pokemon, check_adjacent = false)
  return [] if pokemon.position.nil? || pokemon.position >= @battle_info.vs_type

  position = pokemon.position
  return @battlers.flat_map.with_index do |battler_bank, bank|
    next nil.to_a if bank == pokemon.bank

    next battler_bank.select.with_index do |foe, foe_position|
      foe.can_fight? && (!check_adjacent || (foe_position - position).abs <= 1)
    end
  end
end

#force_sort_actions(&block)

Sort the actions

Parameters:

  • block (Block)

    block used to sort the actions take |Actions::Base, Actions::Base| as arguments



59
60
61
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00102 Actions.rb', line 59

def force_sort_actions(&block)
  @actions.sort!(&block)
end

#fterrain_change_handlerBattle::Logic::FTerrainChangeHandler

Get a new field terrain change handler



47
48
49
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 47

def fterrain_change_handler
  return FTerrainChangeHandler.new(self, @scene)
end

#item_change_handlerBattle::Logic::ItemChangeHandler

Get a new item change handler



11
12
13
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 11

def item_change_handler
  return ItemChangeHandler.new(self, @scene)
end

#load_battlers

Load the battlers from the battle infos



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 87

def load_battlers
  @battle_info.parties.each_with_index do |parties, bank|
    next unless parties

    parties.each_with_index do |party, index|
      load_battlers_from_party(party, bank, index)
    end
    adjust_party(@battlers[bank]) if @battle_info.vs_type > 1
    @battle_info.vs_type.times do |i|
      @battlers.dig(bank, i)&.position = i
    end
  end
  all_battlers { |battler| transform_handler.initialize_transform_attempt(battler) }
end

#load_rng(seeds = Hash.new(Random.new_seed))

Load the RNG for the battle logic

Parameters:

  • seeds (Hash) (defaults to: Hash.new(Random.new_seed))

    seeds for the RNG



109
110
111
112
113
114
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 109

def load_rng(seeds = Hash.new(Random.new_seed))
  @move_damage_rng = Random.new(seeds[:move_damage_rng])
  @move_critical_rng = Random.new(seeds[:move_critical_rng])
  @move_accuracy_rng = Random.new(seeds[:move_accuracy_rng])
  @generic_rng = Random.new(seeds[:generic_rng])
end

#perform_next_actionBoolean

Execute the next action

Returns:

  • (Boolean)

    if there was an action or not



31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00102 Actions.rb', line 31

def perform_next_action
  return false if @actions.empty? || !can_battle_continue?

  # @type [Actions::Base]
  action = @actions.pop
  log_debug("Current action : #{action}")
  @scene.message_window.blocking = false
  PFM::Text.reset_variables # Prevent wrong pokemon name from being shown
  action.execute
  execute_post_action_events
  battle_phase_switch_exp_check
  return true
end

#request_switch(who, with)

Add a switch request

Parameters:



105
106
107
108
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 105

def request_switch(who, with)
  @switch_request.delete_if { |request| request[:who] == who }
  @switch_request << { who: who, with: with }
end

#rng_seedsHash{ Symbol => Integer }

Get the current RNG Seeds

Returns:

  • (Hash{ Symbol => Integer })


118
119
120
121
122
123
124
125
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 118

def rng_seeds
  {
    move_damage_rng: @move_damage_rng.seed,
    move_critical_rng: @move_critical_rng.seed,
    move_accuracy_rng: @move_accuracy_rng.seed,
    generic_rng: @generic_rng.seed
  }
end

#sort_actions

Note:

The last action in the stack is the first action to pop out from the stack

Sort the actions



47
48
49
50
51
52
53
54
55
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00102 Actions.rb', line 47

def sort_actions
  refine_actions
  sorted_actions = sort_action_and_add_effects
  @actions.clear
  @actions.concat(sorted_actions.reverse)
  @turn_actions.clear
  @turn_actions.concat(sorted_actions.reverse)
  define_pokemon_action_properties
end

#stat_change_handlerBattle::Logic::StatChangeHandler

Get a new stat change handler



5
6
7
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 5

def stat_change_handler
  return StatChangeHandler.new(self, @scene)
end

#status_change_handlerBattle::Logic::StatusChangeHandler

Get a new item change handler



17
18
19
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 17

def status_change_handler
  return StatusChangeHandler.new(self, @scene)
end

#switch_battlers(who, with)

Switch two pokemon (logically)

Parameters:



158
159
160
161
162
163
164
165
166
167
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 158

def switch_battlers(who, with)
  with_position = @battlers[who.bank].index(with)
  who_position = @battlers[who.bank].index(who)
  @battlers[who.bank][who_position] = with
  @battlers[with.bank][with_position] = who
  with.position, who.position = who.position, with.position
  with.place_in_party, who.place_in_party = who.place_in_party, with.place_in_party
  # Ensure the newly comming pokemon gets the right battle turn
  with.last_battle_turn = $game_temp.battle_turn
end

#switch_handlerBattle::Logic::SwitchHandler

Get a new switch handler



29
30
31
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 29

def switch_handler
  return SwitchHandler.new(self, @scene)
end

#to_s Also known as: inspect

Safe to_s & inspect



78
79
80
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00100 Logic.rb', line 78

def to_s
  format('#<%<class>s:%<id>08X>', class: self.class, id: __id__)
end

#trainer_battlersArray<PFM::PokemonBattler>

List all the trainer Pokemon

Returns:



195
196
197
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 195

def trainer_battlers
  return @battlers[0].compact.select(&:from_party?)
end

#transform_handlerBattle::Logic::TransformHandler

Get the transform handler



83
84
85
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 83

def transform_handler
  return TransformHandler.new(self, @scene)
end

#update_battler_turn_count

Update the turn count of all alive battler



111
112
113
114
115
116
117
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00101 Battler.rb', line 111

def update_battler_turn_count
  $game_temp.battle_turn += 1
  all_alive_battlers.each do |pokemon|
    pokemon.turn_count += 1
    pokemon.last_battle_turn = $game_temp.battle_turn
  end
end

#weather_change_handlerBattle::Logic::WeatherChangeHandler

Get a new weather change handler



41
42
43
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00105 Handlers.rb', line 41

def weather_change_handler
  return WeatherChangeHandler.new(self, @scene)
end

#weather_effectEffects::Weather

Get the weather effect

Returns:



75
76
77
78
79
80
# File 'scripts/01600 Alpha 25 Battle Engine/00200 Battle_Logic/00106 Effects.rb', line 75

def weather_effect
  if !@weather_effect || @weather_effect.db_symbol != $env.current_weather_db_symbol
    @weather_effect = Battle::Effects::Weather.new(self, $env.current_weather_db_symbol)
  end
  return @weather_effect
end