Архив за Сентябрь 2017

Добавляем автоперенос в игру на Kirikiri

Как вы знаете, японцам перенос на новую строку по пробелу не очень-то нужен, как следствие практически во всех японских ВНках на Kirikiri перенос осуществляется побуквенно.

Сегодня я расскажу, как перестать расставлять переносы руками в переводе и начать жить 🙂

И, прежде чем мы начнём, давайте поблагодарим товарища Nagato, написавшего первоначальный код этой процедуры.

Итак, что нам понадобится.
Прежде всего, это полный текст строки. Думаете, это не проблема? Увы, бывает всё не так просто и в разных играх он может добываться разными методами. Сегодня речь пойдёт о том, как это сделано в игре Tsugihagi Make Peace — Pretending x Friendship.

Приступим.

Открываем в редакторе файл MainWindow.tjs (надеюсь, распаковка скриптов у вас вопросов не вызвала) и добавляем в самом начал, туда, где определяются переменные:


var textLine = void; // автоперенос: переменная для хранения полного текста текущего фрагмента
var wrapNum = 0; // автоперенос: переменная для хранения количества пробелов
var wrapPos = 0; // автоперенос: переменная для хранения позиции переноса
var oldLine = void; // автоперенос: переменная для хранения предыдущей строки
var splitLine = void; // автоперенос: переменная для хранения массива слов
var canWrap = true; // автоперенос: признак возможности переноса строки (есть ли в строке пробелы и дефисы)
var newPage = false; // автоперенос: признак перехода на новый экран при превышении количества строк, помещающихся на экране
var mustReline = false; // автоперенос: признак необходимости переноса на новую строку

Отлично. Далее, находим функцию, отвечающую за вывод имени персонажа. И пусть вас не смущает, что есть фрагменты, в которых имя не используется, - функция всё равно будет вызвана.
dispname : function(elm)
И первой же строчкой пишем:
textLine = getCurrentInfo().lineStr; // получаем строку, которая будет выводится в окне диалога

Если что-то пойдёт не так, вы можете, конечно, перенести эту строку в функцию посимвольного вывода (о которой речь пойдёт ниже), но тогда этот код будет исполнятся при выводе каждой буквы каждого фрагмента, что с точки зрения программирования отчаянное рукожопство 🙂

Ах да! Полезный хинт! Хотите вывести окно со значением той или иной переменной? Нет проблем! Используйте для этого следующую функцию:
System.inform(textLine);

С этим разобрались. Осталось немного.
Ищем функцию, отвечающую за вывод очередного символа, - ch : function(elm), и в ней после проверки на включённость режима пропуска (if (skipNoDisp) { return 0;}), добавляем следующий код:

/*
Wordwrapping code
Nagato (nagato@readyoursicp.com)
Adapted by DOOMer
*/
/* Важные замечания от DOOMer'а:
- в elm.text хранится текущий выводящийся символ, не весь текст фрагмента, как можно было бы подумать
- переменная textLine присвоена в функции dispname
*/
if (textLine != void)
{
if (textLine.indexOf(" ") != -1 || textLine.indexOf("-") != -1) // если в строке нет пробелов и дефисов, то идём дальше
{
if (oldLine != textLine) // если эта строка отличается от уже обработанной, то переопределяем переменные
{
var tempStr = void; // автоперенос: переменная, которая будет содержать неразбитую исходную строку без символов экранирования
oldLine = textLine; // переменная, хранящая в себе исходную строку
wrapNum = 0; // количество мест переносов
for (var i = 0; i < oldLine.length; i++) // проходим циклом по всем буквам строки
{
if (oldLine[i] != '\\') // тут удаляются все символы экранирования "\"
tempStr = "%s%c" . sprintf(tempStr, oldLine[i]);
}
if (tempStr === void || (tempStr.indexOf(" ") == -1 && tempStr.indexOf("-") == -1)) // если строка пустая или пробелов с дефисами нет, то переносы не требуются
canWrap = false; // переносы не нужны
else
{
canWrap = true; // переносы возможны
splitLine = tempStr.split("/ |-/"); // разбиваем строку по пробелам и дефисам, получаем массив слов
}
wrapPos = current.x;
}

if (canWrap) // если переносы возможны
{
if (elm.text == " " || elm.text == "-") // если текущий символ пробел или дефис
{
wrapNum++; // увеличиваем счётчик возможных переносов
wrapPos = current.x;
}
if (wrapPos + current.lineLayer.font.getTextWidth(splitLine[wrapNum]) > current.relinexpos) // если позиция переноса + ширина оставшегося текста (с учётом действующего шрифта) выходит за правую границу окна сообщений
{
if (current.lineLayer.font.getTextWidth(splitLine[wrapNum]) <= current.relinexpos) // если ширина строки меньше отведённого под неё окна, то ничего не переносим
{
if (elm.text == " ") // если перенос по пробелу
{
elm.text = ""; // выпиливаем символ пробела - он не нужен
mustReline = true; // устанавливаем признак необходимости перехода на новую строку
}
if (mustReline) // если установлен признак перехода на новую строку, то...
{
mustReline = false; // ...сбрасываем признак перехода на новую строку
historyLayer.reline(); // ...переходим на новую строку в истории
if (current.processReturn()) // ...переносим на новую строку в окне сообщений; если больше нет места для новых строк, то переходим на новый экран
{
newPage = true; // устанавливаем признак перехода на новый экран
return showPageBreakAndClear(); // выводим новый экран
}
}
if (elm.text == "-") // если перенос по дефису (например, в "ёк-макарёк"), то выпиливать символ дефиса не нужно, мало того перенос должен произойти после вывода дефиса, перед выводом следующего символа...
mustReline = true; // ...поэтому устанавливаем признак необходимости перехода на новую строку только здесь, уже после кода перехода на новую строку
}
wrapPos = current.x;
}
}
}

if (newPage) // если произошёл переход на новый экран, то сбрасываем переменные
{
elm.text = ""; // сбрасываем значение текущего символа
newPage = false; // сбрасываем признак перехода на новый экран
}
}

Вот и всё.
Поздравляю. Мы это сделали. Возможно, у нас даже всё работает 🙂

Суббота, 30 сен 2017 Переводы Ваш отзыв

Про Kirikiri, pimg и картинки, в нём содержащиеся

Как-то так получилось, что я оказался вовлечён в решение проблемы с редактированием графики в проекте перевода игры Tsugihagi Make Peace, а если точнее, с невозможностью запаковать картинки обратно в контейнер pimg.

Так как хорошая память — явно не про меня, решил написать этот пост, чтобы не забыть самому, да и кому-нить тоже, может, пригодится.

Распаковка скриптов.
Тут всё просто: arc_conv. Просто запускаем arc_conv.exe, тыкаем в диалоге выбора файлов на data.xp3 и ждём. В итоге получаем директорию data.xp3~, вот в ней всё. Если говорить о графике, то она находится в нескольких директориях, и, если с PNG-файлами всё ясно, то в директории uipsd видим странные файлы с расширением pimg, в которых содержится весь гуй. Вот эти pimg’и мы и будем раскуривать.

Итак, pimg — это своего рода контейнер, содержащий в себе изображения того или иного контрола (например, в title_bg.pimg содержится главное меню). Если заглянуть в него HxD, то увидим сигнатуру psb, хотя от этого не легче: все найденные в интернете средства для работы со скриптами Kirikiri пасовали перед этими файлами (речь о конкретной игре)… Все, кроме одного: https://github.com/marcussacana/KrKrZSceneManager.

Внимание! Так как большинство описанных ниже утилит по умолчанию создают результирующие файлы в разных директориях, предлагаю для всех последующих операций завести отдельную директорию и в неё перетаскивать те файлы, с которыми непосредственно работаете!

Качаем версию под Windows отсюда.
Нет, эта версия не умеет паковать обратно, так что либо качаем и собираем вот эту версию, либо ищем вот такую вот:

Называется «SCNEditor 2017», это допиленная нашим соотечественником под свои нужды версия.
Увы, найти первую версию под Windows мне не удалось, а второй со мной поделились частным порядком и распространять её я не считаю правильным, так что для вас я собрал из исходников первую.

Распаковываем. Запускаем.
Если вы таки раздобыли «SCNEditor 2017», то жмём ПКМ, «Open file», если качнули «Advanced SCN Editor», то просто в меню выбираем «File / Open .scn file». В открывшемся диалоге выбираем интересующий нас файл pimg (предварительно поменяв справа внизу в диалог тип файла с «KiriKiri Compiled Files» на «Pack of Resources»), например всё тот же title_bg.pimg. После этого получаем в директории программы кучу файлов с расширением res. Но что дальше с ними делать?
Внимание! Не закрывайте окно приложения до завершения операций над картинками данного контейнера!

А дальше мы качаем arc_unpacker отсюда.
Распаковываем.
На иконку arc_unpacker.exe мышкой кидаем все получившиеся в предыдущем пункте res-файлы. Рядом с ними получаем пачку файлов с расширением png.

<Надругательства над файлами изображений вырезаны цензурой>

Итак, мы допилили png-файлы напильником и нам надо упихнуть всё взад. Приступим.

Для начала качаем вот это.
Распаковываем.
Идём в директорию kirikiri2\tools и там запускаем krkrtpc.exe.
В левом и в правом столбцах выбираем TLG5. Тащим на это окно все png-файлы. Рядом с ними получаем файлы с расширением tlg.
Переименовываем (меняем расширение) их из png в res.

И последний этап. Помните, у нас там открыт SCN Editor? Идём в него, и либо снова ПКМ, либо в меню «Save file». Указываем наш pimg-файл (например, title_bg.pimg), и всё.

После этого полученный pimg-файл (ровно как и всё остальное), кладём в папочку patch и из корня игры запускаем arc_conv как-то так:
arc_conv.exe --pack xp3 _patch.xp3 patch.xp3
В результате создаётся файл patch.xp3, что и требовалось.

Запускаем игру, проверяем.

Блин, как-то всё сложно получилось 🙁
Но, стоит единожды разобраться, и всё вроде бы просто. Дерзайте! 🙂

Вторник, 26 сен 2017 Переводы Ваш отзыв

Поддержите меня!

Если вы хотите отблагодарить меня, можете закинуть денег мне на хостинг.
Делается это просто: в любом терминале ищем провайдера "Masterhost" и указываем лицевой счёт c123759 (обычно без первой буквы).

А я уж постараюсь и дальше стараться! :D

Яндекс.Деньги

41001543226857