Video

This plugin gives developers move control over the visual and mechanical aspects of the game’s timer system.

Timer Upgrade
Version 1.01
SumRndmDde

This plugin gives developers move control over the visual and mechanical
aspects of the game's timer system.

==============================================================================
Plugin Commands
==============================================================================

The following Plugin Commands can be used to manipulate the extra mechanics
of the upgraded timer:

SetTimer [frames] [seconds] [minutes] [hours]

Using this command, the frames, seconds, minutes, and hours can be set on the
game timer. This allows users to surpass the default settings for the MV
engine and specify the count down to frames.

For example, if you wish to set the timer to 3 minutes, you would do:
SetTimer 0 0 3 0

If you wished to set the timer to 30 frames and 60 seconds, do:
SetTimer 30 60 0 0

AddTimer [frames] [seconds] [minutes] [hours]

Using this command, frames, seconds, minutes, and hours can be added to the
game timer. Instead of replacing the timer value, this command adds to the
current value.

For example, if you wanted to add 5 minutes to the timer, you would do:
AddTimer 0 0 5 0

If you wanted to add 30 frames and 1 hour, you would do:
AddTimer 30 0 0 1

PauseTimer

Using this command, the timer can be paused. This keeps the timer at its
current position until unpaused or restarted.

UnpauseTimer

Using this command, the timer can be unpaused. This will let the timer
continue from when it was paused.

SetExpireCommonEvent [id]

Using this command, the expire Common Event can be set up. This is a Common
Event that will automatically play once the Timer ends. Once the Common
Event has been played, it will no longer be the expire Common Event.

SetTimerLabel [text]

This command allows you to change the timer label in the middle of the game.
Setting this to blank would remove the label.

==============================================================================
End of Help File
==============================================================================

Welcome to the bottom of the Help file.

Thanks for reading!
If you have questions, or if you enjoyed this Plugin, please check
out my YouTube channel!

https://www.youtube.com/c/SumRndmDde

Until next time,
~ SumRndmDde
var SRD = SRD || {};
SRD.TimerUpgrade = SRD.TimerUpgrade || {};
SRD.PluginCommands = SRD.PluginCommands || {};

var Imported = Imported || {};
Imported["SumRndmDde Timer Upgrade"] = 1.01;

(function(_, $) {

"use strict";

//-----------------------------------------------------------------------------
// SRD.TimerUpgrade
//-----------------------------------------------------------------------------

const params = PluginManager.parameters('SRD_TimerUpgrade');

_.format = String(params['Timer Format']);
_.pos = String(params['Timer Position']);
_.start = String(params['Timer Start SE']);
_.stop = String(params['Timer Expire SE']);
_.pauseColor = String(params['Pause Color']);
_.back = String(params['Use Background']).trim().toLowerCase() === 'true';

_.autoStop = String(params['Use Auto-Stop']).trim().toLowerCase() === 'true';
_.autoPause = String(params['Use Auto-Pause']).trim().toLowerCase() === 'true';
_.autoOpacity = parseInt(params['Auto-Pause Opacity']);
_.abort = String(params['Use Auto-Abort']).trim().toLowerCase() === 'true';

_.default = String(params['Default Label']);
_.labelSize = parseInt(params['Label Font Size']);

_.font = String(params['Timer Font']);
_.size = parseInt(params['Timer Font Size']);
_.italic = String(params['Timer Italic']).trim().toLowerCase() === 'true';
_.color = String(params['Timer Text Color']);
_.outline = String(params['Timer Outline Color']);

_.updateBooleans = function() {
	this.usesHours = !!(this.format.match(/%1/));
	this.usesMinutes = !!(this.format.match(/%2/));
	this.usesSeconds = !!(this.format.match(/%3/));
	this.usesFrames = !!(this.format.match(/%4/));
};

_.getLowestType = function() {
	if(this.usesFrames) return 0;
	else if(this.usesSeconds) return 1;
	else if(this.usesMinutes) return 2;
	return 3;
};

_.setupPosition = function() {
	this.vert = (!!this.pos.match(/top/i)) ? 0 : 1;
	if(!!this.pos.match(/-l/i)) {
		this.horz = -1;
	} else if(!!this.pos.match(/-r/i)) {
		this.horz = 1;
	} else {
		this.horz = 0;
	}
};

_.setupSoundEffects = function() {
	if(this.start) {
		const info = this.start.split(/\s*,\s*/);
		this.start = {
			name: info[0], 
			volume: parseInt(info[1]),
			pitch: parseInt(info[2]),
			pan: parseInt(info[3])
		}
	}
	if(this.stop) {
		const info = this.stop.split(/\s*,\s*/);
		this.stop = {
			name: info[0], 
			volume: parseInt(info[1]),
			pitch: parseInt(info[2]),
			pan: parseInt(info[3])
		}
	}
};

_.updateBooleans();
_.setupPosition();
_.setupSoundEffects();

//-----------------------------------------------------------------------------
// SRD.PluginCommands
//-----------------------------------------------------------------------------

$['settimer'] = function(args) {
	const v = $gameVariables._data;
	let result = eval(args[0]);
	if(args[1]) result += (eval(args[1]) * 60);
	if(args[2]) result += (eval(args[2]) * 60 * 60);
	if(args[3]) result += (eval(args[3]) * 60 * 60 * 60);
	$gameTimer.start(result);
};

$['addtimer'] = function(args) {
	const v = $gameVariables._data;
	let result = $gameTimer.getFrames();
	if(args[0]) result += (eval(args[0]));
	if(args[1]) result += (eval(args[1]) * 60);
	if(args[2]) result += (eval(args[2]) * 60 * 60);
	if(args[3]) result += (eval(args[3]) * 60 * 60 * 60);
	if(result < 0) result = 0;
	$gameTimer.start(result);
};

$['pausetimer'] = function(args) {
	$gameTimer.pause();
};

$['unpausetimer'] = function(args) {
	$gameTimer.unpause();
};

$['setexpirecommonevent'] = function(args) {
	$gameTimer.setExpireCommonEvent(parseInt(args[0]));
};

$['settimerlabel'] = function(args) {
	if(args.length === 0) {
		$gameTimer.setLabel('');
	} else {
		let text = '';
		for(let i = 0; i < args.length; i++) {
			text += String(args[i]) + " ";
		}
		$gameTimer.setLabel(text);
	}
};

//-----------------------------------------------------------------------------
// Game_Interpreter
//-----------------------------------------------------------------------------

if(!SRD.Game_Interpreter_pluginCommand) {

SRD.Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args) {
	const com = command.trim().toLowerCase();
	if($[com]) {
		$[com].call(this, args);
		return;
	}
	SRD.Game_Interpreter_pluginCommand.apply(this, arguments);
};

}

//-----------------------------------------------------------------------------
// Game_Timer
//-----------------------------------------------------------------------------

_.Game_Timer_initialize = Game_Timer.prototype.initialize;
Game_Timer.prototype.initialize = function() {
	_.Game_Timer_initialize.apply(this, arguments);
	this._onExpireCommonEvent = 0;
	this._isPaused = false;
	this._label = _.default;
};

_.Game_Timer_update = Game_Timer.prototype.update;
Game_Timer.prototype.update = function(sceneActive) {
	if(!this._isPaused && !this.isAutoPaused()) {
		_.Game_Timer_update.apply(this, arguments);
	}
};

Game_Timer.prototype.isAutoPaused = function() {
	return _.autoPause && $gameMap.isEventRunning() && SceneManager._scene.constructor === Scene_Map;
};

Game_Timer.prototype.getCount = function(type) {
	switch(type) {
		case 0: return this._frames;
		case 1: return Math.floor(this._frames / 60);
		case 2: return Math.floor(this._frames / (60 * 60));
		case 3: return Math.floor(this._frames / (60 * 60 * 60));
	}
};

Game_Timer.prototype.getLabel = function() {
	if(!this._label) return '';
	let text = this._label;
	text = text.replace(/\\V\[(\d+)\]/gi, function() {
		return $gameVariables.value(parseInt(arguments[1]));
	}.bind(this));
	return text;
};

Game_Timer.prototype.setLabel = function(label) {
	this._label = label;
};

_.Game_Timer_start = Game_Timer.prototype.start;
Game_Timer.prototype.start = function(count) {
	_.Game_Timer_start.apply(this, arguments);
	if(_.start) AudioManager.playSe(_.start);
	this.unpause();
};

_.Game_Timer_stop = Game_Timer.prototype.stop;
Game_Timer.prototype.stop = function(count) {
	_.Game_Timer_stop.apply(this, arguments);
	this.unpause();
};

Game_Timer.prototype.getFrames = function() {
	return this._frames;
};

Game_Timer.prototype.setExpireCommonEvent = function(id) {
	this._onExpireCommonEvent = id;
};

Game_Timer.prototype.onExpire = function() {
	if(_.abort) BattleManager.abort();
	if(_.stop) AudioManager.playSe(_.stop);
	this.playExpireCommonEvent();
	if(_.autoStop) this.stop();
};

Game_Timer.prototype.playExpireCommonEvent = function() {
	if(this._onExpireCommonEvent !== 0) {
		$gameTemp.reserveCommonEvent(this._onExpireCommonEvent);
		this._onExpireCommonEvent = 0;
	}
};

Game_Timer.prototype.pause = function() {
	this._isPaused = true;
};

Game_Timer.prototype.unpause = function() {
	this._isPaused = false;
};

Game_Timer.prototype.isPaused = function() {
	return this._isPaused;
};

//-----------------------------------------------------------------------------
// Scene_Base
//-----------------------------------------------------------------------------

Scene_Base.prototype.createTimer = Spriteset_Base.prototype.createTimer;

//-----------------------------------------------------------------------------
// Scene_Map
//-----------------------------------------------------------------------------

_.Scene_Map_createSpriteset = Scene_Map.prototype.createSpriteset;
Scene_Map.prototype.createSpriteset = function() {
    _.Scene_Map_createSpriteset.apply(this, arguments);
    this.createTimer()
};

//-----------------------------------------------------------------------------
// Scene_Battle
//-----------------------------------------------------------------------------

_.Scene_Battle_createSpriteset = Scene_Battle.prototype.createSpriteset;
Scene_Battle.prototype.createSpriteset = function() {
    _.Scene_Battle_createSpriteset.apply(this, arguments);
    this.createTimer();
};

//-----------------------------------------------------------------------------
// Spriteset_Base
//-----------------------------------------------------------------------------

Spriteset_Base.prototype.createTimer = function() {};

//-----------------------------------------------------------------------------
// Sprite_Timer
//-----------------------------------------------------------------------------

_.Sprite_Timer_initialize = Sprite_Timer.prototype.initialize;
Sprite_Timer.prototype.initialize = function() {
	this.initMembers();
	_.Sprite_Timer_initialize.apply(this, arguments);
	this.createBackground();
	this.createLabel();
	this.addChildren();
	this.redraw();
};

Sprite_Timer.prototype.initMembers = function() {
	this._lowestType = _.getLowestType();
	this._count = 0;
	this._paused = false;
	this._label = $gameTimer.getLabel();
};

Sprite_Timer.prototype.createBackground = function() {
	const width = this.numBitmap.width * (1.5);
	let height = this.numBitmap.height;
	if(this._label) height += _.labelSize + 16;
	this.background = new Sprite(new Bitmap(width, height));
	if(_.back) {
		if(_.horz) {
			this.background.bitmap.gradientFillRect(0, 0, width, height, 'rgba(0, 0, 0, 0)', 'rgba(0, 0, 0, 1)', false);
			this.background.scale.x = _.horz;
		} else {
			this.background.bitmap = new Bitmap(width * 2, height);
			this.background.bitmap.gradientFillRect(0, 0, width, height, 'rgba(0, 0, 0, 0)', 'rgba(0, 0, 0, 1)', false);
			this.background.bitmap.gradientFillRect(width, 0, width, height, 'rgba(0, 0, 0, 1)', 'rgba(0, 0, 0, 0)', false);
			this.background.anchor.x = 0.5;
		}
	}
};

Sprite_Timer.prototype.createLabel = function() {
	this.label = new Sprite(new Bitmap(this.numBitmap.width, _.labelSize + 16));
	this.label.bitmap.fontFace = _.font;
	this.label.bitmap.fontSize = _.labelSize;
	this.label.bitmap.fontItalic = _.italic;
	this.label.bitmap.textColor = _.color;
	this.label.bitmap.outlineColor = _.outline;
	this.refreshLabel();
};

Sprite_Timer.prototype.refreshLabel = function() {
	const bit = this.label.bitmap;
	bit.clear();
	if(this._label) {
		bit.drawText(this._label, 0, 0, bit.width, bit.height, 'center');
	}
};

Sprite_Timer.prototype.removeChildren = function() {
	this.removeChild(this.background);
	this.removeChild(this.numbers);
	this.removeChild(this.label);
};

Sprite_Timer.prototype.addChildren = function() {
	this.addChild(this.background);
	this.addChild(this.numbers);
	this.addChild(this.label);
};

Sprite_Timer.prototype.createBitmap = function() {
	const fontSize = _.size;
	const bitmap = new Bitmap(1, 1);
	bitmap.fontFace = _.font;
	bitmap.fontSize = fontSize;
	bitmap.fontItalic = _.italic;
	const newWidth = bitmap.measureTextWidth(this.timerText()) + 16;
	const newHeight = fontSize + 16;

	this.numbers = new Sprite(new Bitmap(newWidth, newHeight));
	this.numBitmap = this.numbers.bitmap;
	this.numBitmap.fontFace = _.font;
	this.numBitmap.fontSize = fontSize;
	this.numBitmap.fontItalic = _.italic;
	this.numBitmap.textColor = _.color;
	this.numBitmap.outlineColor = _.outline;
};

_.Sprite_Timer_update = Sprite_Timer.prototype.update;
Sprite_Timer.prototype.update = function() {
	_.Sprite_Timer_update.apply(this, arguments);
	this.updatePause();
	this.updateLabel();
};

Sprite_Timer.prototype.updateBitmap = function() {
	if(this._count !== $gameTimer.getCount(this._lowestType)) {
		this._count = $gameTimer.getCount(this._lowestType);
		this.redraw();
	}
};

Sprite_Timer.prototype.updatePause = function() {
	if(this._paused !== $gameTimer.isPaused()) {
		this._paused = $gameTimer.isPaused();
		if(this._paused) this.redrawForPause();
		else this.redraw();
	}
};

Sprite_Timer.prototype.updateLabel = function() {
	if(this._label !== $gameTimer.getLabel()) {
		const refreshChildren = (!!this._label !== !!$gameTimer.getLabel());
		this._label = $gameTimer.getLabel();
		this.refreshLabel();
		if(refreshChildren) {
			this.removeChildren();
			this.createBackground();
			this.addChildren();
		}
	}
};

Sprite_Timer.prototype.redraw = function() {
	if(this._paused) return;
	const text = this.timerText();
	const width = this.numBitmap.width;
	const height = this.numBitmap.height;
	this.numBitmap.clear();
	this.numBitmap.drawText(text, 0, 0, width, height, 'center');
};

Sprite_Timer.prototype.redrawForPause = function() {
	const text = this.timerText();
	const width = this.numBitmap.width;
	const height = this.numBitmap.height;
	const color = this.numBitmap.textColor;
	this.numBitmap.clear();
	this.numBitmap.textColor = _.pauseColor;
	this.numBitmap.drawText(text, 0, 0, width, height, 'center');
	this.numBitmap.textColor = color;
};

Sprite_Timer.prototype.timerText = function() {
	let result = _.format;
	const frames = $gameTimer.getFrames();
	const seconds = Math.floor(frames / 60);
	const minutes = Math.floor(frames / (60 * 60));
	const frm = frames % 60;
	const sec = seconds % 60;
	const min = minutes % 60;
	const hur = Math.floor(minutes / 60) % 60;
	if(_.usesFrames) result = result.replace(/%4/, frm.padZero(2));
	if(_.usesSeconds) result = result.replace(/%3/, sec.padZero(2));
	if(_.usesMinutes) result = result.replace(/%2/, min.padZero(2));
	if(_.usesHours) result = result.replace(/%1/, hur.padZero(2));
	return result;
};

Sprite_Timer.prototype.updateVisibility = function() {
	if($gameTimer.isWorking()) {
		this.opacity = ($gameTimer.isAutoPaused()) ? _.autoOpacity : 255;
	} else {
		this.opacity = 0;
	}
};

Sprite_Timer.prototype.updatePosition = function() {
	if(!this.background) return;
	this.updateVertical();
	this.updateCountPosition();
	this.updateHorizontal();
};

Sprite_Timer.prototype.updateVertical = function() {
	if(_.vert === 1) {
		this.y = Graphics.boxHeight - this.background.height;
	} else {
		this.y = 0;
	}
};

Sprite_Timer.prototype.updateCountPosition = function() {
	if(this._label) {
		this.numbers.y = _.labelSize + 16;
	} else {
		this.numbers.y = 0;
	}
};

Sprite_Timer.prototype.updateHorizontal = function() {
	if(_.horz === 1) {
		this.x = Graphics.boxWidth - this.numBitmap.width;
		this.background.x = this.numBitmap.width - this.background.bitmap.width;
	} else if(_.horz === -1) {
		this.x = 0;
		this.background.x = this.background.bitmap.width;
	} else {
		this.x = (Graphics.boxWidth - this.numBitmap.width) / 2;
		this.background.x = this.numBitmap.width / 2;
	}
};

})(SRD.TimerUpgrade, SRD.PluginCommands);