• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

FoxSpellPack v1.0

  • Like
Reactions: Jazztastic
This is the pack of spells I've been working on recently.

It includes
  • Cursed Ground
    • Blights Targeted Ground.
  • Reckless Reanimation
    • Revives dead trees or restores gold to Gold Mines, at the cost of the casters life.
  • Infectious Presence (Passive Aura)
    • Has a chance to on death of enemy units around heroes to transform them into an undead Changeling follower, that if survives its painful transformation, will become full fledged Zombie.
  • Unholy Light
    • Damages enemies in the spell's area and heals your units based on the damage done and how many of your units are in the area.

Also I have the spells in there own folder saved as .j files if anyone would like me to upload them all in a zip and pm them to you just let me know.

Update: I have condensed all the spells into 1 trigger each. And made some other minor edits to speed them up a bit as well. and here is the scripts too XD

Update 7-12-12: Sorry for the long wait, allot of work lately, I have fixed the problems as suggested by the Mod, if you have any other ideas or suggestions let me know.




Unholy%20Light%2001.jpg


Unholy%20Light%2002.jpg

---
Cursed%20Ground%2001.jpg

Cursed%20Ground%2002.jpg

Cursed%20Ground%2003.jpg

---

Selfless%20Reanimation%2001.jpg


Selfless%20Reanimation%2002.jpg


Selfless%20Reanimation%2003.jpg

---
Infectious%20Presence%2001.jpg



JASS:
// Spell Config

// This function returns ability of the Spell at given level
function Fox_CursedGroundAbil takes integer id returns integer
    if (id == 1) then
        // Change this to the first ability of the spell
        return 'A001'
    elseif (id == 2) then
        // Change this to the second ability of the spell
        return 'A002'
    elseif (id == 3) then
        // Change this to the third ability of the spell
        return 'A003'
    elseif (id == 4) then
        // Change this to the Hero ability of the spell
        return 'A00I'
    else
        return 0
    endif
endfunction

// This function returns Cast Time of the Spell at given level
function Fox_CursedGroundCastTimes takes integer level returns real
    if (level == 1) then
        // Change this to the first cast time of the spell
        return 15.0
    elseif (level == 2) then
        // Change this to the second cast time of the spell
        return 10.0
    elseif (level == 3) then
        // Change this to the third cast time of the spell
        return 10.0
    else
        return 10.0
    endif
endfunction

// This function returns Dummy Unit of the Spell
constant function Fox_CursedGroundDummy takes nothing returns integer
    // Change this to the UnitId of Dummy Unit
    return 'h000'
endfunction

// This function returns the Spell Effect model's path
constant function Fox_CursedGroundSFX takes nothing returns string
    // Change this to the Spell Effect model's path
    return "Abilities\\Spells\\NightElf\\TargetArtLumber\\TargetArtLumber.mdl"
endfunction

// This function returns the Spell Sound's path
constant function Fox_CursedGroundSound takes nothing returns sound
    // Change this to the Spell Sound's path
    return gg_snd_Fox_CursedGroundSound
endfunction

// This function returns the Spell's Tech
constant function Fox_CursedGroundTech takes nothing returns integer
    // Change this to the Tech you need to research in order to get the ability
    return 'R007'
endfunction

// This function returns the Spell's Ability that the Dummy Unit should cast at the given level
function Fox_CursedGroundTrueAbils takes integer level returns integer
    if (level == 1) then
        // Change this to the Ability the Dummy Unit should cast at level 1
        return 'A00A'
    elseif (level == 2) then
        // Change this to the Ability the Dummy Unit should cast at level 2
        return 'A00B'
    elseif (level == 3) then
        // Change this to the Ability the Dummy Unit should cast at level 3
        return 'A00C'
    else
        return 0
    endif
endfunction

// Functions

// This function is the Timer's function
function Fox_CursedGround_TimerFunc takes nothing returns nothing
    //-----------------------------------
    // Declare locals
    //-----------------------------------
    // Declare castTimer
    local timer castTimer
    // Declare dummyUnit
    local unit dummyUnit
    // Declare players
    local force players
        
    //-----------------------------------
    // Declare saved locals
    //-----------------------------------
    // Declare targetPoint
    local location targetPoint
    // Declare castingPlayer
    local player castingPlayer
    // Declare spellLevel
    local integer spellLevel
    // Declare spellFX
    local effect spellFX
    
    //-----------------------------------
    // Set timer variable
    //-----------------------------------
    // set timer
    set castTimer = GetExpiredTimer()

    //-----------------------------------
    // Load variables
    //-----------------------------------
    // Load targetPoint
    set targetPoint = LoadLocationHandle(udg_Fox_CursedGroundHash, GetHandleId(castTimer), 0)
    // Load spellLevel
    set spellLevel = LoadInteger(udg_Fox_CursedGroundHash, GetHandleId(castTimer), 1)
    // Load casterPlayer
    set castingPlayer = LoadPlayerHandle(udg_Fox_CursedGroundHash, GetHandleId(castTimer), 2)
    // Load spellFX
    set spellFX = LoadEffectHandle(udg_Fox_CursedGroundHash, GetHandleId(castTimer), 3)
    
    //-----------------------------------
    // Set variables
    //-----------------------------------
    // Set players
    set players = GetForceOfPlayer(castingPlayer)
    // Set dummyUnit
    set dummyUnit = null

    //-----------------------------------    
    // Actions
    //-----------------------------------
    call DestroyEffect(spellFX)
    // Create DummyUnit at the targetPoint
    call CreateNUnitsAtLoc(1, Fox_CursedGroundDummy(), castingPlayer, targetPoint, bj_UNIT_FACING )
    // store the created unit in dummyUnit
    set dummyUnit = GetLastCreatedUnit()
    // Add timer to kill dummyUnit after 5 seconds
    call UnitApplyTimedLifeBJ( 1.0, 'BTLF', dummyUnit )
    // Remove Locust
    call UnitRemoveAbility(dummyUnit, 'Aloc')
    // Add Ability to dummyUnit
    call UnitAddAbility(dummyUnit, Fox_CursedGroundTrueAbils(spellLevel))
    // Add Locust
    call UnitAddAbility(dummyUnit, 'Aloc')
    // Ping Minimap
    call PingMinimapLocForForceEx(players, targetPoint, 1, bj_MINIMAPPINGSTYLE_SIMPLE, 0.00, 0.00, 0.00 )

    
    //-----------------------------------
    // Clean-up
    //-----------------------------------
    // Remove all saved Data
    call FlushChildHashtable(udg_Fox_CursedGroundHash, GetHandleId(castTimer))
    
    // Destroy variables
    call DestroyTimer(castTimer)
    call RemoveLocation(targetPoint)
    call DestroyForce(players)
    
    // Null variables
    set castTimer = null
    set targetPoint = null
    set players = null
    set dummyUnit = null

endfunction

// This function handles upgrading the spell
function Fox_CursedGroundResearched takes player whichPlayer returns nothing
    // Declare spellLevel
    local integer techLevel
    // Set techLevel
    set techLevel = GetPlayerTechCountSimple(Fox_CursedGroundTech(), whichPlayer)
    // Actions
    // Enable New Spell
    call SetPlayerAbilityAvailable(whichPlayer, Fox_CursedGroundAbil(techLevel), true)
    // Check whether to disable others
    if (techLevel > 1) then
        // Disable Old Spell
        call SetPlayerAbilityAvailable(whichPlayer, Fox_CursedGroundAbil(techLevel - 1), false)
    endif
endfunction

// This function handles the casting of the spell
function Fox_CursedGroundSpellCasted takes location targetPoint, unit castingUnit, integer spellId returns nothing
    //-----------------------------------
    // Declare locals
    //-----------------------------------
    // Declare castTimer
    local timer castTimer
    // Declare castTime
    local real castTime
    
    //-----------------------------------
    // Declare saved locals
    //-----------------------------------
    // Declare spellLevel
    local integer spellLevel
    // Declare castingPlayer
    local player castingPlayer
    // Declare spellFX
    local effect spellFX
    
    //-----------------------------------
    // Set variables
    //-----------------------------------
    // Create timer
    set castTimer = CreateTimer()
    // Set castingPlayer
    set castingPlayer = GetOwningPlayer(castingUnit)
    // Set spellLevel
    if (spellId == Fox_CursedGroundAbil(4)) then
        // Hero casted spell
        set spellLevel = GetUnitAbilityLevel(castingUnit, spellId)
    else
        // Unit casted spell
        if (spellId == Fox_CursedGroundAbil(1)) then
            // Unit casted spell (lv 1)
            set spellLevel = 1
        elseif (spellId == Fox_CursedGroundAbil(2)) then
            // Unit casted spell (lv 2)
            set spellLevel = 2
        else
            // Unit casted spell (lv 3)
            set spellLevel = 3            
        endif
    endif
    // Set castTime
    set castTime = Fox_CursedGroundCastTimes(spellLevel)
    // Set the spellFX
    set spellFX = AddSpecialEffectTarget(Fox_CursedGroundSFX(), castingUnit, "origin")    
    // Start Sound
    call PlaySoundAtPointBJ(Fox_CursedGroundSound(), 50.0, targetPoint, GetLocationZ(targetPoint))
    
    //-----------------------------------
    // Save variables
    //-----------------------------------
    // Save Location of spell
    call SaveLocationHandle(udg_Fox_CursedGroundHash, GetHandleId(castTimer), 0, targetPoint)
    // Save Level of spell
    call SaveInteger(udg_Fox_CursedGroundHash, GetHandleId(castTimer), 1, spellLevel)
    // Save casterPlayer
    call SavePlayerHandle(udg_Fox_CursedGroundHash, GetHandleId(castTimer), 2, castingPlayer)
    // Save spellFX
    call SaveEffectHandle(udg_Fox_CursedGroundHash, GetHandleId(castTimer), 3, spellFX)
    
    //-----------------------------------
    // Start Timer
    //-----------------------------------
    call TimerStart(castTimer, castTime, false, function Fox_CursedGround_TimerFunc)
    
    //-----------------------------------
    // Clean-up
    //-----------------------------------
    // Null variables
    set castTimer = null
    set targetPoint = null
    set castingPlayer = null
    set spellFX = null
    
endfunction

// This function Initializes the Spell
function Trig_CursedGroundInitialize takes nothing returns nothing
    local integer i = 0
    // Set Fox_CursedGroundHash
    set udg_Fox_CursedGroundHash            = InitHashtable()
    // Setup Spells
    loop
        exitwhen i > 15
        if (GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING) then
            call SetPlayerAbilityAvailable(Player(i), Fox_CursedGroundAbil(2), false)
            call SetPlayerAbilityAvailable(Player(i), Fox_CursedGroundAbil(3), false)
        endif
        set i = (i + 1)
    endloop
endfunction

// This function is the actions part of the trigger and calls the needed function
function Trig_CursedGround_Actions takes nothing returns nothing
    local integer tech      = GetResearched()
    local integer spellId   = GetSpellAbilityId()
    // If Researching
    if (tech == Fox_CursedGroundTech()) then
        // Call Research Spell for player
        call Fox_CursedGroundResearched(GetOwningPlayer(GetTriggerUnit()))
        
    // If Casting
    elseif ((spellId == Fox_CursedGroundAbil(1)) or (spellId == Fox_CursedGroundAbil(2)) or (spellId == Fox_CursedGroundAbil(3)) or (spellId == Fox_CursedGroundAbil(4))) then
        // The Spell casting function
        call Fox_CursedGroundSpellCasted(GetSpellTargetLoc(), GetTriggerUnit(), spellId)
    
    // Map Initialization
    else
        // Initialize Spell
        call Trig_CursedGroundInitialize()
    endif
endfunction

//===========================================================================
function InitTrig_CursedGround takes nothing returns nothing
    set gg_trg_CursedGround = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CursedGround, EVENT_PLAYER_UNIT_RESEARCH_FINISH )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CursedGround, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerRegisterTimerEventSingle( gg_trg_CursedGround, 0.50 )
    call TriggerAddAction( gg_trg_CursedGround, function Trig_CursedGround_Actions )
endfunction
JASS:
// Spell Config

// This function returns ability of the Spell at given level
function Fox_SRAbil takes integer level returns integer
    if (level == 1) then
        // Change this to the first ability of the spell
        return 'A004'
    elseif (level == 2) then
        // Change this to the second ability of the spell
        return 'A005'
    elseif (level == 3) then
        // Change this to the third ability of the spell
        return 'A006'
    else
        return 0
    endif
endfunction

// This function returns Cast Time of the Spell at given level
function Fox_SRCastTimes takes integer level returns real
    if (level == 1) then
        // Change this to the first cast time of the spell
        return 20.0
    elseif (level == 2) then
        // Change this to the second cast time of the spell
        return 15.0
    elseif (level == 3) then
        // Change this to the third cast time of the spell
        return 15.0
    else
        return 0.0
    endif
endfunction

// This function returns Amount of Gold restored of the Spell at given level
function Fox_SRGoldAmount takes integer level returns integer
    if (level == 1) then
        // Change this to the first amount of gold added to Gold Mine of the spell
        return 4000
    elseif (level == 2) then
        // Change this to the second amount of gold added to Gold Mine of the spell
        return 5000
    elseif (level == 3) then
        // Change this to the third amount of gold added to Gold Mine of the spell
        return 6000
    else
        return 4000
    endif
endfunction

// This function returns the range of the Spell at given level
function Fox_SRRanges takes integer level returns real
    if (level == 1) then
        // Change this to the first range of the spell
        return 512.0
    elseif (level == 2) then
        // Change this to the second range of the spell
        return 1024.0
    elseif (level == 3) then
        // Change this to the third range of the spell
        return 2048.0
    else
        return 0.0
    endif
endfunction

// This function returns the Spell Effect model's path
constant function Fox_SRSFX takes nothing returns string
    // Change this to the Spell Effect model's path
    return "Abilities\\Spells\\NightElf\\TargetArtLumber\\TargetArtLumber.mdl"
endfunction

// This function returns the Spell Sound's path
constant function Fox_SRSound takes nothing returns sound
    // Change this to the Spell Sound's path
    return gg_snd_Fox_SRSound
endfunction

// This function returns the Spell's Tech
constant function Fox_SRTech takes nothing returns integer
    // Change this to the Tech you need to research in order to get the ability
    return 'R006'
endfunction

// Functions

// This function checks if Doodad is a dead tree
function Fox_SelflessReanimation_IsADeadTree takes nothing returns boolean
    local integer destructableTypeID = GetDestructableTypeId(GetFilterDestructable())
    // Check if the destructable is dead
    if (GetDestructableLife(GetFilterDestructable()) <= 0) then
        // Check if the destructable is a tree
        if (destructableTypeID == 'ATtr') then
            return true
        elseif (destructableTypeID == 'BTtw') then
            return true
        elseif (destructableTypeID == 'KTtw') then
            return true
        elseif (destructableTypeID == 'YTft') then
            return true
        elseif (destructableTypeID == 'JTct') then
            return true
        elseif (destructableTypeID == 'YTst') then
            return true
        elseif (destructableTypeID == 'YTct') then
            return true
        elseif (destructableTypeID == 'YTwt') then
            return true
        elseif (destructableTypeID == 'JTwt') then
            return true
        elseif (destructableTypeID == 'DTsh') then
            return true
        elseif (destructableTypeID == 'FTtw') then
            return true
        elseif (destructableTypeID == 'CTtr') then
            return true
        elseif (destructableTypeID == 'ITtw') then
            return true
        elseif (destructableTypeID == 'NTtw') then
            return true
        elseif (destructableTypeID == 'OTtw') then
            return true
        elseif (destructableTypeID == 'ZTtw') then
            return true
        elseif (destructableTypeID == 'WTst') then
            return true
        elseif (destructableTypeID == 'LTlt') then
            return true
        elseif (destructableTypeID == 'GTsh') then
            return true
        elseif (destructableTypeID == 'VTlt') then
            return true
        elseif (destructableTypeID == 'WTtw') then
            return true
        elseif (destructableTypeID == 'Attc') then
            return true
        elseif (destructableTypeID == 'BTtc') then
            return true
        elseif (destructableTypeID == 'CTtc') then
            return true
        elseif (destructableTypeID == 'ITtc') then
            return true
        elseif (destructableTypeID == 'NTtc') then
            return true
        elseif (destructableTypeID == 'ZTtc') then
            return true
        else
            // Destructable isn't a tree
            return false
        endif
    else
        // Destructable isn't dead
        return false
    endif
endfunction

// This function resurrects the enum tree 
function Fox_SelflessReanimation_ReviveTreesEnum takes nothing returns nothing
    // Revive Tree
    call DestructableRestoreLife(GetEnumDestructable(), GetDestructableMaxLife(GetEnumDestructable()), true)
endfunction

// This function loops through the trees in the given radius, and runs the given function on the trees
function Fox_SelflessReanimation_EnumTreesInCircle takes real x, real y, real radius, code func returns nothing
    local rect r = Rect(x - radius,y - radius,x + radius,y + radius)
    call EnumDestructablesInRect(r, Filter(function Fox_SelflessReanimation_IsADeadTree), func)
    call RemoveRect(r)
    set r = null
endfunction

// This function plays the given sound at given coors
function Fox_SelflessReanimation_PlaySound takes sound soundHandle, real volumePercent, real x, real y, real z returns nothing
    if (soundHandle != null) then
        call SetSoundPosition(soundHandle, x, y, z)
        call SetSoundVolumeBJ(soundHandle, PercentToInt(volumePercent, 127))
        call StartSound(soundHandle)
    endif
endfunction

// This function checks is the filter for checking if a unit is a Gold Mine and Alive
function Fox_SelflessReanimation_IsAGoldMineAndAlive takes nothing returns boolean
    return ((GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0) and ((GetUnitTypeId(GetFilterUnit()) == 'ngol') or (GetUnitTypeId(GetFilterUnit()) == 'ugol')))
endfunction

// This function is the Timer's function
function Fox_SelflessReanimation_TimerFunc takes nothing returns nothing
    // Declare locals
    // Declare castTimer
    local timer castTimer
    // Declare castingPlayer
    local player castingPlayer
    
    // Declare saved locals
    // Declare targetX
    local real targetX
    // Declare targetY
    local real targetY
    // Declare castingUnit
    local unit castingUnit
    // Declare spellLevel
    local integer spellLevel
    // Declare spellFX
    local effect spellFX
    
    // set timer
    set castTimer = GetExpiredTimer()
    
    // Load variables
    // Load targetX
    set targetX     = LoadReal(udg_Fox_SRHash, GetHandleId(castTimer), 0)
    // Load targetY
    set targetY     = LoadReal(udg_Fox_SRHash, GetHandleId(castTimer), 1)
    // Load castingUnit
    set castingUnit = LoadUnitHandle(udg_Fox_SRHash, GetHandleId(castTimer), 2)
    // Load spellLevel
    set spellLevel  = LoadInteger(udg_Fox_SRHash, GetHandleId(castTimer), 3)
    // Load spellFX
    set spellFX     = LoadEffectHandle(udg_Fox_SRHash, GetHandleId(castTimer), 4)

    // Set variables
    // Set castingUnit
    set castingPlayer       = GetOwningPlayer(castingUnit)
    
    // Actions
    // Destroy spellFX
    call DestroyEffect(spellFX)

    // Clear global Group just in case
    call GroupClear(udg_Fox_SRGroup)    
    // Add units in range to global Group
    call GroupEnumUnitsInRange(udg_Fox_SRGroup, targetX, targetY, Fox_SRRanges(spellLevel), Filter(function Fox_SelflessReanimation_IsAGoldMineAndAlive))
    if (CountUnitsInGroup(udg_Fox_SRGroup) > 0) then
        // Spell targeted a Gold Mine
        // Add gold to Gold Mine
        call AddResourceAmount(FirstOfGroup(udg_Fox_SRGroup), Fox_SRGoldAmount(spellLevel))
    else
        // Resurrect every tree in range of spell targetPoint
        call Fox_SelflessReanimation_EnumTreesInCircle(targetX, targetY, Fox_SRRanges(spellLevel), function Fox_SelflessReanimation_ReviveTreesEnum)
    endif
    // Clear global Groups contents
    call GroupClear(udg_Fox_SRGroup)

    // Kill unit casting the ability
    call UnitApplyTimedLifeBJ( 0.5, 'BTLF', castingUnit)
    
    // Clean-up
    // Remove all saved Data
    call FlushChildHashtable(udg_Fox_SRHash, GetHandleId(castTimer))
    
    // Destroy variables
    call DestroyTimer(castTimer)
    
    // Null variables
    set castTimer       = null
    set castingUnit     = null
    set castingPlayer   = null
    set spellFX         = null

endfunction

// This function handles upgrading the spell
function Fox_SRResearched takes player whichPlayer returns nothing
    // Declare spellLevel
    local integer techLevel
    // Set techLevel
    set techLevel = GetPlayerTechCountSimple(Fox_SRTech(), whichPlayer)
    // Actions
    // Enable New Spell
    call SetPlayerAbilityAvailable(whichPlayer, Fox_SRAbil(techLevel), true)
    // Check whether to disable others
    if (techLevel > 1) then
        // Disable Old Spell
        call SetPlayerAbilityAvailable(whichPlayer, Fox_SRAbil(techLevel - 1), false)
    endif
endfunction

// This function handles the casting of the spell
function Fox_SRSpellCasted takes real targetX, real targetY, real targetZ, unit castingUnit returns nothing
    // Declare castTimer
    local timer castTimer
    // Declare castTime
    local real castTime

    // Declare spellLevel
    local integer spellLevel
    // Declare spellFX
    local effect spellFX

    // create timer
    set castTimer   = CreateTimer()
    // Set spellLevel
    set spellLevel  = GetPlayerTechCountSimple(Fox_SRTech(), GetOwningPlayer(castingUnit))
    // Set castTime
    set castTime    = Fox_SRCastTimes(spellLevel)
    // Set SpellFX
    set spellFX     = AddSpecialEffectTarget(Fox_SRSFX(), castingUnit, "origin") 
    // Start Sound
    call Fox_SelflessReanimation_PlaySound(Fox_SRSound(), 50.0, targetX, targetY, targetZ)
    
    // Save targetX
    call SaveReal(udg_Fox_SRHash, GetHandleId(castTimer), 0, targetX)
    // Save targetY
    call SaveReal(udg_Fox_SRHash, GetHandleId(castTimer), 1, targetY)
    // Save castingUnit
    call SaveUnitHandle(udg_Fox_SRHash, GetHandleId(castTimer), 2, castingUnit)
    // Save spellLevel
    call SaveInteger(udg_Fox_SRHash, GetHandleId(castTimer), 3, spellLevel)
    // Save spellFX
    call SaveEffectHandle(udg_Fox_SRHash, GetHandleId(castTimer), 4, spellFX)
    
    // Start Timer
    call TimerStart(castTimer, castTime, false, function Fox_SelflessReanimation_TimerFunc)
    
    // Clean-up
    // Null variables
    set castTimer   = null
    set castingUnit = null
    set spellFX     = null
endfunction

// This function Initializes the Spell
function FoxSRInitialize takes nothing returns nothing
    local integer i = 0
    // Initialize Hashtable
    set udg_Fox_SRHash  = InitHashtable()
    // Initialize global Group
    set udg_Fox_SRGroup = CreateGroup()
    // Disable Unavailible Spell Levels
    loop
        exitwhen i > 15
        if (GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING) then
            call SetPlayerAbilityAvailable(Player(i), Fox_SRAbil(2), false)
            call SetPlayerAbilityAvailable(Player(i), Fox_SRAbil(3), false)
        endif
        set i = (i + 1)
    endloop
endfunction

// This function is the actions part of the trigger and calls the needed function
function Trig_SelflessReanimation_Actions takes nothing returns nothing
    local integer tech      = GetResearched()
    local integer spellId   = GetSpellAbilityId()
    local location spellLoc = GetSpellTargetLoc()
    // If Researching
    if (tech == Fox_SRTech()) then
        // Call Research Spell for player
        call Fox_SRResearched(GetOwningPlayer(GetTriggerUnit()))
        
    // If Casting
    elseif ((spellId == Fox_SRAbil(1)) or (spellId == Fox_SRAbil(2)) or (spellId == Fox_SRAbil(3))) then
        // The Spell casting function
        call Fox_SRSpellCasted(GetSpellTargetX(), GetSpellTargetY(), GetLocationZ(spellLoc), GetTriggerUnit())
    
    // Map Initialization
    else
        // Initialize Spell
        call FoxSRInitialize()
    endif
    
    // Clean-up
    call RemoveLocation(spellLoc)
    set spellLoc = null
endfunction

//===========================================================================
function InitTrig_SelflessReanimation takes nothing returns nothing
    set gg_trg_SelflessReanimation = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_SelflessReanimation, EVENT_PLAYER_UNIT_RESEARCH_FINISH )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_SelflessReanimation, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerRegisterTimerEventSingle( gg_trg_SelflessReanimation, 0.50 )
    call TriggerAddAction( gg_trg_SelflessReanimation, function Trig_SelflessReanimation_Actions )
endfunction
JASS:
// Infectious Presence
// Spell Config

// This function returns ability of the Spell at given level
function Fox_InfectiousPresenceAbil takes integer level returns integer
    if (level == 1) then
        // Change this to the first ability of the spell
        return 'A00R'
    elseif (level == 2) then
        // Change this to the second ability of the spell
        return 'A00S'
    elseif (level == 3) then
        // Change this to the third ability of the spell
        return 'A00T'
    else
        return 0
    endif
endfunction

// This function returns different chance values of the Spell
function Fox_InfectiousPresenceChance takes integer level returns integer
	if (level == 0) then
		return 0
	endif
	return level * 5 + 5
endfunction

// This function returns the max level of the Spell
constant function Fox_InfectiousPresenceMaxAbilLevel takes nothing returns integer
    // Change this to the max level of the Spell
    return 3
endfunction

// This function returns the range of the Spell at given level
function Fox_InfectiousPresenceRanges takes integer level returns real
	if (level == 0) then
		return 0
	endif
	return level * 1024.0
endfunction

// This function returns the Spell Effect model's path
constant function Fox_InfectiousPresenceSFX takes nothing returns string
    // Change this to the Spell Effect model's path
    return "Abilities\\Spells\\Items\\AIma\\AImaTarget.mdl"
endfunction

// This function returns the Spell's Tech
constant function Fox_InfectiousPresenceTech takes nothing returns integer
    // Change this to the Tech you need to research in order to get the ability
    return 'R00B'
endfunction

// Zombie/Changeling Config

// This function returns the UnitId of the Changeling
constant function Fox_InfectiousPresenceChangelingId takes nothing returns integer
    // Change this to the UnitId of the Changeling
    return 'n002'
endfunction

// This function returns the UnitId of the Zombie Unit
constant function Fox_InfectiousPresenceZombieId takes nothing returns integer
    // Change this to the UnitId of the Zombie
    return 'n003'
endfunction

// Constant function returning the Damage done to the Changeling
constant function Fox_InfectiousPresenceZombieDmgTotal takes nothing returns real
    // change this to the max damage you want the changeling to endure during the change
    return 100.0
endfunction

// Constant function returning the amount of ticks per second
constant function Fox_InfectiousPresenceZombieTicksPerSec takes nothing returns real
    // Change this to the amount of ticks per second
    return 2.0 // 2 ticks per second
endfunction

// Constant function returning the time the zombie (Changeling) has to survive
constant function Fox_InfectiousPresenceZombieTime takes nothing returns real
    // This is the total time the Changeling must survive
    return 10.0
endfunction

// Functions

// Constant function returning the amount of Damage done per tick
constant function Fox_InfectiousPresenceZombieDmgPerTick takes nothing returns real
    return Fox_InfectiousPresenceZombieDmgTotal() / Fox_InfectiousPresenceZombieTime() / Fox_InfectiousPresenceZombieTicksPerSec()
endfunction

// Constant function returning the delay of the timer
constant function Fox_InfectiousPresenceZombieTickTime takes nothing returns real
    return 1 / Fox_InfectiousPresenceZombieTicksPerSec()
endfunction

// Check if unit is within a radius of another unit
function Fox_InfectiousPresenceUnitWithinUnitRadius takes unit unitToCheck1, unit unitToCheck2, real radius returns boolean
    local real unitX = GetUnitX(unitToCheck1)
    local real unitY = GetUnitY(unitToCheck1)
    local real targetX = GetUnitX(unitToCheck2)
    local real targetY = GetUnitY(unitToCheck2)
    if ((targetX - radius <= unitX) and(unitX <= targetX + radius)) then
        if ((targetY - radius <= unitY) and(unitY <= targetY + radius)) then
            return true
        endif
    endif
    return false
endfunction

// This function is the Timer's function
function Fox_InfectiousPresence_Main_TimerFunc takes nothing returns nothing
    //-----------------------------------
    // Declare locals
    //-----------------------------------
    // Declare zombieDeathTimer
    local timer zombieDeathTimer
    // Declare zombieDoTTimer
    local timer zombieDoTTimer
    // Declare zombieUnit
    local unit zombieUnit
    // Declare spellFX
    local effect spellFX
    
    //-----------------------------------
    // Set timer variable
    //-----------------------------------
    // Set zombieDeathTimer
    set zombieDeathTimer = GetExpiredTimer()
    
    //-----------------------------------
    // Load variables
    //-----------------------------------
    // Load zombieUnit
    set zombieUnit      = LoadUnitHandle(  udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDeathTimer), 0)
    // Load zombieDoTTimer
    set zombieDoTTimer  = LoadTimerHandle( udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDeathTimer), 1)
    // Load spellFX
    set spellFX         = LoadEffectHandle(udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDoTTimer),   1)
    
    //-----------------------------------
    // Actions
    //-----------------------------------
    // Pause zombieDeathTimer to prevent Errors
    call PauseTimer(zombieDeathTimer)
    // Pause zombieDoTTimer to prevent Errors
    call PauseTimer(zombieDoTTimer)
    // Check spellFX to insure that it isn't null
    if (spellFX != null) then
        // Destroy the Effect
        call DestroyEffect(spellFX)
    endif
    // Check if unit is still alive
    if (IsUnitType(zombieUnit, UNIT_TYPE_DEAD)) then
        // Change the unit into full-fledged Zombie
        call ReplaceUnitBJ(zombieUnit, Fox_InfectiousPresenceZombieId(), bj_UNIT_STATE_METHOD_ABSOLUTE)
    endif
    //-----------------------------------
    // Clean-up
    //-----------------------------------
    // Remove all saved Data
    call FlushChildHashtable(udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDeathTimer))
    call FlushChildHashtable(udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDoTTimer))
    
    // Destroy Handles
    call DestroyTimer(zombieDeathTimer)
    call DestroyTimer(zombieDoTTimer)
        
    // Null variables
    set zombieDeathTimer    = null
    set zombieDoTTimer      = null
    set zombieUnit          = null
    set spellFX             = null
    
endfunction

// This function deals damage to the Changeling
function Fox_InfectiousPresence_Main_TimerFunc2 takes nothing returns nothing
    //-----------------------------------
    // Declare locals
    //-----------------------------------
    // Declare zombieDoTTimer
    local timer zombieDoTTimer
    // Declare zombieUnit
    local unit zombieUnit
    // Declare spellFX
    local effect spellFX
    // Declare newHeath
    local real newHealth
    
    //-----------------------------------
    // Set timer variable
    //-----------------------------------
    // Set zombieDeathTimer
    set zombieDoTTimer = GetExpiredTimer()
    
    //-----------------------------------
    // Load variables
    //-----------------------------------
    // Load zombieUnit
    set zombieUnit = LoadUnitHandle(  udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDoTTimer), 0)
    // Load spellFX
    set spellFX    = LoadEffectHandle(udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDoTTimer), 1)
    
    //-----------------------------------
    // Set variables
    //-----------------------------------
    set newHealth = GetUnitState(zombieUnit, UNIT_STATE_LIFE) - Fox_InfectiousPresenceZombieDmgPerTick()
    
    //-----------------------------------
    // Actions
    //-----------------------------------
    // Check if the Changeling is Alive
    if (IsUnitType(zombieUnit, UNIT_TYPE_DEAD)) then
        // Do damage to the Changeling Unit
        call SetUnitState(zombieUnit, UNIT_STATE_LIFE, newHealth)
        call DestroyEffect(spellFX)
        // Play spellFX
        set spellFX = AddSpecialEffectTarget(Fox_InfectiousPresenceSFX(), zombieUnit, "origin") 
        // Save spellFX
        call SaveEffectHandle(udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDoTTimer),   1, spellFX)
    else
        // Check spellFX to insure that it isn't null
        if (spellFX != null) then
            // Destroy the Effect
            call DestroyEffect(spellFX)
        endif
    endif
    
    //-----------------------------------
    // Clean-up
    //-----------------------------------
    // Null variables
    set zombieDoTTimer      = null
    set zombieUnit          = null
    set spellFX             = null

endfunction

// This function handles upgrading the spell
function Fox_InfectiousPresenceResearched takes player whichPlayer returns nothing
    // Declare spellLevel
    local integer techLevel
    // Set techLevel
    set techLevel = GetPlayerTechCountSimple(Fox_InfectiousPresenceTech(), whichPlayer)
    
    // Actions
    // Enable New Spell
    call SetPlayerAbilityAvailable(whichPlayer, Fox_InfectiousPresenceAbil(techLevel), true)
    // Check whether to disable others
    if (techLevel > 1) then
        // Disable Old Spell
        call SetPlayerAbilityAvailable(whichPlayer, Fox_InfectiousPresenceAbil(techLevel - 1), false)
    endif
endfunction

// This function handles the casting of the spell
function Fox_InfectiousPresenceDeathActions takes unit dyingUnit returns nothing
    //-----------------------------------
    // Declare locals
    //-----------------------------------
    // Declare zombieDeathTimer
    local timer zombieDeathTimer
    // Declare zombieDoTTimer
    local timer zombieDoTTimer
    // Declare zombieUnit
    local unit zombieUnit
    // Declare unitToCheck
    local unit unitToCheck
    // Declare dummyUnit
    local unit dummyUnit
    // Declare spellEffectiveChance
    local integer spellEffectiveChance
    // Declare spellRoll
    local integer spellRoll
    // Declare trigPlayer
    local player trigPlayer
    // Declare spellFX
    local effect spellFX
    
    //-----------------------------------
    // Set variables
    //-----------------------------------
    // Set zombieDeathTimer
    set zombieDeathTimer        = null
    // Set zombieUnit
    set zombieUnit              = null
    // Set unitToCheck
    set unitToCheck             = null
    // Set dummyUnit
    set dummyUnit               = null
    // Set spellEffectiveChance
    set spellEffectiveChance    = 0
    // Set spellRoll
    set spellRoll               = 0
    // Set trigPlayer
    set trigPlayer              = GetOwningPlayer(dyingUnit)
    
    //-----------------------------------
    // Actions
    //-----------------------------------
    // Clear Group just in case
    call GroupClear(udg_Fox_InfectiousPresenceGroup)
    // Use Filter to check if units are within the Max Range to avoid looping through all the units on the map
    call GroupEnumUnitsInRange(udg_Fox_InfectiousPresenceGroup, GetUnitX(dyingUnit), GetUnitY(dyingUnit), Fox_InfectiousPresenceRanges(Fox_InfectiousPresenceMaxAbilLevel()), null)

    // Loop through the possible Enemy Hero Matches
    loop
        set unitToCheck = FirstOfGroup(udg_Fox_InfectiousPresenceGroup)
        exitwhen unitToCheck == null
        if (IsPlayerEnemy(GetOwningPlayer(unitToCheck), trigPlayer) and Fox_InfectiousPresenceUnitWithinUnitRadius(dyingUnit, unitToCheck, Fox_InfectiousPresenceRanges(GetPlayerTechCount(GetOwningPlayer(unitToCheck), Fox_InfectiousPresenceTech(), true))) and (IsUnitType(unitToCheck, UNIT_TYPE_HERO))) then
            // Set spellEffectiveChance
            set spellEffectiveChance = Fox_InfectiousPresenceChance(GetPlayerTechCount(GetOwningPlayer(unitToCheck), Fox_InfectiousPresenceTech(), true))
            // Roll
            set spellRoll = GetRandomInt(1, 100)
            // Check if spell is effective
            if (spellRoll < spellEffectiveChance) then
                // Spell was successful
                // Create Zombie at Dying units Coordinates, and Set zombieUnit
                set zombieUnit = CreateUnit(GetOwningPlayer(unitToCheck), Fox_InfectiousPresenceZombieId(), GetUnitX(dyingUnit), GetUnitY(dyingUnit), GetUnitFacing(dyingUnit))
                // Play spellFX
                set spellFX    = AddSpecialEffectTarget(Fox_InfectiousPresenceSFX(), zombieUnit, "origin") 
                            
                // Set Timer for new Zombie
                set zombieDeathTimer = CreateTimer()
                // Set Timer for the Damage over Time on the Zombie
                set zombieDoTTimer   = CreateTimer()
        
                // Save variables
                // Save variables for the zombieDeathTimer
                // Save Zombie Unit to Timer Handle
                call SaveUnitHandle(udg_Fox_InfectiousPresenceHash,   GetHandleId(zombieDeathTimer), 0, zombieUnit)
                // Save DoT to Timer Handle
                call SaveTimerHandle(udg_Fox_InfectiousPresenceHash,  GetHandleId(zombieDeathTimer), 1, zombieDoTTimer)
                        
                // Save variables for the zombieDoTTimer
                call SaveUnitHandle(udg_Fox_InfectiousPresenceHash,   GetHandleId(zombieDoTTimer),   0, zombieUnit)
                // Save spellFX
                call SaveEffectHandle(udg_Fox_InfectiousPresenceHash, GetHandleId(zombieDoTTimer),   1, spellFX)
                                        
                // Start Timers
                // Start zombieDeathTimer
                call TimerStart(zombieDeathTimer, Fox_InfectiousPresenceZombieTime(), false, function Fox_InfectiousPresence_Main_TimerFunc)
                // Start zombieDoTTimer
                call TimerStart(zombieDoTTimer, Fox_InfectiousPresenceZombieTickTime(), true, function Fox_InfectiousPresence_Main_TimerFunc2)
                        
                // Exit loop
                exitwhen true
            endif
        endif
        call GroupRemoveUnit(udg_Fox_InfectiousPresenceGroup, unitToCheck)
    endloop
    call GroupClear(udg_Fox_InfectiousPresenceGroup)
    
    //-----------------------------------
    // Clean-up
    //-----------------------------------
    // Null variables
    set zombieDeathTimer    = null
    set zombieUnit          = null
    set unitToCheck         = null
    set trigPlayer          = null
    set spellFX             = null
endfunction

// This function Initializes the Spell
function Trig_InfectiousPresenceInitialize takes nothing returns nothing
    local integer i = 0
    // Initialize global Hash
    set udg_Fox_InfectiousPresenceHash = InitHashtable()
    // Initialize global Group
    set udg_Fox_InfectiousPresenceGroup = CreateGroup()
    // Setup Spells
    loop
        exitwhen i > 15
        if (GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING) then
            call SetPlayerAbilityAvailable(Player(i), Fox_InfectiousPresenceAbil(2), false)
            call SetPlayerAbilityAvailable(Player(i), Fox_InfectiousPresenceAbil(3), false)
        endif
        set i = (i + 1)
    endloop
endfunction

// This function is the actions part of the trigger and calls the needed function
function Trig_InfectiousPresence_Actions takes nothing returns nothing
    local integer tech      = GetResearched()
    local unit dyingUnit    = GetDyingUnit()
    // If Researching
    if (tech == Fox_InfectiousPresenceTech()) then
        // Call Research Spell for player
        call Fox_InfectiousPresenceResearched(GetTriggerPlayer())
        
    // If unit dies
    elseif (GetUnitTypeId(dyingUnit) != 0) then
        if ((IsUnitType(dyingUnit, UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(dyingUnit, UNIT_TYPE_HERO) == false) and (IsUnitType(dyingUnit, UNIT_TYPE_SUMMONED) == false) and (IsUnitType(dyingUnit, UNIT_TYPE_UNDEAD) == false)) then
            // The Spell casting function
            call Fox_InfectiousPresenceDeathActions(dyingUnit)
        endif
    
    // Map Initialization
    else
        // Initialize Spell
        call Trig_InfectiousPresenceInitialize()
    endif
endfunction

//===========================================================================
function InitTrig_InfectiousPresence takes nothing returns nothing
    set gg_trg_InfectiousPresence = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_InfectiousPresence, EVENT_PLAYER_UNIT_RESEARCH_FINISH )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_InfectiousPresence, EVENT_PLAYER_UNIT_DEATH )
    call TriggerRegisterTimerEventSingle( gg_trg_InfectiousPresence, 0.50 )
    call TriggerAddAction( gg_trg_InfectiousPresence, function Trig_InfectiousPresence_Actions )
endfunction
JASS:
// Spell Config

// This function returns the Ability of the Spell
constant function Fox_UnholyLightAbil takes nothing returns integer
    // Change this to the ability of the spell
    return 'A00U'
endfunction

// This function returns the range of the Spell
constant function Fox_UnholyLightRange takes nothing returns real
    // Change this to the first range of the ability
    return 512.0
endfunction

// This function returns the Damaging Spell Effect model's path
constant function Fox_UnholyLightSFX_1 takes nothing returns string
    // Change this to the Damaging Spell Effect model's path
    return "Abilities\\Spells\\Human\\Slow\\SlowCaster.mdl"
endfunction

// This function returns the Healing Spell Effect model's path
constant function Fox_UnholyLightSFX_2 takes nothing returns string
    // Change this to the Healing Spell Effect model's path
    return "Abilities\\Spells\\Items\\AIma\\AImaTarget.mdl"
endfunction

// Constant function returning the amount of ticks per second
constant function Fox_UnholyLight_TicksPerSec takes nothing returns real
    // Change this to the amount of ticks per second
    return 1.0 / 3.0 // 1 ticks every 3 seconds
endfunction

// This function returning the amount of Damage done per tick
function Fox_UnholyLight_CalcSpellDmg takes unit hero returns real
    // Return Damage
    return (GetHeroInt(hero, true) * 0.75)
endfunction

// Functions

// Constant function returning the delay of the timer
constant function Fox_UnholyLight_TickTime takes nothing returns real
    return 1.0 / Fox_UnholyLight_TicksPerSec()
endfunction

// Constant function returning the amount of time the spell lasts
constant function FoxUnholyLight_CastDuration takes nothing returns real
    return 12.0
endfunction

// Constant function returning the amount of times the Spell Fires (Ticks)
constant function Fox_UnholyLight_TotalTicks takes nothing returns real
    return FoxUnholyLight_CastDuration() / Fox_UnholyLight_TickTime()
endfunction

// Constant function returning the amount of hashes used before the start of the spellFX variables
constant function Fox_UnholyLight_HashesUsed takes nothing returns integer
    return 2
endfunction

// This function returning the amount of Damage done per tick
function Fox_UnholyLight_AbsVal takes real number returns real
    if (number < 0) then
        return number * -1
    endif
    return number
endfunction

// This function Removes all old Spell Effects
function Fox_UnholyLight_RemoveEffects takes integer timerHandleID returns nothing
    //-----------------------------------
    // Declare locals
    //-----------------------------------
    // Declare spellFX
    local effect spellFX
    // Declare spellFXAmount
    local integer spellFXAmount
    // Declare i
    local integer i
    
    //-----------------------------------
    // Set variables
    //-----------------------------------
    set i = 0
    
    //-----------------------------------
    // Load variables
    //-----------------------------------
    // Load spellFXAmount
    set spellFXAmount   = LoadInteger(udg_Fox_UnholyLightHash, timerHandleID, 3)
    
    //-----------------------------------
    // Actions
    //-----------------------------------
    loop
        // Increase loop variable i
        set i = i + 1
        // Exit if i is greater then the amount of Spell Effects
        exitwhen i > spellFXAmount
        // Load spellFX
        set spellFX = LoadEffectHandle(udg_Fox_UnholyLightHash, timerHandleID, Fox_UnholyLight_HashesUsed() + spellFXAmount)
        // Destroy spellFX
        call DestroyEffect(spellFX)
    endloop
    // Save spellFXAmount
    call SaveInteger(udg_Fox_UnholyLightHash, timerHandleID, 3, 0)

endfunction

// Checks if the Filter Unit is alive
function Fox_UnholyLightFilterUnitIsAlive takes nothing returns boolean
    // return if the Filter Unit is alive
    return (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0)
endfunction

// This function is the Timer's function
function Fox_UnholyLight_TimerFunc takes nothing returns nothing
    // Declare locals
    local timer castTimer
    local unit hero
    local unit unitToCheck
    local player castingPlayer
    local real dmg
    local real healthPool
    local boolean damageHit
    local real timesRan
    local effect spellFX
    local integer spellFXAmount

    // Set castTimer
    set castTimer = GetExpiredTimer()
        
    // Load variables
    // Load hero
    set hero            = LoadUnitHandle(     udg_Fox_UnholyLightHash, GetHandleId(castTimer), 0)
    // Load timesRan
    set timesRan        = LoadReal(        udg_Fox_UnholyLightHash, GetHandleId(castTimer), 1)
    
    // Set variables
    // Set the castingPlayer to the Owner of the Hero
    set castingPlayer = GetOwningPlayer(hero)
    // Set healthPool
    set healthPool = 0
    // Increase timesRan
    set timesRan = timesRan + 1.0
    // Set spellFXAmount
    set spellFXAmount   = 0
    
    // Actions
    // Save timesRan
    call SaveReal(udg_Fox_UnholyLightHash, GetHandleId(castTimer), 1, timesRan)
    // Remove all old Spell Effects
    call Fox_UnholyLight_RemoveEffects(GetHandleId(castTimer))
            
    // If it has not ran more the 6 times and the hero is alive
    if ((timesRan < Fox_UnholyLight_TotalTicks() + 1) and (GetUnitState(hero, UNIT_STATE_LIFE) > 0)) then
        // Clear global Groups just in case
        call GroupClear(udg_Fox_UnholyLightGroupAll)
        call GroupClear(udg_Fox_UnholyLightPlayerUnits)
        // Set the testGroup to all units
        call GroupEnumUnitsInRange(udg_Fox_UnholyLightGroupAll, GetUnitX(hero), GetUnitY(hero), Fox_UnholyLightRange(), Filter(function Fox_UnholyLightFilterUnitIsAlive))
        // Set the Damage Amount
        set dmg = Fox_UnholyLight_CalcSpellDmg(hero)
        
        // Loop through all Units in Area of spell
        loop
            set unitToCheck = FirstOfGroup(udg_Fox_UnholyLightGroupAll)
            exitwhen unitToCheck == null
            // Actions
            // if unitToCheck is an enemy unit
            if (IsUnitEnemy(unitToCheck, castingPlayer)) then
                // Actions
                set damageHit = UnitDamageTarget(hero, unitToCheck, dmg, false, false, null, null, null)
                if (damageHit) then
                    // Add the damage done to the health pool to heal caster's units
                    set healthPool = healthPool + dmg
                    // Add Special Effect
                    set spellFX = AddSpecialEffectTarget(Fox_UnholyLightSFX_1(), unitToCheck, "origin") 
                    // Increase spellFXAmount
                    set spellFXAmount = spellFXAmount + 1
                    // Save Special Effect
                    call SaveEffectHandle(udg_Fox_UnholyLightHash, GetHandleId(castTimer), Fox_UnholyLight_HashesUsed() + spellFXAmount, spellFX)
                endif
            elseif (GetOwningPlayer(unitToCheck) == castingPlayer) then                    
                // Add unit to playerUnits
                call GroupAddUnit(udg_Fox_UnholyLightPlayerUnits, unitToCheck)
            endif
            // Remove unitToCheck from testGroup
            call GroupRemoveUnit(udg_Fox_UnholyLightGroupAll, unitToCheck)
        endloop
        
        // Insure that that the group count is greater than 0 (Avoid possible dividing by 0 crash)
        if (CountUnitsInGroup(udg_Fox_UnholyLightPlayerUnits) > 0) then
            // Set the Healing Amount
            set dmg = Fox_UnholyLight_AbsVal(healthPool / CountUnitsInGroup(udg_Fox_UnholyLightPlayerUnits) + 25.0) * - 1.0
            // Loop through all playerUnits
            //  - heal them based on healthPool
            loop
                set unitToCheck = FirstOfGroup(udg_Fox_UnholyLightPlayerUnits)
                exitwhen unitToCheck == null
                // Actions
                set damageHit = UnitDamageTarget(hero, unitToCheck, dmg, false, false, null, null, null)
                if (damageHit) then
                    // Add Special Effect
                    set spellFX = AddSpecialEffectTarget(Fox_UnholyLightSFX_2(), unitToCheck, "origin") 
                    // Increase spellFXAmount
                    set spellFXAmount = spellFXAmount + 1
                    // Save Special Effect
                    call SaveEffectHandle(udg_Fox_UnholyLightHash, GetHandleId(castTimer), Fox_UnholyLight_HashesUsed() + spellFXAmount, spellFX)
                endif
                // Remove unitToCheck from testGroup
                call GroupRemoveUnit(udg_Fox_UnholyLightPlayerUnits, unitToCheck)
            endloop
        endif
        // Clear global groups now
        call GroupClear(udg_Fox_UnholyLightGroupAll)
        call GroupClear(udg_Fox_UnholyLightPlayerUnits)

        // Clean-up
        // Null variables
        set castTimer       = null
        set hero            = null
        set unitToCheck     = null
        set castingPlayer   = null
        
    else
        // Clean-up
        // Remove all old Effects
        call Fox_UnholyLight_RemoveEffects(GetHandleId(castTimer))
                
        // Remove all saved Data
        call FlushChildHashtable(udg_Fox_UnholyLightHash, GetHandleId(castTimer))
        
        // Pause Timer
        call PauseTimer(castTimer)
        
        // Destory handles
        call DestroyTimer(castTimer)
        
        // Null variables
        set castTimer       = null
        set hero            = null
        set unitToCheck     = null
        set castingPlayer   = null
    endif

endfunction

// This function handles the casting of the spell
function Fox_UnholyLightSpellCasted takes unit hero returns nothing
    // Declare locals
    local timer castTimer
    local real timesRan
    local integer spellFXAmount

    // Set variables
    // Create castTimer
    set castTimer       = CreateTimer()
    // Set timesRan
    set timesRan        = 0
    // Set spellFXAmount
    set spellFXAmount   = 0
    
    // Save variables
    // Save hero
    call SaveUnitHandle(udg_Fox_UnholyLightHash, GetHandleId(castTimer), 0, hero)
    // Save timesRan
    call SaveReal(      udg_Fox_UnholyLightHash, GetHandleId(castTimer), 1, timesRan)
    // Save spellFXAmount
    call SaveInteger(   udg_Fox_UnholyLightHash, GetHandleId(castTimer), 2, spellFXAmount)
    
    // Start Timer
    call TimerStart(castTimer, Fox_UnholyLight_TickTime(), true, function Fox_UnholyLight_TimerFunc)
    
endfunction

// This function Initializes the Spell
function Trig_UnholyLightInitialize takes nothing returns nothing
    // Set Initialize Hash
    set udg_Fox_UnholyLightHash         = InitHashtable()
    // Initialize global Groups
    set udg_Fox_UnholyLightGroupAll     = CreateGroup()
    set udg_Fox_UnholyLightPlayerUnits  = CreateGroup()
endfunction

// This function is the actions part of the trigger and calls the needed function
function Trig_UnholyLight_Actions takes nothing returns nothing
    local integer spellId   = GetSpellAbilityId()    
    local unit hero         = GetTriggerUnit()
    // If Casting
    if (spellId == Fox_UnholyLightAbil()) then        
        // The Spell casting function
        call Fox_UnholyLightSpellCasted(hero)
    
    // Map Initialization
    else
        // Initialize Spell
        call Trig_UnholyLightInitialize()
    endif
endfunction

//===========================================================================
function InitTrig_UnholyLight takes nothing returns nothing
    set gg_trg_UnholyLight = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_UnholyLight, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( gg_trg_UnholyLight, function Trig_UnholyLight_Actions )
endfunction

Update 09-17-11
  • Updated spells to use global Groups
  • Updated spells to entirely in one script
  • Updated spells to have a disabled trigger with the required global variables in it
  • Updated spells to not use GetAllUnitsInRect()
  • Updated spells to not use global variables for configuration
  • Removed the extra comments
  • Replaced the use of Locations, and used other calls to get the script to work
  • Posted updated spells Triggers

Keywords:
Evil, Dark, Undead, Zombie, Blight, Tree, Gold Mine, Passive, Aura
Contents

Fox Spells Pack 1.0 (Map)

Reviews
16 July 2012 Bribe: This spellpack is decent, thanks for the submission. Approved 3.2/5.

Moderator

M

Moderator

16 July 2012
Bribe: This spellpack is decent, thanks for the submission. Approved 3.2/5.
 
• If you use Jass, try to become familiar with coordinates. GetUserLoc() could be replaced with GetUnitX() and GetUnitY().
• Don't use such a heavy documentation, under every local variable. You could add comments next to them.
• You don't need GUI variables for confugrables, the only thing needed is the hashtable. The other ones can be replaced with functions that return the value needed. Implement them in one trigger, there's no reason to use two of them, just for declaration.

These are the most basic, yet most effective changes. This cannot be approved for now.
 
JASS:
function Fox_CursedGroundAbil takes integer id returns integer
    if (id == 1) then
        // Change this to the first ability of the spell
        return 'A001'
    elseif (id == 2) then
        // Change this to the second ability of the spell
        return 'A002'
    elseif (id == 3) then
        // Change this to the third ability of the spell
        return 'A003'
    elseif (id == 4) then
        // Change this to the Hero ability of the spell
        return 'A00I'
    else
        return 0
    endif
endfunction

Instead of this long block, you could just use an array and return array[id].
You can do the same thing for the other functions.
For the spell damage or times-calculating functions, you could use a mathematical formula instead of an if block.
It's way better.

And you really don't need to use those BJ functions.

JASS:
call CreateNUnitsAtLoc(1, Fox_CursedGroundDummy(), castingPlayer, targetPoint, bj_UNIT_FACING )
// store the created unit in dummyUnit
set dummyUnit = GetLastCreatedUnit()

Those 2 lines can simply be this:

set dummyUnit = CreateUnit(castingPlayer, Fox_CursedGroundDummy(), GetLocationX(targetPoint), GetLocationY(targetPoint), 0)

Actually, you shouldn't even be using locations.
They have no use here. Using coordinates is a lot better, faster, and uses less memory :p

And instead of adding an event to the trigger to initialize the spell, why don't you do call Trig_CursedGroundInitialize() inside the init function instead?
It's less cumbersome :3

edit
You should also call the initialization function of UnholyLight inside the InitTrig because right now, it seems
like it would just ignore the first cast.
 
Level 3
Joined
Aug 27, 2011
Messages
41
Ok I'll look for the Bjs, does anyone have a list of useless ones, or do I just need to look for native alternatives?

And I didn't think the array would be very easy for the people who arn't very good with coding but I'll change it.

And I'll fix the Init. function.
 
Top