- Joined
- Dec 15, 2011
- Messages
- 1,423
JASS:
scope spell
globals
private constant integer SPHERE_UNIT_ID = 'h000'
private constant integer SPHERE_SPELL_ID = 'A001'
private constant integer SPHERE_EFFECT_ID = 'A000'
private constant integer SPHERE_BUFF_ID = 'B000'
private constant integer SPHERE_SUB_ID = 'A002'
private constant string SPHERE_CAST_EFFECT = "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl"
private constant string SPHERE_SOUL_EFFECT = "Abilities\\Spells\\Undead\\ReplenishMana\\SpiritTouchTarget.mdl"
private constant string SPHERE_TARGET_EFFECT = "Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl"
private constant real SPHERE_SIZE = 2
private constant real SPHERE_DAMAGE_PERCENT = 0.24
private constant real SPHERE_DAMAGE_AOE = 275
private constant integer DATA_DEFAULT = 2
private integer Data_Max = 0
private integer array Data_Stack
private hashtable Data_Storage = InitHashtable()
endglobals
//============================================//
struct Sphere extends Pulling
//============================================//
private unit caster
private unit target
private unit sphere
private timer ti
private group soulgroup
private effect sfx_cast
//=========================================================//
//===================== SUB ABILITY =======================//
//=========================================================//
private static method onBurn takes nothing returns nothing
local thistype d
local thistype p
local integer i
local unit u
local group g
local real dx
local real dy
local effect sfx
local real dmg
set i = 0
loop
set i = i + 1
set d = Data_Stack[i]
if d.caster == GetTriggerUnit() then
set g = CreateGroup()
call GroupAddGroup(d.soulgroup, g)
loop
set u = FirstOfGroup(g)
exitwhen u == null
set dx = GetUnitX(d.sphere) - GetUnitX(u)
set dy = GetUnitY(d.sphere) - GetUnitY(u)
if SquareRoot( dx * dx + dy * dy ) <= SPHERE_DAMAGE_AOE then
set p = LoadInteger( Data_Storage , 0, GetHandleId(u) )
if GetUnitState(p.target, UNIT_STATE_LIFE) > 0 then
set dmg = GetUnitState(p.target, UNIT_STATE_MAX_LIFE) * SPHERE_DAMAGE_PERCENT
call UnitDamageTarget( d.caster, p.target, dmg, true , false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
call UnitRemoveAbility( p.target, SPHERE_BUFF_ID )
set sfx = AddSpecialEffect( SPHERE_TARGET_EFFECT, GetUnitX(p.target), GetUnitY(p.target) )
call DestroyEffect(sfx)
endif
call RemoveUnit(u)
set sfx = AddSpecialEffect( SPHERE_SOUL_EFFECT, GetUnitX(u), GetUnitY(u) )
call DestroyEffect(sfx)
call GroupRemoveUnit(d.soulgroup, u)
endif
call GroupRemoveUnit(g, u)
endloop
call DestroyGroup(g)
endif
exitwhen i == Data_Max
endloop
endmethod
private static method BurnFilt takes nothing returns boolean
return (GetSpellAbilityId() == SPHERE_SUB_ID)
endmethod
//=========================================================//
//===================== MAIN ABILITY ======================//
//=========================================================//
private static method GetFilter takes nothing returns boolean
return true
endmethod
private static method onExpired takes nothing returns nothing
local thistype d = GetTimerData(GetExpiredTimer())
local thistype p
local unit u
local effect sfx
call SetUnitTimeScale(d.sphere, 1.0 )
call KillUnit(d.sphere)
loop
set u = FirstOfGroup(d.soulgroup)
exitwhen u == null
set p = LoadInteger( Data_Storage , 0, GetHandleId(u) )
set sfx = AddSpecialEffect( SPHERE_SOUL_EFFECT, GetUnitX(u), GetUnitY(u) )
call DestroyEffect(sfx)
call RemoveUnit(u)
call UnitRemoveAbility( p.target, SPHERE_BUFF_ID )
set p.target = null
call GroupRemoveUnit(d.soulgroup, u)
endloop
call ReleaseTimer(d.ti)
call DestroyGroup(d.soulgroup)
set d.sphere = null
call d.destroy()
if d == Data_Max then
set Data_Stack[d] = Data_Stack[Data_Max]
set Data_Max = Data_Max - 1
endif
endmethod
private static method onDelay takes nothing returns nothing
local thistype d = GetTimerData(GetExpiredTimer())
local location loc = GetUnitLoc(d.sphere)
local group g = CreateGroup()
local unit u
local unit soul
local unit dummy
call GroupEnumUnitsInRangeOfLoc( g, loc, 750, function thistype.GetFilter )
call SetUnitTimeScale(d.sphere, 0)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if IsUnitEnemy( u, GetOwningPlayer(d.sphere)) == false or GetUnitState(u, UNIT_STATE_LIFE) <= 0 or IsUnitType(u, UNIT_TYPE_SUMMONED) == true or IsUnitType(u, UNIT_TYPE_MECHANICAL) == true or IsUnitType(u, UNIT_TYPE_STRUCTURE) == true then
call GroupRemoveUnit(g, u)
else
set dummy = CreateUnit( GetOwningPlayer(d.sphere), 'h001', 0, 0, 270 )
set soul = CreateUnitAtLoc( Player(PLAYER_NEUTRAL_PASSIVE), GetUnitTypeId(u), loc, GetUnitFacing(u))
call SetUnitPathing(soul , false)
call SetUnitPosition( soul , GetUnitX(u), GetUnitY(u) )
call UnitAddAbility( soul , 'Aloc' )
call SetUnitVertexColor( soul , 255, 255, 255, 100 )
call .setup( u, soul, d.sphere, thistype.create())
call UnitApplyTimedLife( dummy, 'BTLF', 0.1)
call UnitAddAbility( dummy, SPHERE_EFFECT_ID )
call IssueTargetOrder( dummy, "soulburn", u )
call GroupAddUnit(d.soulgroup, soul)
call GroupRemoveUnit(g, u)
set dummy = null
endif
endloop
call TimerStart( d.ti, 4, false , function Sphere.onExpired )
call RemoveLocation(loc)
call DestroyGroup(g)
set loc = null
set u = null
set soul = null
endmethod
private static method setup takes unit t, unit u, unit s, thistype this returns nothing
local real ux = GetUnitX(u)
local real uy = GetUnitY(u)
local real sx = GetUnitX(s)
local real sy = GetUnitY(s)
set .target = t
call SaveInteger( Data_Storage, 0, GetHandleId(u), this)
call .SetPullUnit(u)
call .start( ux, uy, sx, sy )
endmethod
method onPullStart takes nothing returns nothing
set .pullSpeed = 350
set .isPulled = true
endmethod
private static method Filt takes nothing returns boolean
return (GetSpellAbilityId() == SPHERE_SPELL_ID)
endmethod
private static method LearnFilt takes nothing returns boolean
return (GetLearnedSkill() == SPHERE_SPELL_ID and GetLearnedSkillLevel() == 1)
endmethod
private static method onSpell takes nothing returns nothing
local unit u = GetTriggerUnit()
local location loc = GetSpellTargetLoc()
local thistype d = create()
set d.caster = u
set d.ti = NewTimer()
set d.soulgroup = CreateGroup()
set d.sphere = CreateUnitAtLoc( GetOwningPlayer(u), SPHERE_UNIT_ID, loc, 270)
call SetUnitScale( d.sphere, SPHERE_SIZE, 0, 0 )
call SetUnitTimeScale( d.sphere, 0.5 )
call UnitAddAbility( d.sphere, 'Amrf' )
call UnitAddAbility( d.sphere, SPHERE_EFFECT_ID )
call SetUnitFlyHeight( d.sphere, 100 , 0)
call SetTimerData(d.ti, d)
call TimerStart( d.ti, 1.7, false, function Sphere.onDelay )
set Data_Max = Data_Max + 1
set Data_Stack[Data_Max] = d
endmethod
private static method onLearn takes nothing returns nothing
call UnitAddAbility( GetTriggerUnit(), SPHERE_SUB_ID )
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local trigger m = CreateTrigger()
local trigger z = CreateTrigger()
local integer i
call TriggerAddAction(t, function thistype.onSpell )
call TriggerAddAction(m, function thistype.onBurn )
call TriggerAddAction(z, function thistype.onLearn )
call TriggerAddCondition( t, function thistype.Filt )
call TriggerAddCondition( m, function thistype.BurnFilt )
call TriggerAddCondition( z, function thistype.LearnFilt )
set i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
call TriggerRegisterPlayerUnitEvent(m, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
call TriggerRegisterPlayerUnitEvent(z, Player(i), EVENT_PLAYER_HERO_SKILL, null)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
endmethod
endstruct
endscope