• 🏆 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!

Metaversal Spell Pack v1.03 [Deuterium]

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.

Deuterium's Metaversal Spellpack


Spell Description
The caster throws a ball of fire towards an enemy unit which burns the target for 20 damage and overheats its armor dealing extra damage depending on the target's armor every 1 second.
v1.00
- Released

v1.01
- Reworked

Dark_Dragon
- Fixing a few mistakes

- LibraryDT (Deuterium)
- ArmorUtils (Rising_Dusk)

JASS:
scope Balminess

globals
    private integer array DAMAGE_INTERVALS
    private real array DAMAGE_INTERVAL_TIME_GAP
    private real array BASE_DAMAGE
    private real array DAMAGE_MULTIPLIER
endglobals

//===========================================================================
        
    ////////////////////////////////////
    //          ADJUSTABLES           //
    ////////////////////////////////////
      
    globals
    
        // --- IDs ---
        private constant integer    ABILITY_ID                      = 'A008'            // The ID of the Balminess ability
        private constant integer    BUFF_ABILITY_ID                 = 'A009'            // The ID of the BA_Burn ability
        private constant integer    BUFF_ID                         = 'B002'            // The ID of the BA_Burn buff
        
        // --- Missile settings ---
        private constant string     MISSILE_MODEL                   = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"       // The model of the missile
        private constant real       MISSILE_SPEED                   = 30.               // The speed of the missile
        private constant real       MISSILE_COLLISION_RANGE         = 30.               // The collision range of the missile
        private constant real       MISSILE_HEIGHT                  = 80.               // The height of missile
        private constant real       MISSILE_SIZE                    = 1.                // The size of the missile
        private constant real       MISSILE_OFFSET                  = 0.                // The missile's offset from the caster at creation
        
        // --- Damage and attack types settings ---
        private constant attacktype ATTACK_TYPE                     = ATTACK_TYPE_CHAOS // The attack type of the damage dealt
        private constant damagetype DAMAGE_TYPE                     = DAMAGE_TYPE_FIRE  // The damage type of the damage dealt
        
        // --- Special effects settings ---
        private constant string     TARGET_SFX                      = "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"  // The special effect attached to the target being damaged
        private constant string     TARGET_SFX_ATTACHMENT_PT        = "chest"           // The attachment point for the special effect on the target being damaged
        
        // --- Core settings ---
        private constant real       TIMEOUT                         = .03               // The time gap at which the main timer runs
        
    endglobals

    private function Setup takes nothing returns nothing
        
        // General Setup note:
        //      the array integer refers to the level of the intended ability
        
        
        // --- Damage properties ---
        
        // Damage formula would be:
        //      BASE_DAMAGE + (DAMAGE_MULTIPLIER x Target's armor)
        
        // The number of intervals for the damage to occur
        set DAMAGE_INTERVALS[1] = 10
        set DAMAGE_INTERVALS[2] = 10
        set DAMAGE_INTERVALS[3] = 10
        set DAMAGE_INTERVALS[4] = 10
        
        // The number of the time gap between each damage interval
        set DAMAGE_INTERVAL_TIME_GAP[1] = 1.
        set DAMAGE_INTERVAL_TIME_GAP[2] = 1.
        set DAMAGE_INTERVAL_TIME_GAP[3] = 1.
        set DAMAGE_INTERVAL_TIME_GAP[4] = 1.
        
        // The base damage dealt regardless of the target's armor
        set BASE_DAMAGE[1] = 20.
        set BASE_DAMAGE[2] = 20.
        set BASE_DAMAGE[3] = 20.
        set BASE_DAMAGE[4] = 20.
        
        // The factor to which the targer's armor is multiplied and whose product is then dealt in damage
        set DAMAGE_MULTIPLIER[1] = 1.
        set DAMAGE_MULTIPLIER[2] = 2.
        set DAMAGE_MULTIPLIER[3] = 3.
        set DAMAGE_MULTIPLIER[4] = 4.
        
    endfunction

    ////////////////////////////////////
    //        ADJUSTABLES END         //
    ////////////////////////////////////

//===========================================================================
    
private struct BA

//= Struct Variables ========================================================

    unit tr     // Triggering unit
    player pt   // Owner of the triggering unit
    integer lvl // Level of the ability
    
    unit ta     // Target unit
    real tx     // Target's X
    real ty     // Target's Y
    effect e    // Effect attached to target

    unit m      // Missile
    
    real f      // Armor info
    
    real tco    // Timer counter
    integer ico // Interval counter
    
    timer time  // Timer variable
    
    debug boolean bool
    
//= destroy ================================================================

    private method destroy takes nothing returns nothing
        call PauseTimer(this.time)
        call FlushTimerUserData(this.time)
        call DestroyTimer(this.time)
        
        call UnitRemoveAbility(this.ta, BUFF_ID)
        
        call DestroyEffect(this.e)
        
        set this.tr     = null
        set this.pt     = null
        set this.ta     = null
        set this.e      = null
        set this.m      = null
        set this.time   = null
        set this.ico    = 0
        
        debug call BJDebugMsg("|cffc3dbffBalminess:|r Struct instance |cffff0000" + I2S(this) + "|r destroyed")
        debug call BJDebugMsg(" ")
        debug set this.bool = false
        
        call .deallocate()
    endmethod
    
//= Damage Over Time ========================================================

    private static method DoT takes nothing returns nothing
        
    // --- Announcing struct instance and running time counter ---
        local BA d = BA(GetTimerUserData(GetExpiredTimer()))
        set d.tco = d.tco + TIMEOUT
        
    // --- Debug ---
        debug if d.bool == false then
        debug      call BJDebugMsg("|cffc3dbffBalminess:|r Target hit")
        debug      call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug      call BJDebugMsg(" ")
        debug      set d.bool = true
        debug endif
        
    // --- Checking if the target is dead to terminate the instance ---
        if IsUnitType(d.ta, UNIT_TYPE_DEAD) then
            debug call BJDebugMsg("|cffc3dbffBalminess:|r Target died")
            debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
            debug call BJDebugMsg(" ")
            
            set d.tco = 0.
            call d.destroy()
            return
        endif
        
    // --- Checking if it's time to damage ---
        if d.tco >= DAMAGE_INTERVAL_TIME_GAP[d.lvl] then
            set d.tco = 0.
            set d.ico = d.ico + 1
            
            debug call BJDebugMsg("|cffc3dbffBalminess:|r Target damaged -- Damage instance: " + I2S(d.ico))
            debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
            debug call BJDebugMsg(" ")
            
    // --- Getting target's armor ---
            if GetUnitArmor(d.ta) > 0. then
                set d.f = GetUnitArmor(d.ta)
            else
                set d.f = 0.
            endif
    
    // --- Damaging target ---
            call UnitDamageTarget(d.tr, d.ta, (BASE_DAMAGE[d.lvl] + (DAMAGE_MULTIPLIER[d.lvl] * d.f)), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE_WHOKNOWS)
            
    // --- Checking if all intervals ran to terminate the instance ---
            if d.ico >= DAMAGE_INTERVALS[d.lvl] then
                debug call BJDebugMsg("|cffc3dbffBalminess:|r All intervals ran")
                debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
                debug call BJDebugMsg(" ")
                
                call d.destroy()
            endif
        endif
    endmethod
    
//= Missile's Motion ========================================================

    private static method Loop takes nothing returns nothing
    
    // --- Announcing struct instance ---
        local BA d = BA(GetTimerUserData(GetExpiredTimer()))
    
    // --- Debug ---
        debug if d.bool == false then
        debug      call BJDebugMsg("|cffc3dbffBalminess:|r Missile is moving")
        debug      call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug      call BJDebugMsg(" ")
        debug      set d.bool = true
        debug endif
        
    // --- Moving missile ---
        set d.tx = GetUnitX(d.ta)
        set d.ty = GetUnitY(d.ta)
        call MoveMissileDT(d.m, d.tx, d.ty, MISSILE_SPEED)
        
    // --- Checking if missile collided with target to detroy missile ---
        if GetDistanceBetweenPointsDT(GetUnitX(d.m), GetUnitY(d.m), d.tx, d.ty) <= MISSILE_COLLISION_RANGE then
            call CastTargetDT(d.m, d.ta, BUFF_ABILITY_ID, "curse", d.lvl)
            call DestroyMissileDT(d.m)
            set d.e = AddSpecialEffectTarget(TARGET_SFX, d.ta, TARGET_SFX_ATTACHMENT_PT)
            
            debug set d.bool = false
    
    // --- Running damage over time ---
            call PauseTimer(d.time)
            call TimerStart(d.time, TIMEOUT, true, function BA.DoT)
        endif
    endmethod
    
//= Initial Actions =========================================================

    private static method Create takes nothing returns nothing
    
    // --- Allocating new struct instance ---
        local BA d = BA.allocate()
    
    // --- Debug ---
        debug call BJDebugMsg("|cffc3dbffBalminess:|r Initiated")
        debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug call BJDebugMsg(" ")
        
    // --- Setting some variables ---
        set d.tr = GetTriggerUnit()
        set d.pt = GetOwningPlayer(d.tr)
        set d.lvl = GetUnitAbilityLevel(d.tr, ABILITY_ID)
        
        set d.ta = GetSpellTargetUnit()
        
        set d.m = CreateMissileDT(d.pt, GetUnitX(d.tr), GetUnitY(d.tr), GetUnitFacing(d.tr), MISSILE_OFFSET, MISSILE_MODEL, "origin", MISSILE_HEIGHT, MISSILE_SIZE)
    
    // --- Creating and running timer to move missile ---
        set d.time = CreateTimer()
        call SetTimerUserData(d.time, integer(d))
        call TimerStart(d.time, TIMEOUT, true, function BA.Loop)
    endmethod

//= Condition and Initializer ===============================================

    private static method ConditionCheck takes nothing returns boolean
        return GetSpellAbilityId() == ABILITY_ID
    endmethod

    private static method onInit takes nothing returns nothing
        call SpellInitDT(EVENT_PLAYER_UNIT_SPELL_EFFECT, function BA.Create, function BA.ConditionCheck)
        
        call Setup()
        
        call PreloadSpecialEffectDT(MISSILE_MODEL)
        call PreloadSpecialEffectDT(TARGET_SFX)
    endmethod

endstruct
    
endscope
Spell Description
The caster tends to let his target in on his pain dealing damage proportional to the caster's lost health over time. Every instance at which the target get's damage, it loses armor. If the target dies under the effect of Foltern, the caster tends to gain a certain percentage of his lost health.
v1.00
- Released

v1.01
- Reworked

- LibraryDT (Deuterium)

Dark_Dragon
- Improving the onDestroy method

-BerZeKeR-
- The idea of decreasing the target's armor
- The advice on special effects

JASS:
scope Foltern

globals
    private integer array DAMAGE_INTERVALS
    private real array DAMAGE_INTERVAL_TIME_GAP
    private real array DAMAGE_RATIO
    private real array BASE_DAMAGE
endglobals

//===========================================================================
        
    ////////////////////////////////////
    //          ADJUSTABLES           //
    ////////////////////////////////////
      
    globals
    
        // --- IDs ---
        private constant integer    ABILITY_ID                      = 'A000'            // The ID of the Balminess ability
        private constant integer    ARMOR_ABILITY_ID                = 'A001'            // The ID of the FO_Armor ability
        
        // --- Damage and attack types settings ---
        private constant attacktype ATTACK_TYPE                     = ATTACK_TYPE_NORMAL// The attack type of the damage dealt
        private constant damagetype DAMAGE_TYPE                     = DAMAGE_TYPE_DEATH // The damage type of the damage dealt
        
        // --- Special effects settings ---
        private constant string     RUN_THROUGH_SFX                 = "Abilities\\Spells\\Human\\Banish\\BanishTarget.mdl"              //The special effect attached to the target throughout the whole cast
        private constant string     RUN_THROUGH_SFX_ATTACHMENT_PT   = "origin"           // Attachment point  
        
        private constant string     INIT_SFX_1                      = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl"   //The special effect attached to the target when the spell starts
        private constant string     INIT_SFX_1_ATTACHMENT_PT        = "origin"          // Attachment point
        
        private constant string     INIT_SFX_2                      = "units\\nightelf\\SpiritOfVengeance\\SpiritOfVengeance.mdl"       //The special effect attached to the  target when the spell starts
        private constant string     INIT_SFX_2_ATTACHMENT_PT        = "origin"          // Attachment point
        
        private constant string     DAMAGE_SFX                      = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"          //The special effect attached to the target every instance it gets damaged
        private constant string     DAMAGE_SFX_ATTACHMENT_PT        = "chest"           // Attachment point
        
        private constant string     DEATH_SFX_1                     = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"   //The special effect attached to the target and caster when the caster dies
        private constant string     DEATH_SFX_1_ATTACHMENT_PT       = "origin"          // Attachment point
        
        private constant string     DEATH_SFX_2                     = "units\\nightelf\\SpiritOfVengeance\\SpiritOfVengeance.mdl"       //The special effect attached to the target and caster when the caster dies
        private constant string     DEATH_SFX_2_ATTACHMENT_PT       = "origin"          // Attachment point

        // --- Texttag settings ---
        private constant boolean    TEXTAG_BOOLEAN                  = true              // If true, shows texttag, and if false, doesn't
        private constant integer    TEXTAG_COLOR_RED                = 75                // Texttag's red coloring (ranges from 0 to 255)
        private constant integer    TEXTAG_COLOR_GREEN              = 0                 // Texttag's green coloring (ranges from 0 to 255)
        private constant integer    TEXTAG_COLOR_BLUE               = 100               // Texttag's blue coloring (ranges from 0 to 255)
        private constant real       TEXTAG_FADE_TIME                = 1.                // Texttag's fading time
        private constant real       TEXTAG_SIZE                     = .025              // Texttag's size
        private constant real       TEXTAG_HEIGHT_OFFSET            = 32.               // Texttag's height offset
        private constant real       TEXTAG_VELOCITY                 = .036              // Texttag's upwards velocity
        
        // --- Core settings ---
        private constant real       TIMEOUT                         = .03               // The time gap at which the main timer runs
    endglobals
    
    private function Setup takes nothing returns nothing
    
        // General Setup note:
        //      the array integer refers to the level of the intended ability
        
        
        // --- Damage properties ---
        
        // Damage formula would be:
        //      BASE_DAMAGE + (DAMAGE_RATIO x Triggering unit's lost life)
        
        // The number of intervals for the damage to occur
        set DAMAGE_INTERVALS[1] = 4
        set DAMAGE_INTERVALS[2] = 5
        set DAMAGE_INTERVALS[3] = 6
        set DAMAGE_INTERVALS[4] = 7
        
        // The number of the time gap between each damage interval
        set DAMAGE_INTERVAL_TIME_GAP[1] = 4.
        set DAMAGE_INTERVAL_TIME_GAP[2] = 4.
        set DAMAGE_INTERVAL_TIME_GAP[3] = 4.
        set DAMAGE_INTERVAL_TIME_GAP[4] = 4.
        
        // The percentage of the triggering unit's lost life dealt in damage
        set DAMAGE_RATIO[1] = .10
        set DAMAGE_RATIO[2] = .10
        set DAMAGE_RATIO[3] = .10
        set DAMAGE_RATIO[4] = .10
        
        // The base damage dealt regardless of the triggering unit's life
        set BASE_DAMAGE[1] = 25.
        set BASE_DAMAGE[2] = 25.
        set BASE_DAMAGE[3] = 25.
        set BASE_DAMAGE[4] = 25.
        
    endfunction
    
    //! objectediting
    
        // Armor lost per damage interval (Ability Editor -- FO_Armor):
        //      Adjust "Level # - Data - Defense Bonus" to the required values.
        //      The level number stands for the number of the damage instance
        //      and the inserted value stands for then sum of the lost armor at that instance.
    
    //! endobjectediting
    
    ////////////////////////////////////
    //        ADJUSTABLES END         //
    ////////////////////////////////////
    
//===========================================================================

private struct FO

//= Struct Variables ========================================================

    unit tr     // Triggering unit
    player pt   // Owner of the triggering unit
    integer lvl // Level of the ability
    
    unit ta     // Target unit
    effect e    // Special effect
    
    real h      // Damage to be dealt
    
    real tco    // Timer counter
    integer ico // Interval Counter
    
    timer time  // Timer variable
    
    debug boolean bool

//= onDestroy ===============================================================

    private method destroy takes nothing returns nothing
        call PauseTimer(this.time)
        call FlushTimerUserData(this.time)
        call DestroyTimer(this.time)
        
        call UnitRemoveAbility(this.ta, ARMOR_ABILITY_ID)
        
        call DestroyEffect(this.e)
        
        set this.tr     = null
        set this.pt     = null
        set this.ta     = null
        set this.e      = null
        set this.time   = null
        set this.tco    = 0.
        set this.ico    = 0
        
        debug call BJDebugMsg("|cffc3dbffFoltern:|r Struct instance |cffff0000" + I2S(this) + "|r destroyed")
        debug call BJDebugMsg(" ")
        debug set this.bool = false
        
        call .deallocate()
    endmethod
    
//= Damaging =========================================================

    private static method Loop takes nothing returns nothing
    
    // --- Announcing struct instance and running time counter ---
        local FO d = FO(GetTimerUserData(GetExpiredTimer()))
        set d.tco = d.tco + TIMEOUT
        
    // --- Debug ---
        debug if d.bool == false then
        debug      call BJDebugMsg("|cffc3dbffFoltern:|r Target damage pending")
        debug      call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug      call BJDebugMsg(" ")
        debug      set d.bool = true
        debug endif
    
        // --- Checking if it's time to damage ---
        if d.tco >= DAMAGE_INTERVAL_TIME_GAP[d.lvl] then
            set d.tco = 0.
            set d.ico = d.ico + 1
            set d.h = ((GetUnitState(d.tr, UNIT_STATE_MAX_LIFE) - GetUnitState(d.tr, UNIT_STATE_LIFE)) * DAMAGE_RATIO[d.lvl]) + BASE_DAMAGE[d.lvl]
            
        // --- Debug ---
            debug call BJDebugMsg("|cffc3dbffFoltern:|r Target damaged -- Damage instance: " + I2S(d.ico))
            debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
            debug call BJDebugMsg(" ")
            
        // --- Reducing armor ---
            if d.ico == 1 then
                call UnitAddAbility(d.ta, ARMOR_ABILITY_ID)
            endif
            call SetUnitAbilityLevel(d.ta, ARMOR_ABILITY_ID, d.ico)
            
        // --- Dealing damage ---
            call UnitDamageTarget(d.tr, d.ta, d.h, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE_WHOKNOWS)
            
        // --- Special effect ---
            call DestroyEffect(AddSpecialEffectTarget(DAMAGE_SFX, d.ta, DAMAGE_SFX_ATTACHMENT_PT))
            
        // --- Texttag ---
            if TEXTAG_BOOLEAN then
                call TextTagUnitDT(d.ta, I2S(R2I(d.h))+"!", TEXTAG_FADE_TIME, TEXTAG_SIZE, TEXTAG_HEIGHT_OFFSET, TEXTAG_VELOCITY, TEXTAG_COLOR_RED, TEXTAG_COLOR_GREEN, TEXTAG_COLOR_BLUE, 255)
            endif
            
        // --- Checking if all intervals ran to terminate the instance ---
            if d.ico >= DAMAGE_INTERVALS[d.lvl] then
                call d.destroy()
            endif
        endif
        
        // --- Checking if target died to heal triggering unit and terminate the instance ---
        if IsUnitType(d.ta, UNIT_TYPE_DEAD) then
            debug call BJDebugMsg("|cffc3dbffFoltern:|r Target died")
            debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
            debug call BJDebugMsg(" ")
            
            call SetUnitState(d.tr, UNIT_STATE_LIFE, (GetUnitState(d.tr, UNIT_STATE_LIFE) + d.h))
            call DestroyEffect(AddSpecialEffectTarget(DEATH_SFX_1, d.tr, DEATH_SFX_1_ATTACHMENT_PT))
            call DestroyEffect(AddSpecialEffectTarget(DEATH_SFX_2, d.tr, DEATH_SFX_2_ATTACHMENT_PT))
            call d.destroy()
        endif
    endmethod

//= Initial Actions =========================================================

    private static method Create takes nothing returns nothing

    // --- Allocating new struct instance ---
        local FO d = FO.allocate()
        
    // --- Debug ---
        debug call BJDebugMsg("|cffc3dbffFoltern:|r Initiated")
        debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug call BJDebugMsg(" ")
        
    // --- Setting some variables ---
        set d.tr = GetTriggerUnit()
        set d.pt = GetOwningPlayer(d.tr)
        set d.lvl = GetUnitAbilityLevel(d.tr, ABILITY_ID)
        
        set d.ta = GetSpellTargetUnit()
        
    // --- Special effects ---
        set d.e = AddSpecialEffectTarget(RUN_THROUGH_SFX, d.ta, RUN_THROUGH_SFX_ATTACHMENT_PT)
        call DestroyEffect(AddSpecialEffectTarget(INIT_SFX_1, d.ta, INIT_SFX_1_ATTACHMENT_PT))
        call DestroyEffect(AddSpecialEffectTarget(INIT_SFX_2, d.ta, INIT_SFX_2_ATTACHMENT_PT))
        
    // --- Creating and running timer to move missile ---
        set d.time = CreateTimer()
        call SetTimerUserData(d.time, integer(d))
        call TimerStart(d.time, TIMEOUT, true, function FO.Loop)
    endmethod

//= Condition and Initializer ===============================================

    private static method ConditionCheck takes nothing returns boolean
        return GetSpellAbilityId() == ABILITY_ID
    endmethod

    private static method onInit takes nothing returns nothing
        call SpellInitDT(EVENT_PLAYER_UNIT_SPELL_EFFECT, function FO.Create, function FO.ConditionCheck)
        
        call Setup()
        
        call PreloadSpecialEffectDT(RUN_THROUGH_SFX)
        call PreloadSpecialEffectDT(DAMAGE_SFX)
        call PreloadSpecialEffectDT(DEATH_SFX_1)
        call PreloadSpecialEffectDT(DEATH_SFX_2)
        call PreloadSpecialEffectDT(INIT_SFX_1)
        call PreloadSpecialEffectDT(INIT_SFX_2)
    endmethod
    
endstruct

endscope
Spell Description
The caster uses black magic upon his enemy rendering his target unable of regenerating life through any possible approach.
v1.00
- Released

v1.01
- Reworked

- LibraryDT (Deuterium)

JASS:
scope Hiatus

globals
    private real array BUFF_DURATION
endglobals

//===========================================================================
        
    ////////////////////////////////////
    //          ADJUSTABLES           //
    ////////////////////////////////////
      
    globals
    
        // --- IDs ---
        private constant integer    ABILITY_ID                      = 'A010'            // The ID of the Hiatus ability
        private constant integer    BUFF_ID                         = 'B003'            // The Id of the HI_Hiatus buff
        
        // --- Special effect settings ---
        private constant string     TARGET_BUFF_SFX                 = "Abilities\\Spells\\Undead\\Curse\\CurseTarget.mdl"       // The effect attached to the unit which has the buff
        private constant string     TARGET_BUFF_SFX_ATTACHMENT_PT   = "overhead"        // Special effect attachment point
        
        // --- Core settings ---
        private constant real       TIMEOUT                         = .03               // The time gap at which the main timer runs
        
    endglobals
    
    private function Setup takes nothing returns nothing
    
        // General Setup note:
        //      the array integer refers to the level of the intended ability
        
        // --- The duration of the buff on the enemy target ---
        set BUFF_DURATION[1] = 5.
        set BUFF_DURATION[2] = 7.
        set BUFF_DURATION[3] = 9.
        set BUFF_DURATION[4] = 11.
        
    endfunction
    
    ////////////////////////////////////
    //        ADJUSTABLES END         //
    ////////////////////////////////////
    
//===========================================================================
private struct HI

//= Struct Variables ========================================================

    player pt   // Owner of the triggering unit
    integer lvl // Level of the ability
    
    unit ta     // Target unit
    effect e    // Special effect
    
    real life   // Life variable
    real check  // Life checker
    
    real tco    // Time counter
    
    timer time  // Timer variable
    
    debug boolean bool
    
//= onDestroy ===============================================================

    private method destroy takes nothing returns nothing
        call PauseTimer(this.time)
        call FlushTimerUserData(this.time)
        call DestroyTimer(this.time)
        
        call DestroyEffect(this.e)
        
        set this.pt     = null
        set this.ta     = null
        set this.e      = null
        set this.time   = null
        set this.tco    = 0
        
        debug call BJDebugMsg("|cffc3dbffHiatus:|r Struct instance |cffff0000" + I2S(this) + "|r destroyed")
        debug call BJDebugMsg(" ")
        debug set this.bool = false
        
        call .deallocate()
    endmethod

//= Preventing Regen =================================================

    private static method Loop takes nothing returns nothing
    
    // --- Announcing struct instance and running timer counter ---
        local HI d = HI(GetTimerUserData(GetExpiredTimer()))
        set d.tco = d.tco + TIMEOUT
        
    // --- Debug ---
        debug if d.bool == false then
        debug      call BJDebugMsg("|cffc3dbffHiatus:|r Regen paused")
        debug      call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug      call BJDebugMsg(" ")
        debug      set d.bool = true
        debug endif
    
    // --- Ending instance target is dead or duration is over ---
        if (d.tco >= BUFF_DURATION[d.lvl]) or IsUnitType(d.ta, UNIT_TYPE_DEAD) then
            debug if d.tco >= BUFF_DURATION[d.lvl] then
            debug      call BJDebugMsg("|cffc3dbffHiatus:|r Duration ended")
            debug elseif IsUnitType(d.ta, UNIT_TYPE_DEAD) then
            debug      call BJDebugMsg("|cffc3dbffHiatus:|r Target died")
            debug endif
            debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
            debug call BJDebugMsg(" ")
            
            call d.destroy()
        endif
        
    // --- Preventing Regeneration ---
        set d.check = GetUnitState(d.ta, UNIT_STATE_LIFE)
        if d.check > d.life then
            call SetUnitState(d.ta, UNIT_STATE_LIFE, d.life)
        elseif d.check < d.life then
            set d.life = d.check
        endif
    endmethod

//= Initial Actions =========================================================

    private static method Create takes nothing returns nothing
    
    // --- Allocating new struct instance ---
        local HI d = HI.allocate()
        
    // --- Debug ---
        debug call BJDebugMsg("|cffc3dbffHiatus:|r Initiated")
        debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug call BJDebugMsg(" ")
        
    // --- Setting some variables ---
        set d.pt = GetOwningPlayer(GetTriggerUnit())
        set d.lvl = GetUnitAbilityLevel(GetTriggerUnit(), ABILITY_ID)
        
        set d.ta = GetSpellTargetUnit()
        set d.life = GetUnitState(d.ta, UNIT_STATE_LIFE)
        
    // --- Special effects ---
        set d.e = AddSpecialEffectTarget(TARGET_BUFF_SFX, d.ta, TARGET_BUFF_SFX_ATTACHMENT_PT)
        
    // --- Creating and running timer to prevent life regeneration ---
        set d.time = CreateTimer()
        call SetTimerUserData(d.time, integer(d))
        call TimerStart(d.time, TIMEOUT, true, function HI.Loop)
    endmethod

//= Condition and Initializer ===============================================

    private static method ConditionCheck takes nothing returns boolean
        return GetSpellAbilityId() == ABILITY_ID
    endmethod

    private static method onInit takes nothing returns nothing
        call SpellInitDT(EVENT_PLAYER_UNIT_SPELL_EFFECT, function HI.Create, function HI.ConditionCheck)
        
        call Setup()
        
        call PreloadSpecialEffectDT(TARGET_BUFF_SFX)
    endmethod
    
endstruct

endscope
Spell Description
The caster hurls an ancient orb of magic which deals certain damage to the target and fills up with a certaion percentage of the target's maximum mana to carry it back to teh caster.
v1.00
- Released

v1.01
- Converted from GUI to vJass

v1.02
- Fixed a bug

- LibraryDT (Deuterium)

JASS:
scope Impairment

globals
    private real array MANA_STEAL_RATIO
    private real array DAMAGE
endglobals

//===========================================================================
        
    ////////////////////////////////////
    //          ADJUSTABLES           //
    ////////////////////////////////////
      
    globals
        
        // --- IDs ---
        private constant integer    ABILITY_ID                      = 'A007'                // The ID of the Impairment ability
        
        // --- Missile settings ---
        private constant string     MISSILE_MODEL                   = "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl"   // The model of the missile
        private constant real       MISSILE_SIZE                    = 2.                    // The size of the missile
        private constant real       MISSILE_HEIGHT                  = 50.                    // The height of the missile
        private constant real       MISSILE_SPEED                   = 15.                   // The speed of the missile
        private constant real       MISSILE_COLLISION_RANGE         = 20.                   // The collision size of the missile
        private constant real       MISSILE_OFFSET                  = 50.                   // The missile's offset from the caster at creation

        private constant string     MISSILE_COLLISION_SFX           = "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl"   // The special effect attached at the target at collision
        private constant string     MISSILE_COLLISION_SFX_ATTACH    = "origin"              // Attachment point
        
        // --- Damage and attack types
        private constant attacktype ATTACK_TYPE                     = ATTACK_TYPE_NORMAL    // Attack type of the damage dealt
        private constant damagetype DAMAGE_TYPE                     = DAMAGE_TYPE_MAGIC     // Damage type of the damage dealt
        
        // --- Core settings ---
        private constant real       TIMEOUT                         = .03                   // The time gap at which the main timer runs
        
    endglobals
    
    private function Setup takes nothing returns nothing
    
        // General Setup note:
        //      the array integer refers to the level of the intended ability
        
        // --- Mana setting ---
        
        // The percentage of the mana stolen from the target (ex: 10.00 as in 10.00%)
        set MANA_STEAL_RATIO[1] = 10.
        set MANA_STEAL_RATIO[2] = 12.
        set MANA_STEAL_RATIO[3] = 14.
        set MANA_STEAL_RATIO[4] = 16.
        
        
        // --- Damage setting ---
        
        // The damage dealt to the target at missile collision
        set DAMAGE[1] = 80.
        set DAMAGE[2] = 100.
        set DAMAGE[3] = 120.
        set DAMAGE[4] = 140.
        
    endfunction

    ////////////////////////////////////
    //        ADJUSTABLES END         //
    ////////////////////////////////////
    
//===========================================================================

private struct IM

//= Struct Variables ========================================================

    unit tr     // Triggering unit
    integer lvl // Ability level
    
    unit ta     // Target unit
    
    unit m      // Missile Dummy
    
    timer time  // Timer
    
    real mana
    real manaratio
    
    debug boolean bool

//= onDestroy ===============================================================

    private method onDestroy takes nothing returns nothing
        call PauseTimer(this.time)
        call FlushTimerUserData(this.time)
        call DestroyTimer(this.time)
        
        call DestroyMissileDT(this.m)
        
        set this.tr     = null
        set this.ta     = null
        set this.m      = null
        set this.time   = null
        
        debug call BJDebugMsg("|cffc3dbffImpairment:|r Struct instance |cffff0000" + I2S(this) + "|r destroyed")
        debug call BJDebugMsg(" ")
        debug set this.bool = false
    endmethod

//= Moving Missile Towards Caster ===========================================

    private static method BackwardLoop takes nothing returns nothing
    
        // --- Announcing struct instance ---
        local IM d = IM(GetTimerUserData(GetExpiredTimer()))
        
        // --- Debug ---
        debug if d.bool == false then
        debug      call BJDebugMsg("|cffc3dbffImpairment:|r Missile moving towards caster")
        debug      call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug      call BJDebugMsg(" ")
        debug      set d.bool = true
        debug endif

        // --- Moving Missile ---
        call MoveMissileTargetDT(d.m, d.tr, MISSILE_SPEED)
        
        // --- Checking for collision ---
        if GetDistanceBetweenUnitsDT(d.m, d.tr) <= MISSILE_COLLISION_RANGE then
            debug call BJDebugMsg("|cffc3dbffImpairment:|r Missile collided with the caster")
            debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
            debug call BJDebugMsg(" ")
        
            call SetUnitState(d.tr, UNIT_STATE_MANA, GetUnitState(d.tr, UNIT_STATE_MANA) + d.manaratio)
            call d.destroy()
        endif
    endmethod

//= Moving Missile Towards Target ===========================================

    private static method ForwardLoop takes nothing returns nothing
    
        // --- Announcing struct instance ---
        local IM d = IM(GetTimerUserData(GetExpiredTimer()))
        
        // --- Debug ---
        debug if d.bool == false then
        debug      call BJDebugMsg("|cffc3dbffImpairment:|r Missile moving towards target")
        debug      call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug      call BJDebugMsg(" ")
        debug      set d.bool = true
        debug endif
    
        // --- Moving Missile ---
        call MoveMissileTargetDT(d.m, d.ta, MISSILE_SPEED)
        
        // --- Checking for collision ---
        if GetDistanceBetweenUnitsDT(d.m, d.ta) <= MISSILE_COLLISION_RANGE then
        
        // --- Debug ---
        debug call BJDebugMsg("|cffc3dbffImpairment:|r Missile collided with the target")
        debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug call BJDebugMsg(" ")
        debug set d.bool = false
        
        // --- Damaging target ---
            call UnitDamageTarget(d.m, d.ta, DAMAGE[d.lvl], true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE_WHOKNOWS)
        
        // --- Reducing mana ---
            set d.mana = GetUnitState(d.ta, UNIT_STATE_MANA)
            set d.manaratio = d.mana * MANA_STEAL_RATIO[d.lvl]/100.
            if d.mana >= d.manaratio then
                call SetUnitState(d.ta, UNIT_STATE_MANA, d.mana - d.manaratio)
            else
                call SetUnitState(d.ta, UNIT_STATE_MANA, 0.)
                set d.manaratio = d.mana
            endif
            
        // --- Special effect ---
            call DestroyEffect(AddSpecialEffectTarget(MISSILE_COLLISION_SFX, d.ta, MISSILE_COLLISION_SFX_ATTACH))
        
        // --- Setting timer to move the missile back towards the triggering unit ---
            call PauseTimer(d.time)
            call TimerStart(d.time, TIMEOUT, true, function IM.BackwardLoop)
        endif
    endmethod

//= Initial Actions =========================================================

    private static method Create takes nothing returns nothing
    
        // --- Allocation new struct instance ---
        local IM d = IM.allocate()
        
        // --- Debug ---
        debug call BJDebugMsg("|cffc3dbffImpairment:|r Initiated")
        debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug call BJDebugMsg(" ")
        
        // --- Setting some variables
        set d.tr = GetTriggerUnit()
        set d.lvl = GetUnitAbilityLevel(d.tr, ABILITY_ID)
        
        set d.ta = GetSpellTargetUnit()
        
        // --- Creating missile ---
        set d.m = CreateFiredMissileDT(d.tr, MISSILE_OFFSET, MISSILE_MODEL, "origin", MISSILE_HEIGHT, MISSILE_SIZE)
        
        // --- Starting timer to move missile towards target ---
        set d.time = CreateTimer()
        call SetTimerUserData(d.time, integer(d))
        call TimerStart(d.time, TIMEOUT, true, function IM.ForwardLoop)
    endmethod

//= Condition and Initializer ===============================================

    private static method ConditionCheck takes nothing returns boolean
        return GetSpellAbilityId() == ABILITY_ID
    endmethod

    private static method onInit takes nothing returns nothing
        call SpellInitDT(EVENT_PLAYER_UNIT_SPELL_EFFECT, function IM.Create, function IM.ConditionCheck)
        call Setup()
        
        call PreloadSpecialEffectDT(MISSILE_MODEL)
    endmethod
    
endstruct

endscope
Spell Description
The caster creates a temporal ward which mini-stuns enemy units at a certain range.
v1.00
- Released

v1.01
- Converted from GUI to vJass

- LibraryDT (Deuterium)

JASS:
scope StunningWard

globals
    private real array STUN_INTERVAL_TIME
    private real array STUN_INTERVALS
    private real array STUN_RADIUS
endglobals

//===========================================================================
        
    ////////////////////////////////////
    //          ADJUSTABLES           //
    ////////////////////////////////////
      
    globals
        
        // --- IDs ---
        private constant integer    ABILITY_ID                      = 'A005'            // The ID of the Balminess ability
        private constant integer    STUN_ABILITY_ID                 = 'A006'            // The ID of the SW_MiniStun ability
        private constant integer    WARD_ID                         = 'h001'            // The ID of the SW_Ward unit
    
        // --- Spell setting ---
        private constant boolean    WARD_INVULNERABLE               = false              // If set to true, ward is invulnerable
                                                                                        // If set to false, ward isn't invulnerable
        
    endglobals
    
    private function Setup takes nothing returns nothing
    
        // General Setup note:
        //      the array integer refers to the level of the intended ability
        
        
        // --- Stun settings ---
        
        // The time gap between each stun instance
        set STUN_INTERVAL_TIME[1] = 1.
        set STUN_INTERVAL_TIME[2] = 1.
        set STUN_INTERVAL_TIME[3] = 1.
        set STUN_INTERVAL_TIME[4] = 1.
        
        // The number of stun intervals plus the initial stun
        set STUN_INTERVALS[1] = 6
        set STUN_INTERVALS[2] = 8
        set STUN_INTERVALS[3] = 10
        set STUN_INTERVALS[4] = 12
        
        // The radius around the ward at which stunning takes effect
        set STUN_RADIUS[1] = 400.
        set STUN_RADIUS[2] = 400.
        set STUN_RADIUS[3] = 400.
        set STUN_RADIUS[4] = 400.
        
    endfunction

    //! objectediting
    
        // Stun duration (Ability Editor -- SW_MiniStun):
        //      Adjust "Level # - Stats - Duration" to the required values.
    
            
        // AoE targetting image size (Ability Editor -- Stunning Ward):
        //      Adjust "Level # - Area of Effect" to the required values.
    
    //! endobjectediting    
    
    ////////////////////////////////////
    //        ADJUSTABLES END         //
    ////////////////////////////////////
    
//===========================================================================

private struct SW

//= Struct Variables ========================================================

    unit tr     // Triggering unit
    player pt   // Triggering player
    integer lvl // Ability level
    
    unit w      // Ward
    real x      // Ward's X
    real y      // Ward's Y
    
    group g     // Group
    
    integer ico  // Interval counter
    
    timer time  // Timer
    
    static SW Temp

//= onDestroy ===============================================================

    private method destroy takes nothing returns nothing
        call PauseTimer(this.time)
        call FlushTimerUserData(this.time)
        call DestroyTimer(this.time)
        
        call DestroyGroup(this.g)
        
        set this.tr     = null
        set this.pt     = null
        set this.w      = null
        set this.g      = null
        set this.time   = null
        set this.ico     = 0
        
        debug call BJDebugMsg("|cffc3dbffStunning Ward:|r Struct instance |cffff0000" + I2S(this) + "|r destroyed")
        debug call BJDebugMsg(" ")
        
        call .deallocate()
    endmethod
    
//= Stun ==================================================================    

    private static method FilterOut takes nothing returns boolean
        set bj_lastCreatedUnit = GetFilterUnit()
        return (IsUnitEnemy(bj_lastCreatedUnit, SW.Temp.pt) == true) and (IsUnitType(bj_lastCreatedUnit, UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(bj_lastCreatedUnit, UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(bj_lastCreatedUnit, UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(bj_lastCreatedUnit, UNIT_TYPE_DEAD) == false)
    endmethod
    
    private static method GroupLoop takes nothing returns nothing
        call DummyCastTargetDT(SW.Temp.pt, GetEnumUnit(), STUN_ABILITY_ID, "thunderbolt", SW.Temp.lvl)
    endmethod

    private static method RunStun takes integer i returns nothing
        local SW d = i
        call GroupEnumUnitsInRange(d.g, d.x, d.y, STUN_RADIUS[d.lvl], Condition(function SW.FilterOut))
        call ForGroup(d.g, function SW.GroupLoop)
        call GroupClear(d.g)
        call DestroyCondition(Condition(function SW.FilterOut))
    endmethod

//= Timed Actions =========================================================

    private static method Loop takes nothing returns nothing
    
        // --- Announcing instance and running timer counter ---
        local SW d = SW(GetTimerUserData(GetExpiredTimer()))
        set SW.Temp = integer(d)
        set d.ico = d.ico + 1
        
        // --- Debug ---
        debug call BJDebugMsg("|cffc3dbffStunning Ward:|r Stunned -- Stun instance: " + I2S(d.ico))
        debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug call BJDebugMsg(" ")
        
        // --- Checking if ward is dead ---
        if IsUnitType(d.w, UNIT_TYPE_DEAD) then
            debug call BJDebugMsg("|cffc3dbffStunning Ward:|r Ward died")
            debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
            debug call BJDebugMsg(" ")
            
            call d.destroy()
            return
        endif
        
        // --- Stunning ---
        call SW.RunStun(d)
        
        // --- Checking if all intervals ran ---
        if d.ico >= STUN_INTERVALS[d.lvl] then
            debug call BJDebugMsg("|cffc3dbffStunning Ward:|r All intervals ran")
            debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
            debug call BJDebugMsg(" ")
        
            call d.destroy()
        endif
    endmethod

//= Initial Actions =========================================================

    private static method Create takes nothing returns nothing
    
        // --- Allocating new instance ---
        local SW d = SW.allocate()
        set SW.Temp = integer(d)
        
        // --- Debug ---
        debug call BJDebugMsg("|cffc3dbffStunning Ward:|r Initiated")
        debug call BJDebugMsg("|cffffcc00Struct instance:|r |cffff0000" + I2S(d) + "|r")
        debug call BJDebugMsg(" ")
        
        // --- Setting some variables ---
        set d.tr = GetTriggerUnit()
        set d.pt = GetOwningPlayer(d.tr)
        set d.lvl = GetUnitAbilityLevel(d.tr, ABILITY_ID)
        
        // --- Creating ward ---
        set d.w = CreateUnit(d.pt, WARD_ID, GetSpellTargetX(), GetSpellTargetY(), bj_UNIT_FACING)
        
        set d.x = GetUnitX(d.w)
        set d.y = GetUnitY(d.w)
        
        call UnitApplyTimedLife(d.w, 'BTLF', STUN_INTERVALS[d.lvl] * STUN_INTERVAL_TIME[d.lvl])
        if WARD_INVULNERABLE then
            call SetUnitInvulnerable(d.w, true)
        endif
        
        // --- Running stun ---
        set d.g = CreateGroup()
        call SW.RunStun(d)
        
        // --- Running timer ---
        set d.time = CreateTimer()
        call SetTimerUserData(d.time, integer(d))
        call TimerStart(d.time, STUN_INTERVAL_TIME[d.lvl], true, function SW.Loop)
    endmethod

//= Condition and Initializer ===============================================

    private static method ConditionCheck takes nothing returns boolean
        return GetSpellAbilityId() == ABILITY_ID
    endmethod

    private static method onInit takes nothing returns nothing
        call SpellInitDT(EVENT_PLAYER_UNIT_SPELL_EFFECT, function SW.Create, function SW.ConditionCheck)
        call Setup()
        
        call PreloadUnitDT(WARD_ID)
    endmethod
    
endstruct

endscope
Spell Description
The caster emits a blazing flash out of his inner core, leaving those who face him blinded and damaged.
v1.00
- Released

v1.01
- Minor edits

- LibraryDT (Deuterium)

JASS:
scope SwelteringBlaze initializer Init

globals
    private real array DAMAGE
endglobals

//===========================================================================
        
    ////////////////////////////////////
    //          ADJUSTABLES           //
    ////////////////////////////////////
      
    globals

        // --- IDs ---
        private constant integer    ABILITY_ID                      = 'A002'            // The ID of the Balminess ability
        private constant integer    BLIND_ABILITY_ID                = 'A003'            //The ID of the SB_Blind ability
        
        // --- Spell settings ---
        private constant real       SIGHT_RANGE                     = 60.               //The sight angle of the target in degrees
        private constant real       RADIUS                          = 500.              //The area of effect
        
        private constant attacktype ATTACK_TYPE                     = ATTACK_TYPE_CHAOS // The attack type of the damage dealt
        private constant damagetype DAMAGE_TYPE                     = DAMAGE_TYPE_FIRE  // The damage type of the damage dealt
        
        // --- Special effects ---
        private constant string     CASTER_SFX                      = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"       //The effect created on the caster
        private constant string     CASTER_SFX_ATTACHMENT_PT        = "chest"           // Attachment point
        
        private constant string     TARGET_SFX                      = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"  //The effect created on the target
        private constant string     TARGET_SFX_ATTACHMENT_PT        = "head"           // Attachment point

    endglobals
    
    private function Setup takes nothing returns nothing
    
        // General Setup note:
        //      the array integer refers to the level of the intended ability
        
        
        // --- Damage setting ---
        
        // The damage dealt to each unit who matches the conditions
        set DAMAGE[1] = 35.
        set DAMAGE[2] = 50.
        set DAMAGE[3] = 65.
        set DAMAGE[4] = 80.
        
    endfunction

    //! objectediting
    
        // Chance to miss (Ability Editor -- SB_Blind):
        //      Adjust "Level # - Data - Chance to Miss" to the required values.
    
        // Blind duration (Ability Editor -- SB_Blind):
        //      Adjust "Level # - Stats - Duration" to the required values.
    
    //! endobjectediting

    ////////////////////////////////////
    //        ADJUSTABLES END         //
    ////////////////////////////////////
    
//= Global variables ========================================================

globals
        private unit t      // Triggering unit
        private player p    // Owner of triggering unit
        private integer i   // Ability level
        
        private unit u      // Filter & enum units
        
        private real x
        private real y
        private real a
        private real f
        
        private constant group g = CreateGroup()
endglobals
    
//= Group functions =========================================================

private function FilterOut takes nothing returns boolean
    set u = GetFilterUnit()
    set f = GetUnitFacing(u)
    set a = bj_RADTODEG * Atan2((y) - GetUnitY(u), x - GetUnitX(u))
    return (((f <= (a + SIGHT_RANGE)) and (f >= (a - SIGHT_RANGE))) or ((f <= (a + 360. + SIGHT_RANGE)) and (f >= (a + 360. - SIGHT_RANGE)))) and  (IsUnitType(u, UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(u, UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitEnemy(u, p) == true) and (IsUnitType(u, UNIT_TYPE_DEAD) == false)
endfunction

private function GroupActions takes nothing returns nothing
    // --- Damaging & Blinding ---
    set u = GetEnumUnit()
    call DummyCastTargetDT(p, u, BLIND_ABILITY_ID, "curse", i)
    call UnitDamageTarget(bj_lastCreatedUnit, u, DAMAGE[i], true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE_WHOKNOWS)

    // --- Targets' special effect ---
    call DestroyEffect(AddSpecialEffectTarget(TARGET_SFX, u, TARGET_SFX_ATTACHMENT_PT))
endfunction

//= Actions =================================================================

private function Action takes nothing returns nothing
        
    // --- Debug ---
    debug call BJDebugMsg("|cffc3dbffSweltering Blaze:|r Spell effect occured")
    debug call BJDebugMsg("|cffffcc00Instance is instant|r")
    debug call BJDebugMsg(" ")
        
    // --- Setting some variables ---
    set t = GetTriggerUnit()
    set x = GetUnitX(t)
    set y = GetUnitY(t)
    set p = GetOwningPlayer(t)
    set i = GetUnitAbilityLevel(t, ABILITY_ID)
    
    // --- Picking group ---
    call GroupEnumUnitsInRange(g, x, y, RADIUS, Condition(function FilterOut))
    call ForGroup(g, function GroupActions)
    call DestroyCondition(Condition(function FilterOut))
    call GroupClear(g)
    
    // --- Caster's special effect ---
    call DestroyEffect(AddSpecialEffectTarget(CASTER_SFX, t, CASTER_SFX_ATTACHMENT_PT))
    
    // --- Slight cleaning ---
    set t = null
    set u = null
    set p = null
endfunction

//= Condition and Initializer ===============================================

private function ConditionCheck takes nothing returns boolean
    return GetSpellAbilityId() == ABILITY_ID
endfunction

private function Init takes nothing returns nothing
    call SpellInitDT(EVENT_PLAYER_UNIT_SPELL_EFFECT, function Action, function ConditionCheck)
    call Setup()
    
    call PreloadSpecialEffectDT(CASTER_SFX)
    call PreloadSpecialEffectDT(TARGET_SFX)
endfunction

endscope
v1.00
- Released

v1.01
- Full re-do of the library

v1.02
- Improved the library

JASS:
library LibraryDT initializer Init

//= Adjustables =============================================================
        
    ////////////////////////////////////
    //          ADJUSTABLES           //
    ////////////////////////////////////
      
    globals
    
        constant integer DummyDT = 'h000'       // The ID of the General Dummy

    endglobals

    ////////////////////////////////////
    //        ADJUSTABLES END         //
    ////////////////////////////////////



//***************************************************************************
//*                        GENERAL PURPOSE FUNCTIONS                        *
//***************************************************************************

//= Spell Init ==============================================================

// call SpellInitDT(pue, action, condition)
function SpellInitDT takes playerunitevent pue, code action, code condition returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    loop
        call TriggerRegisterPlayerUnitEvent(t, Player(i), pue, null)
        exitwhen i >= 15
        set i = i + 1
    endloop
    call TriggerAddCondition(t, Condition(condition))
    call TriggerAddAction(t, action)
    set t = null
endfunction


//= Timer User Data (works for handles too) ================================

// call SetTimerUserData(whichTimer, whichStruct)
function SetTimerUserData takes handle whichTimer, integer whichStruct returns nothing
    call SaveInteger(HASHTABLE_DT, 1, GetHandleId(whichTimer), whichStruct)
endfunction

// call GetTimerUserData(whichTimer)
function GetTimerUserData takes handle whichTimer returns integer
    return LoadInteger(HASHTABLE_DT, 1, GetHandleId(whichTimer))
endfunction

// call FlushTimerUserData(whichTimer)
function FlushTimerUserData takes handle whichTimer returns nothing
    call FlushChildHashtable(HASHTABLE_DT, GetHandleId(whichTimer))
endfunction


//= Preload =================================================================

globals
    private constant real PRELOAD_X = GetRectCenterX(bj_mapInitialPlayableArea)
    private constant real PRELOAD_Y = GetRectCenterY(bj_mapInitialPlayableArea)
endglobals

// call PreloadSpecialEffectDT(SFX)
function PreloadSpecialEffectDT takes string whichSFX returns nothing
    call Preload(whichSFX)
    call PreloadStart()
endfunction

// call PreloadUnitDT(whichUnit)
function PreloadUnitDT takes integer unitid returns nothing
    set bj_lastCreatedUnit = CreateUnit(Player(15), unitid, PRELOAD_X, PRELOAD_Y, 0.)
    call RemoveUnit(bj_lastCreatedUnit)
endfunction

//= General Initializer =====================================================
globals
    hashtable HASHTABLE_DT
endglobals

private function Init takes nothing returns nothing
    set HASHTABLE_DT = InitHashtable()

    call PreloadUnitDT(DummyDT)

    debug call BJDebugMsg("|cffffcc00LibraryDT Initiated|r")
endfunction



//***************************************************************************
//*                             MATH FUNCTIONS                              *
//***************************************************************************

//= Distance ================================================================

globals
    private real dx
    private real dy
endglobals

// call GetDistanceBetweenPointsDT(ax, ay, bx, by)
function GetDistanceBetweenPointsDT takes real ax, real ay, real bx, real by returns real
    set dx = bx - ax
    set dy = by - ay

    return SquareRoot(dx * dx + dy * dy)
endfunction

// call GetDistanceBetweenUnitsDT(unita, unitb)
function GetDistanceBetweenUnitsDT takes unit a, unit b returns real
    return GetDistanceBetweenPointsDT(GetUnitX(a), GetUnitY(a), GetUnitX(b), GetUnitY(b))
endfunction



//***************************************************************************
//*                            DUMMY FUNCTIONS                              *
//***************************************************************************

//= Cast Target =============================================================

// call CastTargetDT(aster, targer, abil, order, level)
function CastTargetDT takes unit caster, unit target, integer abilcode, string order, integer level returns nothing
    call UnitAddAbility(caster, abilcode)
    call SetUnitAbilityLevel(caster, abilcode, level)
    call IssueTargetOrder(caster, order, target)
endfunction

// call DummyCastTargetDT(id, target, abil, order, level)
function DummyCastTargetDT takes player id, unit target, integer abilcode, string order, integer level returns nothing
    set bj_lastCreatedUnit = CreateUnit(id, DummyDT, GetUnitX(target), GetUnitY(target), 0.)
    call CastTargetDT(bj_lastCreatedUnit, target, abilcode, order, level)
    call UnitApplyTimedLife(bj_lastCreatedUnit, 'BTLF', .5)
endfunction



//***************************************************************************
//*                          TEXTTAG FUNCTIONS                              *
//***************************************************************************

//= TextTag Unit ============================================================

// call TextTagUnitDT(u, tag, fade, size, height, vel, red, green, blue, trans)
function TextTagUnitDT takes unit u, string tag, real fade, real size, real heightoffset, real vel, integer red, integer green, integer blue, integer visibility returns nothing
    set bj_lastCreatedTextTag = CreateTextTag()
    call SetTextTagText(bj_lastCreatedTextTag, tag, size)
    call SetTextTagPosUnit(bj_lastCreatedTextTag, u, heightoffset)
    call SetTextTagColor(bj_lastCreatedTextTag, red, green, blue, visibility)
    call SetTextTagPermanent(bj_lastCreatedTextTag, false)
    call SetTextTagVelocity(bj_lastCreatedTextTag, 0., vel)
    call SetTextTagLifespan(bj_lastCreatedTextTag, fade)
    call SetTextTagFadepoint(bj_lastCreatedTextTag, fade)
    call SetTextTagVisibility(bj_lastCreatedTextTag, true)
endfunction



//***************************************************************************
//*                          MISSILE FUNCTIONS                              *
//***************************************************************************

//= Move Missile ============================================================
globals
    private real xm
    private real ym
    private real an
endglobals

// call MoveMissileDT(missile, tx, ty, speed)
function MoveMissileDT takes unit missile, real tx, real ty, real speed returns nothing
    set xm = GetUnitX(missile)
    set ym = GetUnitY(missile)
    set an = Atan2(ty - ym, tx - xm)

    call SetUnitPosition(missile, xm + speed * Cos(an), ym + speed * Sin(an))
    call SetUnitFacing(missile, (bj_RADTODEG * an))
endfunction

// call MoveMissileTargetDT(missile, target, speed)
function MoveMissileTargetDT takes unit missile, unit target, real speed returns nothing
    call MoveMissileDT(missile, GetUnitX(target), GetUnitY(target), speed)
endfunction


//= Create Missile ==========================================================

globals
    private effect array MissileModel
endglobals

// call CreateMissileDT(owner, x, y, facing, offset, model, attachmentpt, height, size)
function CreateMissileDT takes player owner, real x, real y, real facing, real offset, string model, string attachmentpt, real height, real size returns unit
    set bj_lastCreatedUnit = CreateUnit(owner, DummyDT, x + offset * Cos(facing), y + offset * Sin(facing), facing)
    if size != 1. then
        call SetUnitScale(bj_lastCreatedUnit, size, size, size)
    endif
    if height != 0. then
        call UnitAddAbility(bj_lastCreatedUnit, 'Arav')
        call SetUnitFlyHeight(bj_lastCreatedUnit, height, 0.)
        call UnitRemoveAbility(bj_lastCreatedUnit, 'Arav')
    endif
    call SaveEffectHandle(HASHTABLE_DT, 1, GetHandleId(bj_lastCreatedUnit), AddSpecialEffectTarget(model, bj_lastCreatedUnit, attachmentpt))
    return bj_lastCreatedUnit
endfunction

// call CreateFiredMissileDT(firingunit, offset, model, attachmentpt, height, size)
function CreateFiredMissileDT takes unit firingunit, real offset, string model, string attachmentpt, real height, real size returns unit
    return CreateMissileDT(GetOwningPlayer(firingunit), GetUnitX(firingunit), GetUnitY(firingunit), GetUnitFacing(firingunit), offset, model, attachmentpt, height, size)
endfunction

// call DestroyMissileDT(whichMissile)
function DestroyMissileDT takes unit whichMissile returns nothing
    call DestroyEffect(LoadEffectHandle(HASHTABLE_DT, 1, GetHandleId(whichMissile)))
    call UnitApplyTimedLife(whichMissile, 'BTLF', .01)
endfunction


//===========================================================================

endlibrary
v1.00 (August 13, 2009)
- Released

v1.01 (September 11, 2009)
- Reworked most of the spells and LibraryDT

v1.02 (August 29, 2011)
- Removed the spell: Maze
- Fixed a bug in Impairment

v1.03 (August 31, 2011)
- Improved LibraryDT


The vJass spells require Jass New Gen Pack.

Feel free to ask questions, report problems, or/and give advice.
Credit is appreciated.
Contents

Metaversal Spell Pack v1.03 (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 12 Nov 2011 Bribe: This needs a number of updates and revisions. "SpellInitDT" should just be replaced with RegisterPlayerUnitEvent by Magtheridon96. Missiles should use...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.


12 Nov 2011
Bribe: This needs a number of updates and revisions.

"SpellInitDT" should just be replaced with RegisterPlayerUnitEvent by Magtheridon96.

Missiles should use MissileRecycler.

LibraryDT should probably be eliminated altogether, as there are other utilities for doing text tags, timer attaching, etc.

When you come back we can go over some more specific things to improve the resource.
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Well, here's a spell pack with simple yet useful spells.
Special effects aren't anything big, and that's for the sake of keeping things simple, neat, and not overcrowding the player's screen with effects during gameplay.

To make a few points clear:

- During the process of making these spells I learnt alot of new things considering vJass, so the coding might differ between one spell and another.
- As I was checking out Blizzard's root abilities (since I didn't know anything about them), I found out that Maze is similar to Blizzard's Sleep, yet they are very different in the sense that Maze only triggers by hero attacks (although I included the option to change that) and units would automatically attack the mazed target, unlike sleep where the don't attack. What's more, there's the missile.
- I know I might get alot of nagging on the simplicity of the spells, but to be honest, few are the complex spells that are nice to use in-game. For all I know, they're original (so I know at least).
- BZK noticed me on the fact that the spawned unit's can get in the way sometimes, that's why I added a few commands to "minimize" that problem.

Well, thanks to:
- Dark_Dragon: for teaching me all I know in triggering - from basic GUI to advanced vJass.
- -BerZeKeR-: for always havin those creative ideas in mind and for his extremely creative special effects ideas.
- Thanathos: for helping me with those little vJass snippets which I always missed or missunderstood.
- LebaneseSoul: for getting me in the first place into "world editing" and for always providing me with terrain for testing spells.

Hope you all enjoy this pack, and any comment is welcome. Also, nice original and creative ideas to be made as spells are welcome.

~ Deut

PS: I usually forget stuff, so I'd be expecting comments on "what to fix" :p
 
Level 9
Joined
Aug 2, 2008
Messages
219
Yeah finally released ! I´ve been very curios all the time^^
Sadly i have to start with a bad thing which is not necessarily your fault Deut...Something went wrong with DD´s group library, there were problems with all Debug messages which made it uncompileable, so i had to remove them manually...
I tested all the spells an for me they are nice and can be very useful...Im not going to skimm every spell code but from what i´ve seen the coding was really decent. Documentation and in-code comments were also provided. Among all those spells the Haitus was my fav, because i just love the idea and lulz somehow i got into the credits...
I really have to say GJ Deut ! =)

[edit]
Oh forgot to say i´ll do some more advanced tests now^^
 

Rmx

Rmx

Level 19
Joined
Aug 27, 2007
Messages
1,164
The Spellpack doesn't work ...

Compile error .. " Syntax MSG excute something ext..."

call Msg.execute("|cffff0000WARNING: Adding unit ("+GetUnitName(whichUnit)+") twice in a same groupex!|r")

They show me this line !

EDIT !

After some creative imagination .. i just read the spell description and looked at the codes * Confused too much lines *

/text marco .. what the fuck is it ! ?....

Anyway .. your spells in GUI !

Review ...

In the Stunning ward ...

Simple usefull and just needs a bit more sfx :D coding GUI MUI leakless and lagless ...

In the Impaiment spell...

Well it is not efficient ... but the idea is very lovely and it's MUI leakless lagles..

But to make it more efficient .. you could Just when the Mana ball hits the enemy .. Set Enemy = Hero ...

So it will just follow the hero ..... but make just one integer that calculates steps ..

Like ... Step = 1
Mana ball hits enemy ... then .... make ..... Step = 2 .. set Enemy = Hero ..

Mana ball hits Hero ... if Step =2 .. don't damage just bla bla ...

This could make your triggering more efficient .. and avoid alot of triggering :D

Still the map lags itself .. don't know why .. :S .. maybe it leaks in Inti triggers .. didn't check :D
 
Last edited:
Level 17
Joined
Mar 17, 2009
Messages
1,349
Well ummm... yeah I know what the problem is now that you specified it.
Basically just turn of the Debug Mode in the Jass Helper tab at the top of the WE before saving the map, or just open it without saving it.

I can't remove those lines now since I'm at some internet cafe, i guess by 2moro I'll have internet at home so I'll be definetly fixing that =)

I understand what you said about Impairment, but I guess I won't update it unless I want to vJass it, or if it's a one minute thing :p

I'll think of some nice SFX for the stunning ward, but until then.... well :p

@ Rmx:
About textmacro, well it's just a command for lazy people. You'll see all my scripts has:
JASS:
//! runtextmacro TimerUserDataDT

check the LibraryDT, you'll find the TimerUserData Functions between textmacro tags.
Basically, when I order //! runtextmacro, it copies those functions which are between the tags :p

I also use them for looping =P
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
wow that's weird it never crashed on my pc :s
Well, I fixed the debug messages so it now functions in Debug Mode.

I tested all the problems you mentioned in this new version, and there were no crashes. whether when opening, restarting, or whatever you guys mentioned :) hope it's like that for everyone and not only me...

But just to let you guys know, the vJass spells only function in Warcraft v1.24 and using Jass New Gen Pack v5c or later....

Let me know if there are still any problems, thank you =)


EDIT:
Struct members don't need to be nulled, but nulling them is slightly more efficient :) basically removing leaks until same struct array is used, or removing the leaks of the arrays that happen to not be used anymore throughout the game...
 
Level 9
Joined
Nov 25, 2008
Messages
194
First impression is very nice, some cool spells you made there, really like the mana ball although it slightly reminds me of gorgon's spell in dota ;P

The DK spells really rock IMO, especially foltern although i dunno what it means. It could aswell be a german word, which would mean "to torture" ;D

Now checking code

EDIT:

Oh btw I could a little typo in the mana-ball, but can't remember :(

OK now to the coding:

Impairment v1.00:
I must admit I admire most of the things you did
First of all:
JASS:
//***********************************************************************
//*                                                                     *
//* Spell Description:                                                  *
//*                                                                     *
//*     The caster hurls an ancient orb of magic which deals certain    *
//*     damage to the target and fills up with a certaion percentage of *
//*     the target's maximum mana to carry it back to teh caster.       *
//*                                                                     *
//***********************************************************************
//*                                                                     *
//* How to adjust and customize:                                        *
//*                                                                     *
//*     The caster hurls an ancient orb of magic which deals certain    *
//*     damage to the target and fills up with a certaion percentage of *
//*     the target's maximum mana to carry it back to the caster.       *
//*                                                                     *
//***********************************************************************

Somehow odd^^


Secondly GREAT and I mean really great setup section.
But I think all the locations don't need to be arrays, because they are instantly removed I think.
One thing, I really don't get is:
  • Unit - Cause IM_Missile[IM_Index[3]] to damage IM_TargUnit[IM_Index[3]], dealing IM_HitPoint[IM_Index[3]] damage of attack type Spells and damage type Normal
If I am right, you used dummy spells to damage enemies earlier, but why don't you refer to the trigUnit now?
Lastly the Ison boolean can be avoided by using

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • Triggering unit unequal to No Unit
    • Then - Actions
      • your actions
    • Else - Actions
And when you set the boolean to false you simply set unit to no unit, although I think you already know that^^
As said above it's just small stuff, so nvm if you don't care


Stunning Ward v1.00
JASS:
//***********************************************************************
//*                                                                     *
//* How to adjust and customize:                                        *
//*                                                                     *
//*     Simply adjust the variables found between the two tags:      *
//*     USER DEFINED VARIABLES/END OF USER ADJUSTABLE GLOBALS        *
//*     found in the trigger "Stunning Ward Main".                   *
//*                                                                     *
//*                                                                     *
//***********************************************************************
Three stars don't match ;(


Hm I kinda think the triggering fails a bit :(
  • Time - Every 1.00 seconds of game time
And if I do smth like
  • Set SW_RefreshRate[SW_Index[2]] = 0.10
it only lasts 10 times longer.

I think you can probably figure a way to fix that yourself

Bah rest is JASS and I'M neither experienced enough to tell much about it, nor in the mood to do so, but I just can highly recommend these spells for everyone to use them, if it is what they are looking for!
 
Last edited:

Rmx

Rmx

Level 19
Joined
Aug 27, 2007
Messages
1,164
On an old business laptop, there's no lag whatsoever :s

Maybe becoz i played it too much or becoz i was opening Garena, GIMP, Thw Chat, MSN and World editor .. then i played it in the Small Warcraft * Reinventing ext.. *

It lags .. but well it maybe coz those programs are open ...

Off-topic and PS :p .. thnx for the comment on my Ice Spear icon :D +rep on both :D

EDIT !

Need to spread Fosto2
 
Last edited:
Level 9
Joined
Nov 25, 2008
Messages
194
I must admit I somehow like it more than Gorgon's skill

Just took a little glance at the JASS stuff, and must say great setup here too.

Anyway, how come you use a german skill name? Oo
I thought my English would be too bad ;P

And I really love this submission for multiple reasons: high quality spells, esay readable triggers, a spellpack, and I finally got to see more than just one spell from you!
:thumbs_up:

EDIT: Btw Rmx what the hell does "Fosto2" mean? Oo
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Hahaha Fosto2, well let me remember the English word for it... pistachio.

How come I used the German word? Well, I was curious to check what torture meant in French (I used to know french when I was a kid, now I don't know shit :p), so my dictionary happens to also have translators to Spanish, Italian, and German... so I found the word and it sounded cool. Never forgot it since then :)

The thing about GUI (I forgot to mention this in the documentation) is that you can't use variables in the "Time Events"... so besides changing the refresh rate in the variables, you also have to manually adjust the event:
  • Time - Every 1.00 seconds of game time
That won't be a problem from now on since as you can see in my vJass spells, I work on Intervals and not on Expiry Timers anymore (ie, Intervals = 10, PeriodicTime =1.00 ; this loops at 1 second intervals for 10 times).


And I also quote myself:
Deuterium said:
PS: I usually forget stuff, so I'd be expecting comments on "what to fix" :p

So I was expecting these little problem :p

I happen to like using the IsOn boolean more than the other method, so it's a matter of taste :)
Also, I happen to always use dummies to damage just to avoid any interference with the trig unit's orders, but after some testing it seems like damaging leads to no interference, well I'll open a thread on this 2moro :)

Thanks for your review Rofl, and I'll update in a few days, let's see what other people have to comment on this spell pack :)


EDIT @ Rmx:
Have you rechecked the pack? I've fixed the Debug problem that didn't allow you to run the vJass spells...
 
Level 9
Joined
Nov 25, 2008
Messages
194
But for the periodic event you could implement a little counter thing, like a variable counting up every 0.02 sec or whatsoever and when it reaches the interval it resets and does the actions.

As already mentionend, these are all just very small things, and I didnt't want to sound harsh or unfriendly in anyway.

The thing is, that through your outstanding setup you could create 2 different spells with different things, for example one classic ward and one ball flying to the target stunning everything in it's aoe and damaging it. Now you want different intervals on those, and you are kinda fucked.

I know, this is really a small thing, and I probably shouldn't mention it, because it's only neccesary at systems usually, but I'd feel bad, if I didn't.


Also the stuff with the Ison doesn't really matter, I just wanted to mention it.

And I am almost 99.99% sure that
  • Unit - Damage Target
doesn't interfer any orders, or why else should Blizzard tell us "This does not interrupt the unit's orders". The thing why I prefer it, is that sometimes the unit needs to deal the damage, i.e. "onkill" skills.
 
Last edited:
Level 16
Joined
Jun 9, 2008
Messages
734
I see a lot of issues in the codes (in my opinion :grin:) :

- you could update efficiency by using TimerUtils instead of destroying the timers everytime
- you do a bunch of stuff outside of your struct's create methods and then pass it there, you don't have any other methods, all the code is just outside the structs in random functions
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
scorpion182 said:
- you could update efficiency by using TimerUtils instead of destroying the timers everytime
Well, it's a minor improvement issue, so it's no big deal... but maybe I'll use some timer system in the future if I see it necessary :)

scorpion182 said:
- you do a bunch of stuff outside of your struct's create methods and then pass it there, you don't have any other methods, all the code is just outside the structs in random functions
You know that methods are functions right? Methods aren't any more efficient that functions... so it doesn't really matter which you do use. It's just a matter of coding style :)

Rmx said:
i like shiny spells :D
Well, if I don'y end up being a lazy ass, you'd love my new idea :D let's hope I just end up doing it some day :p

nerovesper said:
although I don't know though Jasses.... xD
Well, those are some simple vJass, so you can actually learn a lot from them since they're easy to understand. All the complicated vJass spells I start working on I end up giving up on them since the chance of having bugs in them is higher, and I HATE fixing bugs :s

Roflcoptor said:
But for the periodic event you could implement a little counter thing, like a variable counting up every 0.02 sec or whatsoever and when it reaches the interval it resets and does the actions.
Yes I did that in the first place, but then I though that it's a waste of CPU processing, so I've changed to how it is. I'll include a comment in the documentation next version about that. I mean, it's not a big efficiency thing, yet still, this is simpler and nicer.

Roflcoptor said:
and I didnt't want to sound harsh or unfriendly in anyway.
Don't worry about that :) it's constructive criticism.

Roflcoptor said:
or why else should Blizzard tell us "This does not interrupt the unit's orders".
Oh I never noticed that :p
 
Level 9
Joined
Aug 2, 2008
Messages
219
As i said some posts ago i did some more advanced testing and here are my results...
What i really like is the fact that no bugs occurred while testing the spells ingame :thumbs_up:
Now let me say a very few words about the vJASS coding...

Coding overall was good, it had a nice setup part and some user constant... But there are some minor things to improve:
1. In the comment block at the top you called this spell Foltern, but it the real name is Balminess or i got something wrong...

2.
JASS:
        call PauseTimer(d.time)
        call DestroyTimer(d.time)
        
        set d.time = CreateTimer()
        call SetTimerUserData(d.time, integer(d))
        call TimerStart(d.time, PeriodicTime, true, function DoT)
You don´t need to destroy the old timer and create a new one to carry on with the spell. Just pause the old timer and use it instead of creating a new one. Oh and you don´t need to pause timer before destroying them.


Coding was decent again here + the user setup + perloading all effects. The only thing i may suggest to improve is that you could add an user constat for the special effect attatchment points.


Let´s take a look at my favorite^^. Well the same positive points as in the other spells...A tiny thing what you could do better is to make the Duration function constant. And somehow you called this spell Foltern too.


This one is a bit too easy for my taste (no offense) but coding was ok here too. If you have a global trigger you could make it constant and initialize it when declaring it. Oh it does not really matter but you can save some characters by leaving out the == true when you do something like IsUnitType(GetEventDamageSource(), UNIT_TYPE_HERO) == true


Coding here was nice too and i can´t even find a flaw :wink:. But i you´re interested i can show you a little trick i learned from Deaod which makes using groups a lot more effecient. Just send me a PM or VM. Oh and using all the temp globals for the filterfunc is a very clever idea.

All in all i have to say it again: GJ Deut. And i have to admire this far better than mine first vJASS stuff !
You should really notify a mod to approve this.


~TNT
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Thanathos said:
You don´t need to destroy the old timer and create a new one to carry on with the spell. Just pause the old timer and use it instead of creating a new one. Oh and you don´t need to pause timer before destroying them.
Nice idea about recycling timer :) yet, Pausing before destroying avoids this little bug where the timer could run one more time... so it's better to pause :)

About the documentation, I tend to copy paste all off Foltern and then fix them, so I might have forgotten some stuff...

And I'm glad to know all the problems are minor stuff... definitely to be fixed in the next version ;)
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Well what I've heard from some pro-coders that (& I even read that once somewhere some very long time ago when I was still learning GUI) timer should be paused before destroying to avoid that bug. I mean, let's say the timer is running at .01 seconds for 10 times, if you just destroy it there's a chance it triggers once more, thus running 11 times.
I didn't test that, so I can't be sure of the truth of that, but to stay in the safe side, I pause it.
 
I like them. Although most of them are quite simple, they're all well coded - your coding style is much, much neater than mine! I give this spellpack a 4/5 since there weren't many nice special effects, but all the spells seemed to work well and they're really well coded.

EDIT:
Well what I've heard from some pro-coders that (& I even read that once somewhere some very long time ago when I was still learning GUI) timer should be paused before destroying to avoid that bug. I mean, let's say the timer is running at .01 seconds for 10 times, if you just destroy it there's a chance it triggers once more, thus running 11 times.
I didn't test that, so I can't be sure of the truth of that, but to stay in the safe side, I pause it.
You're right. The timer can run quite a few times after being destroyed I think.
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Thanks for checking EoW...
Well about the SFX, well they are slightly lacking... I'm not very good with sfx. Also, I tend to keep it simple in order to avoid "overcrowding" the screen during gameplay.
And yes most of them are quite simple, I mean, who wants a complicated spell in-game? Right? :)
For instance, the most know map to all: DotA, has almost all it's spells simple and easy to use (there are few exceptions).

Again, thanks!
 
Level 15
Joined
Jul 19, 2007
Messages
618
heh i found out that some people did have troubles with debug mode! well thats coz the whole librarys are connected and if any piece misses, like Msg.execute! it will crash, not crash but give compile errors.

second of all some people did say that this crashes... well most likely yes! but thats blizzards bug which will be fixed in 1.24b, well its already fixed in 1.24b beta! my universal spell pack as well crashes in 1.24 but in beta no! so once 1.24b full is out all crashes will be fixed, as well as return bug!

this spell pack is really awesome and for this guys which already have JNGPS and did include my ddup.j file do not need to copy and paste this "my librarys from the deuts map" only if the "one" does not have my libs then he will need to copy them from deuts map!

anyway i quickly took a look at this awesome pack and i must say really gj!
Greets and +rep!
~DD
 
Level 15
Joined
Jul 19, 2007
Messages
618
You probably don't have the latest version of JassHelper, 9.I.0.

no basically i have 0.9.I.2! thats the best version of JH for me now! what new ones does is: compile double returns by creating multiple functions and / or variables!

vexorian himself said that this process is slow but should be used on maps which are using return bug! else this feature should 100% be disabled.
 
Level 15
Joined
Jul 6, 2009
Messages
889
This is not compatible with versions below 1.23. So I cannot test it ...

For every spell:
- CONFIGURABLE_GLOBAL_CONSTANTS should be in CAPITALS. It is a naming convention.
- Struct members (player, unit, string, timers, effects, eg) DO NOT need to be nulled, as they are actually global arrays. (Eg, in your Hiatus, you null unit: tr, ta).
- DamageMultipler thingy doesn't need I2R does it?

Balminess:
JASS:
private function DamageMultiplier takes unit whichunit returns real
    return I2R(GetUnitAbilityLevel(whichunit, AbilityIdIs))
endfunction
Can't it be GetUnitAbilityLevel( unit, id )?
I like GTrigger better (search it on TheHelper by Jesus4Lyf) XD
Maze:
JASS:
function ConditionIs takes nothing returns boolean
    return (IsDamageTypeMelee() == true) and (GetUnitAbilityLevel(GetTriggerUnit(), Buff) != 0) and ((IsUnitType(GetEventDamageSource(), UNIT_TYPE_HERO) == true) or ((UnitTrigger) and (IsUnitType(GetEventDamageSource(), UNIT_TYPE_STRUCTURE) == false)))
endfunction
Private and use delimited comments /* */ for better reading xD (not that it really matters, its just for readability)

Sweltering Blaze:
JASS:
    call UnitDamageTarget(bj_lastCreatedUnit, u, Damage(t), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
(In function GroupActions).
Configurable attacktypes, and damagetype, and weapontype? Also, bj_lastCreatedUnit? Huh?

(I prefer KeyTimers2 over any timer system XD)
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
xBlackRose said:
This is not compatible with versions below 1.23. So I cannot test it ...
Actually you can, I included a function which you can uncomment in my LibraryDT to make it work. Oh, and you simply need to disable all of the Dark Dragon's Libraries and the trigger Maze. Maze is the only that doesn't work on pre 1.23.

xBlackRose said:
- CONFIGURABLE_GLOBAL_CONSTANTS should be in CAPITALS. It is a naming convention.
I've got my own convention :p

xBlackRose said:
- Struct members (player, unit, string, timers, effects, eg) DO NOT need to be nulled, as they are actually global arrays. (Eg, in your Hiatus, you null unit: tr, ta).
They do not need to be nulled, but nulling them is a very good thing. Some arrays are never to be used again in the game, thus leaking throughout the whole game. Actually, even if an array is to be reused, you can remove the leak throughout the "cooldown", instead of waiting to recycle it.

xBlackRose said:
Oops :p

xBlackRose said:
Can't it be GetUnitAbilityLevel( unit, id )?
Hehe, well now I actually tend to create function which takes integer (ie ability level).
So it looks like this: i * 5 + 5 or something like that :p

xBlackRose said:
Configurable attacktypes, and damagetype, and weapontype? Also, bj_lastCreatedUnit? Huh?
Oh, haha yeah maybe I should make them configurable. And the bj_lastCreatedUnit is created by DummyCastTargetDT, so instead of recreating dummies using DamageTargetDT, I used the same dummy :p

Thanks for the review =D and try testing the spells if your not too lazy to do those fixes :p
 
Level 15
Joined
Jul 19, 2007
Messages
618
yeah return bug cant be fixed, only H2I can by replacing it with GetHandleId! however I2U... nah, basically it is possible to make that by unit stack index systems... anyway that would require FreeI2U! so yeah... 1.24b is awesome version of wc i already tested it.

that JH j.0 is here to quickly fix false positive returns like Element of Water said!

anyway quit slow through!
 
Top