27

» WarCraft 3 / Требование к покупке предмета

Принятый ответ
Вот еще (тех ополченцев переделать надо в даймиков)
  1. сделана на хэше. В частности каждый тип юнита - целое число (паладин, архимаг и др). Эти типы (числа можно в качестве ключей использовать. А в самом хэше можно сохранить число (1 - воин, 2 - маг, 3 - лучник и так далее).
  2. В РО (редакторе объектов) в предметах также забиваем базу данных. Мы можем использовать уровень, или хп. В поле "уровень" можно записать кол-во золота, чтобы вернуть игроку. В поле "хп" можно записать к какому классу относится (101 - воин, 102 - маг и др)
В моей системе можно узнать - куплен ли предмет или просто подобран/передан кем=то. Имеется связь между покупкой и получением итема (покупка типа раньше происходит). Если куплен не тем классом героя, то итем удалим, деньги вернут. Если не тот класс подобрал, то итем дропается.
Ну добавлять требование можно обратно, при смерти героя (этого не делал).
Загруженные файлы
27

» WarCraft 3 / Требование к покупке предмета

WinneR_302, как это не то? в игре при выборе какого-нибудь класса героя, создаете dummy (если маг - даммик 1, если воин - даммик 2). Это если одного героя выбираете
Единственное, что, если героев можно выбрать несколько (могут возникнуть проблемы, например, можете нанять мага и паладина), также покупать могут не только герои, но и обычные юниты , то делайте систему проверки (кто покупает-и какой тип, если не тот - удаляете сразу, возвращаете деньги, выводите текст : "Предмет не соответствует вашему классу")
27

» WarCraft 3 / Требование к покупке предмета

Могу добавить что это работает только на сделанные предметы из магазина принадлежащего тебе. + один раз изучив технологию заблокировать предмет снова нельзя.
Вот пример. В требование вставляете не технологии, а dummy (с англ. куклу, невидимого (без модельки), неуязвимого, не отмеченного на карте юнита. У него убираете атаку, скорость, обзор видимости, даете москитов и все. Где-нибудь в углу создаете.).
Загруженные файлы
27

» WarCraft 3 / Как через улучшение, увеличить количество выходящих юнитов?

Принятый ответ
Так понимаю это типа спавн как футманы или ТД-шки. можно либо ифами или через подсчет
через ифы
Событие - Завершение улучшение
Условие - Проверка улучшения твоего (тип такой-то)
Действие - 
Если исследования == уровень 1
	тогда set n = 2
Иначе Если исследования == уровень 2
	тогда set n = 3
или проще через формулу
Событие - Завершение улучшение
Условие - Проверка улучшения твоего (тип такой-то)
Действие - set n = x + 1

x - уровень исследования
n - переменная. Когда будете создавать, используйте эту переменную 
27

» WarCraft 3 / Как отследить количество юнитов?

Эта команда "Number of group" - это перебор всех юнитов в группе (если раскрыть BJ-функцию, там к целочисленной переменной прибавляют единицу, +вторую группу используют ),
можно было не вызывать ForGroup (это на Jass), использовать цикл с помощью FirstOfGroup(группа)
правда тут юнит удаляется из группы. суть вот в чем, команда FirstOfGroup берет первого юнита в группе, прибавляем единицу к глобалке. затем этого юнита удаляем из группы, чтобы взять следующего FirstOfGroup. Цикл будет идти до тех пор, пока не удалится из группы последний юнит, то есть FirstOfGroup(группа)==null (FirstOfGroup покажет null, типа юнита нет)
local unit e
local integer c = 0
local group g = CreateGroup() //группа
call GroupEnumUnitsInRange(g,x1,y1,180,null) //Выбираем всех юнитов вокруг точки (x1,y1)

//цикл
loop
	set e = FirstOfGroup(g) //первый юнит в группе
	exitwhen e == null //условие выхода из цикла
	call GroupRemoveUnit(g,e) //удаляем юнита из группы
	set c = c + 1 //прибавляем в счетчик
endloop
call DestroyGroup(g)
set e = null
set g = null
Короче тут вместо GetEnumUnit() будет переменная e
проблема конечно, если нам будет надобно, чтобы юниты были в группе. тогда нам нужна будет вторая группа, в нее пихаем удалившего из первой группы. так делают и в триггерной "Number of group", чтобы сохранить всех юнитов.
чтобы проверить, что группа пуста, есть условие
FirstOfGroup(группа)==null
Типа нет ни одного юнита, значит группа пуста.
27

» WarCraft 3 / Удастся ли заменить GUI-функции в файле Blizzard.j?

Принятый ответ
считаю глупостью заниматься такими вещами. Только чистый jass и понимание, где что утекает (и оптимизация кода).
Тут столько программистов и до сих пор вы не сделали универсальную библиотеку?
сам удивляюсь. Но помнится кто-то делал. Если честно, jass vjass знаю, и я таким не хочу заниматься, меня все устраивает. Даже, если это все будет, новички все равно будут вопросы задавать, инструкции для новичков faq не читают, поиск не юзают (столько вопросов задавали), учиться не хотят. Считаю это бесполезным занятием. Считаю лучше jass, просто менюшками не удобно пользоваться: в них бывает нет всех команд и функции, + это надо все искать по специальным разделам и др.
Суть в том, что это библиотека должна быть не только у тебя, но и у другого юзера. Если ты сделал новыми менюшками триггер, сохранил карту, передал другому человеку. К него должна быть по идее такая же библиотека, иначе не заработает, или не откроет, так как такой функции в редакторе у него нет.
27

» WarCraft 3 / Вопрос про "Раз." массива предметов

Принятый ответ
Это размерность (или размер) массива при инициализации. Видишь строку: "Назн. знач.", напротив текста стоит красненькое слово "Нет". Вот если изменить эту строчку задать что-то. То вы измените и зададите каждому индексу массива значение.
Вот допустим задаете размерность: 3 целочисленной переменной A. Значение будет 5.
При инициализации
set A[0]=5
set A[1]=5
set A[2]=5
set A[3]=5 вроде не уверен, обычно нумерация от нуля начинается
Короче это можно проверить дебагом, то есть выводи на экран.
ссылка
27

» WarCraft 3 / Откуда они берутся эти утечки...

boolexpr - фильтр, работает чаще всего с группами объектов (есть не только группа юнитов, есть группа игроков, выборка декорации, итемов и др). Отсеивает при выборе не нужных юнитов. если ничего туда не вписать (null) то будет брать всех. Например, нужно чтобы выделял только героев, вставляете в условие, а не герои в группу не попадут (отсеятся). Короче фильтр это условие. Если что можно на сайте посмотреть примеры, на форуме.
Ее уничтожать не надо, она не утекает. А короче почему поиск не юзаешь? вбивай по словам: filter, DestroyBoolExpr, BoolExpr и др. На сайте поиск плохой, поэтому пробуйте еще на гугле: "boolexpr xgm". На форуме также пробуйте искать
27

» WarCraft 3 / Как создавать предметы в нейтральном здании?

Принятый ответ
Уже не пойму как это работает. Помню одну хитрость, напишу. Так если посмотреть в стандартных картах, например, чтобы построить одно здание, нужно другое (мастерской нужна кузница). Или чтобы купить одного юнита, нужно иметь еще одно определенное здание (стрелка можно нанять при наличии кузницы). По сути, можно в требованиях вставить невидимого даймика. Если триггерно добавить, то это требование уберется. Если хотите снова добавить требование, удалите даймика. А в имени даймика пишем: "Победить босса первого уровня".
только не знаю соответствует ли данной вашей проблеме, так как не изучал подробно
27

» WarCraft 3 / Откуда они берутся эти утечки...

Alexey103, можно сделать вот что:
как это сделать самостоятельно
  1. скачиваете jngp, устанавливаете. Проблемы с установкой или не работы высылай скрины ошибок, запиши видео - не понятно что не работает у вас
  2. Берете гуишную команду
  1. чтобы посмотреть что из себе представляет гуишная команда, берете выделяете данный триггер. Потом жмем "Правка - конвентировать в код".
Конвентируете в код и получаем код (смю рисунок ниже). У меня код представлен с подсветкой, данной jngp. В обычном редакторе код мелкими буквами печатает.
  1. берете и выделяете нужную функцию. как выше GetUnitsInRectAll. Копируете ее название. Потом как на рисунке ниже жмем на "Function List"
  1. Откроется окно. Это короче библиотека функции, здесь можно найти любую функцию, нативку или переменную. Вставляем скопированный текст. Находим функцию
function GetUnitsInRectAll takes rect r returns group
    return GetUnitsInRectMatching(r, null)
endfunction
function GetUnitsInRectMatching takes rect r, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRect(g, r, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction
как видно, проблема в BJ функции GetUnitsInRectMatching. Она создает каждый раз группу, и еще не обнуляется локалка.
Точно также можно сделать любой другой Jass программе. Но мне что-то удобно в jngp
Загруженные файлы
27

» WarCraft 3 / Откуда они берутся эти утечки...

Alexey103, так все функции BJ группы с выбором юнитов утекают. Там бывает локалка g не обнуляется, ее сразу возвращает функция, а обнулить таким случаем нельзя (если код по-другому переписать, там глобалку вставить).
27

» WarCraft 3 / Дайте инструкцию по решению всех утечек?

Принятый ответ
инструкции как таковой нет, могу описать, но здесь миллион примеров нужно, чтобы разжевать новичку (и случаи уникальны у каждого, и их очень много. Не знаю с чего начать). А вообще что там сложного? знаешь jass, и все. Тебе нужно знать является ли объект хэндл, и нужно ли его удалять (или побочная нативка удалит, как например у текстагов. Текстаги можно не удалять напрямую, есть у него функция, задающая время жизни. Текстаг сам исчезнет. Или вот фильтр удалять не обязательно, она не утекает). Все одинаково: нужно удалить объект (помню, у меня жестко мультиборд утекал, пока не узнал, что есть функция обновляющая ячейку, она еще дает не плодит новые). Поэтому нужно знать можно ли удалить (умирающего юнита например удалять не нужно, сам разложится. А вот например предметы как руны нужно, при подборе руны, руна остается в игре. Например, миллионы книжек в магазине, если игрок будет покупать миллионами, он будет плодить. Поэтому при получении удаляй сразу). Чистить содержимое в хэш-таблице, и обнулять локалки. Функции BJ могут утекать, там не обнуляют локалки. Раскрыть функции BJ, там где есть локалка не обнуленная подправить и др. Помню, хотел взять координаты от точки, там x и y. Я вызвал (создал) два раза точки, раньше не понимал, что создаю точки. Нужно найти альтернативные, что возвращают не точку, а координаты (реальные числа), например, юнита. Чтобы знать, это надо смотреть на сайте (попался необычный хэндл, вбиваешь в поиск). Тебе нужна библиотека всех функции и нативок. Очень удобная библиотека есть в jngp. Щас нубы очень не любят jngp, так как не отображает ошибки и не компилирует что-то. Так выключите плагин UMSWE, и Vjass и Cjass тоже выключите. Пользуйтесь библиотекой и новыми триггерными менюшками, доступны в hNGP без этого. Все придет с опытом, просто подольше посиди с кодом.
27

» WarCraft 3 / Можно ли на гуи отследить атаку и защиту юнита.

Атаку можно: можно замах отследить, и урон. Устал повторять для новичков. Сначало происходит анимация замаха (юнит атакован), а после начинает замахивается, пускать снаряды. Пока снаряды летят или произойдут замахи в ближнем бою, затем срабатывает событие - юнит получает урон. То есть урона нет, как бы заранее получает инфу о получении урона. Можно харанее там отхилять здоровье и прочее. А потом урон приходит спустя 0.00 сек. Многие отслеживают урон с помощью события юнит атакован - это неправильно, так как можно промахнуться, а с событием "юнит получает урон" не получится (а так в одной игре за атаку я получал кучу бонусов: золота миллион). Но событие юнит атакован даст знать, что урон от руки. Какой тип атаки и тип защиты нельзя обычным способом узнать. только мем хаком.
Защиту как бы нельзя отследить никак. В мем хаке можно вот узнать сколько брони и так далее имеет. Юнит имеет разных типов защиты и кучу защитных способностей (уклонение, астрал и др). Можно триггерно самому сделать триггерную защиту, тогда делай систему урона
27

» WarCraft 3 / Можно ли на гуи отследить атаку и защиту юнита.

Принятый ответ
А поиск используешь?
вот
перевод с сайта
сайт
custom value - целочисленное значение, которое вы устанавливаете с помощью триггера в единицу. в начале всегда всегда 0 для каждого блока, но вы можете установить его для каждого целого числа с действием «unit - set custom value».
Можете также и узнать сколько у юнита этого custom value. Переводится как обычное значение. Оно есть у юнита, предмета. У каждого юнита или предмета оно может быть разным. Короче можно систему намутить
Point Value (ты наверное про нижнюю функцию, также в первый раз слышу)? так в нее триггерно ничего нельзя записать, только узнать.
native GetUnitPointValue takes unit whichUnit returns integer
вот нашел проверь
перевод
Значение точки - это целочисленное значение, заданное в редакторе объектов для типа единицы. на самом деле это значение того, сколько очков вы получите для обучения этого подразделения в конце игры, однако это бесполезно в пользовательских играх, и вы можете использовать его для настройки некоторых функций вашей карты. точечное значение единицы всегда задается в редакторе объектов и не может быть установлено на что-то еще во время игры. также все единицы того же типа получили одно и то же значение.
27

» WarCraft 3 / Исследование порчи (Blight)

Сделал наработку для себя, чтобы порча не распространялась в ту сторону, где стоит вард
р
Загруженные файлы
27

» WarCraft 3 / Тригерное похищение жизни

Не луч, а молния. Так молнию можно создать. И двигать тоже можно. Молния это отрезок - там две точке (начальная и конечная). Можно конечную двигать дальше или ближе от конечной. Представим, что начальная точка - точка кастера, конечная - точка цели. Все, что нужно периодически смещать две точки молнии к этим точкам (к кастеру и к цели). По идее кастер стоит на месте и махает руками (ченнинг, это как у бурана или прочее, если прерывается, то заклинание завершается)
как отловить завершение ченнинг
Событие - юнит приводит событие в действие
Действие - создать молнию и включить всосалку
Событие - юнит завершает применение способности (или прекращает, не помню)
Действие - удалить молнию и выключить всосалку
27

» WarCraft 3 / Где утечка и как её убрать?

Alexey103, судя по скрину утечка есть в условии (boolean - unit has an item of type ....). там в функции BJ локалка indexItem не обнуляется. раскрой все функции, используй jngp. там цикл, что мешает самому написать функцию?
код
function GetInventoryIndexOfItemTypeBJ takes unit whichUnit, integer itemId returns integer
    local integer index
    local item    indexItem

    set index = 0
    loop
        set indexItem = UnitItemInSlot(whichUnit, index)
        if (indexItem != null) and (GetItemTypeId(indexItem) == itemId) then
            return index + 1
        endif

        set index = index + 1
        exitwhen index >= bj_MAX_INVENTORY
    endloop
    return 0
endfunction

function UnitHasItemOfTypeBJ takes unit whichUnit, integer itemId returns boolean
    return GetInventoryIndexOfItemTypeBJ(whichUnit, itemId) > 0
endfunction
27

» WarCraft 3 / Как создать конусные заклинания?

Все-таки в 4 варианте были ошибки. Я не правильно код сделал. Мне помог Doc исправить ошибки. Примеры исправленных ошибок
27

» WarCraft 3 / Как создать конусные заклинания?

JaBeN_Симфер, даже не знаю. Просто проверить надо, иногда кажется ошибки где-то. С проверочными молниями вот все проверил, норм. А скалярное произведение векторов иногда не робит, если боком стать. Может кажется, только 99% норм срабатывает. Я так думаю. что мне кажется.
Хорошо, мб я тупанул и работает норм в карте E6. А вот в карте E3 что то не так робит =( пример с хабра. Ну он работает (85% на 15%), но бывает и не работает. В обзорку в 180 град не попадает.
Вот конусные заклинания, добавил изменения, теперь молниями отображается ширина обзора кастера (будет понятно, кто попадает). Ничего сильно не исправлял, добавил молнии
Загруженные файлы
27

» WarCraft 3 / Как создать конусные заклинания?

Решил описать как определить находится вражеский юнит в обзоре нашего героя. Когда делал, я не знал как. Но сейчас нашел несколько вариантов.
Прежде всего это работа с группой. Мы выделяем всех юнитов вокруг в группу. Есть фильтры, которыми можно отсеивать не нужных. Проблема в том, что нужно определить кто попал, не попал. Относительно, все работает от угла обзора, точнее угла поворота юнита (куда смотрит юнит). Существует функция GetUnitFacing, относительно нее и будет делать все. Щас надо придумать как определить. находится ли юнит
1) Смещать центр круга от кастера, и выделять всех юнитов в группу, увеличивая каждый раз радиус круга.
Вот сама идея
Проблема в том, что нужно проверять не выделяется ли юнит в группу по несколько раз. Если мне надо просто узнать попал ли в обзор вражеский юнит, то тогда ладно. Если мне надо нанести урон всем, тогда лучше сначала выделить всех на разных позициях в группу и нанести урон. А не так: занес группу, нанес урон, очистил группу, пошел дальше повторять те же действия. Но бывают ситуации, когда нужны две группы: одна для перечисленных действия, другая для проверки.
2) С расчетом диапазона угла
Здесь идея идет на то, что попал ли угол между героем и выбранным юнитом.
Если угол направления стрелочки известен, то проверяй разницу между углом стрелочки и углом от центра круга до координат заносимых в группу юнитов
Есть данные:
-угол поворота юнита GetUnitFacing A - обычно принимается как центр обзора
-ширина обзора W - насколько угол обзора будет широким. Одна половина ширины слева, другая справа. Образует минимальный и максимальный углы.
-углы максимальный и минимальный
Все что нам нужно - это определить угол между двумя точками и затем проверять попал ли он в наш диапазон.
Можно сделать так, чтобы система брала углы от 0 до 360 град. Почему не в радианах? Можно и в радианах. Но легче понимать в градусах, к тому же GetUnitFacing возвращает от 0 до 360 градусов. А угол между двумя точками возвращает угол в радианах - Atan2 от -Pi до Pi.
Выделяются несколько проблем (раз делаю систему от 0 до 360 град.), которые решил
  1. угол между двумя точками возвращает радианы, к тому же отрицательные значения. Решение: преобразовал в градусы, и если отрицательные, прибавил 360 град.
  2. Если значение угла между точками не попадает диапазон от 0 до 360. Такого в принципе не может быть. так как GetUnitFacing возвращает от 0 до 360 градусов. Но проблема возникает из-за ширины обзора, одну половинку прибавил там (A+W/2) , другую отнял (A-W/2). И может получится так, что один из углов выйти за пределы круга: может быть так меньше 0, так и больше 360. Поэтому пришлось делить на два диапазона. Например: диапазон от -20 град до 30 град., то придется диапазон поделить на две части: от 0 град до 30 град и от 340 град до 360 град
код
пример можно посмотреть во вложенной карте E1
function Trig_CW_Cast_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A000' ) 
endfunction

//Если текущий угол а перешел за 0 град (точнее отрицат. значение), то функция вернет истину
function TZK takes real a returns boolean
return(a < 0)
endfunction

//Если текущий угол а перешел за 360 град , то функция вернет истину
function TZW takes real a returns boolean
return(a > 360)
endfunction

//Функция возвращает угол от 0 до 360. Если текущий угол а меньше 0, то функция вернет нужно значение
//например -40 град, а вернет 320 град
function TZE takes real a returns real

if a < 0 then
set a = 360 + a
endif

return a

endfunction

//Функция возвращает угол от 0 до 360. Если текущий угол а больше 360, то функция вернет нужно значение
//например 380 град, а вернет 20 град
function TZQ takes real a returns real

if a > 360 then
set a = a - 360
endif

return a

endfunction


function TZZ takes nothing returns boolean
local real x1 = GetUnitX(udg_Caster) //координаты кастера
local real y1 = GetUnitY(udg_Caster)
local real x2 = GetUnitX(GetFilterUnit()) //координаты пикнутого
local real y2 = GetUnitY(GetFilterUnit())
local real dx = x2 - x1
local real dy = y2 - y1
local real angle1 = TZE(Atan2(dy,dx)* bj_RADTODEG) //угол переводим из радианов в градусы. Это угол между точками кастера и пикнутого юнита
local real angle2 = udg_Angle //угол поворота. Выражен в градусах
local real angle3 = udg_X //Половина ширины угла. Выражен в градусах

local real A1 = TZE(angle2-angle3)
local real A2 = TZQ(angle2+angle3)

//Углы берется от 0 до 360 град. Если угол меньше нуля (например: диапазон от -20 град до 30 град.), то функция TZK вернет истину.  
//из-за того что угол вышел за ноль град. придется диапазон поделить на две части: от 0 град до 30 град и от 340 град до 360 град
local boolean B1 = TZK(angle2-angle3)
//Если угол меньше нуля (например: диапазон от 40 град до 370 град.), то функция TZW вернет истину.  
//из-за того что угол вышел за 360 град. придется диапазон поделить на две части: от 0 град до 40 град и от 350 град до 360 град
local boolean B2 = TZW(angle2+angle3)
local boolean b1 = false
local boolean b2 = false
local real AMin2
local real AMax2
local real Amin 
local real Amax

//устанавливает минимальный и максимальные углы, нужны для условии. Устанавливает правильный порядок диапазона
if B1 or B2 then 
    if A1 > A2 then
        set Amax = A2 //первый диапазон от нуля до ...
        set Amin = 0
        
        set AMax2 = 360 //второй диапазон от ... до 360
        set AMin2 = A1
    elseif A1 < A2 then
        set Amax = A1 //первый диапазон от нуля до ...
        set Amin = 0

        set AMax2 = 360 //второй диапазон от ... до 360
        set AMin2 = A2
    endif
    set b1 = ((Amin < angle1) and (Amax > angle1)) or ((AMin2 < angle1) and (AMax2 > angle1))
elseif not (B1 and B2) then
    if A2 >= A1 then //Здесь делить на два диапазона не нужно, достаточно одного
        set Amax = A2
        set Amin = A1
    elseif A2 < A1 then
        set Amin = A2
        set Amax = A1
    endif
    set b2 = (Amin < angle1) and (Amax > angle1)
endif


if (b1) and udg_Caster != GetFilterUnit() then
call BJDebugMsg("угол "+ R2S(angle1) + " град. попал в диапазон между углами " +R2S(Amin) +" и " + R2S(Amax) + " или в диапазон между углами "+R2S(AMin2) +" и " + R2S(AMax2) )
elseif (b2) and udg_Caster != GetFilterUnit() then
call BJDebugMsg("угол "+ R2S(angle1) + " град. попал в диапазон между углами " +R2S(Amin) +" и " + R2S(Amax))
elseif udg_Caster != GetFilterUnit() then
call BJDebugMsg("угол "+ R2S(angle1) + " град. НЕ ПОПАЛ в диапазоны между углами " +R2S(Amin) +" и " + R2S(Amax)+" или "+R2S(AMin2) +" и " + R2S(AMax2))
endif



return false
endfunction


function Trig_CW_Cast_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x1 = GetUnitX(u) //координаты кастера
local real y1 = GetUnitY(u)
local real from = 800
local real a = GetUnitFacing(u) //угол поворота юнита
local real S = 90 //Ширина угла
local real angle = S/2 //Половина ширины угла

    set udg_Angle = a
    set udg_Caster = u
    set udg_X = angle

call BJDebugMsg("Угол поворота при касте: "+ R2S(a))

call GroupEnumUnitsInRange(bj_lastCreatedGroup,x1,y1,from, Condition(function TZZ))
//call ForGroup( bj_lastCreatedGroup, function TZZ )
call GroupClear(bj_lastCreatedGroup)

endfunction

//===========================================================================
function InitTrig_CW_Cast takes nothing returns nothing
    set gg_trg_CW_Cast = CreateTrigger(  )
    set bj_lastCreatedGroup = CreateGroup()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CW_Cast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_CW_Cast, Condition( function Trig_CW_Cast_Conditions ) )
    call TriggerAddAction( gg_trg_CW_Cast, function Trig_CW_Cast_Actions )
endfunction
3) Математическая функция Warden
Нашел интересный код, определяет лежит ли угол между двумя углами. Получше даже моего варианта 2
код
function IsAngleBetweenAngles takes real angle, real angle1, real angle2 returns boolean
    local real x
    set angle = ModuloReal(angle, 360)
    set angle1 = ModuloReal(angle1, 360)
    set angle2 = ModuloReal(angle2, 360)
    if (angle1 > angle2) then
        set x = angle1
        set angle1 = angle2
        set angle2 = x
    endif
    if (angle2 - angle1) > (angle1 - (angle2-360)) then
        set angle2 = angle2 - 360
        if angle > 180 then
            set angle = angle-360
        endif
        return angle >= angle2 and angle <= angle1
    endif
    return (angle >= angle1) and (angle <= angle2)
endfunction
Есть вложенный пример карты с дебагом - E2
ссылка
4) Найти угол с помощью скалярного произведения векторов (то о чем говорил Doc)
Мне было сложно понять краткий пример дока. Пообщавшись с ним, он дам мне подсказку. Еще помог хабр разобраться с векторами
Сделал собственный вариант на jass,чтобы было понятно
код
function Trig_CW_Cast_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A000' ) 
endfunction



function TZZ takes nothing returns boolean
local real x1 = GetUnitX(udg_Caster) //координаты кастера
local real y1 = GetUnitY(udg_Caster)
local real from = 600//точнее отклонение от позиции кастера, нужна для точки взгляда.
local real a = GetUnitFacing(udg_Caster) //угол поворота юнита

local real x3 = GetUnitX(GetFilterUnit()) //координаты выбранного юнита
local real y3 = GetUnitY(GetFilterUnit())


//вычисляем координаты (x2,y2) направления D (вгляд героя, можно сказать вгзляд вперед под 90 градусам)
local real x2 = x1 + from * Cos(a * bj_DEGTORAD) 
local real y2 = y1 + from * Sin(a * bj_DEGTORAD)
//координаты направления V (от героя к выбранному юниту)
local real dx = x3 - x1 
local real dy = y3 - y1

local real X = dx * x2 //вектора DV на оси x
local real Y = dy * y2 //вектора Dv на оси y
local real d1 = SquareRoot(dx*dx + dy*dy) //модуль вектора V
local real d2 = SquareRoot(x2*x2 + y2*y2) //модуль вектора D

//косинус угла между векторами можно вычислить таким способом
local real A = (X+Y)/(d1*d2) 
local real Cosinus = Cos(A) //Cosinus - это совсем не нужная переменная и вычисления. Просто было интересно как ведет себя косинус.
local real theta = Acos(A)* bj_RADTODEG

local real width = 90 // угол обзора героя будет равен width градусам. Примерно расставляем какой угол будет в градусах
local real angle = width/2 //Половина ширины обзора, от середины, точнее от угла поворота героя. 
//ВНИМАНИЕ: ЭТО ОЧЕНЬ ВАЖНО. Если угол более angle градусов (половина от угла обзора), то выбранный юнит находится вне поля зрения героя.
//мануал - https://habrahabr.ru/post/131931/




if udg_Caster!= GetFilterUnit() then
call BJDebugMsg("Аргумент (значение) для функции Cos, и Acos - угол в градусах между направлениями вгляда и от кастера к выбранному: "+ R2S(A))
call BJDebugMsg("Cos (угол в градусах, всегда равен единичке): "+ R2S(Cosinus))
call BJDebugMsg("Cos (угол в радианах, всегда равен Пи/180*k): "+ R2S(Cosinus* bj_DEGTORAD))
call BJDebugMsg("ACos (угол theta в градусах): "+ R2S(theta))
call BJDebugMsg("угол angle (угол theta должен быть меньше этого значения): "+ R2S(angle))
endif

return false
endfunction


function Trig_CW_Cast_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x1 = GetUnitX(u) //координаты кастера
local real y1 = GetUnitY(u)
local real from = 800
local real a = GetUnitFacing(u) //угол поворота юнита
local real S = 90 //Ширина угла
local real angle = S/2 //Половина ширины угла

    set udg_Angle = a
    set udg_Caster = u
    set udg_X = angle

call BJDebugMsg("Угол поворота при касте: "+ R2S(a))

call GroupEnumUnitsInRange(bj_lastCreatedGroup,x1,y1,from, Condition(function TZZ))
//call ForGroup( bj_lastCreatedGroup, function TZZ )
call GroupClear(bj_lastCreatedGroup)

endfunction

//===========================================================================
function InitTrig_Cast takes nothing returns nothing
    set gg_trg_Cast = CreateTrigger(  )
    set bj_lastCreatedGroup = CreateGroup()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Cast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Cast, Condition( function Trig_CW_Cast_Conditions ) )
    call TriggerAddAction( gg_trg_Cast, function Trig_CW_Cast_Actions )
endfunction
можете посмотреть пример карты - E3 и E6. Скажу прямо делал как было написано в хабре с подсказками Дока. Карта E3 - другой вариант, более легкий, то есть там нет аркосинуса, и нам не вычислить угол. Там учитывает ширину обзора 180 градусов, то есть сзади он не видит. Если в этой карте возвращает больше нуля, значит попал в обзор.
5) попадание в треугольник
Мы рассчитываем попал ли в треугольник
код
function Trig_CW_Cast_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A000' ) 
endfunction

//Площадь треугольника по координатам
function TriS takes real x1, real y1, real x2, real y2, real x3, real y3 returns real
    return RAbsBJ(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2))/2
endfunction

//Принадлежность точки (x;y) треугольнику (x1;y1);(x2;y2);(x3;y3).
function IsCoordsInTriangle takes real x, real y, real x1, real y1, real x2, real y2, real x3, real y3 returns boolean
    return R2I(TriS(x1, y1, x2, y2, x3, y3))==R2I(TriS(x1, y1, x2, y2, x, y)+TriS(x2, y2, x3, y3, x, y)+TriS(x1, y1, x3, y3, x, y))
endfunction

function AddLightningEx2 takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
local lightning lg = LoadLightningHandle(udg_Hash,id,1)

call DestroyLightning(lg)

call FlushChildHashtable(udg_Hash,id)

call DestroyTimer(t)
set t = null
set lg = null

endfunction

function AddLightningEx1 takes lightning lg returns nothing
local timer t = CreateTimer()
local integer id = GetHandleId(t)

call SaveLightningHandle(udg_Hash,id,1, lg)
call TimerStart(t,5,false, function AddLightningEx2)

set lg=null
set t =null

endfunction


function TZZ takes nothing returns boolean
local real x1 = GetUnitX(udg_Caster) //координаты кастера, будет одной из точек треугольника
local real y1 = GetUnitY(udg_Caster)
local real from = 600//точнее отклонение от позиции кастера, нужна для точки взгляда.

local real a = GetUnitFacing(udg_Caster) //угол поворота юнита
local real width = 90 // угол обзора героя будет равен width градусам. Примерно расставляем какой угол будет в градусах
local real angle = width/2 //Половина ширины обзора, от середины, точнее от угла поворота героя. 

//диапазон обзора героя от Amin до Amax
local real Amin = a - angle
local real Amax = a + angle

//определяем две оставшиеся крайние точки тругольника
local real x2 = x1 + from * Cos(Amin * bj_DEGTORAD) 
local real y2 = y1 + from * Sin(Amin * bj_DEGTORAD)
local real x3 = x1 + from * Cos(Amax * bj_DEGTORAD) 
local real y3 = y1 + from * Sin(Amax * bj_DEGTORAD)

local real x = GetUnitX(GetFilterUnit()) //координаты выбранного юнита
local real y = GetUnitY(GetFilterUnit())

//это молнии нужны для видимости границ треугольника, типа попала ли в треугольник. Так они вообще не нужны
set bj_lastCreatedLightning = AddLightningEx("CLPB", true, x1, y1, 0., x2, y2, 0.)
call AddLightningEx1(bj_lastCreatedLightning)
set bj_lastCreatedLightning = AddLightningEx("CLPB", true, x1, y1, 0., x3, y3, 0.)
call AddLightningEx1(bj_lastCreatedLightning)
set bj_lastCreatedLightning = AddLightningEx("CLPB", true, x2, y2, 0., x3, y3, 0.)
call AddLightningEx1(bj_lastCreatedLightning)


call BJDebugMsg("Угол а: "+ R2S(a))
if IsCoordsInTriangle(x,y,x1,y1,x2,y2,x3,y3) and udg_Caster!= GetFilterUnit() then
call BJDebugMsg("точка выбранного юнита лежит в треугольнике")
endif

return false
endfunction


function Trig_CW_Cast_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x1 = GetUnitX(u) //координаты кастера
local real y1 = GetUnitY(u)
local real from = 800
local real a = GetUnitFacing(u) //угол поворота юнита
local real S = 90 //Ширина угла
local real angle = S/2 //Половина ширины угла

    set udg_Angle = a
    set udg_Caster = u
    set udg_X = angle

call BJDebugMsg("Угол поворота при касте: "+ R2S(a))

call GroupEnumUnitsInRange(bj_lastCreatedGroup,x1,y1,from, Condition(function TZZ))
//call ForGroup( bj_lastCreatedGroup, function TZZ )
call GroupClear(bj_lastCreatedGroup)

endfunction

//===========================================================================
function InitTrig_Cast takes nothing returns nothing
    set gg_trg_Cast = CreateTrigger(  )
    set bj_lastCreatedGroup = CreateGroup()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Cast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Cast, Condition( function Trig_CW_Cast_Conditions ) )
    call TriggerAddAction( gg_trg_Cast, function Trig_CW_Cast_Actions )
endfunction
пример можно посмотреть в карте E7
ссылка на формулу
о
Загруженные файлы
27

» WarCraft 3 / Как перенести счётчик объектов на другую карту?

Alexey103, проверка карты работает. Просто надо привыкнуть. Бывают окна с ошибками выскакивают, при чем не понятные (не нравится JassHepperу, видимо, как пишу. Синтаксис не нрав ему). Проверяешь ошибок никаких нет, но JassHepper тебе показывает на строки. но я на них болт кладу. Карта сохранилась, не понятно пока что. Но пробую запустить, нажимаешь "Тест" (красная галочка), и запускается норм. А бывает и нет, поэтому нужно присмотреться и поискать (ошибки быстро находятся - это уже опыт). Но существенные найдет.
27

» WarCraft 3 / Как перенести счётчик объектов на другую карту?

скинул карту, в ней без jngp. Короче только переменную HandleBoard не забудьте в редакторе переменных создать
27

» WarCraft 3 / Как перенести счётчик объектов на другую карту?

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