474 lines
17 KiB
JavaScript
474 lines
17 KiB
JavaScript
//=============================================================================
|
||
// 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();
|
||
}
|
||
};
|
||
}
|
||
})();
|