mintmike Опубликовано 4 января, 2020 Жалоба Поделиться Опубликовано 4 января, 2020 (изменено) MWSE - "расширитель скриптов Мирровинда" Описание функций MWSE: https://mwse.github.io/MWSE/apis/tes3/ Настройки игры, Game Settings (глобальные переменные): GMST List https://mwse.github.io/MWSE/references/gmst/ MWSE, начиная с версии 2.1, поддерживает простой и быстрый скриптовый язык Lua. Уроки задумывались как справочник, идут в целом по усложнению, но читать можно с любого места. Самая лучшая книга по Lua от его создателя: Р.Иерусалимски, Программирование на языке Lua Руководство на русском языке: https://lua.org.ru/contents_ru.html Сокращенное руководство: https://lua.org.ru/m...little-lua-book *** Урок 1: Сообщения *** Для запуска lua-скриптов, вам не нужно создавать мод в Construction Set. Достаточно открыть блокнот и записать, к примеру, вот такую функцию: local function myFun(e) mwse.log("Запущено сохранение: %s", e.filename) end event.register("loaded", myFun) Мы создали функцию local myFun(e), которая пишет имя загруженного в игре сохранения в лог-файл (по адресу <Путь к папке Morrowind>\MWSE.log). local - означает, что функция локальная (не может быть вызвана из других файлов), e - информация события (типа event), которая будет передаваться в вашу функцию, %s - команда форматирования, которая вставляет вместо "%s" строку из переменной e.filename. event.register - регистрирует вашу функцию для события (привязывает функцию к событию) "loaded" - имя события, данное событие вызывается при окончании загрузки сохранения в игре. Каждый раз, при возникновении события "loaded"(загрузке сохранения) будет запускаться ваша функция. Итак, первый lua-скрипт к Морровинду написан. Сохраняем файл как: <Путь к папке Morrowind>\Data Files\MWSE\mods\<ваш мод>\main.lua Имя основного файла должно быть обязательно "main.lua", таковы требования МыВСЕ. Имя подкаталога <ваш мод> может быть любым. При старте игры MWSE сканирует все подкаталоги ..\Data Files\MWSE\ и компилирует найденные скрипты. Ваш скрипт также скомпилируется, и если синтаксических ошибок нет, скрипт запустится один раз. Что означает "скрипт запустится один раз"? Это значит, что ваш файл исполнится при старте игры, лишь раз. Но так как фунция "myFun" будет зарегистрирована для события"loaded", то и Запускаться она будет каждый раз по событию. При старте игры функция "myFun" вызвана не будет. Заходим в Морровинд, загружаем любое сохранение и выходим. Где-то в середине файле логов MWSE.log должна появится запись: "Запущено сохранение: <имя файл сохранения>" Если допущена ошибка, вы получите сообщение в файле логов: <Путь к папке Morrowind>\MWSE.log Используйте поиск по тексту с именем <вашего мода>, чтобы быстро отыскать сообщения об ошибках в вашем lua-коде. В логах после слова Error указано описание ошибки и строка, в которой она возникла. Исправляйте ошибку и запускайте Морровинд снова. Ну что же. Поздравляю, первый lua-скрипт для Морровинда создан! Давайте запустим ещё какой-нибудь пример. Замените текст в вашем файле, или просто добавьте ниже: local function showMessage(e) tes3.messageBox("Вы взяли " .. tes3.getMobilePlayer().readiedWeapon.object.id) end event.register("weaponReadied", showMessage) Здесь при экипировке оружия будет выведено сообщение на экран. Событие "weaponReadied" вызывается, когда орудие взято в руки готово к атаке. .. - две точки есть операция слияния строк. id является строкой getMobilePlayer() - возвращает ссылку на mobile игрока (на вашу мобилку :), ваш игровой болванчик, а точнее тело) Подробнее о типах объектов, актеров, предметов в следующих уроках. *** Урок 2: События *** Вот все типы событий: https://mwse.github.io/MWSE/references/events/ Рассмотрим с дюжину основных и как они работают: "loaded" - игра загружена (из сохранения) "initialized" - игра инициализирована, .esm и .esp файлы загружены "simulate" - начало каждого игрового кадра (не пауза и не меню) "enterFrame" - начало любого кадра "skillRaised" - произошло повышение скила "attack" - ближняя физ атака (с участием актера или существа, не обязательно игрока) "activate" - активация (кто-либо нажал на активатор) "activationTargetChanged" - в прицеле игрока объект для активации изменился "spellCast" - кто-либо начал произносить заклинание "magicCasted" - заклинание успешно произнесено или алхимия дала эффект "equip" - момент экипировки предмета (начало момента) "keyDown" - нажата клавиша на клавиатуре "menuEnter" - вызвано меню (на пр.кн. мыши) "weaponReadied" - экипировано оружие На событиях держится все обращения от MWSE к вашему коду. event.register(<событие>, <функция>) -- регистрирует имя вашей функции в специальной таблице Событие одно, а привязанных к нему функций может быть много. Функции даже могут иметь одни и те же имена в разных файлах. Все они будет вызываться при каждом наступлении условий и возниконвении связанного с ними события. Таким образом, для каждого события MWSE вызывает свои, зарегистрированные именно для него функции. Мы можем очистить таблицу для конкретного события, написав: event.clear("имя события") Все запомненные для события функции будут отменены. *** Урок 3: Клавиши *** Коды всех клавиш есть тут: https://mwse.github.io/MWSE/references/scan-codes/ Для клавиатуры нам достаточно двух событий: event.register("keyDown", checkKeys) - вызывается при нажатии клавиши event.register("keyUp", checkKeys) - вызывается при отпускании клавиши Как сделать так, чтобы нажатие на кнопку клавиатуры что-нибудь совершало? local function checkKeys(e) -- pressed 'V' if (e.keyCode == 47) then tes3.messageBox("You pressed 'V'") end end event.register("keyDown", checkKeys) Функция checkKeys(e) проверяет код нажатой клавиши. Если это код клавиши 'v', то будет выведено сообщение. Когда несколько клавиш задействовано, то удобнее оформить так: local function dance() ... end local function savePoint() ... end local function createItem() ... end local function checkKeys(e) -- pressed 'U' if (e.keyCode == 22) then dance(); return end -- pressed 'I' if (e.keyCode == 23) then createItem(); return end -- pressed 'O' if (e.keyCode == 24) then savePoint(); return end end local function onLoaded() event.register("keyDown", checkKeys) end event.register("loaded", onLoaded) Ну что, готовы к чему-то побольше, навроде циклов? *** Урок 4: Казначей в локации *** Давайте напишем функцию, которая просканирует локацию и выведет в лог имена и координаты всех и всего найденного в ней. Зарегистрируйте функцию самостоятельно, на событие "loaded". local function makeLog() local cell = tes3.getPlayerCell() -- получаем ячейку нахождения игрока local step = 1 -- это счетчик шагов цикла local str = tostring(step) -- запишем значение счётчика в строку str for ref in cell:iterateReferences() do if (ref.object) then str = str .. " type: " .. tostring(ref.object.objectType) str = str .. " name: " .. ref.object.name str = str .. " id: " .. ref.object.id str = str .. " pos: " .. tostring(ref.position) if (ref.object.objectType == tes3.objectType.npc) then str = str .. " " .. tostring(ref.object.race.name) end print(str) -- печатам нашу строку в лог step = step + 1 str = tostring(step) -- перезапишем всю строку, записав туда снова значение нашего счётчика end end end Данный цикл на каждом шаге печатает в лог-файл новую заполненную строку. Функция print() после вывода сама переходит в начало след.строки без доп.команд. ref - пустая новая переменная-ссылка. iterateReferences() - метод для перебора ссылок на все объекты в ячейке. Методы вызываются через двоеточие. Цикл for ref in cell:iterateReferences() do при каждом шаге кладёт в пустую переменную ref новую ссылку на очередной объект до тех пор, пока объекты не закончатся. do ... end - тело цикла. В теле цикла мы проверяем if (ref.object) - содержит ли наша ссылка объект. Если объект пустой (nil то есть нуль), то условие будет ложным (false), и мы переходим далее, на новый шаг. Если ref.object отлично от нуля, условие истинно (true), и выполняется всё, что между then ... end. tostring(ref.object.objectType) - дополняет нашу строку типом объекта. objectType является числом, поэтому мы переводим его в строку c помощью tostring() if (ref.object.objectType == tes3.objectType.npc) then - проверяет, равен ли тип объекта npc. Если истина, то дополним нашу строку расой объекта. objectType - по сути одно из чисел из таблицы ниже. Таблица находится по адресу tes3.objectType. Это таблица типов (неполная, на самом деле типов больше, см. 7 урок). Value Code Meaning 1230259009 ACTI Activator 1212369985 ACTI Alchemy 1330466113 AMMO Ammunition 1095782465 ACTI Apparatus 1330467393 ARMO Armor 1263488834 BOOK Book 1414483011 CLOT Clothing 1414418243 CONT Container 1095062083 CREA Creature 1380929348 DOOR Door 1380404809 INGR Ingredient 1129727308 LEVC Levelled Creature 1230390604 LEVI Levelled Item 1212631372 LIGH Light 1262702412 LOCK Lockpick 1129531725 MISC Misc Item 1598246990 NPC_ NPC -- наш случай 1112494672 PROB Probe 1095779666 REPA Repair Item 1414546259 SCPT Script 1195658835 SNDG Sound Generator 1279610963 SPEL Spell 1413567571 STAT Static 1346454871 WEAP Weapon ***Урок 5 Кровати-Двери-Сундуки *** В предыдущем уроке мы нашли не одну сотню объектов. Давайте присмотримся к некоторой мебели. Вдруг не для каждого нпс найдется кровать или спальник? Где им спать, в сундуках? Ах да, в Морровинде время же заморожено, никто не спит, кроме нашего героя. Вот беда. Может быть, мы поправим это в последнем уроке? local beds = 0 local doors = 0 local chests = 0 Три локальные переменные для мебели. Если убрать слово local, то переменные станут глобальными (доступными из любого модуля). Локальные переменные могут быть свободно доступны только функциям, определенным в их зоне видимости (то есть в нашем файле). Как выделить из всех предметов, например, кровати? У них имя object.name = 'Кровать'. Но это ненадежно, вдруг имена на английском. Удобнее ориентироваться по id. id для каждого предмета уникален. Как найти слово в строке id? Для поиска в строке существует: string.find(id,'[Bb]ed') -- [Bb] - означает один любой из символов 'B' 'b' Если в строке id есть слово "bed" или "Bed", функция вернёт нам 2 числа (или nil, если ничего не найдено): -- pos1 - на каком символе начинается наше слово -- pos2 - на каком символе заканчивается наше слово local pos1, pos2 = string.find(id,'[Bb]ed') Теперь давайте дополним функцию makeLog: local function makeLog() local cell = tes3.getPlayerCell() local step = 1 local str = tostring(step) for ref in cell:iterateReferences() do if (ref.object) then if (ref.object.name) then -- не у всех предметов имеется поле name str = str .. " " .. ref.object.name end str = str .. " id: " .. ref.object.id if (ref.object.class) then -- не у всех предметов имеется поле class str = str .. " class: " .. ref.object.class.name end if (ref.object.objectType == tes3.objectType.npc) then str = str .. " " .. tostring(ref.object.race.name) end if (string.find(ref.object.id,'[Bb]ed')) then -- если находим кровать beds = beds + 1 str = str .. " BED#" .. tostring(beds) .. "" elseif (string.find(ref.object.id,'[Dd]oor')) then -- иначе если находим дверь doors = doors + 1 str = str .. " DOOR#" .. tostring(doors) elseif (string.find(ref.object.id,'[Cc]hest')) then -- иначе если находим сундук chests = chests + 1 str = str .. " Chest#" .. tostring(chests) end print(str) step = step + 1 str = tostring(step) end end tes3.messageBox("Найдено кроватей %d, дверей %d, сундуков %d", beds, doors, chests) end %d - на это место будет вставлено число из переменной, переданной в функцию messageBox следом за строкой (процесс называется "форматирование строки"). Запускаем, проверяем! Если появились хорошие идеи, пишите в комментариях. Кого создать? *** Урок 6: Bторой муж для Тойвалэ Отрален*** Из урока 4 у нас есть лог объектов в локации, из него можно узнать id - уникальные идентификаторы мировых персонажей, тварей, мебели, и прочих вещей. Давайте заглянем к Арриллу на огонёк и клонируем его 🙂 Надеюсь, его жена не упадёт в обморок. Или это не его жена стоит рядом? --[[ Комментарий. tes3.createReference({...}) - это функция для создания кого-либо, чего-либо, на вход получает таблицу {...} Можно записать без круглых скобок tes3.createReference{...} Делает то же, что и mwscript.PlaceAtPC или xPlace. ]] local ref = tes3.createReference { -- начало таблицы object = "arrille00000000", -- первый элемент таблицыб можно элементы менять местами, порядок не важен position = tes3.getPlayerRef().position, orientation = tes3.getPlayerRef().orientation, cell = tes3.getPlayerCell(), scale = 1 } -- конец таблицы tes3.messageBox("Привет, Тойвалэ!") end Не вздумайте запускать эту функцию не в начальной локации. Аррилл против такого! Нужны данные из незагруженной ячейки игрового мира. Morrowind чего-то не находит в доступе и крашится. Жалко. Ладно. Тут у нас между фигурными скобками целая таблица с полями object, - сюда подойдет id объекта или объект типа tes3physicalObject position, - позиция создаваемого объекта, tes3vector3(x,y,z) orientation, - отриентация создаваемого объекта, tes3vector3(x,y,z) cell, - id ячейки или ячейка tes3cell scale - масштаб, обычно у всех = 1 Как нам усовершенствовать наш код, чтобы клонировать кого угодно от бутылки до Вивека? Сделаем в следующих уроках ^^) Типы tes3объектов (tes3.objectType) -- '>>' обозначим наследование (в исходниках MWSE) GMST (objectType: 'TSMG') PathGrid (objectType: 'DRGP') Region (objectType: 'NGER') Birthsign (objectType: 'NGSB') BaseObject >> Object >> Reference (objectType: 'RFER') BaseObject >> Object >> Spell (objectType: 'LEPS') BaseObject >> Object >> Enchantment (objectType: 'HCNE') BaseObject >> Object >> PhisicalObject PhisicalObject >> Activator (objectType: 'ITCA') PhisicalObject >> Actor >> Container (objectType: 'TNOC') PhisicalObject >> Actor >> Creature (objectType: 'AERC') PhisicalObject >> Actor >> NPC (objectType: '_CPN') PhisicalObject >> BodyPart (objectType: 'YDOB') PhisicalObject >> Door (objectType: 'ROOD') PhisicalObject >> Land (objectType: 'DNAL') PhisicalObject >> LandTexture (objectType: 'XETL') PhisicalObject >> LeveledCreature (objectType: 'CVEL') PhisicalObject >> LeveledItem (objectType: 'IVEL') PhisicalObject >> Static (objectType: 'TATS') PhisicalObject >> Item >> Armor (objectType: 'OMRA') PhisicalObject >> Item >> Alchemy (objectType: 'HCLA') PhisicalObject >> Item >> Apparatus (objectType: 'APPA') PhisicalObject >> Item >> Book (objectType: 'KOOB') PhisicalObject >> Item >> Clothing (objectType: 'TOLC') PhisicalObject >> Item >> Ingredient (objectType: 'RGNI') PhisicalObject >> Item >> Light (objectType: 'HGIL') PhisicalObject >> Item >> Lockpick (objectType: 'KCOL') PhisicalObject >> Item >> Lockpick >> Probe (objectType: 'BORP') PhisicalObject >> Item >> Misc (objectType: 'CSIM') PhisicalObject >> Item >> Weapon (objectType: 'PEAW') Ammo (objectType: 'OMMA') Repair (objectType: 'APER') BaseObject >> AnimationGroup BaseObject >> Class (objectType: 'SALC') BaseObject >> Cell (objectType: 'LLEC') BaseObject >> Dialogue (objectType: 'LAID') BaseObject >> DialogueInfo (objectType: 'OFNI') BaseObject >> Faction (objectType: 'TCAF') BaseObject >> MagicEffect (objectType: 'FEGM') BaseObject >> Quest (objectType: 'SEUQ') BaseObject >> Global (objectType: 'BOLG') BaseObject >> MagicSourceInstance (objectType: 'LLPS') BaseObject >> Race (objectType: 'ECAR') BaseObject >> Script (objectType: 'TPCS') BaseObject >> Skill (objectType: 'LIKS') BaseObject >> Sound (objectType: 'NUOS') BaseObject >> SoundGenerator (objectType: 'GDNS') MobileObject >> MobileActor >> MobileNPC (objectType: 'HCAM') MobileObject >> MobileActor >> MobileNPC >> MobilePlayer (objectType: 'PCAM') MobileObject >> MobileActor >> MobileCreature (objectType: 'RCAM') MobileObject >> MobileProjectile >> MobileSpellProjectile (objectType: 'JRPM') ***Урок 7: Что от чего происходит в мире tes3 *** Все что мы видим и слышим в мире tes3, MWSE разделяет на tes3объекты разных типов (см. таблицу tes3типов выше). GMST -- глобальные переменные игры (objectType: 'TSMG') PathGrid -- сетка для поиска пути актёрами (objectType: 'DRGP') Region -- задаёт погоду и звуки региона (objectType: 'NGER') Birthsign -- знак рождения героя (objectType: 'NGSB') BaseObject -- базовый объект для остальных объектов MobileObject -- мобильный объект - это подвижная модель, 'болванка', ваше tes3 (или чьё-то) бренное тельце, а также снаряд (objectType: 'XXXX') - это 4 символа, которые также можно представить уникальным числом. Таблица с типами находится по адресу tes3.objectType. Тип необходим для выведения разновидностей объектов и проверки в программе, с каким объектом мы имеем дело. Давайте рассмотрим основные важные типы поближе. tes3.objectType.object BaseObject >> Object >> Reference (objectType: 'RFER') BaseObject >> Object >> Spell (objectType: 'LEPS') BaseObject >> Object >> Enchantment (objectType: 'HCNE') BaseObject >> Object >> PhisicalObject Как мы видим, объект (tes3object) происходит от базового объекта и может быть ссылкой (reference), заклинанием, зачарованием или физическим объектом. Физические объекты подразделяются на (см.таблицу): активаторы, актёров, части тела, двери, мировые поверхности, их текстуры, статики (неподвижные объекты), вещи, а также уровневые существа и уровневые вещи. Почти всё, что передставлено в Construction Set, является физическим объектом (tes3.objectType.phisicalObject). Все объекты типа tes3object имеют три поля: object.id (string) -- "айди", идентификатор object.objectType (number) -- tes3-тип это просто уникальное число из таблицы object.sourceMod (string) -- мод-источник объекта Кстати объекты actor, npc не являются видимыми моделями, движущимися игре, а являются описаниями, содержащими имя и прочие свойства. "Болванчиков" представляют объекты tes3mobileObject. tes3.objectType.mobileObject Представляет свойства подвижной модели персонажа, существа, выпущенной стрелы. Имеет свойства для управления движением и положением в пространстве. https://mwse.github.io/MWSE/types/tes3mobileObject/?h=mobileo MobileObject >> MobileActor >> MobileNPC (objectType: 'HCAM') -- тело персонажа MobileObject >> MobileActor >> MobileNPC >> MobilePlayer (objectType: 'PCAM') -- тело персонажа игрока MobileObject >> MobileActor >> MobileCreature (objectType: 'RCAM') -- тело сщество MobileObject >> MobileProjectile >> MobileSpellProjectile (objectType: 'JRPM') -- тело снаряда Тело персонажа имеет: инвентарь атрибуты (сила, ловкость, и т.д.) скилы наложенные эффекты список друзей список врагов управляющие флаги AI данные tes3.objectType.reference Очень нужный и важный тип tes3reference, или tes3-ссылка (далее просто "ссылка"). https://mwse.github.io/MWSE/types/tes3reference/ С помощью этого объекта из функции в функцию передаётся информация об остальных tes3объектах: вещах, актёрах (tes3actor), заклинаниях, генераторах звука и т.п. Давайте взглянем на её происхождение: BaseObject >> Object >> Reference (objectType: 'RFER') Как мы видим, ссылка имеет tes3тип (tes3reference) и происходит от объекта, а он в свою очередь от базового объекта. Это означает, что можно написать: ref.id -- то же, что и ref.object.id ref.objectType -- а вот тип у ссылки свой (objectType: 'RFER') ref.sourceMod -- то же, что и ref.object.sourceMod Поскольку ссылка - объект, настроенный на другой объект, то в её свойствах мы айди самого объекта, мод и т.п. также. Все кроме типа, тип у ссылки собственный. Ссылок на один и тот же объект может быть много. Обращаться через ссылку очень удобно. Например, мы можем проверить ref, на кого или что она настроена: if (ref.objectType == tes3.objectType.сontainer) then ... end -- выполнится, если ref это контейнер if (ref.objectType == tes3.objectType.phisicalObject) then ... end -- выполнится, если ref физ.объект if (ref.objectType == tes3.objectType.light) then ... end -- выполнится, если ref источник света Тут последняя версия уроков, а также рассортированное описание TES3 классов: https://yadi.sk/d/pNaDhws2m1-6AA См.ниже в теме: Урок 8: "Как создать / прочитать текстовый файл" Урок 9: "Как создавать окна, меню, кнопки в Морровинд" Урок 10: "Разговоры" Изменено 23 июля, 2023 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
РЕДМЕНЪ Опубликовано 4 января, 2020 Жалоба Поделиться Опубликовано 4 января, 2020 Спасибо большое, осталось найти досуг, чтобы почитать и постараться понять :). Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 6 января, 2020 Автор Жалоба Поделиться Опубликовано 6 января, 2020 У кого вопросы по lua-базовым вещам читайте в руководстве вот эти разделы: 3.4 – Выражения, все виды операторов3.4.9 – Конструкторы таблиц (как создавать {...} таблицы)3.4.8 – Приоритет операторов (что быстрее выполнится + или >= и т.п)3.5 – Правила видимости (создание/удаление локальных переменных) Ссылка на комментарий Поделиться на другие сайты Поделиться
aL☢ Опубликовано 6 января, 2020 Жалоба Поделиться Опубликовано 6 января, 2020 Спасибо огромное за дельный мануал!! Жаль нет лайков у постов. Хотелось бы еще узнать больше о создании собственных новых навыках. Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 14 января, 2020 Автор Жалоба Поделиться Опубликовано 14 января, 2020 (изменено) Спасибо! Добавил ссылку на последнюю версию уроков, а также более удобно рассортированную документацию по TES3 классам в txt виде. https://www.fullrest.ru/forum/topic/3105-prosby-o-perevode-plaginov-ili-perevedite-po/?p=997387https://www.nexusmods.com/morrowind/mods/47111Я смотрю, набирает популярность и уже включен в требования некоторых многообещающих плагинов, например, https://www.nexusmods.com/morrowind/mods/47480 Очень интересный плагин про маг эффекты. Добавлят заклинания управления погодой, призыва существ из Tamriel Rebuilt, телепортации в города за пределами Вварденфелла, просмотр состояния противника, а также функции для добавления собственных эффектов и заклинаний. Использует недокументированную (ещё) функцию addMagicEffect, которая позволяет добавлять новые эффекты. Примеры использования можно посмотреть в скриптах мода. tes3.addMagicEffect { name, -- string, id, -- number, EffectID description, -- string, описние lighting -- vector3, цвет свечения, RGB icon, -- string, путь к иконке particleTexture , -- string, путь к текстуре частиц baseCost, -- 1.0f по умолчанию school, -- 0 по умолчанию size, -- 1.0f по умолчанию sizeCap, -- 1.0f по умолчанию speed, -- 1.0f по умолчанию castSound, -- string, звуки boltSound hitSound, areaSound, castVFX, -- сами эффекты, PhysicalObject boltVFX, hitVFX, areaVFX, allowEnchanting, -- дальше идут флаги (true/false) allowSpellmaking, appliesOnce, canCastSelf, canCastTarget, canCastTouch, casterLinked, hasContinuousVFX, hasNoDuration, hasNoMagnitude, illegalDaedra, isHarmful, nonRecastable, targetsAttributes, targetsSkills, unreflectable, usesNegativeLighting onTick, onCollision } Можно надеяться, что появится и функция типа addNewSkill ... Изменено 19 января, 2020 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 1 апреля, 2020 Автор Жалоба Поделиться Опубликовано 1 апреля, 2020 (изменено) Урок 8: "Как создать / прочитать текстовый файл" --=== Функции Lua для работы с файлами ===-- io.input() -- задаём файл для чтения io.output() -- задаём файл для записи io.read() -- читаем строку из файла io.write() -- пишем строку в файл Для примера посчитаем количество строк и слов в интересующем нас файле, пусть он называется inp.txt Запускать программу будем на компиляторе lua53.exe (последняя версия). 1. Скачаем, если у вас его нет. Скачать можно тут: http://luabinaries.s...t/download.html 2. Создаём в одном каталоге с lua53.exe новый текстовый файл с текстом программы, например "prog.lua": io.output('out.txt') -- задаём файл с результатом io.input('inp.txt') -- откуда будем читать local str = io.read() -- читаем первую строку из файла local snum = 0 -- количество строк local wnum = 0 -- количество слов while str do -- цикл исполняется пока str не равно nil snum = snum + 1 -- увеличиваем счётчик строк на 1 for s in str:gmatch("[%w'-]+") do -- для каждой найденной в строке цепочки цифро-букв, "'" и "-" if s:find("%a") then -- если цепочка имеет хотя бы одну букву wnum = wnum + 1 -- увеличиваем счётчик слов на 1 end end str = io.read() -- читаем следующую строку end io.write('Всего строк в файле ',snum,'\n') -- выводим результат в файл io.write('Bсего слов в файле ',wnum,'\n') -- \n -- служебный символ перехода на новую строку print('Всего строк в файле',snum,' всего слов в файле',wnum)Замечание: все файлы должны лежать в одной папке. 3. Перетаскиваем мышкой нашу программу "prog.lua" на lua53.exe и отпускаем, рядом появляется наш файл с результатом "res.txt". 4. Для повторных запусков можно создать prog.bat файл, и запускать нашу програму нажатием на него lua53 prog.lua cmd Изменено 1 апреля, 2020 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
aL☢ Опубликовано 3 апреля, 2020 Жалоба Поделиться Опубликовано 3 апреля, 2020 Спасибо огромное за ваш труд! Ждем еще новых уроков! Интересует, как привязать константу к новому навыку. Когда я увеличиваю простым скриптом константу - растет и новый навык в меню Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 3 апреля, 2020 Автор Жалоба Поделиться Опубликовано 3 апреля, 2020 Спасибо огромное за ваш труд! Ждем еще новых уроков! Интересует, как привязать константу к новому навыку. Когда я увеличиваю простым скриптом константу - растет и новый навык в меню <- это интересно.Насколько я понял, нужно привязать значение скила к одной из игровых константВ модуле \MWSE\lib\OtherSkills\common.lua, функция updateSkillList выводит список скилов.Нужно, чтобы значение скила обновлялось в соответствии с константой: this.updateSkillList = function () ... for i,skill in pairs(this.otherSkills) do if skill.active == "active" then if skill.name == "<имя скила>" then skill.value = tes3.gmst.<имя константы> -- << вставить вот эту строку ... Если нужна помощь, пиши лс Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 3 апреля, 2020 Автор Жалоба Поделиться Опубликовано 3 апреля, 2020 (изменено) Про что сделать следующий сложный урок? (не более 2 вариантов в ответе, или свои варианты) 1. Как правильно подключить и использовать mcm (Настройка Модов в Главном меню)2. Как создавать окошки и кнопочки. Внедрим кнопку в окно с диалогом с нпс. По нажатию он будет нам отвечать про погоду и силу ветра.3. Как заставить нпс`а: упасть на кровать и лежать на ней ничком.4. Появляется и исчезает бог (Вивек, например), все сбегаются к месту силы.5. Как работает самый частый пакет ии: AIWander (шататься окрест)6. Как работает AIActivate. Как заставить нпс`а выйти на улицу, а Фаргота бегать по кругу.7. Выделить стат-ку из редактора и посмотреть: сколько и каджитов и орков на Ввардэнфелле и чем они занимаются, какой ср.уровень, скорость, магия. ... итак, ваш выбор? Но сначала простой урок номер 9: "Как создавать окна, меню, кнопки в Морровинд" Самый короткий вариант создать окошко. Назовём его Винни. Короткий плагин из десятка строчек: local winny local function showWinny() winny = tes3ui.createMenu -- создается новое меню (просто окно) { id = tes3ui.registerID('winny'), -- нашему окну выдаётся id, по которому можно затем к нему обращаться fixedFrame = true, -- с жёстко фиксированной рамкой } winny:updateLayout() -- обновить элементы на экране end event.register("keyDown", showWinny, {filter = 44}) -- при нажатии на "z" будет появляться ВинниЗапускаем Главное меню Морровинд. Жмакаем на "z". Появляясь, наше окно не хочет исчезать. Давайте добавим текст в наше окно, а также кнопку "назад": local winny local function hideWinny() winny:destroy() -- функция для удаления Винни end local function showWinny() winny = tes3ui.createMenu { id = tes3ui.registerID('winny'), fixedFrame = true, } winny:createLabel{ text = 'winny'} -- добавляем текст в окно local button = winny:createButton -- добавляем кнопку { id = tes3ui.registerID('Cancel'), text = 'Назад', } button:register("mouseClick", hideWinny) -- при щелчке по кнопке будет вызываться hideWinny() winny:updateLayout() end event.register("keyDown", showWinny, {filter = 44}) -- z Теперь, если нажать "z" в игре, окно появляется и маячит посреди экрана. Как перейти в режим меню? tes3ui.enterMenuMode(winny) -- попадаем в режим, когда игра на паузе и появляется указатель мыши для управления в меню Добавим ещё несколько полезных строк: local winny local winny_id -- сохраним id окна отдельно local function hideWinny() winny:destroy() if tes3ui.menuMode then tes3ui.leaveMenuMode() end -- выходим из режима меню end local function showWinny() if tes3ui.findMenu(winny_id) then return end -- если окно уже есть, не создаём его повторно winny_id = tes3ui.registerID('winny') winny = tes3ui.createMenu { id = winny_id, fixedFrame = true, } winny:createLabel { text = 'winny'} local button = winny:createButton { id = tes3ui.registerID('Cancel'), text = 'Назад', } button:register("mouseClick", hideWinny) winny:updateLayout() tes3ui.enterMenuMode(winny) -- режим меню end event.register("keyDown", showWinny, {filter = 44}) -- z Готово. Также, в окно можо добавлять блоки (свободное пространство для элементов), а в блоки уже добавлять тексты, изображения и кнопки. local block = winny:createBlock{} block.width = 1000 -- ширина block.autoHeight = true -- высота выбирается автоматически block.childAlignX = 0.5 -- горизонт. выравнивание элементов по центру block.childAlignY = 0.5 -- верт. выравнивание элементов по центру block.flowDirection = 'top_to_bottom' -- разместить элементы сверху вниз local l = block:createLabel{ ... } -- добавить запись local b = block:createButton{ ... } -- добавить кнопку local img = block:createImage{ ... } -- добавить изображение local nif = block:createNif{ ... } -- добавить модель Теперь вы можете создавать меню в Морровинд под свои нужды.Полные возможности см. в описании TES3 классов (последняя ссылка в шапке темы) Изменено 4 апреля, 2020 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
Dagot_Prolaps Опубликовано 3 апреля, 2020 Жалоба Поделиться Опубликовано 3 апреля, 2020 кнопку в окно с диалогом с нпс. Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 4 апреля, 2020 Автор Жалоба Поделиться Опубликовано 4 апреля, 2020 (изменено) Урок 10: "Разговоры" Сегодня мы:1. Создадим модуль, который будет штамповать нам окна2. Используя этот модуль, сотворим окно для разговора с НИП'ом (Не Игровым Персонажем)3. Внедрим кнопку в MenuDalogue (в основное окно для диалогов в Морровинде)4. Добавим функции для ответа: "кто вы?", "который час?", "как погода?" Для понимания этого материала нужно основательно усвоить предыдущий урок. Пусть у нас есть каталог с модом MyMod. А в нём основной модуль main.luaСоздадим вспомогательный модуль (файл) win.lua. Он нужен нам для того, чтобы потом затем пользоваться им, не повторяя один и тот же код over9000+ раз. win.lua будет иметь всего одну функцию new(name) - создавать новое окно: local this = {} this.new = function(name) -- функция, создающая новое окно и возвращающая нам его данные local m = { -- данные нашего нового окна id = tes3ui.registerID(name), ltext = ' Enter: ', block = {[1] = ''}, } m.menu = tes3ui.createMenu{id = m.id, fixedFrame = true} m.menu.alpha = 1.0 -- нулевая прозрачность m.show = function() -- отобразить окно m.menu:updateLayout() tes3ui.enterMenuMode(m.menu) end m.hide = function() -- спрятать окно if not tes3ui.findMenu(m.id) then return end m.menu:destroy() if tes3ui.menuMode then tes3ui.leaveMenuMode() end end m.addBlock = function(n, width, ltext) -- добавить блок с номером n, шириной [и необязательным текстом надписи] m.block[n] = m.menu:createBlock{} m.block[n].width = width or 360 m.block[n].autoHeight = true m.block[n].childAlignX = 0.5 m.block[n].childAlignY = 0.5 m.block[n].flowDirection = 'top_to_bottom' if ltext then -- если указан 3 параметр - текст надписи, то добавляем её m.block[n]:createLabel {text = ltext} end end m.addBlockButton = function(n, buttext, func) -- добавить в блок номер n кнопку с текстом buttext local button = m.block[n]:createButton { id = tes3ui.registerID(buttext), text = buttext, } button:register("mouseClick", func) -- при нажатии на кнопку будет вызываться функция func end return m -- возвращаем созданную таблицу с данными и функциями для нашего нового окна end return this Добавим этот модуль в наш основной модуль main.lua local win = require("MyMod.win")Теперь мы можем: w = win.new(...), -- создавать новые окнаw.addBlock (...), -- добавлять в них болкиw.addBlockButton (...) -- конопкиw.show (...) -- показыватьw.hide (...) -- и прятать их Что мы и сделаем: local win = require("Clever Actors Dialogues.win") local winny local function winnyShow() local width = 360 winny = win.new('winny') -- создадим новое окно winny.addBlock(1, width, 'Сказать...') -- добавим блок номер 1 winny.addBlock(2, width, '----------') -- добавим блок номер 2 winny.addBlockButton(2, 'назад', winny.hide) -- добавим в блок номер 2 кнопку назад winny.show() -- а теперь выведем окно end event.register("keyDown", winnyShow, {filter = 44}) -- z При нажатии на "z" окно покажется, при нажатии "назад" - спрячется. Теперь создадим функцию, которая внедрит в меню диалога (MenuDialog) новую кнопку "Диалог с <имя персонажа>" Есть такое событие "menuEnter". Оно возникает, когда на экран выводится любое окно (меню). В данных этого события отправляется id этого нового окна (просто число). Подробнее о всех события тут:https://mwse.readthedocs.io/en/latest/lua/event.html Это нам и нужно. Зарегистрируем на событие "menuEnter" новую функцию в main.lua: local md_id -- id MenuDialog local md_db -- это будет наша кнопка "Диалог с npc" local md_db_id -- id нашей кнопки local function dlgButton(e) -- е - это данные события "menuEnter" md_id = tes3ui.registerID("MenuDialog") if e.menu.id ~= md_id then return end -- выходим, если id окна не совпадает с MenuDialog (открыто что-то другое) md = tes3ui.findMenu(md_id) -- иначе, продолжаем. Сохраняем меню MenuDialog как md md_db_id = tes3ui.registerID("md_db") md_db = md:createButton { -- добавляем нашу кнопку в MenuDialog (появится внизу окна) id = md_db_id, text = 'Диалог c '..tes3ui.getServiceActor().object.name, } md_db.widthProportional = 1.0 md_db:register("mouseClick", winnyShow) -- при нажатии на кнопку будет вызываться наше окно Winny end event.register("menuEnter", dlgButton) -- регистрируем функцию на событие "menuEnter" Можно пробовать запускать. Теперь не хватает вопросов и ответов от нпс. При использовании tes3.messageBox(...) и открытом MenuDialog текст выводится прямо в него, а не появляется отдельно.Этим и воспользуемся.НИП будет нам отвечать: local function selfDialog() -- говорит своё имя, расу и класс local mbl = tes3ui.getServiceActor() local str = 'Это я, '..mbl.object.name..', '.. mbl.object.race.name ..', '..mbl.object.class.id tes3.messageBox(str) end local function daytimeDialog() -- говорит сколько часов до конца дня local wc = tes3.getCurrentWeather().controller local str = tostring(wc.daysRemaining) str = str ..' день , час ' .. tostring(wc.hoursRemaining) tes3.messageBox(str) end local function weatherDialog() -- проверяет состояние погоды, озвучивает local w = tes3.getCurrentWeather() local str = 'Нынче' if w.index == 1 then str = str..' ясно' else str = str..'... что там, не знаю' end tes3.messageBox(str) end Теперь нужно вызывать эти функции из нашего winny.Дополним получившийся main.lua local function winnyShow() local width = 360 local chlist = -- лист ответов ("Choiсe list") { ['Кто вы?'] = selfDialog, ['Который час?'] = daytimeDialog, ['О погоде'] = weatherDialog, } winny = win.new('winny') winny.addBlock(1, width, 'Сказать...') for chtext,fun in pairs(chlist) do -- для каждой записи из chlist winny.addBlockButton(1, chtext, function() -- добавить функцию winny.hide() -- прячущую окно winny fun() -- и вызывающую соответствующую функцию end) end winny.addBlock(2, width, '----------') winny.addBlockButton(2, 'назад', winny.hide) winny.show() end local md_id -- Menu Dialogue id local md_db -- Menu Dialogue _ Dialogue Button local md_db_id local win = require("Clever Actors Dialogues.win") local winny local function dlgButton(e) --collectgarbage('collect') md_id = tes3ui.registerID("MenuDialog") if e.menu.id ~= md_id then return end md = tes3ui.findMenu(md_id) md_db_id = tes3ui.registerID("cleveractors:md_db") md_db = md:createButton { id = md_db_id, text = 'Диалог c '..tes3ui.getServiceActor().object.name, } md_db.widthProportional = 1.0 md_db:register("mouseClick", winnyShow) end local function onLoad() event.register("menuEnter", dlgButton) end event.register("loaded", onLoad) После добавления нашей кнопки в меню диалога, его нужно обновить (updateLayout). Иначе наша кнопка будет появляться не сразу, а только после первого ответа нип`а на любую из тем, или любого др. обновляющего окно события. Если есть идеи, как улучшить ответы нпс, предлагайте. Или, ещё лучше, дополняйте плагин самостоятельно. Публикую opensource :) Последняя версия планина "Morrowind-Dialogues" https://gitlab.com/Scoommich/morrowind-dialogues Изменено 4 апреля, 2020 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 26 июня, 2020 Автор Жалоба Поделиться Опубликовано 26 июня, 2020 (изменено) MWSE Luaпродолжает обзаводиться новыми объектами, событиями и возможностями Что нового?Новые функции появились (~ за первое полугодие 2020) : tes3.createObject - создает объект и возврящает его. Созданный объект будет частью сохраненной игры. Поддерживаемые типы объектов - это те, которые имеют свою собственную функцию создания, такую как, например, tes3activator. tes3.findClosestExteriorReferenceOfObject - Используя ту же функцию двигателя, что и заклинания «Ванильное вмешательство», размещает первую ссылку на данный объект во внешнем мире.tes3.getLastExteriorPosition - Возврящает последнюю запомненную позицию игрока в экстерьере (снаружи)tes3.togglePOV - Вызывает переключение POV игрока в следующем кадре симуляции и возвращает, если игрок ранее был от третьего лица. Несколько вызовов в одном кадре не будут складываться.tes3.force1stPerson - Принудительно вводит POV (Область зрения) игрока от первого лица в следующем кадре симуляции и возвращает true, если POV было изменено. = Новые события = barterOffer Это событие вызывается, когда игрок делает потенциально успешное бартерное предложение. Потенциально успешный означает, что обе стороны имеют необходимые средства для совершения сделки.calcSunDamageScala используется при расчете количества урона, применяемого к магическому эффекту солнечного урона.containerClosed Это событие возникает, когда контейнер закрыт.crimeWitnessed Это событие происходит, когда актером засвидетельствовано преступление.detectSneak Это событие вызывается всякий раз, когда актер проверяет, могут ли они обнаружить, что другой актер подкрался.filterBarterMenu Это событие возникает, когда элемент в бартерном меню фильтруется.determineAction Это событие возникает, когда актер определяет действие в боевом сеансе.determinedAction Это событие возникает, когда актер определил действие в боевом сеансе.filterInventory Это событие возникает, когда предмет в инвентаре фильтруется.filterInventorySelect Это событие возникает, когда для предмета выбран фильтр инвентаря.filterBarterMenu Это событие возникает, когда элемент в бартерном меню фильтруется.filterSoulGemTarget Это событие происходит, когда цель самоцвета души фильтруется.infoGetText Это событие возникает, когда извлекается текст объекта диалога.infoResponse Это событие срабатывает при срабатывании ответа диалога.isGuard Событие isGuard срабатывает всякий раз, когда игровой движок проверяет, является ли объект NPC охранником. Статус охраны может быть изменен. Это само по себе не заставит NPC вести себя как охранник.itemDropped Что-то уронилиitemTileUpdated Это событие срабатывает при срабатывании ответа диалога.lockPick Это событие срабатывает при взломе замка.objectInvalidated Это событие возникает, когда ссылка недействительна. Это включает в себя удаление из памяти. Это событие может быть использовано для безопасного удаления ссылок из таблиц.postInfoResponse Это событие возникает сразу после обработки ответа диалога.preLevelUp Это событие запускается как раз перед тем, как уровень игрока поднимется.projectileHitObject Событие projectileHitObject возникает, когда снаряд сталкивается с объектом.trapDisarm Это событие срабатывает, когда ловушка обезвреживается. = Объекты = Нижереченные сущности пребывали в коде и ранее, но теперь описаны в документации и к ним имеется доступ: tes3birthsignОбъект, представляющий знак рождения.tes3regionСтруктура, которая содержит информацию о регионе.tes3regionSoundСтруктура, которая содержит информацию о звуке региона.tes3staticСтатический игровой объект.tes3statisticСтруктура, которая содержит статистическую информацию, относящуюся к текущим и базовым значениям статистики, таким как здоровье, усталость, магия, атрибуты или навыки.tes3weatherСтруктура, которая содержит базовую информацию о погоде, которая используется для наследования структур погоды. = Доступ к NIF = Расширился доступ к NIF мешам и узам сцены. Типы можно найти в таблице tes3.niType. niObject - Самый базовый NIF объект.Самый базовый объект, из которого получены почти все структуры NetImmerse.niAmbientLightОбъект, который представляет окружающий свет. Этот объект довольно прост и не имеет местоположения, направления или затухания.niCameraОбъект, представляющий камеру. Положение и ориентация определяются родительскими свойствами.niDirectionalLightОбъект, который представляет свет со светом, движущимся в заданном направлении. Свет может быть направлен в любом направлении, вращая свет.niCollisionSwitchОбъект, который указывает, включена ли система столкновений.niDynamicEffectБазовый класс для динамических эффектов, таких как NiLights или эффекты проецируемых текстур.niFormatPrefsКласс, представляющий набор предпочтений для форматов текстур. Эти предпочтения определяют уровни точности пикселей.niGeometryDataОбъекты NiGeometryData содержат данные геометрии, необходимые для визуализации объекта NiGeometry. Когда создается объект на основе NiGeometry, фактические данные геометрии сохраняются в прикрепленном объекте NiGeometryData.niLightБазовый класс, который представляет источники света в графе сцены. Это включает в себя окружающий, рассеянный и зеркальный цвета света, а также его интенсивность.NiNodeБазовый класс, представляющий узлы графа сцены. Узел может иметь любое количество дочерних узлов.niObjectNETОбъект, который имеет имя, дополнительные данные и контроллеры.niPickКласс, используемый в системе пересечения комплектации в игровом движке. Используя луч, движок выполняет операции выбора на графе сцены или любом поддереве. При заданном луче и поддереве поддерево пересекается, и совпадающие узлы добавляются в массив.niPickRecordВложенный класс NiPick, в котором хранятся результаты предыдущих операций выбора для использования игровым движком.niPixelDataПредставляет 2D-массивы значений пикселей, а также пирамиды с несколькими уровнями mipmap, каждый из 2D-массивов значений пикселей. Также содержит информацию, представляющую формат пикселей и размеры массивов. Изменено 26 июня, 2020 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
aL☢ Опубликовано 26 июня, 2020 Жалоба Поделиться Опубликовано 26 июня, 2020 Просто балдеж, спасибо за ценную инфу! Ссылка на комментарий Поделиться на другие сайты Поделиться
-=ChieF=- Опубликовано 7 июля, 2020 Жалоба Поделиться Опубликовано 7 июля, 2020 (изменено) Просьба подробнее рассказать в рамках уроков, как работать с таблицами :) Например, есть вот такой код: local function transferItems(e) local cell = tes3.getPlayerCell() local sack = tes3.createReference{object="sack_id", position=tes3.player.position, orientation=tes3.player.orientation, cell=cell} for _, stack in pairs(tes3.player.object.inventory) do tes3.transferItem{from=tes3.player, to=sack, item=stack.object, count=stack.count, playSound=true} end end local function initialized(e) event.register("keyUp", transferItems, { filter = tes3.scanCode.backspace } ) end event.register("initialized", initialized) Идея в том, что такой код переносит все объекты из инвентаря персонажа в контейнер. А хотелось бы, что переносил все, кроме экипированных. Один умный человек посоветовал создать таблицу, в которую прописать экипированные предметы.Вопрос - а какие элементы таблицы нужно использовать в этом случае? И какие можно использовать в принципе? В уроке номер 6 мы создали таблицу для Аррилла. Но почему именно эти значения мы туда прописали? В общем, прошу подробнее остановиться на таблицах :) p.s. Пункт 3.4.9. руководства я читал, но понятнее не стало Изменено 7 июля, 2020 пользователем -=ChieF=- Ссылка на комментарий Поделиться на другие сайты Поделиться
Муурн Шепард Опубликовано 7 июля, 2020 Жалоба Поделиться Опубликовано 7 июля, 2020 (изменено) Вопрос - а какие элементы таблицы нужно использовать в этом случае? И какие можно использовать в принципе?Айди и количество объектов. Будет что-то вроде for _, stack2 in pairs (tes3.player.object.equipment) do EquipmentList [_] = { ObjId = stack2.object.id Amount = stack2.count } end Таблица -- это, грубо говоря, таблица в экселе. Есть строки (0, 1, 2 и т. д.), есть столбцы. Вместо столбцов -- все свойства объекта. То есть айди, имя, вес, etc. Изменено 7 июля, 2020 пользователем Муурн Шепард Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 7 июля, 2020 Автор Жалоба Поделиться Опубликовано 7 июля, 2020 (изменено) В уроке номер 6 мы создали таблицу для Аррилла. Но почему именно эти значения мы туда прописали? Потому как функция tes3.createReference {...} требует передать ей именно эти значения createReference{object -- указать кого создавать (tes3physicalObject|string)position -- указать в каком месте создавать (tes3vector3|table)orientation -- оринетация по сторонам света (tes3vector3|table)cell -- где создавать, то есть в какой ячейке мира (tes3cell|string|table)scale: -- масштаб созданного объекта, не обязательно указывать, по умолчанию 1 (number)} Также как tes3.transferItem -- просит передать ей откуда, куда, какой item и в каком количестве перемещать. В шапке темы есть ссылка скачать рассортированное описание tes3 функций (файл tes3.txt) Вот в доках пример Идея в том, что такой код переносит все объекты из инвентаря персонажа в контейнер. А хотелось бы, что переносил все, кроме экипированных.Идея отличная, осталось сделать фильтр по надетым на ГГ вещам. Ну ещё можно прикрутить меню и будет готовый плагин. Фильтр можно сделать так: local equip = {} -- создаём новую пустую таблицу for i, node in pairs(tes3.player.object.equipment) do -- запоминаем id и ссылки на надетые на ГГ вещи equip[node.object.id] = node end for i, stack in pairs(tes3.player.object.inventory) do -- проверяем по id, если вещь не запомнена в equip, то сбрасываем её в sack if not equip[stack.object.id] then tes3.transferItem { from = tes3.player, to = sack, item = stack.object, count = stack.count, playSound = true } end end tes3.messageBox("Вещи сброшены") Изменено 7 июля, 2020 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
borivit Опубликовано 18 сентября, 2023 Жалоба Поделиться Опубликовано 18 сентября, 2023 (изменено) Здравствуйте, если еще есть кто живой в этой теме, то может быть он мне поможет разобраться. Я перебираю объекты в инвентаре, выбираю там броню и пытаюсь узнать класс брони(легкая, средняя, тяжелая), но у меня в результате выдает nil. Может кто может мне объяснить что я делаю не так. for i, stack in pairs(tes3.player.object.inventory) do if (stack.object) then if (stack.object.objectType == tes3.objectType.armor) then tes3.messageBox{ message = "armorClass=" .. tostring(stack.object.armorWeightClass)} end end end Изменено 18 сентября, 2023 пользователем borivit Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 18 сентября, 2023 Автор Жалоба Поделиться Опубликовано 18 сентября, 2023 Не находит armorWeightClass, должно быть просто weightClass Ссылка на комментарий Поделиться на другие сайты Поделиться
borivit Опубликовано 18 сентября, 2023 Жалоба Поделиться Опубликовано 18 сентября, 2023 (изменено) В 9/18/2023 в 8:35 PM, mintmike сказал: Не находит armorWeightClass, должно быть просто weightClass Завтра буду дома, попробую. Но у меня такая же история и с weaponType хотя здесь проще т.к. почти все id имеют указание на тип оружия и можно просто искать нужное через id. P.S.: А можно ли как-то вытянуть все значения и ключи относящиеся к объекту? Чтобы можно было увидеть какие есть у объекта свойства и соответственно тогда будет понятно как их узнать. P.S.S.: Только что до читался что через for можно посмотреть все ключи и значения. Завтра попробую. О результатах напишу. Всех приветствую. С weightClass заработало:) а для оружия нужно писать просто type. Это не совсем по теме, но может вы знаете как отключить показ названия и характеристик оружия. Я доступ отключил, а название и характеристики не получается отключить. Цитата P.S.S.: Только что до читался что через for можно посмотреть все ключи и значения. Завтра попробую. О результатах напишу. Ничего с этой затеей не вышло т.к. pairs нельзя запускать внутри pairs. У меня есть еще одна маленькая проблемка. Хочу сделать создание объекта при активации другого объекта, а потом при активации того же объекта удалить созданный объект, но lua почему-то ругается на createReference хотя 1н раз объект создается и 1н раз он удаляется, а потом уже ничего не создается. local function basurero(e) if (e.target.object.id == "A_RZZ_active_bell_01") then if (saco == nil) then local cell = tes3.getPlayerCell() local vector_pos = tes3vector3.new(-346, 250, 25) local vector_orient = tes3vector3.new(0, 0, 25) basura = tes3.createReference{object="A_RZZ_basura", position=vector_pos, orientation=vector_orient, cell=cell} saco = true else saco = nil tes3.deleteObject(basura) end end end event.register("activate", basurero) Ошибку выдает такую: invalid 'object' parameter privided В 9/19/2023 в 7:47 PM, borivit сказал: Ошибку выдает такую: invalid 'object' parameter privided Я так понимаю что удаляется полностью объект и потому выдает эту ошибку. В tes3 конструкторе для точно такой же операции(placeAtPC) я использовал disable и setdelete, а здесь я нашел только disable, а setdelete нет или может я не увидел. P.S.: я нашел в tes3reference - myObject:delete() там пишут что ссылка помечается как удаленная и потом полностью удаляется - это похоже на setdelete в tes3. Завтра буду пробовать. В 9/19/2023 в 9:51 PM, borivit сказал: P.S.: я нашел в tes3reference - myObject:delete() там пишут что ссылка помечается как удаленная и потом полностью удаляется - это похоже на setdelete в tes3. Завтра буду пробовать. Это сработало. Вместо tes3.deleteObject(basura) я вставил basura:delete() и теперь все работает Как через lua запретить показ содержимого контейнера, а потом показать это содержимое после нажатия кнопки в меню? Изменено 18 сентября, 2023 пользователем borivit Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 20 сентября, 2023 Автор Жалоба Поделиться Опубликовано 20 сентября, 2023 (изменено) 4 часа назад, borivit сказал: Как через lua запретить показ содержимого контейнера, а потом показать это содержимое после нажатия кнопки в меню? Например, перемещать или сделать disable предметы, а по нажатии кнопки снова переместить или enable. Кстати, при удалении вещей из контейнера/инвентаря, лучше делать это в следующем кадре (меньше шансов вылета на рабочий стол): timer.delayOneFrame(function() local pgn = tes3.getItemCount{reference = tes3.player, item = 'pouch_gold'} if pgn > 0 then tes3.removeItem{reference = tes3.player, item = 'pouch_gold', count = 1} end end) В 19.09.2023 в 9:47 PM, borivit сказал: Ничего с этой затеей не вышло т.к. pairs нельзя запускать внутри pairs. Сделайте серез функцию, которая вызывается внутри pairs и в ней будет свой pairs. Вообще говоря pairs внутри pairs можно Цитата Это не совсем по теме, но может вы знаете как отключить показ названия и характеристик оружия Возможно есть в моде Descriptive Descriptions, там дополняются описания предметов Изменено 20 сентября, 2023 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 20 сентября, 2023 Автор Жалоба Поделиться Опубликовано 20 сентября, 2023 (изменено) Как удобно распечатать таблицу, чтобы посмотреть все содержимое, все ключи и значения? Есть удобная функция deepToString(value, maxDepth) для распечатки в лог содержимого таблицы (взято из OpenMW util.lua) value - сама таблица maxDepth - максимальная глубина вложенных таблиц, до которой будет распаковываться и печататься в строку содержимое value -- Implementation can be found in `resources/vfs/openmw_aux/util.lua`. local aux_util = {} local function deepToString(val, level, prefix) local level = (level or 1) - 1 local ok, iter, t = pcall(function() return pairs(val) end) if level < 0 or not ok then return tostring(val) end local newPrefix = prefix .. ' ' local strs = {tostring(val) .. ' {\n'} for k, v in iter, t do strs[#strs + 1] = newPrefix .. tostring(k) .. ' = ' .. deepToString(v, level, newPrefix) .. ',\n' end strs[#strs + 1] = prefix .. '}' return table.concat(strs) end -- Works like `tostring` but shows also content of tables. -- @function [parent=#util] deepToString -- @param #any value The value to convert to string -- @param #number maxDepth Max depth of tables unpacking (optional, 1 by default) function aux_util.deepToString(value, maxDepth) return deepToString(value, maxDepth, '') end --... return aux_util Изменено 20 сентября, 2023 пользователем mintmike Ссылка на комментарий Поделиться на другие сайты Поделиться
borivit Опубликовано 21 сентября, 2023 Жалоба Поделиться Опубликовано 21 сентября, 2023 (изменено) Цитата Например, перемещать или сделать disable предметы, а по нажатии кнопки снова переместить или enable. Кстати, при удалении вещей из контейнера/инвентаря, лучше делать это в следующем кадре (меньше шансов вылета на рабочий стол): Это не совсем то что я имел ввиду. Видимо я не правильно изложил вопрос. Мне нужно при активации контейнера получить вместо окна с содержимым контейнера, мое окно с кнопками. Я здесь нашел такую функцию: local tomb = tes3.getReference("A_RZZ_chest_tomb") --контейнер tes3.player:activate(tomb) --открывает содержиме контейнера это работает как activate в tes3 конструкторе, но у меня не получается запретить показ или закрыть меню с содержимым при стандартной активации т.е. как отследить меню контейнера при его активации и сразу же его закрыть? или может можно его запретить по событию? Кстати -> myObject:clearActionFlag(flagIndex) - это не помогло. И я никак не могу понять как правильно заполнять поле buttons и callbackParams tes3ui.showMessageMenu({ id = ..., buttons = ..., callbackParams = ..., cancels = ..., cancelText = ..., cancelCallback = ..., header = ..., message = ..., customBlock = ..., page = ..., pageSize = ... }) Цитата Как удобно распечатать таблицу, чтобы посмотреть все содержимое, все ключи и значения? Есть удобная функция deepToString(value, maxDepth) для распечатки в лог содержимого таблицы (взято из OpenMW util.lua) Благодарю, еще не попробовал, но обязательно испытаю:) Как работает menu:destroy? Я почему-то не могу найти описания. Я заметил что когда запущено мое меню и меню контейнера, то если я закрываю свое меню, закрывается и меню контейнера. P.S.: я нашел описание myObject:destroy(), но мне это не очень помогло, я так понимаю что вместо myObject нужна переменная с объектом окна, но как найти id окна контейнера, а потом получить его объект я пока незнаю или может я не в ту сторону копаю. Изменено 21 сентября, 2023 пользователем borivit Ссылка на комментарий Поделиться на другие сайты Поделиться
borivit Опубликовано 23 сентября, 2023 Жалоба Поделиться Опубликовано 23 сентября, 2023 (изменено) Рассказываю что у меня получилось:) 1. Заменить меню контейнера на свое при его активации local function eActivate(e) if (e.target.object.id == "A_RZZ_chest_tomb") then if (not RZZ_activate) then timer.delayOneFrame(function() if tes3ui.menuMode then tes3ui.leaveMenuMode() end --закрываем контейнер myMenuShow() --Открываем меню end) return false end RZZ_activate = nil --метка активации контейнера end end event.register("activate", eActivate) 2. Открыть контейнер при нажатии кнопки своего меню local function abrirRZZ() local tomb = tes3.getReference("A_RZZ_chest_tomb") cerrarMenu() --закрываем свое меню timer.delayOneFrame(function() RZZ_activate = true --метка активации контейнера tes3.player:activate(tomb) --открываем контейнер end) end 3. Убрать helpMenu т.е. окошко всплывающее при наведении прицела на предмет local function onUIObjectTooltip(e) if string.find(e.reference.id,'muestra') then --выборка нужных предметов e.tooltip.absolutePosAlignX = 4 e.tooltip.absolutePosAlignY = 4 else e.tooltip.absolutePosAlignX = nil e.tooltip.absolutePosAlignY = nil end end event.register("uiObjectTooltip", onUIObjectTooltip) Теперь оталось выяснить как отследить запуск заклинания, как запустить проклятие, как остановить выполнение заклинания, как телепортироваться в нужное место и тогда я свой плагин полностью переведу на lua:) Изменено 23 сентября, 2023 пользователем borivit Ссылка на комментарий Поделиться на другие сайты Поделиться
mintmike Опубликовано 23 сентября, 2023 Автор Жалоба Поделиться Опубликовано 23 сентября, 2023 2 часа назад, borivit сказал: Теперь оталось выяснить как отследить запуск заклинания, как запустить проклятие, как остановить выполнение заклинания, как телепортироваться в нужное место и тогда я свой плагин полностью переведу на lua:) Здорово ) spellCast spellCasted Список маг эффектов Пример телепорта: local result = tes3.positionCell { reference = a.id, cell = c, position = a.lpoint, } Ссылка на комментарий Поделиться на другие сайты Поделиться
borivit Опубликовано 23 сентября, 2023 Жалоба Поделиться Опубликовано 23 сентября, 2023 Цитата spellCast spellCasted Список маг эффектов Пример телепорта: Благодарю:) Я пытаюсь поставить пометку и после телепортировать главного героя, но пометка телепортируется вместе с ним. Как это можно исправить? 12 часов назад, borivit сказал: Я пытаюсь поставить пометку и после телепортировать главного героя, но пометка телепортируется вместе с ним. Как это можно исправить? Вопрос снят:) Сделал свою пометку и теперь не портит стандартную пометку. Теперь мой плагин полностью работает на lua за исключением запрета активации некоторых предметов т.к. это удобнее через конструктор. Благодарю вас за помощь:) Если возникнут еще вопросы, то буду писать сюда:) P.S.: Интересный глюк нарисовался, я когда открываю контейнер через свое меню и беру оттуда предмет, то после закрытия контейнера мое меню уже не открывается, а просто открывается контейнер, а когда возвращаешь предмет на место, то после закрытия контейнера опять начинает открывается мое меню. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Пожалуйста, войдите, чтобы комментировать
Вы сможете оставить комментарий после входа в
Войти