Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ############################################
- # #
- # ENHANCED RANDOM TARGETS SCRIPT #
- # #
- # v1.1 for RPG Maker VX Ace #
- # #
- # Created by Jason "Wavelength" Commander #
- # #
- ############################################
- # "Hit me once, shame on you. Hit me four times with a
- # '4 Random Enemies' spell... still, shame on you."
- # ~ Succubus
- ############################################
- # #
- # ABOUT THIS SCRIPT #
- # #
- ############################################
- # This script provides a significant expansion to VX Ace's
- # "Random Targets" functionality for Skills and Items,
- # and gives you greater control over how random targeting
- # works. Among the types of behavior you can set for any
- # Skill or Item in your game:
- #
- # * The skill/item can be used on random allies
- #
- # * The skill/item can avoid hitting the same target more
- # than once
- #
- # * The skill/item can hit as many random targets as you
- # like - not limited to 4
- #
- # * The skill/item can hit one target the player selects,
- # PLUS any number of additional random targets
- #
- # * The skill/item can be guaranteed to hit a specified
- # number of different enemies
- # Note that this is NOT a script that changes the AI's choices
- # in battle - it is a script that expands and improves the
- # way that skills with Random Target scopes work.
- # This script is compatible with most other scripts. Be careful
- # about using it with other scripts that change how targeting
- # or random scopes work.
- # Thank you to everyone who encouraged me to write and publish
- # this script!
- ############################################
- # #
- # TERMS OF USE #
- # #
- ############################################
- # Free to use for non-commercial projects - just credit me
- # A license is required to use this script in commercial or
- # semi-commercial projects. Please visit my website
- # wavescripts.wordpress.com for more info about obtaining
- # a license for my scripts.
- # You may freely share or modify this script, but you cannot
- # sell it (even if modified) without my written permission
- # Please preserve the header (with version #) and terms of use;
- # besides that, feel free to remove any commenting you please
- ############################################
- # #
- # HOW TO USE THIS SCRIPT #
- # #
- ############################################
- # This script should be placed in the "Materials" section
- # of the script editor. For maximum compatibility,
- # I recommend placing this script above all of your
- # other scripts.
- # Then, simply add notetags to the "Note" box for Skills or Items
- # in your database to determine their Random Targeting behavior.
- # You can also choose not to add a notetag to allow the Skill/Item
- # to use its default targeting behavior.
- # Use the following format for a notetag:
- #
- # <random targets: #(, full)(, multi)>
- #
- # "#" is the total number of times you want VX Ace to 'roll' for a target
- # "full" indicates that you want # different targets to be hit
- # "multi" indicates it's okay for the same target to be hit multiple times
- # See below for examples of notetags and what the corresponding skill/item
- # would do.
- # IMPORTANT: If you want to have skills that choose random allies to target
- # (without giving the player the chance to select the first ally to be
- # targeted), then scroll down to the "Random Allies Section" near the
- # bottom of this script and follow the instructions there.
- ############################################
- # #
- # EXAMPLES AND NOTES ON USAGE #
- # #
- ############################################
- # Here are some examples of notetags that you might use on skills/items to
- # achieve different effects:
- # <random targets: 3>
- #
- # * If the Scope of this skill is "1 Random Enemy", VX Ace will select
- # a random enemy 3 times, then remove any duplicates that were
- # selected. A total of 1-3 random enemies will be hit, and none
- # will be hit more than once.
- #
- # * If the Scope of this skill is "One Enemy", the player will get to
- # select the first enemy to hit, then VX Ace will select a random
- # enemy twice (for a total of 3 targets). Again, duplicates will
- # be removed, so a total of 1-3 enemies will be hit and none will
- # be hit more than once.
- #
- # * If the Scope of this skill is "One Ally", the player will get to
- # select the first ally to hit, then VX Ace will select a random
- # ally twice. Duplicates are removed, 1-3 allies hit, none more
- # than once. Similar behavior for "One Ally (KOed)" except that
- # KOed allies will be targeted instead of alive ones.
- #
- # * If the Scope of this skill is "None", VX Ace will select a random
- # ally 3 times, then remove duplicates. 1-3 allies will be hit,
- # none more than once. Note that this particular behavior requires
- # the "Random Allies Section" of the script to be enabled.
- #
- # * Technically you can use "2 Random Enemies", etc. Scopes with this
- # skill, but there's no reason to, since you can easily control
- # the number of enemies to target (in this case 3) using the notetag.
- # <random targets: 3, full>
- #
- # * This is the same as the above, except instead of 3 attempted targets,
- # VX Ace will keep targeting random battlers (allies or enemies, as
- # appropriate) until 3 UNIQUE battlers have been selected.
- # So instead of 1-3 enemies being hit, you will be assured that 3
- # enemies will be hit (unless there are fewer than 3 enemies alive).
- # Like above, no battlers can be hit more than once.
- #
- # * All scopes listed above can be used with this tag.
- # <random targets: 3, multi>
- #
- # * This will generate 3 attempted targets but will allow a battler to
- # be hit multiple times. So a total of 3 hits will be landed, but
- # that might mean one battler being hit 3 times, or 3 battlers being
- # hit once. This is basically default VX Ace behavior, but this tag
- # might still be useful if you want to randomly target allies or to
- # raise the number of targets above 4.
- #
- # * All scopes listed above can be used with this tag.
- # <random targets: 3, full, multi>
- #
- # * This will cause VX Ace to generate targets over and over UNTIL
- # 3 unique battlers (or the entire party/troop) has been targeted.
- # Because the multi tag allows a battler to be hit multiple times,
- # this means that some battlers might be hit 5-10 times or even more!
- #
- # * Use a large number and a small enemy troop for some funny results!
- #
- # * All scopes listed above can be used with this tag.
- # Instead of "random targets" you may use the shorcut phrases "random hits"
- # or "randoms" instead.
- # Syntax is important; capitalization is not. You may use the "full" and
- # "multi" keywords in any order, just remember to properly separate each
- # field with a comma.
- # NOTE: When I say "no battler (enemy/ally) can be hit more than once", I am
- # referring to the way that this script targets battlers. You can still
- # use the standard "Repeats" field on the skill/item to have it hit each
- # target more than once. This script won't change that behavior.
- ############################################
- # #
- # ICKY CODE! #
- # #
- ############################################
- # Everything from here on represents the inner workings of the script.
- # Please don't alter anything from here on unless you are an
- # advanced scripter yourself (in which case, have at it!)
- # (The "Random Allies" section is much further down, near the bottom
- # of the script.)
- module RPG
- class UsableItem < RPG::BaseItem
- #--------------------------------------------------------------------------
- # * Add extra Parameters to RPG::Skill and RPG::Item items
- #--------------------------------------------------------------------------
- def init_randoms
- @randoms = false # Whether the skill uses Enhanced Random hits
- @random_hits = 0 # The total number of hits dealt by the skill
- @random_full = false # true: will keep picking until the number of
- # unique enemies hit equals "random_hits"
- # false: will only pick a number of times equal
- # to "random hits"
- @random_multi = false # Whether the same enemy can be hit multiple times
- # Set the Random Targets values from the item's notetag
- get_multi_hit_info(@note)
- end
- #--------------------------------------------------------------------------
- # * Public Instance Variables
- #--------------------------------------------------------------------------
- attr_accessor :randoms
- attr_accessor :random_hits
- attr_accessor :random_full
- attr_accessor :random_multi
- #--------------------------------------------------------------------------
- # * Set the Random Targets values from the item's notetag
- #--------------------------------------------------------------------------
- def get_multi_hit_info(note)
- newnote = @note.downcase
- newnote.gsub!($/, "@LINE@")
- if newnote =~ /<randoms:(.*)>/
- splitter = $1.split(",")
- else
- splitter = []
- end
- if newnote =~ /<random hits:(.*)>/
- splitter = $1.split(",")
- end
- if newnote =~ /<random targets:(.*)>/
- splitter = $1.split(",")
- end
- # If the splitter isn't empty, set the other Attributes
- if splitter != []
- # If the splitter is not empty, we know that Random Hits is true
- # (Not currently using this variable for anything)
- @randoms = true
- # Get rid of spaces - they're only there for visual clarity
- for item in splitter
- while item.include?(" ")
- item.slice!(" ")
- end
- ok = true
- the_number = item.to_i rescue ok = false
- if ok == true
- if the_number > 0
- @random_hits = the_number - 1
- end
- end
- if item.is_a?(String)
- if item.start_with?("full") or item.end_with?("full")
- @random_full = true
- end
- if item.start_with?("multi") or item.end_with?("multi")
- @random_multi = true
- end
- end
- end
- end
- end
- end
- end
- module DataManager
- class << self
- #--------------------------------------------------------------------------
- # * Load Normal Database
- #--------------------------------------------------------------------------
- alias :load_normals_with_randoms :load_normal_database
- def load_normal_database
- load_normals_with_randoms
- for item in $data_items
- item.init_randoms if item != nil
- end
- for skill in $data_skills
- skill.init_randoms if skill != nil
- end
- end
- #--------------------------------------------------------------------------
- # * Load Battle Test Database
- #--------------------------------------------------------------------------
- alias :load_btest_with_randoms :load_battle_test_database
- def load_battle_test_database
- load_btest_with_randoms
- for item in $data_items
- item.init_randoms if item != nil
- end
- for skill in $data_skills
- skill.init_randoms if skill != nil
- end
- end
- end
- end
- class Game_Action
- #--------------------------------------------------------------------------
- # * Targets for Opponents
- #--------------------------------------------------------------------------
- def targets_for_opponents
- extra_hits = item.random_hits
- targets_array = []
- # Item for Random Enemies Processing Starts Here - this is used when you
- # don't want enemy selection
- if item.for_random?
- # First, create the standard "random enemies" target array
- targets_array = (Array.new(item.number_of_targets) { opponents_unit.random_target })
- # Then fill the array with additional random hits, per the notetags
- if extra_hits > 0
- ok = false
- while (ok == false)
- targets_array.push(opponents_unit.random_target)
- # If the "Full" option is selected, check the Unique Array...
- if item.random_full == true
- unique_newyork = targets_array.uniq # Try saying "Unique New York"
- if unique_newyork.size > extra_hits # ten times fast!
- ok = true
- end
- # To avoid hangs/freezes, move on if every alive enemy is selected
- if unique_newyork.size == opponents_unit.alive_members.size
- ok = true
- end
- # If the "Full" option is not selected, check the Total Array...
- else
- if targets_array.size > extra_hits
- ok = true
- end
- end
- end
- end
- # Find the list of unique random targets; allow multiple selections of the
- # same target only if 'Multi' is true. Allow multi-hits on the same
- # target, though.
- unless item.random_multi == true
- targets_array.uniq!
- end
- # Return the array now that it's been filtered for uniqueness
- targets_array
- # Item For One Enemy Processing Starts Here - this can be used for random
- # targets processing when you want the player to select the 1st enemy
- elsif item.for_one?
- num = 1 + (attack? ? subject.atk_times_add.to_i : 0)
- if @target_index < 0
- # Keep pushing in targets until it equals the number of hits
- ok = false
- while (ok == false)
- #for i in 0..extra_hits
- targets_array.push([opponents_unit.random_target] * num)
- # If the "Full" option is selected, check the Unique Array...
- if item.random_full == true
- unique_newyork = targets_array.uniq { |small| small.first }
- if unique_newyork.size > extra_hits
- ok = true
- end
- # To avoid hangs/freezes, move on if every alive enemy is selected
- if unique_newyork.size == opponents_unit.alive_members.size
- ok = true
- end
- # If the "Full" option is not selected, check the Total Array...
- else
- if targets_array.size > extra_hits
- ok = true
- end
- end
- end
- else
- # First, push the selected target into the Targets Array
- targets_array.push([opponents_unit.smooth_target(@target_index)] * num)
- # Then, if there are any extra Random Hits to be made, select them the
- # same way as we did above.
- if extra_hits > 0
- ok = false
- while (ok == false)
- targets_array.push([opponents_unit.random_target] * num)
- if item.random_full == true
- unique_newyork = targets_array.uniq { |small| small.first }
- if unique_newyork.size > extra_hits
- ok = true
- end
- if unique_newyork.size == opponents_unit.alive_members.size
- ok = true
- end
- else
- if targets_array.size > extra_hits
- ok = true
- end
- end
- end
- end
- end
- # Find the list of unique random targets; allow multiple selections of the
- # same target only if 'Multi' is true. Allow multi-hits on the same
- # target, though.
- unless item.random_multi == true
- targets_array.uniq! { |small| small.first }
- end
- # Finally, combine all the small arrays into one large array that can be
- # worked with by Scene_Battle
- combined_targets = []
- for small_array in targets_array
- for element in small_array
- combined_targets.push(element)
- end
- end
- # Return the large array
- combined_targets
- else
- # All Enemies Processing is exactly the same as default
- opponents_unit.alive_members
- end
- end
- #--------------------------------------------------------------------------
- # * Targets for Allies
- #--------------------------------------------------------------------------
- def targets_for_friends
- extra_hits = item.random_hits
- targets_array = []
- # Scope: The User processing starts here - this can be used for random
- # targets processing when you want additional random allies to be targeted
- if item.for_user?
- # Push the User into the targets array
- targets_array.push(subject)
- # Then fill the array with additional random hits, per the notetags
- if extra_hits > 0
- ok = false
- while (ok == false)
- targets_array.push(friends_unit.random_target)
- # If the "Full" option is selected, check the Unique Array...
- if item.random_full == true
- unique_newyork = targets_array.uniq # Try saying "Unique New York"
- if unique_newyork.size > extra_hits # ten times fast!
- ok = true
- end
- # To avoid hangs/freezes, move on if every alive enemy is selected
- if unique_newyork.size == friends_unit.alive_members.size
- ok = true
- end
- # If the "Full" option is not selected, check the Total Array...
- else
- if targets_array.size > extra_hits
- ok = true
- end
- end
- end
- end
- # Find the list of unique random targets; allow multiple selections of the
- # same target only if 'Multi' is true. Allow multi-hits on the same
- # target, though.
- unless item.random_multi == true
- targets_array.uniq!
- end
- # Finally, return the filtered (unique, if appropriate) array
- targets_array
- elsif item.for_dead_friend?
- # Scope: One KOed Ally - this can be used for random targets processing
- # when you want add'l random KOed allies to also be targeted
- if item.for_one?
- # First, push the selected KOed target into the targets array
- targets_array.push(friends_unit.smooth_dead_target(@target_index))
- # Then fill the array with additional random hits, per the notetags
- if extra_hits > 0
- ok = false
- while (ok == false)
- targets_array.push(friends_unit.random_dead_target)
- if item.random_full == true
- unique_newyork = targets_array.uniq
- if unique_newyork.size > extra_hits
- ok = true
- end
- # To avoid hangs/freezes, move on if every *KOed* enemy is selected
- if unique_newyork.size >= friends_unit.dead_members.size
- ok = true
- end
- else
- if targets_array.size > extra_hits
- ok = true
- end
- # Additional check in the Non-Full branch: if there are no dead
- # members, move on, to avoid hangs/freezes
- if friends_unit.dead_members.size == 0
- ok = true
- end
- end
- end
- end
- # Find the list of unique random targets; allow multiple selections of the
- # same target only if 'Multi' is true. Allow multi-hits on the same
- # target, though.
- unless item.random_multi == true
- targets_array.uniq!
- end
- # Check to see whether all battlers in this array are nil
- all_nil = true
- if targets_array.size > 0
- for entry in targets_array
- if entry != nil
- all_nil = false
- end
- end
- end
- # If there are no valid (non-nil) battlers in the array, return 'nil'
- if all_nil == true
- []
- else
- # Otherwise, return the filtered (unique, if appropriate) array
- targets_array
- end
- else
- # All KOed Allies Processing is exactly the same as default
- friends_unit.dead_members
- end
- elsif item.for_friend?
- # Scope: One Ally - this can be used for random targets processing when
- # you want additional random allies to also be targeted
- if item.for_one?
- # First, push the selected target into the targets array
- targets_array.push(pick_target_for_one_friend)
- # Then fill the array with additional random hits, per the notetags
- if extra_hits > 0
- ok = false
- while (ok == false)
- targets_array.push(friends_unit.random_target)
- if item.random_full == true
- unique_newyork = targets_array.uniq
- if unique_newyork.size > extra_hits
- ok = true
- end
- if unique_newyork.size == friends_unit.alive_members.size
- ok = true
- end
- else
- if targets_array.size > extra_hits
- ok = true
- end
- end
- end
- end
- unless item.random_multi == true
- targets_array.uniq!
- end
- targets_array
- else
- # All Allies Processing is exactly the same as default
- friends_unit.alive_members
- end
- end
- end
- #--------------------------------------------------------------------------
- # * This method is a copy of the "smooth target" selection from the
- # targets_for_friends method; the only reason I've separated it
- # into its own separate method is to enable a Compatibility Patch
- # with lonewolf's Randomized Enemy Targeting fix.
- #--------------------------------------------------------------------------
- def pick_target_for_one_friend
- friends_unit.smooth_target(@target_index)
- end
- ############################################
- # #
- # RANDOM ALLIES SECTION #
- # #
- ############################################
- =begin
- # This section is used for additional methods to allow you to create
- # skills which target random (alive) Allies without requiring a
- # target selection. To make such a skill, simply tag a skill with
- # a scope of "None" with the Random Targets notetag.
- # The reason this section is disabled by default is to maximize
- # compatibility with other scripts. Therefore, you should only
- # enable this section if you plan to use the functionality
- # described above, especially if you have other scripts that
- # overwrite or alias the "make_targets" method.
- # If you're sure you want to enable this section, remove the tags
- # that read "=begin" and "=end" lines at the top and bottom of
- # this section.
- #--------------------------------------------------------------------------
- # * Create Target Array
- #--------------------------------------------------------------------------
- def make_targets
- if !forcing && subject.confusion?
- [confusion_target]
- elsif item.for_opponent?
- targets_for_opponents
- elsif item.for_friend?
- targets_for_friends
- elsif item.scope == 0
- random_friendly_targets
- else
- []
- end
- end
- #--------------------------------------------------------------------------
- # * Assign Random (Alive) Allies without a Target Selection
- #--------------------------------------------------------------------------
- def random_friendly_targets
- extra_hits = item.random_hits
- targets_array = []
- # Fill the array with random hits, per the notetags
- if extra_hits > 0
- ok = false
- while (ok == false)
- targets_array.push(friends_unit.random_target)
- # If the "Full" option is selected, check the Unique Array...
- if item.random_full == true
- unique_newyork = targets_array.uniq
- if unique_newyork.size > extra_hits
- ok = true
- end
- # To avoid hangs/freezes, move on if every alive enemy is selected
- if unique_newyork.size == friends_unit.alive_members.size
- ok = true
- end
- # If the "Full" option is not selected, check the Total Array...
- else
- if targets_array.size > extra_hits
- ok = true
- end
- end
- end
- end
- # Find the list of unique random targets; allow multiple selections of the
- # same target only if 'Multi' is true. Allow multi-hits on the same
- # target, though.
- unless item.random_multi == true
- targets_array.uniq!
- end
- # Return the array now that it's been filtered for uniqueness
- targets_array
- end
- =end
- # (RANDOM ALLIES SECTION ENDS HERE)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement