| 10-28-2008, 04:12 PM | #1 |
Is it possible to, at any given moment, find out the current unit that another unit is targetting with it's attacks or possibly even other orders? And i mean generically, much like requesting the "Current Order" of a unit. |
| 10-28-2008, 06:19 PM | #2 |
As far as I know you'd need a system for that, I coded one a while ago. JASS:library AttackMonitoringSystem initializer Init requires TimerUtils, ABuff private constant function AttackDuration takes nothing returns real return 2.5 endfunction globals public aBuffType id endglobals private keyword AMData private function AttackExpire takes nothing returns nothing call AMData( GetTimerData(GetExpiredTimer()) ).attackExpire() endfunction private struct AMData integer attAmount=0 AMData firstAttacker=0 AMData attacking=0 AMData prevAttacker=0 AMData nextAttacker=0 timer attTimeout aBuff a static method create takes aBuff a returns AMData local AMData am = AMData.allocate() set am.a=a return am endmethod private method unlinkAttacker takes nothing returns nothing local AMData target = this.attacking if target.firstAttacker==this then set target.firstAttacker=this.nextAttacker else set this.prevAttacker.nextAttacker = this.nextAttacker endif if this.nextAttacker != 0 then set this.nextAttacker.prevAttacker = this.prevAttacker endif set this.nextAttacker = 0 set this.prevAttacker = 0 set target.attAmount=target.attAmount-1 set this.attacking = 0 endmethod private method linkAttacker takes AMData target returns nothing //method assumes attacker is unlinked first if target.firstAttacker != 0 then set target.firstAttacker.prevAttacker = this endif set this.nextAttacker = target.firstAttacker set target.firstAttacker = this set target.attAmount=target.attAmount+1 set this.attacking=target endmethod method attack takes AMData target returns nothing if this.attTimeout==null then set this.attTimeout=NewTimer() call SetTimerData(this.attTimeout,integer(this)) endif if this.attacking != target then if this.attacking != 0 then call this.unlinkAttacker() endif call this.linkAttacker(target) // call BJDebugMsg("Attacking Unit, it now has "+I2S(this.attacking.attAmount)+" attackers.") endif call TimerStart(this.attTimeout, AttackDuration(), false, function AttackExpire) endmethod method attackExpire takes nothing returns nothing if this.attacking != 0 then call this.unlinkAttacker() // call BJDebugMsg("Attack Expired") else //some sort of bug, do nothing debug call BJDebugMsg("Warning: Attack timer expired with unit not attacking anyone.") endif call ReleaseTimer(this.attTimeout) set this.attTimeout=null endmethod method onDestroy takes nothing returns nothing local AMData attackers = 0 if this.attTimeout!=null then call ReleaseTimer(this.attTimeout) set this.attTimeout=null endif if this.attacking != 0 then call this.unlinkAttacker() endif loop set attackers = this.firstAttacker exitwhen attackers == 0 call attackers.unlinkAttacker() if attackers.attTimeout!=null then call ReleaseTimer(attackers.attTimeout) set attackers.attTimeout=null else //some sort of bug, do nothing debug call BJDebugMsg("Warning: Attacker without a timer found on unit death.") endif endloop endmethod endstruct private function Create takes aBuff eventBuff returns nothing set eventBuff.data=integer(AMData.create(eventBuff)) endfunction private function Refresh takes aBuff eventBuff returns nothing set eventBuff.data=eventBuff.olddata endfunction private function Cleanup takes aBuff eventBuff returns nothing call AMData( eventBuff.data ).destroy() endfunction private function Attack takes aBuff eventBuff, unit attacked returns nothing local aBuff a = GetABuffFromUnitByType(attacked, id) local AMData target = AMData( a.data ) if a == 0 then //some sort of bug, just abort debug call BJDebugMsg("attacking a unit without the attack tracking buff") return endif call AMData( eventBuff.data ).attack(target) endfunction private function InitAttackTrackingUnit takes nothing returns nothing call ABuffApply(id, GetTriggerUnit(), null, 0, 0, 0 ) endfunction private function InitAttackTrackingUnitB takes nothing returns nothing call ABuffApply(id, GetEnumUnit(), null, 0, 0, 0 ) endfunction private function InitAttackTrackingUnitC takes nothing returns nothing call ABuffApply(id, GetSummonedUnit(), null, 0, 0, 0 ) endfunction private function Init takes nothing returns nothing local trigger t local group g = GetUnitsInRectAll(GetPlayableMapRect()) set id = aBuffType.create() set id.eventCreate = ABuffEvent_Create.Create set id.eventRefresh = ABuffEvent_Refresh.Refresh set id.eventCleanup = ABuffEvent_Cleanup.Cleanup set id.eventAttack = ABuffEvent_BUnitAttack.Attack set id.ignoreAsBuff = true set t = CreateTrigger() call TriggerRegisterEnterRectSimple( t, GetPlayableMapRect() ) call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_HERO_REVIVE_FINISH ) call TriggerAddAction( t, function InitAttackTrackingUnit ) set t = CreateTrigger() // ressurect abilities don't trigger the unit enters region event, need to use summon event call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SUMMON ) call TriggerAddAction( t, function InitAttackTrackingUnitC ) call ForGroup( g, function InitAttackTrackingUnitB ) endfunction function interface AttackerEnum takes unit enumAtt, integer data returns nothing function AttackerEnumerate takes AttackerEnum f, unit u, integer data returns nothing local aBuff a = GetABuffFromUnitByType(u, id) local AMData amd if integer(a)==0 then return endif set amd = AMData(a.data).firstAttacker loop exitwhen (amd == 0) call f.evaluate(amd.a.target.u, data) set amd = amd.nextAttacker endloop endfunction function GetUnitAttackTarget takes unit attacker returns unit local aBuff a = GetABuffFromUnitByType(attacker, id) if integer(a)==0 then return null endif return AMData(a.data).attacking.a.target.u endfunction function GetBuffedUnitAttackTarget takes aBuff a returns unit set a = GetABuffFromBuffedUnitByType(a, id) if integer(a)==0 then return null endif return AMData(a.data).attacking.a.target.u endfunction function GetUnitAttackersAmount takes unit defender returns integer local aBuff a = GetABuffFromUnitByType(defender, id) if integer(a)==0 then return 0 endif return AMData(a.data).attAmount endfunction function GetBuffedUnitAttackersAmount takes aBuff a returns integer set a = GetABuffFromBuffedUnitByType(a, id) if integer(a)==0 then return 0 endif return AMData(a.data).attAmount endfunction endlibrary |
