Tom_Kazansky
--- wraith it ! ---
- Reaction score
- 157
Thanatos the God of Death
-------------------------------------
This pack has 4 spells, they are MUI, lagless (for me), leakless (I think), vJass. Also they have a good visual effect.
-------------------------------------
First spell: Sword Barrage
- Description:
- Code:
Second spell: Infernal Impact (It needs a different name )
- Description:
- Code:
Third spell: Phantom Swing
- Description:
- Code:
Ultimate spell: Infernal Stigma
- Description:
- Screenshot:
- Code:
Import Instruction
-Import all nessessary models
-Go to the Object Editor \ Abilities, copy Thanatos's Sword (A000), Sword Barrage (A001), Infernal Impact (A002), Phantom Swing (A003), Infernal Stigma (A004)
-Then at Object Editor \ Units, copy Lord of Destruction (N000) (if you want), Dummy Unit (n001), Dummy Unit (Alternate Attachment) (n002), Dummy Unit (Alternate Attachment -90 Roll) (n003), Dummy Unit - Thanatos's Shadow) (n004)
-Go to the Trigger Editor and copy TT (if you don't have it already), CSData and CSSafety (copy them if you don't have ), UtilityFuncs (some "BJ-like" functions, copy them if you don't have), SwordBarrage, InfernalImpact, PhantomSwing, InfernalStigma then change the raw id of the abilities, units in the globals.
Credits
- thanks Tinki3 for the test map template
- thanks Vexorian for CSData and CSSafety
- thanks Cohadar for TT
- Sword model by HappyTauren (hiveworkshop) (its original name is Old Sword)
- thanks WILL THE ALMIGHTY (Wc3campaigns) for the explosion effect (it's actually his "Laser" )
- the model ThanatosLoD (I have renamed it ), I really don't remember the creator of this, so if anyone know, please tell me.
------------
EDIT: attached the map.
EDIT2: update the ultimate. I have a little trouble with the explosion effect but I think it's fine now
EDIT3: update the Import Instruction
Thanatos
the
God of Death
the
God of Death
-------------------------------------
This pack has 4 spells, they are MUI, lagless (for me), leakless (I think), vJass. Also they have a good visual effect.
-------------------------------------
First spell: Sword Barrage
- Description:
- Screenshot:A barrage of phantom swords that damages enemy units within the target area.
JASS:
scope SwordBarrage initializer Init
globals
private constant integer AbilId = 039;A001039; //raw id of the spell
private constant integer DummyId = 039;n002039; //raw id of the dummy unit (requires: dummy.mdx )
private constant string SwordModel = "GreatSwordRibbon.mdx" //an imported attachment model - model of the swords
private constant string SwordHitSFX = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" //sfx on hit
private constant string SwordHitSFX_A = "origin" //attachment point for sfx on hit
private constant attacktype ATKTYPE = ATTACK_TYPE_CHAOS
private constant damagetype DMGTYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEPTYPE = WEAPON_TYPE_METAL_HEAVY_SLICE
//-----------------------------------
private group HITSFX = CreateGroup()
endglobals
private function GetNumberSwords takes integer lvl returns integer
return (4+2*lvl)
endfunction
private function GetDamagePerSword takes integer lvl returns real
return (75.+25*lvl)
endfunction
private function GetBarrageAOE takes integer lvl returns real
return 250. //if you modify this value, you should also modify the "Stats - Area of Effect" of the ability
endfunction
private function GetSwordDamageAOE takes integer lvl returns real
return 100.
endfunction
//=================================
private struct data
unit c
unit d
effect e
real dx
real dy
real x
real y
real angle
real dist
real dmg
real aoe
integer tick
boolean spread = true
real sin
endstruct
private function SwordF takes nothing returns boolean
local data d = TT_GetData()
local unit f = GetFilterUnit()
local boolean ok = ( GetWidgetLife(f) > 0.405 and IsUnitEnemy(f,GetOwningPlayer(d.c)))
set f = null
return ok
endfunction
private function HitSFXSkip takes unit u returns nothing
call TriggerSleepAction(0.1)
call GroupRemoveUnit(HITSFX,u)
endfunction
private function DestroyEffectDelay takes effect e , real wait returns nothing
call TriggerSleepAction(wait)
call DestroyEffect(e)
endfunction
private function SwordE takes nothing returns boolean
local data d = TT_GetData()
local real x
local real y
local real z
local real x2
local real y2
local real z2
local integer in
local group g
local unit p
if not d.spread then
if d.tick == 0 then
set g = GetUnitsInRange( GetUnitX(d.d), GetUnitY(d.d) , d.aoe , Condition( function SwordF ) )
loop
set p = FirstOfGroup(g)
exitwhen p == null
call GroupRemoveUnit(g,p)
if not IsUnitInGroup(p,HITSFX) then
call DestroyEffect( AddSpecialEffectTarget(SwordHitSFX ,p,SwordHitSFX_A ) )
call GroupAddUnit(HITSFX,p)
call HitSFXSkip.execute(p)
endif
call UnitDamageTarget(d.c,p, d.dmg, false, true, ATKTYPE, DMGTYPE ,ConvertWeaponType(6) )
endloop
call ReleaseGroup(g)
set g = null
call DestroyEffectDelay.execute(d.e,0.5)
call KillUnit(d.d)
call d.destroy()
return true
endif
set d.tick = d.tick - 1
set x = GetPPX( d.x, -1 * d.dist * Sin( d.sin * (d.tick-1)* bj_DEGTORAD ) , d.angle )
set y = GetPPY( d.y, -1 * d.dist * Sin( d.sin * (d.tick-1)* bj_DEGTORAD ) , d.angle )
set x2 = GetPPX( d.x, -1 * d.dist * Sin( d.sin * d.tick * bj_DEGTORAD ) , d.angle )
set y2 = GetPPY( d.y, -1 * d.dist * Sin( d.sin * d.tick * bj_DEGTORAD ) , d.angle )
set z = 300. * Sin( (d.sin*2) * (d.tick-1) * bj_DEGTORAD ) + 2.4 * d.tick + 30
set z2 = 300. * Sin( (d.sin*2) * d.tick * bj_DEGTORAD ) + 2.4 * d.tick + 30
call SetUnitX(d.d, x2 )
call SetUnitY(d.d, y2 )
call SetUnitZ( d.d, z2 )
call SetUnitAnimationByIndex(d.d, R2I(bj_RADTODEG*Atan2((z-z2), SquareRoot((x-x2)*(x-x2) + (y-y2)*(y-y2)) + 0.5) + 90 ) )
else
if d.tick == 0 then
set d.angle = AngleLocXY(d.dx, d.dy, d.x,d.y)
set d.dist = DistanceLocXY(d.dx, d.dy, d.x,d.y)
call SetUnitFacing(d.d,d.angle)
call SetUnitBlendTime(d.d,0.15)
call SetUnitAnimationByIndex(d.d,180)
call SetUnitVertexColor(d.d,255,255,255,255)
endif
if d.tick == -5 then
set d.spread = false
call SetUnitBlendTime(d.d,0.0)
set d.tick = 25
set d.sin = 90. / d.tick
call SetUnitVertexColor(d.d,255,255,255,255)
return false
endif
set d.tick = d.tick - 1
if d.tick > 0 then
set d.dx = GetPPX( d.dx, 30. , d.angle )
set d.dy = GetPPY( d.dy, 30. , d.angle )
call SetUnitX(d.d,d.dx)
call SetUnitY(d.d,d.dy)
endif
if d.tick >= 0 then
call SetUnitVertexColor(d.d,255,255,255,R2I(255*(10-d.tick)*0.1))
endif
endif
return false
endfunction
private function Sword takes unit c,real cx, real cy, real x, real y, real dmg, real aoe, real angle returns nothing
local data d = data.create()
set d.c = c
set d.dx = cx
set d.dy = cy
set d.angle = angle
set d.x = x
set d.y = y
set d.dmg = dmg
set d.aoe = aoe
set d.d = CreateUnit(Player(15), DummyId ,d.dx ,d.dy , d.angle )
call SetUnitScale(d.d,0.6,0.6,0.6)
call SetUnitVertexColor(d.d,255,255,255,0)
set d.e = AddSpecialEffectTarget( SwordModel ,d.d,"origin")
set d.tick = 10
call SetUnitZ( d.d, 100. )
call TT_Start( function SwordE , d )
endfunction
private function Act takes nothing returns nothing
local unit c = GetTriggerUnit()
local location loc = GetSpellTargetLoc()
local real x = GetLocationX(loc)
local real y = GetLocationY(loc)
local real cx = GetUnitX(c)
local real cy = GetUnitY(c)
local integer lvl = GetUnitAbilityLevel(c,AbilId)
local real dmg = GetDamagePerSword(lvl)
local real aoe = GetSwordDamageAOE(lvl)
local integer count = GetNumberSwords(lvl)
local real spreadang = 360. / count
local real barrAOE = GetBarrageAOE(lvl)
local real dist
local real ang
local integer i = 1
loop
exitwhen i > count
set dist = GetRandomReal(50. , barrAOE - 50. )
set ang = GetRandomReal( 0, 359. )
call Sword( c, cx, cy, GetPPX(x, dist, ang ), GetPPY(y, dist, ang ), dmg, aoe, spreadang * i )
set i = i + 1
endloop
call RemoveLocation(loc)
set loc = null
set c = null
endfunction
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == AbilId
endfunction
public function Init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( t, function Act )
call TriggerAddCondition( t, Condition( function Cond ) )
set t = null
endfunction
endscope
Second spell: Infernal Impact (It needs a different name )
- Description:
- Screenshot:Thanatos channels for 2 seconds and throws his blade spinning toward a direction, damages enemies on a line at 700 range and returns to his hand.
Each enemy units on the effective range being hit increases damage by +10% per target.
JASS:
scope InfernalImpact initializer Init
globals
private constant integer AbilId = 039;A002039;//raw id of the spell
private constant integer SwordAttachementAbilId = 039;A000039; //ability has the attachment of Thanatos's Sword
private constant integer DummyId = 039;n003039; //raw id of the dummy unit (requires: dummy.mdx )
private constant string SwordModel = "GreatSwordRibbon.mdx" //an imported attachment model - model of the swords
private constant real SwordDamageAOE = 300. //range for damaging
private constant string SwordHitSFX = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" //on hit sfx
private constant string SwordHitSFX_A = "origin" //attachment point of on hit sfx
private constant attacktype ATKTYPE = ATTACK_TYPE_CHAOS
private constant damagetype DMGTYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEPTYPE = WEAPON_TYPE_METAL_HEAVY_SLICE
endglobals
private function GetInitialDamage takes integer lvl returns real
return ( 50. * lvl )
endfunction
private function GetDamageIncrease takes integer lvl returns real
return 0.1
endfunction
//======================
private struct data
unit c
real cx
real cy
real ang
real dmg
real dmginc
group g
group hit
integer tick
integer tickmax
endstruct
private struct sdata
real trans
effect sfx
integer index
endstruct
private function InfernalImpactFilter takes nothing returns boolean
local data d = TT_GetData()
local unit f = GetFilterUnit()
local boolean ok = false
if GetWidgetLife(f) > 0.405 then
if IsUnitEnemy(f,GetOwningPlayer(d.c)) then
if not IsUnitInGroup(f,d.hit) then
set ok = true
endif
endif
endif
set f = null
return ok
endfunction
private function InfernalImpactEF takes nothing returns nothing
local data d = TT_GetData()
local unit e = GetEnumUnit()
local sdata sd = GetUnitUserData(e)
set sd.trans = sd.trans - 0.1
call SetUnitVertexColor( e, 255,255,255, R2I(180 * sd.trans ) )
if sd.trans <= 0 then
call DestroyEffect(sd.sfx)
call sd.destroy()
call GroupRemoveUnit(d.g,e)
call KillUnit(e)
endif
set e = null
endfunction
private function InfernalImpactE takes nothing returns boolean
local data d = TT_GetData()
local sdata sd
local unit u
local real cx
local real cy
local real cf
local group g
local unit p
local sound soundHandle
if ModuloInteger(d.tick - 7 , 20 ) == 0 then
set soundHandle = CreateSound("Units\\Orc\\HeroBladeMaster\\BladeMasterWhirlwind.wav", false, true, true, 12700, 12700, "")
call SetSoundPosition(soundHandle, d.cx, d.cy, 0 )
call StartSound(soundHandle)
call KillSoundWhenDone(soundHandle)
set soundHandle = null
endif
if d.tick == (d.tickmax-11) + 1 then
call SetUnitTimeScale(d.c,0.)
endif
if d.tick > 0 then
if d.tick == (d.tickmax-1)/2 + 1 then
set d.ang = d.ang + 180
endif
if d.tick < (d.tickmax-1)/2 + 1 then
set d.ang = AngleLocXY( d.cx, d.cy, GetUnitX(d.c), GetUnitY(d.c) )
endif
set d.cx = GetPPX( d.cx, 15, d.ang )
set d.cy = GetPPY( d.cy, 15, d.ang )
set cf = d.ang+(d.tickmax-d.tick)*20
set cx = GetPPX( d.cx, 0. , cf )
set cy = GetPPY( d.cy, 0. , cf )
set u = CreateUnit( GetOwningPlayer(d.c) , DummyId , cx, cy, cf - 90 )
call SetUnitVertexColor(u,255,255,255,180)
call SetUnitZ( u , 60. )
set sd = sdata.create()
set sd.index = d.tick
set sd.trans = 1
set sd.sfx = AddSpecialEffectTarget(SwordModel, u, "origin" )
call SetUnitUserData(u,sd)
call GroupAddUnit(d.g, u )
set g = GetUnitsInRange(cx,cy, SwordDamageAOE ,Condition( function InfernalImpactFilter ) )
loop
set p = FirstOfGroup(g)
exitwhen p == null
call GroupRemoveUnit(g,p)
if IsUnitInFront(p,u) then
call DestroyEffect( AddSpecialEffectTarget(SwordHitSFX ,p,SwordHitSFX_A ) )
call UnitDamageTarget(d.c, p , d.dmg , false, true, ATKTYPE, DMGTYPE, WEPTYPE )
call GroupAddUnit(d.hit,p)
set d.dmg = d.dmg * ( 1 + d.dmginc )
endif
endloop
call ReleaseGroup(g)
set g = null
set u = null
//set d.ang = d.ang + 20.
set d.tick = d.tick - 1
endif
call ForGroup( d.g, function InfernalImpactEF )
if FirstOfGroup(d.g) == null then
call SetUnitTimeScale(d.c,1.)
call UnitAddAbility(d.c,SwordAttachementAbilId)
call ReleaseGroup(d.g)
call ReleaseGroup(d.hit)
call d.destroy()
return true
endif
return false
endfunction
function Act takes nothing returns nothing
local unit c = GetTriggerUnit()
local location loc = GetSpellTargetLoc()
local real tx = GetLocationX(loc)
local real ty = GetLocationY(loc)
local integer lvl = GetUnitAbilityLevel(c,AbilId)
local data d = data.create()
set d.c = c
set d.cx = GetUnitX(c)
set d.cy = GetUnitY(c)
set d.hit = NewGroup()
set d.g = NewGroup()
set d.dmg = GetInitialDamage(lvl)
set d.dmginc = GetDamageIncrease(lvl)
call UnitRemoveAbility(c, SwordAttachementAbilId )
set d.ang = AngleLocXY( d.cx, d.cy, tx, ty )
set d.tick = 96 + 1
set d.tickmax = d.tick
call TT_StartEx( function InfernalImpactE, d, 0.02 )
endfunction
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == AbilId
endfunction
public function Init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( t, function Act )
call TriggerAddCondition( t, Condition( function Cond ) )
set t = null
endfunction
endscope
Third spell: Phantom Swing
- Description:
- Screenshot:Every time Thanatos attacks, he has a chance to summon phantom swords that spin around him. Theses swords damages directly into the soul of enemies, destroying their mana and dealing 1.5 damage per destroyed mana point.
Enemies who don't have mana will take damage equal to this amount.
Cooldown: 1 seconds.
JASS:
scope PhantomSwingCast initializer Init
globals
private constant integer AbilId = 039;A003039; //raw id of the spell
private constant integer DummyId = 039;n003039; //raw id of the dummy (requires: dummy.mdx )
private constant string SwordModel = "GreatSwordRibbon.mdx" //an imported attachment model - model of the swords
private constant real SwordDamageAOE = 300. //range for damaging
private constant string SwordHitSFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"//on hit sfx with mana break
private constant string SwordHitSFX_A = "origin" //attachment point for on hit sfx with mana break
private constant string SwordHitSFX2 = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl"//on hit sfx without mana break
private constant string SwordHitSFX2_A = "origin" //attachment point for on hit sfx without mana break
private constant attacktype ATKTYPE = ATTACK_TYPE_CHAOS
private constant damagetype DMGTYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEPTYPE = WEAPON_TYPE_METAL_HEAVY_SLICE
//-----------------------
private group InCooldown = CreateGroup()
endglobals
private function GetChance takes integer lvl returns integer
return (8+2*lvl)
endfunction
private function GetManaBreakAmount takes integer lvl returns real
return (50.+25*lvl)
endfunction
private function GetDamagePerMPBreak takes integer lvl returns real
return 1.5
endfunction
private function GetCooldown takes integer lvl returns real
return 1.
endfunction
//=============================
private struct data
unit c
real cx
real cy
real dmg
real mnbr
real ang
group g
group hit
integer tick
integer tickmax
endstruct
private struct sdata
real trans
effect sfx
endstruct
private function PhantomSwingFilter takes nothing returns boolean
local data d = TT_GetData()
local unit f = GetFilterUnit()
local boolean ok = false
if GetWidgetLife(f) > 0.405 then
if IsUnitEnemy(f,GetOwningPlayer(d.c)) then
if not IsUnitInGroup(f,d.hit) then
set ok = true
endif
endif
endif
set f = null
return ok
endfunction
private function PhantomSwingEF takes nothing returns nothing
local data d = TT_GetData()
local unit e = GetEnumUnit()
local sdata sd = GetUnitUserData(e)
set sd.trans = sd.trans - 0.1
call SetUnitVertexColor( e, 255,255,255, R2I(160 * sd.trans ) )
if sd.trans <= 0 then
call DestroyEffect(sd.sfx)
call sd.destroy()
call GroupRemoveUnit(d.g,e)
call KillUnit(e)
endif
set e = null
endfunction
private function PhantomSwingE takes nothing returns boolean
local data d = TT_GetData()
local sdata sd
local unit u
local real cx
local real cy
local real cf
local group g
local unit p
local real pMP
local real dmg
if d.tick > 0 then
set d.cx = GetUnitX(d.c)
set d.cy = GetUnitY(d.c)
set cf = d.ang+(d.tickmax-d.tick)*20
set cx = GetPPX( d.cx, 50. , cf )
set cy = GetPPY( d.cy, 50. , cf )
set u = CreateUnit( GetOwningPlayer(d.c) , DummyId , cx, cy, cf )
call SetUnitScale(u,1.,1.,1.)
call SetUnitZ( u , 60. )
set sd = sdata.create()
set sd.trans = 1
set sd.sfx = AddSpecialEffectTarget( SwordModel , u, "origin" )
call SetUnitVertexColor(u,255,255,255,160)
call SetUnitUserData(u,sd)
call GroupAddUnit(d.g, u )
set g = GetUnitsInRange(cx,cy, SwordDamageAOE ,Condition( function PhantomSwingFilter ) )
loop
set p = FirstOfGroup(g)
exitwhen p == null
call GroupRemoveUnit(g,p)
if IsUnitInFront(p,u) then
if GetUnitState(p,UNIT_STATE_MAX_MANA) > 0 then
call DestroyEffect( AddSpecialEffectTarget(SwordHitSFX ,p,SwordHitSFX_A ) )
set pMP = GetUnitState(p,UNIT_STATE_MANA)
if pMP > d.mnbr then
set dmg = d.mnbr * d.dmg
set pMP = pMP - d.mnbr
else
set dmg = pMP * d.dmg
set pMP = 0
endif
call SetUnitState(p,UNIT_STATE_MANA,pMP)
call UnitDamageTarget(d.c, p , dmg , false, true, ATKTYPE, DMGTYPE, WEPTYPE )
else
call DestroyEffect( AddSpecialEffectTarget(SwordHitSFX2 ,p,SwordHitSFX2_A ) )
call UnitDamageTarget(d.c, p , d.mnbr , false, true, ATKTYPE, DMGTYPE, WEPTYPE )
endif
call GroupAddUnit(d.hit,p)
endif
endloop
call ReleaseGroup(g)
set g = null
set u = null
set d.tick = d.tick - 1
endif
call ForGroup( d.g, function PhantomSwingEF )
if FirstOfGroup(d.g) == null then
call ReleaseGroup(d.g)
call ReleaseGroup(d.hit)
call d.destroy()
return true
endif
return false
endfunction
private function Act takes nothing returns nothing
local unit c = GetAttacker()
local integer lvl = GetUnitAbilityLevel(c,AbilId)
local data d
local sound soundHandle
if GetRandomInt( 1, 100 ) > GetChance(lvl) then
set c = null
return
endif
set soundHandle = CreateSound("Units\\Orc\\HeroBladeMaster\\BladeMasterWhirlwind.wav", false, true, true, 12700, 12700, "")
call SetSoundPosition(soundHandle, GetUnitX(c), GetUnitY(c), 0 )
call StartSound(soundHandle)
call KillSoundWhenDone(soundHandle)
set soundHandle = null
set d = data.create()
set d.c = c
set d.cx = GetUnitX(c)
set d.cy = GetUnitY(c)
set d.mnbr = GetManaBreakAmount(lvl)
set d.dmg = GetDamagePerMPBreak(lvl)
set d.ang = GetUnitFacing(c)
set d.g = NewGroup()
set d.hit = NewGroup()
set d.tick = 18 + 1
set d.tickmax = d.tick
call TT_StartEx( function PhantomSwingE, d, 0.03 )
call GroupAddUnit(InCooldown,c)
call TriggerSleepAction( GetCooldown(lvl) )
call GroupRemoveUnit(InCooldown,c)
set c = null
endfunction
private function Cond takes nothing returns boolean
return GetUnitAbilityLevel( GetAttacker(), AbilId ) > 0 and not IsUnitInGroup( GetAttacker() , InCooldown )
endfunction
public function Init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddAction( t, function Act )
call TriggerAddCondition( t, Condition( function Cond ) )
set t = null
endfunction
endscope
Ultimate spell: Infernal Stigma
- Description:
(Should I call it "Marks of Chaos" instead ? )With an etremely fast glide, Thanatos moves around the battlefield, damages and engraves enemy units on his wake with Marks of Abyss. He then leap back to previous position with lightning-fast movement and damages all enemy units who bear the Marks of Abyss.
- Screenshot:
JASS:
scope InfernalStigmaCast initializer Init
globals
private constant integer AbilId = 039;A004039; //raw id of the spell
private constant integer DummyId = 039;n001039; //raw id of the dummy (requires: dummy.mdx )
private constant integer SwordAttachementAbilId = 039;A000039; //ability has the attachment of Thanatos's Sword
private constant string WeaponAttachmentSFX = "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl" //the effect attached to weapon of Thanatos when he's casting this spell
private constant string MarkofChaosSFXpath = "MarkOfAbyss.mdx" //Mark of Chaos's sfx path
private constant string MarkofChaosExplodeSFXpath = "MarkOfAbyssExplode.mdx" //Mark of Chaos explosion's sfx path
private constant integer ThanatosShadowId = 039;n004039; //raw id of dummy unit - Thanatos's Shaodw
private constant string StrikeHitSFX = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" //effect on unit who are struck
private constant string StrikeHitSFX_A = "origin" //attachment point of the above effect
private constant string ExplodeHitSFX = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl" //effect on unit who are hit by the explosions
private constant string ExplodeHitSFX_A = "origin" //attachment point of the above effect
private constant string MovesSFX = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl" //sfx when he moves
private constant attacktype ATKTYPE = ATTACK_TYPE_CHAOS
private constant damagetype DMGTYPE = DAMAGE_TYPE_NORMAL
private constant damagetype DMGTYPE2 = DAMAGE_TYPE_MAGIC
private constant weapontype WEPTYPE = WEAPON_TYPE_METAL_HEAVY_SLICE
endglobals
private function GetStrikeDamage takes unit c, integer lvl returns real
return GetHeroAgi(c,true) * ( 1.+lvl )
endfunction
private function GetExplodeDamage takes integer lvl returns real
return ( 50.+50*lvl )
endfunction
private function GetTargetCount takes integer lvl returns integer
return 4+2*lvl
endfunction
//=========================
private struct data
unit c
unit a
unit d
unit u
real cx
real cy
real dx
real dy
group g
effect ef
unit array m [10]
unit array md [10]
effect array me [10]
integer mk = -1
integer mkm = -1
boolean finish = false
real dist
real angle
real dmg
real dmgexp
integer lvl
integer tick
integer count
boolean pau = false
endstruct
private function InfernalStigmaF takes nothing returns boolean
local data d = TT_GetData()
local unit f = GetFilterUnit()
local boolean ok = false
if GetWidgetLife(f) > 0.405 then
if IsUnitEnemy(f,GetOwningPlayer(d.c)) then
if not IsUnitInGroup(f,d.g) then
set ok = true
endif
endif
endif
return ok
endfunction
private function InfernalStigmaE takes nothing returns boolean
local data d = TT_GetData()
local integer i
local integer array ani
local real dist
local group g
local unit p
if not d.pau then
call PauseUnit(d.c,true)
call SetUnitInvulnerable(d.c,true)
call SetUnitPathing(d.c,false)
call IssueImmediateOrder(d.c,"stop")
call SetUnitVertexColor(d.c,255,255,255,127)
set d.pau = true
endif
//----
if d.finish then
if d.tick <= -1 then
if d.tick == -1 then
call SetUnitX(d.c,d.cx)
call SetUnitY(d.c,d.cy)
call SetUnitFacing(d.c, AngleLocXY(d.cx,d.cy,d.dx,d.dy) )
call SetUnitAnimation(d.c,"Spell")
call QueueUnitAnimation(d.c,"Ready")
endif
if d.tick <= -12 then
call ReleaseGroup(d.g)
set g = NewGroup()
set i = d.mkm
loop
exitwhen i <= -1
call PauseUnit(d.m<i>,false)
call SetUnitAnimationByIndex(d.md[d.mk],90)
call DestroyEffect( AddSpecialEffectTarget(MarkofChaosExplodeSFXpath,d.md<i>,"origin") )
call DestroyEffect(d.me<i>)
call UnitApplyTimedLife(d.md<i>,039;BTLF039;,1.0)
call EnumUnitsInRange( g, GetUnitX(d.m<i>), GetUnitY(d.m<i>), 300. , Condition( function InfernalStigmaF ) )
loop
set p = FirstOfGroup(g)
exitwhen p == null
call GroupRemoveUnit(g,p)
if ExplodeHitSFX != null then
call DestroyEffect( AddSpecialEffectTarget(ExplodeHitSFX,p,ExplodeHitSFX_A) )
endif
call UnitDamageTarget(d.c,p,d.dmgexp,false,true,ATKTYPE,DMGTYPE2,null)
endloop
set p = null
set i = i - 1
endloop
call ReleaseGroup(g)
set g = null
call DestroyEffect(d.ef)
call PauseUnit(d.c,false)
call SetUnitTimeScale(d.c,1.0)
call SetUnitVertexColor(d.c,255,255,255,255)
call SetUnitInvulnerable(d.c,false)
call SetUnitPathing(d.c,true)
call d.destroy()
return true
endif
else
call SetUnitX(d.c, GetUnitX(d.m[d.mk]) )
call SetUnitY(d.c, GetUnitY(d.m[d.mk]) )
set d.mk = d.mk - 1
endif
else
if d.a != null then
if d.tick == 10 then
set d.angle = GetRandomReal(1.,360.)
call SetUnitFacing(d.c,d.angle+180.)
call SetUnitX(d.c, GetPPX(GetUnitX(d.a), 150. , d.angle) )
call SetUnitY(d.c, GetPPY(GetUnitY(d.a), 150. , d.angle) )
call DestroyEffect( AddSpecialEffect(MovesSFX,GetUnitX(d.c),GetUnitY(d.c)) )
set ani[0] = 1
set ani[1] = 2
set ani[2] = 7
set i = GetRandomInt(0,2)
call SetUnitAnimationByIndex(d.c, ani<i> )
set d.u = CreateUnit(GetOwningPlayer(d.c),ThanatosShadowId, GetUnitX(d.c), GetUnitY(d.c), GetUnitFacing(d.c) )
call UnitAddAbility(d.u,SwordAttachementAbilId)
call SetUnitVertexColor(d.u,255,255,255,0)
call SetUnitAnimationByIndex(d.u,ani<i>)
call QueueUnitAnimation(d.u,"Ready")
endif
call SetUnitFacing(d.c, AngleUnits(d.c,d.a) )
call SetUnitFacing(d.u, AngleUnits(d.u,d.a) )
if d.tick == -2 then
call DestroyEffect( AddSpecialEffect(MovesSFX,GetUnitX(d.c),GetUnitY(d.c)) )
set d.mk = d.mk + 1
set d.mkm = d.mk
set d.m[d.mk] = d.a
set d.md[d.mk] = CreateUnit(Player(15), DummyId, GetUnitX(d.a), GetUnitY(d.a) , d.angle)
call SetUnitAnimationByIndex(d.md[d.mk],30+120*GetRandomInt(0,1))
call SetUnitScale(d.md[d.mk],2.,2.,2.)
call SetUnitZ(d.md[d.mk],100.)
set d.me[d.mk] = AddSpecialEffectTarget(MarkofChaosSFXpath,d.md[d.mk],"origin")
call PauseUnit(d.a,true)
call GroupAddUnit(d.g,d.a)
call UnitDamageTarget(d.c,d.a,d.dmg,false,true,ATKTYPE,DMGTYPE,WEPTYPE )
call DestroyEffect( AddSpecialEffectTarget(StrikeHitSFX,d.a,StrikeHitSFX_A) )
endif
if d.tick == -5 then
if d.count > 0 then
set g = GetUnitsInRange( GetUnitX(d.a), GetUnitY(d.a), 500. , Condition( function InfernalStigmaF ) )
set d.a = GroupPickRandomUnit(g)
call ReleaseGroup(g)
set g = null
set d.count = d.count - 1
endif
if d.a == null or d.count == 0 then
set d.finish = true
set d.tick = d.mk
set d.mkm = d.mk
else
set d.tick = 11
endif
call SetUnitVertexColor(d.u,255,255,255,127)
call UnitApplyTimedLife(d.u,039;BTLF039;,0.4)
endif
endif
endif
set i = d.mkm
loop
exitwhen i <= -1
call SetUnitX(d.md<i>,GetUnitX(d.m<i>))
call SetUnitY(d.md<i>,GetUnitY(d.m<i>))
set i = i - 1
endloop
set d.tick = d.tick - 1
return false
endfunction
private function Act takes nothing returns nothing
local data d = data.create()
set d.c = GetTriggerUnit()
set d.a = GetSpellTargetUnit()
set d.g = NewGroup()
set d.tick = 10
set d.cx = GetUnitX(d.c)
set d.cy = GetUnitY(d.c)
set d.lvl = GetUnitAbilityLevel(d.c,AbilId)
set d.dmg = GetStrikeDamage(d.c,d.lvl)
set d.dmgexp = GetExplodeDamage(d.lvl)
set d.count = GetTargetCount(d.lvl)
set d.ef = AddSpecialEffectTarget(WeaponAttachmentSFX,d.c,"weapon")
set d.dx = GetUnitX(d.a)
set d.dy = GetUnitY(d.a)
call DestroyEffect( AddSpecialEffect(MovesSFX,GetUnitX(d.c),GetUnitY(d.c) ))
call TT_Start( function InfernalStigmaE , d )
endfunction
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == AbilId
endfunction
public function Init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( t, function Act )
call TriggerAddCondition( t, Condition( function Cond ) )
set t = null
endfunction
endscope</i></i></i></i></i></i></i></i></i></i></i></i>
Import Instruction
-Import all nessessary models
-Go to the Object Editor \ Abilities, copy Thanatos's Sword (A000), Sword Barrage (A001), Infernal Impact (A002), Phantom Swing (A003), Infernal Stigma (A004)
-Then at Object Editor \ Units, copy Lord of Destruction (N000) (if you want), Dummy Unit (n001), Dummy Unit (Alternate Attachment) (n002), Dummy Unit (Alternate Attachment -90 Roll) (n003), Dummy Unit - Thanatos's Shadow) (n004)
-Go to the Trigger Editor and copy TT (if you don't have it already), CSData and CSSafety (copy them if you don't have ), UtilityFuncs (some "BJ-like" functions, copy them if you don't have), SwordBarrage, InfernalImpact, PhantomSwing, InfernalStigma then change the raw id of the abilities, units in the globals.
Credits
- thanks Tinki3 for the test map template
- thanks Vexorian for CSData and CSSafety
- thanks Cohadar for TT
- Sword model by HappyTauren (hiveworkshop) (its original name is Old Sword)
- thanks WILL THE ALMIGHTY (Wc3campaigns) for the explosion effect (it's actually his "Laser" )
- the model ThanatosLoD (I have renamed it ), I really don't remember the creator of this, so if anyone know, please tell me.
------------
EDIT: attached the map.
EDIT2: update the ultimate. I have a little trouble with the explosion effect but I think it's fine now
EDIT3: update the Import Instruction