Перейти к содержанию

Дайджест за январь-март

Обновления гайдов и аддонов

Март Февраль Январь

Мониторинг серверов и редактор аддонов

Представляем вам две легенды. То, о чем можно было только мечтать, стало реальностью.

Мониторинг серверов Редактор аддонов

Подсказки из игры на вашем сайте

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

Подробнее

Апдейтер аддонов

Представляем вам программу для автообновления аддонов и делимся подробностями.

Подробнее Скачать

ramirez

Разработчик аддонов
  • Постов

    224
  • Зарегистрирован

  • Посещение

Весь контент ramirez

  1. Quote: With the "Synchronize" part a Goldspammer, which was banned with one OF YOUR character, will be automaticly banned at all YOUR other characters. Oh well, that was stupid of me. =) Thx for answer. Quote: If I am right, that is also not possible to write something as an infoline in the chat? You're right. Quote: you can find it at the end of Mods/Docs/api_v1.xml I can't find anything like this. What's this about?
  2. Quote: but the ignorlist ist charbounded. Ok, so you have your "Spammer" list with some number of charnames in it. So how exactly you can catch and ban all other characters at spammer's account? All that "Synchronise" part can do is adding all this names to ignorlist again. But hey, they already there. =) Quote: BTW: What a sense has the a in "for a, entry in ipairs( Spammer ) do ..." (I know from prolog what _ is^^) "a" is table index, "entry" is table value. In Lua "_" is valid string identifier, like "o_O", "^_^" and so on. So you can use it like this Spammer [ _ ] = something.
  3. I think that "Synchronize" part is not needed at all. Your ignorlist is saved on server, so why bother? =) You can "ignore" some person only once, and he (or she) will remain in ignorelist as long as you wanted. You can't interact with "chat" or any other standard addon, no matter what.
  4. Код переписать - быстро, а аддон делать и тестить - долго. =) А у Carnifex'а аддон уже есть.
  5. Code: Global( "Spammer", {} ) Global( "Chatmsg", {} ) Global( "debugmode", false ) Global( "logout", false ) Global( "spam", {} ) Global( "on", {} ) -------------------------------------------------------------------------------- -- MAIN -------------------------------------------------------------------------------- function LoadTables() Spammer = common.GetGlobalConfigSection( "SpammerList" ) or {} if debugmode then Chatmsg = common.GetGlobalConfigSection( "ChatLog", Chatmsg ) or {} end end -------------------------------------------------------------------------------- function SaveTables() common.SetGlobalConfigSection( "SpammerList", Spammer ) if debugmode then common.SetGlobalConfigSection( "ChatLog", Chatmsg ) end end -------------------------------------------------------------------------------- function Synchronize() for _, entry in ipairs( Spammer ) do social.AddIgnore( entry, entry ) end end -------------------------------------------------------------------------------- function HasEntry( tab, sample ) for _, entry in ipairs( tab ) do if common.CompareWString( entry, sample ) == 0 then return true end end return false end -------------------------------------------------------------------------------- function common.RegisterEventHandlers( handlers ) for event, handler in pairs( handlers ) do common.RegisterEventHandler( handler, event ) end end -------------------------------------------------------------------------------- -- HANDLERS -------------------------------------------------------------------------------- on [ "EVENT_CHAT_MESSAGE" ] = function( event ) local msg, sender = event.msg, event.sender if debugmode then table.insert( Chatmsg, msg ) end if event.chatType == CHAT_TYPE_ZONE and HasEntry( spam, msg ) and not HasEntry( Spammer, sender ) then social.AddIgnore( sender, sender ) table.insert( sender ) end end -------------------------------------------------------------------------------- on [ "EVENT_AVATAR_WILL_BE_REMOVED" ] = function( event ) if not logout then SaveTables() logout = true end end -------------------------------------------------------------------------------- on [ "EVENT_AVATAR_LOGOUT_CANCELLED" ] = function( event ) logout = false end -------------------------------------------------------------------------------- on [ "EVENT_AVATAR_CLIENT_ZONE_CHANGED" ] = SaveTables on [ "EVENT_AVATAR_CREATED" ] = Synchronize -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- function Init() for i = 1, 33 do table.insert( spam, common.GetAddonRelatedText( string.format( "spam%02d", i ) ) ) end LoadTables() common.RegisterEventHandlers( on ) if avatar.IsExist() then Synchronize() end end -------------------------------------------------------------------------------- Init() There can be a few glitches in this code, but hey, i know, you can fix it. =)
  6. -1 --> arg1 < arg2; table.sort second argument function should return true 0 --> arg1 == arg2; table.sort second argument function should return true (?) 1 --> arg1 > arg2. table.sort second argument function should return false
  7. Quote: I think table.sort is somethink like quicksort or heapsort, and there it can come of swichen positions of same values. Oh, c'mon already! =) It's quicksort. http://lua-users.org/wiki/LuaSorting http://www.lua.org/manual/5.0/manual.html#5.4 About table.sort: Quote: The sort algorithm is not stable, that is, elements considered equal by the given order may have their relative positions changed by the sort. BTW, there is common.CompareWString( arg1, arg2 ) internal Lua API function, use it instead of standard Lua string comparison operators.
  8. Quote: Но ведь некоторые функции API, при некоторых обстоятельствах, могут вернуть nil вместо таблицы. Ну, если могут, и это для них нормально, то стоит явно проверять значение на nil, прежде чем начинать с ним работать. Все равно придется такие проверки проводить дальше по коду, почему бы этого не сделать один раз в начале? Иначе оно грохнется где-нибудь в другом месте, и найти причину будет уже труднее. А в общем, делай, как тебе удобнее.
  9. Нет никакой запутанной истории. =) table.getn возвращает не размер массива, а n - индекс последнего элемента. Элемент массива считается последним, если за ним следом идет nil. Этот самый n считается лишь однажды, а дальше бережно хранится в недрах Lua'шных хэш-таблиц. После того, как он там сохранился, повлиять на него могут только функции библиотеки table. insert, например, увеличивает на 1, а remove - уменьшает на 1. Его даже руками можно задать через table.setn. Элементы из массива правильно удалять через table.remove, тогда все последующие элементы быстро и аккуратно сдвинутся на -1, и никакой дырки не останется, а n будет корректным. А присваивание элементу nil'а - суть указание, что элемент массива все еще есть, просто он стал nil'овым, а индекс последнего элемента массива при этом так и не поменялся.
  10. Лучше так: Code: function GetTableSize( t ) assert( type(t) == "table", "invalid argument passed." ) local n = table.getn( t ) return t [0] and (n + 1) or n end Замалчивать ошибки в скрипте нехорошо, нечего спрашивать размер у всякого мусора. Я не знаю, насколько быстр Lua'шный ассерт (вроде достаточно), но мне краткость нравится. =) Code: local wtChild = self.Widget:GetNamedChildren() [ index ] Можно, но разницы ощутимой не даст. Первая запись бывает предпочтительнее, так как локальные переменные работают в разы быстрее индексирования таблиц. Quote: Ramirez, можешь, как специалист по LUA, посмотреть, что можно с ними сделать? Посмотрел, переделал. Думаю, этого недостаточно. Там очень много задействовано всяких поисков перебором, которые не трогал, но которые по-хорошему стоит заменить хэш-таблицами. Часть функций почему-то не используется. Сама структура аддона диктует многократные перевызовы одних и тех же функций, но тут уже мало что можно поделать. Я так толком и не въехал, как все это работает, смотрел по месту в основном.
  11. Прошелся по всем скриптам, и пооптимайзил, где счел возможным, не меняя структуру аддона. Сделал сортировку. Проверить все не могу, персонаж дохловат. Что смог проверить - работает. Надеюсь, от этого будет какая-то польза. Скрипты в аттаче. File: Scripts.zip
  12. Quote: Только, имхо, основные тормоза, всё же, в самом подсчёте статистики. Сначала надо попробовать. У меня, например, есть мнение, что тормоза там от беспощадной работы с виджетами. Lua специально оптимизирована для работы со строками, так что, если там не фигурирует массированная конкатенация, то конкретно за строки, в общем, можно не беспокоится. Ну и не считать и не обновлять три тыщи раз одно и то же тоже конечно надо. =) Quote: ...наткнулся на использование функции table.getn() вместо GetTableSize(). Про GetTableSize(). Призываю всех перестать использовать эту функцию вообще, удалить отовсюду ее вызовы, а ее саму стереть к чертям. Это очень, очень плохая функция. Про table надо понимать три простые вещи: Функции библиотеки table существуют для работы с массивами . Массив есть таблица с элементами, индексированными uint'ами, идущими подряд без пропусков, начиная с 1. В Lua первым элементом массива считается элемент с индексом[1] , а не [0] , как считают в Нивале. Из последнего проистекает наличие GetTableSize, и беды, с ней связанные. Интересно, что LuaAPI возвращает либо объекты, либо массивы, и размер нужен только от последних, а потому функция, пересчитывающая в цикле элементы с любыми индексами, только для того, чтоб изловить единственный элемент, индексированный нулем - это глупость и тормоза при массированном использовании. Лист, начинающийся с [0] превращается в лист, начинающийся с [1] так: Code: table.insert( list, 0, nil ) После этого table.getn() выдает коррекный размер, и с листом можно полноценно работать (и сортировать QuickSort'ом, а не руками), но надо помнить, что теперь индексы смещены, и отдавать их в таком виде обратно в AO LuaAPI нельзя...
  13. Тут немного пооптимизировал Дарковы библиотечные функции. Если подменить \data\Mods\Addons\DarkDPSMeter\Scripts\AOClassLibrary.lua на скрипт из аттача, работать должно быстрее. Насколько быстрее, надо проверить в деле. File: AOClassLibrary.zip
  14. Крестик и уголок - просто баловался с артом. Правый клик в пчело-кнопку тоже, в общем, закрывает. Там вообще много перегрузки. Текстурки переэкспортил и выложил новую версию. Теперь файлов меньше. Quote: p.s.Заметил, если перегрузить, например, Chat,... Да, видимо, разрабам критично что-то где-то прописывать именно на старте. Ну, сами себе буратины, что можно сказать. =) Не надо там ничего слать, это читерство, да и не сработает для чата все равно.
  15. Да, я видел, но там вроде что-то глючило последний раз... Этим я сам пользуюсь, тут одним кликом все перегружается, для разработки самое оно. P.S. Так ведь неизвестно, поймает аддон после включения этот эвент или нет. Лучше делать аддоны "перезагрузкоустойчивыми", тогда не придется нигде хачить.
  16. Привет. У меня тут есть аддон, который умеет включать/выключать и перегружать любые аддоны из общего списка нажатием одной кнопки. Он сильно девелоперский, перегружен неочевидными функциями, весь в латинице, и простым игрокам он больше навредит, чем поможет, поэтому будет он аттачем. Велкам тестить. Инструкция по эксплуатации: - Распаковать в data/Mods/Addons. - После входа в игру в правом нижнем углу экрана появится маленькая пчело-кнопка. Это нормальное состояние аддона. - Правый клик по пчело-кнопке открывает/закрывает список аддонов, доступных для манипуляций. Стандартные нивальские там тоже есть. Весь список посортирован по алфавиту, хотя это несильно помогает. Свои аддоны можно найти по префиксу UserAddon/ в названии, они там ближе к концу списка. - В списке: левый клик по названию аддона селектит/деселектит этот аддон. Поселектить можно сразу несколько аддонов. Поселекченность аддонов в списке сохраняется в рамках текущей сессии игры. - клик по квадратику слева от названия аддона включает/выключает этот аддон. Состояние аддонов сохраняется между сессиями, то есть выключенный однажды аддон при следующем входе в игру останется выключенным. - Левый клик по пчело-кнопке перезагружает все поселекченные аддоны сразу, неважно открыт список или нет. - В списке: правый клик по названию аддона тут же на месте однократно перегружает аддон без всякого селекшена. - Аддон пишет в mods.txt строчку про включение/выключение и перезагрузку. - Очень сильно пытался прикрутить хот-кеи, но разрабы перекрыли там весь кислород, так что не вышло, и похоже оно вообще не возможно. Alert: - Далеко не все стандартные аддоны можно безнаказанно перезагружать, некоторые после перезагрузки тупо перестают работать, поэтому аккуратнее. - Не рекомендуется использовать этот менеджер аддонов с каким-либо еще одновременно, так как аддоны не умеют оповещать друг друга о своем состоянии, и потому менеджеры могут разойтись во мнениях, какой аддон включен, а какой - нет. - Данный аддон восстанавливает сохраненное состояние, реагируя на EVENT_AVATAR_CREATED, поэтому возможно некоторые аддоны, которые на инициализации спят, и включаются только этим менеджером, могут проспать этот эвент. Вроде все. Пользуйтесь на здоровье. File: AddonReloader.zip
  17. Потому что это работает так: Code: block = ( block and false ) or true Выражение в скобках всегда разрешается в false. После чего оставшееся выглядит так: Code: block = false or true Что получится? =)
  18. Привет. =) Нет никакой мистики. Подумай в таком ключе: аддонов куча, многие подписаны на искомый ивент, и совсем никто не знает, в каком порядке будут выполнены хэндлеры этих аддонов. В таких условиях любой чих, даже само сочетание установленных аддонов может сильно влиять на проявляемость бага. Можно проверить влияние имен аддонов, уверен, оно есть. Нивальский драг-н-дроп за вами иногда не успевает. =) По-хорошему, весь этот mission.DND... для абсолютной безбаговости должен управляться централизованно только одним специализированным аддоном. Ибо налицо ситуация острой конкуренции за эту функциональность между аддонами, которые друг о друге и не догадываются, и договориться друг с другом не могут. Offtopic: А почему у меня превью поста кракозябрами? =( (только) Я в Опере последней живу под XP.
  19. ЗачОт! =) А вот такое если: Code: avatar.GetItemInfo(avatar.GetInventoryItemIds() [0] ) Там хорошая вложенность, и вообще много интересного.
  20. Пустой WidgetLayerSimpleTexture решает все проблемы. Белый квадрат. Размеры - пофигу. Если надо покрасить - добавляем цвет. Болванка пустого слоя: Code: <WidgetLayerSimpleTexture> <Color>0xffffffff</Color> <BlendEffect>BLEND_EFFECT_ALPHABLND</BlendEffect> </WidgetLayerSimpleTexture>
  21. Дык, вперед. Кто запостит текущее содержимое _G - тот сам себе молодец. А через недельку запосчу (запостю? =) сам, и сравним. Не думаю, что кто-то захочет адаптировать на 5.0 аццкую функцию на ~170 строк от metalua.luaforge.net. http://lua-users.org/wiki/ZenOfLua - grok it! =) File: _G.zip
  22. Тестом на рекурсию пусть будет безбаговый вызов TableToString( _G ).
  23. Мне не нада, у меня есть. =) Upd: там много интересного, но почти все под 5.1.x. Для таблиц string.match в 5.0.x не нашел, хотя оно там вроде не особо и надо... надо посмотреть, короче. =)
  24. 1. "Гнобить" не хотел. Нравится твоя инициатива и совсем не нравится реализация. Пытался подсказывать, не указывая недостатков. Если кратце, пообщались так: - DarkMaster: давайте пользоваться моей библиотекой! - kosh, Valltron, Ramirez: Сходу ниасилил. Сомневуха берет. Без нее пока проще. - DarkMaster: Да не, смотрите как клево! - Valltron: Да не. Вот на ивенты хитро подписываться - это клево! ... Эскапада с Demens'ом - DarkMaster: Я тут дописал, теперь еще лучше. - Ramirez: А вот смотри, классы по-Нивальски - прикольные! - DarkMaster: Да один хрен, дело вкуса. Ты про реакции давай колись. - Ramirez: Нифига, оно по возможностям шире. Про реакции - облом, только в обход. - DarkMaster: Не гони, нету разницы. Смотри, какой SetWidth простой! - Ramirez: Он лишний, там placement есть. ... И понеслась. Ты не понимал про "узконаправленную, громоздкую и сырую" - я расписал. Аргументов там достаточно. Не нравятся мои - поспрашивай еще кого-нибудь из камрадов, кто-нибудь библиотеку пытался использовать? Нормальный менеджер НЕ решает за подчиненных их задачи, иначе они ему на шею сразу сядут. И слова "истенна" в языке нет. =) Quote: "Тонкий" намек на "толстую реализацию" - ну и что ? Прочитав это я что должен понять ? Что я криворуки неудачник ? *) В чем смысл данного коммента ? Где тут конструктив по сабжу ? Если ты умеешь лучще, видишь как нужно сделать правельно - конкретезируй, а иначе это выглядит - не коректно *))) Дублирую предыдущий пост: Code: GetChildByName -> widget:GetChildUnchecked( name, recursive )GetChildByIndex -> widget:GetNamedChildren() [ ChildIndex ] SetColor -> widget:SetBackgroundColor( color ) GetChildCount -> GetTableSize( widget:GetNamedChildren() ) Hide -> Show( false ) ShowAllChild, HideAllChild -> parent:Show( bVisible ) Расшифровываю: в строках после "->" дана ПОЛНАЯ замена твоим функциям. Как еще конкретизировать? 2. С твоих слов, цель мудаков из Нивала - бесконечно осложнять тебе жизнь. Так вот, их цель - игру сделать и тебе продать. И placement - он, чтобы виджетами нивальскими пользоваться. Если пользуешься - разберись. Обертка сейчас - хуже. Аргументы уже приводил. 3. Толпа ненужных функций мешает знакомиться с твоим кодом. Из чего возникло "ниасилил" у некоторых камрадов. 4. Подход реализации А тупиковый, развивать бессмысленно. Кодер Х высказывает альтернативные идеи. С примерами. Идеи игнорируются. Кодера Х активно разводят на готовый код. Кодеру Х реализация А не нужна. Он все равно должен что-то писать? Итог: Учить - и не брался, учиться извольте сами. Я здесь ссылки приводил на Lua.org, хоть один камрад там побывал? Все приведенные мной примеры кода вызывали в ответ непонимание и "гнутие пальцев" в стиле "можно и так, просто дело вкуса". Развернутые попытки показать разницу - либо игнорируются, либо вызывают недовольство. Ну ок.
  25. 1. нету такой в AO. 2. нет защиты от рекурсивных ссылок.
×
×
  • Создать...

Важная информация

Пользуясь сайтом, вы принимаете Условия использования