lil Toady

Administrators
  • Content count

    2,318
  • Joined

  • Last visited

Community Reputation

3 Neutral

About lil Toady

  • Rank
    Godfather (The MTA Team)
  • Birthday 17/03/1990

Details

  • Gang
    Full Metal Jacket
  • Location
    Are you gangsters? No, we are Russians
  1. Да не работает так Lua. Объект не может обнулить/удалить сам себя, а соответственно и все ссылки на себя. function CEditField:Destroy() это лишь короткая запись для function CEditField.Destroy( self ) или CEditField.Destroy = function ( self ) все эти записи будут работать абсолютно одинаково, соответственно self = nil это лишь обнуление локальной переменной, что не делает ровным счетом ничего. self - не магия, а локальная переменная которая передается в функцию. Вот эти 2 записи тоже делают абсолютно одно и то же: v:Destroy() CEditField.Destroy ( v ) Чисти таблицу. В ней не могут быть значения nil: либо есть значение, либо его нет. А вот метаметоды __tostring и иже с ними могут запутать. Для примера, если записать в таблицу игрока, когда он выйдет с сервера, он все еще останется в таблице и tostring все еще будет говорить что у нас на руках userdata, не смотря на то что МТА его удалила. Просто потому что невозможно удалить все ссылки на этого игрока удалив его самого.
  2. Особо не вчитывался, но v:Destroy() может и выполняет какие-то действия, сам Lua объект/таблицу она удалить не может, соответственно таблица EditField все еще полна и коллектор не подберет то что в ней находится. Распространенная ошибка когда скрипты сохраняют юзеров или какие еще элементы в глобальной таблице, юзеры уходят с сервера или элементы удаляются, а таблицу никто не чистит.
  3. killmessage без иконок

    Там все не так тривиально, но, собственно, не смотря на то что тебе тут насоветовали, не надо искать где рисуется сама иконка - тут это бессмысленно, потому что оружия перемаппируются на ид иконок в другом месте. Ты изначально все правильно нашел, в файле killmessages_client.lua, в самом конце, можно найти такие строки: return outputMessage ( {killerName, {"padding",width=3}, {"icon",id=weapon}, {"padding",width=3},{"color",r=wr,g=wg,b=wb}, wastedName}, kr,kg,kb ) Тут как раз и формируется сообщение для вывода: "убийца(killerName) <отступ(padding)> иконка <отступ> умерший(wastedName)". Надо заменить {"icon",id=weapon} на название оружия. Могло бы быть так просто, как: return outputMessage ( {killerName, {"padding",width=3}, getWeaponNameFromID ( weapon ), {"padding",width=3},{"color",r=wr,g=wg,b=wb}, wastedName}, kr,kg,kb ) Или даже проще: return outputMessage ( {killerName.." "..getWeaponNameFromID ( weapon ).." "..wastedName}, kr,kg,kb ) Но это будет работать только для оружий, а weapon же тут может означать и транспорт, и взрывы, суицид, утопление, падение, и т.д... ИДшники к иконкам привязываются в файле definitions.lua; а как задаются эти ИДшники, определяется в функции KillMessages_onPlayerWasted в killmessages_server.lua. Думаю отсюда и сам разберешься как прикрутить имена для остальных идишников.
  4. Дада (: фулдилка

    Ага, сегодня от них письмо пришло МТА попало в топ-100. Но по их правилам мы больше не можем занимать призовые места.
  5. Вопросы и ответы по MTA.

    Костыль? Это то, для чего короутины вообще существуют. Невозможно в Lua добавить потоки, в привычном их виде, Lua не thread-safe. Да и смысла нет, весь API абсолютно event based, все скрипты - это обработчики каких-либо событий. Сами по себе они не существуют.
  6. Вопросы и ответы по MTA.

    Ну неправда же. Вполне можно сделать чтобы функция делала запрос к серверу, получала ответ и выдавала результат там где выполняется - coroutine. Для db функций тоже можно использовать. В итоге все будет очень красиво и удобно, но для этого нужно чтобы обработчики событий выполнялись в короутинах, соответственно addEventHandler лучше обернуть, вместе с removeEventHandler и т.д. Принцип таков: - вызывается событие (ткнули в кнопку рефреш в окне, например); - создается новый короутин; - короутин запускается с аргументами события; - где-то понадобилось запросить данные с сервера, вызывается функция, скажем getServerData(); - getServerData делает triggerServerEvent на сервер, записывает в промежуточную таблицу (например requests) что такой-то короутин ждет ответа от сервера; - сервер обрабатывает запрос, отвечает с triggerClientEvent - клиент ловит ответ, берет из таблицы requests короутин который этот ответ ждал, передает в него результат и продолжает его (coroutine.resume) В итоге в коде все будет оч красиво: addEventHandler ( "onClientGuiClick", refreshbutton, function () ... local data = getServerData () -- в этой функции сделается запрос к серверу и вернутся данные, выполнение остановится, пока данные не придут -- заполняем гуи ... end, false ) Для примера, вот небольшой враппер для db функций, где db.query возвращает результат там где выполняется, а не в колбек: тык local users = db.query ( "select * from users" ); А тут пример враппера с короутинами для евентов (правда чуть кривой): тык
  7. Вопросы и ответы по MTA.

    setElementPosition ( value, unpack ( split ( dataTable[1]["playerPosition"], "," ) ) )
  8. Что приходит на ум: 1. Логическое разделение, само по себе полезно; 2. На "живом" сервере проще перезапустить часть общей системы, чем общий ресурс; 3. Один ресурс еще и дольше перезапускается; 4. Четкое разделение прав - а это безопасность вашего сервера (не стоит делать админку, там же где и все остальное); 5. Коллизия глобальных переменных - это особенно относится к процедурному программированию. Глобальная среда растет, избежать коллизии, все труднее. Более того, чем больше одна Lua среда - тем медленнее она работает (хоть и не очень значительно); Опять же, для взаимодействия между скриптами можно использовать не только экспорты, но и собственные эвенты. Да и если посмотреть на опыт крупных серверов, можно заметить что они предпочитают разбивать логику на разные ресурсы.
  9. Вопросы и ответы по MTA.

    Компиляция Lua скриптов никак не ускорит их выполнение, лишь загрузку. Текстовый скрипт и так переводится в байт код при загрузке. На счет ООП в Lua - выполнение одной функции скорее будет быстрее процедурно (хотя тут зависит от того сколько у нас глобальных переменных, сколько функций в классе, и на каком уровне наследования находится функция). Тупо потому что при обращении, идет поиск функции в таблице по строковому названию: moo() - это то же самое что и _G["moo"]() Но смысл в том что за счет большей абстракции в ООП, общая логика для достижения того же результата будет меньше (уже есть примеры, freecam переписанный на ооп в несколько раз меньше, с тем же функционалом) В ирке я выдвинул на обсуждение небольшое изменение нынешней структуры метатаблиц. А именно: перенос наследственности на уровень таблицы класса и перенос свойств (переменных) туда же, для тех кто шарит, мой пример будет понятен: Element = { setHealth = ..., getHealth = ..., health = { __set = ... __get = ... }, ... } Vehicle = { func = ..., ... } setmetatable ( Vehicle, { __index = Element } ) Это и ускорит поиск, по сравнению с нынешним; упростит наследование от элементов МТА; упростит создание своих свойств объекта.
  10. ООП в МТА 1.4

    Прикольно ты длинными словами кидаешься, но вот те поворот: - наследственность присутствует, отражая внутреннюю структуру классов. Player наследует методы/свойства от Ped, а тот в свою очередь от Element. Например метод setData определен только в классе Element, но player:setData вполне себе работает, и можно даже переопределить исключительно для объектов класса Player. - полиморфизм тоже присутствует, все как и раньше, vehicle:setParent ( object ) - чем не полиморфизм? Для общего развития, на моей странице в вики есть структура мета таблиц: тык. И для особо продвинутых есть возможность эти мета таблицы переопределить по своему вкусу. Инкапсуляция? Извините, если МТА добавит приватные методы в Lua классы, кто же, блин, будет их вызывать?!?! Где смысл? В своих - сколько влезит, каркас есть. OOP дает скриптерам больше чем это, стандартные имплементации векторов/матриц и т.д. будут делать математику за вас. Очень популярная тема: как взять точку перед игроком? В ООП очень просто: player.matrix.forward, можно даже на определенном расстоянии: player.matrix.forward * length. И планов по развитию еще море. Если есть какие-то свои предложения, добро пожаловать на баг трекер или в ирк. А раз все молчат - подразумеваем предложений нет, или каждому надо лично написать и спросить? Уж пора бы запомнить.
  11. Математикой: addEventHandler ( "onPlayerFinish", getRootElement(), function ( rank ) if ( rank >= 10 ) then return end givePlayerMoney ( source, 1000 - 100 * ( rank - 1 ) ) end ) Или, если все же хочется хранить, то в таблице: local rewards = { 1000, 900, 800, 700, 600, 500, 400, 300, 200, 100 } addEventHandler ( "onPlayerFinish", getRootElement(), function ( rank ) if ( not rewards[rank] ) then return end givePlayerMoney ( source, rewards[rank] ) end )
  12. Вопросы и ответы по MTA.

    Да, но это пока еще не строгое ограничение, и в данном случае проблема именно в несовместимости 32-х битного скрипта и 64-х битного сервера. MTA'шный компилятор так же использует luac в своих недрах. Вот то что у нашего компилятора нет опции под 64 бита - это надо решать.
  13. Вопросы и ответы по MTA.

    От платформы как раз и зависит, Lua байткод скомпилированный на 32-х битной машине не будет работать в 64-х битном интерпретаторе. Либо скрипты перекомпилировать, либо скачать и поставить 32-х битную версию МТА. http://www.lua.org/manual/5.1/luac.html
  14. Вопрос по интерьеру.

    Можно использовать один и тот же, только в разных измерениях (dimension - set/getElementDimension)
  15. Вопросы и ответы по MTA.

    Можно, просто биндить по очереди: bind 1 showchat 1 bind 1 showhud 1 Чтоб разбиндить одну из команд, например: unbind 1 showchat