-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTPBCastTime.js
347 lines (329 loc) · 10.1 KB
/
TPBCastTime.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
//=============================================================================
// RPG Maker MZ - Implement wait TPB cast time
//=============================================================================
/*:
* @target MZ
* @plugindesc Implement wait TPB cast time
* @author MihailJP
* @url https://github.com/MihailJP/mihamzplugin/blob/master/TPBCastTime.js
*
* @help TPBCastTime.js
*
* This plugin implements waiting (delay) for cast which is
* incorrectly implemented as of version 1.0.0.
*
* It does not provide plugin commands.
*
* Changelog
* 26 Sept 2020: Fixed crash issue with out-of-battle skills.
* 26 Sept 2020: Fixed issue forced action causes being stuck.
* Avoid cost duplicate.
* 25 Sept 2020: First edition.
*
* @param flashWhenCastStarts
* @text Flash when cast starts
* @desc Flash the enemy who started cast
* @default true
* @type boolean
*
* @param soundWhenCastStarts
* @text SE played when cast starts
* @desc SE played when cast starts.
* @type struct<sound>
*
* @param soundForZeroCastTime
* @text SE for zero cast time
* @desc Whether the SE should be played even for skills of zero cast time.
* @type boolean
* @default false
* @on Play
* @off Don’t play
*
* @param actorInterrupt
* @text Interrupt Ally
* @desc Message shown when an ally’s action got interrupted. %1 will be replaced with the target.
* @default %1 was interrupted!
* @type string
*
* @param enemyInterrupt
* @text Interrupt Enemy
* @desc Message shown when an enemy’s action got interrupted. %1 will be replaced with the target.
* @default %1 was interrupted!
* @type string
*
* @param interruptByDamage
* @text Interrupt by damage
* @desc Whether HP damage causes interrupt to skill in cast time
* @default false
* @type boolean
*/
/*~struct~sound:
* @param name
* @text File
* @type file
* @dir audio/se
*
* @param volume
* @text Volume
* @default 90
* @type number
* @min 0
* @max 100
*
* @param pitch
* @text Pitch
* @default 100
* @type number
* @min 50
* @max 150
*
* @param pan
* @text Balance
* @default 0
* @type number
* @min -100
* @max 100
*/
/*:ja
* @target MZ
* @plugindesc TPBに詠唱待ちを実装
* @author MihailJP
* @url https://github.com/MihailJP/mihamzplugin/blob/master/TPBCastTime.js
*
* @help TPBCastTime.js
*
* このプラグインは、バージョン1.0.0のTPBで正しく実装されていなかった
* 詠唱(キャスト)待ちを実装します。
*
* プラグインコマンドはありません。
*
* 更新履歴
* 令和2年9月26日 戦闘外でスキルを使うと落ちる問題を修正
* 令和2年9月26日 戦闘行動の強制で止まる問題を修正
* コストの2度払いを抑止
* 令和2年9月25日 初版
*
* @param flashWhenCastStarts
* @text キャスト開始時に光らせる
* @desc キャスト開始した敵を光らせます。
* @default true
* @type boolean
*
* @param soundWhenCastStarts
* @text キャスト開始時の効果音
* @desc キャスト開始時に鳴らす効果音です。
* @type struct<sound>
*
* @param soundForZeroCastTime
* @text 即時発動スキルの時
* @desc 速度補正が0のスキルでもキャスト開始音を鳴らすかどうかを指定します。
* @type boolean
* @default false
* @on 鳴らす
* @off 鳴らさない
*
* @param actorInterrupt
* @text 味方に行動妨害
* @desc 味方の行動が妨害されたときに表示されるメッセージを指定します。%1は対象に変換されます。
* @default %1は行動を妨害された!
* @type string
*
* @param enemyInterrupt
* @text 敵に行動妨害
* @desc 敵の行動を妨害したときに表示されるメッセージを指定します。%1は対象に変換されます。
* @default %1の行動を妨害した!
* @type string
*
* @param interruptByDamage
* @text ダメージを与えると行動妨害
* @desc HPダメージを与えることで行動を妨害できるかを指定します。
* @default false
* @type boolean
*/
/*~struct~sound:ja
* @param name
* @text ファイル
* @type file
* @dir audio/se
*
* @param volume
* @text 音量
* @default 90
* @type number
* @min 0
* @max 100
*
* @param pitch
* @text ピッチ
* @default 100
* @type number
* @min 50
* @max 150
*
* @param pan
* @text 位相
* @default 0
* @type number
* @min -100
* @max 100
*/
(() => {
const pluginName = "TPBCastTime";
const param = PluginManager.parameters(pluginName);
const soundWhenCastStarts = (function(k) {
k.volume = parseInt(k.volume);
k.pitch = parseInt(k.pitch);
k.pan = parseInt(k.pan);
return k;
})(JSON.parse(param.soundWhenCastStarts));
const orig_Game_Action_clear = Game_Action.prototype.clear;
Game_Action.prototype.clear = function() {
orig_Game_Action_clear.call(this);
this._deferredTarget = null;
this._costPaid = false;
};
const orig_Game_Action_isValid = Game_Action.prototype.isValid;
Game_Action.prototype.isValid = function() {
return this._costPaid || orig_Game_Action_isValid.call(this);
};
const orig_Game_ActionResult_clear = Game_ActionResult.prototype.clear;
Game_ActionResult.prototype.clear = function() {
orig_Game_ActionResult_clear.call(this);
this.interrupt = false;
};
const orig_Game_Battler_useItem = Game_Battler.prototype.useItem;
Game_Battler.prototype.useItem = function(item) {
if ((!$gameParty._inBattle) || (!BattleManager.isTpb())) {
orig_Game_Battler_useItem.call(this, item);
} else if (this.currentAction()._forcing) {
orig_Game_Battler_useItem.call(this, item);
this._actions[0]._costPaid = true;
} else if (this._tpbState === "acting") {
if (BattleManager._action._deferredTarget) {
BattleManager._targets = BattleManager._action._deferredTarget;
} else if (BattleManager._action._targetIndex >= 0) {
if (BattleManager._action.isForFriend()) {
BattleManager._targets = [this.friendsUnit().members()[BattleManager._action._targetIndex]];
} else {
BattleManager._targets = [this.opponentsUnit().members()[BattleManager._action._targetIndex]];
}
}
if (this._actions[0]._costPaid) {
// to avoid cost duplicate...
const mp = this._mp;
const tp = this._tp;
if (DataManager.isItem(item) && item.consumable) {
$gameParty.gainItem(item, 1); // regain pre-consumed item
}
orig_Game_Battler_useItem.call(this, item);
this._mp = mp;
this._tp = tp;
} else {
orig_Game_Battler_useItem.call(this, item);
this._actions[0]._costPaid = true;
}
} else {
if (JSON.parse(param.flashWhenCastStarts)) {
this.requestEffect("whiten");
}
if (soundWhenCastStarts.name) {
if (JSON.parse(param.soundForZeroCastTime) || (this.tpbRequiredCastTime() > 0)) {
AudioManager.playSe(soundWhenCastStarts);
}
}
orig_Game_Battler_useItem.call(this, item);
this._actions[0]._costPaid = true;
this._actions[0]._deferredTarget = BattleManager._targets;
this._actions.unshift(this._actions[0]);
BattleManager._phase = "turn";
BattleManager._action = null;
BattleManager._targets = [];
}
};
const orig_Game_Battler_onDamage = Game_Battler.prototype.onDamage;
Game_Battler.prototype.onDamage = function(value) {
orig_Game_Battler_onDamage.call(this, value);
if (JSON.parse(param.interruptByDamage)) {
this.interruptTpbCast();
}
};
Game_BattlerBase.prototype.cancelTpbAction = function() {
this._actionState = "done";
this._tpbState = "charging";
this._tpbTurnEnd = false;
this._actions = [];
this._tpbChargeTime = this._tpbCastTime = this._tpbIdleTime = 0;
BattleManager._actionBattlers = BattleManager._actionBattlers.filter(b => (b !== this));
};
Game_BattlerBase.prototype.interruptTpbCast = function() {
// Canceled if got restriction during cast time
if (this._tpbState === "casting") {
this.cancelTpbAction();
this._result.interrupt = true;
}
};
const orig_Game_BattlerBase_onRestrict = Game_BattlerBase.prototype.onRestrict;
Game_BattlerBase.prototype.onRestrict = function() {
// Canceled if got restriction during cast time
this.interruptTpbCast();
orig_Game_BattlerBase_onRestrict.call(this);
};
const orig_BattleManager_startAction = BattleManager.startAction;
BattleManager.startAction = function() {
try {
orig_BattleManager_startAction.call(this);
} catch (e) {
if ((e instanceof TypeError) && (e.message == "Cannot read property 'applyGlobal' of null")) {
// intended cancellation. nothing to do.
} else {
throw e;
}
}
};
const orig_BattleManager_processTurn = BattleManager.processTurn;
BattleManager.processTurn = function() {
if (!this.isTpb()) {
orig_BattleManager_processTurn.call(this);
} else if (this._subject.currentAction() && this._subject.currentAction()._forcing) {
const nosOfActions = this._subject._actions.length;
orig_BattleManager_processTurn.call(this);
if (nosOfActions <= this._subject._actions.length) {
this._subject.removeCurrentAction();
}
} else {
if (this._actionBattlers.length) {
if (this._subject) {
this._actionBattlers.push(this._subject);
}
this._subject = this.getNextSubject();
}
if (this._subject) {
if ((this._subject._tpbState !== "casting")
|| (this._subject._actions.length == 0)
|| (this._subject._actions[0]._deferredTarget === null)
) {
orig_BattleManager_processTurn.call(this);
}
}
if (this._subject) {
if (this._subject._tpbState === "casting") {
this._actionBattlers.push(this._subject);
this._subject = null;
}
}
}
};
Window_BattleLog.prototype.displayInterrupt = function(target) {
this._methods.pop(); // popBaseLine
this.push("addText", param[target.isActor() ? "actorInterrupt" : "enemyInterrupt"].format(target.name()));
this.push("waitForNewLine");
this.push("popBaseLine");
};
const orig_Window_BattleLog_displayActionResults = Window_BattleLog.prototype.displayActionResults;
Window_BattleLog.prototype.displayActionResults = function(subject, target) {
orig_Window_BattleLog_displayActionResults.call(this, subject, target);
if ((target.result().used) && (target.result().interrupt)) {
this.displayInterrupt(target);
}
};
})();