//***************************************************************************
//***************************************************************************
//***************************************************************************
// S H A D O W I M A G E B L I N K
// By: Elphis (Nyuu)
// Version: 1.0
//
// Sepll Description:
// ` - Use dark power, creating an illusion and a energy
// ball shot to the selected point and after energy ball hit the target point,
// it will explodes and stuns enemies in 2/2.5/3/3.5 seconds and cause 50/100/150/200
// damage in 300 range.
// - Installation:
// - Import/copy Shadow Image Blink code to your map
// - Import/copy the custom ability and unit to your map and change the SPELL_ID, DSPELL_ID, DUMMY_BOLT and DUMMY_CASTER if needed
// - You may view the raw ID of the objects by pressing CTRL+D in the object editor
// - You may play with the configurables below
// - Credit:
// - Unleashthepower.mdx - http://www.hiveworkshop.com/forums/models-530/unleash-power-243024/?prev=search%3DPower%26d%3Dlist%26r%3D20
// - TerrainPathability - http://www.wc3c.net/showthread.php?t=103862
//
//
//***************************************************************************
//***************************************************************************
//***************************************************************************
library ShadowImageBlink uses TerrainPathability
globals
//Spell rawcode, change if needed
private constant integer SPELL_ID = 'A000'
//
private constant integer DSPELL_ID = 'A001'
//Dummy unit rawcode (Bolt model) change if needed
private constant integer DUMMY_BOLT = 'e000'
//Dummy caster rawcode, change if needed
private constant integer CASTER_DUMMY = 'e001'
//Crow Form ability
private constant integer CROW_FORM = 'Amrf'
//Animation play when the caster casting this spell
private constant string ANIMATION = "spell"
//Effect of spell
private constant string BLINK_CAST = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
//Effect of spell when begin & end spell
private constant string BLINK_END = "war3mapImported\\Unleash the power.mdx"
//Attachment of the caster when spell end (Using BLINK_END effect)
private constant string ATTACHMENT = "chest"
//Order id of dummy caster casting the dummy ability
private constant string ORDER_ID = "thunderbolt"
//Dummy owner
private constant player DUMMY_OWNER = Player(15)
//******************************DAMAGE DATA SETTINGS******************************
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_DEATH
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_CLAW_HEAVY_SLICE
//********************************************************************************
//Damage radius
private constant real DAMAGE_RADIUS = 300.
//Damage base of this spell
private constant real DAMAGE_BASE = 50.
//Animation speed of the caster unit when this spell is used
private constant real ANIMATION_SPEED = 0.43
//Spell period
private constant real PERIODIC = .031250000
//Virtual caster speed separator
private constant real SPERATION_SPEED = 20.
//Max height of the ball power
private constant real MAX_HEIGHT = 1000.
/*Fade settings*/
private constant integer FADE_COUNT = 10
private constant integer FADE_FLASH = 85
private constant integer FADE_SPEED = 10
//********************************************************
//***************************Non - Configurable*****************************
/* */
/**/private constant group G = CreateGroup()/**/
/* */
/**/private integer MUI = -1 /**/
/* */
/**/private integer array StructData /**/
/* */
/**/private constant timer TIMER = CreateTimer()/**/
//**************************************************************************
/**/private unit Dummy
//**************************************************************************
endglobals
//************************************DO NOT MODIFY ANYTHING BELOW************************************
//*******************Damage setting***********************************
/**/constant function getDamage takes integer lvl returns real /**/
/**/ return DAMAGE_BASE * lvl /**/
/**/endfunction /**/
//********************************************************************
//*******************Filter Function***********************************
/**/function filterFunc takes player owner,unit filterUnit returns boolean
/**/ //Assure a better death check//
/**/return not IsUnitType(filterUnit,UNIT_TYPE_DEAD) and /**/GetUnitTypeId(filterUnit) != 0/**/ and IsUnitEnemy(filterUnit,owner)
/**/endfunction
//********************************************************************
private struct ShadowImageBlink
unit caster
unit dummy_1
unit dummy_2
unit dummy_3
integer fade = 255
integer lvl
integer fade_count = FADE_COUNT
boolean fade_done = false
boolean subtract = true
player owner
real cos
real sin
real facing
real total = -SPERATION_SPEED
real angle
real fade_seperation
real targetx
real targety
real speration_speed
real height
real dmg
static method onPeriodic takes nothing returns nothing
local integer i = 0
local thistype this
local real x
local real y
local real o
local real z
local unit f = null
loop
exitwhen i > MUI
set this = StructData[i]
if subtract then
set x = GetUnitX(dummy_1) + cos
set y = GetUnitY(dummy_1) + sin
set o = GetUnitX(dummy_2) - cos
set z = GetUnitY(dummy_2) - sin
if fade > fade_seperation then
if not fade_done then
set fade = fade - FADE_SPEED
else
set fade = 0
endif
elseif fade_done then
set fade = FADE_FLASH
if fade_count > 0 then
set fade_count = fade_count - 1
else
set subtract = false
set fade_done = false
set fade = 0
set cos = Cos(angle)
set sin = Sin(angle)
set x = targetx + total * cos
set y = targety + total * sin
call SetUnitX(dummy_1,x)
call SetUnitY(dummy_1,y)
call DestroyEffect(AddSpecialEffect(BLINK_CAST,x,y))
set x = targetx - total * cos
set y = targety - total * sin
call SetUnitX(dummy_2,x)
call SetUnitY(dummy_2,y)
call DestroyEffect(AddSpecialEffect(BLINK_CAST,x,y))
set cos = speration_speed*Cos(angle)
set sin = speration_speed*Sin(angle)
endif
else
set fade_done = true
endif
set total = total + speration_speed
endif
if not fade_done and not subtract then
set x = GetUnitX(dummy_1) - cos
set y = GetUnitY(dummy_1) - sin
set o = GetUnitX(dummy_2) + cos
set z = GetUnitY(dummy_2) + sin
if fade_count < FADE_COUNT then
set fade_count = fade_count + 1
if fade == 0 then
set fade = FADE_FLASH
else
set fade = 0
endif
if fade_count == FADE_COUNT then
set fade = 0
endif
elseif fade < 255 then
set fade = fade + FADE_SPEED
else
set StructData[i] = StructData[MUI]
set StructData[MUI] = -2
set MUI = MUI - 1
if MUI == -1 then
call PauseTimer(TIMER)
endif
call DestroyEffect(AddSpecialEffectTarget(BLINK_END,caster,ATTACHMENT))
call GroupEnumUnitsInRange(G,targetx,targety,DAMAGE_RADIUS,null)
call SetUnitAbilityLevel(Dummy,DSPELL_ID,lvl)
loop
set f = FirstOfGroup(G)
exitwhen f == null
if filterFunc(owner,f) then
call SetUnitX(Dummy,GetUnitX(f))
call SetUnitY(Dummy,GetUnitY(f))
call IssueTargetOrder(Dummy,ORDER_ID,f)
call UnitDamageTarget(caster,f,dmg,true,false,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
endif
call GroupRemoveUnit(G,f)
endloop
call SetUnitX(caster,targetx)
call SetUnitY(caster,targety)
call ShowUnit(caster,true)
call SetUnitTimeScale(caster,1.)
if GetLocalPlayer() == owner then
call ClearSelection()
call SelectUnit(caster,true)
endif
call RemoveUnit(dummy_1)
call RemoveUnit(dummy_2)
call RemoveUnit(dummy_3)
set owner = null
set dummy_1 = null
set dummy_2 = null
set dummy_3 = null
set caster = null
call destroy()
endif
endif
call SetUnitX(dummy_1,x)
call SetUnitY(dummy_1,y)
call SetUnitX(dummy_2,o)
call SetUnitY(dummy_2,z)
call SetUnitFlyHeight(dummy_3,GetUnitFlyHeight(dummy_3)-height,0.)
call SetUnitVertexColor(dummy_1,255,255,255,fade)
call SetUnitVertexColor(dummy_2,255,255,255,fade)
set i = i + 1
endloop
endmethod
static method onCast takes nothing returns boolean
local thistype this
local real x
local real y
local playercolor owner_color
local integer i
if GetSpellAbilityId() == SPELL_ID then
set x = GetSpellTargetX()
set y = GetSpellTargetY()
if IsTerrainWalkable(x,y) then
set this = allocate()
set MUI = MUI + 1
set StructData[MUI] = this
set caster = GetTriggerUnit()
set owner = GetTriggerPlayer()
set owner_color = GetPlayerColor(owner)
set lvl = GetUnitAbilityLevel(caster,SPELL_ID)
set dmg = getDamage(lvl)
call ShowUnit(caster,false)
set targetx = x
set targety = y
set fade_seperation = FADE_FLASH/3
set x = GetUnitX(caster)
set y = GetUnitY(caster)
set angle = 57.29583 * Atan2(targety - y, targetx - x) + 90.
set facing = angle - 90.
set angle = angle *.0174533
set speration_speed = SPERATION_SPEED/FADE_SPEED
set height = MAX_HEIGHT/(SPERATION_SPEED*FADE_SPEED/speration_speed-10.)
set cos = speration_speed * Cos(angle)
set sin = speration_speed * Sin(angle)
set i = GetUnitTypeId(caster)
set dummy_1 = CreateUnit(DUMMY_OWNER,i,x,y,facing)
if UnitAddAbility(dummy_1,'Aloc') then
call SetUnitPathing(dummy_1,false)
call SetUnitX(dummy_1,x)
call SetUnitY(dummy_1,y)
endif
set dummy_2 = CreateUnit(DUMMY_OWNER,i,x,y,facing)
if UnitAddAbility(dummy_2,'Aloc') then
call SetUnitPathing(dummy_2,false)
call SetUnitX(dummy_2,x)
call SetUnitY(dummy_2,y)
endif
set dummy_3 = CreateUnit(DUMMY_OWNER,DUMMY_BOLT,targetx,targety,facing)
if UnitAddAbility(dummy_3,CROW_FORM) then
call UnitRemoveAbility(dummy_3,CROW_FORM)
call SetUnitFlyHeight(dummy_3,MAX_HEIGHT,0.)
endif
//********************************************
call SetUnitColor(dummy_1,owner_color)
call SetUnitColor(dummy_2,owner_color)
//********************************************
call SetUnitTimeScale(caster,ANIMATION_SPEED)
call SetUnitTimeScale(dummy_1,ANIMATION_SPEED)
call SetUnitTimeScale(dummy_2,ANIMATION_SPEED)
//********************************************
call SetUnitAnimation(caster,ANIMATION)
call SetUnitAnimation(dummy_1,ANIMATION)
call SetUnitAnimation(dummy_2,ANIMATION)
//********************************************
if MUI == 0 then
call TimerStart(TIMER,PERIODIC,true,function thistype.onPeriodic)
endif
endif
endif
set owner_color = null
return false
endmethod
static method onInit takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i = i + 1
endloop
call TriggerAddCondition(t,function thistype.onCast)
set Dummy = CreateUnit(DUMMY_OWNER,CASTER_DUMMY,0.,0.,0.)
endmethod
endstruct
endlibrary