//=============================================================================
// BulletHell.js
//=============================================================================
/*:
@plugindesc Simple Bullet hell shoot 'em up engine.
@author Hash'ak'Gik
@param config
@desc Configuration file (in data).
@default BulletHell.json
@param resume
@desc Resume string.
@default Resume
@param retry
@desc Retry string.
@default Retry
@param deadzone
@desc Deadzone string.
@default Analog deadzone
@param speed_multiplier
@desc Speed multiplier string for analog sticks.
@default Analog scale
@param quit
@desc Quit string.
@default Quit
@param yes
@desc Yes string.
@default Yes
@param no
@desc No string.
@default No
@param speed
@desc Speed string.
@default Speed
@param rate
@desc Rate of fire string.
@default Rate
@param power
@desc Power string.
@default Power
@param bombs
@desc Bombs string.
@default Bombs
@param buy_players
@desc Buy new players string.
@default Players
@param buy_upgrade
@desc Buy upgrades string.
@default Upgrades
@param init_bgm
@desc BGM played during the player selection.
@default null
@param victory_me
@desc ME played on victory.
@default Victory1
@param bullet
@desc Default bullet sprite.
@default $Bullets
@param explosion
@desc Default explosion sprite.
@default $Explosions
@param grazing_score
@desc Bonus points awarded for grazing (a bullet moves close to the player, but doesn't hit it).
@default 50
@param bullet_timeout
@desc Timeout in frames after which the enemy bullets are destroyed while the player is dead.
@default 300
@param immortal_timeout
@desc Timeout in frames during which the player is immortal after a respawn.
@default 300
@param life_bonus_first
@desc Number of points required for the first life bonus.
@default 30000
@param life_bonus_next
@desc Number of points required for the following life bonuses.
@default 80000
@param DCprice
@desc Money required to buy a D -> C upgrade.
@default 5000
@param CBprice
@desc Money required to buy a C -> B upgrade.
@default 10000
@param BAprice
@desc Money required to buy a B -> A upgrade.
@default 50000
@param ASprice
@desc Money required to buy an A -> S upgrade.
@default 100000
@param warning_img
@desc Picture for the warning sign. NOTE: It's a PICTURE, not a charset.
@default
@param warning_duration
@desc Length of warning animation.
@default 120
@param warning_se
@desc Sound effect for warning.
@default
@help
Plugin commands:
- Play a stage:
Bullethell mapId [retry [quit]]
For example:
Bullethell 2: starts a stage on map 2 with retry and quit options enabled,
Bullethell 5 false: starts a stage on map 5 with retry disabled and quit enabled,
Bullethell 11 true false: starts a stage on map 11 with retry enabled and quit disabled.
- Lock a player:
Bullethell lock playerId
For example:
Bullethell lock 2: The third player defined on the JSON can no longer be used. Note: at least one player must be enabled, so the plugin will prevent locking a player if there aren't any more left.
- Unlock a player:
Bullethell unlock playerId
For example:
Bullethell unlock 5: The sixth player defined on the JSON can be used.
- Enable a player purchase:
Bullethell canbuy playerId
For example:
Bullethell canbuy 3: The fourth player defined on the JSON can be purchased from now on.
- Disable a player purchase:
Bullethell cannotbuy playerId
For example:
Bullethell canbuy 3: The fourth player defined on the JSON can no longer be bought.
- Open the powerup shop:
Bullethell shop
*/
/**
* Stores the stage's results.
* @typedef $gameBHellResult
* @type {Object}
* @property {boolean} won True if the player has won.
* @property {boolean} gaveUp True if the player gave up.
* @property {number} retries Number of retries for the current stage.
* @property {number} score Final score (reset at each retry).
* @property {number} hitRatio % of bullets hitting a target (reset at each retry).
* @property {number} enemiesKilled Number of enemies killed (reset at each retry).
* @property {number} enemiesMissed Number of enemies escaped (reset at each retry).
* @property {number} enemiesCrashed Number of enemies crashed against the player (reset at each retry).
* @property {number} livesLost Number of lives lost (cumulated for all retries).
* @property {number} bombsUsed Number of bombs used (cumulated for all retries).
*/
var $gameBHellResult;
/**
* Stores the players' settings in $gamePlayer (which is persistently serialised in save files).
*
* Note: ranks are stored as letters: D (worst), C, B, A and S (best).
*
* @typedef bhellPlayers
* @type {Array}
* @property {number} index The player index in the JSON file.
* @property {boolean} unlocked True if the player can be used.
* @property {boolean} canBeBought True if the player can be bought at the shop.
* @property {number} price Shop price for the player.
* @property {string} speed Current speed rank (how fast the player can move).
* @property {string} rate Current rate of fire rank (how fast bullets are shot).
* @property {string} power Current power rank (how strong the emitters are).
* @property {string} bombs Current bomb rank (how many bombs can be stored).
*/
/**
* Stores the controller's speed multiplier setting in $gameSystem (which is persistently serialised in save files).
* When moving the player using a controller, the actual speed will be scaled by this value.
*
* @typedef controllerSpeedMultiplier
* @type {Number}
*/
/**
* Stores the controller's deadzone setting in $gameSystem (which is persistently serialised in save files).
*
* Note: this value is not used outside the Bullet Hell engine and therefore does not interfere with the normal Input
* class' (rpg_core.js) behaviour.
*
* @typedef deadzone
* @type {Number}
*/
/**
* @namespace BHell
*/
var BHell = (function (my) {
var parameters = PluginManager.parameters('BulletHell');
var BHellJSON = String(parameters['config'] || "BulletHell.json");
my.initBgm = null;
if (String(parameters['init_bgm']) !== "null") {
my.initBgm = {name: String(parameters['init_bgm']), volume: 90, pitch: 100, pan: 0};
}
my.victoryMe = null;
if (String(parameters['victory_me']) !== "null") {
my.victoryMe = {name: String(parameters['victory_me']), volume: 90, pitch: 100, pan: 0};
}
my.defaultBullet = String(parameters['bullet'] || "$Bullets");
my.defaultExplosion = String(parameters['explosion'] || "$Explosions");
my.resume = String(parameters['resume'] || "Resume");
my.retry = String(parameters['retry'] || "Retry");
my.deadzone = String(parameters['deadzone'] || "Analog deadzone");
my.speedMul = String(parameters['speed_multiplier'] || "Analog scale");
my.quit = String(parameters['quit'] || "Quit");
my.yes = String(parameters['yes'] || "Yes");
my.no = String(parameters['no'] || "No");
my.speed = String(parameters['speed'] || "Speed");
my.rate = String(parameters['rate'] || "Rate");
my.power = String(parameters['power'] || "Power");
my.bombs = String(parameters['bombs'] || "Bombs");
my.buyPlayers = String(parameters['buy_players'] || "Players");
my.buyUpgrades = String(parameters['buy_upgrades'] || "Upgrades");
my.grazingScore = Number(parameters['grazing_score'] || 50);
my.bulletTimeout = Number(parameters['bullet_timeout'] || 300);
my.immortalTimeout = Number(parameters['immortal_timeout'] || 300);
my.lifeBonusFirst = Number(parameters['life_bonus_first'] || 30000);
my.lifeBonusNext = Number(parameters['life_bonus_next'] || 80000);
my.dcPrice = Number(parameters['DCprice'] || 5000);
my.cbPrice = Number(parameters['CBprice'] || 10000);
my.baPrice = Number(parameters['BAprice'] || 50000);
my.asPrice = Number(parameters['ASprice'] || 100000);
my.warningImg = String(parameters['warning_img'] || "");
my.warningDuration = Number(parameters['warning_duration'] || 120);
my.warningSE = String(parameters['warning_se'] || "");
// Override Scene_Boot.create()
var _Boot_create = Scene_Boot.prototype.create;
Scene_Boot.prototype.create = function () {
DataManager._databaseFiles.push({name: "$dataBulletHell", src: BHellJSON});
_Boot_create.call(this);
};
var _Game_Interpreter_pluginCommand =
Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
_Game_Interpreter_pluginCommand.call(this, command, args);
if (command === 'Bullethell') {
// Set the default value for the player's speed multiplier when using a controller.
$gameSystem.controllerSpeedMultiplier = $gameSystem.controllerSpeedMultiplier || 0.5;
// Set the default value for the controller's analog deadzone.
$gameSystem.controllerDeadzone = $gameSystem.controllerDeadzone || 0.25;
// If the players' settings aren't loaded yet, load them from the JSON.
$gamePlayer.bhellPlayers = $gamePlayer.bhellPlayers || [];
for (var i = 0; i < $dataBulletHell.players.length; i++)
{
$gamePlayer.bhellPlayers[i] = $gamePlayer.bhellPlayers[i] || {};
$gamePlayer.bhellPlayers[i].index = i;
if ($gamePlayer.bhellPlayers[i].unlocked === undefined) {
$gamePlayer.bhellPlayers[i].unlocked = $gamePlayer.bhellPlayers[i].unlocked || $dataBulletHell.players[i].unlocked || false;
}
if ($gamePlayer.bhellPlayers[i].canBeBought !== false) {
$gamePlayer.bhellPlayers[i].canBeBought = $gamePlayer.bhellPlayers[i].canBeBought || $dataBulletHell.players[i].can_be_bought;
}
$gamePlayer.bhellPlayers[i].price = $gamePlayer.bhellPlayers[i].price || $dataBulletHell.players[i].price || 50000;
$gamePlayer.bhellPlayers[i].speed = $gamePlayer.bhellPlayers[i].speed || $dataBulletHell.players[i].speed || 1;
$gamePlayer.bhellPlayers[i].rate = $gamePlayer.bhellPlayers[i].rate || $dataBulletHell.players[i].rate || 1;
$gamePlayer.bhellPlayers[i].power = $gamePlayer.bhellPlayers[i].power || $dataBulletHell.players[i].power || 1;
$gamePlayer.bhellPlayers[i].bombs = $gamePlayer.bhellPlayers[i].bombs || $dataBulletHell.players[i].bombs || 1;
}
switch (args[0]) {
case "lock":
if ($gamePlayer.bhellPlayers.filter(p => {
return p.unlocked === true;
}).length > 1) {
if (Number(args[1]) >= 0 && Number(args[1]) < $gamePlayer.bhellPlayers.length) {
$gamePlayer.bhellPlayers[Number(args[1])].unlocked = false;
}
}
break;
case "unlock":
if (Number(args[1]) >= 0 && Number(args[1]) < $gamePlayer.bhellPlayers.length) {
$gamePlayer.bhellPlayers[Number(args[1])].unlocked = true;
}
break;
case "canbuy":
if (Number(args[1]) >= 0 && Number(args[1]) < $gamePlayer.bhellPlayers.length) {
$gamePlayer.bhellPlayers[Number(args[1])].canBeBought = true;
}
break;
case "cannotbuy":
if (Number(args[1]) >= 0 && Number(args[1]) < $gamePlayer.bhellPlayers.length) {
$gamePlayer.bhellPlayers[Number(args[1])].canBeBought = false;
}
break;
case "shop":
$gameBHellResult = {};
$gameBHellResult.retries = 0;
$gameBHellResult.livesLost = 0;
$gameBHellResult.bombsUsed = 0;
$gameBHellResult.hitRatio = 0;
$gameBHellResult.enemiesKilled = 0;
$gameBHellResult.enemiesMissed = 0;
$gameBHellResult.enemiesCrashed = 0;
$gameBHellResult.score = 0;
$gameBHellResult.gaveUp = false;
$gameBHellResult.won = false;
SceneManager.push(my.Scene_BHell_Shop);
break;
default:
if (Number(args[0]) >= 0) {
{
$gameBHellResult = {};
$gameBHellResult.retries = 0;
$gameBHellResult.livesLost = 0;
$gameBHellResult.bombsUsed = 0;
$gameBHellResult.hitRatio = 0;
$gameBHellResult.enemiesKilled = 0;
$gameBHellResult.enemiesMissed = 0;
$gameBHellResult.enemiesCrashed = 0;
$gameBHellResult.score = 0;
$gameBHellResult.gaveUp = false;
$gameBHellResult.won = false;
my.map = Number(args[0]);
my.canRetry = true;
my.canQuit = true;
if (args[1] != null) {
my.canRetry = args[1] !== "false";
}
if (args[2] != null) {
my.canQuit = args[2] !== "false";
}
SceneManager.push(my.Scene_BHell_Init);
}
break;
}
}
}
};
// Rewrite Input._updateGamepadState to include axes informations and whether the last input came from a gamepad or the keyboard.
Input._updateGamepadState = function(gamepad) {
var lastState = this._gamepadStates[gamepad.index] || [];
var newState = [];
var buttons = gamepad.buttons;
var axes = gamepad.axes;
var threshold = 0.5;
newState[12] = false;
newState[13] = false;
newState[14] = false;
newState[15] = false;
for (var i = 0; i < buttons.length; i++) {
newState[i] = buttons[i].pressed;
}
if (axes[1] < -threshold) {
newState[12] = true; // up
} else if (axes[1] > threshold) {
newState[13] = true; // down
}
if (axes[0] < -threshold) {
newState[14] = true; // left
} else if (axes[0] > threshold) {
newState[15] = true; // right
}
for (var j = 0; j < newState.length; j++) {
if (newState[j] !== lastState[j]) {
var buttonName = this.gamepadMapper[j];
if (buttonName) {
this._currentState[buttonName] = newState[j];
}
}
}
this._gamepadStates[gamepad.index] = newState;
this._axes = gamepad.axes;
this._lastInputIsGamepad = newState.filter(b => {return b === true;}).length > 0;
};
// Rewrite Input._onKeyDown to include whether the last input came from a gamepad or the keyboard.
Input._onKeyDown = function(event) {
if (this._shouldPreventDefault(event.keyCode)) {
event.preventDefault();
}
if (event.keyCode === 144) { // Numlock
this.clear();
}
var buttonName = this.keyMapper[event.keyCode];
if (ResourceHandler.exists() && buttonName === 'ok') {
ResourceHandler.retry();
} else if (buttonName) {
this._currentState[buttonName] = true;
}
this._lastInputIsGamepad = false;
};
// Checks where the last input came from.
Input.isLastInputGamepad = function() {
return !!this._lastInputIsGamepad;
};
// Returns the value for a given axis. If the value is below the deadzone it returns 0.
Input.readAxis = function(axis, deadzone = 0.20) {
var ret = 0;
if (this._axes && Math.abs(this._axes[axis]) >= deadzone) {
ret = this._axes[axis];
}
return ret;
};
var _ti_onTouchMove = TouchInput._onTouchMove;
TouchInput._onTouchMove = function(event) {
var oldX = this._x;
var oldY = this._y;
_ti_onTouchMove.call(this, event);
this._dx = this._x - oldX;
this._dy = this._y - oldY;
};
TouchInput.isLastInputTouch = function() {
return this._screenPressed;
};
Object.defineProperty(TouchInput, 'dx', {
get: function() {
return this._dx;
},
configurable: true
});
Object.defineProperty(TouchInput, 'dy', {
get: function() {
return this._dy;
},
configurable: true
});
return my;
}(BHell || {}));