XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Барахолка
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
NeutralAttackAI
Автор:Nerevar

NeutralAttackAI

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

Описание

Также в триггере есть показ текста,который описывает сколько нанёс определенный юнит,кого монстр идет атаковать,когда монст идёт в лагерь.Также настраиваемые параметры имеют комментарии(радиус возвращения,период сброса урона и т.д.).Используется для управления нейтрально-пассивным игроком(чтобы приказы адекватно отдавались),поэтому,если будете использовать у себя в карте,необходимо установить его как противника для всех игроков.Для обеспечения работы необходима глобальная переменная типа хэш-таблица с названием ah.Используется only jass.
Для удаления показа текста необходимо удалить все строки,отвечающие за их показ(начинающиеся с call DisplayText.В будущем планирую прикрутить засчитывание исцеления как урон(чтобы целителям жизнь сладкой не казалась=Ъ).
» Код
function IsUnitNearUnit takes unit u1,unit u2 returns boolean
local real x1=GetUnitX(u1)
local real y1=GetUnitY(u1)
local real x2=GetUnitX(u2)
local real y2=GetUnitY(u2)
local real distance=SquareRoot((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
local real MaxDistance=1200.//максимальное расстояние,
// на котором нейтрал будет "думать" что юнит находится рядом
    return distance<=MaxDistance
endfunction

function IsUnitInHome takes unit u returns boolean
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real tx=LoadReal(udg_ah,GetHandleId(u),StringHash("HomeX"))
local real ty=LoadReal(udg_ah,GetHandleId(u),StringHash("HomeY"))
local real distance=SquareRoot((tx - x) * (tx - x) + (ty - y) * (ty - y))
local real MaxDistance=1200.//максимальное расстояние,
// на котором нейтрал будет "думать" что он ещё возле своего лагеря
    return distance<MaxDistance
endfunction

function GetAggreUnit takes unit u,unit target,group gn returns unit
local unit f
local group g=CreateGroup()
local real agre
local real agre2
call GroupAddGroup(gn,g)
loop 
    set f=FirstOfGroup(g)
exitwhen f==null
    set agre=LoadReal(udg_ah,GetHandleId(u),GetHandleId(f))
    set agre2=LoadReal(udg_ah,GetHandleId(u),GetHandleId(target))
if agre>agre2 and IsUnitVisible(f,Player(PLAYER_NEUTRAL_PASSIVE)) and IsUnitNearUnit(f,u) and not IsUnitType(f,UNIT_TYPE_DEAD) and GetUnitState(f,UNIT_STATE_LIFE)>0.405  then
    set target=f
endif
    call DisplayTextToForce( GetPlayersAll(), GetUnitName(f)+ " agre is "+R2S(agre))
    call GroupRemoveUnit(g,f)
endloop
    call DestroyGroup(g)
set g=null
set f=null
return target
endfunction

function Trig_AttackTaken_Conditions takes nothing returns boolean
    return GetOwningPlayer(GetTriggerUnit()) == Player(PLAYER_NEUTRAL_PASSIVE)
endfunction

function GoHome_Remove takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)
local unit u=LoadUnitHandle(udg_ah,id,0)
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real tx=LoadReal(udg_ah,GetHandleId(u),StringHash("HomeX"))
local real ty=LoadReal(udg_ah,GetHandleId(u),StringHash("HomeY"))
local real distance=SquareRoot((tx - x) * (tx - x) + (ty - y) * (ty - y))
local trigger trg=LoadTriggerHandle(udg_ah,GetHandleId(u),StringHash("DamageTakenTrigger"))
local real HomeDistance=100.//расстояние,подойдя на которое к исходной позиции,нейтрал
// будет думать что в исходном лагере
if distance<=HomeDistance then
    call EnableTrigger(trg)
    call PauseTimer(t)
    call DestroyTimer(t)
    call FlushChildHashtable(udg_ah,id)
endif
set u=null
set t=null
set trg=null
endfunction

function Agre_Remove takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer id=GetHandleId(t)
local integer i1=LoadInteger(udg_ah,id,0)
local unit Attacker=LoadUnitHandle(udg_ah,id,1)
local real Damage=LoadReal(udg_ah,id,2)
local real DamageTaken=LoadReal(udg_ah,i1,GetHandleId(Attacker))-Damage
local group DamageGroup=LoadGroupHandle(udg_ah,i1,StringHash("DamagedNeutralGroup"))
if DamageTaken==0. then
    call GroupRemoveUnit(DamageGroup,Attacker)
    call SaveGroupHandle(udg_ah,i1,StringHash("DamagedNeutralGroup"),DamageGroup)
endif
    call SaveReal(udg_ah,i1,GetHandleId(Attacker),DamageTaken)
    call PauseTimer(t)
    call DestroyTimer(t)
    call FlushChildHashtable(udg_ah,id)
set DamageGroup=null
set t=null
set Attacker=null
endfunction

function Trig_DamageTaken_Conditions takes nothing returns boolean
local trigger DamageCheck=GetTriggeringTrigger()
local unit Damaged=LoadUnitHandle(udg_ah,GetHandleId(DamageCheck),0)
local integer DamagedId=GetHandleId(Damaged)
local unit Attacker=GetEventDamageSource()
local integer AttackerId=GetHandleId(Attacker)
local real Damage=GetEventDamage()
local group DamagedNeutralGroup=LoadGroupHandle(udg_ah,DamagedId,StringHash("DamagedNeutralGroup"))
local unit Target
local real DamageTaken=LoadReal(udg_ah,DamagedId,AttackerId)+Damage
local timer AgreRemoveTimer=CreateTimer()
local integer Timerid=GetHandleId(AgreRemoveTimer)
local timer GoHomeTimer
local integer GoHomeTimerId
local real AggreRemove=10.//время,через которое нанесенный нейтралу урон будет уменьшаться
call SaveReal(udg_ah,DamagedId,AttackerId,DamageTaken)
call DisplayTextToForce( GetPlayersAll(), "Damage is taken by "+GetUnitName(Attacker)+" is "+R2S(Damage))
call SaveInteger(udg_ah,Timerid,0,DamagedId)
call SaveUnitHandle(udg_ah,Timerid,1,Attacker)
call SaveReal(udg_ah,Timerid,2,Damage)
call SaveReal(udg_ah,Timerid,3,0.)
call TimerStart(AgreRemoveTimer,AggreRemove,false,function Agre_Remove)
if GetUnitState(Damaged,UNIT_STATE_LIFE)<0.405 and IsUnitType(Damaged,UNIT_TYPE_DEAD) or Damage>GetUnitState(Damaged,UNIT_STATE_LIFE) then
    call TriggerClearConditions(DamageCheck)
    call DestroyTrigger(DamageCheck)
    call FlushChildHashtable(udg_ah,DamagedId)
    call FlushChildHashtable(udg_ah,GetHandleId(DamageCheck))
endif
    set Target=GetAggreUnit(Damaged,Attacker,DamagedNeutralGroup)
if IsUnitInHome(Damaged) then
if Target!=null then
    call IssueTargetOrder(Damaged,"attack",Target)
    call DisplayTextToForce( GetPlayersAll(), "Go to attack a "+GetUnitName(Target))
elseif Target==null then
    call IssuePointOrder(Damaged,"move",LoadReal(udg_ah,DamagedId,StringHash("HomeX")),Lo​adReal(udg_ah,DamagedId,StringHash("HomeY")))
    call DisplayTextToForce( GetPlayersAll(), "Go home ")
    call DisableTrigger(DamageCheck)
    set GoHomeTimer=CreateTimer()
    set GoHomeTimerId=GetHandleId(GoHomeTimer)
    call SaveUnitHandle(udg_ah,GoHomeTimerId,0,Damaged)
    call TimerStart(GoHomeTimer,0.5,true,function GoHome_Remove)
endif
elseif not IsUnitInHome(Damaged) then
    call IssuePointOrder(Damaged,"move",LoadReal(udg_ah,DamagedId,StringHash("HomeX")),Lo​adReal(udg_ah,DamagedId,StringHash("HomeY")))
    call DisplayTextToForce( GetPlayersAll(), "Go home ")
    call DisableTrigger(DamageCheck)
    set GoHomeTimer=CreateTimer()
    set GoHomeTimerId=GetHandleId(GoHomeTimer)
    call SaveUnitHandle(udg_ah,GoHomeTimerId,0,Damaged)
    call TimerStart(GoHomeTimer,0.5,true,function GoHome_Remove)
endif
set GoHomeTimer=null
set AgreRemoveTimer=null
set Damaged=null
set Attacker=null
set DamagedNeutralGroup=null
set DamageCheck=null
return true
endfunction

function Trig_AttackTaken_Actions takes nothing returns nothing
local unit Damaged=GetTriggerUnit()
local integer DamagedId=GetHandleId(Damaged)
local unit Attacker=GetAttacker()
local group DamagedNeutralGroup=LoadGroupHandle(udg_ah,DamagedId,StringHash("DamagedNeutralGroup"))
local trigger DamageCheck
local real DamagedX=GetUnitX(Damaged)
local real DamagedY=GetUnitY(Damaged)
local real PeriodicAttack=1.//период,через который нейтрал будет находить
// цель для атаки,кроме тех случаев,когда нейтрал получает урон
if HaveSavedHandle(udg_ah,DamagedId,StringHash("DamagedNeutralGroup")) and not IsUnitInGroup(Attacker,DamagedNeutralGroup) then
    call GroupAddUnit(DamagedNeutralGroup,Attacker)
    call SaveGroupHandle(udg_ah,DamagedId,StringHash("DamagedNeutralGroup"),DamagedNeutralGroup)
elseif not HaveSavedHandle(udg_ah,DamagedId,StringHash("DamagedNeutralGroup")) then
    set DamagedNeutralGroup=CreateGroup()
    call GroupAddUnit(DamagedNeutralGroup,Attacker)
    call SaveGroupHandle(udg_ah,DamagedId,StringHash("DamagedNeutralGroup"),DamagedNeutralGroup)
    call DisplayTextToForce( GetPlayersAll(), "DamageGroup Is Create") 
if not HaveSavedHandle(udg_ah,DamagedId,StringHash("DamageTakenTrigger")) then
    set DamageCheck=CreateTrigger()
    call TriggerRegisterUnitEvent( DamageCheck, Damaged, EVENT_UNIT_DAMAGED )
    call TriggerRegisterTimerEvent(DamageCheck, PeriodicAttack, true)
    call TriggerAddCondition( DamageCheck, Condition( function Trig_DamageTaken_Conditions ) )
    call SaveTriggerHandle(udg_ah,DamagedId,StringHash("DamageTakenTrigger"),DamageCheck)
    call SaveUnitHandle(udg_ah,GetHandleId(DamageCheck),0,Damaged)
endif
    call SaveReal(udg_ah,DamagedId,StringHash("HomeX"),DamagedX)
    call SaveReal(udg_ah,DamagedId,StringHash("HomeY"),DamagedY)
endif
set Damaged=null
set Attacker=null
set DamagedNeutralGroup=null
set DamageCheck=null
endfunction

//===========================================================================
function InitTrig_AttackTaken takes nothing returns nothing
    set gg_trg_AttackTaken = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_AttackTaken, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_AttackTaken, Condition( function Trig_AttackTaken_Conditions ) )
    call TriggerAddAction( gg_trg_AttackTaken, function Trig_AttackTaken_Actions )
endfunction
Прошу оставить мнение о системе,какие недочёты или присутствующие утечки.
Прикрепленные файлы
Тип файла: w3x NeutralAttackAI.w3x (17.2 Кбайт, 46 просмотров )

Отредактировано Nerevar, 13.08.2011 в 18:29.
Старый 13.08.2011, 18:13
AlakFrost

offline
Опыт: 7,936
Активность:
Больно долго думает моб кого бить , иногда вообще ступор . А так не плохая идея , пофиксить главное .
Старый 14.08.2011, 19:04
Msey
????
offline
Опыт: 67,346
Активность:
Системка неплохая. Хотя иногда мобы реально ТУПЯТ, видать задействовано несколько действий в одно и то же время.
Но моя система круче :3
Старый 09.09.2011, 23:45
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 20:06.