Записи участника (SirNikolas) - Форум


Правила форума ·

  • Страница 1 из 4
  • 1
  • 2
  • 3
  • 4
  • »
Результаты поиска

SirNikolas

#1 | Тема: Anti-Leak Library
Данная библиотека предназначена для тех, кто не хочет или не может изучать JASS, но имеет проблемы с утечками. Для использования необходимо:
1. Установить JASS NewGen Pack.
2. Если у вас нет меню "cJass", скачать AdicHelper и поставить его сверху на JNGP.
3. Скачать, собственно, саму библиотеку и закинуть ее в папку ...\jassnewgenpack5d\AdicHelper\lib\
4. В своей карте написать в нестандартном коде: include "ALL.j"
5. Забыть об утечках.

Результат - такое действие, как, например, "Боевая единица - Move (Triggering unit) to ((Position of (Target unit of ability being cast)) offset by 200.00 towards (Angle from (Position of (Triggering unit)) to (Position of (Target unit of ability being cast))) degrees)" не будет оставлять утечных точек.

Если же Вам нужно, к примеру, занести точку в переменную для дальнейшей работы с ней, перед этим действием нужно прописать Личным сценарием (Custom script): ALL_Remove = false, а после него - ALL_Remove = true.

Однако повторюсь, лучше использовать JASS, ведь вручную можно сделать все гораздо лучше.
letitbit.net
depositfiles.com
Сообщение отредактировал SirNikolas - Ср, 28.12.11, 17:55
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#2 | Тема: Dictionary

Класс Dictionary


Что-то я в последнее время стал делать из JASS'а C++ :)



Предисловие


Данный класс - это ассоциативный массив, он является эквивалентом классов std::map в C++ и System.Collections.Generic.Dictionary в C#. Проще говоря, это массив, в качестве индексов в котором выступают не целые числа, а любые типы, которые Вы укажете.


Использование


Основное применение - создание баз данных. Скорость обращения к таким базам относительно линейного поиска тем выше, чем больше элементов в базе. Также в качестве индексов Вы можете использовать... таймеры. Да, это еще одна замена хэшу, однако применять ее стоит лишь тогда, когда одновременно существует много объектов. При малом количестве повышения производительности не будет.


Объявление типа


Думаю, можно не говорить, что следует скопировать триггер Dictionary себе в карту. Затем Вам нужно определить функции, которые будут сравнивать индексы. Создаются они по такому шаблону:[jass]library <Имя>
public function less takes <Имя типа> left, <Имя типа> right returns boolean
<Условие, если левый операнд меньше правого>
endfunction

public function equal takes <Имя типа> left, <Имя типа> right returns boolean
<Условие, если операнды равны>
endfunction
endlibrary[/jass]Разберем на конкретном примере - пусть нам нужен массив с индексатором integer:[jass]library IntegerComparison
public function less takes integer op1, integer op2 returns boolean
return op1 < op2
endfunction

public function equal takes integer op1, integer op2 returns boolean
return op1 == op2
endfunction
endlibrary[/jass]
После этого необходимо объявить массив нужного типа. Делается это с помощью следующей инструкции препроцессора:[jass]//! runtextmacro DeclareDictionary("<Тип индексатора>","<Тип значений>","<Наследуется ли индексатор от handle>","<Наследуется ли значение от handle>","<Имя библиотеки сравнения>","<Максимальный суммарный размер всех словарей данного типа>")[/jass]Например:[jass]//! runtextmacro DeclareDictionary("integer","unit","false","true","IntegerComparison","8191")[/jass]Эта инструкция объявит тип массива unit с индексом integer (integer не наследуется от handle, unit - наследуется, поэтому "false, true"). Для сравнения ключей будут использоваться функции из библиотеки IntegerComparison, размер всех словарей - 8191. Этот размер не стоит уменьшать - память Вы этим не сэкономите.
Обратите внимание: все значения макроса пишутся в кавычках; между запятыми и кавычками не должно быть пробелов!
Все необходимые приготовления сделаны, можно начинать кодить.


Работа с классом


Нужно просто объявить переменную типа Dictionary_<Тип индексатора>_<Тип значений> и инициализировать ее значением Dictionary_<Тип индексатора>_<Тип значений>.Create(), затем можно использовать ее как обычный массив:[jass]function Example1 takes nothing returns nothing
local Dictionary_integer_unit d = Dictionary_integer_unit.Create()
set d[0] = CreateUnit(...)
set d[1] = null
set d[-1] = CreateUnit(...)//Записываем по отрицательному индексу. Да, это возможно!
set d[100500] = CreateUnit(...)//И это тоже разрешено!
call KillUnit(d[0])
call RemoveUnit(d[-1])
//После использования, если массив временный, его необходимо уничтожить:
call d.Destroy()
endfunction[/jass]Однако гораздо чаще требуются словари, которые существуют всю игру и, следовательно, не требуют удаления. Их можно делать глобальными:[jass]globals
Dictionary_integer_unit MyDict
endglobals

function InitTrig_Example2 takes nothing returns nothing
set MyDict = Dictionary_integer_unit.Create()
set MyDict[0] = CreateUnit(...)
endfunction[/jass]Следует запомнить, что глобальный словарь, к сожалению, нельзя создать сразу же в globals.[jass]globals
Dictionary_integer_unit MyDict = Dictionary_integer_unit.Create()//Недопустимо!
endglobals[/jass]

Можно полностью очистить массив, не удаляя его:[jass]call MyDict.Clear()[/jass]Также есть свойство, показывающее количество элементов в данный момент:[jass]local Dictionary_integer_unit d = Dictionary_integer_unit.Create()
set d[0] = CreateUnit(...)
set d[1] = CreateUnit(...)
set d[2] = CreateUnit(...)
set d[3] = CreateUnit(...)
call BJDebugMsg(I2S(d.Count))//Выведет "4"
call d.Destroy()[/jass]После "Count" скобки не пишутся.

При попытке получить из словаря значение, которое не было туда помещено, будет возвращено значение по умолчанию. Вы также можете просто узнать, есть ли оно там:[jass]local Dictionary_integer_unit d = Dictionary_integer_unit.Create()
set d[0] = CreateUnit(...)
call BJDebugMsg(I2S(GetHandleId(d[2])))//d[2] пуст, поэтому будет возвращен юнит null, ID которого равен 0
if not d.Exists[2] then
call BJDebugMsg("По индексу 2 ничего не записано")
endif
call d.Destroy()[/jass]Если Вы делаете большую базу данных, которая не меняется всю игру, и Вам нужно ее максимальное быстродействие, Вам может оказаться полезным метод Rebuild, перестраивающий словарь для наиболее быстрого доступа к элементам. Следует учесть, что он достаточно медленный, поэтому после каждого обновления его вызывать не стоит.[jass]//! runtextmacro DeclareDictionary("integer","string","false","false","IntegerComparison","8191")

globals
Dictionary_integer_string SpellData
endglobals

function Trig_Spells_Actions takes nothing returns boolean
local string s = SpellData[GetSpellAbilityId()]
if s != null then
call ExecuteFunc(s)
endif
return false
endfunction

function InitTrig_Spells takes nothing returns nothing
local trigger trig = CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(trig, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT,  null)
exitwhen i == 15
set i = i + 1
endloop
call TriggerAddCondition(trig, Condition(function Trig_Spells_Actions))
set trig = null

set SpellData = Dictionary_integer_string.Create()
set SpellData['A000'] = "Trig_FireStorm_Actions"
set SpellData['A001'] = "Trig_IceWall_Actions"
set SpellData['A002'] = "Trig_PoisonTouch_Actions"
set SpellData['A003'] = "Trig_HandOfGod_Actions"
set SpellData['A004'] = "Trig_Timeback_Actions"
//...
call SpellData.Rebuild()
endfunction[/jass]Еще один способ применения, который я упомянул ранее - создание MUI-спеллов.[jass]//! runtextmacro DeclareDictionary("timer","TimebackStruct","true","false","HandleComparison","8191")

library HandleComparison
public function less takes handle op1, handle op2 returns boolean
return GetHandleId(op1) < GetHandleId(op2)
endfunction

public function equal takes handle op1, handle op2 returns boolean
return op1 == op2
endfunction
endlibrary

globals
Dictionary_timer_TimebackStruct TimebackDict
endglobals

struct TimebackStruct
unit u
real x
real y
endstruct

function Trig_Timeback_Timer takes nothing returns nothing
local timer t = GetExpiredTimer()
local TimebackStruct s = TimebackDict[t]
call SetUnitX(s.u, s.x)
call SetUnitY(s.u, s.y)
set TimebackDict[t] = 0
call DestroyTimer(t)
call s.destroy()
set t = null
endfunction

function Trig_Timeback_Actions takes nothing returns nothing
local TimebackStruct s = TimebackStruct.create()
local timer t = CreateTimer()
set s.u = GetSpellTargetUnit()
set s.x = GetWidgetX(s.u)
set s.y = GetWidgetY(s.u)
set TimebackDict[t] = s
call TimerStart(t, 5., false, function Trig_Timeback_Timer)
set t = null
endfunction

function InitTrig_Timeback takes nothing returns nothing
set TimebackDict = Dictionary_timer_TimebackStruct.Create()
endfunction[/jass]Важный момент - в таких случаях необходимо ВСЕГДА обнулять данные массивов, даже если это integer или real.


Взгляд изнутри


Этот раздел посвящен тем, кто хочет разобраться, как именно (и почему smile ) данная система работает.

Класс Dictionary сделан на основе бинарного древа, так что доступ к элементам осуществляется с логарифмической скоростью. При перестроении дерево раскладывается в массив, который сортируется методом расчески и снова собирается в дерево. Код не влез в размеры сообщения, но его можно скачать отдельно.


Если возникнут вопросы, задавайте, не стесняйтесь. smile

Сообщение отредактировал SirNikolas - Сб, 07.01.12, 20:19
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#3 | Тема: bitset
bitset - это класс в языке C++, позволяющий оперировать каждым отдельным битом в числе. Это настолько полезная штука, что я решил реализовать ее в JASS. Конечно, у этой версии возможностей меньше, чем у оригинала, но для WarCraft это не важно.

Я сделал две версии - для vJASS (требуется JNGP) и для простого JASS2. Думаю, не надо говорить, какая из них более удобная и обладает большим функционалом.

В данный момент система поддерживает работу только с 30 битами (из 32), однако это будет исправлено в будущем.

Самое простое использование bitset - перевод чисел из десятичной системы счисления в двоичную и обратно:
Code
local bitset bs = bitset.create()
set bs.integer = 100
call BJDebugMsg("dec(" + I2S(bs.integer) + ") = bin(" + bs.string + ")")
set bs.string = "1100100"
call BJDebugMsg("dec(" + I2S(bs.integer) + ") = bin(" + bs.string + ")")
call bs.destroy()
Сначала нужно создать объект bitset и записать в его переменную этого типа. Затем мы можем получить доступ к десятичному представлению числа и двоичной строке, используя "<имя переменной>.integer" и "<имя переменной>.string". После использования объект необходимо уничтожить, иначе будет своеобразная утечка памяти.

Создавать bitset можно не только через .create():
Code
local bitset bs = bitset.create()//Создает bitset с нулевым начальным значением
local bitset bs2 = bitset.initialize(10)//Создает объект и присваивает начальное значение 10
local bitset bs3 = bitset.parse("10100")//Создает объект и присваивает начальное значение, соответствующее переданной двоичной строке, т. е. 20


Также с помощью этой системы можно получать или изменять конкретные биты в числе с помощью квадратных скобок:
Code
local bitset bs = bitset.initialize(10)//"1010"
set bs[0] = true
call BJDebugMsg(bs.string)//Выведет "1011"
set bs[1] = false
call BJDebugMsg(bs.string)//Выведет "1001"
set bs[3] = true
call BJDebugMsg(bs.string)//Выведет "1001" - значение не изменилось
if bs[2] == false then
     call BJDebugMsg("Третий бит равен 0")
endif
call bs.destroy()
Заметьте, что биты нумеруются справа налево, с нуля.

И, наконец, можно "вырезать" и "заменять" целые группы битов:
Code
local bitset bs = bitset.parse("10011100")//156
call BJDebugMsg(I2S(bs.cut(1, 3)))//Вырезает со второго по четвертый биты ("110"); выводит их десятичное представление - 6
call bs.replace(0, 2, 2)//Заменяет с первого по третий биты двоичной строкой, соответствующей числу 2 ("010")
call BJDebugMsg(bs.string)//Выведет "10011010"
call bs.destroy()


В демонстрационной карте приведено четыре примера практического применения класса bitset.

Скачать v1.0
Скачать v1.0 JASS2
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#4 | Тема: Правила Сайта и Форума
Quote (ПРАВИЛА ОТКРЫТИЯ НОВОЙ ТЕМЫ)
4. Запрещено создавать темы, имеющие в названии более 50 процентов ЗАГЛАВНЫХ БУКВ. Пример: Правила Форума, а не ПРАВИЛА ФОРУМА. За каждое такое нарушение, Вы получите предупреждение от модератора.
Quote
ПРАВИЛА САЙТА И ФОРУМА
lol
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#6 | Тема: Anti-Leak Library
Quote (Ty3uK)
ищет утечные бж и заменяет их. Все smile
Нет, не всё. Он также отлавливает все функции (native & BJ), возвращающие утечные типы, и прогоняет их результат через свою функцию, которая запускает таймер на .0 секунд и удаляет утечку спустя это время.
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#7 | Тема: Dictionary
Ty3uK, суть не в расческе. Суть в том, что эта штука построена на бинарном древе => поиск элементов куда быстрее линейного.
Quote (H_A_PK)
Только я вот не пойму, мало - это сколько? 1400 - 1500?
При 1024 элементах худший случай - когда искомое значение находится в самом конце, на 1023 месте. Линейный поиск найдет его на 1024 шаге, бинарный же - на 10. Есть разница? smile

BTW, автоматической сортировки тут нет, зря ты это написал. Древо сортируется при вызове метода .Rebuild(). Это массив с произвольным индексированием.
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#8 | Тема: Anti-Leak Library
Правда, он будет бессилен, если кодер напишет свою утечную функцию. Но, с другой стороны, какой же это кодер! smile
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#9 | Тема: Личный кабинет
SunCreep, нескромный вопрос: а ты знаешь, что такое циклы? Используя их вместе с массивами, можно сократить плод твоих титанических усилий до трех триггеров, как и писал GraF.

В общем, вот полностью переделанная версия:
http://rghost.ru/35542036

P. S. Впервые за несколько месяцев написал на GUI больше пяти строк подряд. Какая же это ж... жуть.
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#10 | Тема: Досчитаем до 1 000 000 000
15-4380-412#59614
А в чем смысл темы? Неужели так интересно писать номер своего поста?

Кстати, вы знаете, что вам понадобится примерно 81000 лет, чтобы досчитать до миллиарда? smile

Добавлено (24.12.11, 12:54)
---------------------------------------------
15-4380-412#59617*

"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.

SirNikolas

#14 | Тема: Arena Multiboard (Jass 2 / cJass)
Ty3uK, обычно выкладывают код системы, а не весь код карты.
Бегло пробежался по коду. Сделано, вроде, аккуратно, никаких грубых ошибок нет (что и следовало ожидать). Правда, я бы определение цвета сделал через свое любимое дерево:
Code
string GetPlayerNameColored(player p) {
     int id = GetHandleId(GetPlayerColor(p));
     if id < 6 {
         if id < 3 {
             if id == 0 {
                 return "|cFFFF0303" + GetPlayerName(p) + "|r";
             } elseif id == 1 {
                 return "|cFF0042FF" + GetPlayerName(p) + "|r";
             } else {
                 return "|cFF1CE6B9" + GetPlayerName(p) + "|r";
             }
         } elseif id == 3 {
             return "|cFF540081" + GetPlayerName(p) + "|r";
         } elseif id == 4 {
             return "|cFFFFFC00" + GetPlayerName(p) + "|r";
         } else {
             return "|cFFFE8A0E" + GetPlayerName(p) + "|r";
         }
     } elseif id < 9 {
         if id == 6 {
             return "|cFF20C000" + GetPlayerName(p) + "|r";
         } elseif id == 7 {
             return "|cffff80c0" + GetPlayerName(p) + "|r";
         } else {
             return "|cFF959697" + GetPlayerName(p) + "|r";
         }
     } elseif id < 11 {
         if id == 9 {
             return "|cFF7FBFF1" + GetPlayerName(p) + "|r";
         } else {
             return "|cFF106246" + GetPlayerName(p) + "|r";
         }
     } elseif id == 11 {
         return "|cFF4E2A04" + GetPlayerName(p) + "|r";
     } else {
         return "the |cFF333429" + GetPlayerName(p) + "|r";
     }
}
"I will make this the first approved cJass-only resource here on the Hive" - Bribe about ALL.
  • Страница 1 из 4
  • 1
  • 2
  • 3
  • 4
  • »
Поиск: