GRB MenuInfoWindowsMZ

Матеріал з РПГ.укр
Перейти до: навігація, пошук
Приклад вікна меню з додатковими інформаційними вікнами.

GRB_MenuInfoWindowsMZплагін для RPG Maker MZ від команди Гарбата. Дозволяє додати на екран меню додаткові інформаційні вікна над вікном грошей (або замість нього).

Завантажити плагін для MZ можна тут: GRB_MenuInfoWindowsMZ.js.

У плагіну також є версія для RPG Maker MV: GRB_MenuInfoWindows.

Функції плагіну[ ]

В вікнах, доданих цим плагіном, можна показати наступне (зміст):

  • значення змінної (напр., репутацію, кількість різних валют, кількість відкритих предметів, тощо),
  • ігрові дані (назву карти, кількість кроків, час гри, час на таймері; кількість записів гри, битв, перемог, утікань; реальний годинник),
  • значення, встановлені в коді мовою JavaScript (код має встановлювати змінну value).

Крім того, у кожного вікна може бути свій заголовок (він показується над основним змістом вікна) та одиницю виміру (вона показується після змісту). Для кожного вікна можна вказати перемикач, який буде приховувати вікно.

Плагін також дозволяє приховати стандартне вікно з грошима.

Код[ ]

Показати код плагіну

//==========================
// GRB_MenuInfoWindowsMZ.js
//==========================

/*:
 * @plugindesc Info windows in menu
 * @author Garbata team
 * @url https://rpgukr.one/GRB_MenuInfoWindowsMZ
 * @target MZ
 *
 * @help
 * This plugin allows to add additional informational windows to the menu scene.
 * They will be placed above (or instead of) the gold window, and they are
 * functionally similar to it.
 *
 * The "Info windows" parameter specifies which windows will be displayed.
 * Each window has the contents, that is, the main text it displays.
 * Contents can be either:
 * - a variable,
 * - game data (step counter),
 * - or a value produced by the JavaScript code (the code must store the
 * result in the "value" variable).
 * You can use only one contents type. If several contents types are set,
 * the first one will be used.
 *
 * Also, the windows can have:
 * - a header line above them
 * - an unit value below them (for example, " steps" or " coins").
 *
 * The hiding switch can be used to conditionally display the window. If it is
 * used, the window will be shown only when the switch is OFF. When it is ON,
 * the window will be hidden.
 *
 * The "Update contents" allows to update the contents when the menu is opened.
 * If this option is not selected, the contents will be set at the menu opening,
 * and not updated later. "Update contents" is useful for some game data
 * (play time, clock) and JS values. It is not useful for variables, because
 * variables cannot change their value when the menu is open.
 *
 * Besides the "Info windows", there is one more parameter: "Hide gold window".
 * If it is chosen, the default gold window will not be shown.
 *
 * This is the MZ version of the plugin. For the MV version, refer here:
 * https://rpgukr.one/GRB_MenuInfoWindows
 *
 * This plugin is placed into public domain according to the CC0 public domain
 * dedication. See https://creativecommons.org/publicdomain/zero/1.0/ for more
 * information.
 *
 * @param infoWindows
 * @text Info windows
 * @desc Windows that will be added to the menu screen.
 * @type struct<InfoWindow>[]
 * @default ["{\"header\":\"Play time\",\"contents\":\"\",\"variable\":\"\",\"gameData\":\"Play time\",\"jsCode\":\"\",\"unitText\":\"\",\"hidingSwitch\":\"\",\"updateValue\":\"true\"}","{\"header\":\"Steps\",\"contents\":\"\",\"variable\":\"\",\"gameData\":\"Steps\",\"jsCode\":\"\",\"unitText\":\"\",\"hidingSwitch\":\"\",\"updateValue\":\"false\"}"]
 *
 * @param hideGold
 * @text Hide gold window
 * @desc Hide the default gold window
 * @type boolean
 * @on Hide
 * @off Keep visible
 * @default false
 */
/*~struct~InfoWindow:
 * @param header
 * @text Header
 * @desc A line of text shown above the contents.
 * @type string
 *
 * @param contents
 * @text --- Contents: ---
 * @desc Don't set this parameter. Instead, set
 * one of the parameters after it.
 *
 * @param variable
 * @text Variable
 * @parent contents
 * @desc If this parameter is set, the content
 * of this variable will be shown.
 * @type variable
 *
 * @param gameData
 * @text Game Data
 * @parent contents
 * @desc If this parameter is set, the window
 * will display game data.
 * @type select
 * @option (none)
 * @option Map Name
 * @option Steps
 * @option Play time
 * @option Timer
 * @option Save count
 * @option Battle count
 * @option Win count
 * @option Escape count
 * @option Clock
 *
 * @param jsCode
 * @text JS code to evaluate
 * @parent contents
 * @desc If this parameter is set, this code will be
 * evaluated. It must set the "value" variable.
 * @type note
 *
 * @param unitText
 * @text Unit text
 * @desc Text that will be shown after contents.
 * For example, " coins"
 * @type string
 *
 * @param hidingSwitch
 * @text Hiding switch
 * @desc When the switch chosen here is ON, the
 * info window will be hidden.
 * @type switch
 *
 * @param updateValue
 * @text Update contents
 * @desc If enabled, the contents will be refreshed
 * after the menu is opening (e.g. for play time)
 * @type boolean
 * @on Update
 * @off Don't update
 * @default false
 */
/*:uk
 * @plugindesc Інформаційні вікна в меню
 * @author Команда Гарбата
 * @url https://rpgukr.one/GRB_MenuInfoWindowsMZ
 * @target MZ
 *
 * @help
 * Цей плагін додає додаткові інформаційні вікна на екран меню. Вони будуть
 * показуватися над вікном грошей (або замість його), і по своїй функції вони
 * на нього схожі.
 *
 * Параметр «Інформаційні вікна» вказує, які вікна будуть показуватися.
 * У кожного вікна є зміст, тобто основний текст, який показується в вікні.
 * Зміст може буди одним з наступним:
 * - змінною,
 * - даними гри,
 * - значенням, встановленним у коді мовою JavaScript (код має записувати
 * результат у змінну value).
 * Можна викорситовувати тільки один з цих типів змісту. Якщо для вікна вказано
 * їх декілька, буде використовуватися перший.
 *
 * Крім цього, у вікні можуть бути:
 * - заголовок над змістом,
 * - одиниця виміру після змісту (наприклад, « кр.» або « мон.»).
 *
 * Перемикач приховання дозволяє показувати вікно тільки при певних умовах.
 * Якщо вибрано перемикач приховання, вікно буде показуватися тільки тоді, коли
 * цей перемикач ВИМкнено. Коли він УВімкнений, вікно буде приховано.
 *
 * Параметр «Оновлювати зміст» дозволяє оновлювати зміст після того, як меню
 * відкрито. Якщо цей параметр вимкнено, зміст встановлюється при відкритті
 * меню і після цього не оновлюється. «Оновлювати зміст» корисне для деяких
 * ігрових даних (час гри, годинник) і коду на JS. Воно не має сенсу для
 * змінних, бо значення змінних не міняється, поки меню відкрите.
 *
 * Під параметром «Інформаційні вікна» є це один параметр: «Приховати вікно
 * грошей». Якщо він вибраний, стандартне вікно з кількістю грошей (золота)
 * не буде показуватися.
 *
 * Це версія плагіна для MZ. Версію для MV можна знайти тут:
 * https://rpgukr.one/GRB_MenuInfoWindows
 *
 * Цей плагін передано до суспільного надбання згідно з CC0. Детальніше див.
 * на сторінці https://creativecommons.org/publicdomain/zero/1.0/deed.uk
 *
 * @param infoWindows
 * @text Інформаційні вікна
 * @desc Вікна, які будуть додані на екран меню.
 * @type struct<InfoWindow>[]
 * @default ["{\"header\":\"Час гри\",\"contents\":\"\",\"variable\":\"\",\"gameData\":\"Час гри\",\"jsCode\":\"\",\"unitText\":\"\",\"hidingSwitch\":\"\",\"updateValue\":\"true\"}","{\"header\":\"Кроки\",\"contents\":\"\",\"variable\":\"\",\"gameData\":\"Кількість кроків\",\"jsCode\":\"\",\"unitText\":\"\",\"hidingSwitch\":\"\",\"updateValue\":\"false\"}"]
 *
 * @param hideGold
 * @text Приховати вікно грошей
 * @desc Чи приховувати стандартне вікно
 * з кількістю грошей.
 * @type boolean
 * @on Приховувати
 * @off Залишити
 * @default false
 */
/*~struct~InfoWindow:uk
 * @param header
 * @text Заголовок
 * @desc Рядок тексту, який показується над змістом.
 * @type string
 *
 * @param contents
 * @text --- Зміст: ---
 * @desc Не встановлюйте цю змінну. Встановлюйте
 * одну з наступних.
 *
 * @param variable
 * @text Змінна
 * @parent contents
 * @desc Якщо встановити цей параметр, у вікні
 * буде показуватися число зі змінної.
 * @type variable
 *
 * @param gameData
 * @text Ігрові дані
 * @parent contents
 * @desc Якщо встановлено цей параметр, у вікні
 * будуть показуватися ігрові дані.
 * @type select
 * @option (нічого)
 * @option Назва карти
 * @option Кількість кроків
 * @option Час гри
 * @option Таймер
 * @option Кількість записів гри
 * @option Кількість битв
 * @option Кількість перемог
 * @option Кількість утікань
 * @option Годинник
 *
 * @param jsCode
 * @text Код на JS
 * @parent contents
 * @desc Цей код буде викликатися, щоб отримати зміст
 * вікна. Код має записувати результат у змінну "value".
 * @type note
 *
 * @param unitText
 * @text Одиниця виміру
 * @desc Текст, який буде показано після змісту.
 * Наприклад, " ₴"
 * @type string
 *
 * @param hidingSwitch
 * @text Перемикач приховання
 * @desc Якщо вибраний тут перемикач УВімкнено,
 * вікно буде приховуватися.
 * @type switch
 *
 * @param updateValue
 * @text Оновлювати зміст
 * @desc Якщо увімкнено, вікно буде оновлюватися після
 * відкриття меню (корисно, напр., для часу гри)
 * @type boolean
 * @on Оновлювати
 * @off Не оновлювати
 * @default false
 */
/*:be
 * @plugindesc Інфармацыйныя вокны ў меню
 * @author Каманда Гарбата
 * @url https://rpgukr.one/GRB_MenuInfoWindowsMZ
 * @target MZ
 *
 * @help
 * Гэты плагін дадае дадатковыя інфармацыйныя вокны на экран меню. Яны будуць
 * паказвацца над акном грошай (або замест яго), і па сваёй функцыі яны на яго
 * падобныя.
 *
 * Параметр «Інфармацыйныя вокны» ўказвае, якія вокны будуць паказвацца.
 * У кожнага акна ёсць змест, г. зн. асноўны тэкст, які паказваецца ў акне.
 * Змест можа быць адным з наступных:
 * - пераменнай,
 * - гульнявымі даными,
 * - значэннямі, устаноўленымі ў кодзе на мове JavaScript (код мае запісваць
 * рэзультат у пераменную value).
 * Можна выкарыстоўваць толькі адзін гэтых тыпаў зместу. Калі для акна ўказана
 * іх некалькі, будзе выкарыстоўвацца толькі першы.
 *
 * Акрамя таго, у акна могуць быць:
 * - загаловак над зместам,
 * - адзінка вымярэння пасля зместу (напрыклад, « кр.» або  « руб.»).
 *
 * Пераключальнік скрывання дазваляе паказваць акно толькі пры пэўных умовах.
 * Калі выбраны пераключальнік скрывання, акно будзе паказвацца толькі тады,
 * калі гэты пераключальнік ВЫКЛючаны. Калі ён УКЛючаны, акно будзе скрытае.
 *
 * Параметр «Абнаўляць змест» дазваляе абнаўляць змест пасля адкрыцця меню.
 * Калі гэты параметр выключаны, змест устанаўліваецца толькі падчас адкрыцця
 * меню, і пасля гэтага не абнаўляецца. Параметр «Абнаўляць змест» карысны
 * для некаторых гульнявых даных (час гульні, гадзіннік) і коду на JS. Яно
 * не мае сэнсу для пераменных, бо значэнні пераменных не мяняюцца, пакуль
 * меню адкрытае.
 *
 * Пад параметрам «Інфармацыйныя вокны» ёсць яшчэ адзін параметр: «Скрываць
 * акно грошай». Калі ён выбраны, стандартнае акно з колькасцю грошай (золата)
 * не будзе паказвацца.
 *
 * Гэта версія плагіна для MZ. Версію для MV можна знайсці тут:
 * https://rpgukr.one/GRB_MenuInfoWindows
 *
 * Гэты плагін перададзены ў грамадскі набытак згодна з CC0. Падрабязней гл.
 * на старонцы https://creativecommons.org/publicdomain/zero/1.0/deed.be
 *
 * @param infoWindows
 * @text Інфармацыйныя вокны
 * @desc Вокны, якія будуць дададзеныя на экран меню.
 * @type struct<InfoWindow>[]
 * @default ["{\"header\":\"Час гульні\",\"contents\":\"\",\"variable\":\"\",\"gameData\":\"Час гульні\",\"jsCode\":\"\",\"unitText\":\"\",\"hidingSwitch\":\"\",\"updateValue\":\"true\"}","{\"header\":\"Крокі\",\"contents\":\"\",\"variable\":\"\",\"gameData\":\"Колькасць крокаў\",\"jsCode\":\"\",\"unitText\":\"\",\"hidingSwitch\":\"\",\"updateValue\":\"false\"}"]
 *
 * @param hideGold
 * @text Скрываць акно грошай
 * @desc Ці скрываць стандартнае акно
 * з колькасцю грошай.
 * @type boolean
 * @on Скрываць
 * @off Пакінуць
 * @default false
 */
/*~struct~InfoWindow:be
 * @param header
 * @text Загаловак
 * @desc Радок тэксту, які паказнаецца над зместам.
 * @type string
 *
 * @param contents
 * @text --- Змест: ---
 * @desc Не ўстанаўлівайце гэты параметр. Устанаўлівайце
 * адзін з наступных.
 *
 * @param variable
 * @text Пераменная
 * @parent contents
 * @desc Калі ўстанавіць гэты параметр, у акне будзе
 * паказвацца лік з пераменнай.
 * @type variable
 *
 * @param gameData
 * @text Гульнявыя даныя
 * @parent contents
 * @desc Калі ўстанавіць гэты параметр, у акне
 * будуць паказвацца гульнявыя даныя.
 * @type select
 * @option (нічога)
 * @option Назва карты
 * @option Колькасць крокаў
 * @option Час гульні
 * @option Таймер
 * @option Колькасць запісаў гульні
 * @option Колькасці бітваў
 * @option Колькасць перамог
 * @option Колькасць уцёкаў
 * @option Гадзіннік
 *
 * @param jsCode
 * @text Код на JS
 * @parent contents
 * @desc Гэты код будзе выклікацца, каб атрымаць змест
 * акна. Код мусіць запісаць рэзультат у пераменную "value".
 * @type note
 *
 * @param unitText
 * @text Адзінка вымярэння
 * @desc Тэкст, які будзе паказаны пасля зместу.
 * Напрыклад, " руб."
 * @type string
 *
 * @param hidingSwitch
 * @text Пераключальнік скрывання
 * @desc Калі выбраны тут пераключальнік УКЛючаны,
 * акно будзе скрытае.
 * @type switch
 *
 * @param updateValue
 * @text Абнаўляць змест
 * @desc Калі параметр уключаны, акно будзе абнаўляцца пасля
 * адкрыцця меню (карысна, напр., для часу гульні)
 * @type boolean
 * @on Абнаўляць
 * @off Не абнаўляць
 * @default false
 */
/*:ru
 * @plugindesc Информационные окна в меню
 * @author Команда Гарбата
 * @url https://rpgukr.one/GRB_MenuInfoWindowsMZ
 * @target MZ
 *
 * @help
 * Этот плагин добавляет дополнительные информационные окна на экран меню. Они
 * будут показываться над окном денег (или вместо него), и по своей функции они
 * на него похожи.
 *
 * Параметр «Информационные окна» указывает, какие окна будут показываться.
 * У каждого окна есть содержание, т. е. основной текст, показываемый в окне.
 * Содержание может быть одним из следующих:
 * - переменной,
 * - игровыми данными,
 * - значениями, установленными в коде на языке JavaScript (код должен
 * записывать результат в переменную value).
 * Можно использовать только один этих типов содержания. Если для окна указано
 * их несколько, будет использоваться только первый.
 *
 * Кроме того, у окна могут быть:
 * - заголовок над содержанием,
 * - единица измерения после содержания (например, « шаг.» или « руб.»).
 *
 * Переключатель скрытия позволяет показывать окно только при определенных
 * условиях. Если выбран переключатель скрытия, окно будет показываться только
 * тогда, когда этот переключатель ВЫКЛючен. Когда он ВКЛючен, окно будет
 * скрыто.
 *
 * Параметр «Обновлять содержание» позволяет обновлять содержание после
 * открытия меню. Если этот параметр выключен, содержание устанавливается
 * только во время открытия меню, и после этого не обновляется. Параметр
 * «Обновлять содержание» полезен для некоторых игровых данных (время игры,
 * часы) и кода на JS. Оно не имеет смысла для переменных, так как значения
 * переменных не меняются, пока меню открыто.
 *
 * Под параметром «Информационные окна» есть еще один параметр: «Скрывать
 * окно денег». Если он выбран, стандартное окно с количеством денег (золота)
 * не будет показываться.
 *
 * Это версия плагина для MZ. Версию для MV можно найти здесь:
 * https://rpgukr.one/GRB_MenuInfoWindows
 *
 * Этот плагин передан в общественное достояние согласно CC0. Подробнее см. на
 * странице https://creativecommons.org/publicdomain/zero/1.0/deed.ru
 *
 * @param infoWindows
 * @text Информационные окна
 * @desc Окна, которые будут добавлены на экран меню.
 * @type struct<InfoWindow>[]
 * @default ["{\"header\":\"Время игры\",\"contents\":\"\",\"variable\":\"\",\"gameData\":\"Время игры\",\"jsCode\":\"\",\"unitText\":\"\",\"hidingSwitch\":\"\",\"updateValue\":\"true\"}","{\"header\":\"Шаги\",\"contents\":\"\",\"variable\":\"\",\"gameData\":\"Количество шагов\",\"jsCode\":\"\",\"unitText\":\"\",\"hidingSwitch\":\"\",\"updateValue\":\"false\"}"]
 *
 * @param hideGold
 * @text Скрывать окно денег
 * @desc Скрывать ли стандартное окно с количеством денег.
 * @type boolean
 * @on Скрывать
 * @off Оставить
 * @default false
 */
/*~struct~InfoWindow:ru
 * @param header
 * @text Заголовок
 * @desc Строка текста, которая показывается над содержанием.
 * @type string
 *
 * @param contents
 * @text --- Содержание: ---
 * @desc Не устанавливайте этот параметр. Устанавливайте один
 * из следующих.
 *
 * @param variable
 * @text Переменная
 * @parent contents
 * @desc Если установить этот параметр, в окне будет
 * показываться число из переменной.
 * @type variable
 *
 * @param gameData
 * @text Игровые данные
 * @parent contents
 * @desc Если установить этот параметр, в окне
 * будут показываться игровые данные.
 * @type select
 * @option (ничего)
 * @option Название карты
 * @option Количество шагов
 * @option Время игры
 * @option Таймер
 * @option Количество сохранений
 * @option Количество битв
 * @option Количество побед
 * @option Количество побегов
 * @option Часы
 *
 * @param jsCode
 * @text Код на JS
 * @parent contents
 * @desc Этот код будет вызываться, чтобы получить содержание.
 * Код должен записывать результат в переменную "value".
 * @type note
 *
 * @param unitText
 * @text Единица измерения
 * @desc Текст, который будет показан после содержания.
 * Например, " руб."
 * @type string
 *
 * @param hidingSwitch
 * @text Переключатель скрытия
 * @desc Если выбранный здесь переключатель ВКЛючён,
 * окно будет скрыто.
 * @type switch
 *
 * @param updateValue
 * @text Обновлять содержание
 * @desc Если параметр включён, окно будет обновляться после
 * открытия меню (полезно, напр., для времени игры)
 * @type boolean
 * @on Обновлять
 * @off Не обновлять
 * @default false
 */

 if (typeof Imported === 'undefined') {
   Imported = {};
 }
 Imported.GRB_MenuInfoWindows = 0.01;

function Window_GrbMenuInfo() {
    this.initialize(...arguments);
}

Window_GrbMenuInfo.prototype = Object.create(Window_Selectable.prototype);
Window_GrbMenuInfo.prototype.constructor = Window_GrbMenuInfo;

// Lists of options can have values, but then the value will be displayed
// in the list, and not the data. We want a nicely formatted translated data,
// so we're converting text into IDs here.
Window_GrbMenuInfo.NORMALIZED_GAME_DATA_TYPE = {
  // English
  'Map Name': 'mapName',
  'Steps': 'steps',
  'Play time': 'playTime',
  'Timer': 'timer',
  'Save count': 'saveCount',
  'Battle count': 'battleCount',
  'Win count': 'winCount',
  'Escape count': 'escapeCount',
  'Clock': 'clock',

  // Ukrainian (not used by MZ editor, but might be available in alternative
  // editors... although it's very unlikely since MZ engine is not free
  // software, so we don't expect free editors, but let's keep this as a
  // symbolic gesture. Maybe Kadokawa will add Ukrainian and Belarusian one day,
  // who knows?)
  'Назва карти': 'mapName',
  'Кількість кроків': 'steps',
  'Час гри': 'playTime',
  'Таймер': 'timer',
  'Кількість записів гри': 'saveCount',
  'Кількість битв': 'battleCount',
  'Кількість перемог': 'winCount',
  'Кількість утікань': 'escapeCount',
  'Годинник': 'clock',

  // Belarusian (not used by MZ editor, but will be available in alternative
  // editors)
  'Назва карты': 'mapName',
  'Колькасць крокаў': 'steps',
  'Час гульні': 'playTime',
  //'Таймер': 'timer', //(same as Ukrainian)
  'Колькасць запісаў гульні': 'saveCount',
  'Колькасці бітваў': 'battleCount',
  'Колькасць перамог': 'winCount',
  'Колькасць уцёкаў': 'escapeCount',
  'Гадзіннік': 'clock',

  // Russian
  'Название карты': 'mapName',
  'Количество шагов': 'steps',
  'Время игры': 'playTime',
  // 'Таймер': 'timer', //(same as in Ukrainian)
  'Количество сохранений': 'saveCount',
  'Количество битв': 'battleCount',
  'Количество побед': 'winCount',
  'Количество побегов': 'escapeCount',
  'Часы': 'clock',
};

Window_GrbMenuInfo.prototype.initialize = function(description, rect) {
    this.description = description;
    Window_Selectable.prototype.initialize.call(this, rect);
    this.refresh();
};

Window_GrbMenuInfo.prototype.colSpacing = function() {
    return 0;
};

Window_GrbMenuInfo.prototype.open = function() {
    this.refresh();
    Window_Selectable.prototype.open.call(this);
};

Window_GrbMenuInfo.prototype.refresh = function() {
    const rect = this.itemLineRect(0);
    const x = rect.x;
    const width = rect.width;

    const value = this.value();
    this.grbLastSavedValue = value;

    this.contents.clear();

    let y = rect.y;
    if (this.hasHeader()) {
        this.drawInfoHeader(x, y, width);
        y += this.lineHeight();
    }
    this.drawInfoValue(value, x, y, width);
};

Window_GrbMenuInfo.prototype.drawInfoHeader = function(x, y, width) {
  this.changeTextColor(ColorManager.systemColor());
  this.drawText(this.description.header, x, y, width, 'left');
}

Window_GrbMenuInfo.prototype.drawInfoValue = function(value, x, y, width) {
    const unitWidth = this.textWidth(this.description.unitText);
    let valueWidth = width - unitWidth - 6;
    if (unitWidth == 0) {
      valueWidth = width;
    }

    this.resetTextColor();
    this.drawText(value, x, y, valueWidth, 'right');
    this.changeTextColor(ColorManager.systemColor());
    this.drawText(
      this.description.unitText, x + width - unitWidth, y, unitWidth, 'right'
  );
};

Window_GrbMenuInfo.prototype.value = function() {
  if (this.description.variable) {
    const parsedVariableId = parseInt(this.description.variable);
    if (!isNaN(parsedVariableId)) {
      return $gameVariables.value(parsedVariableId);
    }
  }

  if (this.description.gameData) {
    const dataType = Window_GrbMenuInfo.NORMALIZED_GAME_DATA_TYPE[
      this.description.gameData
    ];
    if (dataType) {
      return this.gameDataValue(dataType);
    }
  }

  if (this.description.jsCode) {
    return this.jsValue(this.description.jsCode);
  }

  return '---';
}

Window_GrbMenuInfo.prototype.gameDataValue = function(dataType) {
  switch (dataType) {
    case 'mapName':
      return $gameMap.displayName();
    case 'steps':
      return $gameParty.steps();
    case 'playTime':
      return this.formatTime($gameSystem.playtime());
    case 'saveCount':
      return $gameSystem.saveCount();
    case 'battleCount':
      return $gameSystem.battleCount();
    case 'winCount':
      return $gameSystem.winCount();
    case 'escapeCount':
      return $gameSystem.escapeCount();
    case 'timer':
      return this.formatTime($gameTimer.seconds());
    case 'clock':
      return this.clockValue()
    default:
      console.log('Uknown game data type: ' + dataType);
  }
  return "???";
};

Window_GrbMenuInfo.prototype.formatTwoDigits = function(x) {
  const s = String(x);
  if (s.length == 1) {
    return '0' + s;
  } else {
    return s;
  }
};

Window_GrbMenuInfo.prototype.formatTime = function(seconds) {
  const hours = Math.floor(seconds / (60 * 60));
  const mins = Math.floor(seconds / 60) % 60;
  const secs = seconds % 60;

  if (hours > 0) {
    return hours + ':' + this.formatTwoDigits(mins) +
          ':' + this.formatTwoDigits(secs)
  } else {
    return this.formatTwoDigits(mins) + ':' + this.formatTwoDigits(secs)
  }
};

Window_GrbMenuInfo.prototype.clockValue = function() {
  const date = new Date();
  return date.getHours() + ':' + this.formatTwoDigits(date.getMinutes());
};

Window_GrbMenuInfo.prototype.jsValue = function(js) {
  let value;
  eval(JSON.parse(js));

  return value;
};

Window_GrbMenuInfo.prototype.hasHeader = function() {
  return !!this.description.header;
};

Window_GrbMenuInfo.prototype.grbIsUpdateable = function() {
  return this.description.updateValue &&
          JSON.parse(this.description.updateValue);
};

Window_GrbMenuInfo.prototype.refreshIfNeeded = function() {
  if (this.value() !== this.grbLastSavedValue) {
    this.refresh();
  }
};

;(function () {

  const parameters = PluginManager.parameters('GRB_MenuInfoWindowsMZ');

  function parseDescriptions(jsonString) {
    return JSON.parse(jsonString).map(JSON.parse);
  }

  const infoWindowDescriptions = parseDescriptions(parameters.infoWindows);

  const Scene_Menu_create = Scene_Menu.prototype.create;
  Scene_Menu.prototype.create = function() {
    this.grbPrecalculateInfoWindowSizes();
    Scene_Menu_create.call(this);
    this.grbCreateInfoWindows();
    this.grbHideGoldWindow();
  }

  Scene_Menu.prototype.grbPrecalculateInfoWindowSizes = function () {
    let bottomY = this.mainAreaBottom();
    if (!this.grbNeedToHideGoldWindow()) {
      const goldWindowRect = this.goldWindowRect();
      bottomY = goldWindowRect.y;
    }
    const singleLineHeight = this.calcWindowHeight(1, true);
    const twoLineHeight = singleLineHeight + Window_Base.prototype.lineHeight();

    const width = this.mainCommandWidth();
    const x = this.isRightInputMode() ? Graphics.boxWidth - width : 0;

    this.grbInfoWindowRects = new Array(infoWindowDescriptions.length);
    for (let i = infoWindowDescriptions.length - 1; i >= 0; i--) {
      const desc = infoWindowDescriptions[i];
      if (this.grbIsInfoWindowVisible(desc)) {
        const height = !!desc.header ? twoLineHeight : singleLineHeight;
        this.grbInfoWindowRects[i] = new Rectangle(
          x, bottomY - height, width, height
        );

        bottomY -= height;
      } else {
        this.grbInfoWindowRects[i] = null;
      }
    }
    this.grbMaxCommandWindowHeight = bottomY - this.mainAreaTop();
  }

  const Scene_Menu_commandWindowRect = Scene_Menu.prototype.commandWindowRect;
  Scene_Menu.prototype.commandWindowRect = function() {
    const rect = Scene_Menu_commandWindowRect.call(this);
    if (rect.height > this.grbMaxCommandWindowHeight) {
      console.log(`NEW RECT: ${rect.x}, ${rect.y}; ${rect.width}, ${this.grbMaxCommandWindowHeight}`);
      return new Rectangle(
        rect.x, rect.y, rect.width, this.grbMaxCommandWindowHeight
      );
    }

    return rect;
  }

  Scene_Menu.prototype.grbNeedToHideGoldWindow = function () {
    return parameters.hideGold && JSON.parse(parameters.hideGold);
  }

  Scene_Menu.prototype.grbCreateInfoWindows = function() {
    this.grbUpdatableInfoWindows = [];

    const infoWindows = [];
    // We are starting from the lowest window, because we can't find y of the
    // upper window without knowing the y of the lower windows.
    for (let i = infoWindowDescriptions.length - 1; i >= 0; i--) {
      const window = this.grbCreateInfoWindow(i);

      if (window) {
        infoWindows.push(window);
        if (window.grbIsUpdateable()) {
          this.grbUpdatableInfoWindows.push(window)
        }
      }
    }

    // We are storing info windows in the same order as descriptions,
    // for convenience
    this.grbInfoWindows = infoWindows.reverse();
  }

  Scene_Menu.prototype.grbIsInfoWindowVisible = function(description) {
    let isVisible = true;
    if (description.hidingSwitch) {
      isVisible = !$gameSwitches.value(description.hidingSwitch);
    }

    return isVisible;
  }

  Scene_Menu.prototype.grbCreateInfoWindow = function(index) {
    const description = infoWindowDescriptions[index];

    if (this.grbIsInfoWindowVisible(description)) {
      const rect = this.grbInfoWindowRects[index];
      const window = new Window_GrbMenuInfo(description, rect);
      this.addWindow(window);

      return window;
    } else {
      return null;
    }
  }

  Scene_Menu.prototype.grbHideGoldWindow = function() {
    if (this.grbNeedToHideGoldWindow()) {
      this._goldWindow.hide();
    }
  }

  const Scene_Menu_update = Scene_Menu.prototype.update;
  Scene_Menu.prototype.update = function() {
    Scene_Menu_update.call(this);
    if (this.grbUpdatableInfoWindows) {
      this.grbUpdatableInfoWindows.forEach(function (window) {
        window.refreshIfNeeded();
      });
    }

  }
})();