lil Toady

Administrators
  • Content Count

    2,318
  • Joined

  • Last visited

Community Reputation

4 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

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  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. Там все не так тривиально, но, собственно, не смотря на то что тебе тут насоветовали, не надо искать где рисуется сама иконка - тут это бессмысленно, потому что оружия перемаппируются на ид иконок в другом месте. Ты изначально все правильно нашел, в файле 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. Костыль? Это то, для чего короутины вообще существуют. Невозможно в Lua добавить потоки, в привычном их виде, Lua не thread-safe. Да и смысла нет, весь API абсолютно event based, все скрипты - это обработчики каких-либо событий. Сами по себе они не существуют.
  6. Ну неправда же. Вполне можно сделать чтобы функция делала запрос к серверу, получала ответ и выдавала результат там где выполняется - 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. setElementPosition ( value, unpack ( split ( dataTable[1]["playerPosition"], "," ) ) )
  8. Что приходит на ум: 1. Логическое разделение, само по себе полезно; 2. На "живом" сервере проще перезапустить часть общей системы, чем общий ресурс; 3. Один ресурс еще и дольше перезапускается; 4. Четкое разделение прав - а это безопасность вашего сервера (не стоит делать админку, там же где и все остальное); 5. Коллизия глобальных переменных - это особенно относится к процедурному программированию. Глобальная среда растет, избежать коллизии, все труднее. Более того, чем больше одна Lua среда - тем медленнее она работает (хоть и не очень значительно); Опять же, для взаимодействия между скриптами можно использовать не только экспорты, но и собственные эвенты. Да и если посмотреть на опыт крупных серверов, можно заметить что они предпочитают разбивать логику на разные ресурсы.
  9. Компиляция Lua скриптов никак не ускорит их выполнение, лишь загрузку. Текстовый скрипт и так переводится в байт код при загрузке. На счет ООП в Lua - выполнение одной функции скорее будет быстрее процедурно (хотя тут зависит от того сколько у нас глобальных переменных, сколько функций в классе, и на каком уровне наследования находится функция). Тупо потому что при обращении, идет поиск функции в таблице по строковому названию: moo() - это то же самое что и _G["moo"]() Но смысл в том что за счет большей абстракции в ООП, общая логика для достижения того же результата будет меньше (уже есть примеры, freecam переписанный на ооп в несколько раз меньше, с тем же функционалом) В ирке я выдвинул на обсуждение небольшое изменение нынешней структуры метатаблиц. А именно: перенос наследственности на уровень таблицы класса и перенос свойств (переменных) туда же, для тех кто шарит, мой пример будет понятен: Element = { setHealth = ..., getHealth = ..., health = { __set = ... __get = ... }, ... } Vehicle = { func = ..., ... } setmetatable ( Vehicle, { __index = Element } ) Это и ускорит поиск, по сравнению с нынешним; упростит наследование от элементов МТА; упростит создание своих свойств объекта.
  10. Прикольно ты длинными словами кидаешься, но вот те поворот: - наследственность присутствует, отражая внутреннюю структуру классов. 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. Да, но это пока еще не строгое ограничение, и в данном случае проблема именно в несовместимости 32-х битного скрипта и 64-х битного сервера. MTA'шный компилятор так же использует luac в своих недрах. Вот то что у нашего компилятора нет опции под 64 бита - это надо решать.
  13. От платформы как раз и зависит, Lua байткод скомпилированный на 32-х битной машине не будет работать в 64-х битном интерпретаторе. Либо скрипты перекомпилировать, либо скачать и поставить 32-х битную версию МТА. http://www.lua.org/manual/5.1/luac.html
  14. Можно использовать один и тот же, только в разных измерениях (dimension - set/getElementDimension)
  15. Можно, просто биндить по очереди: bind 1 showchat 1 bind 1 showhud 1 Чтоб разбиндить одну из команд, например: unbind 1 showchat