// 半即时战斗脚本 // 作者:xsrong // --------------------------------------------------- // 插件简介: // 启用该脚本后,战斗系统将改变为蓄槽模式的半即时战斗。 // --------------------------------------------------- // 使用注意: // ※本插件为战斗每个成员新增了cp值,cp值按照该成员的敏捷值进行增长, // ※我方成员的cp值增长到10000后弹出战斗选项,敌方成员cp值增长至10000之后采取行动。 // ※可以为每个技能和物品设定单独的cp cost,使用该技能和物品的话会扣除相应的cp。 // ※设定方法:在物品或技能的备注栏备注<CPCOST xxxxx>。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[i].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[i].enemy().battlerName); } } Window_CPBar.prototype.drawActorCPBarFaces = function() { actors = $gameParty.members(); for (var i = 0; i < actors.length; i++) { if (actors[i].isAlive()) { var pw = Window_Base._faceWidth; var ph = Window_Base._faceHeight; var rate = actors[i]._cp / 10000; rate = Math.min(rate, 1); var dx = rate * (this.width - 95); var dy = 0; var sx = actors[i].faceIndex() % 4 * pw; var sy = Math.floor(actors[i].faceIndex() / 4) * ph; this.contents.blt(this._actorFaceBitmaps[i], 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[i].isAlive()) { var pw = this._enemyFaceBitmaps[i]._image.width; var ph = this._enemyFaceBitmaps[i]._image.height; var rate = enemies[i]._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[i], 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(); return true; } else { return this.updateEventMain(); } } return this.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直接涨满 }); } else if (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[i]._cp = this._actionBattlers[i].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()[i]; 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()[j]; 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[preemptiveSwitch]) { this._preemptive = true; // 强制先手的开关打开时,战斗强制先手 } if (!$gameSwitches._data[preemptiveSwitch] && $gameSwitches._data[surpriseSwitch]) { this._surprise = true; // 强制被偷袭的开关打开时,战斗强制被偷袭 } if ($gameSwitches._data[noPreemptiveAndSurprise]) { 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 = /<CPCOST\s\d+>/; var str = pat.exec(skill.note); var cpCost; if (str) { cpCost = parseInt(str.input.split(" ")[1]); 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); } else if (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] === 0) { troopId = this._params[1]; } else if (this._params[0] === 1) { troopId = $gameVariables.value(this._params[1]); } else { troopId = $gamePlayer.makeEncounterTroopId(); } if ($dataTroops[troopId]) { BattleManager.setup(troopId, this._params[2], this._params[3]); BattleManager.onEncounter(); // 采用明雷遇敌时增加偷袭和被偷袭功能 BattleManager.setEventCallback(function(n) { this._branch[this._indent] = n; }.bind(this)); $gamePlayer.makeEncounterCount(); SceneManager.push(Scene_Battle); } } return true; }; 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[s].iconIndex > 0; }) var text; for (var i = 0; i < icons.length; i++) { // 在角色状态图标上增加剩余回合数 this.drawIcon(icons[i], x + (Window_Base._iconWidth + 8) * i, y + 2); if (i < states.length) { stateId = states[i] if ($dataStates[stateId].autoRemovalTiming == 1) { text = actor._stateTurns[stateId] // 能够自动解除的状态显示剩余回合数 } else { text = "∞" // 不能自动解除的状态显示剩余回合数无限 } } else { text = actor._buffTurns[i - states.length] // 显示角色身上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[s].iconIndex > 0; }); var text; if (this._stateIconSprite._animationIndex < states.length) { // 在敌人状态图标上增加剩余回合数 if ($dataStates[this._enemy._states[this._stateIconSprite._animationIndex]].autoRemovalTiming == 1) { text = this._enemy._stateTurns[this._enemy._states[this._stateIconSprite._animationIndex]]; // 能够自动解除的状态显示剩余回合数 } else { text = "∞"; // 不能自动解除的状态显示剩余回合数无限 } } else { text = this._enemy._buffTurns[this._stateIconSprite._animationIndex - states.length]; // 显示敌人身上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; } else if (BattleManager.actor()) { return BattleManager.actor() } else { return null } }
1.png (1014.75 KB, 下载次数: 105)
半即时战斗截图
333.93 KB, 下载次数: 289
范例工程
欢迎光临 Project1 (https://rpg.blue/) | Powered by Discuz! X3.1 |