library IllusionSight uses/*
Illusion Sight v1.00
by Flux
An IllusionSight grants a unit the ability to distinguish enemy illusions.
*/ optional RegisterPlayerUnitEvent /*
*********************************
API
*********************************
struct IllusionSight
static method create takes unit u, real radius, real duration returns IllusionSight
Add an Illusion Sight to <unit u> revealing if units nearby are illusions within <real radius>
for <real duration> second(s). For infinite duration, use 0.
static method addToItem takes integer itemId, real radius returns nothing
Make all items of rawcode <integer itemId> have IllusionSight having <real radius>.
static method defaultColor takes integer unitId, integer red, integer green, integer blue returns nothing
Tells the system that all units with rawcode <integer unitId> has a vertex color of
<integer red>, <integer greenn>, <integer blue> configured in Object Editor.
method destroy takes nothing returns nothing
Destroy an IllusionSight instance. You mostly won't need this if the duration is not set to 0.
CREDITS:
Magtheridon96 - RegisterPlayerUnitEvent
*/
globals
//Recommended Value: 0.1 to 0.2
private constant real TIMEOUT = 0.1
//If certain items will have a passive Illusion Sight, set this to true
//else set it to false to have lesser compiled code
private constant boolean WILL_USE_ON_ITEMS = true
endglobals
native UnitAlive takes unit u returns boolean
private function TargetFilter takes unit u, player owner returns boolean
return UnitAlive(u) and IsUnitEnemy(u, owner)
endfunction
private struct Color
readonly integer id
readonly integer r
readonly integer g
readonly integer b
method destroy takes nothing returns nothing
call this.deallocate()
endmethod
static method create takes integer unitId, integer red, integer green, integer blue returns thistype
local thistype this = thistype.allocate()
set this.id = unitId
set this.r = red
set this.g = green
set this.b = blue
return this
endmethod
endstruct
struct IllusionSight
private unit u
private player owner
private group visible
private boolean inf
private real duration
private real radius
private thistype next
private thistype prev
private static group g = CreateGroup()
private static group swap = CreateGroup()
private static group tempG
private static timer t = CreateTimer()
private static hashtable hash = InitHashtable()
private method reset takes unit u returns nothing
local integer id = GetHandleId(u)
local integer count = LoadInteger(thistype.hash, id, 0) - 1
local Color c
call SaveInteger(thistype.hash, id, 0, count)
if count == 0 then
if IsUnitAlly(this.u, GetLocalPlayer()) then
if HaveSavedInteger(thistype.hash, GetUnitTypeId(u), 0) then
set c = LoadInteger(thistype.hash, GetUnitTypeId(u), 0)
call SetUnitVertexColor(u, c.r, c.g, c.b, 255)
else
call SetUnitVertexColor(u, 255, 255, 255, 255)
endif
endif
call RemoveSavedInteger(thistype.hash, id, 0)
endif
endmethod
method destroy takes nothing returns nothing
local unit u
set this.prev.next = this.next
set this.next.prev = this.prev
if thistype(0).next == 0 then
call PauseTimer(thistype.t)
endif
loop
set u = FirstOfGroup(this.visible)
exitwhen u == null
call GroupRemoveUnit(this.visible, u)
call this.reset(u)
endloop
call DestroyGroup(this.visible)
set this.visible = null
set this.u = null
call this.deallocate()
endmethod
//! textmacro ILLLUSION_SIGHT_PERIODIC_UPDATE
if not this.inf then
set this.duration = this.duration - TIMEOUT
endif
if this.duration > 0 then
call GroupEnumUnitsInRange(thistype.g, GetUnitX(this.u), GetUnitY(this.u), this.radius, null)
loop
set u = FirstOfGroup(thistype.g)
exitwhen u == null
call GroupRemoveUnit(thistype.g, u)
if IsUnitIllusion(u) and TargetFilter(u, this.owner) and not IsUnitInGroup(u, this.visible) then
call GroupAddUnit(this.visible, u)
set id = GetHandleId(u)
call SaveInteger(thistype.hash, id, 0, LoadInteger(thistype.hash, id, 0) + 1)
endif
endloop
loop
set u = FirstOfGroup(this.visible)
exitwhen u == null
call GroupRemoveUnit(this.visible, u)
if IsUnitInRange(u, this.u, this.radius) then
call GroupAddUnit(thistype.swap, u)
if IsUnitAlly(this.u, GetLocalPlayer()) then
call SetUnitVertexColor(u, 0, 0, 255, 255)
endif
else
call this.reset(u)
endif
endloop
set thistype.tempG = this.visible
set this.visible = thistype.swap
set thistype.swap = thistype.tempG
else
call this.destroy()
endif
//! endtextmacro
private static method pickAll takes nothing returns nothing
local thistype this = thistype(0).next
local integer id
local unit u
loop
exitwhen this == 0
//! runtextmacro ILLLUSION_SIGHT_PERIODIC_UPDATE()
set this = this.next
endloop
endmethod
static method create takes unit u, real radius, real duration returns thistype
local thistype this = thistype.allocate()
set this.u = u
set this.owner = GetOwningPlayer(u)
set this.radius = radius
if duration == 0 then
set this.inf = true
set this.duration = TIMEOUT
else
set this.inf = false
set this.duration = duration
endif
set this.visible = CreateGroup()
set this.next = 0
set this.prev = thistype(0).prev
set this.next.prev = this
set this.prev.next = this
if this.prev == 0 then
call TimerStart(thistype.t, TIMEOUT, true, function thistype.pickAll)
endif
return this
endmethod
static method defaultColor takes integer unitId, integer red, integer green, integer blue returns nothing
call SaveInteger(thistype.hash, unitId, 0, Color.create(unitId, red, green, blue))
endmethod
static if WILL_USE_ON_ITEMS then
private static method drop takes nothing returns nothing
local item it = GetManipulatedItem()
local integer id = GetItemTypeId(it)
if HaveSavedReal(thistype.hash, id, 0) then
call thistype(LoadInteger(thistype.hash, GetHandleId(GetTriggerUnit()), GetHandleId(it))).destroy()
endif
set it = null
endmethod
private static method pick takes nothing returns nothing
local item it = GetManipulatedItem()
local integer id = GetItemTypeId(it)
local unit u
if HaveSavedReal(thistype.hash, id, 0) then
set u = GetTriggerUnit()
call SaveInteger(thistype.hash, GetHandleId(u), GetHandleId(it), thistype.create(u, LoadReal(thistype.hash, id, 0), 0))
set u = null
endif
set it = null
endmethod
static method addToItem takes integer itemId, real radius returns nothing
call SaveReal(thistype.hash, itemId, 0, radius)
endmethod
private static method onInit takes nothing returns nothing
static if LIBRARY_RegisterPlayerUnitEvent then
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_PICKUP_ITEM, function thistype.pick)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DROP_ITEM, function thistype.drop)
else
local trigger pickTrg = CreateTrigger()
local trigger dropTrg = CreateTrigger()
local code c1 = function thistype.pick
local code c2 = function thistype.drop
call TriggerRegisterAnyUnitEventBJ(pickTrg, EVENT_PLAYER_UNIT_PICKUP_ITEM)
call TriggerRegisterAnyUnitEventBJ(dropTrg, EVENT_PLAYER_UNIT_DROP_ITEM)
call TriggerAddCondition(pickTrg, Filter(c1))
call TriggerAddCondition(dropTrg, Filter(c2))
endif
endmethod
endif
endstruct
endlibrary