cr4xzZz
Also known as azwraith_ftL.
- Reaction score
- 51
Unholy Pervasion
A spell from my map - Mini Ashenvale Arena.
Idea came from Cohadar's Ancestral Spirits, so this is why they look similar.
GUI/JASS/vJASS? vJASS.
MUI? Yes.
Leakless? Yes.
Lagless? Yes. (It's normal to lag on first cast)
Follows JESP? I couldn't find a way to make it fully JESP... Only two arguments aren't.
Requires?
- TT v3.4 by Cohadar
- JASS NewGen Pack v1.5a
Description:
Creates spirits that will follow you everywhere but will return if they go too far away. The spirits will attack all enemies they acquire, while in the same time, enemies will be slowed greatly. Spirits cannot be killed unless they are Purged or targeted by a really powerful spell. Attacked spirits will explode violently, sending dark waves everywhere and burning mana. Duration, number of spirits, strength of the slow and the damaging from each explosion increases each level. The slow lasts as long as the spell continues, even if all spirits are killed.
Code:
JASS:
scope UnholyPervasion initializer DoIt
//===========================================================================
// Unholy Pervasion by cr4xzZz (also known as azwraith_ftL)
// Date: August 13, 2008
// Version: 1[1].0b
//===========================================================================
// C O N F I G U R A T I O N M E N U
//===========================================================================
globals
// Raw code of the Summer Storm ability.
private constant integer AID_UNHOLY_PERVASION = 039;A000039;
// Raw code of the Wave ability (Unholy Pervasion Wave in Object Editor).
private constant integer AID_UNHOLY_PERVASION_WAVE = 039;A001039;
// String for casting the Wave ability (Unholy Pervasion Wave in Object Editor).
private constant string SID_WAVE = "breathoffire"
// Raw code of the Slow ability (Unholy Pervasion Slow in Object Editor).
private constant integer AID_UNHOLY_PERVASION_SLOW = 039;A002039;
// String for casting the Slow ability (Unholy Pervasion Slow in Object Editor).
private constant string SID_SLOW = "slow"
// Raw code of the Spirit unit (Unholy Pervasion Spirit in Object Editor).
private constant integer UID_UNHOLY_PERVASION_SPIRIT = 039;h000039;
// Raw code of the Dummy Unit.
private constant integer UID_DUMMY = 039;u001039;
// What kind of order the spirit to issue when it has to move periodically.
// Note that it issues an order on a location, not a unit.
private constant string SID_ORDER = "attack"
// Period between casting AID_UNHOLY_PERVASION_SLOW and movement of spirits.
private constant real PERIOD = 1.
// Effect attached to the caster during the effect of the ability.
private constant string SFX_ATTACH = "Abilities\\Spells\\Other\\HowlOfTerror\\HowlTarget.mdl"
// Attachment point for the SFX_ATTACH special effect.
private constant string AP_ATTACH = "chest"
// Effect created when a spirit explodes.
private constant string SFX_EXPLODE = "Abilities\\Spells\\Items\\AIil\\AIilTarget.mdl"
// One of these two effects will be created on enemies randomly every time Slow is casted (just some eyecandy).
private constant string SFX_ONE = "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl"
private constant string SFX_TWO = "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl"
// Attachment point of the two effects above.
private constant string AP_ONETWO = "origin"
endglobals
// I have included the caster below because someone might want to base values on his attributes.
// Number of Spirits that are created.
private function SPIRIT_NUMBER takes unit cast, integer lvl returns integer
return 1 + (1 * lvl)
endfunction
// Red colouring of the Spirits.
private function SPIRIT_RED takes unit cast, integer lvl returns integer
return 255
endfunction
// Green colouring of the Spirits.
private function SPIRIT_GREEN takes unit cast, integer lvl returns integer
return 255
endfunction
// Blue colouring of the Spirits.
private function SPIRIT_BLUE takes unit cast, integer lvl returns integer
return 255
endfunction
// Transparency of the Spirits.
private function SPIRIT_ALPHA takes unit cast, integer lvl returns integer
return 128
endfunction
// Max distance for the spirits. If they pass it, they will be instantly returned to the caster.
private function SPIRIT_DISTANCE takes unit cast, integer lvl returns real
return 450. + (25. * lvl)
endfunction
// Mana burned when a Spirit explodes.
private constant function MANA_BURN takes nothing returns real
return 50.
endfunction
// AoE in which the units get their mana burned when a Spirit explodes.
private constant function MANA_AOE takes nothing returns real
return 300.
endfunction
// In this AoE all enemies will be slowed every X seconds (PERIOD).
private function AOE takes unit cast, integer lvl returns real
return 450. + (25. * lvl)
endfunction
// Duration of the spell.
private function DURATION takes unit cast, integer lvl returns real
return 5. * lvl
endfunction
//===========================================================================
// E N D O F C O N F I G U R A T I O N M E N U
//===========================================================================
private struct Data
unit cast
integer lvl
unit array spirit[100] // if you are crazy enough to create more than 100 spirits...
integer fps = R2I(PERIOD / TT_PERIOD)
integer ticks
effect sfx
method onDestroy takes nothing returns nothing
local integer i = 0
call DestroyEffect(.sfx)
loop
exitwhen .spirit<i> == null
call KillUnit(.spirit<i>)
set .spirit<i> = null
set i = i + 1
endloop
endmethod
endstruct
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID_UNHOLY_PERVASION
endfunction
private function Enum takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) then
if IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) == false then
if IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false then
return true
endif
endif
endif
return false
endfunction
private function Attack takes nothing returns boolean
local unit first = null
local group gr = null
local unit at = null
local integer i = 1
local real x
local real y
if GetUnitTypeId(GetTriggerUnit()) == UID_UNHOLY_PERVASION_SPIRIT and IsUnitEnemy(GetAttacker(), GetOwningPlayer(GetTriggerUnit())) then
set at = GetTriggerUnit()
set gr = CreateGroup()
call GroupEnumUnitsInRange(gr, GetUnitX(at), GetUnitY(at), MANA_AOE(), Condition(function Enum))
loop
set first = FirstOfGroup(gr)
exitwhen first == null
call SetUnitState(first, UNIT_STATE_MANA, GetUnitState(first, UNIT_STATE_MANA) - MANA_BURN())
call GroupRemoveUnit(gr, first)
endloop
call DestroyGroup(gr)
loop
exitwhen i > 8
set first = CreateUnit(GetOwningPlayer(at), UID_DUMMY, GetUnitX(at), GetUnitY(at), 0.)
call UnitAddAbility(first, AID_UNHOLY_PERVASION_WAVE)
set x = GetUnitX(at) + 200. * Cos((45. * i) * bj_DEGTORAD)
set y = GetUnitY(at) + 200. * Sin((45. * i) * bj_DEGTORAD)
call IssuePointOrder(first, SID_WAVE, x, y)
call UnitApplyTimedLife(first, 039;BTLF039;, 2.)
set i = i + 1
endloop
call KillUnit(at)
set gr = null
set first = null
set at = null
return true
endif
return false
endfunction
private function Callback takes nothing returns boolean
local Data d = TT_GetData()
local integer i = 0
local real x = GetUnitX(d.cast)
local real y = GetUnitY(d.cast)
local real dx
local real dy
local real sr
local group gr = null
local unit first = null
set d.ticks = d.ticks - 1
if GetWidgetLife(d.cast) < .405 or d.ticks <= 0 then
call d.destroy()
return true
else
set d.fps = d.fps - 1
if d.fps <= 0 then
set d.fps = R2I(PERIOD / TT_PERIOD)
loop
exitwhen i > SPIRIT_NUMBER(d.cast, d.lvl) - 1
set dx = x - GetUnitX(d.spirit<i>)
set dy = y - GetUnitY(d.spirit<i>)
set sr = SquareRoot(dx * dx + dy * dy)
if sr > SPIRIT_DISTANCE(d.cast, d.lvl) then
call SetUnitX(d.spirit<i>, x)
call SetUnitY(d.spirit<i>, y)
endif
set sr = GetRandomReal(0., 360.)
set dx = GetUnitX(d.spirit<i>) + 400. * Cos(sr * bj_DEGTORAD)
set dy = GetUnitY(d.spirit<i>) + 400. * Sin(sr * bj_DEGTORAD)
call IssuePointOrder(d.spirit<i>, SID_ORDER, dx, dy)
set i = i + 1
endloop
set gr = CreateGroup()
call GroupEnumUnitsInRange(gr, x, y, AOE(d.cast, d.lvl), Condition(function Enum))
loop
set first = FirstOfGroup(gr)
exitwhen first == null
if IsUnitEnemy(first, GetOwningPlayer(d.cast)) then
set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(d.cast), UID_DUMMY, x, y, 0.)
call UnitAddAbility(bj_lastCreatedUnit, AID_UNHOLY_PERVASION_SLOW)
call SetUnitAbilityLevel(bj_lastCreatedUnit, AID_UNHOLY_PERVASION_SLOW, d.lvl)
call IssueTargetOrder(bj_lastCreatedUnit, SID_SLOW, first)
call UnitApplyTimedLife(bj_lastCreatedUnit, 039;BTLF039;, 2.)
if GetRandomInt(1, 2) == 1 then
call DestroyEffect(AddSpecialEffectTarget(SFX_ONE, first, AP_ONETWO))
else
call DestroyEffect(AddSpecialEffectTarget(SFX_TWO, first, AP_ONETWO))
endif
endif
call GroupRemoveUnit(gr, first)
endloop
call DestroyGroup(gr)
set gr = null
set first = null
endif
endif
return false
endfunction
private function Actions takes nothing returns nothing
local Data d = Data.create()
local integer i = 0
set d.cast = GetTriggerUnit()
set d.lvl = GetUnitAbilityLevel(d.cast, AID_UNHOLY_PERVASION)
loop
exitwhen i > SPIRIT_NUMBER(d.cast, d.lvl) - 1
set d.spirit<i> = CreateUnit(GetOwningPlayer(d.cast), UID_UNHOLY_PERVASION_SPIRIT, GetUnitX(d.cast), GetUnitY(d.cast), GetRandomReal(1., 360.))
call UnitApplyTimedLife(d.spirit<i>, 039;BTLF039;, DURATION(d.cast, d.lvl))
call SetUnitVertexColor(d.spirit<i>, SPIRIT_RED(d.cast, d.lvl), SPIRIT_GREEN(d.cast, d.lvl), SPIRIT_BLUE(d.cast, d.lvl), SPIRIT_ALPHA(d.cast, d.lvl))
set i = i + 1
endloop
set d.ticks = R2I(DURATION(d.cast, d.lvl) * d.fps)
set d.sfx = AddSpecialEffectTarget(SFX_ATTACH, d.cast, AP_ATTACH)
call TT_Start(function Callback, d)
endfunction
private function DoIt takes nothing returns nothing
local trigger trig
set trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trig, Condition(function Conditions))
call TriggerAddAction(trig, function Actions)
set trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddCondition(trig, Condition(function Attack))
endfunction
endscope
</i></i></i></i></i></i></i></i></i></i></i></i></i>
Screenshots:
Attached to the post... But it's better to see the spell in-game.
Credits:
Credits to Cohadar for TT, PUI and CreepRevival and to Tinki3 for the Test Map Template (edited though).