[RMMV] Пишем свой первый плагин

Изначально урок писался для светлой, но теперь думаю буду публиковать новые уроки (если такие будут) сначала здесь.

Всем доброй ночи.

plugins

Сегодня мой день был потрачен не зря, ибо мне удалось написать свой первый небольшой плагин для нового RPG Maker MV. Сразу скажу, что ни разу не профессионал, занимаюсь в свободное от кухни время и только только разбираюсь во всём это безобразии. Хотя есть некоторый опыт скриптоковыряния VX Ace, что конечно же мне помог и тут. В любом случае спешу поделится своими изысканиями и надеюсь они будут ещё полезны кому-нибудь.

Начать мне хотелось бы с редактора. Как вы уже наверное заметили, в отличии от VX Ace в MV своего редактора нет. Скрипты лежат в открытом виде и можете спокойно их редактировать в любом текстовом редакторе. В одном из видеоуроков человек порекомендовал brackets. Опыта у меня не много в подобного рода редакторах, но мне понравился. Особенно очень удобно когда начинаешь что-то писать, а тебе бац и сразу подсказки. Мелочь, а приятно. При желании можно выбрать удобную цветовую тему. Так что можете тоже попробовать совершенно бесплатно.

brackets

Для начала о том, что мы будем сегодня делать. Этот простой плагин рисует на экране небольшое окошко с иконкой и цифрой. Данные берутся из переменных (Variables) RPG Maker. А с помощью ключа (switch) можно включить или спрятать отображение данного окна. Теперь для чего? Например NPC даёт герою задание, что нужно собрать 20 шишек. Понятно, что задание не сильно увеселительное, но можно игроку немного скрасить жизнь. Отображая например цифрами, сколько ему ещё осталось мучится. Выглядит это примерно так:

screenshot

Для того, что бы пользователь мог выбрать произвольные ячейки (Variables) и ключ (Switch) для отображения, мы выведем эти параметры в настройки нашего плагина. В принципе можно вынести и размер окна и его положение на экране, но мне бы пока не хотелось так всё сразу запутывать.

Итак, создадим новый файл ItemOnMap.js в папке нашего проекта, а именно js\plugins. Этого уже достаточно, что бы он уже появился в списке доступных плагинов, однако всё же стоит добавить его описание:

//=============================================================================
// ItemOnMap.js
//=============================================================================

Здесь название нашего файла. Не могу сказать, что это нужно наверняка, но во всех плагинах под MV примерно такое-же оформление. Возможно система по этому определяет, что это именно наш плагин а ни чей-нибудь ещё.

/*:

Открываем комментарий и описываем различные параметры:

* @plugindesc Отображает на экране количество предметов в ячейке
* @author Mur
*

Далее указывается описание плагина (@plugindesc) и собственно кто автор (@author)

* @param enableSwitchId
* @desc Показать/скрыть (номер ключа)
* @default 1
*

Затем следуют перечисления параметров нашего плагина. Тут надо быть очень внимательными, ибо эти название затем используются в скрипте. И если что-то напутать, ничего не получится. Один параметр состоит из трёх частей, собственно его названия @param (на английском языке и честно не знаю, можно ли писать на русском), описание данного параметра @desc (не знаю почему, но описание на русском не отображается) и значение по умолчанию @default. Данный параметр указывает какой ключ (switch) будет разрешать или запрещать отображение данного окошка.

* @param itemVarId
* @desc Иконка предмета (номер переменной)
* @default 1
*

Здесь указывает номер переменной (Variable) в которой хранится номер предмета, который должен собирать наш главный герой. Иконка этого предмета и отображается в нашем окошке.

* @param countVarId
* @desc Количество предметов (номер переменной)
* @default 2

Ну и завершает это всё последний параметр, который так же указывает на номер переменной (Variable) в которой хранится количество собранных предметов.

*/

Закрываем комментарий и далее следует уже наш скрипт самого плагина.

(function() {

Такой строчкой начинаются почти все плагины, которая собственно и сообщает системе, что сейчас мы будет творить!

var parameters = PluginManager.parameters('ItemOnMap');

Для начала нам нужно добраться до настроек нашего плагина. Не знаю как это всё связано, но обратите внимание, что наш файл, первый кусочек и здесь название плагина везде одинаковое, в данном случае это «ItemOnMap».

var enableSwitchId = Number(parameters['enableSwitchId']);
var itemVarId = Number(parameters['itemVarId']);
var countVarId = Number(parameters['countVarId']);

Здесь мы получаем значение наших параметров. Честно не знаю, зачем тут написано Number, но в других скриптах сделано так же, так что видимо так надо.

А так это выглядит когда мы подключаем наш плагин:

params
//Обновление всех окон
var _Scene_Map_createAllWindows = Scene_Map.prototype.createAllWindows;
Scene_Map.prototype.createAllWindows = function() {
   _Scene_Map_createAllWindows.call(this);
   this._itemOnMap = new ItemOnMap(10,10, 120, 60);
   this.addWindow(this._itemOnMap);
};

Вот тут очень важный и сложный момент. Для того, что бы наше окно постоянно отображалось. Нам нужно втиснутся в основную функцию создания всех окон (createAllWindows). Если вы писали скрипты (или хотя бы пытались что-то изменить в чужих, как я например) под VX Ace, то наверняка заметили схожий приём. Когда главная функция системы подменялась на нашу, а потом вызывалась внутри с такими же параметрами. Ну не суть важно, я думаю если кому интересно он спросит у знатоков, а тут просто для пояснения.

Сначала создаём «копию» основной функции системы:

var _Scene_Map_createAllWindows = Scene_Map.prototype.createAllWindows;

Затем заменяем её уже своей функцией:

Scene_Map.prototype.createAllWindows = function() {

внутри которой вызываем настоящую, что бы ничего не поломалось:

_Scene_Map_createAllWindows.call(this);

И затем уже добавляем создание нашего окошка:

this._itemOnMap = new ItemOnMap(10,10, 120, 60);

Первые два числа это координаты где на экране будет наше окно, а два другие его соответственно ширина и высота.

this.addWindow(this._itemOnMap);

Затем это окно добавляется в систему и далее собственно уже функции нашего окна:

function ItemOnMap() {
this.initialize.apply(this, arguments);
}

Честно скажу, назначение этого кусочка мне до конца не ясно. Однако сразу скажу, что без него не работает и кроме того опять же очень важно название — «ItemOnMap»!! Оно идёт везде одинаковое, ошибётесь на 1 букву будут ошибки.

ItemOnMap.prototype = Object.create(Window_Base.prototype);
ItemOnMap.prototype.constructor = ItemOnMap;

Дальше, если я правильно понимаю, копируются все параметры, свойства и собственно функции отрисовки системного окна в наш ItemOnMap. Дальше мы можем в нём менять всё что душе угодно, не боясь что это отобразиться свойствах всех остальных окошек.

ItemOnMap.prototype.standardPadding = function() {
return 0;
};

Например вот, по умолчанию отступ у всех окон 18px. Для того что бы наш текст и иконка были видны его стоит задать равным 0.

ItemOnMap.prototype.initialize = function(x, y, width, height) {
Window_Base.prototype.initialize.call(this, x, y, width, height);
this._id = 1;
};

Далее, как я понимаю идёт инициализация нашего окна, с такими же параметрами как у главного.

Ну и самое интересное. Окно появилось, и остаётся только вывести в него информацию:

ItemOnMap.prototype.update = function() {

Для этого необходимо в функции update написать то, что мы хотим вывести в нашем окне.

this.contents.clear();

Для начала его надо очистить, если этого не сделать всё будет накладываться друг на дружку и в конце концов будет выглядеть ужасно.

if ($gameSwitches.value(enableSwitchId)) {

Далее мы проверяем, разрешено ли показывать наше окно, если да, то:

this.show();

Покажем окно

this.resetTextColor();

Установим настройки (цвет, размер) текста по умолчанию

var itemId = $gameVariables.value(itemVarId);

Берём номер предмета, который нужно отобразить:

if (itemId == 0) {
itemId = 1;
}

Проверяем, что бы он не был равен 0, иначе будет ошибка.

this.drawIcon($dataItems[itemId].iconIndex, 15, 15);

Рисуем нашу иконку. $dataItems[itemId].iconIndex номер иконки предмета, и две последующие цифры это координаты x,y внутри нашего окна.

this.drawTextEx(":" + $gameVariables.value(countVarId), 52, 15);

Далее выводим наше число из переменной, и опять же два последующих числа это координаты x,y внутри нашего окна, но только уже для вывода текста.

} else {

Если же показывать окно нельзя, то

this.hide();

Скроем его и закончим данную функцию.

    }
}

Собственно на этом всё, остаётся только не забыть закончить главную функцию плагина:

})();

Как видите ничего сложного почти нет. Хотя по правде говоря было очень не просто сходу разобраться со всем этим, и если бы не потраченные дни предварительного разбирания и ковыряния VX Ace, мне бы не удалось это всё сделать так «быстро». Однако надо сказать огромное спасибо авторам, что так же как в VX Ace, RMMV название функций и переменных очень схожи, что конечно хоть и не сильно, но всё же упрощает написание плагинов под RMMV.

Если вдруг будут какие-то вопросы, постараюсь в меру своих сил ответить.

p.s. огромное спасибо всем кто мне помогал и помогает разбираться с премудростями RPG Maker, как здесь на форуме, так и в нашем горячо любимом чатике. Как видите мои глупые вопросы наконец вылились во что-то если не серьёзное, так во что-то не плохое это точно.


Небольшое дополнение:

Если необходимо, что бы окно так же отображалось во время боя, то для этого достаточно перед строчкой «function ItemOnMap() {»

Добавить, по аналогии с «_Scene_Map_createAllWindows»:

//Обновление окон во время битвы
var _Scene_Battle_createAllWindows = Scene_Battle.prototype.createAllWindows;
Scene_Battle.prototype.createAllWindows = function() {
_Scene_Battle_createAllWindows.call(this);
this._itemOnMap = new ItemOnMap(10,10, 120, 60);
this.addWindow(this._itemOnMap);
};

Правда появятся проблемы:

ItemOnMap

Наше окошко будет перекрывать системные сообщения о битве. Поэтому нужно указать где-то другое место.


Ссылки:

[RMMV] Пишем свой первый плагин: 14 комментариев

  1. Уведомление: Первые материалы | Mi Games

  2. Большое спасибо) Я включила плагин в своем проекте, но он, что то не работает( если, что у меня версия MV 1.0.1). Нажимала shift и ставила номер своего предмета в плагине, но как вхожу в игру ничего, может я делаю, что то не так?

    Нравится

    • В настройках плагина задаётся номер ключа switch который отвечает, за то будет ли отображаться информация на экране или нет. По умолчанию (после установки) это ключ номер 1.

      Нравится

  3. Я понимаю, что наверняка здесь нет ничего сложного, но все же мне как то не хватает урока. Я уже скачала чей то проект где используется похожий плагин и там все работает. Я поняла, что скорей всего проблема состоит в переменой которую надо задать. Если, что там номер иконки вписывается /I[X], но вписываю у себя номер своей иконки и что ваш плагин, что другой ничего изображения как нет так и не было. Поэтому я сошлась на том, что надо правильно задать в событии переменную и указать ее потом в плагине, и тут то у меня возникла загвоздка… Заранее спасибо)

    Нравится

    • Ну вообще, по большей части здесь рассказывалось для тех, кто хочет разобраться как устроены плагины внутри и самостоятельно начать их создавать. По поводу настроек тут действительно ничего сложного нет.

      Возможно поможет готовый пример проекта с настройками по умолчанию.

      https://yadi.sk/d/j7MrpQHK3GZNun

      На карте всего два персонажа, при обращении к первому показывается меню «включить/выключить» отображение на экране, при обращении ко второму добавляется или отнимается предмет.

      Вот скриншот диалога для первого персонажа:
      https://yadi.sk/i/gAtY3Mjz3GZPBE

      И соответственно для второго:
      https://yadi.sk/i/pVpzD_rj3GZPBG

      Нравится

    • Здравствуйте. Для того что бы показать или скрыть окошко используется ключ (switch) номер которого собственно из задаётся в настройках. Так же надо в настройках указать номер предмета (items) для отображения иконки. Ну и собственно там же задаётся номер переменной (variable) которая будет отображать количество.

      Нравится

Оставьте комментарий