累计送礼: 0 个 累计收礼: 1 个 TA的每日心情 开心 前天 04:10
签到天数: 209 天
连续签到: 2 天
[LV.7]常住居民III
管理员
VIP
7
卡币
22945
OK点
16
推广点
0
同能卷
50
积分 28308
Introduction
This script defines new scope types for items and skills in battle.
More specifically, it separates the scope into distinct properties you can define independently.
Those properties are:
- Affects allies
- Affects enemies
- Affects the entire group or only one
- Selects one randomly
(new)
- Includes the user
- Only affects battlers that are alive
- Only affects battlers that are dead
You can also define completely custom restrictions by block, for example skills that can't target ghost enemies, or items that can only target allies that have a state, or more than 50% HP, etc.
Author: Wecoc
First Release: January 2017
Last Version: November 2018
Terms of use
- Giving credits (Wecoc) is optional, but appreciated.
- You can repost this code.
- You can edit this code freely, and distribute the edits as well.
- This code can be used on commercial games.
Demo
You can download a basic demo here:
Advanced Scope.zip
Code
There are two versions, a normal one and a version compatible with
Data File Save .
Normal version (independent)
Spoiler: Code
Ruby: #============================================================================== # ** [XP] Advanced Scope v1.1 #------------------------------------------------------------------------------ # Author: Wecoc (credits are optional) #------------------------------------------------------------------------------ # Defines new types of scope for items and skills in battle #------------------------------------------------------------------------------ # $data_items[ID] and $data_skills[ID] work exactly the same way # To define the target use: # $data_items[ID].scope_ally = true | false # Ally # $data_items[ID].scope_enemy = true | false # Enemy # $data_items[ID].scope_all = true | false # Entire group / Only one # $data_items[ID].scope_random = true | false # Pick one randomly # $data_items[ID].scope_user = true | false # Include user # $data_items[ID].scope_alive = true | false # Only alive members # $data_items[ID].scope_dead = true | false # Only dead members #------------------------------------------------------------------------------ # $data_items[ID].restriction(&block) # Set custom restriction # $data_items[ID].restrictions # Get all custom restrictions # $data_items[ID].clear_restrictions # Clear all custom restrictions #============================================================================== #============================================================================== # ** Scope Configuration #============================================================================== module Scope #---------------------------------------------------------------------------- # Default Dead Select #---------------------------------------------------------------------------- # By default if an item only affects members that are alive you can still # select a dead member, but the item won't have any effect. # The same happens with items that only affect dead members. # Set to false if you want to disable that and apply a strict restriction. #---------------------------------------------------------------------------- DEFAULT_DEAD_SELECT = true end #============================================================================== # ** Array #============================================================================== class Array #-------------------------------------------------------------------------- # * Select! #-------------------------------------------------------------------------- unless self.respond_to?(:select!) def select!(&block) result = self.select(&block) self.replace(result) end end end #============================================================================== # ** RPG #============================================================================== for Klass in [RPG::Item, RPG::Skill] class Klass #-------------------------------------------------------------------------- # * Public Instance Variables #-------------------------------------------------------------------------- attr_writer :scope_ally, :scope_enemy, :scope_all, :scope_random attr_writer :scope_user, :scope_alive, :scope_dead #-------------------------------------------------------------------------- # * For Allies #-------------------------------------------------------------------------- def scope_ally @scope_ally = [3, 4, 5, 6].include?(@scope) if @scope_ally == nil return @scope_ally end #-------------------------------------------------------------------------- # * For Enemies #-------------------------------------------------------------------------- def scope_enemy @scope_enemy = [1, 2].include?(@scope) if @scope_enemy == nil return @scope_enemy end #-------------------------------------------------------------------------- # * For All Party/Troop Members #-------------------------------------------------------------------------- def scope_all @scope_all = [2, 4, 6].include?(@scope) if @scope_all == nil return @scope_all end #-------------------------------------------------------------------------- # * Random Pick #-------------------------------------------------------------------------- def scope_random @scope_random = false if @scope_random == nil return @scope_random end #-------------------------------------------------------------------------- # * User included #-------------------------------------------------------------------------- def scope_user if Scope::DEFAULT_DEAD_SELECT == true @scope_user = [3, 4, 5, 6, 7].include?(@scope) if @scope_user == nil else @scope_user = [3, 4, 7].include?(@scope) if @scope_user == nil end return @scope_user end #-------------------------------------------------------------------------- # * Only Alive #-------------------------------------------------------------------------- def scope_alive @scope_alive = [1, 2, 3, 4, 7].include?(@scope) if @scope_alive == nil return @scope_alive end #-------------------------------------------------------------------------- # * Only Dead #-------------------------------------------------------------------------- def scope_dead @scope_dead = [5, 6].include?(@scope) if @scope_dead == nil return @scope_dead end #-------------------------------------------------------------------------- # * Define Scope #-------------------------------------------------------------------------- def set_scope(ally,enemy,all,random=false,user=true,alive=true,dead=false) self.scope_ally = ally self.scope_enemy = enemy self.scope_all = all self.scope_random = random self.scope_user = user self.scope_alive = alive self.scope_dead = dead end #-------------------------------------------------------------------------- # * Special Restrictions #-------------------------------------------------------------------------- def scope_rest @scope_rest = [] if @scope_rest == nil return @scope_rest end def restriction(&block) self.scope_rest.push(block) end def restrictions() self.scope_rest end def clear_restrictions() self.scope_rest.clear end #-------------------------------------------------------------------------- end end #============================================================================== # ** Arrow_Base #============================================================================== class Arrow_Base < Sprite attr_reader :user attr_reader :item attr_reader :target attr_reader :targets #-------------------------------------------------------------------------- # * Initialize #-------------------------------------------------------------------------- def initialize(viewport, user, item) super(viewport) self.bitmap = RPG::Cache.windowskin($game_system.windowskin_name) self.ox = 16 self.oy = 64 self.z = 2500 @blink_count = 0 @index = 0 @help_window = nil @user = user @item = item @targets = target_battlers @target = @targets[0] update_sprite end #-------------------------------------------------------------------------- # * Get index #-------------------------------------------------------------------------- def index return @targets.index(@target) rescue -1 end #-------------------------------------------------------------------------- # * Set index #-------------------------------------------------------------------------- def index=(index) @target = @targets[index] end #-------------------------------------------------------------------------- # * Get selectable targets #-------------------------------------------------------------------------- def target_battlers if @user.is_a?(Game_Actor) allies = $game_party.actors.clone enemies = $game_troop.enemies.clone else allies = $game_troop.enemies.clone enemies = $game_party.actors.clone end allies.delete_if {|target| target.hidden} enemies.delete_if{|target| target.hidden} if @item == nil enemies.delete_if {|target| !target.exist? } return enemies end result = [] if @item.scope_ally == true for target in allies result.push(target) end end if @item.scope_enemy == true for target in enemies result.push(target) end end if @item.scope_user == true if !result.include?(@user) result.push(@user) end end if @item.scope_user == false result.delete(@user) end if @item.scope_alive == true && Scope::DEFAULT_DEAD_SELECT == false result.select!{|target| !target.dead?} end if @item.scope_dead == true && Scope::DEFAULT_DEAD_SELECT == false result.select!{|target| target.dead?} end for r in @item.restrictions if r.arity == 1 result.select!{|target| r.call(target) == true} rescue nil else result.select!{|target| r.call == true} rescue nil end end return result end #-------------------------------------------------------------------------- # * Update #-------------------------------------------------------------------------- def update update_sprite if @help_window != nil update_help end if @target == nil self.visible = false return end self.visible = true # Next target if Input.repeat?(Input::RIGHT) $game_system.se_play($data_system.cursor_se) self.index = (self.index + 1) % @targets.size end # Previous target if Input.repeat?(Input::LEFT) $game_system.se_play($data_system.cursor_se) self.index = (self.index - 1) % @targets.size end # Place arrow over target if @target != nil self.x = @target.screen_x self.y = @target.screen_y end end #-------------------------------------------------------------------------- # * Update Sprite #-------------------------------------------------------------------------- def update_sprite @blink_count = (@blink_count + 1) % 8 if @blink_count < 4 self.src_rect.set(128, 96, 32, 32) else self.src_rect.set(160, 96, 32, 32) end end #-------------------------------------------------------------------------- # * Update Help #-------------------------------------------------------------------------- def update_help if @target == nil @help_window.set_text("") return end if @target.is_a?(Game_Actor) @help_window.set_actor(@target) else @help_window.set_enemy(@target) end end end #============================================================================== # ** Game_Battler #============================================================================== class Game_Battler #-------------------------------------------------------------------------- # * Check if the skill can be used #-------------------------------------------------------------------------- alias wecoc_scope_skill_use? skill_can_use? unless $@ def skill_can_use?(skill_id) skill = $data_skills[skill_id] return false if skill.nil? # Skill doesn't exist return false if !self.exist? # User is hidden or dead if self.is_a?(Game_Actor) members = $game_party.actors.clone else members = $game_troop.enemies.clone end if members.size == 1 # User is the only member and requires an ally if skill.user == false && skill.ally == false && skill.enemy == false return false end end for r in skill.restrictions if r.arity == 1 members.select!{|target| r.call(target) == true} rescue nil else members.select!{|target| r.call == true} rescue nil end end return false if members.size == 0 return wecoc_scope_skill_use?(skill_id) end #-------------------------------------------------------------------------- # * Check if the item can be used #-------------------------------------------------------------------------- def item_can_use?(item_id) item = $data_items[item_id] return false if item.nil? # Item doesn't exist return false if !self.exist? # User is hidden or dead if self.is_a?(Game_Actor) # Party doesn't contain that item return false if $game_party.item_number(item_id) == 0 # Item restrictions (Only menu / battle) return false if $game_temp.in_battle && item.occasion == 2 return false if !$game_temp.in_battle && item.occasion == 1 members = $game_party.actors.clone else members = $game_troop.enemies.clone end if members.size == 1 # User is the only member and requires an ally if item.user == false && item.ally == false && item.enemy == false return false end end for r in item.restrictions if r.arity == 1 members.select!{|target| r.call(target) == true} rescue nil else members.select!{|target| r.call == true} rescue nil end end return false if members.size == 0 return true end end #============================================================================== # ** Game_Party #============================================================================== class Game_Party #-------------------------------------------------------------------------- # * Check if the party can use an item #-------------------------------------------------------------------------- def item_can_use?(item_id) for member in $game_party.actors if member.item_can_use?(item_id) return true end end return false end end #============================================================================== # ** Scene_Battle #============================================================================== class Scene_Battle #-------------------------------------------------------------------------- # * Select enemy #-------------------------------------------------------------------------- def start_enemy_select item = nil if @active_battler.current_action.kind == 1 item = @skill if @skill != nil end if @active_battler.current_action.kind == 2 item = @item if @item != nil end @enemy_arrow = Arrow_Base.new(@spriteset.viewport2, @active_battler, item) @enemy_arrow.help_window = @help_window @actor_command_window.active = false @actor_command_window.visible = false end #-------------------------------------------------------------------------- # * Select actor #-------------------------------------------------------------------------- def start_actor_select item = nil if @active_battler.current_action.kind == 1 item = @skill if @skill != nil end if @active_battler.current_action.kind == 2 item = @item if @item != nil end @actor_arrow = Arrow_Base.new(@spriteset.viewport2, @active_battler, item) @actor_arrow.index = @actor_index @actor_arrow.help_window = @help_window @actor_command_window.active = false @actor_command_window.visible = false end #-------------------------------------------------------------------------- # * Apply skill #-------------------------------------------------------------------------- def make_skill_action_result @skill = $data_skills[@active_battler.current_action.skill_id] unless @active_battler.current_action.forcing unless @active_battler.skill_can_use?(@skill.id) $game_temp.forcing_battler = nil @phase4_step = 1 return end end @active_battler.sp -= @skill.sp_cost @status_window.refresh @help_window.set_text(@skill.name, 1) @animation1_id = @skill.animation1_id @animation2_id = @skill.animation2_id @common_event_id = @skill.common_event_id @target_battlers.clear @target_battlers = set_target_battlers(@skill) for target in @target_battlers target.skill_effect(@active_battler, @skill) end end #-------------------------------------------------------------------------- # * Apply item #-------------------------------------------------------------------------- def make_item_action_result @item = $data_items[@active_battler.current_action.item_id] unless @active_battler.item_can_use?(@item.id) @phase4_step = 1 return end if @item.consumable $game_party.lose_item(@item.id, 1) end @help_window.set_text(@item.name, 1) @animation1_id = @item.animation1_id @animation2_id = @item.animation2_id @common_event_id = @item.common_event_id index = @active_battler.current_action.target_index target = $game_party.smooth_target_actor(index) @target_battlers.clear @target_battlers = set_target_battlers(@item) for target in @target_battlers target.item_effect(@item) end end #-------------------------------------------------------------------------- # * Get available targets for an item or skill #-------------------------------------------------------------------------- def set_target_battlers(item) if @active_battler.is_a?(Game_Actor) allies = $game_party.actors.clone enemies = $game_troop.enemies.clone else allies = $game_troop.enemies.clone enemies = $game_party.actors.clone end index = @active_battler.current_action.target_index result = [] if item.scope_ally == true for target in allies result.push(target) end end if item.scope_enemy == true for target in enemies result.push(target) end end if item.scope_user == true if !result.include?(@active_battler) result.push(@active_battler) end end if item.scope_user == false result.delete(@active_battler) end if item.scope_all == false if item.scope_random == true result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false else if Scope::DEFAULT_DEAD_SELECT == false result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false end end end result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false for r in item.restrictions if r.arity == 1 result.select!{|target| r.call(target) == true } rescue nil else result.select!{|target| r.call == true } rescue nil end end if item.scope_all == false if item.scope_random == true result = [result[rand(result.size)]] else result = [result[index]] end end return result end end 复制代码
DFS version
Spoiler: Code
Ruby: #============================================================================== # ** [XP] Advanced Scope v1.1 # This version is compatible with Data File Save, use it only if you're # using that script. This script must be placed BELOW Data File Save. #------------------------------------------------------------------------------ # Author: Wecoc (credits are optional) #------------------------------------------------------------------------------ # Defines new types of scope for items and skills in battle #------------------------------------------------------------------------------ # $data_items[ID] and $data_skills[ID] work exactly the same way # To define the target use: # $data_items[ID].scope_ally = true | false # Ally # $data_items[ID].scope_enemy = true | false # Enemy # $data_items[ID].scope_all = true | false # Entire group / Only one # $data_items[ID].scope_random = true | false # Pick one randomly # $data_items[ID].scope_user = true | false # Include user # $data_items[ID].scope_alive = true | false # Only alive members # $data_items[ID].scope_dead = true | false # Only dead members #------------------------------------------------------------------------------ # $data_items[ID].restriction(&block) # Set custom restriction # $data_items[ID].restrictions # Get all custom restrictions # $data_items[ID].clear_restrictions # Clear all custom restrictions #============================================================================== #============================================================================== # ** Scope Configuration #============================================================================== module Scope #---------------------------------------------------------------------------- # Default Dead Select #---------------------------------------------------------------------------- # By default if an item only affects members that are alive you can still # select a dead member, but the item won't have any effect. # The same happens with items that only affect dead members. # Set to false if you want to disable that and apply a strict restriction. #---------------------------------------------------------------------------- DEFAULT_DEAD_SELECT = true end #============================================================================== # ** Array #============================================================================== class Array #-------------------------------------------------------------------------- # * Select! #-------------------------------------------------------------------------- unless self.respond_to?(:select!) def select!(&block) result = self.select(&block) self.replace(result) end end end #============================================================================== # ** RPG #============================================================================== for Klass in [RPG::Item, RPG::Skill] class Klass ALLY = [3, 4, 5, 6] ENEMY = [1, 2] ALL = [2, 4, 6] ALIVE = [1, 2, 3, 4, 7] DEAD = [5, 6] USER = [3, 4, 5, 6, 7] define_method(:scope_ally) { @scope_ally |= ALLY.include?(@scope) } define_method(:scope_enemy) { @scope_enemy |= ENEMY.include?(@scope) } define_method(:scope_all) { @scope_all |= ALL.include?(@scope) } define_method(:scope_random) { @scope_random |= false } define_method(:scope_alive) { @scope_alive |= ALIVE.include?(@scope) } define_method(:scope_dead) { @scope_dead |= DEAD.include?(@scope) } define_method(:scope_user) { @scope_user |= USER.include?(@scope) } define_method(:scope_rest) { @scope_rest = [] } define_method(:restrictions) { @scope_rest = [] } def restriction(&block) @scope_rest.push(block) end def clear_restrictions @scope_rest.clear end def set_scope(ally,enemy,all,random=false,user=true,alive=true,dead=false) @scope_ally = ally @scope_enemy = enemy @scope_all = all @scope_random = random @scope_user = user @scope_alive = alive @scope_dead = dead end end end #============================================================================== # ** Arrow_Base #============================================================================== class Arrow_Base < Sprite attr_reader :user attr_reader :item attr_reader :target attr_reader :targets #-------------------------------------------------------------------------- # * Initialize #-------------------------------------------------------------------------- def initialize(viewport, user, item) super(viewport) self.bitmap = RPG::Cache.windowskin($game_system.windowskin_name) self.ox = 16 self.oy = 64 self.z = 2500 @blink_count = 0 @index = 0 @help_window = nil @user = user @item = item @targets = target_battlers @target = @targets[0] update_sprite end #-------------------------------------------------------------------------- # * Get index #-------------------------------------------------------------------------- def index return @targets.index(@target) rescue -1 end #-------------------------------------------------------------------------- # * Set index #-------------------------------------------------------------------------- def index=(index) @target = @targets[index] end #-------------------------------------------------------------------------- # * Get selectable targets #-------------------------------------------------------------------------- def target_battlers if @user.is_a?(Game_Actor) allies = $game_party.actors.clone enemies = $game_troop.enemies.clone else allies = $game_troop.enemies.clone enemies = $game_party.actors.clone end allies.delete_if {|target| target.hidden} enemies.delete_if{|target| target.hidden} if @item == nil enemies.delete_if {|target| !target.exist?} return enemies end result = [] if @item.scope_ally == true for target in allies result.push(target) end end if @item.scope_enemy == true for target in enemies result.push(target) end end if @item.scope_user == true if !result.include?(@user) result.push(@user) end end if @item.scope_user == false result.delete(@user) end if @item.scope_alive == true && Scope::DEFAULT_DEAD_SELECT == false result.select!{|target| !target.dead?} end if @item.scope_dead == true && Scope::DEFAULT_DEAD_SELECT == false result.select!{|target| target.dead?} end for r in @item.restrictions if r.arity == 1 result.select!{|target| r.call(target) == true} rescue nil else result.select!{|target| r.call == true} rescue nil end end return result end #-------------------------------------------------------------------------- # * Update #-------------------------------------------------------------------------- def update update_sprite if @help_window != nil update_help end if @target == nil self.visible = false return end self.visible = true # Next target if Input.repeat?(Input::RIGHT) $game_system.se_play($data_system.cursor_se) self.index = (self.index + 1) % @targets.size end # Previous target if Input.repeat?(Input::LEFT) $game_system.se_play($data_system.cursor_se) self.index = (self.index - 1) % @targets.size end # Place arrow over target if @target != nil self.x = @target.screen_x self.y = @target.screen_y end end #-------------------------------------------------------------------------- # * Update Sprite #-------------------------------------------------------------------------- def update_sprite @blink_count = (@blink_count + 1) % 8 if @blink_count < 4 self.src_rect.set(128, 96, 32, 32) else self.src_rect.set(160, 96, 32, 32) end end #-------------------------------------------------------------------------- # * Update Help #-------------------------------------------------------------------------- def update_help if @target == nil @help_window.set_text("") return end if @target.is_a?(Game_Actor) @help_window.set_actor(@target) else @help_window.set_enemy(@target) end end end #============================================================================== # ** Game_Battler #============================================================================== class Game_Battler #-------------------------------------------------------------------------- # * Check if the skill can be used #-------------------------------------------------------------------------- alias wecoc_scope_skill_use? skill_can_use? unless $@ def skill_can_use?(skill_id) skill = $data_skills[skill_id] return false if skill.nil? # Skill doesn't exist return false if !self.exist? # User is hidden or dead if self.is_a?(Game_Actor) members = $game_party.actors.clone else members = $game_troop.enemies.clone end if members.size == 1 # User is the only member and requires an ally if skill.user == false && skill.ally == false && skill.enemy == false return false end end for r in skill.restrictions if r.arity == 1 members.select!{|target| r.call(target) == true} rescue nil else members.select!{|target| r.call == true} rescue nil end end return false if members.size == 0 return wecoc_scope_skill_use?(skill_id) end #-------------------------------------------------------------------------- # * Check if the item can be used #-------------------------------------------------------------------------- def item_can_use?(item_id) item = $data_items[item_id] return false if item.nil? # Item doesn't exist return false if !self.exist? # User is hidden or dead if self.is_a?(Game_Actor) # Party doesn't contain that item return false if $game_party.item_number(item_id) == 0 # Item restrictions (Only menu / battle) return false if $game_temp.in_battle && item.occasion == 2 return false if !$game_temp.in_battle && item.occasion == 1 members = $game_party.actors.clone else members = $game_troop.enemies.clone end if members.size == 1 # User is the only member and requires an ally if item.user == false && item.ally == false && item.enemy == false return false end end for r in item.restrictions if r.arity == 1 members.select!{|target| r.call(target) == true} rescue nil else members.select!{|target| r.call == true} rescue nil end end return false if members.size == 0 return true end end #============================================================================== # ** Game_Party #============================================================================== class Game_Party #-------------------------------------------------------------------------- # * Check if the party can use an item #-------------------------------------------------------------------------- def item_can_use?(item_id) for member in $game_party.actors if member.item_can_use?(item_id) return true end end return false end end #============================================================================== # ** Scene_Battle #============================================================================== class Scene_Battle #-------------------------------------------------------------------------- # * Select enemy #-------------------------------------------------------------------------- def start_enemy_select item = nil if @active_battler.current_action.kind == 1 item = @skill if @skill != nil end if @active_battler.current_action.kind == 2 item = @item if @item != nil end @enemy_arrow = Arrow_Base.new(@spriteset.viewport2, @active_battler, item) @enemy_arrow.help_window = @help_window @actor_command_window.active = false @actor_command_window.visible = false end #-------------------------------------------------------------------------- # * Select actor #-------------------------------------------------------------------------- def start_actor_select item = nil if @active_battler.current_action.kind == 1 item = @skill if @skill != nil end if @active_battler.current_action.kind == 2 item = @item if @item != nil end @actor_arrow = Arrow_Base.new(@spriteset.viewport2, @active_battler, item) @actor_arrow.index = @actor_index @actor_arrow.help_window = @help_window @actor_command_window.active = false @actor_command_window.visible = false end #-------------------------------------------------------------------------- # * Apply skill #-------------------------------------------------------------------------- def make_skill_action_result @skill = $data_skills[@active_battler.current_action.skill_id] unless @active_battler.current_action.forcing unless @active_battler.skill_can_use?(@skill.id) $game_temp.forcing_battler = nil @phase4_step = 1 return end end @active_battler.sp -= @skill.sp_cost @status_window.refresh @help_window.set_text(@skill.name, 1) @animation1_id = @skill.animation1_id @animation2_id = @skill.animation2_id @common_event_id = @skill.common_event_id @target_battlers.clear @target_battlers = set_target_battlers(@skill) for target in @target_battlers target.skill_effect(@active_battler, @skill) end end #-------------------------------------------------------------------------- # * Apply item #-------------------------------------------------------------------------- def make_item_action_result @item = $data_items[@active_battler.current_action.item_id] unless @active_battler.item_can_use?(@item.id) @phase4_step = 1 return end if @item.consumable $game_party.lose_item(@item.id, 1) end @help_window.set_text(@item.name, 1) @animation1_id = @item.animation1_id @animation2_id = @item.animation2_id @common_event_id = @item.common_event_id index = @active_battler.current_action.target_index target = $game_party.smooth_target_actor(index) @target_battlers.clear @target_battlers = set_target_battlers(@item) for target in @target_battlers target.item_effect(@item) end end #-------------------------------------------------------------------------- # * Get available targets for an item or skill #-------------------------------------------------------------------------- def set_target_battlers(item) if @active_battler.is_a?(Game_Actor) allies = $game_party.actors.clone enemies = $game_troop.enemies.clone else allies = $game_troop.enemies.clone enemies = $game_party.actors.clone end index = @active_battler.current_action.target_index result = [] if item.scope_ally == true for target in allies result.push(target) end end if item.scope_enemy == true for target in enemies result.push(target) end end if item.scope_user == true if !result.include?(@active_battler) result.push(@active_battler) end end if item.scope_user == false result.delete(@active_battler) end if item.scope_all == false if item.scope_random == true result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false else if Scope::DEFAULT_DEAD_SELECT == false result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false end end end result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false for r in item.restrictions if r.arity == 1 result.select!{|target| r.call(target) == true} rescue nil else result.select!{|target| r.call == true} rescue nil end end if item.scope_all == false if item.scope_random == true result = [result[rand(result.size)]] else result = [result[index]] end end return result end end 复制代码
Advanced Instructions
Spoiler: Custom restriction examples
Targets must have a specific class ID$data_items[1].restriction {|target| target.is_a?(Game_Actor) && target.class_id == 3} 复制代码
Target only certain enemy IDs$data_items[1].restriction {|target| target.is_a?(Game_Enemy) && [20, 23, 30, 31].include?(target.id) } 复制代码
Target battlers with more than 50% HP$data_items[1].restriction {|target| target.hp >= (target.maxhp * 50 / 100) } 复制代码
Target battlers that have a certain state$data_items[1].restriction {|target| target.state?(2) } 复制代码
Target actors that know a certain skill$data_items[1].restriction {|target| target.skill_learn?(50) } 复制代码
Target enemies that know a certain skill$data_items[1].restriction {|target| target.actions.any?{|action| action.skill_id == 50 }} 复制代码
Those should be defined both when creating a new game and when loading, but if you're using DFS you only have to define this once wherever you want. FAQ
Spoiler: FAQ
- I want to apply a new restriction from an event script call, but those lines are too long.
Yeah, all my examples are like this
Code: $data_items[ID].restriction { |target| (ACTION) } 复制代码
but you can separate it like this
Code: $data_items[ID].restriction do |target| (ACTION) end 复制代码
- I want to make a "Random Ally" skill, but when there's only one actor (alive) I don't want that skill to be active, since that wouldn't be random at all.
Good point. You can do that with a custom restriction like this
Code: $data_items[1].restriction do n = 0 ; for target in $game_party.actors n += 1 if target.exist? end (n > 1) end 复制代码
Monster-based Scope (AddOn)
This AddOn allows to make some enemies untargetable based on a specific condition. That condition can be the ID of the attacker, his equipment, a switch or any other condition. The fact it cannot be selected implies that if neither meets the condition, the attack and offensive abilities will be directly deactivated for the actor in question.
The only configurable part is the module Monster_Scope, and I made some examples on the instructions of the script.
Normal version (independent)
Spoiler: Code
Ruby: #============================================================================== # ** [XP] Monster-based Scope v1.1 #------------------------------------------------------------------------------ # Author: Wecoc (no credits required) #------------------------------------------------------------------------------ # This script allows to make some enemies untargetable based on a specific # condition. That condition can be the ID of the attacker, his equipment, # a switch or any other condition. The fact it cannot be selected implies # that if neither meets the condition, the attack and offensive abilities # will be directly deactivated for the actor in question. #------------------------------------------------------------------------------ # It allows multiple conditions, simply define them as an array # 1 => ["actor.id == 1", "actor.weapon_id == 1", "actor.id == 1"] # When defined by string, the condition is the same # When defined by array, the first one is for attack, second for skills and # third for items. #------------------------------------------------------------------------------ # To use this you only have to define the conditions as an eval on the constant # SCOPE_CONDITION in the very start of the script. # ID monster => "condition" # Condition examples # # Can only be attacked by the actor with ID 1 # actor.id == 1 # # Can only be attacked if the attacker has weapon with ID 1 equipped # actor.weapon_id == 1 # Conditions accept two shortcuts; 'actor' and 'target' #============================================================================== module Monster_Scope # Set here the condition for each enemy ID SCOPE_CONDITION = { 1 => "actor.id == 1", 2 => "actor.weapon_id == 1" } end class Game_Actor alias monster_scope_skill_use? skill_can_use? unless $@ def skill_can_use?(skill_id) if [1,2].include?($data_skills[skill_id].scope) if $scene.is_a?(Scene_Battle) && !$scene.can_select_any_enemy?(1) return false end end monster_scope_skill_use?(skill_id) end end class Game_Party alias monster_scope_item_use? item_can_use? unless $@ def item_can_use?(item_id) if [1,2].include?($data_items[item_id].scope) if $scene.is_a?(Scene_Battle) && !$scene.can_select_any_enemy?(2) return false end end monster_scope_item_use?(item_id) end end class Scene_Battle def can_select_any_enemy?(kind=0) # Get if any enemy can be selected return if @active_battler.nil? || @active_battler.is_a?(Game_Enemy) for target in $game_troop.enemies return true if !Monster_Scope::SCOPE_CONDITION.keys.include?(target.id) if Monster_Scope::SCOPE_CONDITION[target.id].is_a?(Array) e = Monster_Scope::SCOPE_CONDITION[target.id][kind] else e = Monster_Scope::SCOPE_CONDITION[target.id] end result = instance_eval("actor = @active_battler;" + e) return true if result == true end return false end def get_selectable_enemies(kind=0) # Set target battlers based on the monster scope condition return if @active_battler.nil? || @active_battler.is_a?(Game_Enemy) selectable_enemies = [] for target in $game_troop.enemies index = $game_troop.enemies.index(target) if Monster_Scope::SCOPE_CONDITION.keys.include?(target.id) if Monster_Scope::SCOPE_CONDITION[target.id].is_a?(Array) e = Monster_Scope::SCOPE_CONDITION[target.id][kind] else e = Monster_Scope::SCOPE_CONDITION[target.id] end result = instance_eval("actor = @active_battler;" + e) selectable_enemies.push(index) if result == true else selectable_enemies.push(index) end end return selectable_enemies end def start_enemy_select targets = get_selectable_enemies(@active_battler.current_action.kind) @enemy_arrow = Arrow_Enemy.new(@spriteset.viewport1, targets) @enemy_arrow.help_window = @help_window @actor_command_window.active = false @actor_command_window.visible = false end alias monster_scope_next phase3_next_actor unless $@ def phase3_next_actor @actor_command_window.refresh monster_scope_next # Disable Attack command when none enemies can be selected (display) if !@active_battler.nil? && !can_select_any_enemy?(0) @actor_command_window.disable_item(0) end end alias monster_scope_prior phase3_prior_actor unless $@ def phase3_prior_actor @actor_command_window.refresh monster_scope_prior # Disable Attack command when none enemies can be selected (display) if !@active_battler.nil? && !can_select_any_enemy?(0) @actor_command_window.disable_item(0) end end alias monster_scope_phase3_upd update_phase3_basic_command unless $@ def update_phase3_basic_command # Disable Attack command when none enemies can be selected if Input.trigger?(Input::C) if @actor_command_window.index == 0 if !@active_battler.nil? && !can_select_any_enemy?(0) $game_system.se_play($data_system.buzzer_se) return end end end monster_scope_phase3_upd end end class Arrow_Enemy < Arrow_Base def initialize(viewport, targets=nil) targets = (0...$game_troop.enemies.size).to_a if targets == nil @targets = targets super(viewport) end def exist? return self.enemy.exist? && @targets.include?(self.enemy.index) end def update super $game_troop.enemies.size.times do break if self.exist? @index += 1 @index %= $game_troop.enemies.size end if Input.repeat?(Input::RIGHT) $game_system.se_play($data_system.cursor_se) $game_troop.enemies.size.times do @index += 1 @index %= $game_troop.enemies.size break if self.exist? end end if Input.repeat?(Input::LEFT) $game_system.se_play($data_system.cursor_se) $game_troop.enemies.size.times do @index += $game_troop.enemies.size - 1 @index %= $game_troop.enemies.size break if self.exist? end end if self.enemy != nil self.x = self.enemy.screen_x self.y = self.enemy.screen_y end end end 复制代码
Advanced Scope version
Spoiler: Code
Ruby: #============================================================================== # ** [XP] Monster-based Scope v1.1 [Advanced Scope] #------------------------------------------------------------------------------ # Author: Wecoc (no credits required) # This version requires the script Advanced Scope #------------------------------------------------------------------------------ # This script allows to make some enemies untargetable based on a specific # condition. That condition can be the ID of the attacker, his equipment, # a switch or any other condition. The fact it cannot be selected implies # that if neither meets the condition, the attack and offensive abilities # will be directly deactivated for the actor in question. #------------------------------------------------------------------------------ # It allows multiple conditions, simply define them as an array # 1 => ["actor.id == 1", "actor.weapon_id == 1", "actor.id == 1"] # When defined by string, the condition is the same # When defined by array, the first one is for attack, second for skills and # third for items. #------------------------------------------------------------------------------ # To use this you only have to define the conditions as an eval on the constant # SCOPE_CONDITION in the very start of the script. # ID monster => "condition" # Condition examples # # Can only be attacked by the actor with ID 1 # actor.id == 1 # # Can only be attacked if the attacker has weapon with ID 1 equipped # actor.weapon_id == 1 # Conditions accept two shortcuts; 'actor' and 'target' #============================================================================== module Monster_Scope # Set here the condition for each enemy ID SCOPE_CONDITION = { 1 => "actor.id == 1", 2 => "actor.weapon_id == 1" } end class Game_Actor alias monster_scope_skill_use? skill_can_use? unless $@ def skill_can_use?(skill_id) if $data_skills[skill_id].scope_enemy if $scene.is_a?(Scene_Battle) && !$scene.can_select_any_enemy?(1) return false end end monster_scope_skill_use?(skill_id) end end class Game_Party alias monster_scope_item_use? item_can_use? unless $@ def item_can_use?(item_id) if $data_items[item_id].scope_enemy if $scene.is_a?(Scene_Battle) && !$scene.can_select_any_enemy?(2) return false end end monster_scope_item_use?(item_id) end end class Arrow_Base < Sprite alias monster_scope_ini initialize unless $@ def initialize(viewport, user, item, targets=nil) monster_scope_ini(viewport, user, item) if item.nil? && !targets.nil? @targets = targets @target = @targets[0] update_sprite end end end class Scene_Battle def can_select_any_enemy?(kind=0) # Get if any enemy can be selected return if @active_battler.nil? || @active_battler.is_a?(Game_Enemy) for target in $game_troop.enemies return true if !Monster_Scope::SCOPE_CONDITION.keys.include?(target.id) if Monster_Scope::SCOPE_CONDITION[target.id].is_a?(Array) e = Monster_Scope::SCOPE_CONDITION[target.id][kind] else e = Monster_Scope::SCOPE_CONDITION[target.id] end result = instance_eval("actor = @active_battler;" + e) return true if result == true end return false end def get_selectable_enemies(kind=0) # Set target battlers based on the monster scope condition return if @active_battler.nil? || @active_battler.is_a?(Game_Enemy) selectable_enemies = [] for target in $game_troop.enemies index = $game_troop.enemies.index(target) if Monster_Scope::SCOPE_CONDITION.keys.include?(target.id) if Monster_Scope::SCOPE_CONDITION[target.id].is_a?(Array) e = Monster_Scope::SCOPE_CONDITION[target.id][kind] else e = Monster_Scope::SCOPE_CONDITION[target.id] end result = instance_eval("actor = @active_battler;" + e) selectable_enemies.push(target) if result == true else selectable_enemies.push(target) end end return selectable_enemies end alias monster_scope_enemy_select start_enemy_select def start_enemy_select if @active_battler.current_action.kind == 0 # Attack targets = get_selectable_enemies(@active_battler.current_action.kind) @enemy_arrow = Arrow_Base.new(@spriteset.viewport2, @active_battler, nil, targets) @enemy_arrow.help_window = @help_window @actor_command_window.active = false @actor_command_window.visible = false return end monster_scope_enemy_select end alias monster_scope_next phase3_next_actor unless $@ def phase3_next_actor @actor_command_window.refresh monster_scope_next # Disable Attack command when none enemies can be selected (display) if !@active_battler.nil? && !can_select_any_enemy?(0) @actor_command_window.disable_item(0) end end alias monster_scope_prior phase3_prior_actor unless $@ def phase3_prior_actor @actor_command_window.refresh monster_scope_prior # Disable Attack command when none enemies can be selected (display) if !@active_battler.nil? && !can_select_any_enemy?(0) @actor_command_window.disable_item(0) end end alias monster_scope_phase3_upd update_phase3_basic_command unless $@ def update_phase3_basic_command # Disable Attack command when none enemies can be selected if Input.trigger?(Input::C) if @actor_command_window.index == 0 if !@active_battler.nil? && !can_select_any_enemy?(0) $game_system.se_play($data_system.buzzer_se) return end end end monster_scope_phase3_upd end def set_target_battlers(item) if @active_battler.is_a?(Game_Actor) allies = $game_party.actors.clone enemies = $game_troop.enemies.clone else allies = $game_troop.enemies.clone enemies = $game_party.actors.clone end index = @active_battler.current_action.target_index result = [] if item.scope_ally == true for target in allies result.push(target) end end if item.scope_enemy == true for target in enemies result.push(target) end end if item.scope_user == true if !result.include?(@active_battler) result.push(@active_battler) end end if item.scope_user == false result.delete(@active_battler) end if item.scope_all == false if item.scope_random == true result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false else if Scope::DEFAULT_DEAD_SELECT == false result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false end end end result.select!{|target| !target.dead?} if item.scope_alive == true result.select!{|target| target.dead?} if item.scope_alive == false for r in item.restrictions if r.arity == 1 result.select!{|target| r.call(target) == true } rescue nil else result.select!{|target| r.call == true } rescue nil end end # --- Monster Scope --- kind = 0 # Default kind = 1 if item.is_a?(RPG::Skill); kind = 2 if item.is_a?(RPG::Item) selectable_enemies = $scene.get_selectable_enemies(kind) for target in result if target.is_a?(Game_Enemy) && !selectable_enemies.include?(target) result.delete(target) end end # ------ if item.scope_all == false if item.scope_random == true result = [result[rand(result.size)]] else result = [result[index]] end end return result end end 复制代码
I hope you like this. It's insane how long my posts tend to be
本贴来自国际rpgmaker官方论坛作者:Wecoc处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:
https://forums.rpgmakerweb.com/threads/advanced-scopes-more-target-options-for-battlers.139759/