$imported = {} if $imported.nil? $imported["BattleSymphony-MV"] = true #============================================================================== # �� User Guide #============================================================================== # # This script allows RPG Maker MV formatted battlers to be used with the # Battle Symphony script for RPG Maker VX Ace. # # The default action sequences in battle symphony contain 'POSE' commands # which control 8D Battlers, and 'STANCE' commans to control Holder's # battlers. # This extension adds the 'MOTION' command to control MV format battlers. # # MV format battlers have 18 motions in a 3x6 grid of 3 frames each. # The following keywords are used to refer to each motion in the grid: # # WALK THRUST ESCAPE # WAIT SWING VICTORY # CHANT MISSILE DYING # GUARD SKILL ABNORMAL # DAMAGE SPELL SLEEP # EVADE ITEM DEAD # # In addition, familiar keywords from the POSE and STANCE commands may be used # if you prefer. # # The BREAK motion returns the battler to its normal idle motion. # The ATTACK motion refers to a motion specified in the database note tags, # normally THRUST, SWING or MISSILE. # # NOTE TAGS # # The following database note tags should be used to configure your MV battlers: # # <MV BATTLER: file> - Actor, Enemy # Use an MV format battler for this actor or enemy, the file refers to a file # placed in Graphics/Characters (as with the HB and 8D extensions) # # <MV ATTACK MOTION: keyword> - Actor, Enemy, Weapon # Choose the default attack motion to use for this battler. # An actor's first weapon with an attack motion set overrides the actor's # attack motion (which represents unarmed) # #============================================================================== # �� License Information #============================================================================== # # The MIT License (MIT) # # Copyright (c) 2014 Cuong Nguyen # Copyright (c) 2020 Coelocanth # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the "Software"), to deal in # the Software without restriction, including without limitation the rights to # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of # the Software, and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # #============================================================================== # �� Basic Settings #============================================================================== module SYMPHONY module MV_BATTLER # Whether to process 'POSE' commands in sequences. Set this to false if you # edit all your action sequences to include 'MOTION' commands. It is on by # default for demonstration purposes. MIMIC_POSE = true # Whether to process 'STANCE' commands in sequences. Set this to false if you # edit all your action sequences to include 'MOTION' commands. It is on by # default for demonstration purposes. MIMIC_STANCE = true # The default attack motion when there are no database tags DEFAULT_ATTACK_MOTION = :thrust end end #============================================================================== # �� Direction - Advanced Configuration #============================================================================== module Direction #-------------------------------------------------------------------------- # self.index_mv #-------------------------------------------------------------------------- def self.index_mv(pose) case pose # array = [column, row, loop?, frames] # frames is optional, default is 12 when :walk array = [0, 0, true] when :wait array = [0, 1, true] when :chant array = [0, 2, true] when :guard array = [0, 3, true] when :damage array = [0, 4, false] when :evade array = [0, 5, false] #--- when :thrust, :attack array = [1, 0, false] when :swing array = [1, 1, false] when :missile array = [1, 2, false] when :skill array = [1, 3, false] when :spell array = [1, 4, false] when :item array = [1, 5, false] #--- when :escape array = [2, 0, true] when :victory array = [2, 1, true] when :dying array = [2, 2, true] when :abnormal array = [2, 3, true] when :sleep array = [2, 4, true] when :dead array = [2, 5, true] #--- else array = [0, 1, true] end return array end #-------------------------------------------------------------------------- # self.auto_pose_mv #-------------------------------------------------------------------------- def self.auto_pose_mv(battler) return :dead if battler.dead? return :sleep unless battler.movable? return :abnormal if battler.confusion? return :guard if battler.guard? return :dying if battler.hp < battler.mhp / 4 # If you prefer characters to walk in place, change the next line to :walk return :wait end end # Direction #============================================================================== # �� BattleManager #============================================================================== module BattleManager #-------------------------------------------------------------------------- # alias method: process_victory #-------------------------------------------------------------------------- class <<self; alias bes_mv_process_victory process_victory; end def self.process_victory $game_party.alive_members.each { |battler| battler.force_pose_mv(:victory) } return bes_mv_process_victory end #-------------------------------------------------------------------------- # alias method: process_defeat #-------------------------------------------------------------------------- class <<self; alias bes_mv_process_defeat process_defeat; end def self.process_defeat $game_troop.alive_members.each { |battler| battler.force_pose_mv(:victory) } return bes_mv_process_defeat end end # BattleManager #============================================================================== # �� Regular Expression #============================================================================== module REGEXP module SYMPHONY MV_BATTLER = /<MV[_ ]BATTLER:\s*(.*)>/i MV_ATTACK_MOTION = /MV[_ ]ATTACK[_ ]MOTION:\s*(.*)>/i end end #============================================================================== # �� DataManager #============================================================================== module DataManager #-------------------------------------------------------------------------- # alias method: load_database #-------------------------------------------------------------------------- class <<self; alias load_database_bes_mv load_database; end def self.load_database load_database_bes_mv load_notetags_bes_mv end #-------------------------------------------------------------------------- # new method: load_notetags_bes_mv #-------------------------------------------------------------------------- def self.load_notetags_bes_mv groups = [$data_actors, $data_enemies, $data_weapons] groups.each { |group| group.each { |obj| next if obj.nil? obj.battle_symphony_mv_battler } } end end # DataManager #============================================================================== # �� RPG::BaseItem #============================================================================== class RPG::BaseItem #-------------------------------------------------------------------------- # * Public Instance Variables #-------------------------------------------------------------------------- attr_accessor :mv_battler attr_accessor :mv_attack_motion #-------------------------------------------------------------------------- # new method: battle_symphony_mv_battler #-------------------------------------------------------------------------- def battle_symphony_mv_battler self.note.split(/[\r\n]+/).each { |line| case line when REGEXP::SYMPHONY::MV_BATTLER @mv_battler = $1.to_s when REGEXP::SYMPHONY::MV_ATTACK_MOTION @mv_attack_motion = $1.to_s.upcase end } end end # RPG::BaseItem #============================================================================== # �� Game_Battler #============================================================================== class Game_Battler < Game_BattlerBase #-------------------------------------------------------------------------- # new method: use_mv? #-------------------------------------------------------------------------- def use_mv? self.actor? ? !actor.mv_battler.nil? : !enemy.mv_battler.nil? end #-------------------------------------------------------------------------- # new method: mv_battler #-------------------------------------------------------------------------- def mv_battler self.actor? ? actor.mv_battler : enemy.mv_battler end #-------------------------------------------------------------------------- # new method: mv_attack_motion #-------------------------------------------------------------------------- def mv_attack_motion SYMPHONY::MV_BATTLER::DEFAULT_ATTACK_MOTION end #-------------------------------------------------------------------------- # alias method: set_default_position #-------------------------------------------------------------------------- alias bes_mv_set_default_position set_default_position def set_default_position bes_mv_set_default_position set_mv_default_position if self.use_mv? end #-------------------------------------------------------------------------- # new method: set_mv_default_position #-------------------------------------------------------------------------- def set_mv_default_position self.pose = Direction.auto_pose_mv(self) end #-------------------------------------------------------------------------- # alias method: break_pose #-------------------------------------------------------------------------- alias bes_mv_break_pose break_pose def break_pose bes_mv_break_pose break_pose_mv if self.use_mv? end #-------------------------------------------------------------------------- # new method: break_pose_mv #-------------------------------------------------------------------------- def break_pose_mv @pose = Direction.auto_pose_mv(self) #--- return unless SceneManager.scene.spriteset return unless self.sprite @direction = SYMPHONY::View::PARTY_DIRECTION @direction = Direction.opposite(@direction) if self.enemy? self.sprite.mirror = [9, 6, 3].include?(@direction) #@direction = Direction.opposite(@direction) if self.sprite.mirror end #-------------------------------------------------------------------------- # new method: force_pose_mv #-------------------------------------------------------------------------- def force_pose_mv(pose) return unless self.use_mv? return unless self.exist? #--- self.break_pose self.pose = pose @force_pose = true end #-------------------------------------------------------------------------- # alias method (from symphony): use_custom_charset? #-------------------------------------------------------------------------- alias bes_mv_use_custom_charset? use_custom_charset? def use_custom_charset? return true if use_mv? return bes_mv_use_custom_charset? end #-------------------------------------------------------------------------- # alias method (from symphony): face_coordinate #-------------------------------------------------------------------------- alias bes_mv_face_coordinate face_coordinate def face_coordinate(destination_x, destination_y) saved_pose = @pose bes_mv_face_coordinate(destination_x, destination_y) @pose = saved_pose if use_mv? end end # Game_Battler #============================================================================== # �� Game_Actor #============================================================================== class Game_Actor < Game_Battler #-------------------------------------------------------------------------- # new method: mv_attack_motion #-------------------------------------------------------------------------- def mv_attack_motion weapons.each do |weapon| return weapon.mv_attack_motion unless weapon.mv_attack_motion.nil? end return actor.mv_attack_motion end #-------------------------------------------------------------------------- # alias method: use_charset? #-------------------------------------------------------------------------- alias bes_mv_use_charset? use_charset? def use_charset? return false if use_mv? return bes_mv_use_charset? end end # Game_Actor #============================================================================== # �� Game_Enemy #============================================================================== class Game_Enemy < Game_Battler #-------------------------------------------------------------------------- # new method: mv_attack_motion #-------------------------------------------------------------------------- def mv_attack_motion return enemy.mv_attack_motion end #-------------------------------------------------------------------------- # alias method: use_charset? #-------------------------------------------------------------------------- alias bes_mv_use_charset? use_charset? def use_charset? return false if use_mv? return bes_mv_use_charset? end end # Game_Enemy #============================================================================== # �� Sprite_Battler #============================================================================== class Sprite_Battler < Sprite_Base #-------------------------------------------------------------------------- # alias method: update_bitmap #-------------------------------------------------------------------------- alias bes_mv_update_bitmap update_bitmap def update_bitmap correct_change_pose if @timer.nil? @battler.use_mv? ? update_mvset : bes_mv_update_bitmap end #-------------------------------------------------------------------------- # alias method: update_origin #-------------------------------------------------------------------------- alias bes_mv_update_origin update_origin def update_origin bes_mv_update_origin update_origin_mv if @battler.use_mv? end #-------------------------------------------------------------------------- # new method: update_charset #-------------------------------------------------------------------------- def update_mvset @battler.set_default_position unless pose #--- update_mvset_bitmap update_src_rect end #-------------------------------------------------------------------------- # alias method: correct_change_pose #-------------------------------------------------------------------------- alias bes_mv_correct_change_pose correct_change_pose def correct_change_pose bes_mv_correct_change_pose unless @battler.use_mv? correct_change_pose_mv if @battler.use_mv? end #-------------------------------------------------------------------------- # new method: correct_change_pose_mv #-------------------------------------------------------------------------- def correct_change_pose_mv array = Direction.index_mv(pose) @pattern = @battler.reverse_pose ? 2 : 0 @timer = array[3].nil? ? 12 : array[3] @last_pose = pose @back_step = false end #-------------------------------------------------------------------------- # new method: update_charset_origin #-------------------------------------------------------------------------- def update_origin_mv if bitmap self.ox = @cw / 2 self.oy = @ch end end #-------------------------------------------------------------------------- # new method: mv_graphic_changed? #-------------------------------------------------------------------------- def mv_graphic_changed? self.bitmap.nil? || @character_name != @battler.mv_battler end #-------------------------------------------------------------------------- # alias method: set_character_bitmap #-------------------------------------------------------------------------- alias bes_mv_set_character_bitmap set_character_bitmap def set_character_bitmap bes_mv_set_character_bitmap unless @battler.use_mv? return unless @battler.use_mv? self.bitmap = Cache.character(@character_name) @cw = bitmap.width / 9 @ch = bitmap.height / 6 end #-------------------------------------------------------------------------- # new method: update_mvset_bitmap #-------------------------------------------------------------------------- def update_mvset_bitmap if mv_graphic_changed? @character_name = @battler.mv_battler set_character_bitmap end end #-------------------------------------------------------------------------- # alias method: update_src_rect #-------------------------------------------------------------------------- alias bes_mv_update_src_rect update_src_rect def update_src_rect bes_mv_update_src_rect unless @battler.use_mv? return unless @battler.use_mv? array = Direction.index_mv(pose) @timer -= 1 if @timer <= 0 @pattern += 1 if @pattern > 2 if array[2] # looping patterns go 0,1,2,1 like MV @pattern = -1 else # Non looping patterns are one shot @pattern = 2 end end @timer = array[3].nil? ? 12 : array[3] end #--- column = array[0] * 3 + @pattern.abs row = array[1] sx = column * @cw sy = row * @ch self.src_rect.set(sx, sy, @cw, @ch) end end # Sprite_Battler #=============================================================================== # Scene_Battle #=============================================================================== class Scene_Battle < Scene_Base alias bes_mv_imported_symphony imported_symphony def imported_symphony # This is "MOTION" to match MV terms case @action.upcase when "MOTION" action_motion return end bes_mv_imported_symphony end def action_motion targets = get_action_targets return unless targets.size > 0 #--- case @action_values[1] # special when "BREAK", "CANCEL", "RESET", "NORMAL" targets.each { |target| target.break_pose } return when "ATTACK" pose_key = :attack # first column when "WALK", "FORWARD", "MOVE", "TARGET", "MARCH" pose_key = :walk when "WAIT", "IDLE", "READY" pose_key = :wait when "CHANT", "CHANNEL", "CHARGE" pose_key = :chant when "GUARD", "DEFEND" pose_key = :guard when "DAMAGE", "DMG", "STRUCK" pose_key = :damage when "EVADE", "DODGE" pose_key = :evade # second column when "THRUST" pose_key = :thrust when "SWING", "2H", "2H SWING", "1H", "1H SWING" pose_key = :swing when "SWING REVERSE", "2H REVERSE", "2H SWING REVERSE", "1H REVERSE", "1H SWING REVERSE" pose_key = :swing reverse_pose = true when "MISSILE" pose_key = :missile when "SKILL", "PHYSICAL" pose_key = :skill when "SPELL", "CAST", "INVOKE", "MAGIC" pose_key = :spell when "ITEM" pose_key = :item # third column when "ESCAPE", "ORIGIN", "BACK", "RETREAT" pose_key = :escape when "VICTORY" pose_key = :victory when "DYING", "PIYORI", "CRITICAL", "DAZED", "DAZE", "DIZZY", "WOOZY" pose_key = :dying when "ABNORMAL" pose_key = :abnormal when "SLEEP" pose_key = :sleep when "DEAD", "DOWN", "DOWNED", "FALLEN" pose_key = :dead else; return end #--- targets.each { |target| next unless target.exist? next unless target.use_mv? target.pose = pose_key if pose_key == :attack case target.mv_attack_motion when "THRUST" target.pose = :thrust when "MISSILE" target.pose = :missile when "SWING" target.pose = :swing else target.pose = SYMPHONY::MV_BATTLER::DEFAULT_ATTACK_MOTION end end target.force_pose = true target.reverse_pose = reverse_pose } end alias bes_mv_action_pose action_pose def action_pose action_motion if SYMPHONY::MV_BATTLER::MIMIC_POSE bes_mv_action_pose end alias bes_mv_action_stance action_stance def action_stance action_motion if SYMPHONY::MV_BATTLER::MIMIC_STANCE bes_mv_action_stance end end # Scene_Battle #=============================================================================== # # END OF FILE # #===============================================================================