#-- # Target Manager v1.0 by Enelvon # ============================================================================= # # Summary # ----------------------------------------------------------------------------- # This script is intended to provide a more flexible target manager than the # one present in default Ace. It allows for direct control of what members of # the battle can be targeted by individual skills or items through the use of # filters. It also provides an enhanced version of Ace's random and all target # modes - you can specify ranges for random skills, such as 2-5 hits, and skills # with all or random target modes will have their targets selected via filters. # Any skills that are not tagged as falling under the purview of the Target # Manager will use Ace's default scopes and target methods. # # Compatibility Information # ----------------------------------------------------------------------------- # **Required Scripts:** # SES Core v2.2 or higher. # # **Known Incompatibilities:** # None yet, though likely to be incompatible with battle systems that use # their own target managers/target selection windows. Very unlikely to play nice # with the Luna Engine, but untested. Compatibility fix for the Luna Engine is # simple in theory, however. # # Usage # ----------------------------------------------------------------------------- # This script is configured in two ways - defining filters and defining the # way that the Target Manager will filter a given skill. Filters are defined in # the Filters hash of the SES::TargetManager module and should consist of a # Regular Expression key and a Proc value that evaluates to true or false. The # base script does not contain any examples - please refer to the Basic Filter # package for a few examples. The package is by no means extensive, though it # should suffice for most basic purposes. I urge you to submit your own filters! # If the community produces enough, I may package them into a Community Filter # Package of some kind. # # Now for the part more relevant to most of you: defining the way that the # Target Manager handles filtering for a skill or item. # # ``` # # ...FILTER... # ...FILTER... # # ``` # # Place this in a Notes box to tell the Target Manager how it should filter # targets for the skill or item. The first replacement should be one (which # means that it will bring up a filtered list from which the player can choose # a target), all (which means that it will affect all targets who match the # filter), or rand (which means that it will randomly hit targets who match the # filter). If you use the range option, you should also provide a range. If you # want the skill or item to hit 2-5 times, it would look like this: # # ``` # # ``` # # Please note that the rand option requires both a starting point and an end # point, so if you want it to hit 1-3 times you would need to provide the range # 1..3 rather than just 3. # # You can include as many filters in between the opening and closing tags as # you would like. To take an example from the basic package, you might have this # as a filter set: # # ``` # # enemy_only # hp_<: 50% # # ``` # # This filter would allow the player to choose a target from a list of enemies # with less than 50% of their HP remaining. # # Aliased Methods # ----------------------------------------------------------------------------- # * `class Game_Action` # - `make_targets` # * `class Scene_Battle` # - `create_all_windows` # # Overwritten Methods # ----------------------------------------------------------------------------- # * `class Scene_Battle` # - `command_attack` # - `create_enemy_window` # - `on_skill_ok` # - `on_item_ok` # # License # ----------------------------------------------------------------------------- # This script is made available under the terms of the MIT Expat license. # View [this page](http://sesvxace.wordpress.com/license/) for more detailed # information. # # Installation # ----------------------------------------------------------------------------- # This script requires the SES Core (v2.2 or higher). This scripts may be # found in the SES source repository at the following location: # # * [Core](https://raw.github.com/sesvxace/core/master/lib/core.rb) # # Place this script below Materials, but above Main. Place this script below # the SES Core. # #++ module SES module TargetManager # Grab the Basic Filter Package and place it below this script or define your # own filters here. Filters = { # RegEx => Proc } # Evaluates the filters present in a skill or item and creates a list of # targets. # # @param action [Game_Action] an action in which the item and user are found # @return [Array] array of targets who match the filter def self.make_targets(action) targets = [] ($game_party.battle_members + $game_troop.alive_members).each do |target| add_target = !action.item.target_filters.any? do |filter| !filter[0].call(action.subject, target, *filter[1]) end targets << target if add_target end return targets end end end # Base class for Usable Items. class RPG::UsableItem < RPG::BaseItem alias_method :en_tm_ui_ssn, :scan_ses_notes # Scans the notes boxes of skills and items. # # @param tags [Hash] hash of tags to search for def scan_ses_notes(tags = {}) @target_type = [:one] @target_filters = [] tags[/^/i] = proc do |type, value| @target_type = [type.downcase.to_sym] if type == :rand if value[/^(\d+)$/] then @target_type << $1.to_i elsif value[/^(\d+)(\.+)(\d+)/] then @target_type << [$1.to_i, $2.to_i] end end note[/\s+(.+)\s+<\/Target Manager>/im] if (filters = $1) filters.each_line do |c| f = SES::TargetManager::Filters.keys.find { |f| c[f] } @target_filters << [SES::TargetManager::Filters[f], $~[1..-1]] if f end end end en_tm_ui_ssn(tags) end # The scope of the skill or item. # # @return [Symbol] a symbol corresponding to the scope def target_type scan_ses_notes if @target_type.nil? @target_type end # The filters used to determine possible targets for the skill or item. # # @return [Array] an array of filters def target_filters scan_ses_notes if @target_filters.nil? @target_filters end end # Base class for action data. class Game_Action attr_accessor :set alias_method :en_tm_ga_mt, :make_targets # Creates a list of targets for the action. # # @return [Array] an array of targets def make_targets if @set targets = @set and @set = nil return targets end en_tm_ga_mt end end # Window used for selection. New to the Target Manager. class Window_BattleTarget < Window_Selectable # Creates a new instance of the window. # # @param info_viewport [Viewport] the viewport that the window belongs to # @return [Window_BattleTarget] a new instance of Window_BattleTarget def initialize(info_viewport) @item_max = 0 super(0, info_viewport.rect.y, window_width, fitting_height(4)) @targets = [] refresh self.visible = false @info_viewport = info_viewport end # The width of the window. # # @return [Integer] the width of the window def window_width() Graphics.width - 128 end # The number of columns in the window. # # @return [Integer] the number of columns in the window def col_max() return 2 end # The number of items in the window. # # @return [Integer] the number of items in the window def item_max() @item_max end # The current target. # # @return [Game_Battler] the currently selected target def target() @targets[@index] end # Whether or not the current slot contains a valid target. # # @return [Boolean] whether the target is valid or not def current_item_enabled?() target end # Draws an item in the window. # # @param index [Integer] the index at which the item should be drawn def draw_item(index) change_color(normal_color) draw_text(item_rect_for_text(index), @targets[index].name) end # Sets up the window for a given skill or item. # # @param action [Game_Action] the action containing the skill or item def setup(action) @targets.clear unless action.item.target_filters.empty? @targets = SES::TargetManager.make_targets(action) else item = action.item if item.for_opponent? @targets = $game_troop.alive_members elsif item.for_dead_friend? @targets = $game_party.battle_members.select { |actor| actor.dead? } else $game_party.battle_members.select { |actor| actor.alive? } end end @item_max = @targets.size create_contents refresh show activate end # Displays the window. def show if @info_viewport width_remain = Graphics.width - width self.x = width_remain @info_viewport.rect.width = width_remain select(0) end super end # Hides the window. def hide @info_viewport.rect.width = Graphics.width if @info_viewport super end end # Class that handles much of the battle processing. class Scene_Battle < Scene_Base alias_method :en_tm_sb_caw, :create_all_windows # Creates the windows used in the battle. def create_all_windows en_tm_sb_caw create_target_window end # Creates the enemy target window. Unused. def create_enemy_window() end # Creates the window used by the Target Manager. def create_target_window @target_window = Window_BattleTarget.new(@info_viewport) @target_window.set_handler(:ok, method(:on_target_ok)) @target_window.set_handler(:cancel, method(:on_target_cancel)) end # Processing when attack is selected. def command_attack BattleManager.actor.input.set_attack select_target_selection end # Processing when a skill is selected. def on_skill_ok @skill = @skill_window.item BattleManager.actor.input.set_skill(@skill.id) action = BattleManager.actor.input BattleManager.actor.last_skill.object = @skill if @skill.target_type[0] == :one then select_target_selection else case @skill.target_type[0] when :all BattleManager.actor.input.set = SES::TargetManager.make_targets(action) when :rand targets, set = [], SES::TargetManager.make_targets(action) (@skill.target_type[1][0] + rand(@skill.target_type[1][1])).times do targets << set[rand(set.size)] end BattleManager.actor.input.set = set end @skill_window.hide next_command end end # Processing when an item is selected. def on_item_ok @item = @item_window.item BattleManager.actor.input.set_item(@item.id) action = BattleManager.actor.input case @item.target_type[0] when :one select_target_selection when :all BattleManager.actor.input.set = SES::TargetManager.make_targets(action) when :rand targets, set = [], SES::TargetManager.make_targets(action) (@item.target_type[1][0] + rand(@item.target_type[1][1])).times do targets << set[rand(set.size)] end BattleManager.actor.input.set = set else @item_window.hide next_command end $game_party.last_item.object = @item end # Begins target selection. def select_target_selection @target_window.setup(BattleManager.actor.input) end # Processing when a target is selected. def on_target_ok BattleManager.actor.input.set = [@target_window.target] @target_window.hide @skill_window.hide @item_window.hide next_command end # Processing when target selection is canceled. def on_target_cancel @target_window.hide case @actor_command_window.current_symbol when :attack @actor_command_window.activate when :skill @skill_window.activate when :item @item_window.activate end end end