ultimate-angel-zerachiel/www/js/plugins/ChainCommand.js
2024-01-17 11:38:37 -06:00

556 lines
16 KiB
JavaScript

//==============================================================================
// ChainCommand.js
//==============================================================================
var Imported = Imported || {};
Imported.ChainCommand = true;
/*:
* @plugindesc Everyone loves quicktime events.
* @author mjshi
*
* @param ---Configuration---
*
* @param Valid Keys
* @desc Separate with spaces. (see help for more info)
* @default up down left right ok cancel
*
* @param Default Switch ID
* @desc The switch to turn ON if the player succeeds at the minigame, and OFF if the player fails.
* @default 1
*
* @param Default Time Given
* @desc Default total time to give the player, in frames.
* 60 frames = 1 second.
* @default 360
*
* @param Time Per Key
* @desc Used in automatic time calculations. (see help for more info)
* 60 frames = 1 second.
* @default 30
*
* @param Exit Pause Time
* @desc How long to show the success/failure image for. Set to 0 to not show anything. 60 frames = 1 second.
* @default 45
*
* @param ---Sound Effects----
*
* @param Keypress SFX
* @desc The sound to play when a correct button is pressed.
* @default Cursor2
*
* @param Success SFX
* @desc The sound to play when the sequence is complete.
* @default Heal3
*
* @param Error SFX
* @desc The sound to play when an incorrect button is pressed.
* @default Blind
*
* @param ---Timer Bar----
*
* @param Bar BG X Position
* @desc X position of the bar background. (bar_empty.png)
* @default 285
*
* @param Bar BG Y Position
* @desc Y position of the bar background. (bar_empty.png)
* @default 245
*
* @param Meter X Shift
* @desc X position of the meter relative to Bar BG's X position. (bar_full.png)
* @default 5
*
* @param Meter Y Shift
* @desc Y position of the meter relative to Bar BG's Y position. (bar_full.png)
* @default 5
*
* @param Meter Width
* @desc Width of the meter image. (bar_full.png)
* @default 236
*
* @param Meter Height
* @desc Height of the meter image. (bar_full.png)
* @default 7
*
* @param ---Buttons----
*
* @param Button X Shift
* @desc X position of the button relative to the center.
* @default 0
*
* @param Button Y Shift
* @desc Y position of the button relative to the center.
* @default 0
*
* @param Button Width
* @desc Width of the button images.
* @default 31
*
* @param Button Height
* @desc Height of the button images.
* @default 31
*
* @param Button Spacing
* @desc Spacing between buttons in a sequence.
* @default 15
*
* @param ---Cursor----
*
* @param Cursor X Shift
* @desc X position of the cursor relative to the center button's X position.
* @default 5
*
* @param Cursor Y Shift
* @desc Y position of the cursor relative to the center button's Y position.
* @default 40
*
* @param ---SFX Customization---
* @desc **Thanks to JamesRyan on rpgmakerweb for adding these!
* @default **
*
* @param Keypress Volume
* @desc Volume of Keypress SFX.
* @default 100
*
* @param Keypress Pitch
* @desc Pitch of Keypress SFX.
* @default 100
*
* @param Keypress Pan
* @desc Pan of Keypress SFX.
* @default 0
*
* @param Success Volume
* @desc Volume of Success SFX.
* @default 100
*
* @param Success Pitch
* @desc Pitch of Success SFX.
* @default 100
*
* @param Success Pan
* @desc Pan of Success SFX.
* @default 0
*
* @param Error Volume
* @desc Volume of Error SFX.
* @default 100
*
* @param Error Pitch
* @desc Pitch of Error SFX.
* @default 100
*
* @param Error Pan
* @desc Pan of Error SFX.
* @default 0
*
* @param
* @help
* ------------------------------------------------------------------------------
* Chain Commands v1.1b by mjshi
* Free for both commercial and non-commercial use, with credit.
* ------------------------------------------------------------------------------
* Installation: Extract the included folder to the img/ directory.
*
* There are some additional files in the img/chaincmd/templates folder that
* you can either delete or use for whatever you want.
* ------------------------------------------------------------------------------
* Running the Minigame
* ------------------------------------------------------------------------------
* The minigame runs via plugin command.
* ChainCommand sequence
* ChainCommand time sequence
* ChainCommand time switch sequence
*
* For example:
* ChainCommand x,z,left,right,x,x,z
* ChainCommand auto x,z,left,right,x,x,z
* ChainCommand 240 1 x,z,left,right,x,x,z
* ------------------------------------------------------------------------------
* 'sequence' is composed of:
* up down left right ok cancel
* Since 'ok' and 'cancel' are kind of strange to type so they can also be
* replaced with z and x, respectively.
*
* Separate each key in the sequence with a comma (no space). For example:
* ChainCommand z,x,up,left,right,x
* Because of the way MV maps keys Z can also be triggered with the spacebar
* or enter key, and X can also be triggered by ESC or numpad 0 or backspace.
*
* You can also put random:X here to generate a random sequence composed of X
* keys.
* ------------------------------------------------------------------------------
* 'time' is the amount of time in frames. 60 frames = 1 second. You can also
* put auto here if you want the time to be calculated with the Time Per Key
* parameter. Omit it if you want to use the default time.
* ------------------------------------------------------------------------------
* 'switch' is the switch to turn ON or OFF based on whether or not the
* player successfully punched in the sequence. Omit it if you want to use the
* default switch.
*
* ------------------------------------------------------------------------------
* Extra PluginCommand Functions
* ------------------------------------------------------------------------------
* "Remembering" sequences:
* ChainCommand remember trigger time switch sequence
* "Recalling" sequences:
* ChainCommand recall trigger
*
* 'trigger' is the keyword used for recalling sequences. The other three
* parameters are set as per normal.
*
* For example:
* ChainCommand remember treasure 240 1 x,z,left,right,x,x,z
* would remember the specific chain command that lasts for 240 frames, turns
* on switch 1, and has the sequence x,z,left,right,x,x,z
*
* Then, calling
* ChainCommand recall treasure
* would launch Chain Commands with the trigger's saved parameters.
*
* ------------------------------------------------------------------------------
* Changing The Background
* ------------------------------------------------------------------------------
* In a script command, set ChainCommand.bgImage to your desired background
* image name:
* ChainCommand.bgImage = "bg";
*
* ------------------------------------------------------------------------------
* Adding Keys
* ------------------------------------------------------------------------------
* You can add additional valid keys through the use of other keymapping
* plugins. Preferably, ones that modify the original keymapper rather than
* replacing it with a new system or new functions.
*
* A good one is ZE's Key Mapper:
* http://mvplugins.com/plugin/Zalerinian/ZE%20-%20Key%20Mapper
*
* ------------------------------------------------------------------------------
*
* > Is something broken? Go to http://mjshi.weebly.com/contact.html and I'll
* try my best to help you!
*/
function Scene_ChainCommand() {
this.initialize.apply(this, arguments);
}
var ChainCommand = ChainCommand || {};
ChainCommand.memory = [];
ChainCommand.bgImage = "bg";
(function () {
var params = PluginManager.parameters("ChainCommand");
var defaultSwitch = getN("Default Switch ID") || 1;
var defaultTime = getN("Default Time Given") || 360;
var timePerKey = getN("Time Per Key") || 35;
var pauseTime = getN("Exit Pause Time");
function getN(str) {
return parseInt(params[str]);
}
var backBar = {
x: getN("Bar BG X Position"),
y: getN("Bar BG Y Position"),
};
var frontBar = {
shiftX: getN("Meter X Shift"),
shiftY: getN("Meter Y Shift"),
width: getN("Meter Width"),
height: getN("Meter Height"),
};
var button = {
shiftX: getN("Button X Shift"),
shiftY: getN("Button Y Shift"),
width: getN("Button Width"),
height: getN("Button Height"),
spacing: getN("Button Spacing"),
};
var cursor = {
shiftX: getN("Cursor X Shift"),
shiftY: getN("Cursor Y Shift"),
};
var soundFX = {
keypress: {
name: params["Keypress SFX"],
pan: params["Keypress Pan"],
pitch: params["Keypress Pitch"],
volume: params["Keypress Volume"],
},
victory: {
name: params["Success SFX"],
pan: params["Success Pan"],
pitch: params["Success Pitch"],
volume: params["Success Volume"],
},
defeat: {
name: params["Error SFX"],
pan: params["Error Pan"],
pitch: params["Error Pitch"],
volume: params["Error Volume"],
},
};
var validKeys = params["Valid Keys"].split(" ");
//-----------------------------------------------------------------------------
// Scene_ChainCommand
//
Scene_ChainCommand.prototype = Object.create(Scene_Base.prototype);
Scene_ChainCommand.prototype.constructor = Scene_ChainCommand;
Scene_ChainCommand.prototype.create = function () {
Scene_Base.prototype.create.call(this);
this.createBackground();
this.createTimerBar();
this.createSequence();
};
Scene_ChainCommand.prototype.createBackground = function () {
this.addChild(new Sprite(SceneManager.backgroundBitmap()));
this.addChild(
new Sprite(ImageManager.loadBitmap("img/chaincmd/", ChainCommand.bgImage))
);
};
Scene_ChainCommand.prototype.createTimerBar = function () {
var back = new Sprite(
ImageManager.loadBitmap("img/chaincmd/", "bar_empty")
);
back.x = backBar.x;
back.y = backBar.y;
this.bar = new Sprite(ImageManager.loadBitmap("img/chaincmd/", "bar_full"));
this.bar.setFrame(0, 0, frontBar.width, frontBar.height);
this.bar.x = back.x + frontBar.shiftX;
this.bar.y = back.y + frontBar.shiftY;
this.addChild(back);
this.addChild(this.bar);
};
function parseSequence(string) {
var a = [];
var str = string.toLowerCase();
if (str.startsWith("random:")) {
var x = parseInt(str.split(":")[1]);
while (a.length < x)
a.push(validKeys[Math.floor(Math.random() * validKeys.length)]);
} else {
a = str.split(",");
for (var i = 0; i < a.length; i++) {
if (a[i] === "z") a[i] = "ok";
if (a[i] === "x") a[i] = "cancel";
}
}
return a;
}
Scene_ChainCommand.prototype.createSequence = function () {
this.sequence = parseSequence(ChainCommand.sequence);
this.buttons = [];
if (isNaN(ChainCommand.time))
ChainCommand.time = this.sequence.length * timePerKey;
var x = (Graphics.boxWidth - button.width) / 2 + button.shiftX;
var y = (Graphics.boxHeight - button.height) / 2 + button.shiftY;
//create button sequence
for (var i = 0; i < this.sequence.length; i++) {
this.buttons[i] = new Sprite(
ImageManager.loadBitmap("img/chaincmd/", this.sequence[i])
);
this.buttons[i].x = x;
this.buttons[i].y = y;
this.addChild(this.buttons[i]);
x += button.width + button.spacing;
}
this.index = 0;
this.failed = false;
//create pointer
this._cursor = new Sprite(
ImageManager.loadBitmap("img/chaincmd/", "cursor")
);
this._cursor.x = this.buttons[0].x + cursor.shiftX;
this._cursor.y = this.buttons[0].y + cursor.shiftY;
this.addChild(this._cursor);
};
Scene_ChainCommand.prototype.updateBar = function (fraction) {
this.bar.setFrame(0, 0, frontBar.width * fraction, frontBar.height);
};
Scene_ChainCommand.prototype.updateButtons = function () {
this.index++;
if (this.index > this.sequence.length - 1) return;
AudioManager.playSe(soundFX.keypress);
for (var i = 0; i < this.buttons.length; i++) {
this.buttons[i].x -= button.width + button.spacing;
if (i < this.index) this.buttons[i].opacity = 255 - (this.index - i) * 40;
}
};
Scene_ChainCommand.prototype.update = function () {
Scene_Base.prototype.update.call(this);
//update exit animation
if (this.ended) {
if (this.ended === true) this.ended = Graphics.frameCount;
if (Graphics.frameCount - this.ended > pauseTime) this.popScene();
return;
}
if (!this._startTime) this._startTime = Graphics.frameCount;
//update scene exit
var elapsed = Graphics.frameCount - this._startTime;
if (elapsed > ChainCommand.time) {
this.hasFailed();
return;
}
this.updateBar(1 - elapsed / ChainCommand.time);
this.processInput();
if (this.index == this.sequence.length) this.hasSucceeded();
};
Scene_ChainCommand.prototype.processInput = function () {
for (var i = 0; i < validKeys.length; i++) {
if (Input.isTriggered(validKeys[i])) {
if (this.sequence[this.index] === validKeys[i]) this.updateButtons();
else this.hasFailed();
return;
}
}
};
Scene_ChainCommand.prototype.hasFailed = function () {
$gameSwitches.setValue(ChainCommand.switch, false);
AudioManager.playSe(soundFX.defeat);
if (pauseTime == 0) {
this.popScene();
return;
}
this.addChild(
new Sprite(ImageManager.loadBitmap("img/chaincmd/", "failure"))
);
this.ended = true;
};
Scene_ChainCommand.prototype.hasSucceeded = function () {
$gameSwitches.setValue(ChainCommand.switch, true);
AudioManager.playSe(soundFX.victory);
if (pauseTime == 0) {
this.popScene();
return;
}
this.addChild(
new Sprite(ImageManager.loadBitmap("img/chaincmd/", "success"))
);
this.ended = true;
};
//-----------------------------------------------------------------------------
// ChainCommand Memory Functions
//
ChainCommand.remember = function (trigger, time, switch1, sequence) {
if (this.getFromMemory(trigger) < 0) {
this.memory.push([trigger, time, switch1, sequence]);
} else {
console.log(
"ChainCommand could not register '" +
trigger +
"' because it is already registered to a sequence!"
);
}
};
ChainCommand.recall = function (trigger) {
var index = ChainCommand.getFromMemory(trigger);
if (index < 0) return false;
var memory = this.memory[index];
this.time = memory[1];
this.switch = memory[2];
this.sequence = memory[3];
return true;
};
ChainCommand.getFromMemory = function (trigger) {
var index = -1;
for (var i = 0; i < this.memory.length; i++) {
if (this.memory[i][0] === trigger) {
index = i;
break;
}
}
return index;
};
//-----------------------------------------------------------------------------
// pluginCommand
//
var CCmd_Game_Interpreter_pluginCommand =
Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
CCmd_Game_Interpreter_pluginCommand.call(this, command, args);
if (command === "ChainCommand") {
//remember sequences
if (args[0] === "remember" && args.length === 5) {
ChainCommand.remember(args[1], args[2], args[3], args[4]);
return;
}
//recall sequences
if (args[0] === "recall" && args.length === 2) {
if (!ChainCommand.recall(args[1].trim())) return;
//parse sequences
} else {
ChainCommand.switch = defaultSwitch;
ChainCommand.time = defaultTime;
ChainCommand.sequence = args[args.length - 1];
if (args.length > 1) ChainCommand.time = parseInt(args[0]);
if (args.length > 2) ChainCommand.switch = parseInt(args[1]);
}
SceneManager.push(Scene_ChainCommand);
}
};
//-----------------------------------------------------------------------------
// Save Data
//
var alias_makeSaveContents = DataManager.makeSaveContents;
DataManager.makeSaveContents = function () {
contents = alias_makeSaveContents.call(this);
contents.chainCommandMemory = ChainCommand.memory;
return contents;
};
var alias_extractSaveContents = DataManager.extractSaveContents;
DataManager.extractSaveContents = function (contents) {
alias_extractSaveContents.call(this, contents);
ChainCommand.memory = contents.chainCommandMemory;
};
})();