//============================================================================= // MPP_StateLevel.js //============================================================================= // Copyright (c) 2024 Mokusei Penguin // Released under the MIT license // http://opensource.org/licenses/mit-license.php //============================================================================= /*: * @target MZ * @plugindesc ステートを重ね掛け出来るようにします。 * @author 木星ペンギン * @url * * @help [version 1.0.0] * - 本プラグインはRPGツクールMZ用です。 * - Japanese help only. * - 不具合・競合・機能追加等の要望に対処できない場合があります。 * - これらに対応する場合、有償となります。 * * ▼ 仕様 * 〇 ステート重ね掛け * - ステートを重ね掛けした場合、そのステートが複数個付与されている状態と * なります。 * - 2回重ね掛けした場合、単純に効果が2倍になるとは限りません。 * (一部の乗算処理に関しては2倍になるように調整しています) * - 細かな仕様はツクール側の仕様や他プラグインの仕様に準じます。 * * 〇 他追加機能 * - ステートに重ねて表示される数値は重ね掛けした回数です。 * - ステートの下に表示されるゲージは残り効果時間です。 * - ステートを上書きした場合、効果時間が減らないように修正。 * * ================================ * Mail : wood_penguin@yahoo.co.jp (@は半角) * Blog : http://woodpenguin.blog.fc2.com/ * License : MIT license * */ 'use strict'; (() => { const pluginName = 'MPP_StateLevel'; // Plugin Parameters const parameters = PluginManager.parameters(pluginName); const __base = (obj, prop) => { if (obj.hasOwnProperty(prop)) { return obj[prop]; } else { const proto = Object.getPrototypeOf(obj); return function () { return proto[prop].apply(this, arguments); }; } }; let stateUser; //------------------------------------------------------------------------- // Game_Temp const _Game_Temp_initialize = Game_Temp.prototype.initialize; Game_Temp.prototype.initialize = function() { _Game_Temp_initialize.apply(this, arguments); stateUser = null; }; //------------------------------------------------------------------------- // Game_Action const _Game_Action_itemEffectAddAttackState = Game_Action.prototype.itemEffectAddAttackState; Game_Action.prototype.itemEffectAddAttackState = function(target, effect) { stateUser = this.subject(); _Game_Action_itemEffectAddAttackState.apply(this, arguments); stateUser = null; }; const _Game_Action_itemEffectAddNormalState = Game_Action.prototype.itemEffectAddNormalState; Game_Action.prototype.itemEffectAddNormalState = function(target, effect) { stateUser = this.subject(); _Game_Action_itemEffectAddNormalState.apply(this, arguments); stateUser = null; }; //------------------------------------------------------------------------- // Game_BattlerBase const _Game_BattlerBase_clearStates = Game_BattlerBase.prototype.clearStates; Game_BattlerBase.prototype.clearStates = function() { _Game_BattlerBase_clearStates.apply(this, arguments); this._stateLevels = {}; this._stateMaxTurns = {}; }; const _Game_BattlerBase_eraseState = Game_BattlerBase.prototype.eraseState; Game_BattlerBase.prototype.eraseState = function(stateId) { _Game_BattlerBase_eraseState.apply(this, arguments); delete this._stateLevels[stateId]; delete this._stateMaxTurns[stateId]; }; const _Game_BattlerBase_resetStateCounts = Game_BattlerBase.prototype.resetStateCounts; Game_BattlerBase.prototype.resetStateCounts = function(stateId) { const stTurns = this._stateTurns; const stLevels = this._stateLevels; const lastStateTurn = stTurns[stateId] || 0; _Game_BattlerBase_resetStateCounts.apply(this, arguments); stTurns[stateId] = Math.max(stTurns[stateId], lastStateTurn); if (stLevels[stateId]) { const maxLevel = this.maxStateLevel(stateId) + (stateUser ? stateUser.stateLevelPlus(stateId) : 0); if (stLevels[stateId] < maxLevel) stLevels[stateId]++; } else { stLevels[stateId] = 1; } }; Game_BattlerBase.prototype.maxStateLevel = function(stateId) { const state = $dataStates[stateId]; return state ? 99 : 1; }; Game_BattlerBase.prototype.displayedStates = function() { return this.states().filter(state => state.iconIndex > 0); }; Game_BattlerBase.prototype.stateTurn = function(stateId) { return this._stateTurns[stateId] || 0; }; Game_BattlerBase.prototype.maxStateTurn = function(stateId) { return this._stateMaxTurns[stateId] || 1; }; Game_BattlerBase.prototype.allLevels = function() { const levels = this.displayedStates().map(state => { return this.maxStateLevel(state.id) > 1 ? this._stateLevels[state.id] : 0; }); // for (let i = 0; i < this._buffs.length; i++) { // if (this._buffs[i] !== 0) { // levels.push(Math.abs(this._buffs[i])); // } // } return levels; }; // overwrite Game_BattlerBase.prototype.traitObjects = function() { return this.levelStates(); }; Game_BattlerBase.prototype.levelStates = function() { return this.states().reduce((r, state) => { const level = this._stateLevels[state.id] || 1; for (let i = 0; i < level; i++) r.push(state); return r; }, []); }; // overwrite Game_BattlerBase.prototype.traitsPi = function(code, id) { const traitMap = new Map(); const stateTraits = this.states().map(state => state.traits).flat(); let value = this.traitsWithId(code, id).reduce((r, trait) => { if (stateTraits.includes(trait)){ traitMap.set(trait, (traitMap.get(trait) || 0) + 1); return r; } return r * trait.value; }, 1); for (const [trait, level] of traitMap) value *= (trait.value - 1) * level + 1; return value; }; Game_BattlerBase.prototype.allMetadata = function(name) { return this.traitObjects().reduce((r, obj) => { if (name in obj.meta) r.push(obj.meta[name]); return r; }, []); }; Game_BattlerBase.prototype.metadataNumbers = function(name) { return this.allMetadata(name).map(Number); }; Game_BattlerBase.prototype.metadataSum = function(name) { return this.metadataNumbers(name).reduce((r, n) => r + n, 0); }; //------------------------------------------------------------------------- // Game_Battler const _Game_Battler_addState = Game_Battler.prototype.addState; Game_Battler.prototype.addState = function(stateId) { _Game_Battler_addState.apply(this, arguments); if (this.isStateAffected(stateId)) this.resetMaxStateTurn(stateId); }; Game_Battler.prototype.resetMaxStateTurn = function(stateId) { this._stateMaxTurns[stateId] = Math.max( this._stateMaxTurns[stateId] || 0, this._stateTurns[stateId] ); }; Game_Battler.prototype.stateLevelPlus = function(stateId) { return this.metadataSum(`stLvPlus ${stateId}`); }; //------------------------------------------------------------------------- // Sprite_StateTurnGauge class Sprite_StateTurnGauge extends Sprite_Gauge { constructor() { super(); this._stateId = 0; this.anchor.set(0.5); } bitmapWidth() { return ImageManager.iconWidth; } bitmapHeight() { return 8; } textHeight() { return this.gaugeHeight(); } gaugeHeight() { return this.bitmapHeight() - 2; } gaugeX() { return 0; } setup(battler) { super.setup(battler, 'stTurn'); } setState(stateId) { if (this._stateId !== stateId) { this._stateId = stateId; this._value = NaN; this._maxValue = NaN; } } currentValue() { const state = $dataStates[this._stateId]; return this._battler && state && state.autoRemovalTiming > 0 ? this._battler.stateTurn(this._stateId) : NaN; } currentMaxValue() { return this._battler ? this._battler.maxStateTurn(this._stateId) : NaN; } gaugeColor1() { return ColorManager.ctGaugeColor1(); } gaugeColor2() { return ColorManager.ctGaugeColor2(); } drawLabel() {} drawValue() {} } //------------------------------------------------------------------------- // Sprite_StateIcon const _Sprite_StateIcon_initialize = Sprite_StateIcon.prototype.initialize; Sprite_StateIcon.prototype.initialize = function() { _Sprite_StateIcon_initialize.apply(this, arguments); this._level = 0; this._lastLevel = 0; this.createTurnSprite(); this.createLevelSprite(); }; Sprite_StateIcon.prototype.createTurnSprite = function() { this._turnSprite = new Sprite_StateTurnGauge(); this._turnSprite.move(0, 20); this.addChild(this._turnSprite); }; Sprite_StateIcon.prototype.createLevelSprite = function() { const bitmap = new Bitmap(ImageManager.iconWidth, ImageManager.iconHeight); bitmap.fontFace = $gameSystem.numberFontFace(); bitmap.fontSize = ImageManager.iconHeight - 12; bitmap.textColor = ColorManager.normalColor(); bitmap.outlineColor = 'rgba(80, 64, 64, 0.75)';//ColorManager.outlineColor(); bitmap.outlineWidth = 5; this._levelSprite = new Sprite(bitmap); this._levelSprite.move(-12, -12); this.addChild(this._levelSprite); }; const _Sprite_StateIcon_destroy = __base(Sprite_StateIcon.prototype, 'destroy'); Sprite_StateIcon.prototype.destroy = function() { this._levelSprite.bitmap.destroy(); _Sprite_StateIcon_destroy.apply(this, arguments); }; const _Sprite_StateIcon_setup = Sprite_StateIcon.prototype.setup; Sprite_StateIcon.prototype.setup = function(battler) { if (this._battler !== battler) this._turnSprite.setup(battler); _Sprite_StateIcon_setup.apply(this, arguments); }; const _Sprite_StateIcon_update = Sprite_StateIcon.prototype.update; Sprite_StateIcon.prototype.update = function() { _Sprite_StateIcon_update.apply(this, arguments); if (this._lastLevel !== this._level) { this._lastLevel = this._level; this.updateLevel(); } }; const _Sprite_StateIcon_updateIcon = Sprite_StateIcon.prototype.updateIcon; Sprite_StateIcon.prototype.updateIcon = function() { _Sprite_StateIcon_updateIcon.apply(this, arguments); const levels = this.shouldDisplay() ? this._battler.allLevels() : []; const state = this._battler.displayedStates()[this._animationIndex]; this._level = levels.length ? levels[this._animationIndex] || 0 : 0; this._turnSprite.setState(state ? state.id : 0); }; Sprite_StateIcon.prototype.updateLevel = function() { const bitmap = this._levelSprite.bitmap; const width = ImageManager.iconWidth; const height = ImageManager.iconHeight - 12; bitmap.clear(); if (this._level > 0) bitmap.drawText(this._level, 0, 12, width - 2, height, 'right'); }; })();