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")),LoadReal(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")),LoadReal(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
Прошу оставить мнение о системе,какие недочёты или присутствующие утечки.
Отредактировано Nerevar, 13.08.2011 в 18:29.
|