Preserved forum archive. This topic stores the original first post and locally mirrored RPG Maker Web attachments when available. It is posted by the BMMPlay archive account, not by the original creator.
Original Source
- Original title: Advanced Scopes - More target options for battlers
- Original author: Wecoc
- Original date: August 20, 2021
- Source thread: https://forums.rpgmakerweb.com/threads/advanced-scopes-more-target-options-for-battlers.139759/
- Source forum path: Game Development Engines > Ruby Game System (RGSS) Scripts > RGSS Scripts (RMXP)
Summary
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:
Archived First Post
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)
DFS version
Advanced Instructions
FAQ
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)
Advanced Scope version
I hope you like this. It's insane how long my posts tend to be
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)
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
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
Targets must have a specific class ID
Target only certain enemy IDs
Target battlers with more than 50% HP
Target battlers that have a certain state
Target actors that know a certain skill
Target enemies that know a certain skill
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.
$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
- 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
but you can separate it like this
- 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
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)
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
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
Downloads / Referenced Files
Log in to download
Log in, then follow the RPG Maker Developers Group to see these download links.
Log in to downloadLicense / Terms Note
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.
Creator Claims / Removal
If you are the original creator and want this listing reassigned, edited, or removed, join BMMPlay and contact the moderators with proof that matches the original RPG Maker Web profile, linked GitHub, itch.io page, or another public creator identity.
Replies (0)
No replies yet.
0
replies
2
views
Topic Summary
Loading summary...