Шёл 2019 год. Очередное переиздание Скайрима на микроволновке прекрасно продаётся. А что же Шинд, его предшественник аж 17-летней давности? Так и он тоже живее всех живых! Почему? Благодаря модам, разумеется. Так уж сложилось исторически: ТЕС – это моды, а моды – это ТЕС, и одно без другого немыслимо. Вы помните свои первые впечатления, когда узнали о существовании КС и открыли редактор? Это что же, все данные игры аккуратно рассортированы по таблицам, и я могу их менять? Как сам того пожелаю?! Я что, теперь разработчик игор? Ооо дааа! Нужен убер-меч? Пожалуйста! А может личный домик в Балморе? Заверните мне два! А что это тут за колонка «scripts»? Ну, if – это если, это понятно, тааак падажжите… ОГО! Так вот почему Фаргот крадётся к своему любимому пню! Так это что получается, я теперь не только гейм-дизайнер, но ещё и погроммист?! И ЧИМ был познан… И весь Аурбис разверзся пред волей нового Демиурга! Целые квестовые линейки, компаньоны, перки, крафт… да всё что угодно! Скрипты разрастались, превращаясь в монструозные громадины. Иногда многоэтажки из 30 if-elseif рушились под тяжестью собственного веса, а если не рушились, то подвешивали двемеропекарню секунд на 5. Ох, на какие только ухищрения не приходилось идти молодым ЧИМанутым Демиургам дабы привести свою Волю в исполнение! Узрев их, поездоголовый человек немедленно разогнался бы до околосветовой скорости от осознания своей непомерной нормальности и улетел бы за пределы Нирна, прямо вслед за двемерами. О, эврика! Долго ломал голову и придумал наконец, как отследить одно очень заковыристое событие! Сделаю я это по звукам, издаваемым жопками скрибов, долбящих ими по камням. Отслеживать, правда, придётся нонстопом, а потом проверять ещё полсотни сторонних условий, а скрибов в округе развелось нынче немало! И все с жопами! И все непрерывно стучат! Ах да, и ещё всё тело скрипта выполнялось каждый фрейм, а число самих фреймов у обладателей особо мощных двемеропекарен доходило до 15! Только вдумайтесь, какие вычислительные мощности расходовались вхолостую вместо того чтобы вычислять биткойн! MWSE оказался ложкой скуумы в бочке скаттла. Привнеся кучу новых функций (а вместе с ними и багов), он позволил особо смышлёным Демиургам вывести своё постижение ЧИМа на новый уровень и гульнуть на широкую ногу. Но скуумовая эйфория была недолгой. Чего не скажешь о послевкусии после многочисленных бочек со скаттлом. Да, у всего в этом мире есть предел. И предел скриптового языка КС был давно достигнут. Но хвала Троим! – всё изменилось с приходом MWSE 2.1. Ни говоря ни слова больше, ЧИМанутый Демиург вынул костыль из своей задницы… и создал папку Data Files\MWSE\mods\MyAwesomeMod Затем он создал в ней пустой текстовый файл main.txt и сменил его расширение на аббревиатуру языка Истинных Богов Кодинга – lua Получившаяся скрижаль main.lua по-прежнему прекрасно открывалась блокнотом, Демиург улыбнулся – ему не придётся страдать фигнёй с редакторами и компиляцией. Но пока что перед ним был чистый холст. Уже обладая опытом в постижении Языков Богов, Демиург понял, что быстрее всего это выйдет сделать на готовом примере. Открывая и изучая файлы других творцов, он чувствовал себя культистом карго в китайской комнате. И тут и там встречались интуитивно понятные элементы, но что с ними делать и как сложить в единую картину? Он мог изменить цифры в готовых функциях, и поначалу этого было достаточно. Однако ему хотелось большего осознания того, что он делает и зачем. Понемногу истина начала вырисовываться. Полотно окрасилось первыми строчками, суть которых являла собой общий шаблон, с помощью которого можно было достичь всего что угодно:
local function MyAwesomeFunction(e)
end
local function initialized(e)
event.register(" ", MyAwesomeFunction)
end
event.register("initialized", initialized)Суть была такова: Игра не будет прокручивать всё тело скрипта каждый фрейм. Двемеропекарня вздохнула свободно. От одного осознания этого факта число кадров в секунду сразу скакнуло аж до двадцати! В луа игра только регистрирует конкретные события – эвенты. И каждый раз когда указанное событие происходит, игра выполнит указанную функцию, в данном случае – MyAwesomeFunction. Да, названия и наполнение функций можно придумывать самому. Сейчас наполнение функции пустует, да и с отслеживаемым событием мы не определились. Для каждого эвента есть своё зарезервированное название, которое нужно знать точно. Так, посмотрим, что у нас в меню? https://mwse.readthedocs.io/en/latest/lua/event.html Неплохо, да? О, что это у нас тут? calcHitChance. Это же то о чём я думаю? Решено! Сколько себя помнил, всякие зумерки всегда плевались от боевой системы Шинда, не в силах попасть по грязекрабу даже 1 раз из 10. В этом даже было некоторое очарование, но быть может скайримодети в чём-то правы, и система попаданий действительно нуждается в починке? Итак. У каждого эвента есть определённый список игровых данных. Что же может предложить нам эвент calcHitChance? Смотрим: attackerMobile targetMobile target attacker hitChance Ридонли, ридонли, ридонли… о! hitChance не ридонли! Да, это означает, что его можно менять! Вот мы и подошли к сути работы с эвентами – граалю MWSE 2.1 – перехват игровых данных событий и изменение этих данных на свой вкус в собственноручно составляемых функциях! Оператор присвоения значения переменной – это знак равенства. Ну, сколько забабахаем? Не будем мелочиться! 100% шанса, 10 попаданий по грязекрабу из 10! Теперь наш манускрипт выглядит так, и он УЖЕ в полностью рабочем состоянии!
local function MyAwesomeFunction(e)
e.hitChance = 100
end
local function initialized(e)
event.register("calcHitChance", MyAwesomeFunction)
end
event.register("initialized", initialized)Да, вот так просто! Скрипт перехватил игровые данные о шансе на попадание и изменил их. И не один раз – а всегда. Функция вызывается при каждом событии удара, и теперь при каждом ударе шанс будет выставляться на сотку. А может, не стоит быть столь радикальными? Сотня шанса это хоть и прекрасно, и мы одной строчкой кода почти превратили Шинд в Подливион, но всё же – не пропадать ведь шарму промахов в упор? Особенно если этот механизм можно довести до ума. Изменим наш код следующим образом:
local function MyAwesomeFunction(e)
local hitreduction
if ((e.targetMobile.isMovingLeft or e.targetMobile.isMovingRight) and (e.targetMobile.isMovingForward == false)) then -- если цель движется влево или вправо и при этом не движется вперёд
hitreduction = e.targetMobile.agility.current / 2
else
hitreduction = 0
end
e.hitChance = 100 + (e.attackerMobile.agility.current / 2) - e.attackerMobile.blind - (e.targetMobile.sanctuary / 2) - (e.targetMobile.chameleon / 2) - hitreduction
end
local function initialized(e)
event.register("calcHitChance", MyAwesomeFunction)
end
event.register("initialized", initialized)Что всё это значит? Попробуем разобраться. * Сразу бросаются в глаза уже знакомые нам по esscript блоки if-end. else и elseif тоже в деле. Что изменилось? После условия обязательно надо прописывать ещё и оператор then. * Комменты идут после сдвоенного минуса -- * С пробелами и скобками тут куда больше вольностей. А вот регистр букв важен – его надо чётко соблюдать. * Операторы and и or, два барата-бубенца кастрированного хаджита вернулись на своё законное место! Больше не надо громоздить монструозные мгногоэтажки. Вообще, в луа как в полноценном языке есть много фич, недоступных ущербному esscript. И таймеры, боже, настоящие таймеры! Как же их не хватало в КС! * Нужна своя переменная? Провозгласите её с помощью волшебного слова local. Так мы прописали local hitreduction и ввели переменную hitreduction. Она будет доступна скрипту только в пределах той функции или блока if-end, в котором она была провозглашена. Так что если вы хотите, чтобы ваши локальные переменные были доступны для всего скрипта – провозгласите их в самом-самом начале файла. * А что это за вездесущие буковки e? В MWSE для Шинда есть очень много зарезервированных названий игровых данных. Многие данные представляют собой целые базы данных. Сначала пишем название базы данных, затем точка без пробелов, затем опять же без пробелов название переменной внутри этой базы, причём сама эта переменная в свою очередь тоже может оказаться базой данных со своими переменными внутри. Это как путь к файлам в многочисленных папках. Укажите весь путь через точки. Так e – это база данных всего события. В нашем примере, события расчёта шанса на попадание. Какие переменные есть внутри этой базы данных? Мы их уже видели: attackerMobile targetMobile target attacker hitChance Нам пока нужно знать что в этом конкретном событии attackerMobile означает атакующего, targetMobile означает цель атаки, а hitChance – собственно сам шанс на попадание. Нужно нам узнать, сколько у атакующего текущая ловкость – прописываем: e.attackerMobile.agility.current Нужно узнать, сколько у защищающегося эффекта светоча – прописываем: e.targetMobile.sanctuary Где же посмотреть все зарезервированные имена баз данных и их содержимое? Для мобильного актёра (коим и являются наши e.attackerMobile и e.targetMobile) например здесь: https://mwse.readthedocs.io/en/latest/lua/type/tes3/mobileActor.html А для остальных типов данных – здесь: https://mwse.readthedocs.io/en/latest/lua/type.html Теперь, зная всё это, мы можем прочесть скрипт и понять, что мы сотворили. Сначала проверили, движется ли защищающийся влево или вправо и не движется ли он при этом вперёд? Если да, то присвоили созданной нами переменной hitreduction значение половины от текущей ловкости защищающегося. А если нет, то присвоили hitreduction 0. Потом вычисляем сам шанс на попасть. Взяли 100%, прибавили половину от текущей ловкости нападающего, отняли величину слепоты нападающего, отняли половину от величины светоча и хамелеона защищающегося, и наконец отняли величину нашей переменной hitreduction. Вуаля! Теперь очень ловкий персонаж получает нехилый шанс уклониться от атаки, если будет правильно двигаться. Светоч и хамелеон защищающегося, а также слепота и ловкость нападающего так же окажут эффект. Вообще-то вы можете придумать свою формулу, поставив зависимость шанса на попадание от почти чего-угодно, хоть от погоды на Массере. Доступных событий множество – вы можете легко изменять наносимый урон, параметры объектов и актёров, раздавать и удалять предметы и заклинания, менять прирост опыта в навыках, разрешать и запрещать использование предметов, отслеживать состояние боя, сохранения, загрузку, нажатие определённых кнопок и многое, многое другое… Особо искушённые творцы сумеют изменить интерфейс, создавать собственные продвинутые меню, добавлять новые навыки и даже новые магические эффекты! Открывающиеся возможности просто поразительны. Теперь же, когда вы узрели силу луа в самых элементарных алгоритмах, вы получите заряд к познанию большего. Изучите общие принципы языка луа, посмотрите гайды от авторов МВСЕ. Постарайтесь прочесть несколько уже готовых плагинов, например эти: https://www.nexusmods.com/morrowind/mods/47056 https://www.nexusmods.com/morrowind/mods/47035 https://www.nexusmods.com/morrowind/mods/47062 Если удастся – то вы уже освоили достаточно и теперь можете сотворить что-то своё. Так сделайте это и Живите в Своём Собственном Благословлённом Мире, который Сами и Создали!