556 lines
16 KiB
JavaScript
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;
|
|
};
|
|
})();
|