COTUS COUNTER
Version: 1.2Author: ThorondorRelease date: March 26th 2010Updated: May 26th 2010IntroductionThis script lets you set states to allow counterattacks, and set a variety of factors pertaining to the counterattack, such as strength, what sets it off, and the elements of the attack. Now also allows you to give the counterattack a chance to activate, instead of activating every time the conditions are met. Skills can be activated by a counterattack, instead of doing a normal counterattack.
Features- Counterattacks can interrupt the action that triggered them
- Variable counterattack strength, based off of attack, spirit, agility, or defense
- A selection of possible requirements for actions to trigger the counterattack
- Set the animation, elements, accuracy and critical rate of the counterattack if desired
- NEW! Give the counterattack a chance to activate upon its conditions being met
- NEWER! Activate a skill instead of making a normal counterattack
Script<div style="margin:20px; margin-top:5px"><div style="margin-bottom:2px">
[Show/Hide] Script</div><div style="margin: 0px; padding: 6px; border: 1px inset;"><div style="display: none;">
CODE
=begin
=begin
COTUS - Counterattack Version 1.3
by Thorondor
===============================================================================
Updates:
5-24-2010: Added the 'chance' attribute, allowing counterattacks to activate
only a certain percentage of the time instead of all the time.
5-26-2010: Now allows counterattacks to activate skills.
1-17-2012: Minor fixes on counterattack skills, which now are completely
functional except with YEM and possibly the Yanfly Engine Redux battle system
as well. Changes to function of couterattacks that use skills but not the
<targetnorm> tag.
===============================================================================
Installation: put it under materials, and above main. You may have to move it
around some due to other scripts.
Counterattacks are set by putting a series of notes in a state's notebox. That
state will then allow whichever battlers it is on to counterattack. A normal
counterattack is denoted by <counter>, an interrupting counterattack is denoted
<interrupt>. By default, counterattacks are only activated when the battler
making the counterattack is targetted; this can be changed by the use of
<guardian>, causing the battler to counterattack if any allies are targetted as
well. The damage dealt by the counterattack is determined by the use of four
tags: <atk_f x>, <spi_f x>, <def_f x>, and <agi_f x>, where x is the percentage
of base damage used. Attack and spirit based damage are done the same way as for
skills, and defense and agility are treated the same way as spirit. There are a
variety of tags for what actions can set off the counterattack. <vs_attacks>
counters attacks, <vs_skills> counters skills, <vs_items> counters items,
<vs_physical> counters attacks and skills or items with the physical attack tag,
<vs_phys_skills> counters physical attack skills, <vs_phys_items> counters
physical attack items, <vs_spells> counters skills with any spi_f,
<vs_spell_items> is the same as <vs_spells>, but for items, <vs_other_skill>
counters any skill that is neither physical nor a spell, and <vs_other_item>
counters any item that is neither physical nor a spell. Any or all of these can
be used for one state. <counterspell> gives the counterattack different text
upon activation, and treats the counterattack more like a skill than an attack,
ignoring any states normally applied by an attack and ignoring evasion unless
specified otherwise by the use of <evasion>. <animation x> sets the
counterattack's animation; if x is 0 or the tag isn't used, the animation will
be the same as a normal attack's. <element x> or <element x,x>, with as many x's
as wanted, sets the counterattacks elements. If x is zero, or the tag isn't
used, no elements will be used; if it is -1, a normal attack's elements will be
used. <accuracy x> gives the counterattack an accuracy seperate from a normal
attack's; 0 or non-use means normal attack accuracy. <critical x> determines
critical rate; it not entered, the battler's critical rate will be used.
<chance x> determines the counterattack's chance of activating when conditions
are met. The number entered is the percent chance of activating. If not entered,
it is 100.
<cskill x> sets the counterattack to activate a skill, x being the id
of the skill. The skill will be activated whether or not the battler can use it
normally. This tag overrides other tags that determine the strength of a
counterattack. <costskill> causes the skill to cost its normal amount of MPs.
<targetnorm> is intended to allow this script to work with custom targetting,
but is not currently functional. Without it, the skill uses the targetting set
in the database. Currently, however, it seems to cause one specific battler to
always be targetted. Without it, a skill that targets enemies will always target
the battler that triggered it, even if normally it would target a random foe.
Any additional random foes are selected as normal. Skills that target all foes
function as normal. If the skill targets an ally, it will target the
counterattacking battler. Skills that target all allies still do so.
A couple of example counterattack setups:
<interrupt>
<guardian>
<spi_f 100>
<vs_spells>
<vs_spell_items>
<counterspell>
<animation 15>
<element 6>
<accuracy 100>
<critical 0>
This counterattack is of the counterspell variety, and is an interrupting
counterattack. It activates off of spells and spell items targetting any ally.
Damage dealt is full spirit damage (look in the RPGmaker's help file if you
don't know the formula). The animation ID is 15, the attack uses element 6, it
never misses, and never gets a critical.
<counter>
<atk_f 100>
<vs_physical>
<element -1>
This counterattack activates when attacks or physical items or skills are used
on whatever battler has this state. The damage dealt is the same as if a normal
attack. The counterattack uses the battler's attack elements.
================================================================================
Compatibility notes:
Alias: Scene_Battle; execute_action_attack, and skill and item versions of same
Overwrites: Game_BattleAction; make_targets
================================================================================
Credit:
If you use this, please credit me; COTUS works, Thorondor probably does,
although I don't know if anyone else is using that name, a possibility which
could cause some confusion...
Also, I'd like to thank the many other people who have made scripts, as I
learned a lot of how to do it from other people's scripts.
================================================================================
=end
$imported = {} if $imported == nil
$imported["COTUS Counter"] = true
module COTUS
module REGEXP
module STATE
# This is the text looked for in the notebox. If you don't know what you
# are doing, leave it be. :)
# These adjust the type of counterattack
COUNTER = /<(?:COUNTER|counter)>/i
INTERRUPT = /<(?:INTERRUPT|interrupt)>/i
GUARDIAN = /<(?:GUARDIAN|guardian)>/i
VS_ATTACKS = /<(?:VS_ATTACKS|vs_attacks)>/i
VS_SKILLS = /<(?:VS_SKILLS|vs_skills)>/i
VS_ITEMS = /<(?:VS_ITEMS|vs_items)>/i
VS_PHYSICAL = /<(?:VS_PHYSICAL|vs_physical)>/i
VS_PHYS_SKILLS = /<(?:VS_PHYS_SKILLS|vs_phys_skills)>/i
VS_PHYS_ITEMS = /<(?:VS_PHYS_ITEMS|vs_phys_items)>/i
VS_SPELLS = /<(?:VS_SPELLS|vs_spells)>/i
VS_SPELL_ITEMS = /<(?:VS_SPELL_ITEMS|vs_spell_items)>/i
VS_OTHER_SKILL = /<(?:VS_OTHER_SKILL|vs_other_skill)>/i
VS_OTHER_ITEM = /<(?:VS_OTHER_ITEM|vs_other_item)>/i
COUNTERSPELL = /<(?:COUNTERSPELL|counterspell)>/i
# These adjust numbered attributes
ATK_F = /<(?:ATF_F|atk_f)[ ]*(\d+)>/i
SPI_F = /<(?:SPI_F|spi_f)[ ]*(\d+)>/i
AGI_F = /<(?:AGI_F|agi_f)[ ]*(\d+)>/i
DEF_F = /<(?:DEF_F|def_f)[ ]*(\d+)>/i
ANIMATION = /<(?:ANIMATION|animation)[ ]*(\d+)>/i
ACCURACY = /<(?:ACCURACY|accuracy)[ ]*(\d+)>/i
CRITICAL = /<(?:CRITICAL|critical)[ ]*(\d+)>/i
ELEMENT = /<(?:ELEMENT|element)[ ]*(\d+(?:\s*,\s*\d+)*)>/i
CHANCE = /<(?:CHANCE|chance)[ ]*(\d+)>/i
CSKILL = /<(?:CSKILL|cskill)[ ]*(\d+)>/i
# These are different
EVASION = /<(?:EVASION|evasion)>/i
COSTSKILL = /<(?:COSTSKILL|costskill)>/i
TARGETNORM = /<(?:TARGETNORM|targetnorm)>/i
end # STATE
end # REGEXP
module VOCAB
# HERE IS THE TEXT FOR A COUNTERATTACK: change as desired
# Standard counterattack text, where %s = counterattacker
COUNTERTEXT = "%s counterattacks!"
# Standard interrupt text
INTERRUPTTEXT = "%s interrupts!"
# Counterspell text
CSPELLTEXT = "%s's counterspell!"
# Counterspell interrupt text
CSPELLINTERRUPT = "%s interrupts with a counterspel1"
end # VOCAB
end # COTUS
#===============================================================================
# RPG::State
# This is the stuff for defining the new attributes of states.
#===============================================================================
class RPG::State
#--------------------------------------------------------------------------
# COTUS_Cache_CCA
#--------------------------------------------------------------------------
def cotus_cache_cca # Creating new state factors
@counter = false; @interrupt = false; @guardian = false;
@vs_attacks = false; @vs_skills = false; @vs_items = false;
@vs_physical = false; @vs_phys_skills = false; @vs_phys_items = false;
@vs_spells = false; @vs_spell_items = false; @vs_other_skill = false;
@vs_other_item = false; @counterspell = false; @atk_fc = 0; @spi_fc = 0;
@agi_fc = 0; @def_fc = 0; @animation = 0; @accuracy = -1; @critical = -1;
@evasion = false; @element = []; @chance = 100; @cskill = 0;
@costskill = false; @targetnorm = false
self.note.split(/[\r\n]+/).each { |line| # Finding text in the noteboxes
case line
when COTUS::REGEXP::STATE::ELEMENT
$1.scan(/\d+/).each { |num|
if num.to_i >= 0
@element.push(num.to_i)
end }
when COTUS::REGEXP::STATE::COUNTER
@counter = true
when COTUS::REGEXP::STATE::INTERRUPT
@interrupt = true
when COTUS::REGEXP::STATE::GUARDIAN
@guardian = true
when COTUS::REGEXP::STATE::VS_ATTACKS
@vs_attacks = true
when COTUS::REGEXP::STATE::VS_SKILLS
@vs_skills = true
when COTUS::REGEXP::STATE::VS_ITEMS
@vs_items = true
when COTUS::REGEXP::STATE::VS_PHYSICAL
@vs_physical = true
when COTUS::REGEXP::STATE::VS_PHYS_SKILLS
@vs_phys_skills = true
when COTUS::REGEXP::STATE::VS_PHYS_ITEMS
@vs_phys_items = true
when COTUS::REGEXP::STATE::VS_SPELLS
@vs_spells = true
when COTUS::REGEXP::STATE::VS_SPELL_ITEMS
@vs_spell_items = true
when COTUS::REGEXP::STATE::VS_OTHER_SKILL
@vs_other_skill = true
when COTUS::REGEXP::STATE::VS_OTHER_ITEM
@vs_other_item = true
when COTUS::REGEXP::STATE::COUNTERSPELL
@counterspell = true
when COTUS::REGEXP::STATE::ATK_F
@atk_fc = $1.to_i
when COTUS::REGEXP::STATE::SPI_F
@spi_fc = $1.to_i
when COTUS::REGEXP::STATE::AGI_F
@agi_fc = $1.to_i
when COTUS::REGEXP::STATE::DEF_F
@def_fc = $1.to_i
when COTUS::REGEXP::STATE::ANIMATION
@animation = $1.to_i
when COTUS::REGEXP::STATE::ACCURACY
@accuracy = $1.to_i
when COTUS::REGEXP::STATE::CRITICAL
@critical = $1.to_i
when COTUS::REGEXP::STATE::CHANCE
@chance = $1.to_i
when COTUS::REGEXP::STATE::CSKILL
@cskill = $1.to_i
when COTUS::REGEXP::STATE::EVASION
@evasion = true
when COTUS::REGEXP::STATE::COSTSKILL
@costskill = true
when COTUS::REGEXP::STATE::TARGETNORM
@targetnorm = true
end
}
@element = [0] if @element == []
end # cotus_cache_cca
#--------------------------------------------------------------------------
# Counter Types
#--------------------------------------------------------------------------
def counter
cotus_cache_cca if @counter == nil
return @counter
end
def interrupt
cotus_cache_cca if @interrupt == nil
return @interrupt
end
def guardian
cotus_cache_cca if @guardian == nil
return @guardian
end
#--------------------------------------------------------------------------
# Counter Times
#--------------------------------------------------------------------------
def vs_attacks
cotus_cache_cca if @vs_attacks == nil
return @vs_attacks
end
def vs_skills
cotus_cache_cca if @vs_skills == nil
return @vs_skills
end
def vs_items
cotus_cache_cca if @vs_items == nil
return @vs_items
end
def vs_physical
cotus_cache_cca if @vs_physical == nil
return @vs_physical
end
def vs_phys_skills
cotus_cache_cca if @vs_phys_skills == nil
return @vs_phys_skills
end
def vs_phys_items
cotus_cache_cca if @vs_phys_items == nil
return @vs_phys_items
end
def vs_spells
cotus_cache_cca if @vs_spells == nil
return @vs_spells
end
def vs_spell_item
cotus_cache_cca if @vs_spell_item == nil
return @vs_spell_item
end
def vs_other_skill
cotus_cache_cca if @vs_other_skill == nil
return @vs_other_skill
end
def vs_other_item
cotus_cache_cca if @vs_other_item == nil
return @vs_other_item
end
def counterspell
cotus_cache_cca if @counterspell == nil
return @counterspell
end
#--------------------------------------------------------------------------
# Counter Strength
#--------------------------------------------------------------------------
def atk_fc
cotus_cache_cca if @atf_fc == nil
return @atk_fc
end
def spi_fc
cotus_cache_cca if @spi_fc == nil
return @spi_fc
end
def agi_fc
cotus_cache_cca if @agi_fc == nil
return @agi_fc
end
def def_fc
cotus_cache_cca if @def_fc == nil
return @def_fc
end
#--------------------------------------------------------------------------
# Additional Effects
#--------------------------------------------------------------------------
def animation
cotus_cache_cca if @animation == nil
return @animation
end
def accuracy
cotus_cache_cca if @accuracy == nil
return @accuracy
end
def critical
cotus_cache_cca if @critical == nil
return @critical
end
def chance
cotus_cache_cca if @chance == nil
return @chance
end
def cskill
cotus_cache_cca if @cskill == nil
return @cskill
end
def evasion
cotus_cache_cca if @evasion == nil
return @evasion
end
def costskill
cotus_cache_cca if @costskill == nil
return @costskill
end
def targetnorm
cotus_cache_cca if @targetnorm == nil
return @targetnorm
end
def element
cotus_cache_cca if @element == nil
return @element
end
end # RPG::State
#===============================================================================
# Game_Temp
# I needed to put these variables somewhere they could be accessed...
#===============================================================================
class Game_Temp
#--------------------------------------------------------------------------
# Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :newtargets # Store targets for later use
attr_accessor :interrupt_state # Store the interrupting state
attr_accessor :interrupter # Store the interrupting battler
end # Game_Temp
#===============================================================================
# Game_BattleAction
#===============================================================================
class Game_BattleAction
#--------------------------------------------------------------------------
# * Overwrite Create Target Array
#--------------------------------------------------------------------------
def make_targets
$game_temp.interrupter = nil
$game_temp.interrupt_state = nil
@newtargets = []
if attack?
targets = make_attack_targets # Set targets
if foe_target_cca?(targets) # If used on foes
check_interrupt(battler, targets) # Check for an interrupt
end
elsif skill?
targets = make_obj_targets(skill) # Set targets
if foe_target_cca?(targets) # If used on foes
check_interrupt(battler, targets) # Check for an interrupt
end
elsif item?
targets = make_obj_targets(item) # Set targets
if foe_target_cca?(targets) # If used on foes
check_interrupt(battler, targets) # Check for an interrupt
end
end
$game_temp.newtargets = targets # Store targets
if $game_temp.interrupt_state != nil # If there is an interrupt
for target in targets # For each target
targets.delete(target) # Delete target
end
end
return targets
end
#--------------------------------------------------------------------------
# foe_target_cca?
#--------------------------------------------------------------------------
def foe_target_cca?(targets)
for target in targets # For each target
if opponents_unit.members.include?(target) # If target is an enemy
return true
end
end
return false
end
#--------------------------------------------------------------------------
# Make Counter?
#--------------------------------------------------------------------------
def make_counter?(state)
if rand(100) >= state.chance # If activation fails
return false # Counterattack cannot be made
end
if self.kind == 0 and self.basic == 0 # If action is an attack
return true if state.vs_attacks or state.vs_physical
elsif self.skill.is_a?(RPG::Skill) # If action is a skill
if self.skill.physical_attack # If skill is a physical attack
return true if state.vs_skills or state.vs_physical or state.vs_phys_skills
elsif self.skill.spi_f > 0 # If skill is a spell
return true if state.vs_skills or state.vs_spells
else # If none of the above
return true if state.vs_skills or state.vs_other_skill
end
elsif self.item.is_a?(RPG::Item) # If action is an item
if self.item.physical_attack # If item is a physical attak
return true if state.vs_items or state.vs_physical or state.vs_phys_items
elsif self.item.spi_f > 0 # If item is a spell
return true if state.vs_skills or state.vs_spell_items
else # If none of the above
return true if state.vs_items or state.vs_other_item
end
end
return false
end
#--------------------------------------------------------------------------
# Check Interrupt
#--------------------------------------------------------------------------
def check_interrupt(battler, targets)
for member in battler.action.opponents_unit.existing_members
for state in member.states
if state.guardian # If guardian flag is active
if state.interrupt # If interrupt flag is active
if battler.action.make_counter?(state) # If interrupt is valid
return unless member.movable? # Return if immobile
$game_temp.interrupter = member # Set interrupter
$game_temp.interrupt_state = state # Set interrupting state
return
end
end
end
end
end
for target in targets
return if battler.action.friends_unit.members.include?(target) # Ignore friends
for state in target.states
if state.interrupt # If counter flag is active
if not state.guardian # Ensure there are no repeats
if battler.action.make_counter?(state) # If interrupt is valid
return unless target.movable? # Return if immobile
$game_temp.interrupter = target # Set interrupter
$game_temp.interrupt_state = state # Set interrupting state
return
end
end
end
end
end
end
#--------------------------------------------------------------------------
# Make Counter Skill Targets
#--------------------------------------------------------------------------
def make_cskill_targets(cskill, battler, trigger)
targets = []
if cskill.for_opponent?
if cskill.for_random?
if cskill.for_one? # One random enemy
number_of_targets = 0
elsif cskill.for_two? # Two random enemies
number_of_targets = 1
else # Three random enemies
number_of_targets = 2
end
targets.push(trigger)
number_of_targets.times do
targets.push(opponents_unit.random_target)
end
elsif cskill.dual? # One enemy, dual
targets.push(trigger)
targets.push(trigger)
elsif cskill.for_one? # One enemy
targets.push(trigger)
else # All enemies
targets += opponents_unit.existing_members
end
elsif cskill.for_user? # User
targets.push(battler)
elsif cskill.for_dead_friend?
if cskill.for_one? # One ally (incapacitated)
targets.push(battler)
else # All allies (incapacitated)
targets += friends_unit.dead_members
end
elsif cskill.for_friend?
if cskill.for_one? # One ally
targets.push(battler)
else # All allies
targets += friends_unit.existing_members
end
end
return targets
end
end # Game_BattleAction
#===============================================================================
# Game_Battler
#===============================================================================
class Game_Battler
#--------------------------------------------------------------------------
# Counter Effects
#--------------------------------------------------------------------------
def counter_effect(attacker, state)
clear_action_results
unless attack_effective?(attacker) # If target is dead
@skipped = true
return
end
if state.accuracy < 0 # If no set accuracy
accuracy = calc_hit(attacker) # Set accuracy to base
else
accuracy = state.accuracy # Use counterattack accuracy
end
if rand(100) >= accuracy # If attack misses
@missed = true
return
end
if state.counterspell # If a counterspell
if state.evasion # If has evasion tag
evasion = calc_eva(attacker) # Use normal evasion
else
evasion = 0 # No evasion
end
else
evasion = calc_eva(attacker) # Use normal evasion
end
if rand(100) < evasion # If attack is evaded
@evaded = true
return
end
make_counter_damage_value(attacker, state) # Damage calculation
execute_damage(attacker) # Damage reflection
if @hp_damage == 0 # Physical and no damage?
return
end
apply_state_changes(attacker) unless state.counterspell # State changes
if $imported["CustomSkillEffects"] # Compatibility effects
if state.counterspell
if YE::BATTLE::INC_RAGE_SKILL
attacker.rage += YE::BATTLE::NUM_RAGE_SKILL
end
else
if YE::BATTLE::INC_RAGE_ATTACK
attacker.rage += YE::BATTLE::NUM_RAGE_ATTACK
end
end
end
if $imported["BattleEngineMelody"]
if state.counterspell
value = YEM::BATTLE_ENGINE::SKILL_SETTINGS[:magical_rage_gain]
else
value = YEM::BATTLE_ENGINE::SKILL_SETTINGS[:attack_rage_gain]
end
value = attacker.rage_modifiers(value)
attacker.gain_rage(value)
end
if $imported["SubclassSelectionSystem"] # Compatibility effects
return unless attacker.actor?
return unless YE::SUBCLASS::EARN_JP_VIA_ATTACK_ENABLE
amount = YE::SUBCLASS::EARN_JP_VIA_ATTACK_AMOUNT
unless YE::SUBCLASS::EARN_JP_VIA_ATTACK_RANDOM == 0
amount += rand(YE::SUBCLASS::EARN_JP_VIA_ATTACK_RANDOM)
end
attacker.gain_jp(amount)
end
end
#--------------------------------------------------------------------------
# Counterattack damage calculation
#--------------------------------------------------------------------------
def make_counter_damage_value(attacker, state)
damage_atk = attacker.atk * 4 - self.def * 2 # Attack damage
damage_atk *= state.atk_fc # Modified by multiplier
if $imported["RES Stat"] # Compatability
damage_spi = attacker.spi * 2 - self.res # Spirit damage
else
damage_spi = attacker.spi * 2 - self.spi # Spirit damage
end
damage_spi *= state.spi_fc # Modified by multiplier
damage_agi = attacker.agi * 2 - self.agi # Agility damage
damage_agi *= state.agi_fc # Modified by multiplier
damage_def = attacker.def * 2 - self.def # Defense damage
damage_def *= state.def_fc # Modified by multiplier
damage = damage_atk + damage_spi + damage_agi + damage_def # Combined
damage /= 100 # Complete multipliers
damage = 0 if damage < 0 # No negative damage
elements = []
if state.element.include?(-1) # If element -1
for element in attacker.element_set
elements.push(element) # Add attack elements
end
elements.push(state.element) # Add counterattack elements
elements.delete(-1) # Remove trigger element
elsif state.element.include?(0) # If element 0
elements = [] # No elements
else
for element in state.element
elements.push(element) # Add counterattack elements
end
end
damage *= elements_max_rate(elements) # Element based damage mod
damage /= 100 # Complete element damage
if damage == 0 # If damage is 0,
damage = rand(2) # Half of the time, 1 dmg
elsif damage > 0
if state.critical < 0 # If no set critical rate
critical = attacker.cri # Attacker's rate
else
critical = state.critical # Set critical rate
end
@critical = (rand(100) < attacker.cri) # Critical hit?
@critical = false if prevent_critical # Criticals prevented?
damage *= 3 if @critical # Critical adjustment
end
damage = apply_variance(damage, 20) # Variance
damage = apply_guard(damage) # Guard adjustment
@hp_damage = damage # Damage HP
end
end # Game_Battler
#===============================================================================
# Scene_Battle
#===============================================================================
class Scene_Battle < Scene_Base
#--------------------------------------------------------------------------
# * Alias Execute Battle Action: Attack
#--------------------------------------------------------------------------
alias execute_action_attack_cca execute_action_attack
def execute_action_attack
execute_action_attack_cca
if $game_temp.interrupt_state != nil # If there is an interrupt
if $game_temp.interrupt_state.cskill > 0
execute_skill_interrupt($game_temp.interrupt_state, $game_temp.interrupter)
else
execute_action_interrupt($game_temp.interrupt_state, $game_temp.interrupter) # Execute
end
else
check_counter($game_temp.newtargets) # Check for a counterattack
end
end
#--------------------------------------------------------------------------
# * Alias Execute Battle Action: Skill
#--------------------------------------------------------------------------
alias execute_action_skill_cca execute_action_skill
def execute_action_skill
execute_action_skill_cca
if $game_temp.interrupt_state != nil # If there is an interrupt
if $game_temp.interrupt_state.cskill > 0
execute_skill_interrupt($game_temp.interrupt_state, $game_temp.interrupter)
else
execute_action_interrupt($game_temp.interrupt_state, $game_temp.interrupter) # Execute
end
elsif @active_battler.action.foe_target_cca?($game_temp.newtargets) # If targetting an enemy
check_counter($game_temp.newtargets) # Check for a counterattack
end
end
#--------------------------------------------------------------------------
# * Alias Execute Battle Action: Item
#--------------------------------------------------------------------------
alias execute_action_item_cca execute_action_item
def execute_action_item
execute_action_item_cca
if $game_temp.interrupt_state != nil # If there is an interrupt
if $game_temp.interrupt_state.cskill > 0
execute_skill_interrupt($game_temp.interrupt_state, $game_temp.interrupter)
else
execute_action_interrupt($game_temp.interrupt_state, $game_temp.interrupter) # Execute
end
elsif @active_battler.action.foe_target_cca?($game_temp.newtargets) # If targetting an enemy
check_counter($game_temp.newtargets) # Check for a counterattack
end
end
#--------------------------------------------------------------------------
# display attack animation counter
#--------------------------------------------------------------------------
def display_attack_animation_counter(attacker, targets)
if $imported["AnimationFix"] # Compatibility effects
if attacker.is_a?(Game_Enemy)
if YE::FIX::ENEMY_ANI
if attacker.enemy.attack_ani > 0
ani_id = attacker.enemy.attack_ani
else
ani_id = YE::FIX::ENEMY_ATTACK_ANI
end
display_normal_animation(targets, ani_id, false)
else
Sound.play_enemy_attack
wait(15, true)
end
else
aid1 = attacker.atk_animation_id
aid2 = attacker.atk_animation_id2
display_normal_animation(targets, aid1, false)
display_normal_animation(targets, aid2, true)
end
wait_for_animation
elsif $imported["BattleEngineMelody"]
if attacker.is_a?(Game_Enemy)
aid1 = attacker.atk_animation_id
display_normal_animation(targets, aid1)
else
aid1 = attacker.atk_animation_id
aid2 = attacker.atk_animation_id2
display_normal_animation(targets, aid1, false)
wait_for_animation if aid2 != 0
display_normal_animation(targets, aid2, true)
end
wait_for_animation
else
if attacker.is_a?(Game_Enemy) # If a monster
Sound.play_enemy_attack # Do monster thing
wait(15, true)
else # Otherwise, do attack animation
aid1 = attacker.atk_animation_id
aid2 = attacker.atk_animation_id2
display_normal_animation(targets, aid1, false)
display_normal_animation(targets, aid2, true)
end
wait_for_animation
end
end
#--------------------------------------------------------------------------
# Check Counter
#--------------------------------------------------------------------------
def check_counter(targets)
for battler in @active_battler.action.opponents_unit.existing_members
for state in battler.states
if state.guardian # If guardian flag is active
if state.counter # If counter flag is active
return unless battler.movable? # Return if immobile
if state.cskill > 0 # If counter uses a skill
execute_skill_counter(state, battler) # Make skill counterattack
else
execute_action_counter(state, battler) # Make counterattack
end
end
end
end
end
for target in targets
return if @active_battler.action.friends_unit.members.include?(target) # Ignore friends
for state in target.states
if state.counter # If counter flag is active
if not state.guardian # Ensure there are no repeats
return unless target.movable? # Return if immobile
if state.cskill > 0 # If counter uses a skill
execute_skill_counter(state, target) # Make skill counterattack
else
execute_action_counter(state, target) # Make counterattack
end
end
end
end
end
end
#--------------------------------------------------------------------------
# Execute Battle Action: Counterattack
#--------------------------------------------------------------------------
def execute_action_counter(state, battler)
return unless @active_battler.action.make_counter?(state) # Return if counter invalid
mini_line = @message_window.line_number
if $imported["SceneBattleReDux"] # Compatibility effects
if YE::REDUX::BATTLE::MSG_CURRENT_ACTION
if state.counterspell
text = sprintf(COTUS::VOCAB::CSPELLTEXT, battler.name)
else
text = sprintf(COTUS::VOCAB::COUNTERTEXT, battler.name)
end
@message_window.add_instant_text(text)
end
else
if state.counterspell # If a counterspell
text = sprintf(COTUS::VOCAB::CSPELLTEXT, battler.name) # Counterspell text
else # Otherwise
text = sprintf(COTUS::VOCAB::COUNTERTEXT, battler.name) # Counterattack text
end
@message_window.add_instant_text(text)
end
targets = [@active_battler]
if state.animation == 0 # If no set animation for counter
display_attack_animation_counter(battler, targets) # Use battler's attack animation
else
display_animation(targets, state.animation) # Use counterattack's animation
end
@active_battler.counter_effect(battler, state) # Calculate effects
display_action_effects(@active_battler) # Display effects
if $imported["BattleEngineMelody"]
@active_battler.perform_collapse
end
if $imported["SceneBattleReDux"] # Compatibility effects
for target in targets
target.perform_collapse unless target.collapse
if @redux_msg and target.actor?
@status_window.draw_item(target.index) if target.collapse
end
end
end
@message_window.back_to(mini_line)
end
#--------------------------------------------------------------------------
# Execute Battle Action: Interrupt
#--------------------------------------------------------------------------
def execute_action_interrupt(state, battler)
mini_line = @message_window.line_number
if $imported["SceneBattleReDux"] # Compatibility effects
if YE::REDUX::BATTLE::MSG_CURRENT_ACTION
if state.counterspell
text = sprintf(COTUS::VOCAB::CSPELLINTERRUPT, battler.name)
else
text = sprintf(COTUS::VOCAB::INTERRUPTTEXT, battler.name)
end
@message_window.add_instant_text(text)
end
else
if state.counterspell # If a counterspell
text = sprintf(COTUS::VOCAB::CSPELLINTERRUPT, battler.name) # CSpell interrupt text
else
text = sprintf(COTUS::VOCAB::INTERRUPTTEXT, battler.name) # Interrupt text
end
@message_window.add_instant_text(text)
end
targets = [@active_battler]
if state.animation == 0 # If no set animation for counter
display_attack_animation_counter(battler, targets) # Use battler's attack animation
else # Otherwise
display_animation(targets, state.animation) # Use counterattack's animation
end
@active_battler.counter_effect(battler, state) # Calculate effects
display_action_effects(@active_battler) # Display effects
if $imported["BattleEngineMelody"]
@active_battler.perform_collapse
end
if $imported["SceneBattleReDux"] # Compatibility effects
for target in targets
target.perform_collapse unless target.collapse
if @redux_msg and target.actor?
@status_window.draw_item(target.index) if target.collapse
end
end
end
@message_window.back_to(mini_line)
end
#--------------------------------------------------------------------------
# Execute Battle Action: Counterattack Skill
#--------------------------------------------------------------------------
def execute_skill_counter(state, battler)
return unless @active_battler.action.make_counter?(state) # Return if counter invalid
mini_line = @message_window.line_number
if $imported["SceneBattleReDux"] # Compatibility effects
if YE::REDUX::BATTLE::MSG_CURRENT_ACTION
if state.counterspell
text = sprintf(COTUS::VOCAB::CSPELLTEXT, battler.name)
else
text = sprintf(COTUS::VOCAB::COUNTERTEXT, battler.name)
end
@message_window.add_instant_text(text)
end
else
if state.counterspell # If a counterspell
text = sprintf(COTUS::VOCAB::CSPELLTEXT, battler.name) # Counterspell text
else # Otherwise
text = sprintf(COTUS::VOCAB::COUNTERTEXT, battler.name) # Counterattack text
end
@message_window.add_instant_text(text)
end
cskill = $data_skills[state.cskill]
if state.targetnorm
targets = battler.action.make_obj_targets(cskill)
else
targets = battler.action.make_cskill_targets(cskill, battler, @active_battler)
end
if cskill.animation_id < 0 and state.animation == 0
display_attack_animation_counter(battler, targets)
elsif state.animation != 0
display_animation(targets, state.animation)
else
display_animation(targets, cskill.animation_id)
end
if state.costskill
battler.mp -= battler.calc_mp_cost(skill)
end
$game_temp.common_event_id = cskill.common_event_id
for target in targets
target.skill_effect(battler, cskill)
display_action_effects(target, cskill)
if $imported["BattleEngineMelody"] # Compatibility effects
target.perform_collapse
end
if $imported["SceneBattleReDux"] # Compatibility effects
target.perform_collapse unless target.collapse
if @redux_msg and target.actor?
@status_window.draw_item(target.index) if target.collapse
end
end
end
@message_window.back_to(mini_line)
end
#--------------------------------------------------------------------------
# Execute Battle Action: Interrupt Skill
#--------------------------------------------------------------------------
def execute_skill_interrupt(state, battler)
return unless @active_battler.action.make_counter?(state) # Return if counter invalid
mini_line = @message_window.line_number
if $imported["SceneBattleReDux"] # Compatibility effects
if YE::REDUX::BATTLE::MSG_CURRENT_ACTION
if state.counterspell
text = sprintf(COTUS::VOCAB::CSPELLINTERRUPT, battler.name)
else
text = sprintf(COTUS::VOCAB::INTERRUPTTEXT, battler.name)
end
@message_window.add_instant_text(text)
end
else
if state.counterspell # If a counterspell
text = sprintf(COTUS::VOCAB::CSPELLINTERRUPT, battler.name) # CSpell interrupt text
else
text = sprintf(COTUS::VOCAB::INTERRUPTTEXT, battler.name) # Interrupt text
end
@message_window.add_instant_text(text)
end
cskill = $data_skills[state.cskill]
if state.targetnorm
targets = battler.action.make_obj_targets(cskill)
else
targets = battler.action.make_cskill_targets(cskill, battler, @active_battler)
end
if cskill.animation_id < 0 and state.animation == 0
display_attack_animation_counter(battler, targets)
elsif state.animation != 0
display_animation(targets, state.animation)
else
display_animation(targets, cskill.animation_id)
end
if state.costskill
battler.mp -= battler.calc_mp_cost(skill)
end
$game_temp.common_event_id = cskill.common_event_id
for target in targets
target.skill_effect(battler, cskill)
display_action_effects(target, cskill)
if $imported["BattleEngineMelody"] # Compatibility effects
target.perform_collapse
end
if $imported["SceneBattleReDux"] # Compatibility effects
target.perform_collapse unless target.collapse
if @redux_msg and target.actor?
@status_window.draw_item(target.index) if target.collapse
end
end
end
@message_window.back_to(mini_line)
end
end # Scene_Battle
</div></div></div>
CustomizationYou shouldn't have to customize much of the script for normal use, but the text for when a counterattack happens can be easily edited. It's short distance below the description of how to set up counterattack states in the script. Just change the text in the quotes.
CompatibilityI don't know how it will react to other counterattack scripts, so it's possible this would be compatable with at least some of them. Other than those, I would expect this to be compatable with most scripts. It should have full compatibility with Yanfly's custom skill effects, animation fix, and scene battle redux scripts, as I added in some pieces for that purpose. It also is intended to work with YEM, but the targeting is not fully functional with it.
For it to work with Tankentai, insert the following line:
@spriteset.set_damage_pop(@active_battler.actor?, @active_battler.index, @hp_damage)
between the lines
display_action_effects(@active_battler) # Display effects
and
if $imported["BattleEngineMelody"]
(Thanks to ave369 for finding this.)
InstallationJust put it above Main and below Materials. Some shuffling may be required to get it to work right with other scripts.
Terms and ConditionsUse as desired; please credit me if you use it, that kind of stuff. For crediting, COTUS should work, Thorondor is also fine, but I don't know if anyone else is using that name and making scripts. If someone is, COTUS would probably be less likely to cause confusion.
CreditsLarge parts of my understanding of scripting came from other peoples scripts, particularly Yanfly's. Without that, I never would have made this script.
This post has been edited by Thorondor: Mar 17 2012, 09:31 AM