//Spell Name: Doppelganger v1.5
//Created by: Mckill2009
//===HOW TO USE:
//- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
//- The trigger name MUST be >>> Doppelganger (see the name below)
//- Copy ALL that is written here and overwrite the existing texts in the custom text
//- Copy the Dummy/custom abilities/buffs etc... to your object editor
//- Make sure you inputed the correct raw codes of the base spell/buffs/dummy etc...
//- If your raw code is different, you MUST CHANGE IT...
//- You can view the raw codes by pressing CTRL+D in the object editor
//- Examples of raw codes are 'A000', 'h000' etc...
//===REQUIRED VARIABLES:
// DPL_Hash = hashtable
// DPL_DPL_Group = group
// DPL_Timer = timer
// DPL_Portal = unit
// DPL_Counter = integer
//==========CONFIGURABLES==========
//===IMPORTANT NOTICE: Raw codes MUST BE CHANGED if your raw code has changed as indicated below
function DPL_SpellId takes nothing returns integer
return 'A000' //the main spell
endfunction
function DPL_SleepId takes nothing returns integer
return 'A002' //the portal will cast this spell to enemy units
endfunction
function DPL_ImageCasterId takes nothing returns integer
return 'H001' //a dummy unit hero, this is the caster of the image
endfunction
function DPL_PortalId takes nothing returns integer
return 'h000' //raw code of the portal unit, it is recommended to use the Shimmering Portal
endfunction
function DPL_ItemId takes nothing returns integer
return 'I000' //this is an item which is given to the dummy hero
endfunction
function DPL_GetDuration takes integer i returns real
return 10 + i * 15. //the life of the portal
endfunction
constant function DPL_TimerInterval takes nothing returns real
return 0.1 //dont change
endfunction
constant function DPL_AoE takes nothing returns real
return 400. //the reach of the portal casting the sleep
endfunction
//==========END OF CONFIGURABLES==========
function DPL_LoopAction takes nothing returns nothing
local unit portal = GetEnumUnit()
local unit first
local integer portalID = GetHandleId(portal)
local real maxduration = LoadReal(udg_DPL_Hash, portalID, 1)
local real mindur = LoadReal(udg_DPL_Hash, portalID, 2)
if maxduration > 0 then
call SaveReal(udg_DPL_Hash, portalID, 1, maxduration - DPL_TimerInterval())
call SaveReal(udg_DPL_Hash, portalID, 2, mindur + DPL_TimerInterval())
if mindur >= 9 and (LoadInteger(udg_DPL_Hash, portalID, 3)==0) then
//setting the saved integer to 1 in order for this not to run again
//otherwise the add ability will always run
call SaveInteger(udg_DPL_Hash, portalID, 3, 1)
call UnitAddAbility(portal, DPL_SleepId())
elseif mindur > 9 then //it takes 9 seconds for the portal to animate it's birth
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(portal), GetUnitY(portal), DPL_AoE(), null)
loop
set first = FirstOfGroup(bj_lastCreatedGroup)
exitwhen first==null
if IsUnitEnemy(portal, GetOwningPlayer(first)) and not IsUnitType(first, UNIT_TYPE_STRUCTURE) and not IsUnitType(first, UNIT_TYPE_SLEEPING) and not IsUnitType(first, UNIT_TYPE_DEAD) then
call IssueTargetOrder(portal, "sleep", first)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, first)
endloop
endif
else
call KillUnit(portal)
call FlushChildHashtable(udg_DPL_Hash, portalID)
call GroupRemoveUnit(udg_DPL_Group, portal)
set udg_DPL_Counter = udg_DPL_Counter - 1
if udg_DPL_Counter == 0 then
call PauseTimer(udg_DPL_Timer)
endif
endif
set portal = null
endfunction
function DPL_CastOn takes unit u, integer spellId, integer portalId returns nothing
local real facing = GetUnitFacing(u) * bj_DEGTORAD
local real x = GetUnitX(u)+100*Cos(facing)
local real y = GetUnitY(u)+100*Sin(facing)
local integer portalID
local integer level = GetUnitAbilityLevel(u, spellId)
local unit portal = CreateUnit(GetTriggerPlayer(), portalId, x, y, facing)
set portalID = GetHandleId(portal)
call SetUnitAnimation(portal, "birth")
call SaveReal(udg_DPL_Hash, portalID, 1, DPL_GetDuration(level))
call SaveReal(udg_DPL_Hash, portalID, 2, 0) //mindur
call SaveInteger(udg_DPL_Hash, portalID, 3, 0) //this is used for checking only
call GroupAddUnit(udg_DPL_Group, portal)
set portal = null
endfunction
function DPL_GroupLooper takes nothing returns nothing
call ForGroup(udg_DPL_Group, function DPL_LoopAction)
endfunction
function DPL_CastCond takes nothing returns boolean
local unit u
local unit imagecaster
if GetSpellAbilityId()==DPL_SpellId() then
if udg_DPL_Counter == 0 then
call TimerStart(udg_DPL_Timer, DPL_TimerInterval(), true, function DPL_GroupLooper)
endif
set udg_DPL_Counter = udg_DPL_Counter + 1
call DPL_CastOn(GetTriggerUnit(), DPL_SpellId(), DPL_PortalId())
elseif GetSpellAbilityId()==DPL_SleepId() then
set u = GetSpellTargetUnit()
set imagecaster = CreateUnit(GetTriggerPlayer(), DPL_ImageCasterId(), GetUnitX(u), GetUnitY(u), 0)
call UnitApplyTimedLife(imagecaster, 'BTLF', 1.0)
call UnitUseItemTarget(imagecaster, UnitAddItemById(imagecaster, DPL_ItemId()), u)
set u = null
set imagecaster = null
endif
return false
endfunction
function InitTrig_Doppelganger takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, function DPL_CastCond)
set t = null
set udg_DPL_Hash = InitHashtable() //hashtable
//Preloading
set bj_lastCreatedUnit = CreateUnit(Player(15), DPL_ImageCasterId(),0,0,0)
call UnitAddAbility(bj_lastCreatedUnit, DPL_SleepId())
call RemoveUnit(bj_lastCreatedUnit)
endfunction