Нужно определить юнит-алтарь, который в данный момент воскрешает героя?
Нужно решить для ситуации множества алтарей и возможности воскрешения нескольких героев с одинаковым типом ид.
Думал можно отловить ордер - но ордера воскрешения вообще нет.
Как и не обнаружил нативной функции, что вернула бы алтарь - формально герой воскрешает сам себя, даже до завершения воскрешения остаётся лежать где помер.
Можно, конечно, перебрать все алтари игрока - но как определить нужный, который воскрешает конкретного героя в конкретном месте?
По сути аналогичный вопрос про строительство - как определить рабочего-строителя, что строит здание?
Как находясь внутри здания (как у орков) и вне здания (как у альянса)? У ночных эльфов ещё есть выращивание древ с потерей рабочего (но если отменить до завершения - то рабочий возвращается - значит, до этого момента он ещё существует, как его найти)
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
10
9 месяцев назад
0
При воскрешении героя искать ближайший к нему алтарь. Я бы сделал так (если действительно нет вариантов сделать нормально)
0
6
9 месяцев назад
0
  1. Делать триггерное воскрешение.
  2. Как вариант добавлять абилку при начале строительства, но с отменой и завершением удалять.
С помощью этой абилки и проверять.
Можно определить триггерами, только кто начал строить или закончил, если не ошибаюсь.
Или же делать свою триггерное строительство.
0
29
9 месяцев назад
0
Думал можно отловить ордер - но ордера воскрешения вообще нет.
Насколько я помню, алтарю будет отдан приказ с равкодом героя.
По идее, можно отлавливать приказы и писать в хт состояния юнитов.
0
5
9 месяцев назад
Отредактирован Darklight
0
Slonick, как написал - алатрей может быть много. Нужно достоверное определение
Darkmen500,
1. Делать триггерное воскрешение - над этим можно подумать, хотя чувствую, что очень геморно это и цель не оправдает средства - это надо делать свою абилку алтаря для каждого героя (добавляя её всем алтарям по событию "EVENT_PLAYER_HERO_REVIVABLE" и убирая по событию "EVENT_PLAYER_HERO_REVIVE_START" и возвращать по событию "EVENT_PLAYER_HERO_REVIVE_CANCEL" - но тогда придётся ещё как-то эмулировать сам процесс воскрешения - начиная от правильного определения ресурсов и времени (причём в подсказке текстом это заранее не показать) и до полосы прогресса (стандартный не сделать) и обработки отмены.
Хотя нет, события "EVENT_PLAYER_HERO_REVIVE_*" не подойдут – если эмулировать сам процесс воскрешения (их не будет), да и обрабатывать нужно именно события самой аблики (ведь именно событие абилки будет на алтаре).
Выполнить процесс воскрешение на подставном алтаре видимо тоже не получится – такой команды (и нативной функции), судя по всему, просто нет. А функция ReviveHero воскрешает немедленно!
2. Как вариант добавлять абилку при начале строительства, но с отменой и завершением удалять - вот тут не понял о чём речь. Причём здесь строительство? Герой как и алтарь могут вообще быть на карте не от строительства.
nazarpunk, "Насколько я помню, алтарю будет отдан приказ с равкодом героя" - только при найме, при воскрешении нет приказа :-( Есть события - но все он от героя, который остаётся даже лежать где пал, а не переносится к алтарю (собственно первым делом и хотелось бы сделать этот самый перенос горя к алтарю)
Вот мом размышления "на свежую голову":
Найти алтарь, выполняющий воскрешение, наверное, не большая проблема - достаточно пройтись по всем живым алтарям, программно добавить им дамми-абилку и попробовать дать ей команду - думаю, что занятый алтарь не выполнит команду - это можно отследить (но не факт, что не выполнит); останется отфильтровать только алтари, занятые процессом найма (но это как раз отслеживается по команде найма).
Проблема в том, что если будет несколько алтарей, одновременно воскрешающих героя - то как определить нужный?
Но, думаю это тоже решаемо - алтари же не начинают этот процесс одновременно - всё-равно сначала начнёт один, затем начнёт второй и т.д.
Поэтому надо отслеживать, указанным мною способом, алтарь, который только что начал воскрешение, и помечать его занятым, при следующей "команде" на воскрешение исключать его до завершения воскрешения.
Остаётся понять какого героя алтарь начал воскрешать (если мёртвых было несколько)?
Но это уже по событию "EVENT_PLAYER_HERO_REVIVE_START" определить можно (отмену тоже надо отслеживать) - собственно с него и надо начинать - сразу получаем героя, ищем занятный (но ещё не обработанный/связанный с другим героем - воскрешаемым или нанимаемым) алтарь через дамми-абилку, вуа-ля - нашли нужный алтарь - связали его с нужным героем. По событиям "EVENT_PLAYER_HERO_REVIVE_CANCEL" и "EVENT_PLAYER_HERO_REVIVE_FINISH" освобождаем связь алтаря и героя (находя её по герою).
Осталось проверить сработает ли приказ дамми-абилки на занятом воскрешением алтаре - какую лучше абилку для этого взять, посоветуете?
Ну и система обработки событий сразу двух триггеров параллельно выходит не очень простая (события от героя и от дамми-аблики, что нужно совместить с одним набором данных)
0
10
9 месяцев назад
0
Darklight, Алтарей может быть много, но ближайший к воскрешенному герою - один
0
29
9 месяцев назад
0
Darklight, Алтарей может быть много, но ближайший к воскрешенному герою - один
А как ты определишь случай, когда этот алтарь застроен, и героя бросило к другому алтарю?
0
5
9 месяцев назад
Отредактирован Darklight
0
Вы вообще о чём? Героя никуда не перебрасывает до момента окончания воскрешения.
Вот пришёл в голову более простой вариант (для интерактивной работы, с программной всё прозрачнее и там таких проблем нет):
Второй вариант. Определять текущий алтарь через выбранный пользователем (по событию "EVENT_PLAYER_HERO_REVIVE_START")
//На самом деле этот метод фильтра не нужен - без него ничего не изменится (в группе априори будет один нужный алтарь... ну не совсем, но фильтр ничего не изменит)
fucntion FindAltarCond takes nothing returns boolean
	return (GetUnitTypeId(GetFilterUnit())=='t321' and IsUnitAliveBJ(GetFilterUnit()))
endfucntion
fucntion FindAltar takes player p returns Unit
        local group g
        local unit u
        
            set g = CreateGroup()
            call SyncSelections()
            call GroupEnumUnitsSelected(g, p, Filter(function FindAltarCond))
            set u = FirstOfGroup(g)
            if (u != null) then
                call BJDebugMsg("Reviving altar "+GetUnitName(u))
            endif
            call DestroyGroup(g)
            set g = null
            return u
endfucntion
Но.... увы... это оказалось плохой идеей - ведь герои могут стоять в очереди и к моменту очереди воскрешения очередного героя алтарь нужный скорее всего не будет выбран :-(
Так что пока остаётся первый вариант с дамми-абилкой (ниже текущая предварительная версия), да и есть проблема с событием "EVENT_PLAYER_HERO_REVIVE_CANCEL" - кажется не срабатывает при отмене воскрешения по клику на иконку исключения из очереди (текущего обрабатываемого элемента)
Сделал на одном триггере (по событию "EVENT_PLAYER_HERO_REVIVE_START") с небольшим ожиданием обработки команды
Открыть
static method FindAltar takes player p, integer state returns Unit
        local integer aid = 't321'
        local group g
        local group g2
        local unit u
        local string comName
		local boolean ok = false	
            set g2 = GetUnitsOfPlayerAndTypeId(p, aid)
            set g = CreateGroup()
            loop
                set u = FirstOfGroup(g2)
                exitwhen (u==null)
                call GroupRemoveUnit(g2, u)
                if (IsUnitAliveBJ(u) and IsNotBusy(u)) then //IsNotBasy - некая кастомная функция проверки  пометки, что алтарь ранее уже был занят
                    set comName = GetLastCommand(u) //Некая кастомная функция, получающая последнюю сохранённую команду 
                        if (comName=="roar") then
                            debug BJDebugMsg("FLUSH "+GetUnitName(u)
                            call FlushOrder(u) //Некая кастомная функция очистки последний сохранённой команды
                        endif
                        call GroupAddUnit(g, u)
                endif
            endloop
            loop
                set u = FirstOfGroup(g)
                exitwhen (u==null)
                call GroupRemoveUnit(g, u)
                if (IsUnitAliveBJ(u) and IsNotBusy(u)) then
                            debug BJDebugMsg("ROAR "+GetUnitName(u))
                            call IssueImmediateOrder(u,"roar")
                            call GroupAddUnit(g2, u)
                endif
            endloop
            call DestroyGroup(g)
            call TriggerSleepAction(0.2)
            loop
                set u = FirstOfGroup(g2)
                exitwhen (u==null)
                call GroupRemoveUnit(g2, u)
                if (IsUnitAliveBJ(u)) then
                		set comName = GetLastCommand(u) //Некая кастомная функция, получающая последнюю сохранённую команду 
                            if (comName=="roar") then
                                call BJDebugMsg("ROAR COMPLETED")
                                call FlushOrder(u) 
                            else
                                call BJDebugMsg("Reviving altar "+GetUnitName(u))
								set ok = true
                            endif
                     endif
                exitwhen (ok==true)
            endloop
            call DestroyGroup(g2)
            set g = null
            set g2 = null
			call  MarkBusy(u) //u - алтарь надо ещё пометить как теперь уже занятый
            return u
        endmethod
Все доп данные можно хранить в hashtable с привязкой по юниту (этот код опускаю - у меня более сложная система хранения доп данных по юниту со структурами на vJass - а в хештаблицах только привязка юнитов к индексам структур vJass)
Чтобы оставить комментарий, пожалуйста, войдите на сайт.