//-----------------------------------------------------------------------------
// Window_Message
//
// The window for displaying text messages.
/**
* The window for displaying text messages.
*
* @class
* @extends Window
*/
function Window_Message() {
this.initialize(...arguments);
}
Window_Message.prototype = Object.create(Window_Base.prototype);
Window_Message.prototype.constructor = Window_Message;
Window_Message.prototype.initialize = function(rect) {
Window_Base.prototype.initialize.call(this, rect);
this.openness = 0;
this.initMembers();
};
/**
* Initializes window variables
*/
Window_Message.prototype.initMembers = function() {
this._background = 0;
this._positionType = 2;
this._waitCount = 0;
this._faceBitmap = null;
this._textState = null;
this._goldWindow = null;
this._nameBoxWindow = null;
this._choiceListWindow = null;
this._numberInputWindow = null;
this._eventItemWindow = null;
this.clearFlags();
};
/**
* Associates the gold window
*
* @param {Window_Gold} goldWindow - The gold window to associate with this window
*/
Window_Message.prototype.setGoldWindow = function(goldWindow) {
this._goldWindow = goldWindow;
};
/**
* Associates the name box window
*
* @param {Window_NameBox} nameBoxWindow - The name box window to associate with this window
*/
Window_Message.prototype.setNameBoxWindow = function(nameBoxWindow) {
this._nameBoxWindow = nameBoxWindow;
};
/**
* Associates the choice list window
*
* @param {Window_ChoiceList} nameBoxWindow - The choice list window to associate with this window
*/
Window_Message.prototype.setChoiceListWindow = function(choiceListWindow) {
this._choiceListWindow = choiceListWindow;
};
/**
* Associates the number input window
*
* @param {Window_NumberInput} nameBoxWindow - The number input window to associate with this window
*/
Window_Message.prototype.setNumberInputWindow = function(numberInputWindow) {
this._numberInputWindow = numberInputWindow;
};
/**
* Associates the event item window
*
* @param {Window_EventItem} nameBoxWindow - The event item window to associate with this window
*/
Window_Message.prototype.setEventItemWindow = function(eventItemWindow) {
this._eventItemWindow = eventItemWindow;
};
/**
* Clears window flags
*/
Window_Message.prototype.clearFlags = function() {
this._showFast = false;
this._lineShowFast = false;
this._pauseSkip = false;
};
Window_Message.prototype.update = function() {
this.checkToNotClose();
Window_Base.prototype.update.call(this);
this.synchronizeNameBox();
while (!this.isOpening() && !this.isClosing()) {
if (this.updateWait()) {
return;
} else if (this.updateLoading()) {
return;
} else if (this.updateInput()) {
return;
} else if (this.updateMessage()) {
return;
} else if (this.canStart()) {
this.startMessage();
} else {
this.startInput();
return;
}
}
};
/**
* Check if the window should instead stay open if it is closing
*/
Window_Message.prototype.checkToNotClose = function() {
if (this.isOpen() && this.isClosing() && this.doesContinue()) {
this.open();
}
};
/**
* Sync the name box window with this window
*/
Window_Message.prototype.synchronizeNameBox = function() {
this._nameBoxWindow.openness = this.openness;
};
/**
* Check if the window can start
*
* @return {boolean} True if the window can start
*/
Window_Message.prototype.canStart = function() {
return $gameMessage.hasText() && !$gameMessage.scrollMode();
};
/**
* Starts the message
*/
Window_Message.prototype.startMessage = function() {
const text = $gameMessage.allText();
const textState = this.createTextState(text, 0, 0, 0);
textState.x = this.newLineX(textState);
textState.startX = textState.x;
this._textState = textState;
this.newPage(this._textState);
this.updatePlacement();
this.updateBackground();
this.open();
this._nameBoxWindow.start();
};
/**
* Get the x coordinate for a new line
*
* @param {Object} textState - The text state object
* @return {number} The x coordinate of a new line
*/
Window_Message.prototype.newLineX = function(textState) {
const faceExists = $gameMessage.faceName() !== "";
const faceWidth = ImageManager.standardFaceWidth;
const spacing = 20;
const margin = faceExists ? faceWidth + spacing : 4;
return textState.rtl ? this.innerWidth - margin : margin;
};
/**
* Update window placements
*/
Window_Message.prototype.updatePlacement = function() {
const goldWindow = this._goldWindow;
this._positionType = $gameMessage.positionType();
this.y = (this._positionType * (Graphics.boxHeight - this.height)) / 2;
if (goldWindow) {
goldWindow.y = this.y > 0 ? 0 : Graphics.boxHeight - goldWindow.height;
}
};
/**
* Updates the window background
*/
Window_Message.prototype.updateBackground = function() {
this._background = $gameMessage.background();
this.setBackgroundType(this._background);
};
/**
* Ends the message
*/
Window_Message.prototype.terminateMessage = function() {
this.close();
this._goldWindow.close();
$gameMessage.clear();
};
/**
* Updates the window wait
*
* @return {boolean} True if updated
*/
Window_Message.prototype.updateWait = function() {
if (this._waitCount > 0) {
this._waitCount--;
return true;
} else {
return false;
}
};
/**
* Cancels waiting
* @since 1.8.0
*/
Window_Message.prototype.cancelWait = function() {
if ($gameSystem.isMessageSkipEnabled()) {
this._waitCount = 0;
}
};
/**
* Update window loading
*
* @return {boolean} True if updated
*/
Window_Message.prototype.updateLoading = function() {
if (this._faceBitmap) {
if (this._faceBitmap.isReady()) {
this.drawMessageFace();
this._faceBitmap = null;
return false;
} else {
return true;
}
} else {
return false;
}
};
/**
* Update window input
*
* @return {boolean} True if updated
*/
Window_Message.prototype.updateInput = function() {
if (this.isAnySubWindowActive()) {
return true;
}
if (this.pause) {
if (this.isTriggered()) {
Input.update();
this.pause = false;
if (!this._textState) {
this.terminateMessage();
}
}
return true;
}
return false;
};
/**
* Check if there is any sub window that is currently active
*
* @return {boolean} True if choice/num input/event item window is active
*/
Window_Message.prototype.isAnySubWindowActive = function() {
return (
this._choiceListWindow.active ||
this._numberInputWindow.active ||
this._eventItemWindow.active
);
};
/**
* Updates the message
*
* @return {boolean} True if updated
*/
Window_Message.prototype.updateMessage = function() {
const textState = this._textState;
if (textState) {
while (!this.isEndOfText(textState)) {
if (this.needsNewPage(textState)) {
this.newPage(textState);
}
this.updateShowFast();
this.processCharacter(textState);
if (this.shouldBreakHere(textState)) {
break;
}
}
this.flushTextState(textState);
if (this.isEndOfText(textState) && !this.isWaiting()) {
this.onEndOfText();
}
return true;
} else {
return false;
}
};
/**
* Check if the message should break
*
* @param {Object} textState - The text state object
* @return {boolean} True if message should break
*/
Window_Message.prototype.shouldBreakHere = function(textState) {
if (this.canBreakHere(textState)) {
if (!this._showFast && !this._lineShowFast) {
return true;
}
if (this.isWaiting()) {
return true;
}
}
return false;
};
/**
* Check if the message can break
*
* @param {Object} textState - The text state object
* @return {boolean} True if message can break
*/
Window_Message.prototype.canBreakHere = function(textState) {
if (!this.isEndOfText(textState)) {
const c = textState.text[textState.index];
if (c.charCodeAt(0) >= 0xdc00 && c.charCodeAt(0) <= 0xdfff) {
// surrogate pair
return false;
}
if (textState.rtl && c.charCodeAt(0) > 0x20) {
return false;
}
}
return true;
};
/**
* Handling for when there is no more text
*/
Window_Message.prototype.onEndOfText = function() {
if (!this.startInput()) {
if (!this._pauseSkip) {
this.startPause();
} else {
this.terminateMessage();
}
}
this._textState = null;
};
/**
* Starts input
*
* @return {boolean} True if input started
*/
Window_Message.prototype.startInput = function() {
if ($gameMessage.isChoice()) {
this._choiceListWindow.start();
return true;
} else if ($gameMessage.isNumberInput()) {
this._numberInputWindow.start();
return true;
} else if ($gameMessage.isItemChoice()) {
this._eventItemWindow.start();
return true;
} else {
return false;
}
};
/**
* Check if input is triggered
*
* @return {boolean} True if input is triggered
*/
Window_Message.prototype.isTriggered = function() {
return (
Input.isRepeated("ok") ||
Input.isRepeated("cancel") ||
TouchInput.isRepeated()
);
};
/**
* Check if the message continues
*
* @return {boolean} True if message continues
*/
Window_Message.prototype.doesContinue = function() {
return (
$gameMessage.hasText() &&
!$gameMessage.scrollMode() &&
!this.areSettingsChanged()
);
};
/**
* Check if the message window settings are changed
*
* @return {boolean} True if message settings changed
*/
Window_Message.prototype.areSettingsChanged = function() {
return (
this._background !== $gameMessage.background() ||
this._positionType !== $gameMessage.positionType()
);
};
/**
* Update for showing fast
*/
Window_Message.prototype.updateShowFast = function() {
if (this.isTriggered()) {
this._showFast = true;
}
};
/**
* Starts a new page
*
* @param {Object} textState - The text state object
*/
Window_Message.prototype.newPage = function(textState) {
this.contents.clear();
this.resetFontSettings();
this.clearFlags();
this.updateSpeakerName();
this.loadMessageFace();
textState.x = textState.startX;
textState.y = 0;
textState.height = this.calcTextHeight(textState);
};
/**
* Updates the speaker name for the name box window
*/
Window_Message.prototype.updateSpeakerName = function() {
this._nameBoxWindow.setName($gameMessage.speakerName());
};
/**
* Loads the face image for the message window
*/
Window_Message.prototype.loadMessageFace = function() {
this._faceBitmap = ImageManager.loadFace($gameMessage.faceName());
};
/**
* Draws the face in the message window
*/
Window_Message.prototype.drawMessageFace = function() {
const faceName = $gameMessage.faceName();
const faceIndex = $gameMessage.faceIndex();
const rtl = $gameMessage.isRTL();
const width = ImageManager.standardFaceWidth;
const height = this.innerHeight;
const x = rtl ? this.innerWidth - width - 4 : 4;
this.drawFace(faceName, faceIndex, x, 0, width, height);
};
Window_Message.prototype.processControlCharacter = function(textState, c) {
Window_Base.prototype.processControlCharacter.call(this, textState, c);
if (c === "\f") {
this.processNewPage(textState);
}
};
Window_Message.prototype.processNewLine = function(textState) {
this._lineShowFast = false;
Window_Base.prototype.processNewLine.call(this, textState);
if (this.needsNewPage(textState)) {
this.startPause();
}
};
/**
* Processes a new page
*
* @param {Object} textState - The text state object
*/
Window_Message.prototype.processNewPage = function(textState) {
if (textState.text[textState.index] === "\n") {
textState.index++;
}
textState.y = this.contents.height;
this.startPause();
};
/**
* Check if there is no more text in the text state
*
* @param {Object} textState - The text state object
* @return {boolean} True if no more text
*/
Window_Message.prototype.isEndOfText = function(textState) {
return textState.index >= textState.text.length;
};
/**
* Check if the message needs a new page
*
* @param {Object} textState - The text state object
* @return {boolean} True if a new page is needed
*/
Window_Message.prototype.needsNewPage = function(textState) {
return (
!this.isEndOfText(textState) &&
textState.y + textState.height > this.contents.height
);
};
Window_Message.prototype.processEscapeCharacter = function(code, textState) {
switch (code) {
case "$":
this._goldWindow.open();
break;
case ".":
this.startWait(15);
break;
case "|":
this.startWait(60);
break;
case "!":
this.startPause();
break;
case ">":
this._lineShowFast = true;
break;
case "<":
this._lineShowFast = false;
break;
case "^":
this._pauseSkip = true;
break;
default:
Window_Base.prototype.processEscapeCharacter.call(
this,
code,
textState
);
break;
}
};
/**
* Starts a wait for the given count
*
* @param {number} count - The amount to wait for
*/
Window_Message.prototype.startWait = function(count) {
this._waitCount = count;
};
/**
* Starts a pause
*/
Window_Message.prototype.startPause = function() {
this.startWait(10);
this.pause = true;
};
/**
* Check if the window is waiting
*
* @return {boolean} True if the window is waiting
* @since Version 1.2.1
*/
Window_Message.prototype.isWaiting = function() {
return this.pause || this._waitCount > 0;
};