所谓 TickBased
RMMV 原生的战斗系统是基于回合的,速度只决定行动顺序。在 Tick Based 系统中,战斗时每个角色在单位时间(一般称为 Tick)内都会积累行动值,当行动值达到满值时就可以行动,行动会消耗行动值。行动后行动值继续积累,直到下一次满再次行动。
实现
写个对象方便重写方法。
// Battle System
var System = System || {};
System.Battle = System.Battle || {};
为 Game_BattlerBase
添加行动值(CT)属性,并定义操作它的方法和临界值。
System.Battle.Game_BattlerBase_initMembers = Game_BattlerBase.prototype.initMembers;
Game_BattlerBase.prototype.initMembers = function() {
this._ct = 0;
System.Battle.Game_BattlerBase_initMembers.call(this);
};
Game_BattlerBase.prototype.actionCT = function() {
return 1000;
};
Game_BattlerBase.prototype.addCT = function(value) {
if (this.isAlive()) {
this._ct += value;
}
};
去掉原本的和 Turn 相关的方法,因为在本站战斗系统中不需要回合。新增一个 'waiting' 阶段,在本阶段计算ct增长。新增 'acting' 阶段,在此阶段决定行动的角色。
BattleManager.update = function() {
if (!this.isBusy() && !this.updateEvent()) {
switch (this._phase) {
case 'start':
this.startInput();
break;
case 'waiting':
this.think();
break;
case 'acting':
this.updateActing();
break;
case 'action':
this.updateAction();
break;
case 'battleEnd':
this.updateBattleEnd();
break;
}
}
};
修改战斗开始方法,直接进入 'waiting' 阶段。
BattleManager.startBattle = function() {
this._phase = 'waiting';
$gameSystem.onBattleStart();
$gameParty.onBattleStart();
$gameTroop.onBattleStart();
this.displayStartMessages();
};
think方法,计算CT值的自然增长
BattleManager.think = function() {
var battlers = this.allBattleMembers();
var readies = [];
var hasActor = false;
battlers.forEach(function(b) {
b.addCT(b.agi);
if (b._ct >= b.actionCT()) {
b.addCT(-1000);
readies.push(b);
b.makeActions();
if (b.isActor()) {
hasActor = true;
} else {
b._actionState = 'waiting';
}
}
}, this);
if (readies.length < 1) return;
this._actionBattlers = readies;
if (hasActor) { //如果有玩家角色可以行动,则进入输入阶段,如果只有敌人行动,则不需要输入。
this._phase = 'input';
} else {
this._phase = 'acting';
}
};
修改剩下的相关方法,使之符合现在的逻辑
//完成一次行动后,再次进入 'acting' 阶段,进行下一个行动
BattleManager.endAction = function() {
this._logWindow.endAction(this._subject);
this._phase = 'acting';
};
//所有行动结束后 'acting' 阶段结束, 回到 'waiting' 阶段
BattleManager.updateActing = function() {
if (!this._subject) {
this._subject = this.getNextSubject();
}
if (this._subject) {
this.processTurn();
} else {
this._phase = 'waiting';
}
};
BattleManager.startTurn = function() {
this._phase = 'acting';
this.clearActor();
};
BattleManager.updateEvent = function() {
switch (this._phase) {
case 'start':
case 'waiting':
if (this.isActionForced()) {
this.processForcedAction();
return true;
} else {
return this.updateEventMain();
}
}
return this.checkAbort2();
};
修改can input 方法,让每个角色的行动输入分开进行。
Game_BattlerBase.prototype.canInput = function() {
return this.isAppeared() && !this.isRestricted() && !this.isAutoBattle() && BattleManager._actionBattlers.indexOf(this) > -1;
};