Have you ever wanted your monsters to respond immediately to a brazen attack? Do you feel that your quick and agile thief may wish to slice the brute who landed a blow? Then feel free to use this script to allow for devastating counter attacks. With this script, you can define enemies and actors that may respond to any successful strike.
Script
Here be the Script
Code:
#==============================================================================
# ** Kingly Kounters
#------------------------------------------------------------------------------
# by DerVVulfman
# version 1.2
# 06-13-2022 (mm/dd/yyyy)
# RGSS / RPGMaker XP
#==============================================================================
#
# INTRODUCTION:
#
# Have you ever wanted your monsters to respond immediately to a brazen at-
# tack? Do you feel that your quick and agile thief may wish to slice the
# brute who landed a blow? Then feel free to use this script to allow for
# devastating counter attacks.
#
# With this script, you can define enemies and actors that may respond to
# any successful strike. Each may be assigned the chance of striking back,
# the Skill ID used for the attack, and optionally whether skill used for
# the counter attack uses up their SP. However, if the Skill ID assigned is
# set to '0', it is a melee attack which would make the SP cost moot.
#
# A special note regarding Skills and SP usage. IF a battler set to deli-
# ver a spell-based counter doesn't have sufficient SP for the skill's use,
# then the counter automatically converts to a melee attack. This, if the
# counter attack is defined to use SP.
#
# Of course, this defines a 'counter' as an extra attack beside the attack
# which the defender was already planning to use or have already delivered.
#
#------------------------------------------------------------------------------
#
# INSTALLATION:
#
# Place this script below Scene_Debug and above Main for use.
#
# If used with AnimBat, place it below AnimBat. Placing the script above
# AnimBat will make the counter attacks the defender's only attack.
#
# Then go to the CounterAttack module and fill arrays as desired.
#
#------------------------------------------------------------------------------
#
# COMPATIBILITY:
#
# Designed for RPGMaker XP
#
#
#------------------------------------------------------------------------------
#
# TERMS OF USE:
#
# Free for use, even in commercial games. Only due credit is required. Mind
# you, due credit for kingray100 for the request is also a requisite.
#
#
#==============================================================================
module CounterAttack
# Creates the Actor Enemy Hash Arrays. Do not remove. ---------------------
ACTOR, ENEMY = {}, {} # Do not touch ---------------------------------------
# --------------------------------------------------------------------------
# Actor Counters
# ==============
# Define the actors perfoming counter attacks: the chance of a counter,
# the skill ID used (or 0 for melee), and optionally the SP cost.
#
# Chance Skill SPCost
#========== ====== ====== ======
ACTOR[2] = [ 50, 0] # Basil delivers melee 50%
# Enemy Counters
# ==============
# Define the enemies perfoming counter attacks: the chance of a counter,
# the skill ID used (or 0 for melee), and optionally the SP cost.
#
# Chance Skill SPCost
#========== ====== ====== ======
ENEMY[1] = [ 100, 7, true] # Ghosts use Fire 100%
end
#==============================================================================
# ** Game_Battler
#------------------------------------------------------------------------------
# This class deals with battlers. It's used as a superclass for the Game_Actor
# and Game_Enemy classes.
#==============================================================================
class Game_Battler
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :countertargets # Counterattack targets
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias game_battler_counter_king_initialize initialize
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
# Perform the original method
game_battler_counter_king_initialize
# Attached value
@countertargets = []
end
end
#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
# This class performs battle screen processing.
#==============================================================================
class Scene_Battle
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias scene_battle_counter_king_update_phase4_step5 update_phase4_step5
alias scene_battle_counter_king_update_phase4_step6 update_phase4_step6
#--------------------------------------------------------------------------
# * Frame Update (main phase step 5 : damage display)
#--------------------------------------------------------------------------
def update_phase4_step5
#
# Perform counterattack detection
counterattack_phase4_step5
# Perform the original method
scene_battle_counter_king_update_phase4_step5
#
end
#--------------------------------------------------------------------------
# * Frame Update (main phase step 6 : refresh)
#--------------------------------------------------------------------------
def update_phase4_step6
#
# If counter-attacking
if @counterattack == true
# Make pause before next action
@wait_count = 20
@counterattack = nil
end
#
# Perform the original method
scene_battle_counter_king_update_phase4_step6
# Perform counterattack action
counterattack_phase4_step6
#
end
#--------------------------------------------------------------------------
# * Frame Update (main phase step 5 : counterattack determination)
#--------------------------------------------------------------------------
def counterattack_phase4_step5
#
# Cycle through targets
for target in @target_battlers
#
# Next if no damage
next if target.damage.nil?
#
# Next if paralyzed - 'Can't Move'
next if target.restriction == 4
#
# Skip if no HP loss (healing ignored)
next unless (target.damage).to_i > 0
# Skip if attack was a counter
next if @counterattack == true
#
# Define chance
chance = 0
# Determine counterattack chance for enemy/actor
if target.is_a?(Game_Enemy)
if CounterAttack::ENEMY.has_key?(target.id)
chance = CounterAttack::ENEMY[target.id][0]
end
else
if CounterAttack::ACTOR.has_key?(target.id)
chance = CounterAttack::ACTOR[target.id][0]
end
end
#
# Skip if there is no chance of counter
next if chance == 0
# Skip if counterattack failed
next if chance < rand(100)
# Push active battler into array
target.countertargets.push(@active_battler)
#
end
#
end
#--------------------------------------------------------------------------
# * Frame Update (main phase step 6 : counterattack action)
#--------------------------------------------------------------------------
def counterattack_phase4_step6
#
# Cycle through targets
for target in @target_battlers
#
# Ignore if dead
next if target.dead?
# Ignore if no countertargets
next if target.countertargets == []
#
# Target now becomes active battler
@active_battler = target
# Acquire counterattack target
target = @active_battler.countertargets[0]
# Erase countertarget array
@active_battler.countertargets.clear
# Set array of targeted battlers
@target_battlers = [target]
#
# Determine counterattack type and optional sp cost for enemy/actor
if @active_battler.is_a?(Game_Enemy)
id = CounterAttack::ENEMY[@active_battler.id][1]
cost = CounterAttack::ENEMY[@active_battler.id][2]
else
id = CounterAttack::ACTOR[@active_battler.id][1]
cost = CounterAttack::ACTOR[@active_battler.id][2]
end
#
# Branch on melee or skill
(id == 0 ) ? counterattack_melee : counterattack_skill(id, cost)
#
# Show counter attack performed
@counterattack = true
# Shift to step 3
@phase4_step = 3
#
end
#
end
#--------------------------------------------------------------------------
# * Counterattack - Melee Action
#--------------------------------------------------------------------------
def counterattack_melee
#
# Set animation ID
@animation1_id = @active_battler.animation1_id
@animation2_id = @active_battler.animation2_id
#
# Apply normal attack results
for target in @target_battlers
target.attack_effect(@active_battler)
end
#
end
#--------------------------------------------------------------------------
# * Counterattack - Skill Action
#--------------------------------------------------------------------------
def counterattack_skill(skill_id, cost=false)
#
# Get skill
@skill = $data_skills[skill_id]
#
# If sp cost is used
if cost == true
# If not enough sp, use melee instead
if @active_battler.sp < @skill.sp_cost
return counterattack_melee
end
# Use up SP
@active_battler.sp -= @skill.sp_cost
end
#
# Set animation ID
@animation1_id = @skill.animation1_id
@animation2_id = @skill.animation2_id
#
# Set command event ID
@common_event_id = @skill.common_event_id
#
# Apply skill effect
for target in @target_battlers
target.skill_effect(@active_battler, @skill)
end
#
end
end
How do I implement the countering system to an enemy? I added the script, but I don't understand the instructions. Is there a variable I need to make? Or is there a button for countering or something? Lol
First... OOPS. Minor correction in the config. One list is for actors, the other for enemeis. But I didn't change the 'text' to note the second is for enemies. The values are correct... just the text describing them was borked.
As too defining the enemies that perform counter attacks, it's just that you add them to the list within the configuration section: module CounterAttack.
Code:
# Enemy Counters
# ==============
# Define the actors perfoming counter attacks: the chance of a counter,
# the skill ID used (or 0 for melee), and optionally the SP cost.
#
# Chance Skill SPCost
#========== ====== ====== ======
ENEMY[1] = [ 100, 7, true] # Ghosts use Fire 100%
This (now corrected) is the list that depicts the enemies that perform counter attacks. Currently only one enemy is defined, an enemy with the ID of 1: The Ghost.
Regarding [100, 7, true]... let's go down the list shall we?
The ghost, if struck, will perform a counter attack 100% of the time.
The ghost, if delivering a counterattack, will use skill #7 (Fire).
And if using a skill counterattack, WILL use the ghost's SP because it's set to true.
If I wished to make another enemy like the IMP, I could define it thusly...
Code:
#========== ====== ====== ======
ENEMY[7] = [ 50, 33] # Imps use Venom 50% (no SP Loss)
Now THIS Imp has different characteristics, they are as follows:
The Imp, if struck, will perform a counter attack only 50% of the time
The Imp, if delivering a counter attack, will use skill #33 (Venom).
And if using a skill counterattack, the use of SP is not defined (trueis optional)
And again, as the instructions imply... if the skill is set to 0, then the attack is a melee attack and not a skill.
Both actors and enemies can be configured this way. And once fonfigured... it's automatic. No on/off switch. The actual strike hitting the enemy (or actor) triggers the counterattack.
Ok so I discovered an issue.
So a couple things I noticed:
I was battling an enemy that counters 20% of the time with a basic attack. But I noticed that randomly my character 2 was auto attacking out of turn, even when he was paralyzed. That was weird.
But then the battle also crashed during testing with a message saying:
Line 221:No method error occured.
undefined method ' ' for nil:NilClass
Paralyzed!? Ooh. Status ailments to the rescue. Yeah, that's something I had not considered. So indeed, something will need to be done.
Insofar as your 'Character 2' attacking out of turn... Does he/she share a Database position index as an attacker? By that, consider that the Sahagin is enemy #3 as well as Cyrus being actor #3. I would have sworn this was not an issue at all, but if this is the case, let me know.
As to:
Line 221:No method error occured.
undefined method ' ' for nil:NilClass
... the system performs a few tests before a counter attack is performed. And within in phase_4_step5, I have this bit of code
Code:
# Define chance
chance = 0
# Determine counterattack chance for enemy/actor
if target.is_a?(Game_Enemy)
if CounterAttack::ENEMY.has_key?(target.id)
chance = CounterAttack::ENEMY[target.id][0]
end
else
if CounterAttack::ACTOR.has_key?(target.id)
chance = CounterAttack::ACTOR[target.id][0]
end
end
#
Initially, I thought it was adequate. But I figure one additional like would be worthwhile:
next if chance == 0
Place this before the line that reads next if chance < rand(100)
And if no 'chance' for a combo attack still exists... SKIP IT!
Currently, that is why I dub this script
BUMP to version 1.1
Temporarily of course. I still need to consider the Restriction Level 4(Can't Move) for any Paralyze-styled status ailments.
Oh wow I'm so sorry! The script has the actor 2 automatically having a 50% counterattack rate. For some reason, my mind wrote it off as a demonstration purpose type thing. I imagine that will fix the random counter attacking.
Also, I can't seem to find the line the " next if chance < rand(100)" is on, in order to insert the "next if chance == 0" before it.
I stated that the previous version was temporary until I inserted a measure so a paralyzed person cannot respond with a counter attack. And as of now, a simple line was added (and comments of course) to add that measure into the system.
The new line now exists on line 170, below the 'next if target.damage.nil?' statement within the counterattack_phase4_step5 method. And it is a simple statement as you can see below:
next if target.restriction ==4
Nothing of the configuration system needed change, so one could just rip and replace the whole engine below the config section if you like.