自制半即时战斗系统
发一个自制的半即时战斗系统,长相就是下面图片的样子……不太会用的也可以参考范例工程~
注意:此脚本未经过严格的测试,可能发生BUG或与其它脚本不兼容的情况。
如有问题可以回帖或私信。
JAVASCRIPT 代码
// 半即时战斗脚本
// 作者:xsrong
// ---------------------------------------------------
// 插件简介:
// 启用该脚本后,战斗系统将改变为蓄槽模式的半即时战斗。
// ---------------------------------------------------
// 使用注意:
// ※本插件为战斗每个成员新增了cp值,cp值按照该成员的敏捷值进行增长,
// ※我方成员的cp值增长到10000后弹出战斗选项,敌方成员cp值增长至10000之后采取行动。
// ※可以为每个技能和物品设定单独的cp cost,使用该技能和物品的话会扣除相应的cp。
// ※设定方法:在物品或技能的备注栏备注。xxxxx最小为0,最大为10000。
// ※未设定物品或技能的cp cost则默认为10000。
// ※逃跑失败固定扣除10000cp。
//
// ※本插件更改了遇敌时决定先手和被袭击的条件,
// ※使得明雷遇敌(在事件中呼叫战斗处理)也有几率触发先手和被袭击。
// ※另外需要设置以下三个全局开关用以控制先手和被袭击:
// ※在preemptiveSwitch储存的开关id打开的情况下必定先手
// ※在surpriseSwitch储存的开关id打开的情况下必定被袭击
// ※在noPreemptiveAndSurprise储存的开关id打开的情况下不会触发先手和被袭击
// ※默认1号开关打开情况下每次战斗必先手,2号开关打开情况下必被偷袭,3号开关打开情况下不会发生先手或被偷袭。
//
// ※本插件为每个战斗成员新增了_turnCount属性,用以记录战斗成员的回合数。
//
// ※本插件新增了以下两个全局函数用以设置战斗事件的发生条件:
// ※currentActionBattler() 调用该函数会返回当前正在行动的战斗成员
// ※currentActionBattlerTurnCount() 调用该函数会返回当前正在行动的战斗成员的回合数
// ※本插件向Game_Battler类新增了isCurrentActionBattler()函数,调用该方法会返回某Game_Battler实例是否是当前正在行动的成员的布尔值。
// ※通过上面三个函数,可以在战斗事件中精确控制己方或地方成员每回合的动作。
// ※具体设置方法可以参考范例工程。
//
// ※本插件更改了战斗中状态图标的显示,战斗中的状态图标右上角显示该状态有效的剩余回合数。
// ※每个战斗成员的状态剩余回合数是独立控制的。该成员行动之后,该成员身上的状态会立即更新。
// ---------------------------------------------------
// 设置战斗成员的初始cp
Game_Battler.prototype._cp = 0;
// 控制每次战斗必先手的开关id
var preemptiveSwitch = 1;
// 控制每次战斗必备偷袭的开关id
var surpriseSwitch = 2;
// 注:上面两个开关同时打开时,每次战斗必先手
// 控制战斗先手和被偷袭无效的开关id
var noPreemptiveAndSurprise = 3;
// ---------------------------------------------------
// 绘制战斗成员行动槽的窗口
// ---------------------------------------------------
function Window_CPBar(){
this.initialize.apply(this, arguments)
};
Window_CPBar.prototype = Object.create(Window_Base.prototype);
Window_CPBar.prototype.constructor = Window_CPBar;
Window_CPBar.prototype.initialize = function(x, y, w, h){
Window_Base.prototype.initialize.call(this, x, y, w, h);
this.opacity = 0; // 将窗口背景和框架透明化
this._actorFaceBitmaps = []; // 保存行动槽上角色头像的数组
this._enemyFaceBitmaps = []; // 保存行动槽上敌人头像的数组
this.createActorCPBarFaces();
this.createEnemyCPBarFaces();
};
Window_CPBar.prototype.refresh = function(){
this.contents.clear();
this.drawCPBar(this.x + 20, this.y,this.width - 80);
this.drawCPBarFaces()
};
Window_CPBar.prototype.drawCPBar = function(x, y, width){
width = width || 186;
var color1 = 'black'; // 行动槽左端颜色
var color2 = 'grey'; // 行动槽右端颜色
this.drawGauge(x, y, width, 1, color1, color2);
};
Window_CPBar.prototype.createActorCPBarFace = function(faceName){
var bitmap = ImageManager.loadFace(faceName);
this._actorFaceBitmaps.push(bitmap);
}
Window_CPBar.prototype.createActorCPBarFaces = function(){
actors = $gameParty.members();
for(var i = 0; i < actors.length; i++){
this.createActorCPBarFace(actors.faceName());
}
}
Window_CPBar.prototype.createEnemyCPBarFace = function(battlerName){
var bitmap = ImageManager.loadEnemy(battlerName);
this._enemyFaceBitmaps.push(bitmap);
}
Window_CPBar.prototype.createEnemyCPBarFaces = function(){
enemies = $gameTroop.members();
for(var i = 0; i < enemies.length; i++){
this.createEnemyCPBarFace(enemies.enemy().battlerName);
}
}
Window_CPBar.prototype.drawActorCPBarFaces = function(){
actors = $gameParty.members();
for(var i = 0; i < actors.length; i++){
if(actors.isAlive()){
var pw = Window_Base._faceWidth;
var ph = Window_Base._faceHeight;
var rate = actors._cp / 10000;
rate = Math.min(rate, 1);
var dx = rate * (this.width - 95);
var dy = 0;
var sx = actors.faceIndex() % 4 * pw;
var sy = Math.floor(actors.faceIndex() / 4) * ph;
this.contents.blt(this._actorFaceBitmaps, sx, sy, pw, ph, dx, dy, 30, 30);
}
}
}
Window_CPBar.prototype.drawEnemyCPBarFaces = function(){
enemies = $gameTroop.members();
for(var i = 0; i < enemies.length; i++){
if(enemies.isAlive()){
var pw = this._enemyFaceBitmaps._image.width;
var ph =this._enemyFaceBitmaps._image.height;
var rate = enemies._cp / 10000;
rate = Math.min(rate, 1);
var dx = rate * (this.width - 95);
var dy = 0;
var sx = 0;
var sy = 0;
this.contents.blt(this._enemyFaceBitmaps, sx, sy, pw, ph, dx, dy, 30, 30);
}
}
}
Window_CPBar.prototype.drawCPBarFaces = function(){
this.drawEnemyCPBarFaces();
this.drawActorCPBarFaces();
}
// ---------------------------------------------------
// 修改战斗场景
// ---------------------------------------------------
xsrongSceneBattleCreateAllWindows = Scene_Battle.prototype.createAllWindows;
Scene_Battle.prototype.createAllWindows = function(){
xsrongSceneBattleCreateAllWindows.call(this);
this.createCPBarWindow(); // 向战斗场景中加入行动槽
};
Scene_Battle.prototype.createCPBarWindow = function(){
this._cpBarWindow = new Window_CPBar(0, 0, Graphics.boxWidth, 72)
this._spriteset.addChild(this._cpBarWindow)
};
Scene_Battle.prototype.updateCPBarWindow = function(){
var battlers = $gameParty.members().concat($gameTroop.members());
battlers.forEach(function(b){
if(b.isAlive()){
b._cp += b.agi; // 战斗成员cp值的增加量为该成员的敏捷度
}
});
this._cpBarWindow.refresh();
};
// 向战斗场景中的角色命令窗口增加逃跑选项
xsrongSceneBattleCreateActorCommandWindow = Scene_Battle.prototype.createActorCommandWindow;
Scene_Battle.prototype.createActorCommandWindow = function(){
this._actorCommandWindow = new Window_ActorCommand();
this._actorCommandWindow.setHandler('attack', this.commandAttack.bind(this));
this._actorCommandWindow.setHandler('skill',this.commandSkill.bind(this));
this._actorCommandWindow.setHandler('guard',this.commandGuard.bind(this));
this._actorCommandWindow.setHandler('item', this.commandItem.bind(this));
this._actorCommandWindow.setHandler('escape', this.commandEscape.bind(this));
this.addWindow(this._actorCommandWindow);
};
xsrongSceneBattleCommandEscape = Scene_Battle.prototype.commandEscape;
Scene_Battle.prototype.commandEscape = function(){
BattleManager.processEscape();
};
BattleManager.processEscape = function(){
$gameParty.performEscape();
SoundManager.playEscape();
var success = this._preemptive ? true : (Math.random() < this._escapeRatio);
if(success){
this.displayEscapeSuccessMessage();
this._escaped = true;
this.processAbort();
}else{
this.actor()._cp -= 10000; // 逃跑失败扣除10000点cp
this.actor().onTurnEnd(); // 逃跑失败更新该角色身上的状态
this.displayEscapeFailureMessage();
this._escapeRatio += 0.1;
$gameParty.clearActions();
this._phase = 'xsrong_wait'; // 逃跑失败继续等待行动
this.xsrongWait();
}
return success;
};
xsrongBattleManagerUpdate = BattleManager.update;
BattleManager.update = function(){
if(!this.isBusy() && !this.updateEvent()){
switch(this._phase){
case'start':
this.xsrongStart();
break;
case'turn':
this.updateTurn();
break;
case'action':
this.updateAction();
break;
case'turnEnd':
this.updateTurnEnd();
break;
case'battleEnd':
this.updateBattleEnd();
break;
case'xsrong_wait': // 等待行动槽涨满
this.xsrongWait();
break;
case'enemy_action': // 等待敌人行动
this.updateTurn();
break;
};
}
};
xsrongBattleManagerUpdateEvent = BattleManager.updateEvent;
BattleManager.updateEvent = function(){
switch(this._phase){
case'start':
case'turn':
case'enemy_action':
if(this.isActionForced()){
this.processForcedAction();
returntrue;
}else{
returnthis.updateEventMain();
}
}
returnthis.checkAbort();
};
BattleManager.processForcedAction = function(){
if(this._actionForcedBattler){
this._subject = this._actionForcedBattler;
this._actionForcedBattler = null;
this.startAction();
this._subject.removeCurrentAction();
this._subject._turnCount++; // 战斗事件中强制战斗行动后增加该成员的回合数
this._subject.onTurnEnd(); // 战斗事件中强制战斗行动后更新该成员身上的状态
}
};
xsrongBattleManagerMakeActionOrders = BattleManager.makeActionOrders;
BattleManager.makeActionOrders = function(){
var battlers = [];
battlers = battlers.concat($gameParty.members()).concat($gameTroop.members())
this._actionBattlers = battlers;
};
// 设置战斗开始时每个战斗成员的cp
BattleManager.setupMemberCP = function(){
if(this._surprise){
$gameTroop.members().forEach(function(enemy){
enemy._cp = 10000 - Math.floor(Math.random()*5) * 10; // 被偷袭的场合,所有敌人的cp直接涨满
});
}elseif(this._preemptive){
$gameParty.members().forEach(function(actor){
actor._cp = 10000 - actor.agi; // 我方先手的场合,所有我方队员的cp直接涨满
});
}else{
for(var i = 0; i < this._actionBattlers.length; i++){
randNum = Math.floor(Math.random()*20) * 50;
this._actionBattlers._cp = this._actionBattlers.agi * 10 + randNum; // 没有先手和被偷袭的场合,随机设置所有成员的初始cp
};
}
}
BattleManager.setupMemberTurnCount = function(){
battlers = this._actionBattlers;
battlers.forEach(function(battler){
battler._turnCount = 1; // 设置每个成员的初始回合数
})
}
BattleManager.xsrongStart = function(){
this.makeActionOrders();
this.setupMemberCP();
this.setupMemberTurnCount();
this._phase = 'xsrong_wait'; // 进入战斗后开始等待行动槽涨满
};
BattleManager.xsrongWait = function(){
for(var i = 0; i < $gameParty.members().length; i++){
var actor =$gameParty.members();
if(actor._cp >= 10000){
this._phase = "turn"
this._subject = actor;
this._actorIndex = $gameParty.members().indexOf(actor);
if(!this.updateEvent()){
this._phase = "input"; // 角色没有被强制行动的话,输入战斗指令
actor.makeActions();
}else{
this.processForcedAction(); // 角色被强制行动的话,无视已输入的指令,执行强制行动
}
break;
}
};
for(var j = 0; j < $gameTroop.members().length; j++){
var enemy = $gameTroop.members();
if(enemy._cp >= 10000){
$gameTroop.increaseTurn();
this._phase = "enemy_action";
enemy.makeActions();
this._subject = enemy;
break;
}
}
SceneManager._scene.updateCPBarWindow();
};
xsrongBattleManagerSelectNextCommand = BattleManager.selectNextCommand;
BattleManager.selectNextCommand = function(){
do{
this.startTurn();
break;
}while(!this.actor().canInput());
};
xsrongBattleManagerUpdateTurnEnd = BattleManager.updateTurnEnd;
BattleManager.updateTurnEnd = function(){
this.xsrongWait(); // 一个战斗成员的行动结束后,继续等待行动槽涨满
};
xsrongBattleManagerOnEncounter = BattleManager.onEncounter
BattleManager.onEncounter = function(){
xsrongBattleManagerOnEncounter.call(this);
if($gameSwitches._data){
this._preemptive = true; // 强制先手的开关打开时,战斗强制先手
}
if(!$gameSwitches._data && $gameSwitches._data){
this._surprise = true; // 强制被偷袭的开关打开时,战斗强制被偷袭
}
if($gameSwitches._data){
this._preemptive = false; // 先手和被偷袭无效的开关打开时,先手和被偷袭无效
this._surprise = false;
}
};
xsrongBattleManagerProcessTurn = BattleManager.processTurn
BattleManager.processTurn = function(){
var subject = this._subject;
var action = subject.currentAction();
if(action){
action.prepare();
if(action.isValid()){
this.startAction();
}
subject.removeCurrentAction();
subject._turnCount++ ; // 行动结束后增加战斗成员的回合数
subject.onTurnEnd(); // 行动结束后更新战斗成员身上的状态
}else{
subject.onAllActionsEnd();
this.refreshStatus();
this._logWindow.displayAutoAffectedStatus(subject);
this._logWindow.displayCurrentState(subject);
this._logWindow.displayRegeneration(subject);
this._subject = this.getNextSubject();
}
};
xsrongBattleManagerEndTurn = BattleManager.endTurn
BattleManager.endTurn = function(){
this._phase = 'turnEnd';
this._preemptive = false;
this._surprise = false;
this.allBattleMembers().forEach(function(battler){ // 取消了在这里更新战斗成员状态的代码
this.refreshStatus();
this._logWindow.displayAutoAffectedStatus(battler);
this._logWindow.displayRegeneration(battler);
}, this);
};
// 读取技能和物品需要的cp
Game_BattlerBase.prototype.skillCpCost = function(skill){
var pat = //;
var str = pat.exec(skill.note);
var cpCost;
if(str){
cpCost = parseInt(str.input.split(" "));
cpCost = Math.min(cpCost, 10000)
cpCost = Math.max(cpCost, 0)
}else{
cpCost = 10000;
}
return cpCost;
};
Game_Battler.prototype.useItem = function(item){
if(DataManager.isSkill(item)){
this.paySkillCost(item);
}elseif(DataManager.isItem(item)){
this.consumeItem(item);
if($gameParty.inBattle()){ // 在战斗中使用物品会被扣除相应的cp
var cpCost = this.skillCpCost(item);
this._cp -= cpCost;
}
}
};
xsrongGameBattlerBasePaySkillCost = Game_BattlerBase.prototype.paySkillCost;
Game_BattlerBase.prototype.paySkillCost = function(skill){
xsrongGameBattlerBasePaySkillCost.call(this, skill);
if($gameParty.inBattle()){
this._cp -= this.skillCpCost(skill); // 在战斗中使用技能会被扣除相应的cp
}
};
xsrongGameBattlerBaseDie = Game_BattlerBase.prototype.die
Game_BattlerBase.prototype.die = function(){
xsrongGameBattlerBaseDie.call(this);
this._cp = 0; // 角色倒下时cp归零
};
xsrongWindowActorCommandMakeCommandList = Window_ActorCommand.prototype.makeCommandList;
Window_ActorCommand.prototype.makeCommandList = function(){
if(this._actor){
this.addAttackCommand();
this.addSkillCommands();
this.addGuardCommand();
this.addItemCommand();
this.addEscapeCommand();
}
};
Window_ActorCommand.prototype.addEscapeCommand = function(){
this.addCommand(TextManager.escape, 'escape', BattleManager.canEscape());
};
xsrongGameInterpreterCommand301 = Game_Interpreter.prototype.command301;
Game_Interpreter.prototype.command301 = function(){
if(!$gameParty.inBattle()){
var troopId;
if(this._params === 0){
troopId = this._params;
}elseif(this._params === 1){
troopId = $gameVariables.value(this._params);
}else{
troopId = $gamePlayer.makeEncounterTroopId();
}
if($dataTroops){
BattleManager.setup(troopId, this._params, this._params);
BattleManager.onEncounter(); // 采用明雷遇敌时增加偷袭和被偷袭功能
BattleManager.setEventCallback(function(n){
this._branch = n;
}.bind(this));
$gamePlayer.makeEncounterCount();
SceneManager.push(Scene_Battle);
}
}
returntrue;
};
xsrongDataManagerSetupBattleTest = DataManager.setupBattleTest;
DataManager.setupBattleTest = function(){
this.createGameObjects();
$gameParty.setupBattleTest();
BattleManager.setup($dataSystem.testTroopId, true, false);
BattleManager.onEncounter(); // 战斗测试中增加偷袭和被偷袭功能
BattleManager.setBattleTest(true);
BattleManager.playBattleBgm();
};
Window_Base.prototype.drawActorIcons = function(actor, x, y, width){
width = width || 144;
var icons = actor.allIcons().slice(0, Math.floor(width / Window_Base._iconWidth));
var states = actor._states.filter(function(s){
return $dataStates.iconIndex > 0;
})
var text;
for(var i = 0; i < icons.length; i++){ // 在角色状态图标上增加剩余回合数
this.drawIcon(icons, x + (Window_Base._iconWidth + 8) * i, y + 2);
if(i < states.length){
stateId = states
if($dataStates.autoRemovalTiming == 1){
text = actor._stateTurns // 能够自动解除的状态显示剩余回合数
}else{
text = "∞" // 不能自动解除的状态显示剩余回合数无限
}
}else{
text = actor._buffTurns // 显示角色身上buff的剩余回合数
}
this.drawIconText(text, x + (Window_Base._iconWidth + 8) * i + 24, y);
}
};
Window_Base.prototype.drawIconText = function(text, x, y){
var bitmap = new Bitmap(this.width, this.height);
bitmap.drawCircle(16, 16, 16, 'red');
bitmap.drawText(text, 0, 0, 32, 32, 'center');
this.contents.blt(bitmap, 0, 0, 32, 32, x, y, 12, 12);
};
Sprite_Enemy.prototype.updateStateTurnSpriteText = function(){
var states = this._enemy._states.filter(function(s){
return $dataStates.iconIndex > 0;
});
var text;
if(this._stateIconSprite._animationIndex < states.length){ // 在敌人状态图标上增加剩余回合数
if($dataStates].autoRemovalTiming == 1){
text = this._enemy._stateTurns]; // 能够自动解除的状态显示剩余回合数
}else{
text = "∞"; // 不能自动解除的状态显示剩余回合数无限
}
}else{
text = this._enemy._buffTurns; // 显示敌人身上buff的剩余回合数
}
this.drawStateTurnSprite(text);
if(states.length > 0){
this._stateTurnSprite.opacity = 255
}else{
this._stateTurnSprite.opacity = 0
}
};
Sprite_Enemy.prototype.update = function(){
Sprite_Battler.prototype.update.call(this);
if(this._enemy){
this.updateEffect();
this.updateStateSprite();
this._stateTurnSprite.y = this._stateIconSprite.y - 20
this._stateTurnSprite.x = 8
this.updateStateTurnSpriteText();
}
};
Sprite_Enemy.prototype.createStateTurnSprite = function(){
var bitmap = new Bitmap(12, 12)
bitmap.outlineWidth = 0;
bitmap.fontSize = 10;
sp = new Sprite(bitmap);
this._stateTurnSprite = sp;
this.addChild(this._stateTurnSprite);
};
Sprite_Enemy.prototype.drawStateTurnSprite = function(text){
bitmap = this._stateTurnSprite.bitmap
bitmap.drawCircle(6, 6, 6, 'red');
bitmap.drawText(text, 0, 0, 12, 12, 'center');
};
Sprite_Enemy.prototype.initMembers = function(){
Sprite_Battler.prototype.initMembers.call(this);
this._enemy = null;
this._appeared = false;
this._battlerName = '';
this._battlerHue = 0;
this._effectType = null;
this._effectDuration = 0;
this._shake = 0;
this.createStateIconSprite();
this.createStateTurnSprite();
};
// 判断某个Game_Battler实例对象是否正在行动
Game_Battler.prototype.isCurrentActionBattler = function(){
return currentActionBattler() === this;
}
// 返回正在行动的战斗成员的回合数
currentActionBattlerTurnCount = function(){
var battler = currentActionBattler();
if(battler){
return battler._turnCount;
}
}
// 返回正在行动的战斗成员。如没有正在行动的战斗成员,则返回null
currentActionBattler = function(){
if(BattleManager._subject){
return BattleManager._subject;
}elseif(BattleManager.actor()){
return BattleManager.actor()
}else{
returnnull
}
}
本帖来自P1论坛作者xsrong2,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=479546若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
页:
[1]