//**********************************************************************************************
//*
//* Optical Flare
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯
//* Requires:
//* - The Pool Class functions
//* - The Handle Variables functions
//* - The Optical Flare Ability
//* - The Optical Flare Buff
//* - The Optical Flare Sight Destruction Ability
//* - The Flare Vision unit type
//* - This Trigger (make sure it points to the right rawcodes)
//* Note:
//* - If you have any custom detector ability in your map, you have to add it to the
//* SetupDetectionPool function at the end of this configuration section.
//*
//**********************************************************************************************
//==============================================================================================
// Optical Flare Configuration
//
constant function OpticalFlare_SpellId takes nothing returns integer
return 'A007' //// The Rawcode of the Optical Flare Ability In your map
endfunction
constant function OpticalFlare_BuffId takes nothing returns integer
return 'B000' //// The Rawcode of the Optical Flare Buff In your map
endfunction
constant function OpticalFlare_SightDestructorSpellId takes nothing returns integer
return 'A006' //// The Rawcode of the Optical Flare Sight Destructor ability In your map
endfunction
constant function OpticalFlare_FakeSightUnit takes nothing returns integer
return 'n000' //// The Rawcode of the Optical Flare Vision unit type In your map
endfunction
constant function OpticalFlare_MissileSpeed takes nothing returns integer
return 1500 //// The missile speed, should be exactly the same as the one used by the ability
endfunction
function SetupDetectionPool takes integer spells returns nothing
call PoolAddItem(spells,'Agyv') //True Sight (Flying Machine)
call PoolAddItem(spells,'Atru') //True Sight (Shade)
call PoolAddItem(spells,'Adtg') //True Sight (Neutral 1)
call PoolAddItem(spells,'ANtr') //True Sight (Neutral 2)
call PoolAddItem(spells,'Adts') //Magic Sentry
call PoolAddItem(spells,'Adt1') //Detector (Sentry Ward)
call PoolAddItem(spells,'Abdt') //Burrow Detection (fliers)
//If you have any custom ability that allows passive detection, you must add a line for it
// Example:
call PoolAddItem(spells,'A008') //Creep Detection Ability
// Remove the example from your map, or this ability would remove an ability it is not
// supposed to remove.
endfunction
//===================================================================================================
function OpticalFlareDetectDetector takes unit u, integer p returns integer
local integer n=CountItemsInPool(p)
local integer i
loop
exitwhen n==0
set i=PoolGetItem(p,n)
if GetUnitAbilityLevel(u,i)>0 then
return i
endif
set n=n-1
endloop
return 0
endfunction
function OpticalFlare_GetUnit takes timer t, string s returns unit
return GetHandleHandle(t,s)
endfunction
function OpticalFlare_Timer takes nothing returns nothing
local timer t=GetExpiredTimer()
local unit b=OpticalFlare_GetUnit(t,"b")
local unit sh=OpticalFlare_GetUnit(t,"sh")
local real x=GetHandleReal(t,"x")
local real y=GetHandleReal(t,"y")
local real nx=GetUnitX(b)
local real ny=GetUnitY(b)
local real a=ModuloReal( Atan2(ny-y,nx-x) , 2*bj_PI)
local real d= SquareRoot(Pow(x-nx,2) +Pow(y-ny,2))
if ModuloReal(a+bj_PI/4,bj_PI*2)<=bj_PI then
set d=d*40
endif
call SetUnitPosition(sh,nx+d*Cos(a),ny+d*Sin(a) )
call SetHandleReal(t,"x",nx)
call SetHandleReal(t,"y",ny)
call SetUnitFacing(sh,GetUnitFacing(b))
call SetUnitFlyHeight(sh, GetUnitFlyHeight(b)+120,0)
set t=null
set b=null
set sh=null
endfunction
function OpticalFlare_Effect takes unit b, integer l returns nothing
local real ac=GetUnitAcquireRange(b)
local unit sh=CreateUnit( GetOwningPlayer(b), OpticalFlare_FakeSightUnit(), GetUnitX(b), GetUnitY(b), 0)
local integer abi=OpticalFlareDetectDetector(b, GetStoredInteger(InitGameCache("opticalflare"),"opt","pool") )
local timer t=CreateTimer()
call SetUnitPathing(sh,false)
call UnitRemoveAbility(b, abi )
call UnitAddAbility(b, OpticalFlare_SightDestructorSpellId() )
call UnitMakeAbilityPermanent(b,true,OpticalFlare_SightDestructorSpellId())
call UnitMakeAbilityPermanent(b,true,OpticalFlare_BuffId())
call SetHandleHandle(t,"b",b)
call SetHandleHandle(t,"sh",sh)
call TimerStart(t,0.01,true, function OpticalFlare_Timer )
loop
exitwhen IsUnitDeadBJ(b)
call TriggerSleepAction(0)
exitwhen not UnitHasBuffBJ(b, OpticalFlare_BuffId() )
endloop
call UnitRemoveAbility(b, OpticalFlare_SightDestructorSpellId() )
call UnitAddAbility(b, abi )
call RemoveUnit(sh)
call FlushHandleLocals(t)
call DestroyTimer(t)
set t=null
set sh=null
endfunction
function Trig_Optical_Flare_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit blind=GetSpellTargetUnit()
local integer l=GetUnitAbilityLevel(u,GetSpellAbilityId() )
call PolledWait( SquareRoot(Pow(GetUnitX(u)-GetUnitX(blind),2) + Pow(GetUnitY(u)-GetUnitY(blind),2) ) / OpticalFlare_MissileSpeed() )
call OpticalFlare_Effect(blind,l)
set u=null
set blind=null
endfunction
function Trig_Optical_Flare_Conditions takes nothing returns boolean
return GetSpellAbilityId() == OpticalFlare_SpellId()
endfunction
function InitTrig_Optical_Flare takes nothing returns nothing
local integer i=CreatePool()
call StoreInteger(InitGameCache("opticalflare"),"opt","pool",i)
call SetupDetectionPool(i)
set gg_trg_Optical_Flare = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Optical_Flare, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Optical_Flare, Condition( function Trig_Optical_Flare_Conditions ) )
call TriggerAddAction( gg_trg_Optical_Flare, function Trig_Optical_Flare_Actions )
endfunction
constant function OpticalFlare_SpellId takes nothing returns integer
return 'A007' //// The Rawcode of the Optical Flare Ability In your map
endfunction
constant function OpticalFlare_BuffId takes nothing returns integer
return 'B000' //// The Rawcode of the Optical Flare Buff In your map
endfunction
constant function OpticalFlare_SightDestructorSpellId takes nothing returns integer
return 'A006' //// The Rawcode of the Optical Flare Sight Destructor ability In your map
endfunction
constant function OpticalFlare_FakeSightUnit takes nothing returns integer
return 'n000' //// The Rawcode of the Optical Flare Vision unit type In your map
endfunction
constant function OpticalFlare_MissileSpeed takes nothing returns integer
return 1500 //// The missile speed, should be exactly the same as the one used by the ability
endfunction
//=====================================================================
struct flaredata
unit b //Unit affected by the buff
unit sh //The dummy unit
real x //]
real y ///Previous Position
boolean destroyplease = false
endstruct
globals
integer array DetectorSpells
integer array DetectorSpellsN=0
flaredata array OpticalFlare_Ar
integer OpticalFlare_total = 0
timer OpticalFlare_timer=CreateTimer()
endglobals
function SetupDetectionAbilities returns nothing
set DetectorSpells[1]='Agyv' //True Sight (Flying Machine)
set DetectorSpells[2]='Atru' //True Sight (Shade)
set DetectorSpells[3]='Adtg' //True Sight (Neutral 1)
set DetectorSpells[4]='ANtr' //True Sight (Neutral 2)
set DetectorSpells[5]='Adts' //Magic Sentry
set DetectorSpells[6]='Adt1' //Detector (Sentry Ward)
set DetectorSpells[7]='Abdt' //Burrow Detection (fliers)
// set DetectorSpellsN=7 //normally these 7 spells are needed, uncomment this line if they are just 7
//If you have any custom ability that allows passive detection, you must add a line for it
// Example:
set DetectorSpells[8]='A008' //Creep Detection Ability
set DetectorSpellsN=8 //We added 8 detector spells to the array, so let's specify that number here.
// Remove the example for your map (also update the count), or this ability would remove an ability it is not
// supposed to remove.
endfunction
function OpticalFlareDetectDetector takes unit u returns integer
local integer i
local integer n=DetectorSpellsN
loop
exitwhen n==0
set i=DetectorSpells[n]
if GetUnitAbilityLevel(u,i)>0 then
return i
endif
set n=n-1
endloop
return 0
endfunction
function OpticalFlare_Timer takes nothing returns nothing
local integer i=0
local flaredata dat
local real nx
local real ny
local real a
local real d
loop
exitwhen i==OpticalFlare_total
set dat= OpticalFlare_Ar[i]
if (dat.destroyplease) then
//This is tricky.
// We already have the ith flaredata referenced by dat, so we
// will first remove it from the array, since the order does not matter
// we can simply move the last flaredata to this position and decrease
// the total
set OpticalFlare_Ar[i]= OpticalFlare_Ar[ OpticalFlare_total - 1]
set OpticalFlare_total=OpticalFlare_total-1
//now we are free to destroy the dat
call dat.destroy() //another way to destroy struct objects.
//If we don't substract i, it will skip the new object we just moved
// to the ith position (we are increasing i later)
set i=i-1
else //Notice how this ressembles the original expire function
set nx=GetUnitX(dat.b)
set ny=GetUnitY(dat.b)
set a=ModuloReal( Atan2(ny-dat.y , nx-dat.x ) , 2*bj_PI)
set d= SquareRoot(Pow(dat.x-nx,2) +Pow(dat.y-ny,2))
if ModuloReal(a+bj_PI/4,bj_PI*2)<=bj_PI then
set d=d*40
endif
call SetUnitPosition(dat.sh,nx+d*Cos(a),ny+d*Sin(a) )
set dat.x=nx
set dat.y=ny
call SetUnitFacing( dat.sh,GetUnitFacing( dat.b ))
call SetUnitFlyHeight( dat.sh, GetUnitFlyHeight( dat.b )+120,0)
endif
set i=i+1
endloop
if (OpticalFlare_total==0) then
// let's pause the timer, it is not needed anymore
call PauseTimer(OpticalFlare_timer)
endif
endfunction
function OpticalFlare_Effect takes unit b, integer l returns nothing
local real ac=GetUnitAcquireRange(b)
local unit sh=CreateUnit( GetOwningPlayer(b), OpticalFlare_FakeSightUnit(), GetUnitX(b), GetUnitY(b), 0)
local integer abi=OpticalFlareDetectDetector(b )
local flaredata dat = flaredata.create()
call SetUnitPathing(sh,false)
call UnitRemoveAbility(b, abi )
call UnitAddAbility(b, OpticalFlare_SightDestructorSpellId() )
call UnitMakeAbilityPermanent(b,true,OpticalFlare_SightDestructorSpellId())
call UnitMakeAbilityPermanent(b,true,OpticalFlare_BuffId())
set dat.x=0. //struct fields aren't automatically initialized to 0, unlike handle vars
set dat.y=0. // It is also possible to make them initialize to a default value inside the struct block
set dat.b=b
set dat.sh=sh
if(OpticalFlare_total==0) then //There are no elements in the array so the timer is inactive
call TimerStart(OpticalFlare_timer,0.01,true,function OpticalFlare_Timer) //restart it
endif
set OpticalFlare_total=OpticalFlare_total+1 //increase the number of elements
set OpticalFlare_Ar[ OpticalFlare_total-1 ] = dat //add the flaredata to the array, notice that these are arrays
//that begin with the [0] index...
loop
exitwhen IsUnitDeadBJ(b)
call TriggerSleepAction(0)
exitwhen not UnitHasBuffBJ(b, OpticalFlare_BuffId() )
endloop
call UnitRemoveAbility(b, OpticalFlare_SightDestructorSpellId() )
call UnitAddAbility(b, abi )
call RemoveUnit(sh)
set dat.destroyplease = true //Will send a signal to the timer function so it destroys this object...
set sh=null
endfunction
function Trig_Optical_Flare_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit blind=GetSpellTargetUnit()
local integer l=GetUnitAbilityLevel(u,GetSpellAbilityId() )
call PolledWait( SquareRoot(Pow(GetUnitX(u)-GetUnitX(blind),2) + Pow(GetUnitY(u)-GetUnitY(blind),2) ) / OpticalFlare_MissileSpeed() )
call OpticalFlare_Effect(blind,l)
set u=null
set blind=null
endfunction
function Trig_Optical_Flare_Conditions takes nothing returns boolean
return GetSpellAbilityId() == OpticalFlare_SpellId()
endfunction
function InitTrig_Optical_Flare takes nothing returns nothing
call SetupDetectionAbilities()
set gg_trg_Optical_Flare = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Optical_Flare, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Optical_Flare, Condition( function Trig_Optical_Flare_Conditions ) )
call TriggerAddAction( gg_trg_Optical_Flare, function Trig_Optical_Flare_Actions )
endfunction
constant function OpticalFlare_SpellId takes nothing returns integer
return 'A007' //// The Rawcode of the Optical Flare Ability In your map
endfunction
constant function OpticalFlare_BuffId takes nothing returns integer
return 'B000' //// The Rawcode of the Optical Flare Buff In your map
endfunction
constant function OpticalFlare_SightDestructorSpellId takes nothing returns integer
return 'A006' //// The Rawcode of the Optical Flare Sight Destructor ability In your map
endfunction
constant function OpticalFlare_FakeSightUnit takes nothing returns integer
return 'n000' //// The Rawcode of the Optical Flare Vision unit type In your map
endfunction
constant function OpticalFlare_MissileSpeed takes nothing returns integer
return 1500 //// The missile speed, should be exactly the same as the one used by the ability
endfunction