Custom Battle System script - Guidance needed

Mewgull

Warper
Member
Joined
May 20, 2016
Messages
2
Reaction score
0
First Language
English
Primarily Uses
Hello,


I have not signed up for one of these forums in a while, so I will try my best to explain my situation:


I am currently writing my own custom script for a battle system similar to a "Free Turn". In this system, every battler acts immediately when their turn comes around to them.


Every battler in the field (both ALLIES and ENEMIES) are arranged in an array based on their agility stat, and the system will iterate through that array, allowing the index to perform their turn one-by-one.


On with what I have.


In BattleManager I have this:


#--------------------------------------------------------------------------
# * New Method: get_battler_order
#--------------------------------------------------------------------------
def self.get_battler_order
action_battlers = []
all_battle_members = $game_party.members + $game_troop.members
all_battle_members.each do |battler|
action_battlers << battler
end
action_battlers.sort! {|x,y| y.agi <=> x.agi}
return action_battlers
end


As per the script above, I created an array that gathers ALL battlers present and then sorts them by their agility stat.


Next, in Scene_Battle I have:


#--------------------------------------------------------------------------
# * Overwrite: Battle Start
#--------------------------------------------------------------------------
def battle_start
BattleManager.battle_start
process_event
@battler_list = BattleManager.get_battler_order
get_next_action_battler
end

#--------------------------------------------------------------------------
# new method: get_next_action_battler
#--------------------------------------------------------------------------
def get_next_action_battler(index = 0)
if @battler_list[index].actor?
#PROCESS ALLY TURN
else
#PROCESS ENEMY TURN
end
end


I understand that eventually, after the turn has been processed, I will have to iterate through the array and continuously refer to that method to process each turn until the end of the array where it will go back to index 0.


But this is where I am stuck. There are so many methods and classes that I could choose from in the regular system, but I don't know where to start to process the battler's actions immediately, when to iterate through the array (increasing index) and when to recall that get_next_action_battler method again. I am not using anything in the database that increases attack times, etc. And I want to make it so that state removal conditions, for example, are processed at the beginning of a turn.


I'm just completely lost and I've been staring at my screen almost all day, haha.


If you need any more details, please feel free to reply.


I am not looking for anyone to make my script for me (although that would be awesome), I am simply looking for guidance.


Thanks so much!
 

Shaz

Veteran
Veteran
Joined
Mar 2, 2012
Messages
40,098
Reaction score
13,704
First Language
English
Primarily Uses
RMMV
Please do not post the same topic multiple times. First posts require moderator approval, and if you posted in the wrong place, mods will move it for you.
 

Mewgull

Warper
Member
Joined
May 20, 2016
Messages
2
Reaction score
0
First Language
English
Primarily Uses
OK, so I whipped something up (after a lot of research) and referencing Yanfly's Free Turn Battle script, and came up with this:


Please note "masagi" means "Mewgull Ace Scripts - Agility"



#==============================================================================
# * Battle Manager
#==============================================================================

module BattleManager

#--------------------------------------------------------------------------
# * New Method: get_battler_order
#--------------------------------------------------------------------------
def self.get_battler_order
masagi_action_battlers = []
masagi_action_battlers = $game_party.members + $game_troop.members
masagi_action_battlers.sort! {|x,y| y.agi <=> x.agi}
#console
puts "- - BATTLE ORDER:"
masagi_action_battlers.each do |index|
puts "#{index.name} / #{index.agi}"
end
#
return masagi_action_battlers
end

#--------------------------------------------------------------------------
# * New Method: actor_set
#--------------------------------------------------------------------------
def self.actor_set(value)
@actor_index = value
end

#--------------------------------------------------------------------------
# * overwrite: next_command
#--------------------------------------------------------------------------
def self.next_command
return true
end
#--------------------------------------------------------------------------
# * overwrite: prior_command
#--------------------------------------------------------------------------
def self.prior_command
return true
end

end #BattleManager

#==============================================================================
# * Game_Actor
#==============================================================================

class Game_Actor < Game_Battler

#--------------------------------------------------------------------------
# alias method: next_command
#--------------------------------------------------------------------------
alias game_actor_next_command_masagi next_command
def next_command
if SceneManager.scene_is?(Scene_Battle)
return false
end
return game_actor_next_command_masagi
end

#--------------------------------------------------------------------------
# alias method: prior_command
#--------------------------------------------------------------------------
alias game_actor_prior_command_masagi prior_command
def prior_command
if SceneManager.scene_is?(Scene_Battle)
return false
end
return game_actor_prior_command_masagi
end

end #Game_Actor

#==============================================================================
# ■ Scene_Battle
#==============================================================================

class Scene_Battle < Scene_Base

#--------------------------------------------------------------------------
# * Overwrite: Battle Start
#--------------------------------------------------------------------------
def battle_start
puts "- - BATTLE START!"
BattleManager.battle_start
process_event
@battler_index = 0
@masagi_battler_list = BattleManager.get_battler_order
puts "- - ORDER START!"
masagi_perform_next_action_battler
end

#--------------------------------------------------------------------------
# * Start Party Command Selection
#--------------------------------------------------------------------------
def start_party_command_selection
unless scene_changing?
refresh_status
@status_window.unselect
@status_window.open
@actor_command_window.close
@party_command_window.setup
end
end
#--------------------------------------------------------------------------
# * 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)
puts "Player #{BattleManager.actor.name}'s command!"
end

#--------------------------------------------------------------------------
# new method: masagi_get_next_battler
#--------------------------------------------------------------------------
def masagi_perform_next_action_battler(index = 0)
@current_battler = @masagi_battler_list[index]
puts "#{@current_battler.name}'s Turn!"
if @current_battler.inputable?
if @current_battler.actor?
BattleManager.actor_set(@current_battler.index)
start_party_command_selection
else
BattleManager.actor_set(-1)
perform_masagi_enemy_action
end
else
puts "#{@current_battler.name} can't move!"
select_next_member
end
end

#--------------------------------------------------------------------------
# alias method: next_command
#--------------------------------------------------------------------------
alias scene_battle_next_command_masagi next_command
def next_command
if masagi_action?
perform_masagi_actor_action
else
scene_battle_next_command_masagi
end
end

#--------------------------------------------------------------------------
# new method: masagi_action?
#--------------------------------------------------------------------------
def masagi_action?
return false if BattleManager.actor.nil?
return false if BattleManager.actor.current_action.nil?
action = BattleManager.actor.current_action.item
return !action.nil?
end

#--------------------------------------------------------------------------
# new method: perform_masagi_actor_action
#--------------------------------------------------------------------------
def perform_masagi_actor_action
hide_masagi_action_windows
@subject = @current_battler#BattleManager.actor
item = @subject.current_action.item
execute_action
process_event
loop do
@subject.remove_current_action
break if $game_troop.all_dead?
break unless @subject.current_action
@subject.current_action.prepare
execute_action if @subject.current_action.valid?
end
return if $game_troop.alive_members.size <= 0
process_action_end
@subject.make_actions
@subject = nil
show_masagi_action_windows
end

#--------------------------------------------------------------------------
# new method: perform_masagi_enemy_action
#--------------------------------------------------------------------------
def perform_masagi_enemy_action
hide_masagi_action_windows
@subject = @current_battler
@subject.make_actions
execute_action
process_event
loop do
@subject.remove_current_action
break if $game_party.all_dead?
break unless @subject.current_action
@subject.current_action.prepare
execute_action if @subject.current_action.valid?
end
return if $game_party.alive_members.size <= 0
process_action_end
@subject.make_actions
@subject = nil
show_masagi_action_windows
end

#--------------------------------------------------------------------------
# new method: hide_masagi_action_windows
#--------------------------------------------------------------------------
def hide_masagi_action_windows
@info_viewport.visible = true
@status_window.hide
@party_command_window.close
@actor_command_window.close
end

#--------------------------------------------------------------------------
# new method: show_masagi_action_windows
#--------------------------------------------------------------------------
def show_masagi_action_windows
@info_viewport.visible = true
@status_window.show
end_masagi_action
end

#--------------------------------------------------------------------------
# new method: end_masagi_action
#--------------------------------------------------------------------------
def end_masagi_action
select_next_member
end

#--------------------------------------------------------------------------
# new method: select_next_member
#--------------------------------------------------------------------------
def select_next_member
if @battler_index >= @masagi_battler_list.size - 1
puts "INDEX RESET"
@battler_index = 0
else
@battler_index += 1
end
masagi_perform_next_action_battler(@battler_index)
end

end #Scene_Battle




But when I test my game now, I get this error:


Script 'Scene_Battle' line 340: NoMethodError occured.

undefined method 'set_attack' for nil:NilClass


I'm not sure why this error pops up?


This is the method from Scene_Battle:


#--------------------------------------------------------------------------
# * [Attack] Command
#--------------------------------------------------------------------------
def command_attack
BattleManager.actor.input.set_attack
select_enemy_selection
end


But "actor" is already populated with the current action actor, and it's not nil? Don't know if I explained that right... but I'm lost as to why this is happening...
 

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,787
Reaction score
939
First Language
Chinese
Primarily Uses
N/A
It's because the action list of BattleManager.actor is empty.


By default, input in Game_Actor is this:


def input
@actions[@action_input_index]
end


But without calling make_actions in Game_Battler:


def make_actions
clear_actions
return unless movable?
@actions = Array.new(make_action_times) { Game_Action.new(self) }
end


@actions will just be an empty array, so @actions[@action_input_index] will always return nil, leading to BattleManager.actor.input becoming nil.


Note that make_actions is called in BattleManager.input_start:


def self.input_start
if @phase != :input
@phase = :input
$game_party.make_actions
$game_troop.make_actions
clear_actor
end
return !@surprise && $game_party.inputable?
end


Which is called by start_party_command_selection in Scene_Battle:


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


But in your case, start_party_command_selection in Scene_Battle is rewritten into this:


def start_party_command_selection
unless scene_changing?
refresh_status
@status_window.unselect
@status_window.open
@actor_command_window.close
@party_command_window.setup
end
end


So make_actions in Game_Battler will never be called.


P.S.: You may want to check these:


Basic knowledge to the default RMVXA battle flow implementations


Solid understanding to the default RMVXA battle flow implementations
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Profile Posts

Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.
Do you Find Tilesetting or Looking for Tilesets/Plugins more fun? Personally I like making my tileset for my Game (Cretaceous Park TM) xD
How many parameters is 'too many'??

Forum statistics

Threads
105,859
Messages
1,017,030
Members
137,566
Latest member
Fl0shVS
Top