Добавлен
Всем привет ребят. Помогите пожалуйста, хочу сделать ИИ для отдельных юнитов. Карта на 12 человек, но чаще всего я играю с друзьями и нас 2-4 человека, а остальные тупо стоят. Получается 12 героев из них только 2-4 человека, я хочу на каждого героя кинуть ИИ, что бы они сами все делали.
По сути мне надо примерно так.
Уход при низком HP (инвиз + отступление)
Патруль по точкам
Атака врагов поблизости с кастом умений
Подбор предметов
Атака боссов по таймеру
Включение AI только если игрок — компьютер
Отключение по таймеру
Ищу и сам пытался сделать, максимум что могу тупо патрулирование по местности и комп просто атакует и дохнет и по новой. Хочу что бы был чуток умнее. Через ИИ эдитор не получается, шляпа там вообще какая-то.
`
ОЖИДАНИЕ РЕКЛАМЫ...
23
Похожие вопросы:

ответ
Щас бы в 2018 делать Melee карты)))))
В гуи сделай обычный ИИ (если карта не совсем стандартная)
А ещё лучше: xgm.guru/p/wc3/aieditor
ответ
Пока для тестирования оставил вариант с маленькой атакой, так как для нее не требуется писать дополнительных скриптов. Я не знаю, как работают функции отбора групп (отрядов) по условиям и как это оптимизировано внутри игры, но есть подозрение, что если в таймере выбирать все стенки на карте и потом искать боевые единицы врага вокруг каждой из них, это может быть долго. Для такого варианта хорошо кэшировать стены при постройке, но я на время тестирования не стал над этим заморачиваться. Всем спасибо за помощь.
ответ
После применения способности, игра просто доходит до ожидания, вызывает его и все. Можно ждать бесконечно, остальной код не будет исполнен.
TriggerSleepAction нельзя вызвать в кондишенах, только в действиях. Либо юзай экзекют, либо не юзай вейт

Результат тот же, до кода, следующего после цикла, исполнение не доходит.
Ты таким образом себе оп лимит сломал, ведь в первую же долю секунды цикл обрабатывает 25к+ действий

Дредлорда как колбасило при касте, так и колбасит, анимацию он отказывается адекватно
Таймером создаёшь нулевую задержку, устанавливаешь нужную анимацию, а дальше уже либо периодиком проверяешь приказ и отменяешь анимацию, либо через время просто отменяешь анимацию. Это основы гуи, не то что джасс)

вот так решается первый вариант
function InitTrig_Annihilation_Conditions takes nothing returns boolean
    if (GetUnitAbilityLevel(GetSpellAbilityUnit(), udg_Annihilation) > 0) then
        call ExecuteFunc( "AnnihilationActions" )
    endif

    return false
endfunction
и так второй
function ExecuteCast takes nothing returns nothing
    local timer spellDurationTimer = GetExpiredTimer()
    local integer timerHandle = GetHandleId(spellDurationTimer)
    local unit target = LoadUnitHandle(udg_Hash, timerHandle, 0)
    local unit caster = LoadUnitHandle(udg_Hash, timerHandle, 1)

    call ResetUnitAnimation(caster)
    call SetUnitExploded(target, true)
    call KillUnit(target)
    call DestroyTimer(spellDurationTimer)
    set spellDurationTimer = null
endfunction

function SetAnim takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    
    call SetUnitAnimation( LoadUnitHandle( H, GetHandleId( t ), 1 ), "channel" )
    call TimerStart(t, 5, false, function ExecuteCast)
    
    set t = null
endfunction

function AnnihilationActions takes nothing returns nothing
    local unit target = GetSpellTargetUnit()
    local unit caster = GetSpellAbilityUnit()
    local timer spellDurationTimer = CreateTimer()
    local integer timerHandle = GetHandleId(spellDurationTimer)

    call SaveUnitHandle(udg_Hash, timerHandle, 0, target)
    call SaveUnitHandle(udg_Hash, timerHandle, 1, caster)
    call SetUnitAnimationByIndex(caster, 11)
    call SetUnitZ(target, 400)
    
	call TimerStart(spellDurationTimer, 0.00, false, function SetAnim)
	
    set target = null
    set caster = null
    set spellDurationTimer = null
endfunction

8
Так в чем проблема самому написать ИИ? Каждую секунду перебираешь нужных героев
  1. если хп мало, то вычисляешь угол между героем и врагом и отправляешь героя в противоположную сторону.
  2. патруль не понял что это
  3. перебираешь юнитов вокруг героя, проверяешь что враг и приказываешь кастануть спелл.
  4. перебираешь вокруг предметы, настраиваешь фильтр как тебе угодно -> приказываем поднять шмот.
  5. боссы какие то по ситуации надо смотреть, я не понял
  6. ставишь в проверку -> контроллер игрока == комп
Если мазохист, то можно и на гуи такое написать
11
Патруль - это когда ходит юнит туда сюда и атакует всех вражеских на пути.
Объявляешь таймер local timer vTimer, создаёшь таймер set vTimer = CreateTimer(), уничтожаешь потом таймер call DestroyTimer(vTimer), запускаешь таймер call TimerStart(vTimer,1,function fMyFunction). В войдоской функции fMyFunction пишешь цикл по всем игрокам и их героям. Если юнита создавал через jass, то должны сохраниться id юнитов set vHero1 = CreateUnit(Player(10),ID_HERO_1,0,0,0), объявлять юнита следующим образом local unit vHero1. Если через редактор вставлял юнитов, то они как не странно будут в jass, но id юнитов не сохраняться, если сам не подправишь код. Если хочешь искать юнитов то тебе нужен перебиратор юнитов в группе.
Вот пример:
function fGetUnit takes integer vId, player vPlayer returns unit
	local group g=CreateGroup()
	local unit u;
	call GroupEnumUnitsOfPlayer(g,vPlayer,0);
	loop
		set u=FirstOfGroup(g)
		if (GetUnitTypeId(u)==vId) then
			call DestroyGroup(g)
			return u
		endif
		call GroupRemoveUnit(g,u)
	endloop
	call DestroyGroup(g)
	return 0
endfunction
Углы искать между юнитами тебе нужно поучить тригонометрию, а в особенности sin и cos что будет расстояние между двумя точками x1, y1, x2, y2. А тебе нужен противоположенный угол и радиус на сколько убегать. Вообще интересно увидеть всё это в деле.
Если нужно перебирать в радиусе то вот вот функция GroupEnumUnitsInRange(group,x,y,radius,function filter можно 0) для перебирания.
Если вражеский бос id и rect совпадают то бос определён.
Цикл по игрокам компьютерам можешь имя сравнить local string vStr, set vPlayer = Player(0..11), set vStr = GetPlayerName(vPlayer). Может есть другой способ определить ИИ, я не знаю.
Приказ кастануть спелл на цель set vBool = IssueTargetOrderById(u,ID_ORDER,u2), просто нажать кнопку set vBool = IssueImmediateOrderById(u,ID_ORDER), в точку set vBool = IssuePointOrderById(u,ID_ORDER,x,y)
Юнитов лучше сохранять в хеш таблице, и брать данные из хеш-таблицы set vHT = InitHashtable()
call SaveInteger(vHT, parentKey, childKey, value)
set vInt = LoadInteger(vHT, parentKey, childKey)
set parentKey = GetExpiredTimer()
childKey = CONST_HERO_1

p.s. И если ты хочешь сделать сложного бота без дебагера, на jass, то это вряд ли у тебя получится. Так как тыкаться в jass коде без знания параметров каждой переменной это издевательство над собой. Да ещё и с таким опытом, который описан выше. Мапхак тебе в помощь. А если простой бот, так потренироваться по написанию jass кода, ну можно. Только это не серьезно.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.