Basic knowledge to the default RMVXA battle flow implementations
This topic aims to share my understandings to the default RMVXA battle flow implementations, and I'll only share basic stuffs here. However, you're still assumed to have at least iittle scripting proficiency(having written at least few basic Ruby codes) and basic knowledge to the default RMVXA battle flow on the user level(At least you need to know what's going on on the surface when playing it as a player).
Battle Phases
For the basics, you'll need to know a battle consists of an action input phase and an action execution phase. There are actually also initialization, turn end, and aborting, but they'll only be briefly covered here.
Battle Initialization Phase It's the phase where the battle's setting up. There are lots of stuffs going on, like setting up the troop in the battle, whether losing and/or party escape's allowed, whether the battle starts normally, preemptively or under surprise, and some other stuffs. When the battle starts preemptively, the party has a free turn at the start of the battle; When it starts under surprise, the troop has a free turn at the start of the battle instead. A free turn is a turn where the opponents can't input nor execute actions. After finishing the battle initializations, the battle will proceed to the Action Input Phase.
Action Input Phase It's the phase where players can either try to escape the battle, or input actions for all inputable actors. An actor is said to be inputable if he/she/it's alive and has no Restrictions enforced by states and no special flag auto battle. The action input phase will proceed as follows: 1. A party command window shows, letting players choose between fight and escape. 2a. If they choose to escape, then the party will either escape if the attempt's successful, or wasted its turn otherwise, as players won't be able to input anything for that turn. If the party escapes, the battle will proceed to the Abort Battle Phase before actually quitting the battle. 2b. If they choose to fight, then they can input actions for all inputable actors. 3. They'll first input actions for the 1st inputable party member, then the 2nd, 3rd, and finally the last inputable party member. Players won't be able to break that input sequence. 4. Each alive actor has his/her/its own action slots, with its size determined by his/her/its Action Times+. As long as he/she/it's also inputable, players will first input actions for the 1st action slot, then the 2nd, 3rd, ..., and finally the last action slot. Again, players won't be able to break that input sequence. 5. When inputting actions for inputable actors, players can either use the ok command or the cancel command. Using the former and the latter eventually proceeds to the next input and prior input respectively. Next input and prior input eventually proceeds to the Action Execution Phase and the party command window respectively. The below flowchart illustrates the flow within the action input phase(even though it's ultra ugly lol):
Action Execution Phase It's the phase where all battlers' actions are processed and all valid ones are executed. An action is said to be valid upon execution if it's forced or its user can use it upon execution. The action execution phase will proceed as follows: 1. The battle turn count will be increased by 1. This moment is also regarded as the start of the battle turn. Stuffs needing to happen upon turn start will be triggered here. 2. An action order queue including all battlers will be made. The higher the speed of the battler at that moment, the more up front that battler will be positioned in that queue. The speed of the battler's determined by his/her/its agi and all his/her/its inputted actions' speed. 3. The most up front battler in the action order queue will execute all of his/her/its actions, and then leave that queue. This process repeats until the action order queue's empty. 4. As long as that battler's movable(unless he/she/it's force actions), he/she/it'll first process the action in his/her/its 1st action slot, then the one in 2nd, 3rd, ..., and finally the one in the last action slot. All actions that are valid at that moment will be executed. 5. When the last action of that battler's executed, action end processing will be done, and stuffs needing to happen upon action end will be triggered there. 6. When all actors or enemies are dead, the battle will proceed to battle defeat or victory processing respectively. The battle will then be ended. 7. When the action order queue's empty, the battle will proceed to the Turn End Phase.
Turn End Phase It's the phase where the battle turn ends. Stuffs needing to happen upon turn end will be triggered here. After that, the battle will proceed to the Action Input Phase.
Abort Battle Phase It's the phase where the party successfully escapes the battle. The battle will end after processing battle abort.
Related Codes
For the basics, you just need to know which methods are directly involved in the battle flow. You just need to know what they do locally, but not how they work locally, let alone how they work as a whole.
BattleManager
These methods process the Battle Initialization Phase:
#--------------------------------------------------------------------------
# * Setup
#--------------------------------------------------------------------------
def self.setup(troop_id, can_escape = true, can_lose = false)
init_members
$game_troop.setup(troop_id)
@can_escape = can_escape
@can_lose = can_lose
make_escape_ratio
end
#--------------------------------------------------------------------------
# * Initialize Member Variables
#--------------------------------------------------------------------------
def self.init_members
@phase = :init # Battle Progress Phase
@can_escape = false # Can Escape Flag
@can_lose = false # Can Lose Flag
@event_proc = nil # Event Callback
@preemptive = false # Preemptive Attack Flag
@surprise = false # Surprise Flag
@actor_index = -1 # Actor for Which Command Is Being Entered
@action_forced = nil # Force Action
@map_bgm = nil # For Memorizing Pre-Battle BGM
@map_bgs = nil # For Memorizing Pre-Battle BGS
@action_battlers = [] # Action Order List
end
#--------------------------------------------------------------------------
# * Create Escape Success Probability
#--------------------------------------------------------------------------
def self.make_escape_ratio
@escape_ratio = 1.5 - 1.0 * $game_troop.agi / $game_party.agi
end
These methods checks the current battle phase:
#--------------------------------------------------------------------------
# * Determine if Turn Is Executing
#--------------------------------------------------------------------------
def self.in_turn?
@phase == :turn
end
#--------------------------------------------------------------------------
# * Determine if Turn Is Ending
#--------------------------------------------------------------------------
def self.turn_end?
@phase == :turn_end
end
#--------------------------------------------------------------------------
# * Determine if Battle Is Aborting
#--------------------------------------------------------------------------
def self.aborting?
@phase == :aborting
end
These methods process the next input and prior input in the Action Input Phase:
#--------------------------------------------------------------------------
# * To Next Command Input
#--------------------------------------------------------------------------
def self.next_command
begin
if !actor || !actor.next_command
@actor_index += 1
return false if @actor_index >= $game_party.members.size
end
end until actor.inputable?
return true
end
#--------------------------------------------------------------------------
# * To Previous Command Input
#--------------------------------------------------------------------------
def self.prior_command
begin
if !actor || !actor.prior_command
@actor_index -= 1
return false if @actor_index < 0
end
end until actor.inputable?
return true
end
This method judges if the battle defeat or victory's come:
#--------------------------------------------------------------------------
# * Determine Win/Loss Results
#--------------------------------------------------------------------------
def self.judge_win_loss
if @phase
return process_abort if $game_party.members.empty?
return process_defeat if $game_party.all_dead?
return process_victory if $game_troop.all_dead?
return process_abort if aborting?
end
return false
end
This method removes the most up front battler in the action order queue and returns that battler:
#--------------------------------------------------------------------------
# * Get Next Action Subject
# Get the battler from the beginning of the action order list.
# If an actor not currently in the party is obtained (occurs when index
# is nil, immediately after escaping in battle events etc.), skip them.
#--------------------------------------------------------------------------
def self.next_subject
loop do
battler = @action_battlers.shift
return nil unless battler
next unless battler.index && battler.alive?
return battler
end
end
Scene_Battle
These methods process the next input and prior input in the Action Input Phase:
#--------------------------------------------------------------------------
# * To Next Command Input
#--------------------------------------------------------------------------
def next_command
if BattleManager.next_command
start_actor_command_selection
else
turn_start
end
end
#--------------------------------------------------------------------------
# * To Previous Command Input
#--------------------------------------------------------------------------
def prior_command
if BattleManager.prior_command
start_actor_command_selection
else
start_party_command_selection
end
end
This method opens the party command window in the Action Input Phase:
#--------------------------------------------------------------------------
# * Start Party Command Selection
#--------------------------------------------------------------------------
def start_party_command_selection
unless scene_changing?
refresh_status
@status_window.unselect
@status_window.open
if BattleManager.input_start
@actor_command_window.close
@party_command_window.setup
else
@party_command_window.deactivate
turn_start
end
end
end
These methods process the fight command and escape command in the party command window in the Action Input Phase:
This method lets players input the currently selected action slot of the currently selected actor in the Action Input Phase:
#--------------------------------------------------------------------------
# * Start Actor Command Selection
#--------------------------------------------------------------------------
def start_actor_command_selection
@status_window.select(BattleManager.actor.index)
@party_command_window.close
@actor_command_window.setup(BattleManager.actor)
end
These methods proceed the battle to the Action Execution Phase and Turn End Phase respectively:
#--------------------------------------------------------------------------
# * Start Turn
#--------------------------------------------------------------------------
def turn_start
@party_command_window.close
@actor_command_window.close
@status_window.unselect
@subject = nil
BattleManager.turn_start
@log_window.wait
@log_window.clear
end
#--------------------------------------------------------------------------
# * End Turn
#--------------------------------------------------------------------------
def turn_end
all_battle_members.each do |battler|
battler.on_turn_end
refresh_status
@log_window.display_auto_affected_status(battler)
@log_window.wait_and_clear
end
BattleManager.turn_end
process_event
start_party_command_selection
end
These methods process all battlers' actions and the action ends in the Action Execution Phase:
#--------------------------------------------------------------------------
# * Battle Action Processing
#--------------------------------------------------------------------------
def process_action
return if scene_changing?
if !@subject || !@subject.current_action
@subject = BattleManager.next_subject
end
return turn_end unless @subject
if @subject.current_action
@subject.current_action.prepare
if @subject.current_action.valid?
@status_window.open
execute_action
end
@subject.remove_current_action
end
process_action_end unless @subject.current_action
end
#--------------------------------------------------------------------------
# * Processing at End of Action
#--------------------------------------------------------------------------
def process_action_end
@subject.on_action_end
refresh_status
@log_window.display_auto_affected_status(@subject)
@log_window.wait_and_clear
@log_window.display_current_state(@subject)
@log_window.wait_and_clear
BattleManager.judge_win_loss
end
No Comments