mind-luda/www/js/plugins/ConfusionTargetEx.js
2024-03-08 10:39:54 -06:00

474 lines
17 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//=============================================================================
// ConfusionTargetEx.js
//
// ----------------------------------------------------------------------------
// by ecf5DTTzl6h6lJj02
// 2020/12/04
// ----------------------------------------------------------------------------
// Copyright (C) 2020 ecf5DTTzl6h6lJj02
// This software is released under the MIT lisence.
// http://opensource.org/licenses/mit-license.php
//=============================================================================
/*:
* @plugindesc 混乱等のステート時に自分をターゲットに含めない
* @author ecf5DTTzl6h6lJj02
*
* @param SwitchId
* @text 機能を有効にするスイッチのID
* @type switch
* @default 1
* @desc 機能をONにするスイッチID。
* なしに設定すると常に有効。
*
* @param BehaviorOfRecoverAll
* @text 回復スキルを使用したときの対象
* @type select
* @option 通常
* @value 0
* @option パターン A
* @value 1
* @option パターン B
* @value 2
* @default 0
* @desc 回復をした時の対象
* 詳しくはプラグインヘルプで確認ください。
*
* @help
* このプラグインは単体でも動作は可能ですが、
* トリアコンタン様の混乱ステート拡張プラグイン(ConfusionExtend.js)
* https://raw.githubusercontent.com/triacontane/RPGMakerMV/master/ConfusionExtend.js
* との併用を前提に作成しています。
* このプラグイン単体で使用する場合、エネミーもアクターもスキルは使用しません。
* 攻撃できる場合は攻撃。攻撃できる対象が存在しない場合は防御になります。
*
* 混乱ステート拡張プラグインと併用する場合は、
* このプラグインを混乱ステート拡張プラグインの下(できれば真下)に配置してください。
*
* ステートの行動制約が 誰かを攻撃・味方を攻撃になっている場合、
* ターゲットから自分自身を除外するプラグインです。
* 全体攻撃のターゲットからも除外され、自身はダメージを受けません。
* 回復スキルの場合は、自分自身を対象から除外しないようにします。
* 混乱ステート拡張プラグインで パラメータ『味方対象スキルの対象』がON(true)になっているときは、
* 全体回復をすると敵全体、及び、自分自身が回復します。
*
* プラグインパラメータ『機能を有効にするスイッチのID』で指定したスイッチがONの時のみ有効になるように設定してあります。
* このパラメータを なし に設定した場合は常に有効になります。
*
* 〇プラグインパラメータ『回復スキルを使用したときの対象』について
* このパラメータで、回復スキルを使用したときのターゲット設定を変更します。
* 混乱ステート拡張プラグインの『味方対象スキルの対象』の状態によって挙動が変化します。
* ・通常
* 『味方対象スキルの対象』がOFF(false)の時:
*  このプラグインの通常通りの設定でターゲットを設定します。
*
* 『味方対象スキルの対象』がON(true)の時:
*  単体回復の場合は、敵と自分自身でランダムに対象を決定。
* 全体回復の場合は、敵全体 + 自分自身が対象になります。
*
* ・パターン A
* 『味方対象スキルの対象がOFF(false)の時:
*  自分自身のみ対象にするようになります。
*
* 『味方対象スキルの対象』がON(true)の時:
*  単体回復の場合は、自分自身のみを対象にします。
*  全体回復の場合は、敵全体 + 自分自身が対象になります。
*
* ・パターン B
* 『味方対象スキルの対象』がOFF(false)の時:
*  自分自身のみ対象にするようになります。
*
* 『味方対象スキルの対象』がON(true)の時:
*  単体回復の場合は、敵の中からランダムに対象を決定。
* 全体回復の場合は、敵全体を対象にします。
*  (自分自身は対象にならないということです)
*
* プラグインコマンドはありません。
*
*/
(() => {
"use strict";
//混乱ステート拡張プラグインが有効かのチェックフラグ
const isActiveConfusionExtend = $plugins.some(
(plugin) => plugin.name === "ConfusionExtend" && plugin.status
);
//プラグインパラメータの取得
const TargetExValidSwitchId = Number(
PluginManager.parameters("ConfusionTargetEx")["SwitchId"]
);
const BehaviorOfRecoverAll = Number(
PluginManager.parameters("ConfusionTargetEx")["BehaviorOfRecoverAll"]
);
//狙われ率設定の拡張版
Game_Unit.prototype.tgrSumEx = function (candidacies) {
return candidacies.reduce((r, candidacy) => r + candidacy.tgr, 0);
};
//対象から自身を排除する
Game_Unit.prototype.randomTargetWithoutMe = function (subject) {
var candidacies = this.aliveMembers().filter(
(member) => member !== subject
);
var tgrRand = Math.random() * this.tgrSumEx(candidacies);
var target = null;
candidacies.forEach(function (candidacy) {
tgrRand -= candidacy.tgr;
if (tgrRand <= 0 && !target) {
target = candidacy;
}
});
return target;
};
// 対象に自身も入れる
Game_Unit.prototype.randomTargetWithMe = function (subject) {
var candidacies = this.aliveMembers();
candidacies.push(subject);
var tgrRand = Math.random() * this.tgrSumEx(candidacies);
var target = null;
candidacies.forEach(function (candidacy) {
tgrRand -= candidacy.tgr;
if (tgrRand <= 0 && !target) {
target = candidacy;
}
});
return target;
};
if (isActiveConfusionExtend) {
// 混乱ステート拡張プラグインが導入されているとき
// console.log("ConfusionExtend is Active")
var metaTagPrefix = "CE";
var getArgNumber = function (arg, min, max) {
if (arguments.length < 2) min = -Infinity;
if (arguments.length < 3) max = Infinity;
return (parseInt(convertEscapeCharacters(arg), 10) || 0).clamp(min, max);
};
var getMetaValue = function (object, name) {
var metaTagName = metaTagPrefix + (name ? name : "");
return object.meta.hasOwnProperty(metaTagName)
? object.meta[metaTagName]
: undefined;
};
var getMetaValues = function (object, names) {
if (!Array.isArray(names)) return getMetaValue(object, names);
for (var i = 0, n = names.length; i < n; i++) {
var value = getMetaValue(object, names[i]);
if (value !== undefined) return value;
}
return undefined;
};
Game_Action.prototype.setConfusionSpareSkill = function () {
var state = this.getRestrictState();
var value = getMetaValues(state, ["予備スキル", "SpareSkill"]);
if (value) {
var skillId = getArgNumber(value, 1);
if (this.subject().canUse($dataSkills[skillId])) {
this.setSkill(skillId);
} else if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId && $gameSwitches.value(TargetExValidSwitchId))
) {
//予備スキルも使用できない
if (this.subject().confusionLevel() <= 2) {
// 敵を攻撃できる行動制約
this.setAttack();
} else if (this.subject().friendsUnit().aliveMembers().length > 1) {
// 味方が自分のほかに存在する
this.setAttack();
} else {
// console.log(this.subject().name(), ":", "予備スキルも含め、使用できるスキルがないので防御");
this.setGuard();
}
}
} else if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId && $gameSwitches.value(TargetExValidSwitchId))
) {
//予備スキルの指定がない場合
if (this.subject().confusionLevel() <= 2) {
// 敵を攻撃できる行動制約
this.setAttack();
} else if (this.subject().friendsUnit().aliveMembers().length > 1) {
// 味方が自分のほかに存在する
this.setAttack();
} else {
// console.log(this.subject().name(), ":", "使えるスキルがなく、予備スキルの指定もないので防御");
this.setGuard();
}
}
};
//使用効果に回復タブの効果、ステート解除、能力強化、弱体解除の効果があるかチェックする関数
Game_Action.prototype.isRecoverEffect = function () {
return (
this.item().damage.type === 0 &&
this.item().effects.some((effect) =>
[11, 12, 13, 22, 31, 34].contains(effect.code)
)
);
};
//回復魔法を使うときは自身もターゲットに含めるように変更
Game_Action.prototype.targetsForOpponentsWithMe = function () {
var targets = [];
var unit = this.opponentsUnit();
if (this.isForRandom()) {
for (var i = 0; i < this.numTargets(); i++) {
targets.push(unit.randomTarget());
}
} else if (this.isForOne()) {
if (this._targetIndex < 0) {
if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitches.value(TargetExValidSwitchId) &&
(this.isHpRecover() ||
this.isMprecover() ||
this.isRecoverEffect()) &&
BehaviorOfRecoverAll < 2)
) {
targets.push(unit.randomTargetWithMe(this.subject()));
} else {
targets.push(unit.randomTarget());
}
} else {
targets.push(unit.smoothTarget(this._targetIndex));
}
} else {
targets = unit.aliveMembers();
if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitches.value(TargetExValidSwitchId) &&
(this.isHpRecover() ||
this.isMprecover() ||
this.isRecoverEffect()) &&
BehaviorOfRecoverAll < 2)
) {
targets.push(this.subject());
}
}
return targets;
};
const CTEX_Game_Action_confusionTarget =
Game_Action.prototype.confusionTarget;
Game_Action.prototype.confusionTarget = function () {
if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId && $gameSwitches.value(TargetExValidSwitchId))
) {
return this.confusionSkillTarget();
}
return CTEX_Game_Action_confusionTarget.apply(this, arguments);
};
//敵ターゲットの決定法を変更
Game_Action.prototype.confusionSkillTarget = function () {
var state = this.getRestrictState();
var value = getMetaValues(state, ["ターゲット", "Target"]);
if (value) {
var index = getArgNumber(value, -1);
this._targetIndex =
index === -1 ? this.subject().getLastTargetIndex() : index;
}
if (this.isForUser()) {
return this.subject();
}
return this.isConfusionSkillTargetForFriend()
? this.targetsForConfusionFriends()
: this.targetsForOpponentsWithMe();
};
Game_Action.prototype.targetsForConfusionFriends = function () {
if (this.isForRandom()) {
var targets = [];
var unit = this.friendsUnit();
for (var i = 0; i < this.numTargets(); i++) {
if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitches.value(TargetExValidSwitchId))
) {
targets.push(unit.randomTargetWithoutMe(this.subject()));
} else {
targets.push(unit.randomTarget());
}
}
return targets;
} else {
return this.targetsForFriends();
}
};
Game_Action.prototype.targetsForFriends = function () {
var targets = [];
var unit = this.friendsUnit();
if (this.isForUser()) {
return [this.subject()];
} else if (this.isForDeadFriend()) {
if (this.isForOne()) {
targets.push(unit.smoothDeadTarget(this._targetIndex));
} else {
targets = unit.deadMembers();
}
} else if (this.isForOne()) {
if (this._targetIndex < 0) {
if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitches.value(TargetExValidSwitchId))
) {
if (
this.isHpRecover() ||
this.isMpRecover() ||
this.isRecoverEffect()
) {
if (0 < BehaviorOfRecoverAll) {
targets = [this.subject()];
} else {
targets.push(unit.randomTarget());
}
} else {
targets.push(unit.randomTargetWithoutMe(this.subject()));
}
} else {
targets.push(unit.randomTarget());
}
} else {
targets.push(unit.smoothTarget(this._targetIndex));
}
} else {
targets = unit.aliveMembers();
if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId && $gameSwitches.value(TargetExValidSwitchId))
) {
if (
this.isHpRecover() ||
this.isMpRecover() ||
this.isRecoverEffect()
) {
if (0 < BehaviorOfRecoverAll) {
targets = [this.subject()];
}
} else {
targets = targets.filter((target) => target !== this.subject());
}
}
}
return targets;
};
Game_BattlerBase.prototype.isAnyTargetWithoutSelf = function (skill) {
if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId && !$gameSwitches.value(TargetExValidSwitchId))
) {
return true;
}
if (!this.isConfused()) {
// 混乱していない
return true;
}
if (this.confusionLevel() <= 2) {
// 敵を攻撃できる行動制約
return true;
}
if ([7, 8, 9, 10, 11].contains(skill.scope)) {
// 味方が対象のスキル
return true;
}
var unit = this.isActor() ? $gameParty : $gameTroop;
return unit.aliveMembers().length > 1;
};
Game_BattlerBase.prototype.meetsSkillConditions = function (skill) {
return (
this.meetsUsableItemConditions(skill) &&
this.isAnyTargetWithoutSelf(skill) &&
this.isSkillWtypeOk(skill) &&
this.canPaySkillCost(skill) &&
!this.isSkillSealed(skill.id) &&
!this.isSkillTypeSealed(skill.stypeId)
);
};
Game_Action.prototype.isConfusionSkillTargetForFriend = function () {
// console.log("攻撃対象のチェック");
switch (this.subject().confusionLevel()) {
case 1:
return this.isForFriend();
case 2:
if (
!TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitches.value(TargetExValidSwitchId) &&
this.isForOpponent() &&
this.subject().friendsUnit().aliveMembers().length < 2)
) {
// console.log(this.subject().name(), ":", "味方が自分以外いないので、強制的に敵を攻撃");
return false;
}
return Math.randomInt(2) === 0;
case 3:
return !this.isConfusionSkillTargetReverse();
}
return false;
};
} else {
Game_Action.prototype.setConfusion = function () {
// console.log(this.subject().friendsUnit().aliveMembers().length);
if (
(!TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitch.value(TargetExValidSwitchId))) &&
this.subject().confusionLevel() === 3 &&
this.subject().friendsUnit().aliveMembers().length < 2
) {
// console.log(this.subject().name(), ":", "攻撃対象がいないので防御");
this.setGuard();
} else {
this.setAttack();
}
};
Game_Action.prototype.confusionTarget = function () {
switch (this.subject().confusionLevel()) {
case 1:
return this.opponentsUnit().randomTarget();
case 2:
if (
((!TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitches.value(TargetExValidSwitchId))) &&
this.subject().friendsUnit().aliveMembers().length < 2) || // 味方が自分しかいない
Math.randomInt(2) === 0
) {
// もしくは抽選で敵への攻撃が選ばれた
return this.opponentsUnit().randomTarget();
}
return !TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitches.value(TargetExValidSwitchId))
? this.friendsUnit().randomTargetWithoutMe(this.subject())
: this.friendUnit().randomTarget();
default:
return !TargetExValidSwitchId ||
(TargetExValidSwitchId &&
$gameSwitches.value(TargetExValidSwitchId))
? this.friendsUnit().randomTargetWithoutMe(this.subject())
: this.friendUnit().randomTarget();
}
};
}
})();