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

Добавлен
Мне нужно чтобы юнит при входе в зону направлялся к ближайшему зданию. Вот что я пытался но не вышло.
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 например)
Создаешь глобального юнита (если я не ошибаюсь, то здание является юнитом)
Ты выбираешь триггером все здания в округе
Для каждого выбранного здания ты считаешь дистанцию и записываешь в локальную переменную.
Если значение локальной переменной меньше глобальной ( в первый раз оно однозначно будет меньше), то мы:
Записываем значение локалки в глобалку
Выбранное здание записываем в глобального юнита.
Иначе ничего не делаем.
Таким образом триггер моментально переберет все здания в округе, оценит их положение и ближайшее здание запишет в глобального юнита.
Затем ты просто посылаешь вошедшего юнита к этой глобалке.
В конце нужно глобальной целочисленной обратно вернуть большое значение.
Если тебе не нравятся глобалки, то ты можешь использовать хэш, не буду долбать себе мозги.
0
20
11 лет назад
Отредактирован Diaboliko
0
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' разве вернет любого здания & юнита?
Очевидный момент- триггер изначально выключен. Не думаю что это было упущено.
0
17
11 лет назад
0
Diaboliko, да триггер изначально выключен, это нормально так как включение триггера происходит другим тригером. убал чтобы вас это не беспокоило.
так же у меня к вам вопросы:
  1. Какой я задал вопрос?
  2. как переводиться SomeBuilding и SomeUnit.
  3. На какой вопрос вы отвечаете?
0
20
11 лет назад
0
Вопроса задано не было.
Я пытаюсь ответить на вопрос "Почему не работает триггер"
ЛюбоеЗдание и ЛюбойЮнит. Но следуя логике это не вернет необходимого. Либо давайте код как есть, либо IsUnitType(....) or ... т.е. заменять кучу текста троеточием, например.
Ответ был дан исчерпывающий, разве нет?
0
17
11 лет назад
0
Diaboliko, вопрос в шапке, надень очки.
0
20
11 лет назад
0
Даже если так, не заметил его спустя 5.5 часов после 1го ответа. Что конкретно из
Diaboliko:
Область видимости переменной u не позволяет работать с ней так, как вам хочется. Следует заменить глобалкой.
не ясно? Вы используете локальную переменную внутри ForGroup. При том очень криво. При выборе каждого юнита у вас будет создаваться переменная u с адресом NULL. Даже если убрать аннулирование- ничего не изменится.
0
17
11 лет назад
0
Diaboliko, будемс разжевывать:
я задал вопрос "Как на джассе найти самого близкого юнита?"
Предоставил пример со своми мытарствами.
Да я знаю что триггер не работает я пробовал и сглобальными и с локальными.
в моем примере юнит входит в зону, и отправляется к ближайшему зданию.
Дубль 2 - Как найти ближайшее здание?
Ответы почему не работает тригер не предлагать.
1
20
11 лет назад
Отредактирован Diaboliko
1
В переменной с плавающей запятой 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
0
17
11 лет назад
0
я так понимаю из кода что set X2=SquareRoot(X2*X2+Y2*Y2) это ты в квадрате берешь всех юнитов?
1
20
11 лет назад
Отредактирован Diaboliko
1
Чем ждать ответа попробуй вникнуть в код?
X2=SquareRoot(X2*X2+Y2*Y2) присваивает переменной X2 значение расстояния между юнитом U и текущим юнитом, обрабатываемым ForGroup.
Бегло пробежался по коду- ошибок у себя не вижу. Могу потратить еще время, мне не шибко то жалко, но говори конкретнее что не ясно? Могу оформить с использованием #define, будет понятнее. Но, на мой взгляд, тут и так все норм.
3
22
11 лет назад
Отредактирован Стратег
3
Я не буду писать на джассе, просто скажу идею:
Создаешь глобальную целочисленную, присвоив ей какое-нибудь крупное значение (10000 например)
Создаешь глобального юнита (если я не ошибаюсь, то здание является юнитом)
Ты выбираешь триггером все здания в округе
Для каждого выбранного здания ты считаешь дистанцию и записываешь в локальную переменную.
Если значение локальной переменной меньше глобальной ( в первый раз оно однозначно будет меньше), то мы:
Записываем значение локалки в глобалку
Выбранное здание записываем в глобального юнита.
Иначе ничего не делаем.
Таким образом триггер моментально переберет все здания в округе, оценит их положение и ближайшее здание запишет в глобального юнита.
Затем ты просто посылаешь вошедшего юнита к этой глобалке.
В конце нужно глобальной целочисленной обратно вернуть большое значение.
Если тебе не нравятся глобалки, то ты можешь использовать хэш, не буду долбать себе мозги.
Принятый ответ
0
28
11 лет назад
0
зачем хэш зачем глобалка можно всё в локалку
и зачем здание создавать
короче держи
интересно sergant1000 читает ответы на этот вопрос или он забил?
Загруженные файлы
0
22
11 лет назад
0
возможно, глобалки и хэш не нужен, просто структура кода пока не держится в голове)
0
28
11 лет назад
0
я скинул пример там глобалка только для примера используется
Чтобы оставить комментарий, пожалуйста, войдите на сайт.