как найти самого близкого юнита

Добавлен
Мне нужно чтобы юнит при входе в зону направлялся к ближайшему зданию. Вот что я пытался но не вышло.
function Trig_SomeFunc_Conditions takes nothing returns boolean
    return ( GetUnitTypeId(GetTriggerUnit()) == 'SomeUnit' )
endfunction

function Trig_SomeFunc_H takes nothing returns nothing
    local unit f = GetEnumUnit()
    local unit u = null
    if ( R2I(DistanceBetweenPoints(GetUnitLoc(GetTriggerUnit()), GetUnitLoc(f))) <= R2I(DistanceBetweenPoints(GetUnitLoc(GetTriggerUnit()), GetUnitLoc(u))) ) then
        set u = f
    endif
    call IssuePointOrderLoc(GetTriggerUnit(), "move", GetUnitLoc(u))
endfunction

function Trig_SomeFunc_Actions takes nothing returns nothing
    call ForGroupBJ( GetUnitsOfPlayerAndTypeId(GetOwningPlayer(GetTriggerUnit()), 'SomeBuilding'), function Trig_SomeFunc_H )
endfunction
//===============================================
function InitTrig_SomeFunc takes nothing returns nothing
    set gg_trg_SomeFunc = CreateTrigger(  )
    call TriggerRegisterEnterRectSimple( gg_trg_SomeFunc, gg_rct_SomeLocation )
    call TriggerAddCondition( gg_trg_SomeFunc, Condition( function Trig_SomeFunc_Conditions ) )
    call TriggerAddAction( gg_trg_SomeFunc, function Trig_SomeFunc_Actions )
endfunction

Я не буду писать на джассе, просто скажу идею:
Создаешь глобальную целочисленную, присвоив ей какое-нибудь крупное значение (10000 например)
Создаешь глобального юнита (если я не ошибаюсь, то здание является юнитом)
Ты выбираешь триггером все здания в округе
Для каждого выбранного здания ты считаешь дистанцию и записываешь в локальную переменную.
Если значение локальной переменной меньше глобальной ( в первый раз оно однозначно будет меньше), то мы:
Записываем значение локалки в глобалку
Выбранное здание записываем в глобального юнита.
Иначе ничего не делаем.
Таким образом триггер моментально переберет все здания в округе, оценит их положение и ближайшее здание запишет в глобального юнита.
Затем ты просто посылаешь вошедшего юнита к этой глобалке.
В конце нужно глобальной целочисленной обратно вернуть большое значение.
Если тебе не нравятся глобалки, то ты можешь использовать хэш, не буду долбать себе мозги.
`
ОЖИДАНИЕ РЕКЛАМЫ...
20
function Trig_SomeFunc_H takes nothing returns nothing
local unit f = GetEnumUnit()
local unit u = null
if ( R2I(DistanceBetweenPoints(GetUnitLoc(GetTriggerUnit()), GetUnitLoc(f))) <= R2I(DistanceBetweenPoints(GetUnitLoc(GetTriggerUnit()), GetUnitLoc(u))) ) then
set u = f
endif
call IssuePointOrderLoc(GetTriggerUnit(), "move", GetUnitLoc(u))
endfunction
Область видимости переменной u не позволяет работать с ней так, как вам хочется. Следует заменить глобалкой. Ну и оптимизировать есть что, например
if ( R2I(DistanceBetweenPoints(GetUnitLoc(GetTriggerUnit()), GetUnitLoc(f))) <= R2I(DistanceBetweenPoints(GetUnitLoc(GetTriggerUnit()), GetUnitLoc(u))) ) then
Будет производить лишнее вычисление(скорее всего), поэтому кратчайшую дистанцию следует присваивать глобалке. +работа с локациями намного медленнее чем с просто X,Y
Да и 'SomeBuilding' & 'SomeUnit' разве вернет любого здания & юнита?
Очевидный момент- триггер изначально выключен. Не думаю что это было упущено.
17
Diaboliko, да триггер изначально выключен, это нормально так как включение триггера происходит другим тригером. убал чтобы вас это не беспокоило.
так же у меня к вам вопросы:
  1. Какой я задал вопрос?
  2. как переводиться SomeBuilding и SomeUnit.
  3. На какой вопрос вы отвечаете?
20
Вопроса задано не было.
Я пытаюсь ответить на вопрос "Почему не работает триггер"
ЛюбоеЗдание и ЛюбойЮнит. Но следуя логике это не вернет необходимого. Либо давайте код как есть, либо IsUnitType(....) or ... т.е. заменять кучу текста троеточием, например.
Ответ был дан исчерпывающий, разве нет?
20
Даже если так, не заметил его спустя 5.5 часов после 1го ответа. Что конкретно из
Diaboliko:
Область видимости переменной u не позволяет работать с ней так, как вам хочется. Следует заменить глобалкой.
не ясно? Вы используете локальную переменную внутри ForGroup. При том очень криво. При выборе каждого юнита у вас будет создаваться переменная u с адресом NULL. Даже если убрать аннулирование- ничего не изменится.
17
Diaboliko, будемс разжевывать:
я задал вопрос "Как на джассе найти самого близкого юнита?"
Предоставил пример со своми мытарствами.
Да я знаю что триггер не работает я пробовал и сглобальными и с локальными.
в моем примере юнит входит в зону, и отправляется к ближайшему зданию.
Дубль 2 - Как найти ближайшее здание?
Ответы почему не работает тригер не предлагать.
20
В переменной с плавающей запятой R содержится дистанция от ближайшего юнита U3 до нашего U.
В локальной группе G все юниты-здания(ну или какие-либо еще, удовлетворяющие вашим условиям)
Тогда для каждого юнита из группы G:
Если юнит ближе предыдущего, он становится ближайшим.
Итого имеем нечто вроде:
Ближайший юнит находится сравнением расстояний, кэп. Дабы не возникал- вот тебе код(примерный).
globals
unit U
unit U2
unit U3
real R
real X
real Y
real X2
real Y2
endglobals

function BuildingFilter takes nothing returns boolean
set U2=GetFilteredUnit()
return IsUnitType(U2,UNIT_TYPE_BUILDING) and U!=U2
endfunction

function ActionOfTrigger2 takes nothing returns nothing
set U2=GetEnumUnit()
set X2=X-GetUnitX(U2)
set Y2=Y-GetUnitY(U2)
set X2=SquareRoot(X2*X2+Y2*Y2)
if X2<R then
set U3=U2
set R=X2
endif
endfunction

function ActionOfTrigger takes nothing returns nothing
local group G=CreateGroup()//Глобалка не подходит ибо довольно долго будут осуществляться операции с ней. С другой стороны почему бы и нет? Но это уже твоя забота.
set U=Юнит-константа
set X=GetUnitX(U)
set Y=GetUnitY(U)
call GroupEnumUnitsInRect(G,РЕГИОН ВЫБОРА,Condition(function Filter))//По логике: выделение по региону быстрее
set U3=FirstOfGroup(G)
set X2=X-GetUnitX(U3)
set Y2=Y-GetUnitY(U3)
set R=SquareRoot(X2*X2+Y2*Y2)
call GroupRemoveUnit(G,U3)
call ForGroup(G,function ActionOfTrigger2)
//Итого U3- ближайший юнит
endfunction
17
я так понимаю из кода что set X2=SquareRoot(X2*X2+Y2*Y2) это ты в квадрате берешь всех юнитов?
20
Чем ждать ответа попробуй вникнуть в код?
X2=SquareRoot(X2*X2+Y2*Y2) присваивает переменной X2 значение расстояния между юнитом U и текущим юнитом, обрабатываемым ForGroup.
Бегло пробежался по коду- ошибок у себя не вижу. Могу потратить еще время, мне не шибко то жалко, но говори конкретнее что не ясно? Могу оформить с использованием #define, будет понятнее. Но, на мой взгляд, тут и так все норм.
21
Я не буду писать на джассе, просто скажу идею:
Создаешь глобальную целочисленную, присвоив ей какое-нибудь крупное значение (10000 например)
Создаешь глобального юнита (если я не ошибаюсь, то здание является юнитом)
Ты выбираешь триггером все здания в округе
Для каждого выбранного здания ты считаешь дистанцию и записываешь в локальную переменную.
Если значение локальной переменной меньше глобальной ( в первый раз оно однозначно будет меньше), то мы:
Записываем значение локалки в глобалку
Выбранное здание записываем в глобального юнита.
Иначе ничего не делаем.
Таким образом триггер моментально переберет все здания в округе, оценит их положение и ближайшее здание запишет в глобального юнита.
Затем ты просто посылаешь вошедшего юнита к этой глобалке.
В конце нужно глобальной целочисленной обратно вернуть большое значение.
Если тебе не нравятся глобалки, то ты можешь использовать хэш, не буду долбать себе мозги.
Принятый ответ
28
зачем хэш зачем глобалка можно всё в локалку
и зачем здание создавать
короче держи
интересно sergant1000 читает ответы на этот вопрос или он забил?
Загруженные файлы
21
возможно, глобалки и хэш не нужен, просто структура кода пока не держится в голове)
28
я скинул пример там глобалка только для примера используется
Чтобы оставить комментарий, пожалуйста, войдите на сайт.