OMORI_Android/www.eng/js/plugins/YEP_X_CounterControl.js
2024-01-15 18:44:53 +03:00

1986 lines
No EOL
75 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//=============================================================================
// Yanfly Engine Plugins - Battle Engine Extension - Counter Control
// YEP_X_CounterControl.js
//=============================================================================
var Imported = Imported || {};
Imported.YEP_X_CounterControl = true;
var Yanfly = Yanfly || {};
Yanfly.Counter = Yanfly.Counter || {};
Yanfly.Counter.version = 1.08;
//=============================================================================
/*:
* @plugindesc v1.08 (Requires YEP_BattleEngineCore.js) Gives you more
* control over how counters work in RPG Maker MV!
* @author Yanfly Engine Plugins
*
* @param ---General---
* @default
*
* @param Queue Max
* @parent ---General---
* @type number
* @min 1
* @desc What's the maximum size for the counter queue?
* @default 20
*
* @param ---Default Traits---
* @default
*
* @param Counter Skill
* @parent ---Default Traits---
* @type number
* @min 1
* @desc This is the default skill used for counterattacks.
* Insert the skill ID here. Use 0 for the MV default.
* @default 1
*
* @param Evade Counter
* @parent ---Default Traits---
* @type boolean
* @on YES
* @off NO
* @desc Counter skills to evade, then counter by default?
* NO - false YES - true
* @default false
*
* @param Counter Name
* @parent ---Default Traits---
* @desc The default counter skill name used per skill.
* %1 - Skill Name
* @default Counter-%1
*
* @param Counter Icon
* @parent ---Default Traits---
* @type number
* @min 0
* @desc The icon ID used for counter attacks. Leave at 0
* to use the default skill's icon.
* @default 78
*
* @param Counter Total
* @parent ---Default Traits---
* @desc Default amount of counters per actor and enemy.
* @default 1
*
* @param Ally Counter
* @parent ---Default Traits---
* @type boolean
* @on YES
* @off NO
* @desc Allow allies to counter the actions of other allies?
* NO - false YES - true
* @default false
*
* @param ---Default Conditions---
* @default
*
* @param Physical
* @parent ---Default Conditions---
* @type boolean
* @on YES
* @off NO
* @desc Require the countered action to be physical?
* NO - false YES - true
* @default true
*
* @param Single Target
* @parent ---Default Conditions---
* @type boolean
* @on YES
* @off NO
* @desc Require the countered action scope to be single target?
* NO - false YES - true
* @default true
*
* @param Not Counter
* @parent ---Default Conditions---
* @type boolean
* @on YES
* @off NO
* @desc Require the countered action to not be a counter?
* NO - false YES - true
* @default false
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* This plugin requires YEP_BattleEngineCore. Make sure this plugin is located
* under YEP_BattleEngineCore in the plugin list.
*
* If you are using Imported.YEP_X_BattleSysATB or Imported.YEP_X_BattleSysCTB,
* place this plugin under those plugins in the plugin list.
*
* The default counterattack trait in RPG Maker MV doesn't give many options
* for the developer. It's a skill that flatout cancels out the physical skill
* of the attacker by evading it and then producing a normal attack from the
* counterattacker. This plugin will give you more control over how counters
* work in the sense that you can choose to have the counter connect first
* before allowing the counter skill to proc.
*
* ============================================================================
* Instructions - How Advanced Counters Work
* ============================================================================
*
* A counterattack is an action that serves as a reaction to an action used by
* an opposing battler unless the action is marked as able of being countered
* by allied members.
*
* Now begins a clash between the attacker's anti-counter stat (newly added)
* against the target's counter stat plus any of the action's modifiers. Once
* the finalized counter rate is decided, a random number check is made to see
* if the counter will pass. If it doesn't, no counter will occur. If it does,
* the next step occurs.
*
* The target will then generate a pool of skills it can use as counters. It
* will go in a priority list mentioned in the next section below. The battle
* system will then go through the pool of skills in order and select the first
* counter skill that meets all of the conditions required. If no skill is
* selected, no skill will be used as a counter. All skills have a mandatory
* requirement of being able to pay the skill's cost and can use it.
*
* Once the skill is selected, the counter skill is placed in the counter queue
* and waits for the current attacker's turn to be over. Once over, the actions
* in the counter queue will begin. The counterattacker will perform counter
* actions without conflicting with their own turns. This process will repeat
* itself until the counter queue is emptied.
*
* During the counter queue process, counter skills can trigger counter skills,
* too. For that reason, there is a maximum queue size determined by the plugin
* parameters. Once the queue count reaches this size, no more counter skills
* will be added to the counter queue.
*
* ============================================================================
* Instructions - Counter Skill Priority List
* ============================================================================
*
* When the pool of counter skills is being generated, they will be generated
* in the following order:
*
* 1. States - Highest Priority Notebox
* 2. States - Lowest Priority Notebox
* 3. Equipment - Weapons Notebox
* 4. Equipment - Armors Notebox
* 5. Actor - Current Class Notebox
* 6. Actor - Actor Notebox
* 7. Enemy - Enemy Notebox
*
* The order of the pool of counter skills matter in that when going through
* the conditions of the counter skill to be used, the first counter skill
* whose condition is met will be the one used.
*
* ============================================================================
* Notetags
* ============================================================================
*
* You can use the following notetags to alter counters in your game. Each of
* these notetags will alter counters in a particular way.
*
* Actor and Enemy Notetags:
*
* <Default Counter: x>
* <Default Counter: name>
* Sets the default counter skill to x. If it is left as 0, then the counter
* skill will be RPG Maker MV's default counter skill. If you are using the
* name of the skill, and there are multiple skills in the database with the
* same name, then priority will be given to the skill with the highest ID.
* *Note: Use 0 for x if you wish to add RPG Maker MV's default counter.
*
* Actor, Class, Enemy, Weapon, Armor, and State Notetags:
*
* <Counter Skills: x>
* <Counter Skills: x, x, x>
* <Counter Skills: x to y>
* This will add to the list of possible counter skills for the battler.
* If multiple skill ID's are listed, then they're all added. Priority will
* be given to the counter skills listed earlier.
* *Note: Use 0 for x if you wish to add RPG Maker MV's default counter.
* *Note2: See the Counter List priority to see which skills will be given
* priority on the counter skill list.
*
* <Counter Skill: name>
* This will add the named skill to the list of possible counter skills for
* the battler. If there are multiple skills in the database with the same
* name, then priority will be given to the skill with the highest ID.
* *Note: See the Counter List priority to see which skills will be given
* priority on the counter skill list.
*
* <Counter Total: +x>
* <Counter Total: -x>
* Alters the number of times the battler can counter by x. This is the
* amount of times the battler can counter until the battler's turn comes up
* at which, the number of times is reset.
*
* <Target Counter: x%>
* When this battler attacks an opponent target, this will cause the target
* counter rate to be altered by x% rate. If a target has 10% CNT, then a
* notetag of 50% will cause the counter rate to become 5%.
*
* <Target Counter: +x%>
* <Target Counter: -x%>
* When this battler attacks an opponent target, this will cause the target
* counter rate to increase or decrease by x%. If a target has 10% CNT, then
* a notetag of +50% will cause the counter rate to become +60%.
*
* <Evade Counter>
* This will change all counter skills used by the related battler to become
* evade counters regardless of their default nature. However, if the battler
* is affected by a trait that is <Hit Counter>, then priority will be given
* to the <Hit Counter> trait instead.
*
* <Hit Counter>
* This will change all counter skills used by the related battler to become
* hit counters regardless of their default nature. If the battler is also
* affected by <Evade Counter>, this effect will take priority.
*
* Skill and Item Notetags:
*
* <Ally Counter>
* Makes this action able to proc counter skills by allied members.
*
* <Ally Cannot Counter>
* Makes this action unable to proc counter skills by allied members.
*
* <Cannot Counter>
* Causes this action to be un-counterable. This means that it will always
* return a 0% counterattack possibility.
*
* <Counter Rate: x%>
* This will cause this action to proc a counter from the target by x% rate.
* This means if the target has a 10% chance to counter and this notetag is
* 50%, then the target will have a 5% chance to counter.
*
* <Counter Rate: +x%>
* <Counter Rate: -x%>
* This will cause this action to proc a counter from the target by an
* additive x%. This means if the target has a 10% chance to counter and this
* notetag is +50%, then the target has a 60% chance to counter.
*
* Skill Notetags:
*
* <Evade Counter>
* If this skill is being used as the counter skill, the battler will evade
* the current action and then counter.
*
* <Hit Counter>
* If this skill is being used as the counter skill, the battler will take
* the hit against the current action and then counter.
*
* <Counter Name: text>
* This changes the displayed name of the skill when used as a counter skill
* to 'text'.
*
* <Counter Icon: x>
* This changes the displayed icon of the skill when used as a counter skill
* to x icon.
*
* ============================================================================
* Notetags - Counter Conditions
* ============================================================================
*
* When making your counter skills, you can have those counter skills respond
* only to specific conditions. If all conditions are met, the counter skill
* will occur. If a single condition isn't met, that counter skill will then be
* skipped and the next one will be checked. To add counter conditions, use the
* following notetags:
*
* Skill Notetags:
*
* <Counter Condition>
* condition
* condition
* </Counter Condition>
* Replace the 'condition' text in between the notetags with the listed in
* the conditions list below to best fit what you want.
*
* --- Example ---
*
* <Counter Condition>
* physical hit
* single target
* </Counter Condition>
* This skill will only be used as a counter skill if the current action is
* a physical hit that's single target.
*
* ============================================================================
* Counter Condition List
* ============================================================================
*
* Here is a list of all the counter conditions that come with this plugin that
* you can use. Keep in mind that all of the counter conditions must be met
* before a counter will take effect. If even a single counter condition fails
* to be met, the counter skill will not proc.
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* ATTACKER param eval
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Replace 'param' with 'level', 'maxhp', 'hp', 'maxmp', 'mp', 'atk', 'def',
* 'mat', 'mdf', 'agi', or 'luk'. This will run a check against the attacker's
* parameter. If the check returns 'true', the counter condition is met. If it
* returns 'false', the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Attacker level > 50
* Attacker hp <= attacker.mhp * 0.50
* Attacker atk > defender.def
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* CERTAIN HIT
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is a certain hit, the counter
* condition is met. If it isn't, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Certain Hit
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* COUNTER HIT
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is a counter skill, the
* counter condition is met. If it isn't, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Counter Hit
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* DEFENDER param eval
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Replace 'param' with 'level', 'maxhp', 'hp', 'maxmp', 'mp', 'atk', 'def',
* 'mat', 'mdf', 'agi', or 'luk'. This will run a check against the defender's
* parameter. If the check returns 'true', the counter condition is met. If it
* returns 'false', the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Defender level > 50
* Defender hp <= defender.mhp * 0.50
* Defender atk > attacker.def
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* ELEMENT: x
* ELEMENT: name
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target has element X attached to it,
* the counter condition is met. If it isn't, the counter condition isn't met.
* Replace 'x' with the element ID or the element name in the database system
* tab. If multiple elements share the same name, priority will be given to the
* element with the highest ID.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Element: 4
* Element: Fire
* Element: Ice
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* EVAL: code
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* For those with JavaScript experience, you can use the above line to perform
* an eval check to see if the conditions are met for the counter skill. If the
* eval check returns 'true', the condition is met. If it returns 'false', the
* condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Eval: attacker.name() === 'Harold'
* Eval: defender.hpRate() <= 0.50
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* ITEM: x
* ITEM: name
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current aciton used against the target is item x, the counter
* condition is met. If it isn't, the counter condition isn't met. Replace 'x'
* with the item ID. If you choose to use the item name, and your database
* has multiple items with the same name, priority will be given to the item
* with the highest ID.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Item: 30
* Item: Bomb
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* MAGICAL HIT
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is a magical hit, the counter
* condition is met. If it isn't, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Magical Hit
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* MULTI TARGET
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is a multi target action, the
* counter condition is met. If it isn't, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Multi Target
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* NOT CERTAIN HIT
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is NOT certain hit, the
* counter condition is met. If it is, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Not Certain Hit
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* NOT COUNTER HIT
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is NOT a counter skill, the
* counter condition is met. If it is, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Not Counter Hit
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* NOT ELEMENT: x
* NOT ELEMENT: name
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target has element X attached to it,
* the counter condition is NOT met. If it isn't, the counter condition is met.
* Replace 'x' with the element ID or the element name in the database system
* tab. If multiple elements share the same name, priority will be given to the
* element with the highest ID.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Not Element: 4
* Not Element: Fire
* Not Element: Ice
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* NOT ITEM: x
* NOT ITEM: name
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current aciton used against the target is NOT item x, the counter
* condition is met. If it is, the counter condition isn't met. Replace 'x'
* with the item ID. If you choose to use the item name, and your database
* has multiple items with the same name, priority will be given to the item
* with the highest ID.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Not Item: 30
* Not Item: Bomb
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* NOT MAGICAL HIT
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is NOT a magical hit, the
* counter condition is met. If it is, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Not Magical Hit
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* NOT PHYSICAL HIT
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is NOT a physical hit, the
* counter condition is met. If it is, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Not Physical Hit
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* NOT SKILL: x
* NOT SKILL: name
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current aciton used against the target is NOT skill x, the counter
* condition is met. If it is, the counter condition isn't met. Replace 'x'
* with the skill ID. If you choose to use the skill name, and your database
* has multiple skills with the same name, priority will be given to the skill
* with the highest ID.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Not Skill: 50
* Not Skill: Firaga
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* NOT STYPE: x
* NOT STYPE: name
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is NOT a skill and skill type
* x, the counter condition is met. If it isn't the counter condition isn't
* met. Replace 'x' with the Skill Type ID. If you choose to use the skill type
* name and your database has multiple skill types with the same name, priority
* will be given to the skill type with the highest ID.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Not Stype: 1
* Not Stype: Magic
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* PHYSICAL HIT
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is a physical hit, the counter
* condition is met. If it isn't, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Physical Hit
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* RANDOM: x%
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* This will run a random check. There is a x% chance that this counter check
* will pass. If it passes, the counter condition is met. If it doesn't, the
* counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Random: 30%
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* SINGLE TARGET
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is a single target action, the
* counter condition is met. If it isn't, the counter condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Single Target
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* SKILL: x
* SKILL: name
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current aciton used against the target is skill x, the counter
* condition is met. If it isn't, the counter condition isn't met. Replace 'x'
* with the skill ID. If you choose to use the skill name, and your database
* has multiple skills with the same name, priority will be given to the skill
* with the highest ID.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Skill: 50
* Skill: Firaga
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* STYPE: x
* STYPE: name
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If the current action used against the target is a skill and skill type x,
* the counter condition is met. If it isn't the counter condition isn't met.
* Replace 'x' with the Skill Type ID. If you choose to use the skill type name
* and your database has multiple skill types with the same name, priority will
* be given to the skill type with the highest ID.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Stype: 1
* Stype: Magic
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* SWITCH x OFF
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If switch x is OFF (false) prior to the current action being used against
* the target, the counter condition is met. If it is ON (true), the counter
* condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Switch 10 Off
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* SWITCH x ON
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* If switch x is ON (ftrue) prior to the current action being used against
* the target, the counter condition is met. If it is OFF (false), the counter
* condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Switch 10 On
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* VARIABLE x eval
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* This runs an eval check against variable x. If the eval check returns 'true'
* the condition is met. If it returns 'false' then the condition isn't met.
*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example: Variable 15 >= 15
* Variable 16 <= 20
* Variable 17 === $gameParty.aliveMembers().length
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* ============================================================================
* Lunatic Mode - Custom Counter Skills
* ============================================================================
*
* For those with JavaScript proficiency, you can use the following Lunatic
* Mode notetags to give a dynamic set of skills granted for counter usage.
*
* Actor, Class, Enemy, Weapon, Armor, and State Notetags:
*
* <Custom Counter Skills>
* if (user.name() === 'Harold') {
* skills.push(50, 51, 52);
* } else if (user.name() === 'Therese') {
* skills.push(53, 54, 55);
* } else if (user.name() === 'Marsha') {
* skills.push(56, 57, 58);
* } else if (user.name() === 'Lucius') {
* skills.push(59, 60, 61);
* }
* </Custom Counter Skills>
* The 'skills' variable is an array that will contain all the counter skills
* that will be added to the list of potential skills the battler can counter
* actions with provided that their requirements are met.
*
* ============================================================================
* Lunatic Mode - Custom Counter Total
* ============================================================================
*
* For those with JavaScript proficiency, you can use the following Lunatic
* Mode notetags to give a dynamic counter total bonus:
*
* Actor, Class, Enemy, Weapon, Armor, and State Notetags:
*
* <Custom Counter Total>
* value = user.level;
* </Custom Counter Total>
* The 'value' variable is the total amount of counters is increased or
* decreased by. If the total counter value reaches 0 or less than 0 for the
* battler, the battler is unable to use counter skills.
*
* ============================================================================
* Lunatic Mode - Custom Target Counter Rate
* ============================================================================
*
* For those with JavaScript proficiency, you can use the following Lunatic
* Mode notetags to make the attacker's traits alter the target's CNT rate.
*
* Actor, Class, Enemy, Weapon, Armor, and State Notetags:
*
* <Custom Target Counter Rate>
* rate -= user.hpRate();
* </Custom Target Counter Rate>
* The 'rate' variable is the final rate used to determine the counter rate
* the target has. It is already given the value calculated from the target's
* CNT value. This is calculated before the skill's custom counter rate.
*
* ============================================================================
* Lunatic Mode - Custom Counter Rates
* ============================================================================
*
* For those with JavaScript proficiency, you can use the following Lunatic
* Mode notetags to give skills a dynamic chance for the target to counter.
*
* Skill and Item Notetags:
*
* <Custom Counter Rate>
* rate += target.hpRate();
* </Custom Counter Rate>
* The 'rate' variable is the final rate used to determine the counter rate
* the target has. It is already given the value calculated from the target's
* CNT value plus any additional counter rate modifiers from the skill. This
* is calculated after the attacker's custom target counter rate.
*
* ============================================================================
* Lunatic Mode - Custom Counter Condition
* ============================================================================
*
* For those with JavaScript proficiency, you can use the following Luantic
* Mode notetags to give counter skills a custom counter condition. While you
* can do the same with an Eval condition, this notetag is for those who prefer
* to take control over everything at once.
*
* Skill Notetags:
*
* <Custom Counter Condition>
* if (attacker.name() === 'Harold') {
* condition = true;
* } else if (defender.name() === 'Therese') {
* condition = true;
* } else {
* condition = false;
* }
* </Custom Counter Condition>
* The 'condition' variable determines whether or not the counter skill will
* pass or fail. If the 'condition' variable returns 'true', the condition is
* met. If the 'condition' variable returns 'false', the condition fails to
* be met. Once the condition is met, the rest of the <Counter Condition>
* conditions will be checked.
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.08:
* - Updated for RPG Maker MV version 1.5.0.
*
* Version 1.07a:
* - Lunatic Mode fail safes added.
* - Optimization update
*
* Version 1.06:
* - Updated for RPG Maker MV version 1.3.2.
*
* Version 1.05:
* - Fixed a bug that caused the Eval: condition to not work and crash.
* - Fixed an issue that caused default counter attacks to trigger upon magical
* actions.
*
* Version 1.04:
* - Fixed a bug that caused counter-countered actions to no longer disappear
* from queue.
*
* Version 1.03:
* - Fixed a bug that caused enemies to get a free action after a counter in
* the DTB engine.
*
* Version 1.02:
* - Fixed a bug that didn't replace the proper skill for the countered battler
* appropriate causing some action effects to not proc correctly.
*
* Version 1.01:
* - Fixed a bug that caused the <Counter Skills: 0> notetag to not work.
*
* Version 1.00:
* - Finished Plugin!
*/
//=============================================================================
if (Imported.YEP_BattleEngineCore) {
//=============================================================================
// Parameter Variables
//=============================================================================
Yanfly.Parameters = PluginManager.parameters('YEP_X_CounterControl');
Yanfly.Param = Yanfly.Param || {};
Yanfly.Param.CounterMaxQueue = Number(Yanfly.Parameters['Queue Max']);
Yanfly.Param.CounterDefault = Number(Yanfly.Parameters['Counter Skill']);
Yanfly.Param.CounterEvade = eval(String(Yanfly.Parameters['Evade Counter']));
Yanfly.Param.CounterFmt = String(Yanfly.Parameters['Counter Name']);
Yanfly.Param.CounterIcon = Number(Yanfly.Parameters['Counter Icon']);
Yanfly.Param.CounterTotal = Number(Yanfly.Parameters['Counter Total']);
Yanfly.Param.CounterAllyCnt = eval(String(Yanfly.Parameters['Ally Counter']));
Yanfly.Param.CounterConditions = [];
if (eval(String(Yanfly.Parameters['Physical']))) {
Yanfly.Param.CounterConditions.push('PHYSICAL HIT');
};
if (eval(String(Yanfly.Parameters['Single Target']))) {
Yanfly.Param.CounterConditions.push('SINGLE TARGET');
};
if (eval(String(Yanfly.Parameters['Not Counter']))) {
Yanfly.Param.CounterConditions.push('NOT COUNTER HIT');
};
//=============================================================================
// DataManager
//=============================================================================
Yanfly.Counter.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function () {
if (!Yanfly.Counter.DataManager_isDatabaseLoaded.call(this)) return false;
if (!Yanfly._loaded_YEP_X_CounterControl) {
this.processCounterNotetagsI($dataItems);
this.processCounterNotetagsW($dataWeapons);
this.processCounterNotetagsA($dataArmors);
this.processCounterNotetagsS($dataSkills);
this.processCounterNotetagsT($dataStates);
this.processCounterNotetagsSys($dataSystem);
this.processCounterNotetags1($dataActors);
this.processCounterNotetags1($dataEnemies);
this.processCounterNotetags2($dataActors);
this.processCounterNotetags2($dataClasses);
this.processCounterNotetags2($dataEnemies);
this.processCounterNotetags2($dataWeapons);
this.processCounterNotetags2($dataArmors);
this.processCounterNotetags2($dataStates);
this.processCounterNotetags3($dataSkills);
this.processCounterNotetags4($dataSkills);
this.processCounterNotetags4($dataItems);
Yanfly._loaded_YEP_X_CounterControl = true;
}
return true;
};
DataManager.processCounterNotetagsI = function (group) {
if (Yanfly.ItemIdRef) return;
Yanfly.ItemIdRef = {};
for (var n = 1; n < group.length; n++) {
var obj = group[n];
if (obj.name.length <= 0) continue;
Yanfly.ItemIdRef[obj.name.toUpperCase()] = n;
}
};
DataManager.processCounterNotetagsW = function (group) {
if (Yanfly.WeaponIdRef) return;
Yanfly.WeaponIdRef = {};
for (var n = 1; n < group.length; n++) {
var obj = group[n];
if (obj.name.length <= 0) continue;
Yanfly.WeaponIdRef[obj.name.toUpperCase()] = n;
}
};
DataManager.processCounterNotetagsA = function (group) {
if (Yanfly.ArmorIdRef) return;
Yanfly.ArmorIdRef = {};
for (var n = 1; n < group.length; n++) {
var obj = group[n];
if (obj.name.length <= 0) continue;
Yanfly.ArmorIdRef[obj.name.toUpperCase()] = n;
}
};
DataManager.processCounterNotetagsS = function (group) {
if (Yanfly.SkillIdRef) return;
Yanfly.SkillIdRef = {};
for (var n = 1; n < group.length; n++) {
var obj = group[n];
if (obj.name.length <= 0) continue;
Yanfly.SkillIdRef[obj.name.toUpperCase()] = n;
}
};
DataManager.processCounterNotetagsT = function (group) {
if (Yanfly.StateIdRef) return;
Yanfly.StateIdRef = {};
for (var n = 1; n < group.length; n++) {
var obj = group[n];
if (obj.name.length <= 0) continue;
Yanfly.StateIdRef[obj.name.toUpperCase()] = n;
}
};
DataManager.processCounterNotetagsSys = function (group) {
Yanfly.STypeIdRef = {};
for (var i = 1; i < group.skillTypes.length; ++i) {
var name = group.skillTypes[i].toUpperCase();
name = name.replace(/\\I\[(\d+)\]/gi, '');
Yanfly.STypeIdRef[name] = i;
}
Yanfly.ElementIdRef = {};
for (var i = 1; i < group.elements.length; ++i) {
var name = group.elements[i].toUpperCase();
name = name.replace(/\\I\[(\d+)\]/gi, '');
Yanfly.ElementIdRef[name] = i;
}
};
DataManager.processCounterNotetags1 = function (group) {
for (var n = 1; n < group.length; n++) {
var obj = group[n];
var notedata = obj.note.split(/[\r\n]+/);
obj.defaultCounter = Yanfly.Param.CounterDefault;
obj.counterTotal = Yanfly.Param.CounterTotal;
for (var i = 0; i < notedata.length; i++) {
var line = notedata[i];
if (line.match(/<DEFAULT COUNTER:[ ](\d+)>/i)) {
obj.defaultCounter = parseInt(RegExp.$1);
} else if (line.match(/<DEFAULT COUNTER:[ ](.*)>/i)) {
var name = String(RegExp.$1).toUpperCase();
var id = Yanfly.SkillIdRef[name];
if (id) obj.defaultCounter = id;
}
}
}
};
DataManager.processCounterNotetags2 = function (group) {
var noteA1 = /<(?:COUNTER SKILLS):[ ]*(\d+(?:\s*,\s*\d+)*)>/i;
var noteA2 = /<(?:COUNTER SKILLS):[ ](\d+)[ ](?:THROUGH|to)[ ](\d+)>/i;
for (var n = 1; n < group.length; n++) {
var obj = group[n];
var notedata = obj.note.split(/[\r\n]+/);
obj.counterSkills = [];
obj.counterTotal = 0;
obj.targetCounterRate = 1;
obj.targetCounterFlat = 0;
obj.evadeCounter = false;
obj.hitCounter = false;
var evalMode = 'none';
obj.counterTotalEval = '';
obj.counterSkillsEval = '';
obj.targetCounterRateEval = '';
for (var i = 0; i < notedata.length; i++) {
var line = notedata[i];
if (line.match(noteA1)) {
var array = JSON.parse('[' + RegExp.$1.match(/\d+/g) + ']');
obj.counterSkills = obj.counterSkills.concat(array);
} else if (line.match(noteA2)) {
var range = Yanfly.Util.getRange(parseInt(RegExp.$1),
parseInt(RegExp.$2));
obj.counterSkills = obj.counterSkills.concat(range);
} else if (line.match(/<(?:COUNTER SKILL):[ ](.*)>/i)) {
var name = String(RegExp.$1).toUpperCase();
var id = Yanfly.SkillIdRef[name];
if (id) obj.counterSkills.push(id);
} else if (line.match(/<(?:COUNTER TOTAL):[ ]([\+\-]\d+)>/i)) {
obj.counterTotal = parseInt(RegExp.$1);
} else if (line.match(/<(?:TARGET COUNTER):[ ](\d+)([%])>/i)) {
obj.targetCounterRate = parseFloat(RegExp.$1) * 0.01;
} else if (line.match(/<(?:TARGET COUNTER):[ ]([\+\-]\d+)([%])>/i)) {
obj.targetCounterFlat = parseFloat(RegExp.$1) * 0.01;
} else if (line.match(/<(?:EVADE COUNTER|COUNTER EVADE)>/i)) {
obj.evadeCounter = true;
} else if (line.match(/<(?:HIT COUNTER|COUNTER HIT)>/i)) {
obj.hitCounter = true;
} else if (line.match(/<CUSTOM COUNTER TOTAL>/i)) {
evalMode = 'custom counter total';
} else if (line.match(/<\/CUSTOM COUNTER TOTAL>/i)) {
evalMode = 'none';
} else if (evalMode === 'custom counter total') {
obj.counterTotalEval = obj.counterTotalEval + line + '\n';
} else if (line.match(/<CUSTOM COUNTER SKILLS>/i)) {
evalMode = 'custom counter skills';
} else if (line.match(/<\/CUSTOM COUNTER SKILLS>/i)) {
evalMode = 'none';
} else if (evalMode === 'custom counter skills') {
obj.counterSkillsEval = obj.counterSkillsEval + line + '\n';
} else if (line.match(/<CUSTOM TARGET COUNTER RATE>/i)) {
evalMode = 'custom target counter rate';
} else if (line.match(/<\/CUSTOM TARGET COUNTER RATE>/i)) {
evalMode = 'none';
} else if (evalMode === 'custom target counter rate') {
obj.targetCounterRateEval = obj.targetCounterRateEval + line + '\n';
}
}
}
};
DataManager.processCounterNotetags3 = function (group) {
for (var n = 1; n < group.length; n++) {
var obj = group[n];
var notedata = obj.note.split(/[\r\n]+/);
obj.evadeCounter = Yanfly.Param.CounterEvade;
obj.counterName = Yanfly.Param.CounterFmt.format(obj.name);
obj.counterIcon = Yanfly.Param.CounterIcon || obj.iconIndex;
obj.cannotCounter = false;
var evalMode = 'none';
obj.counterConditions = Yanfly.Param.CounterConditions.slice();
obj.counterConditionEval = '';
for (var i = 0; i < notedata.length; i++) {
var line = notedata[i];
if (line.match(/<(?:EVADE COUNTER|COUNTER EVADE)>/i)) {
obj.evadeCounter = true;
} else if (line.match(/<(?:HIT COUNTER|COUNTER HIT)>/i)) {
obj.evadeCounter = false;
} else if (line.match(/<(?:COUNTER NAME):[ ](.*)>/i)) {
obj.counterName = String(RegExp.$1);
} else if (line.match(/<(?:COUNTER ICON):[ ](\d+)>/i)) {
obj.counterIcon = String(RegExp.$1);
} else if (line.match(/<CANNOT COUNTER>/i)) {
obj.cannotCounter = true;
} else if (line.match(/<(?:COUNTER CONDITION|COUNTER CONDITIONS)>/i)) {
evalMode = 'counter condition';
obj.counterConditions = [];
} else if (line.match(/<\/(?:COUNTER CONDITION|COUNTER CONDITIONS)>/i)) {
evalMode = 'none';
} else if (evalMode === 'counter condition') {
obj.counterConditions.push(line);
} else if (line.match(/<CUSTOM COUNTER CONDITION>/i)) {
evalMode = 'custom counter condition';
} else if (line.match(/<\/CUSTOM COUNTER CONDITION>/i)) {
evalMode = 'none';
} else if (evalMode === 'custom counter condition') {
obj.counterConditionEval = obj.counterConditionEval + line + '\n';
}
}
}
};
DataManager.processCounterNotetags4 = function (group) {
for (var n = 1; n < group.length; n++) {
var obj = group[n];
var notedata = obj.note.split(/[\r\n]+/);
obj.allyCounter = Yanfly.Param.CounterAllyCnt;
obj.cannotCounter = false;
obj.counterRate = 1;
obj.counterMod = 0;
var evalMode = 'none';
obj.counterRateEval = '';
for (var i = 0; i < notedata.length; i++) {
var line = notedata[i];
if (line.match(/<ALLY COUNTER>/i)) {
obj.allyCounter = true;
} else if (line.match(/<ALLY CANNOT COUNTER>/i)) {
obj.allyCounter = false;
} else if (line.match(/<CANNOT COUNTER>/i)) {
obj.cannotCounter = true;
} else if (line.match(/<COUNTER RATE:[ ](\d+)([%])>/i)) {
obj.counterRate = parseFloat(RegExp.$1) * 0.01;
} else if (line.match(/<COUNTER RATE:[ ]([\+\-]\d+)([%])>/i)) {
obj.counterMod = parseFloat(RegExp.$1) * 0.01;
} else if (line.match(/<CUSTOM COUNTER RATE>/i)) {
evalMode = 'custom counter rate';
} else if (line.match(/<\/CUSTOM COUNTER RATE>/i)) {
evalMode = 'none';
} else if (evalMode === 'custom counter rate') {
obj.counterRateEval = obj.counterRateEval + line + '\n';
}
}
}
};
//=============================================================================
// BattleManager
//=============================================================================
Yanfly.Counter.BattleManager_initMembers = BattleManager.initMembers;
BattleManager.initMembers = function () {
Yanfly.Counter.BattleManager_initMembers.call(this);
this._counterQueue = [];
this._counterSequence = 0;
this._counterOriginalSubject = undefined;
this._counterOriginalAction = undefined;
this._countering = false;
};
BattleManager.isCountering = function () {
return this._countering;
};
Yanfly.Counter.BattleManager_invokeCounter =
BattleManager.invokeCounterAttack;
BattleManager.invokeCounterAttack = function (subject, target) {
this._counterQueue = this._counterQueue || [];
if (this.isValidCounterAction(target)) this._counterSequence += 1;
if (!this.isMaxCounterQueue()) {
if (this.isValidCounterAction(target)) target.payCounter();
}
if (target.canCounter()) {
this._counterSkill = this.getCounterSkill(subject, target);
this._counterQueue = this._counterQueue || [];
if (this._counterSkill === null) {
if (this._action.isPhysical() && target.canMove()) {
Yanfly.Counter.BattleManager_invokeCounter.call(this, subject, target);
} else {
this.invokeNormalAction(subject, target);
}
return;
} else if (this.evadeAndCounter(subject, target)) {
target.performEvasion();
target.forceEvadePopup();
this.addCounterQueue(subject, target);
} else if (this._counterSkill !== undefined) {
this.invokeNormalAction(subject, target);
this.addCounterQueue(subject, target);
} else {
if (this.isValidCounterAction(target)) {
target.payCounter(-1);
this._counterSequence -= 1;
}
this.invokeNormalAction(subject, target);
return;
}
this._logWindow.displayActionResults(target, subject);
if (subject.isDead()) subject.performCollapse();
} else {
this.invokeNormalAction(subject, target);
}
};
BattleManager.getCounterSkill = function (subject, target) {
target.makeCounterSkills();
var skills = target.counterSkills();
var length = skills.length;
for (var i = 0; i < length; ++i) {
var skill = skills[i];
if (this.meetCounterConditions(skill, subject, target)) return skill;
}
return undefined;
};
BattleManager.meetCounterConditions = function (skill, subject, target) {
if (skill === null) return true;
if (!target.canUse(skill)) return false;
if (!this.meetCounterConditionsEval(skill, subject, target));
var condition = this.getCounterCondition(skill, subject, target);
return condition;
};
BattleManager.meetCounterConditionsEval = function (skill, subject, target) {
var action = this._action;
if (this._action.item().counterConditionEval === '') return true;
var condition = true;
var a = subject;
var user = subject;
var attacker = subject;
var b = target;
var defender = target;
var item = skill;
var s = $gameSwitches._data;
var v = $gameVariables._data;
var code = this._action.item().counterConditionEval;
try {
eval(code);
} catch (e) {
Yanfly.Util.displayError(e, code, 'COUNTER CONDITIONS EVAL ERROR');
}
return condition;
};
BattleManager.getCounterCondition = function (skill, subject, target) {
var conditions = skill.counterConditions;
var length = conditions.length;
for (var i = 0; i < length; ++i) {
var line = conditions[i];
if (!this.checkCounterLine(line, skill, subject, target)) return false;
}
return true;
};
BattleManager.checkCounterLine = function (line, skill, subject, target) {
// EVAL
if (line.match(/EVAL:[ ](.*)/i)) {
var value = String(RegExp.$1);
return this.checkCounterEval(value, skill, subject, target);
// CERTAIN HIT
} else if (line.toUpperCase() === 'CERTAIN HIT') {
return this.checkCounterHitType(Game_Action.HITTYPE_CERTAIN);
// PHYSICAL HIT
} else if (line.toUpperCase() === 'PHYSICAL HIT') {
return this.checkCounterHitType(Game_Action.HITTYPE_PHYSICAL);
// MAGICAL HIT
} else if (line.toUpperCase() === 'MAGICAL HIT') {
return this.checkCounterHitType(Game_Action.HITTYPE_MAGICAL);
// NOT CERTAIN HIT
} else if (line.toUpperCase() === 'NOT CERTAIN HIT') {
return !this.checkCounterHitType(Game_Action.HITTYPE_CERTAIN);
// NOT PHYSICAL HIT
} else if (line.toUpperCase() === 'NOT PHYSICAL HIT') {
return !this.checkCounterHitType(Game_Action.HITTYPE_PHYSICAL);
// NOT MAGICAL HIT
} else if (line.toUpperCase() === 'NOT MAGICAL HIT') {
return !this.checkCounterHitType(Game_Action.HITTYPE_MAGICAL);
// SINGLE TARGET
} else if (line.toUpperCase() === 'SINGLE TARGET') {
return this.checkCounterSingleTarget();
// MULTI TARGET
} else if (line.toUpperCase() === 'MULTI TARGET') {
return !this.checkCounterSingleTarget();
// COUNTER HIT
} else if (line.toUpperCase() === 'COUNTER HIT') {
return !this.checkCounterCounterHit();
// NOT COUNTER HIT
} else if (line.toUpperCase() === 'NOT COUNTER HIT') {
return !this.checkCounterCounterHit();
// RANDOM
} else if (line.match(/RANDOM:[ ](\d+)([%])/i)) {
var value = parseFloat(RegExp.$1) * 0.01;
return !this.checkCounterRandom(value);
// NOT ELEMENT
} else if (line.match(/NOT ELEMENT:[ ](.*)/i)) {
var value = String(RegExp.$1);
return !this.checkCounterElement(value);
// ELEMENT
} else if (line.match(/ELEMENT:[ ](.*)/i)) {
var value = String(RegExp.$1);
return this.checkCounterElement(value);
// SWITCH ON
} else if (line.match(/SWITCH[ ](\d+)[ ]ON/i)) {
var value = parseInt(RegExp.$1);
return this.checkCounterSwitch(value);
// SWITCH OFF
} else if (line.match(/SWITCH[ ](\d+)[ ]OFF/i)) {
var value = parseInt(RegExp.$1);
return !this.checkCounterSwitch(value);
// VARIABLE
} else if (line.match(/VARIABLE[ ](\d+)[ ](.*)/i)) {
var varId = parseInt(RegExp.$1);
var eval = String(RegExp.$2);
eval = '$gameVariables.value(' + varId + ') ' + eval;
return this.checkCounterEval(eval, skill, subject, target);
// NOT SKILL
} else if (line.match(/NOT SKILL:[ ](.*)/i)) {
var value = String(RegExp.$1);
return !this.checkCounterSkill(value);
// SKILL
} else if (line.match(/SKILL:[ ](.*)/i)) {
var value = String(RegExp.$1);
return this.checkCounterSkill(value);
// NOT STYPE
} else if (line.match(/NOT STYPE:[ ](.*)/i)) {
var value = String(RegExp.$1);
return !this.checkCounterStype(value);
// STYPE
} else if (line.match(/STYPE:[ ](.*)/i)) {
var value = String(RegExp.$1);
return this.checkCounterStype(value);
// NOT ITEM
} else if (line.match(/NOT ITEM:[ ](.*)/i)) {
var value = String(RegExp.$1);
return !this.checkCounterItem(value);
// ITEM
} else if (line.match(/ITEM:[ ](.*)/i)) {
var value = String(RegExp.$1);
return this.checkCounterItem(value);
// ATTACKER PARAM
} else if (line.match(/ATTACKER[ ](.*)[ ](.*)/i)) {
var value1 = String(RegExp.$1);
var value2 = String(RegExp.$1);
return this.checkCounterAttacker(value1, value2, skill, subject, target);
// DEFENDER PARAM
} else if (line.match(/DEFENDER[ ](.*)[ ](.*)/i)) {
var value1 = String(RegExp.$1);
var value2 = String(RegExp.$1);
return this.checkCounterDefender(value1, value2, skill, subject, target);
// ELSE - NOTHING LISTED
} else {
return true;
}
};
BattleManager.checkCounterEval = function (code, skill, subject, target) {
var action = this._action;
var a = subject;
var user = subject;
var attacker = subject;
var b = target;
var defender = target;
var item = skill;
var s = $gameSwitches._data;
var v = $gameVariables._data;
var code = code;
try {
return eval(code);
} catch (e) {
Yanfly.Util.displayError(e, code, 'COUNTER CHECK ERROR');
return false;
}
};
BattleManager.checkCounterHitType = function (value) {
return this._action.item().hitType === value;
};
BattleManager.checkCounterCounterHit = function () {
return this._action.isCounter();
};
BattleManager.checkCounterRandom = function (value) {
return Math.random() < value;
};
BattleManager.checkCounterSingleTarget = function () {
return this._action.isForOne();
};
BattleManager.checkCounterElement = function (value) {
if (value.match(/(\d+)/i)) {
var elementId = parseInt(RegExp.$1);
} else {
var elementId = Yanfly.ElementIdRef[value.toUpperCase()];
if (!elementId) return true;
}
var actionElement = this._action.item().damage.elementId;
if (actionElement < 0) {
return this._subject.attackElements().contains(elementId);
} else {
return elementId === actionElement;
}
};
BattleManager.checkCounterSwitch = function (value) {
return $gameSwitches.value(value);
};
BattleManager.checkCounterSkill = function (value) {
if (!this._action.isSkill()) return false;
if (value.match(/(\d+)/i)) {
var skillId = parseInt(RegExp.$1);
} else {
var skillId = Yanfly.SkillIdRef[value.toUpperCase()];
}
var skill = $dataSkills[skillId];
return this._action.item() === skill;
};
BattleManager.checkCounterStype = function (value) {
if (!this._action.isSkill()) return false;
if (value.match(/(\d+)/i)) {
var stypeId = parseInt(RegExp.$1);
} else {
var stypeId = Yanfly.STypeIdRef[value.toUpperCase()];
}
var skill = this._action.item();
return skill.stypeId === stypeId;
};
BattleManager.checkCounterItem = function (value) {
if (!this._action.isItem()) return false;
if (value.match(/(\d+)/i)) {
var itemId = parseInt(RegExp.$1);
} else {
var itemId = Yanfly.SkillIdRef[value.toUpperCase()];
}
var skill = $dataSkills[skillId];
return this._action.item() === skill;
};
BattleManager.checkCounterAttacker = function (v1, v2, skill, subject, target) {
var eval = 'subject.';
if (['LEVEL', 'LV', 'LVL'].contains(v1.toUpperCase())) {
eval += 'level';
} else if (['MAX HP', 'MAXHP', 'MHP'].contains(v1.toUpperCase())) {
eval += 'mhp';
} else if (['HP', 'CURRENT HP'].contains(v1.toUpperCase())) {
eval += 'hp';
} else if (['MAX MP', 'MAXMP', 'MMP'].contains(v1.toUpperCase())) {
eval += 'mmp';
} else if (['MP', 'CURRENT MP'].contains(v1.toUpperCase())) {
eval += 'mp';
} else if (['ATK', 'STR'].contains(v1.toUpperCase())) {
eval += 'atk';
} else if (['DEF'].contains(v1.toUpperCase())) {
eval += 'def';
} else if (['MAT', 'INT', 'SPI'].contains(v1.toUpperCase())) {
eval += 'mat';
} else if (['MDF', 'RES'].contains(v1.toUpperCase())) {
eval += 'mdf';
} else if (['AGI', 'SPD'].contains(v1.toUpperCase())) {
eval += 'agi';
} else if (['LUK'].contains(v1.toUpperCase())) {
eval += 'luk';
} else {
return false;
}
eval += ' ' + v2;
return this.checkCounterEval(eval, skill, subject, target);
};
BattleManager.checkCounterDefender = function (v1, v2, skill, subject, target) {
var eval = 'target.';
if (['LEVEL', 'LV', 'LVL'].contains(v1.toUpperCase())) {
eval += 'level';
} else if (['MAX HP', 'MAXHP', 'MHP'].contains(v1.toUpperCase())) {
eval += 'mhp';
} else if (['HP', 'CURRENT HP'].contains(v1.toUpperCase())) {
eval += 'hp';
} else if (['MAX MP', 'MAXMP', 'MMP'].contains(v1.toUpperCase())) {
eval += 'mmp';
} else if (['MP', 'CURRENT MP'].contains(v1.toUpperCase())) {
eval += 'mp';
} else if (['ATK', 'STR'].contains(v1.toUpperCase())) {
eval += 'atk';
} else if (['DEF'].contains(v1.toUpperCase())) {
eval += 'def';
} else if (['MAT', 'INT', 'SPI'].contains(v1.toUpperCase())) {
eval += 'mat';
} else if (['MDF', 'RES'].contains(v1.toUpperCase())) {
eval += 'mdf';
} else if (['AGI', 'SPD'].contains(v1.toUpperCase())) {
eval += 'agi';
} else if (['LUK'].contains(v1.toUpperCase())) {
eval += 'luk';
} else {
return false;
}
eval += ' ' + v2;
return this.checkCounterEval(eval, skill, subject, target);
};
BattleManager.evadeAndCounter = function (subject, target) {
if (this._counterSkill === undefined) return false;
if (this._counterSkill === null) return false;
if (target.forceHitCounter()) return false;
if (target.forceEvadeCounter()) return true;
return this._counterSkill.evadeCounter;
};
BattleManager.isValidCounterAction = function (target) {
if (this._counterQueue.length <= 0) return true;
return this._counterQueue[0].subject() !== target;
};
BattleManager.addCounterQueue = function (subject, target) {
if (!target.canCounter()) return;
if (!this.isValidCounterAction(target)) return;
var action = new Game_Action(target);
action.setSkill(this._counterSkill.id);
action.setCounter();
if (action.isForOpponent()) {
action.setTarget(subject.index());
} else {
action.setTarget(target.index());
}
this._counterQueue = this._counterQueue || [];
this._counterQueue.push(action);
this._counterOriginalSubject = this._counterOriginalSubject || subject;
this._counterOriginalAction = this._counterOriginalAction || this._action;
};
Yanfly.Counter.BattleManager_createFinishActions =
BattleManager.createFinishActions;
BattleManager.createFinishActions = function () {
Yanfly.Counter.BattleManager_createFinishActions.call(this);
this._actionList.push(['START COUNTER PHASE']);
};
Yanfly.Counter.BattleManager_processActionSequence =
BattleManager.processActionSequence;
BattleManager.processActionSequence = function (actionName, actionArgs) {
// START COUNTER PHASE
if (actionName === 'START COUNTER PHASE') {
return this.actionStartCounterPhase();
}
return Yanfly.Counter.BattleManager_processActionSequence.call(this,
actionName, actionArgs);
};
BattleManager.isMaxCounterQueue = function () {
return this._counterSequence > Yanfly.Param.CounterMaxQueue;
};
BattleManager.actionStartCounterPhase = function () {
this._counterQueue = this._counterQueue || [];
var action = this._counterQueue.shift();
if (this.isMaxCounterQueue() || !action) {
this.actionEndCounterPhase();
} else if (action && action.subject().isDead()) {
this.actionStartCounterPhase();
} else {
this.actionPerformCounterPhase(action);
}
this._counterQueue = this._counterQueue || [];
};
BattleManager.actionEndCounterPhase = function () {
this._countering = false;
if (this._counterOriginalSubject) {
this._subject = this._counterOriginalSubject;
this._action = this._counterOriginalAction;
if (this.isSetCounterOriginal()) {
this._subject.setCounterAction(this._action);
}
}
this._counterOriginalSubject = undefined;
this._counterOriginalAction = undefined;
this._counterSequence = 0;
this._counterQueue = [];
};
BattleManager.isSetCounterOriginal = function () {
if (this.isDTB()) return false;
return true;
};
BattleManager.actionPerformCounterPhase = function (action) {
this._countering = true;
this._subject.removeCounterAction();
this._subject = action.subject();
this._action = action;
var subject = this._subject;
var targets = action.makeTargets();
this.setTargets(targets);
this._allTargets = targets.slice();
this._individualTargets = targets.slice();
this._phase = 'phaseChange';
this._phaseSteps = ['setup', 'whole', 'target', 'follow', 'finish'];
this._returnPhase = '';
this._actionList = [];
subject.useItem(this._action.item());
this._action.applyGlobal();
this._logWindow.startAction(this._subject, this._action, this._targets);
};
//=============================================================================
// Game_BattlerBase
//=============================================================================
Yanfly.Counter.Game_BattlerBase_updateStateActionStart =
Game_BattlerBase.prototype.updateStateActionStart;
Game_BattlerBase.prototype.updateStateActionStart = function () {
if (BattleManager.isCountering()) return;
Yanfly.Counter.Game_BattlerBase_updateStateActionStart.call(this);
};
//=============================================================================
// Game_Battler
//=============================================================================
Yanfly.Counter.Game_Battler_refresh = Game_Battler.prototype.refresh;
Game_Battler.prototype.refresh = function () {
this._counterTotalCache = undefined;
Yanfly.Counter.Game_Battler_refresh.call(this);
};
Game_Battler.prototype.counterSkills = function () {
if (this._counterSkills === undefined || this._counterSkills === []) {
return [];
}
var array = [];
var length = this._counterSkills.length;
for (var i = 0; i < length; ++i) {
var skillId = this._counterSkills[i];
var skill = $dataSkills[skillId];
array.push(skill);
}
return array;
};
Game_Battler.prototype.makeCounterSkills = function () {
this._counterSkills = [];
var length = this.states().length;
for (var i = 0; i < length; ++i) {
var obj = this.states()[i];
if (!obj) continue;
if (obj.counterSkills) {
Yanfly.Util.extend(this._counterSkills, obj.counterSkills);
}
this.extendCounterSkillsEval(obj);
}
};
Game_Battler.prototype.extendCounterSkillsEval = function (obj) {
if (!obj) return;
if (!obj.counterSkillsEval) return;
if (obj.counterSkillsEval === '') return;
var skills = [];
var a = this;
var user = this;
var subject = this;
var b = this;
var target = this;
var s = $gameSwitches._data;
var v = $gameVariables._data;
var code = obj.counterSkillsEval;
try {
eval(code);
} catch (e) {
Yanfly.Util.displayError(e, code, 'COUNTER SKILLS ERROR');
}
Yanfly.Util.extend(this._counterSkills, obj.counterSkills);
};
Yanfly.Counter.Game_Battler_onBattleStart =
Game_Battler.prototype.onBattleStart;
Game_Battler.prototype.onBattleStart = function () {
Yanfly.Counter.Game_Battler_onBattleStart.call(this);
this._counters = 0;
};
Yanfly.Counter.Game_Battler_onTurnStart = Game_Battler.prototype.onTurnStart;
Game_Battler.prototype.onTurnStart = function () {
Yanfly.Counter.Game_Battler_onTurnStart.call(this);
this._counters = 0;
};
Game_Battler.prototype.counterTotal = function () {
var value = Yanfly.Param.CounterTotal;
var length = this.states().length;
for (var i = 0; i < length; ++i) {
var obj = this.states()[i];
if (!obj) continue;
if (obj.counterTotal) value += obj.counterTotal;
value += this.getCounterTotalEval(obj);
}
return value;
};
Game_Battler.prototype.getCounterTotalEval = function (obj) {
if (!obj) return 0;
if (!obj.counterTotalEval) return 0;
if (obj.counterTotalEval === '') return 0;
var value = 0;
var a = this;
var user = this;
var subject = this;
var b = this;
var target = this;
var s = $gameSwitches._data;
var v = $gameVariables._data;
var code = obj.counterTotalEval;
try {
eval(code);
} catch (e) {
Yanfly.Util.displayError(e, code, 'COUNTER TOTAL ERROR');
}
return value;
};
Game_Battler.prototype.payCounter = function (value) {
value = value || 1;
this._counters += value;
};
Game_Battler.prototype.canCounter = function () {
if (!this.canMove()) return false;
return this.counterTotal() >= this._counters;
};
Game_Battler.prototype.targetCounterRate = function () {
var rate = 1;
var length = this.states().length;
for (var i = 0; i < length; ++i) {
var obj = this.states()[i];
if (!obj) continue;
rate *= obj.targetCounterRate;
}
return rate;
};
Game_Battler.prototype.targetCounterFlat = function () {
var value = 0;
var length = this.states().length;
for (var i = 0; i < length; ++i) {
var obj = this.states()[i];
if (!obj) continue;
value += obj.targetCounterFlat;
}
return value;
};
Game_Battler.prototype.targetCounterRateEval = function (rate, target, item) {
var length = this.states().length;
for (var i = 0; i < length; ++i) {
var obj = this.states()[i];
rate = this.getTargetCntRateEval(obj, rate, target, item);
}
return rate;
};
Game_Battler.prototype.getTargetCntRateEval = function (obj, rate, trg, item) {
if (!obj) return rate;
if (!obj.targetCounterRateEval) return rate;
if (obj.targetCounterRateEval === '') return rate;
var skill = item;
var a = this;
var user = this;
var subject = this;
var b = trg;
var target = trg;
var s = $gameSwitches._data;
var v = $gameVariables._data;
var code = obj.targetCounterRateEval;
try {
eval(code);
} catch (e) {
Yanfly.Util.displayError(e, code, 'TARGET COUNTER RATE ERROR');
}
return rate;
};
Game_Battler.prototype.forceEvadeCounter = function () {
var length = this.states().length;
for (var i = 0; i < length; ++i) {
var obj = this.states()[i];
if (!obj) continue;
if (obj.evadeCounter) return true;
}
return false;
};
Game_Battler.prototype.forceHitCounter = function () {
var length = this.states().length;
for (var i = 0; i < length; ++i) {
var obj = this.states()[i];
if (!obj) continue;
if (obj.hitCounter) return true;
}
return false;
};
Game_Battler.prototype.forceEvadePopup = function () {
this._result = new Game_ActionResult();
this._result.evaded = true;
this.startDamagePopup();
this.clearResult();
};
Game_Battler.prototype.setCounterAction = function (action) {
if (!this._originalPreCounterActions) {
this._originalPreCounterActions = JsonEx.makeDeepCopy(this._actions);
}
action.setCounter();
this.setAction(0, action);
};
Game_Battler.prototype.removeCounterAction = function () {
if (this._originalPreCounterActions) {
this._actions = JsonEx.makeDeepCopy(this._originalPreCounterActions);
}
this._originalPreCounterActions = undefined;
};
//=============================================================================
// Game_Actor
//=============================================================================
Game_Actor.prototype.makeCounterSkills = function () {
Game_Battler.prototype.makeCounterSkills.call(this);
var length = this.equips().length;
for (var i = 0; i < length; ++i) {
var obj = this.equips()[i];
if (!obj) continue;
if (obj.counterSkills) {
Yanfly.Util.extend(this._counterSkills, obj.counterSkills);
}
this.extendCounterSkillsEval(obj);
}
if (this.currentClass().counterSkills) {
obj = this.currentClass();
Yanfly.Util.extend(this._counterSkills, obj.counterSkills);
this.extendCounterSkillsEval(obj);
}
if (this.actor().counterSkills) {
obj = this.actor();
Yanfly.Util.extend(this._counterSkills, obj.counterSkills);
this.extendCounterSkillsEval(obj);
}
if (this._counterSkills.length <= 0) {
this._counterSkills.push(obj.defaultCounter);
}
};
Game_Actor.prototype.counterTotal = function () {
if (this._counterTotalCache !== undefined) return this._counterTotalCache;
var value = Game_Battler.prototype.counterTotal.call(this);
var length = this.equips().length;
for (var i = 0; i < length; ++i) {
var obj = this.equips()[i];
if (!obj) continue;
if (obj.counterTotal) value += obj.counterTotal;
value += this.getCounterTotalEval(obj);
}
value += this.currentClass().counterTotal;
value += this.getCounterTotalEval(this.currentClass());
value += this.actor().counterTotal;
value += this.getCounterTotalEval(this.actor());
this._counterTotalCache = value;
return this._counterTotalCache;
};
Game_Actor.prototype.targetCounterRate = function () {
var rate = Game_Battler.prototype.targetCounterRate.call(this);
var length = this.equips().length;
for (var i = 0; i < length; ++i) {
var obj = this.equips()[i];
if (!obj) continue;
rate *= obj.targetCounterRate;
}
rate *= this.currentClass().targetCounterRate;
rate *= this.actor().targetCounterRate;
return rate;
};
Game_Actor.prototype.targetCounterFlat = function () {
var value = Game_Battler.prototype.targetCounterFlat.call(this);
var length = this.equips().length;
for (var i = 0; i < length; ++i) {
var obj = this.equips()[i];
if (!obj) continue;
value += obj.targetCounterFlat;
}
value += this.currentClass().targetCounterFlat;
value += this.actor().targetCounterFlat;
return value;
};
Game_Actor.prototype.targetCounterRateEval = function (rate, target, item) {
var rate = Game_Battler.prototype.targetCounterRateEval.call(this, rate,
target, item);
var length = this.equips().length;
for (var i = 0; i < length; ++i) {
var obj = this.equips()[i];
rate = this.getTargetCntRateEval(obj, rate, target, item);
}
rate = this.getTargetCntRateEval(this.currentClass(), rate, target, item);
rate = this.getTargetCntRateEval(this.actor(), rate, target, item);
return rate;
};
Game_Actor.prototype.forceEvadeCounter = function () {
if (Game_Battler.prototype.forceEvadeCounter.call(this)) return true;
if (this.actor().evadeCounter) return true;
if (this.currentClass().evadeCounter) return true;
var length = this.equips().length;
for (var i = 0; i < length; ++i) {
var obj = this.equips()[i];
if (!obj) continue;
if (obj.evadeCounter) return true;
}
return false;
};
Game_Actor.prototype.forceHitCounter = function () {
if (Game_Battler.prototype.forceHitCounter.call(this)) return true;
if (this.actor().hitCounter) return true;
if (this.currentClass().hitCounter) return true;
var length = this.equips().length;
for (var i = 0; i < length; ++i) {
var obj = this.equips()[i];
if (!obj) continue;
if (obj.hitCounter) return true;
}
return false;
};
//=============================================================================
// Game_Enemy
//=============================================================================
Game_Enemy.prototype.makeCounterSkills = function () {
Game_Battler.prototype.makeCounterSkills.call(this);
if (this.enemy().counterSkills) {
obj = this.enemy();
Yanfly.Util.extend(this._counterSkills, obj.counterSkills);
this.extendCounterSkillsEval(obj);
}
if (this._counterSkills.length <= 0) {
this._counterSkills.push(obj.defaultCounter);
}
};
Game_Enemy.prototype.counterTotal = function () {
if (this._counterTotalCache !== undefined) return this._counterTotalCache;
var value = Game_Battler.prototype.counterTotal.call(this);
value += this.enemy().counterTotal;
value += this.getCounterTotalEval(this.enemy());
this._counterTotalCache = value;
return this._counterTotalCache;
};
Game_Enemy.prototype.targetCounterRate = function () {
var rate = Game_Battler.prototype.targetCounterRate.call(this);
rate *= this.enemy().targetCounterRate;
return rate;
};
Game_Enemy.prototype.targetCounterFlat = function () {
var value = Game_Battler.prototype.targetCounterFlat.call(this);
value += this.enemy().targetCounterFlat;
return value;
};
Game_Enemy.prototype.targetCounterRateEval = function (rate, target, item) {
var rate = Game_Battler.prototype.targetCounterRateEval.call(this, rate,
target, item);
rate = this.getTargetCntRateEval(this.enemy(), rate, target, item);
return rate;
};
Game_Enemy.prototype.forceEvadeCounter = function () {
if (Game_Battler.prototype.forceEvadeCounter.call(this)) return true;
if (this.enemy().evadeCounter) return true;
return false;
};
Game_Enemy.prototype.forceHitCounter = function () {
if (Game_Battler.prototype.forceHitCounter.call(this)) return true;
if (this.enemy().hitCounter) return true;
return false;
};
//=============================================================================
// Game_Action
//=============================================================================
Game_Action.prototype.itemCnt = function (target) {
if (this.item().cannotCounter) return 0;
if (!this.item().allyCounter) {
if (target.isActor() === this.subject().isActor()) return 0;
}
if (!target.canMove()) return 0;
if (!target.canCounter()) return 0;
var rate = target.cnt;
rate *= this.subject().targetCounterRate();
rate *= this.item().counterRate;
rate += this.subject().targetCounterFlat();
rate += this.item().counterMod;
rate = this.subject().targetCounterRateEval(rate, target, this.item());
rate = this.customCounterRateEval(rate, target);
return rate;
};
Game_Action.prototype.customCounterRateEval = function (rate, target) {
if (this.item().counterRateEval === '') return rate;
var item = this.item();
var skill = this.item();
var a = this.subject();
var user = this.subject();
var subject = this.subject();
var b = target;
var s = $gameSwitches._data;
var v = $gameVariables._data;
var code = this.item().counterRateEval;
try {
eval(code);
} catch (e) {
Yanfly.Util.displayError(e, code, 'COUNTER RATE ERROR');
}
return rate;
};
if (Imported.YEP_X_BattleSysCTB) {
Yanfly.Counter.Game_Action_rebalanceCTBSpeed =
Game_Action.prototype.rebalanceCTBSpeed;
Game_Action.prototype.rebalanceCTBSpeed = function (target) {
if (BattleManager.isCountering()) return;
Yanfly.Counter.Game_Action_rebalanceCTBSpeed.call(this, target);
};
}; // Imported.YEP_X_BattleSysCTB
Yanfly.Counter.Game_Action_clear = Game_Action.prototype.clear;
Game_Action.prototype.clear = function () {
Yanfly.Counter.Game_Action_clear.call(this);
this._isCounter = false;
this._isForceMiss = false;
};
Game_Action.prototype.setCounter = function () {
this._isCounter = true;
};
Game_Action.prototype.isCounter = function () {
return this._isCounter;
};
//=============================================================================
// Window_BattleLog
//=============================================================================
Yanfly.Counter.Window_BattleLog_displayIcon =
Window_BattleLog.prototype.displayIcon;
Window_BattleLog.prototype.displayIcon = function (item) {
if (BattleManager.isCountering()) return item.counterIcon;
return Yanfly.Counter.Window_BattleLog_displayIcon.call(this, item);
};
Yanfly.Counter.Window_BattleLog_displayText =
Window_BattleLog.prototype.displayText;
Window_BattleLog.prototype.displayText = function (item) {
if (BattleManager.isCountering()) return item.counterName;
return Yanfly.Counter.Window_BattleLog_displayText.call(this, item);
};
//=============================================================================
// Utilities
//=============================================================================
Yanfly.Util = Yanfly.Util || {};
Yanfly.Util.extend = function (mainArray, otherArray) {
otherArray.forEach(function (i) {
mainArray.push(i)
}, this);
}
Yanfly.Util.displayError = function (e, code, message) {
console.log(message);
console.log(code || 'NON-EXISTENT');
console.error(e);
if (Utils.isNwjs() && Utils.isOptionValid('test')) {
if (!require('nw.gui').window.isDevToolsOpen()) {
require('nw.gui').window.showDevTools();
}
}
};
//=============================================================================
// End of File
//=============================================================================
};