Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*:
- * @plugindesc v1.02 SO4 Bonus Board: Persistent, stacking post-battle effects via certain actions in battle.
- * @author Coolie (William Couillard)
- *
- * @param Empty Icon ID
- * @type number
- * @min 0
- * @desc Icon ID for an empty slot on the Bonus Board
- * @default 16
- *
- * @param Reward 1 Icon ID
- * @type number
- * @min 0
- * @desc Icon ID for Physical KO Bonus
- * @default 32
- *
- * @param Reward 2 Icon ID
- * @type number
- * @min 0
- * @desc Icon ID for Magical KO Bonus
- * @default 33
- *
- * @param Reward 3 Icon ID
- * @type number
- * @min 0
- * @desc Icon ID for One-Hit KO Bonus
- * @default 78
- *
- * @param Reward 4 Icon ID
- * @type number
- * @min 0
- * @desc Icon ID for Critical Hit Bonus
- * @default 77
- *
- * @param Slot Fill Animation ID
- * @type animation
- * @desc Battle animation to play on party when a Bonus Board slot is filled.
- * @default 1
- *
- * @param Reset Animation ID
- * @type animation
- * @desc Battle animation to play on party when the Bonus Board is forcefully reset.
- * @default 1
- *
- * @param Window X
- * @type number
- * @desc X position of the gauge window on the screen. (-1 = centered)
- * @default -1
- *
- * @param Window Y
- * @type number
- * @desc Y position of the gauge window on the screen.
- * @default 0
- *
- * @help
- * -----------------------------------------------------------------------------
- * ABOUT THIS PLUGIN (Star Ocean: The Last Hope Bonus Board)
- * -----------------------------------------------------------------------------
- * The Bonus Board is a feature in Star Ocean: The Last Hope. It is a persistent
- * gauge, always visible during battle. By performing certain actions, the
- * player can fill the gauge for a variety of post-battle effects.
- *
- * -----------------------------------------------------------------------------
- * HOW TO FILL THE BONUS BOARD SLOTS
- * -----------------------------------------------------------------------------
- * Slots will fill for specific KO or hit conditions.
- * 1. Physical KO on an Enemy
- * 2. Magical KO on an Enemy
- * 3. One-Hit KO on an Enemy
- * 4. Critical Hit on an Enemy
- *
- * Bonuses persist across battles, but is reset to empty if:
- * - Any party member is KO'd (reduced to 0 HP) for any reason.
- * - Any party member suffers a critical hit from an enemy.
- *
- * -----------------------------------------------------------------------------
- * BONUS BOARD EFFECTS
- * -----------------------------------------------------------------------------
- * After victory, for each filled slot, post-battle effects will activate.
- *
- * - Physical KO: Heal each living party member for 2% max HP per slot.
- * - Magical KO: Heal each living party member for 2% max MP per slot.
- * - One-Hit KO: Increase party's total EXP reward by 10% per slot.
- * - Critical Hit: Increase party's total Gold reward by 10% per slot.
- *
- * -----------------------------------------------------------------------------
- * OTHER FEATURES
- * -----------------------------------------------------------------------------
- * A custom animation will play on the party when a slot is filled, or when the
- * gauge is forcefully reset by KO or critical hit.
- *
- * You can use a blank Animation if you don't want to use this feature of
- * the plugin, but the plugin parameter must be set to an Animation.
- *
- * -----------------------------------------------------------------------------
- * COMMANDS
- * -----------------------------------------------------------------------------
- * The Bonus Board can be manually reset via the following:
- *
- * Plugin Command: ResetBonusBoard
- * Script Call: $gameSystem.clearBonusBoard();
- *
- * -----------------------------------------------------------------------------
- * TERMS OF USE
- * -----------------------------------------------------------------------------
- * It is OK to use this plugin in both commercial and non-commercial projects.
- *
- * Credit is appreciated, but not required. Happy game making!
- *
- * -----------------------------------------------------------------------------
- * VERSION & UPDATE HISTORY
- * -----------------------------------------------------------------------------
- * > v1.02 : Fixed bug related to HP restoration (incorrectly set to 1%)
- * > September 22, 2025
- *
- * > v1.01 : Fixed bug related to EXP and Gold gain bonuses
- * > September 22, 2025
- *
- * > v1.00 : Initial Release
- * > September 21, 2025
- */
- (function() {
- var pluginName = document.currentScript.src.match(/([^\/]+)\.js$/)[1];
- var parameters = PluginManager.parameters(pluginName);
- function paramInt(name, def) { return Number(parameters[name] || def); }
- var ICON_EMPTY = paramInt('Empty Icon ID', 16);
- var ICON_REWARD1 = paramInt('Reward 1 Icon ID', 64);
- var ICON_REWARD2 = paramInt('Reward 2 Icon ID', 65);
- var ICON_REWARD3 = paramInt('Reward 3 Icon ID', 66);
- var ICON_REWARD4 = paramInt('Reward 4 Icon ID', 67);
- var SLOT_FILL_ANIMATION = paramInt('Slot Fill Animation ID', 0);
- var RESET_ANIMATION = paramInt('Reset Animation ID', 0);
- var WINDOW_X = paramInt('Window X', -1);
- var WINDOW_Y = paramInt('Window Y', 0);
- var SLOTS = 15;
- var ICONS_REWARD = [0, ICON_REWARD1, ICON_REWARD2, ICON_REWARD3, ICON_REWARD4];
- Game_System.prototype.initBonusBoard = function() {
- if (!this._bonusBoard) {
- this._bonusBoard = [];
- for (var i = 0; i < SLOTS; i++) this._bonusBoard[i] = 0;
- }
- };
- Game_System.prototype.bonusBoard = function() {
- this.initBonusBoard();
- return this._bonusBoard;
- };
- Game_System.prototype.setBonusBoard = function(gauge) {
- this._bonusBoard = gauge.slice();
- };
- Game_System.prototype.addRewardSlot = function(type) {
- if (type < 1 || type > 4) return -1;
- var gauge = this.bonusBoard();
- for (var i = 0; i < SLOTS; i++) {
- if (gauge[i] === 0) {
- gauge[i] = type;
- return i;
- }
- }
- return -1;
- };
- Game_System.prototype.countRewardSlots = function(type) {
- return this.bonusBoard().filter(function(x) { return x === type; }).length;
- };
- Game_System.prototype.clearBonusBoard = function() {
- for (var i = 0; i < SLOTS; i++) this._bonusBoard[i] = 0;
- };
- BattleManager.initBonusBoard = function() {
- $gameSystem.initBonusBoard();
- };
- BattleManager.bonusBoard = function() {
- return $gameSystem.bonusBoard();
- };
- BattleManager.addRewardSlot = function(type) {
- var slotIndex = $gameSystem.addRewardSlot(type);
- if (slotIndex >= 0) {
- SceneManager._scene && SceneManager._scene._bonusBoardWindow && SceneManager._scene._bonusBoardWindow.refresh();
- if (SLOT_FILL_ANIMATION > 0 && SceneManager._scene && SceneManager._scene.isBattleActive && SceneManager._scene.isBattleActive()) {
- Scene_Battle.playAnimOnParty(SLOT_FILL_ANIMATION);
- }
- }
- };
- BattleManager.clearBonusBoard = function() {
- $gameSystem.clearBonusBoard();
- SceneManager._scene && SceneManager._scene._bonusBoardWindow && SceneManager._scene._bonusBoardWindow.refresh();
- };
- function Window_BonusBoard() { this.initialize.apply(this, arguments); }
- Window_BonusBoard.prototype = Object.create(Window_Base.prototype);
- Window_BonusBoard.prototype.constructor = Window_BonusBoard;
- Window_BonusBoard.prototype.initialize = function() {
- var width = 36 * SLOTS + this.standardPadding() * 2;
- var height = this.fittingHeight(1);
- Window_Base.prototype.initialize.call(this, 0, 0, width, height);
- this.openness = 255;
- this.refresh();
- };
- Window_BonusBoard.prototype.refresh = function() {
- this.contents.clear();
- var gauge = $gameSystem.bonusBoard();
- for (var i = 0; i < SLOTS; i++) {
- var iconIndex = gauge[i] ? ICONS_REWARD[gauge[i]] : ICON_EMPTY;
- this.drawIcon(iconIndex, i * 36, 0);
- }
- };
- var _Scene_Battle_createAllWindows = Scene_Battle.prototype.createAllWindows;
- Scene_Battle.prototype.createAllWindows = function() {
- _Scene_Battle_createAllWindows.apply(this, arguments);
- this.createBonusBoardWindow();
- };
- Scene_Battle.prototype.createBonusBoardWindow = function() {
- this._bonusBoardWindow = new Window_BonusBoard();
- if (WINDOW_X >= 0) {
- this._bonusBoardWindow.x = WINDOW_X;
- } else {
- this._bonusBoardWindow.x = (Graphics.boxWidth - this._bonusBoardWindow.width) / 2;
- }
- this._bonusBoardWindow.y = WINDOW_Y;
- this._windowLayer.addChild(this._bonusBoardWindow);
- };
- Scene_Battle.playAnimOnParty = function(animId) {
- if (!animId) return;
- var sprites = SceneManager._scene && SceneManager._scene._spriteset ? SceneManager._scene._spriteset.battlerSprites() : [];
- var actors = $gameParty.battleMembers();
- actors.forEach(function(actor) {
- var sprite = sprites.find(function(spr) { return spr._battler === actor; });
- if (sprite) sprite.startAnimation($dataAnimations[animId], false, 0);
- });
- };
- Scene_Battle.prototype.isBattleActive = function() {
- return !!this._spriteset && !!this._bonusBoardWindow;
- };
- var _Game_Enemy_initMembers = Game_Enemy.prototype.initMembers;
- Game_Enemy.prototype.initMembers = function() {
- _Game_Enemy_initMembers.apply(this, arguments);
- this._hpBeforeAction = this.hp;
- this._wasAliveBeforeAction = this.isAlive();
- };
- var _BattleManager_startAction = BattleManager.startAction;
- BattleManager.startAction = function() {
- $gameTroop.members().forEach(function(enemy) {
- enemy._hpBeforeAction = enemy.hp;
- enemy._wasAliveBeforeAction = enemy.isAlive();
- });
- _BattleManager_startAction.apply(this, arguments);
- };
- var _Game_Action_apply = Game_Action.prototype.apply;
- Game_Action.prototype.apply = function(target) {
- _Game_Action_apply.apply(this, arguments);
- if (target.isEnemy() && $gameParty.inBattle()) {
- var result = target.result();
- if (result && result.critical) {
- BattleManager.addRewardSlot(4);
- }
- }
- if (target.isActor() && this.subject() && this.subject().isEnemy()) {
- var result = target.result();
- if (result && result.critical && $gameParty.inBattle()) {
- var anyFilled = $gameSystem.bonusBoard().some(function(x){return x > 0;});
- if (anyFilled) {
- BattleManager.clearBonusBoard();
- if (RESET_ANIMATION > 0 && SceneManager._scene && SceneManager._scene.isBattleActive && SceneManager._scene.isBattleActive()) {
- Scene_Battle.playAnimOnParty(RESET_ANIMATION);
- }
- }
- }
- }
- };
- var _Game_Actor_die = Game_Actor.prototype.die;
- Game_Actor.prototype.die = function() {
- var wasAlive = this.isAlive();
- _Game_Actor_die.apply(this, arguments);
- if (wasAlive && !$gameParty.inBattle()) return;
- if (wasAlive && $gameParty.inBattle()) {
- var anyFilled = $gameSystem.bonusBoard().some(function(x){return x > 0;});
- if (anyFilled) {
- BattleManager.clearBonusBoard();
- if (RESET_ANIMATION > 0 && SceneManager._scene && SceneManager._scene.isBattleActive && SceneManager._scene.isBattleActive()) {
- Scene_Battle.playAnimOnParty(RESET_ANIMATION);
- }
- }
- }
- };
- var _Game_Enemy_performCollapse = Game_Enemy.prototype.performCollapse;
- Game_Enemy.prototype.performCollapse = function() {
- if (BattleManager._subject && this._wasAliveBeforeAction) {
- var action = BattleManager._action;
- var isPhysical = action && action.isPhysical();
- var isMagical = action && action.isMagical();
- var wasFullHP = this._hpBeforeAction === this.mhp;
- var isOHKO = wasFullHP;
- if (action && isPhysical) {
- BattleManager.addRewardSlot(1);
- }
- if (action && isMagical) {
- BattleManager.addRewardSlot(2);
- }
- if (action && isOHKO) {
- BattleManager.addRewardSlot(3);
- }
- }
- _Game_Enemy_performCollapse.apply(this, arguments);
- };
- var _BattleManager__rewardsExp = BattleManager._rewardsExp;
- BattleManager._rewardsExp = function() {
- var baseExp = $gameTroop.expTotal();
- var bonus = $gameSystem.countRewardSlots(3) * 0.10;
- return Math.floor(baseExp * (1 + bonus));
- };
- var _BattleManager__rewardsGold = BattleManager._rewardsGold;
- BattleManager._rewardsGold = function() {
- var baseGold = $gameTroop.goldTotal();
- var bonus = $gameSystem.countRewardSlots(4) * 0.10;
- return Math.floor(baseGold * (1 + bonus));
- };
- BattleManager.gainRewards = function() {
- var count1 = $gameSystem.countRewardSlots(1);
- var count2 = $gameSystem.countRewardSlots(2);
- if (count1 > 0) {
- $gameParty.aliveMembers().forEach(function(actor) {
- var healAmount = Math.floor(actor.mhp * 0.02 * count1);
- if (healAmount > 0) actor.gainHp(healAmount);
- });
- }
- if (count2 > 0) {
- $gameParty.aliveMembers().forEach(function(actor) {
- var healAmount = Math.floor(actor.mmp * 0.02 * count2);
- if (healAmount > 0) actor.gainMp(healAmount);
- });
- }
- var exp = this._rewardsExp();
- var gold = this._rewardsGold();
- $gameParty.allMembers().forEach(function(actor) {
- actor.gainExp(exp, false);
- });
- $gameParty.gainGold(gold);
- $gameTroop.makeDropItems().forEach(function(item) {
- $gameParty.gainItem(item, 1);
- });
- };
- var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
- Game_Interpreter.prototype.pluginCommand = function(command, args) {
- _Game_Interpreter_pluginCommand.apply(this, arguments);
- if (command.toLowerCase() === 'resetbonusboard') {
- $gameSystem.clearBonusBoard();
- if (SceneManager._scene && SceneManager._scene._bonusBoardWindow) {
- SceneManager._scene._bonusBoardWindow.refresh();
- }
- }
- };
- var _DataManager_createGameObjects2 = DataManager.createGameObjects;
- DataManager.createGameObjects = function() {
- _DataManager_createGameObjects2.apply(this, arguments);
- $gameSystem.initBonusBoard();
- };
- })();
Add Comment
Please, Sign In to add comment