//-----------------------------------------------------------------------------
// Game_Action
//
// The game object class for a battle action.
/**
* The game object class for a battle action.
*
* @class
*/
function Game_Action() {
this.initialize(...arguments);
}
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_RECOVER_HP = 11;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_RECOVER_MP = 12;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_GAIN_TP = 13;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_ADD_STATE = 21;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_REMOVE_STATE = 22;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_ADD_BUFF = 31;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_ADD_DEBUFF = 32;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_REMOVE_BUFF = 33;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_REMOVE_DEBUFF = 34;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_SPECIAL = 41;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_GROW = 42;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_LEARN_SKILL = 43;
/** @constant
@type {number}
@default
*/
Game_Action.EFFECT_COMMON_EVENT = 44;
/** @constant
@type {number}
@default
*/
Game_Action.SPECIAL_EFFECT_ESCAPE = 0;
/** @constant
@type {number}
@default
*/
Game_Action.HITTYPE_CERTAIN = 0;
/** @constant
@type {number}
@default
*/
Game_Action.HITTYPE_PHYSICAL = 1;
/** @constant
@type {number}
@default
*/
Game_Action.HITTYPE_MAGICAL = 2;
/**
* Initialize the action
*
* @param {Game_Battler} subject - The subject of the action
* @param {boolean} [forcing=false] - If the action is forcing
*/
Game_Action.prototype.initialize = function(subject, forcing) {
this._subjectActorId = 0;
this._subjectEnemyIndex = -1;
this._forcing = forcing || false;
this.setSubject(subject);
this.clear();
};
/**
* Clears the action
*/
Game_Action.prototype.clear = function() {
this._item = new Game_Item();
this._targetIndex = -1;
};
/**
* Set the subject of the action
*
* @param {Game_Battler} subject - The new subject
*/
Game_Action.prototype.setSubject = function(subject) {
if (subject.isActor()) {
this._subjectActorId = subject.actorId();
this._subjectEnemyIndex = -1;
} else {
this._subjectEnemyIndex = subject.index();
this._subjectActorId = 0;
}
};
/**
* Get the subject of the action
*
* @return {Game_Battler} The subject
*/
Game_Action.prototype.subject = function() {
if (this._subjectActorId > 0) {
return $gameActors.actor(this._subjectActorId);
} else {
return $gameTroop.members()[this._subjectEnemyIndex];
}
};
/**
* Get the friendly unit of the action
*
* @return {Game_Unit} The subject's friendly unit
*/
Game_Action.prototype.friendsUnit = function() {
return this.subject().friendsUnit();
};
/**
* Get the opponent unit of the action
*
* @return {Game_Unit} The subject's opponent unit
*/
Game_Action.prototype.opponentsUnit = function() {
return this.subject().opponentsUnit();
};
/**
* Set an enemy action
*
* @param {Object} The enemy action
*/
Game_Action.prototype.setEnemyAction = function(action) {
if (action) {
this.setSkill(action.skillId);
} else {
this.clear();
}
};
/**
* Set an attack action
*/
Game_Action.prototype.setAttack = function() {
this.setSkill(this.subject().attackSkillId());
};
/**
* Set a guard action
*/
Game_Action.prototype.setGuard = function() {
this.setSkill(this.subject().guardSkillId());
};
/**
* Set a skill action
*
* @param {number} skillId - The set skill's id
*/
Game_Action.prototype.setSkill = function(skillId) {
this._item.setObject($dataSkills[skillId]);
};
/**
* Set an item action
*
* @param {number} itemId - The set item's id
*/
Game_Action.prototype.setItem = function(itemId) {
this._item.setObject($dataItems[itemId]);
};
/**
* Set an item action
*
* @param {Object} object - The item object to set
*/
Game_Action.prototype.setItemObject = function(object) {
this._item.setObject(object);
};
/**
* Set the target index
*
* @param {number} targetIndex - The target index
*/
Game_Action.prototype.setTarget = function(targetIndex) {
this._targetIndex = targetIndex;
};
/**
* Get the item of the action
*
* @return {Object} The item data object
*/
Game_Action.prototype.item = function() {
return this._item.object();
};
/**
* Check if the action item is a skill
*
* @return {boolean} True if skill
*/
Game_Action.prototype.isSkill = function() {
return this._item.isSkill();
};
/**
* Check if the action item is an item
*
* @return {boolean} True if item
*/
Game_Action.prototype.isItem = function() {
return this._item.isItem();
};
/**
* Get amount of repeats
*
* @return {number} Number of repeats
*/
Game_Action.prototype.numRepeats = function() {
let repeats = this.item().repeats;
if (this.isAttack()) {
repeats += this.subject().attackTimesAdd();
}
return Math.floor(repeats);
};
/**
* Check the item's scope
*
* @param {Array} list - The list to check scope for
* @return {boolean} True if scope is included in the list
*/
Game_Action.prototype.checkItemScope = function(list) {
return list.includes(this.item().scope);
};
/**
* Check if the action is for opponent
*
* @return {boolean} True if scope includes opponents
*/
Game_Action.prototype.isForOpponent = function() {
return this.checkItemScope([1, 2, 3, 4, 5, 6, 14]);
};
/**
* Check if the action is for allies
*
* @return {boolean} True if scope includes allies
*/
Game_Action.prototype.isForFriend = function() {
return this.checkItemScope([7, 8, 9, 10, 11, 12, 13, 14]);
};
/**
* Check if the action is for everyone
*
* @return {boolean} True if scope includes everyone
*/
Game_Action.prototype.isForEveryone = function() {
return this.checkItemScope([14]);
};
/**
* Check if the action is for alive allies
*
* @return {boolean} True if scope includes alive allies
*/
Game_Action.prototype.isForAliveFriend = function() {
return this.checkItemScope([7, 8, 11, 14]);
};
/**
* Check if the action is for dead allies
*
* @return {boolean} True if scope includes only dead allies
*/
Game_Action.prototype.isForDeadFriend = function() {
return this.checkItemScope([9, 10]);
};
/**
* Check if the action is for the user
*
* @return {boolean} True if scope includes only the user
*/
Game_Action.prototype.isForUser = function() {
return this.checkItemScope([11]);
};
/**
* Check if the action is for one target
*
* @return {boolean} True if scope includes only one target
*/
Game_Action.prototype.isForOne = function() {
return this.checkItemScope([1, 3, 7, 9, 11, 12]);
};
/**
* Check if the action is for a random unit
*
* @return {boolean} True if scope includes random units
*/
Game_Action.prototype.isForRandom = function() {
return this.checkItemScope([3, 4, 5, 6]);
};
/**
* Check if the action is for all
*
* @return {boolean} True if scope includes all
*/
Game_Action.prototype.isForAll = function() {
return this.checkItemScope([2, 8, 10, 13, 14]);
};
/**
* Check if the action is needs to select a target
*
* @return {boolean} True if scope requires target selection
*/
Game_Action.prototype.needsSelection = function() {
return this.checkItemScope([1, 7, 9, 12]);
};
/**
* Get number of targets when random
*
* @return {number} Amount of random targets
*/
Game_Action.prototype.numTargets = function() {
return this.isForRandom() ? this.item().scope - 2 : 0;
};
/**
* Check if the action's damage type matches the list of damage types
*
* @param {Array} list - List of damage types to check
* @return {boolean} True if damage type included in given list
*/
Game_Action.prototype.checkDamageType = function(list) {
return list.includes(this.item().damage.type);
};
/**
* Check if the action's damage type is an hp type
*
* @return {boolean} True if damage type is hp effect
*/
Game_Action.prototype.isHpEffect = function() {
return this.checkDamageType([1, 3, 5]);
};
/**
* Check if the action's damage type is an mp type
*
* @return {boolean} True if damage type is mp effect
*/
Game_Action.prototype.isMpEffect = function() {
return this.checkDamageType([2, 4, 6]);
};
/**
* Check if the action's damage type is a damage type
*
* @return {boolean} True if damage type is damage effect
*/
Game_Action.prototype.isDamage = function() {
return this.checkDamageType([1, 2]);
};
/**
* Check if the action's damage type is a recover type
*
* @return {boolean} True if damage type is recover effect
*/
Game_Action.prototype.isRecover = function() {
return this.checkDamageType([3, 4]);
};
/**
* Check if the action's damage type is a drain type
*
* @return {boolean} True if damage type is drain effect
*/
Game_Action.prototype.isDrain = function() {
return this.checkDamageType([5, 6]);
};
/**
* Check if the action's damage type is an hp recover type
*
* @return {boolean} True if damage type is hp recover effect
*/
Game_Action.prototype.isHpRecover = function() {
return this.checkDamageType([3]);
};
/**
* Check if the action's damage type is an mp recover type
*
* @return {boolean} True if damage type is mp recover effect
*/
Game_Action.prototype.isMpRecover = function() {
return this.checkDamageType([4]);
};
/**
* Check if the action is a certain hit
*
* @return {boolean} True if certain hit
*/
Game_Action.prototype.isCertainHit = function() {
return this.item().hitType === Game_Action.HITTYPE_CERTAIN;
};
/**
* Check if the action is physical
*
* @return {boolean} True if physical
*/
Game_Action.prototype.isPhysical = function() {
return this.item().hitType === Game_Action.HITTYPE_PHYSICAL;
};
/**
* Check if the action is magical
*
* @return {boolean} True if magical
*/
Game_Action.prototype.isMagical = function() {
return this.item().hitType === Game_Action.HITTYPE_MAGICAL;
};
/**
* Check if the action is an attack
*
* @return {boolean} True if attack
*/
Game_Action.prototype.isAttack = function() {
return this.item() === $dataSkills[this.subject().attackSkillId()];
};
/**
* Check if the action is a guard
*
* @return {boolean} True if guard
*/
Game_Action.prototype.isGuard = function() {
return this.item() === $dataSkills[this.subject().guardSkillId()];
};
/**
* Check if the action is a magic skill
*
* @return {boolean} True if magic skill
*/
Game_Action.prototype.isMagicSkill = function() {
if (this.isSkill()) {
return $dataSystem.magicSkills.includes(this.item().stypeId);
} else {
return false;
}
};
/**
* Choose a random target
*/
Game_Action.prototype.decideRandomTarget = function() {
let target;
if (this.isForDeadFriend()) {
target = this.friendsUnit().randomDeadTarget();
} else if (this.isForFriend()) {
target = this.friendsUnit().randomTarget();
} else {
target = this.opponentsUnit().randomTarget();
}
if (target) {
this._targetIndex = target.index();
} else {
this.clear();
}
};
/**
* Sets confusion action
*/
Game_Action.prototype.setConfusion = function() {
this.setAttack();
};
/**
* Prepares the action
*/
Game_Action.prototype.prepare = function() {
if (this.subject().isConfused() && !this._forcing) {
this.setConfusion();
}
};
/**
* Check if the action is valid
*
* @return {boolean} True if the action is valid
*/
Game_Action.prototype.isValid = function() {
return (this._forcing && this.item()) || this.subject().canUse(this.item());
};
/**
* Get the action speed
*
* @return {number} The action speed
*/
Game_Action.prototype.speed = function() {
const agi = this.subject().agi;
let speed = agi + Math.randomInt(Math.floor(5 + agi / 4));
if (this.item()) {
speed += this.item().speed;
}
if (this.isAttack()) {
speed += this.subject().attackSpeed();
}
return speed;
};
/**
* Make the targets of the action
*
* @return {Game_Battler[]} The array of targets
*/
Game_Action.prototype.makeTargets = function() {
const targets = [];
if (!this._forcing && this.subject().isConfused()) {
targets.push(this.confusionTarget());
} else if (this.isForEveryone()) {
targets.push(...this.targetsForEveryone());
} else if (this.isForOpponent()) {
targets.push(...this.targetsForOpponents());
} else if (this.isForFriend()) {
targets.push(...this.targetsForFriends());
}
return this.repeatTargets(targets);
};
/**
* Repeat the targets for the action if it repeats
*
* @param {Game_Battler[]} targets - The target array to repeat
* @return {Game_Battler[]} The array of targets
*/
Game_Action.prototype.repeatTargets = function(targets) {
const repeatedTargets = [];
const repeats = this.numRepeats();
for (const target of targets) {
if (target) {
for (let i = 0; i < repeats; i++) {
repeatedTargets.push(target);
}
}
}
return repeatedTargets;
};
/**
* Get the confusion target
*
* @return {Game_Battler} The confusion target
*/
Game_Action.prototype.confusionTarget = function() {
switch (this.subject().confusionLevel()) {
case 1:
return this.opponentsUnit().randomTarget();
case 2:
if (Math.randomInt(2) === 0) {
return this.opponentsUnit().randomTarget();
}
return this.friendsUnit().randomTarget();
default:
return this.friendsUnit().randomTarget();
}
};
/**
* Make the targets for everyone
*
* @return {Game_Battler[]} The array of targets for everyone
*/
Game_Action.prototype.targetsForEveryone = function() {
const opponentMembers = this.opponentsUnit().aliveMembers();
const friendMembers = this.friendsUnit().aliveMembers();
return opponentMembers.concat(friendMembers);
};
/**
* Make the targets for opponents
*
* @return {Game_Battler[]} The array of targets for opponents
*/
Game_Action.prototype.targetsForOpponents = function() {
const unit = this.opponentsUnit();
if (this.isForRandom()) {
return this.randomTargets(unit);
} else {
return this.targetsForAlive(unit);
}
};
/**
* Make the targets for allies
*
* @return {Game_Battler[]} The array of targets for allies
*/
Game_Action.prototype.targetsForFriends = function() {
const unit = this.friendsUnit();
if (this.isForUser()) {
return [this.subject()];
} else if (this.isForDeadFriend()) {
return this.targetsForDead(unit);
} else if (this.isForAliveFriend()) {
return this.targetsForAlive(unit);
} else {
return this.targetsForDeadAndAlive(unit);
}
};
/**
* Make the targets for random
*
* @param {Game_Unit} unit - The unit to look for random targets in
* @return {Game_Battler[]} The array of targets for random
*/
Game_Action.prototype.randomTargets = function(unit) {
const targets = [];
for (let i = 0; i < this.numTargets(); i++) {
targets.push(unit.randomTarget());
}
return targets;
};
/**
* Make the targets for dead
*
* @param {Game_Unit} unit - The unit to look for dead targets in
* @return {Game_Battler[]} The array of targets for dead
*/
Game_Action.prototype.targetsForDead = function(unit) {
if (this.isForOne()) {
return [unit.smoothDeadTarget(this._targetIndex)];
} else {
return unit.deadMembers();
}
};
/**
* Make the targets for alive
*
* @param {Game_Unit} unit - The unit to look for alive targets in
* @return {Game_Battler[]} The array of targets for alive
*/
Game_Action.prototype.targetsForAlive = function(unit) {
if (this.isForOne()) {
if (this._targetIndex < 0) {
return [unit.randomTarget()];
} else {
return [unit.smoothTarget(this._targetIndex)];
}
} else {
return unit.aliveMembers();
}
};
/**
* Make the targets for alive
*
* @param {Game_Unit} unit - The unit to look for dead and alive targets in
* @return {Game_Battler[]} The array of targets for dead and alive
*/
Game_Action.prototype.targetsForDeadAndAlive = function(unit) {
if (this.isForOne()) {
return [unit.members()[this._targetIndex]];
} else {
return unit.members();
}
};
/**
* Evaluate the action
*
* @return {number} The value of the action
*/
Game_Action.prototype.evaluate = function() {
let value = 0;
for (const target of this.itemTargetCandidates()) {
const targetValue = this.evaluateWithTarget(target);
if (this.isForAll()) {
value += targetValue;
} else if (targetValue > value) {
value = targetValue;
this._targetIndex = target.index();
}
}
value *= this.numRepeats();
if (value > 0) {
value += Math.random();
}
return value;
};
/**
* Get the target candidates
*
* @return {Game_Battler[]} The array of candidate targets
*/
Game_Action.prototype.itemTargetCandidates = function() {
if (!this.isValid()) {
return [];
} else if (this.isForOpponent()) {
return this.opponentsUnit().aliveMembers();
} else if (this.isForUser()) {
return [this.subject()];
} else if (this.isForDeadFriend()) {
return this.friendsUnit().deadMembers();
} else {
return this.friendsUnit().aliveMembers();
}
};
/**
* Evaluate the action with a target
*
* @param {Game_Battler} target - The target
* @return {number} The value of the action
*/
Game_Action.prototype.evaluateWithTarget = function(target) {
if (this.isHpEffect()) {
const value = this.makeDamageValue(target, false);
if (this.isForOpponent()) {
return value / Math.max(target.hp, 1);
} else {
const recovery = Math.min(-value, target.mhp - target.hp);
return recovery / target.mhp;
}
}
};
/**
* Test applying the action to the target
*
* @param {Game_Battler} target - The target
* @return {boolean} True if the action has an effect
*/
Game_Action.prototype.testApply = function(target) {
return (
this.testLifeAndDeath(target) &&
($gameParty.inBattle() ||
(this.isHpRecover() && target.hp < target.mhp) ||
(this.isMpRecover() && target.mp < target.mmp) ||
this.hasItemAnyValidEffects(target))
);
};
/**
* Test applying the action to the target for life and death states
*
* @param {Game_Battler} target - The target
* @return {boolean} True if the action has an effect that works on the target's alive status
*/
Game_Action.prototype.testLifeAndDeath = function(target) {
if (this.isForOpponent() || this.isForAliveFriend()) {
return target.isAlive();
} else if (this.isForDeadFriend()) {
return target.isDead();
} else {
return true;
}
};
/**
* Test applying the action to the target for valid effects
*
* @param {Game_Battler} target - The target
* @return {boolean} True if the action has an effect
*/
Game_Action.prototype.hasItemAnyValidEffects = function(target) {
return this.item().effects.some(effect =>
this.testItemEffect(target, effect)
);
};
/**
* Test the item effect on the target
*
* @param {Game_Battler} target - The target
* @return {boolean} True if the action has an effect
*/
Game_Action.prototype.testItemEffect = function(target, effect) {
switch (effect.code) {
case Game_Action.EFFECT_RECOVER_HP:
return (
target.hp < target.mhp || effect.value1 < 0 || effect.value2 < 0
);
case Game_Action.EFFECT_RECOVER_MP:
return (
target.mp < target.mmp || effect.value1 < 0 || effect.value2 < 0
);
case Game_Action.EFFECT_ADD_STATE:
return !target.isStateAffected(effect.dataId);
case Game_Action.EFFECT_REMOVE_STATE:
return target.isStateAffected(effect.dataId);
case Game_Action.EFFECT_ADD_BUFF:
return !target.isMaxBuffAffected(effect.dataId);
case Game_Action.EFFECT_ADD_DEBUFF:
return !target.isMaxDebuffAffected(effect.dataId);
case Game_Action.EFFECT_REMOVE_BUFF:
return target.isBuffAffected(effect.dataId);
case Game_Action.EFFECT_REMOVE_DEBUFF:
return target.isDebuffAffected(effect.dataId);
case Game_Action.EFFECT_LEARN_SKILL:
return target.isActor() && !target.isLearnedSkill(effect.dataId);
default:
return true;
}
};
/**
* Get the item cnt (counter attack rate)
*
* @param {Game_Battler} target - The target
* @return {number} The counter attack rate
*/
Game_Action.prototype.itemCnt = function(target) {
if (this.isPhysical() && target.canMove()) {
return target.cnt;
} else {
return 0;
}
};
/**
* Get the item mrf (magic reflection rate)
*
* @param {Game_Battler} target - The target
* @return {number} The magic reflection rate
*/
Game_Action.prototype.itemMrf = function(target) {
if (this.isMagical()) {
return target.mrf;
} else {
return 0;
}
};
/**
* Get the item hit rate
*
* @return {number} The hit rate
*/
Game_Action.prototype.itemHit = function(/*target*/) {
const successRate = this.item().successRate;
if (this.isPhysical()) {
return successRate * 0.01 * this.subject().hit;
} else {
return successRate * 0.01;
}
};
/**
* Get the item evade rate
*
* @param {Game_Battler} target - The target
* @return {number} The evade rate
*/
Game_Action.prototype.itemEva = function(target) {
if (this.isPhysical()) {
return target.eva;
} else if (this.isMagical()) {
return target.mev;
} else {
return 0;
}
};
/**
* Get the item cri (critical rate)
*
* @param {Game_Battler} target - The target
* @return {number} The critical rate
*/
Game_Action.prototype.itemCri = function(target) {
return this.item().damage.critical
? this.subject().cri * (1 - target.cev)
: 0;
};
/**
* Apply the action to the target
*
* @param {Game_Battler} target - The target
*/
Game_Action.prototype.apply = function(target) {
const result = target.result();
this.subject().clearResult();
result.clear();
result.used = this.testApply(target);
result.missed = result.used && Math.random() >= this.itemHit(target);
result.evaded = !result.missed && Math.random() < this.itemEva(target);
result.physical = this.isPhysical();
result.drain = this.isDrain();
if (result.isHit()) {
if (this.item().damage.type > 0) {
result.critical = Math.random() < this.itemCri(target);
const value = this.makeDamageValue(target, result.critical);
this.executeDamage(target, value);
}
for (const effect of this.item().effects) {
this.applyItemEffect(target, effect);
}
this.applyItemUserEffect(target);
}
this.updateLastTarget(target);
};
/**
* Make the damage value
*
* @param {Game_Battler} target - The target
* @param {boolean} critical - If the effect is a critical
* @return {number} The damage value
*/
Game_Action.prototype.makeDamageValue = function(target, critical) {
const item = this.item();
const baseValue = this.evalDamageFormula(target);
let value = baseValue * this.calcElementRate(target);
if (this.isPhysical()) {
value *= target.pdr;
}
if (this.isMagical()) {
value *= target.mdr;
}
if (baseValue < 0) {
value *= target.rec;
}
if (critical) {
value = this.applyCritical(value);
}
value = this.applyVariance(value, item.damage.variance);
value = this.applyGuard(value, target);
value = Math.round(value);
return value;
};
/**
* eval the damage formula
*
* @param {Game_Battler} target - The target
* @return {number} The result value
*/
Game_Action.prototype.evalDamageFormula = function(target) {
try {
const item = this.item();
const a = this.subject(); // eslint-disable-line no-unused-vars
const b = target; // eslint-disable-line no-unused-vars
const v = $gameVariables._data; // eslint-disable-line no-unused-vars
const sign = [3, 4].includes(item.damage.type) ? -1 : 1;
const value = Math.max(eval(item.damage.formula), 0) * sign;
return isNaN(value) ? 0 : value;
} catch (e) {
return 0;
}
};
/**
* Calculate the element rate for the target
*
* @param {Game_Battler} target - The target
* @return {number} The element rate
*/
Game_Action.prototype.calcElementRate = function(target) {
if (this.item().damage.elementId < 0) {
return this.elementsMaxRate(target, this.subject().attackElements());
} else {
return target.elementRate(this.item().damage.elementId);
}
};
/**
* Get the maximum element rate effect
*
* @param {Game_Battler} target - The target
* @param {Array} elements - The list of elements
* @return {number} The max element rate
*/
Game_Action.prototype.elementsMaxRate = function(target, elements) {
if (elements.length > 0) {
const rates = elements.map(elementId => target.elementRate(elementId));
return Math.max(...rates);
} else {
return 1;
}
};
/**
* Apply the critical effect to the damage value
*
* @param {number} damage - The original damage value
* @return {number} The damage value after applying critical effect
*/
Game_Action.prototype.applyCritical = function(damage) {
return damage * 3;
};
/**
* Apply variance to the damage value
*
* @param {number} damage - The base damage value
* @param {number} variance - The variance value
* @return {number} The damage value after applying variance
*/
Game_Action.prototype.applyVariance = function(damage, variance) {
const amp = Math.floor(Math.max((Math.abs(damage) * variance) / 100, 0));
const v = Math.randomInt(amp + 1) + Math.randomInt(amp + 1) - amp;
return damage >= 0 ? damage + v : damage - v;
};
/**
* Apply guard effect to the damage value
*
* @param {number} damage - The base damage value
* @param {Game_Battler} target - The target
* @return {number} The damage value after applying guard effect
*/
Game_Action.prototype.applyGuard = function(damage, target) {
return damage / (damage > 0 && target.isGuard() ? 2 * target.grd : 1);
};
/**
* Execute damage on the target
*
* @param {Game_Battler} target - The target
* @param {number} value - The damage value
*/
Game_Action.prototype.executeDamage = function(target, value) {
const result = target.result();
if (value === 0) {
result.critical = false;
}
if (this.isHpEffect()) {
this.executeHpDamage(target, value);
}
if (this.isMpEffect()) {
this.executeMpDamage(target, value);
}
};
/**
* Execute hp damage on the target
*
* @param {Game_Battler} target - The target
* @param {number} value - The damage value
*/
Game_Action.prototype.executeHpDamage = function(target, value) {
if (this.isDrain()) {
value = Math.min(target.hp, value);
}
this.makeSuccess(target);
target.gainHp(-value);
if (value > 0) {
target.onDamage(value);
}
this.gainDrainedHp(value);
};
/**
* Execute mp damage on the target
*
* @param {Game_Battler} target - The target
* @param {number} value - The damage value
*/
Game_Action.prototype.executeMpDamage = function(target, value) {
if (!this.isMpRecover()) {
value = Math.min(target.mp, value);
}
if (value !== 0) {
this.makeSuccess(target);
}
target.gainMp(-value);
this.gainDrainedMp(value);
};
/**
* Gain drained hp
*
* @param {number} value - The drain value
*/
Game_Action.prototype.gainDrainedHp = function(value) {
if (this.isDrain()) {
let gainTarget = this.subject();
if (this._reflectionTarget) {
gainTarget = this._reflectionTarget;
}
gainTarget.gainHp(value);
}
};
/**
* Gain drained mp
*
* @param {number} value - The drain value
*/
Game_Action.prototype.gainDrainedMp = function(value) {
if (this.isDrain()) {
let gainTarget = this.subject();
if (this._reflectionTarget) {
gainTarget = this._reflectionTarget;
}
gainTarget.gainMp(value);
}
};
/**
* Apply item effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.applyItemEffect = function(target, effect) {
switch (effect.code) {
case Game_Action.EFFECT_RECOVER_HP:
this.itemEffectRecoverHp(target, effect);
break;
case Game_Action.EFFECT_RECOVER_MP:
this.itemEffectRecoverMp(target, effect);
break;
case Game_Action.EFFECT_GAIN_TP:
this.itemEffectGainTp(target, effect);
break;
case Game_Action.EFFECT_ADD_STATE:
this.itemEffectAddState(target, effect);
break;
case Game_Action.EFFECT_REMOVE_STATE:
this.itemEffectRemoveState(target, effect);
break;
case Game_Action.EFFECT_ADD_BUFF:
this.itemEffectAddBuff(target, effect);
break;
case Game_Action.EFFECT_ADD_DEBUFF:
this.itemEffectAddDebuff(target, effect);
break;
case Game_Action.EFFECT_REMOVE_BUFF:
this.itemEffectRemoveBuff(target, effect);
break;
case Game_Action.EFFECT_REMOVE_DEBUFF:
this.itemEffectRemoveDebuff(target, effect);
break;
case Game_Action.EFFECT_SPECIAL:
this.itemEffectSpecial(target, effect);
break;
case Game_Action.EFFECT_GROW:
this.itemEffectGrow(target, effect);
break;
case Game_Action.EFFECT_LEARN_SKILL:
this.itemEffectLearnSkill(target, effect);
break;
case Game_Action.EFFECT_COMMON_EVENT:
this.itemEffectCommonEvent(target, effect);
break;
}
};
/**
* Apply recover hp effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectRecoverHp = function(target, effect) {
let value = (target.mhp * effect.value1 + effect.value2) * target.rec;
if (this.isItem()) {
value *= this.subject().pha;
}
value = Math.floor(value);
if (value !== 0) {
target.gainHp(value);
this.makeSuccess(target);
}
};
/**
* Apply recover mp effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectRecoverMp = function(target, effect) {
let value = (target.mmp * effect.value1 + effect.value2) * target.rec;
if (this.isItem()) {
value *= this.subject().pha;
}
value = Math.floor(value);
if (value !== 0) {
target.gainMp(value);
this.makeSuccess(target);
}
};
/**
* Apply gain tp effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectGainTp = function(target, effect) {
let value = Math.floor(effect.value1);
if (value !== 0) {
target.gainTp(value);
this.makeSuccess(target);
}
};
/**
* Apply add state effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectAddState = function(target, effect) {
if (effect.dataId === 0) {
this.itemEffectAddAttackState(target, effect);
} else {
this.itemEffectAddNormalState(target, effect);
}
};
/**
* Apply add attack state effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectAddAttackState = function(target, effect) {
for (const stateId of this.subject().attackStates()) {
let chance = effect.value1;
chance *= target.stateRate(stateId);
chance *= this.subject().attackStatesRate(stateId);
chance *= this.lukEffectRate(target);
if (Math.random() < chance) {
target.addState(stateId);
this.makeSuccess(target);
}
}
};
/**
* Apply add normal state effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectAddNormalState = function(target, effect) {
let chance = effect.value1;
if (!this.isCertainHit()) {
chance *= target.stateRate(effect.dataId);
chance *= this.lukEffectRate(target);
}
if (Math.random() < chance) {
target.addState(effect.dataId);
this.makeSuccess(target);
}
};
/**
* Apply remove state effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectRemoveState = function(target, effect) {
let chance = effect.value1;
if (Math.random() < chance) {
target.removeState(effect.dataId);
this.makeSuccess(target);
}
};
/**
* Apply add buff effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectAddBuff = function(target, effect) {
target.addBuff(effect.dataId, effect.value1);
this.makeSuccess(target);
};
/**
* Apply add debuff effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectAddDebuff = function(target, effect) {
let chance = target.debuffRate(effect.dataId) * this.lukEffectRate(target);
if (Math.random() < chance) {
target.addDebuff(effect.dataId, effect.value1);
this.makeSuccess(target);
}
};
/**
* Apply remove buff effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectRemoveBuff = function(target, effect) {
if (target.isBuffAffected(effect.dataId)) {
target.removeBuff(effect.dataId);
this.makeSuccess(target);
}
};
/**
* Apply remove debuff effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectRemoveDebuff = function(target, effect) {
if (target.isDebuffAffected(effect.dataId)) {
target.removeBuff(effect.dataId);
this.makeSuccess(target);
}
};
/**
* Apply special effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectSpecial = function(target, effect) {
if (effect.dataId === Game_Action.SPECIAL_EFFECT_ESCAPE) {
target.escape();
this.makeSuccess(target);
}
};
/**
* Apply grow effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectGrow = function(target, effect) {
target.addParam(effect.dataId, Math.floor(effect.value1));
this.makeSuccess(target);
};
/**
* Apply learn skill effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectLearnSkill = function(target, effect) {
if (target.isActor()) {
target.learnSkill(effect.dataId);
this.makeSuccess(target);
}
};
/**
* Apply common event effects on the target
*
* @param {Game_Battler} target - The target
* @param {Object} effect - The item effect
*/
Game_Action.prototype.itemEffectCommonEvent = function(/*target, effect*/) {
//
};
/**
* Make the success status for the target
*
* @param {Game_Battler} target - The target
*/
Game_Action.prototype.makeSuccess = function(target) {
target.result().success = true;
};
/**
* Apply item user effects on the target (in this case, the subject)
*/
Game_Action.prototype.applyItemUserEffect = function(/*target*/) {
const value = Math.floor(this.item().tpGain * this.subject().tcr);
this.subject().gainSilentTp(value);
};
/**
* Get the luk effect rate
*
* @param {Game_Battler} target - The target
* @return {number} The luk effect rate
*/
Game_Action.prototype.lukEffectRate = function(target) {
return Math.max(1.0 + (this.subject().luk - target.luk) * 0.001, 0.0);
};
/**
* Apply global effects
*/
Game_Action.prototype.applyGlobal = function() {
for (const effect of this.item().effects) {
if (effect.code === Game_Action.EFFECT_COMMON_EVENT) {
$gameTemp.reserveCommonEvent(effect.dataId);
}
}
this.updateLastUsed();
this.updateLastSubject();
};
/**
* Update the last used skill or item id
*/
Game_Action.prototype.updateLastUsed = function() {
const item = this.item();
if (DataManager.isSkill(item)) {
$gameTemp.setLastUsedSkillId(item.id);
} else if (DataManager.isItem(item)) {
$gameTemp.setLastUsedItemId(item.id);
}
};
/**
* Update the last subject id
*/
Game_Action.prototype.updateLastSubject = function() {
const subject = this.subject();
if (subject.isActor()) {
$gameTemp.setLastSubjectActorId(subject.actorId());
} else {
$gameTemp.setLastSubjectEnemyIndex(subject.index() + 1);
}
};
/**
* Update the last target id
*/
Game_Action.prototype.updateLastTarget = function(target) {
if (target.isActor()) {
$gameTemp.setLastTargetActorId(target.actorId());
} else {
$gameTemp.setLastTargetEnemyIndex(target.index() + 1);
}
};