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

Artesia Spellpack v1.1.1

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Spells of Artesia from Heroes of Newerth. Only 3 spells (of the 4) are included in spellpack. Here's a link to the information of the original skill-set.

Overview
  • Arcane Missile [Active]
  • Dance of Death [Active]
  • Arcane Bolts [Passive]


Implementation
JASS:
/*******************************************************************************
                        ARTESIA SPELLPACK v1.1.1                      
                              BY Ayanami                            
********************************************************************************

********************************************************************************
                            REQUIREMENTS                                      
********************************************************************************
- JNGP
- CTL
- RegisterPlayerUnitEvent                                                            
- SpellEffectEvent
    * Table
- Unit Indexer
    * Event
- World Bounds                                                                                                              
********************************************************************************

********************************************************************************
                            IMPLEMENTATION                                     
********************************************************************************
1) Copy the whole "Required Systems" Trigger folder & paste in map
2) Copy all 6 abilities under "Human" & paste in map
3) Copy all 2 buffs under "Human" & paste in map
4) Ensure that the following abilities have their buff set properly:
    * Arcane Missile (Slow) - Arcane Missile
    * Dance of Death (Visual) - Dance of Death
5) Copy all 2 units under "Human - Units" & paste in map
    * Arcane Bolt Dummy
    * Arcane Missile Dummy
5) Copy the whole "Artesia Spellpack" Trigger folder
6) Go through all the spell Configurations

*******************************************************************************/


Spell Codes



Fires a bolt of magic at the target location that travels up to 1200 distance. The bolt searches for the nearest target within a radius and homes to that target. Upon contact, all enemies within 150 distance are damaged and slowed by 15%.

Level 1 - 100 damage.
Level 2 - 140 damage.
Level 3 - 180 damage.
Level 4 - 220 damage.

Cast Range: Global
Target Type: Point
Cooldown: 5/4/3/2 seconds

JASS:
library ArcaneMissile uses CTL, SpellEffectEvent, UnitIndexer, WorldBounds, ArcaneBolts

/*******************************************************************************
                                CONFIGURABLES                        
*******************************************************************************/

globals
    private constant integer ABIL_ID = 'ABAM' // raw code of ability "Arcane Missile"
    private constant integer DUM_ABIL_ID = 'AAM0' // raw code of ability "Arcane Missile (Slow)"
    private constant integer BUFF_ID = 'BBAM' // raw code of buff "Arcane Missile"
    
    private constant integer DUMMY_ID = 'duAM' // raw code of unit "Arcane Missile Dummy"
    private constant integer RED = 255 // red vertex color of spell projectile
    private constant integer GREEN = 255 // green vertex color of spell projectile
    private constant integer BLUE = 255 // blue vertex color of spell projectile
    private constant integer TRANS = 255 // transparency of spell projectile, where 0 is fully transparent
    private constant real SCALE = 1.5 // scale size of spell projectile
    private constant real HEIGHT = 100. // flying height of spell projectile
    private constant real SPEED = 700. // distance travelled per second by spell projectile
    private constant real COLLISION = 100. // collision contact size of spell projectile
    private constant real ANGLE_RATE = 60. // maximum turning degree of spell projectile per second
    
    private constant string FX = "Abilities\\Spells\\Human\\SpellSteal\\SpellStealMissile.mdl" // special effect used when damgage is dealt
    private constant string FX_AT = "chest" // attachment point of FX
    
    private constant boolean PRELOAD = true // preloads resources if true
    
    private constant real ENUM_RADIUS = 176. // max collision size of a unit in your map
    
    private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type
    private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type
endglobals

// area of effect
private constant function GetArea takes integer level returns real
    return 150.0
endfunction

// damage dealt
private constant function GetDamage takes integer level returns real
    return 40. * level + 60.
endfunction

// distance travelled by missile
private constant function GetDistance takes integer level returns real
    return 1200.
endfunction

// slow duration
private constant function GetDuration takes integer level returns real
    return 3.
endfunction

// homing detection area
private constant function GetHomeArea takes integer level returns real
    return 600.
endfunction

// target types allowed for dealing damage
private constant function GetFilter takes unit caster, unit target returns boolean
    return /*
    */ not IsUnitType(target, UNIT_TYPE_DEAD) and /* target is alive
    */ IsUnitEnemy(target, GetOwningPlayer(caster)) and /* target is an enemy of caster
    */ not IsUnitType(target, UNIT_TYPE_STRUCTURE) and /* target is not a structure
    */ not IsUnitType(target, UNIT_TYPE_MECHANICAL) and /* target is not mechanic
    */ not IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) /* target is not magic immune
    */
endfunction

/*******************************************************************************
                            END CONFIGURABLES                        
*******************************************************************************/

globals
    private group G = bj_lastCreatedGroup
endglobals

private struct Slow extends array
    private static constant real TIMEOUT = 0.031250000
    private static integer array store
    
    private unit u
    private real dur
    
    implement CTLExpire
        set this.dur = this.dur - TIMEOUT
        
        if this.dur <= 0 or IsUnitType(this.u, UNIT_TYPE_DEAD) or GetUnitTypeId(this.u) == 0 then
            set thistype.store[GetUnitUserData(this.u)] = 0
        
            call UnitRemoveAbility(this.u, DUM_ABIL_ID)
            call UnitRemoveAbility(this.u, BUFF_ID)
            call this.destroy()
        endif
    implement CTLEnd
    
    public static method apply takes unit u, real dur returns nothing
        local thistype this
        local integer id = GetUnitUserData(u)
        
        if thistype.store[id] == 0 then
            set this = thistype.create()
            set this.u = u
            set thistype.store[id] = this
            
            call UnitAddAbility(u, DUM_ABIL_ID)
            call UnitMakeAbilityPermanent(u, true, DUM_ABIL_ID)
        else
            set this = thistype.store[id]
        endif
        
        set this.dur = dur
    endmethod
endstruct

private struct Main extends array
    private static constant real TIMEOUT = 0.031250000
    private static constant real TRUE_SPEED = SPEED * TIMEOUT
    private static constant real TRUE_ANGLE_RATE = ANGLE_RATE * TIMEOUT * bj_DEGTORAD
    private static constant real PI_2 = bj_PI * 2
    
    private unit u
    private unit dummy
    private unit target
    private real area
    private real dmg
    private real dist
    private real dur
    private real homeArea
    private real sin
    private real cos
    
    implement CTL
        local unit u
        local unit target
        local boolean b = false
        local real x
        local real y
        local real dx
        local real dy
        local real r
        local real minDist
        local real facing
    implement CTLExpire
        set target = null
        set b = false
        set x = GetUnitX(this.dummy)
        set y = GetUnitY(this.dummy)
        set minDist = this.homeArea * this.homeArea
    
        call GroupEnumUnitsInRange(G, x, y, this.homeArea + ENUM_RADIUS, null)
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            call GroupRemoveUnit(G, u)
                
            set dx = GetUnitX(u) - x
            set dy = GetUnitY(u) - y
            set r = dx * dx + dy * dy
                
            if GetFilter(this.u, u) and IsUnitInRangeXY(u, x, y, this.homeArea) and r < minDist then
                if IsUnitInRangeXY(u, x, y, COLLISION) then
                    set b = true
                    call GroupClear(G)
                    exitwhen true
                else
                    set minDist = r
                    set target = u
                endif
            endif
        endloop
        
        if b then
            call GroupEnumUnitsInRange(G, x, y, this.area + ENUM_RADIUS, null)
            loop
                set u = FirstOfGroup(G)
                exitwhen u == null
                call GroupRemoveUnit(G, u)
                
                if GetFilter(this.u, u) and IsUnitInRangeXY(u, x, y, this.area) then
                    call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_AT))
                    call UnitDamageTarget(this.u, u, this.dmg, true, false, ATK, DMG, null)
                    call Slow.apply(u, this.dur)
                endif
            endloop
        
            call KillUnit(this.dummy)
            call this.destroy()
        else
            set this.target = target
            set facing = GetUnitFacing(this.dummy) * bj_DEGTORAD

            if this.target != null then
                set r = Atan2(GetUnitY(this.target) - y, GetUnitX(this.target) - x)
                
                if r < 0 then
                    set r = r + PI_2
                endif
                
                if facing < r then
                    set facing = facing + PI_2
                endif
                
                if facing - r < bj_PI then
                    set facing = facing - TRUE_ANGLE_RATE
                elseif facing - r > bj_PI then
                    set facing = facing + TRUE_ANGLE_RATE
                else
                    set facing = r
                endif
            endif
            
            set x = x + TRUE_SPEED * Cos(facing)
            set y = y + TRUE_SPEED * Sin(facing)
            call SetUnitFacing(this.dummy, facing * bj_RADTODEG)
            if x > WorldBounds.minX and y > WorldBounds.minY and x < WorldBounds.maxX and y < WorldBounds.maxY then
                call SetUnitX(this.dummy, x)
                call SetUnitY(this.dummy, y)
            endif
            
            set this.dist = this.dist - TRUE_SPEED
            if this.dist <= 0 then
                call KillUnit(this.dummy)
                call this.destroy()
            endif
        endif
    implement CTLNull
        set u = null
        set target = null
    implement CTLEnd

    private static method onCast takes nothing returns boolean
        local thistype this = thistype.create()
        local integer level
        local real a
        
        set this.u = GetTriggerUnit()
        set a = Atan2(GetSpellTargetY() - GetUnitY(this.u), GetSpellTargetX() - GetUnitX(this.u))
        set this.dummy = CreateUnit(GetOwningPlayer(this.u), DUMMY_ID, GetUnitX(this.u), GetUnitY(this.u), a * bj_RADTODEG)
        set this.target = null
        set level = GetUnitAbilityLevel(this.u, ABIL_ID)
        set this.area = GetArea(level)
        set this.dmg = GetDamage(level)
        set this.dist = GetDistance(level)
        set this.dur = GetDuration(level)
        set this.homeArea = GetHomeArea(level)
        
        call SetUnitVertexColor(this.dummy, RED, GREEN, BLUE, TRANS)
        call SetUnitScale(this.dummy, SCALE, 0, 0)
        call SetUnitFlyHeight(this.dummy, HEIGHT, 0)
        
        return false
    endmethod

    private static method onInit takes nothing returns nothing
        static if PRELOAD then
            local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, 0)
            call UnitAddAbility(u, DUM_ABIL_ID)
            call RemoveUnit(u)
            set u = null
        endif
        
        call RegisterSpellEffectEvent(ABIL_ID, function thistype.onCast)
    endmethod
endstruct

endlibrary




Channel arcane powers up to 3 seconds to heal yourself over time. While performing Dance of Death, Arcane Bolts are generated and fired periodically.

Level 1 - 30 + 10% of INT as heath per second. 0.7 seconds bolt interval.
Level 2 - 40 + 15% of INT as heath per second. 0.6 seconds bolt interval.
Level 3 - 50 + 20% of INT as heath per second. 0.5 seconds bolt interval.
Level 4 - 60 + 25% of INT as heath per second. 0.4 seconds bolt interval.

Channeling Time: 3 seconds
Cast Range: Self
Target Type: Instant
Cooldown: 25/22/18/16 seconds

JASS:
library DanceOfDeath requires CTL, SpellEffectEvent, UnitIndexer, ArcaneBolts

//===========================================================================
//                           CONFIGURABLES                        
//===========================================================================

globals
    private constant integer ABIL_ID = 'ABDD' // raw code of ability "Dance of Death"
    private constant integer DUM_ABIL_ID = 'ADD0' // raw code of ability "Dance of Death (Visual)"
    private constant integer BUFF_ID = 'BBDD' // raw code of buff "Dance of Death"
    private constant string ORDER_STRING = "absorb" // order id of ability "Dance of Death"
    
    private constant boolean PRELOAD = true // preloads resources if true
endglobals

// amount healed per second
private function GetHeal takes integer level, unit u returns real
    return (10. * level + 20.) + (0.05 * level + 0.05) * GetHeroInt(u, true)
endfunction

private function GetInterval takes integer level returns real
    return 0.8 - 0.1 * level
endfunction

//===========================================================================
//                          END CONFIGURABLES                        
//===========================================================================

private struct Main extends array
    private static integer array store
    
    private unit u
    private integer level
    private real amount
    private real interval
    private real intervalCount
    
    implement CTL
        local integer id = OrderId(ORDER_STRING)
    implement CTLExpire
        if GetUnitCurrentOrder(this.u) != id then
            set thistype.store[GetUnitUserData(this.u)] = 0
            
            call UnitRemoveAbility(this.u, DUM_ABIL_ID)
            call UnitRemoveAbility(this.u, BUFF_ID)
            call this.destroy()
        else
            if this.level > 0 then
                if this.intervalCount <= 0 then
                    set this.intervalCount = this.interval
                    
                    call ArcaneBolt.new(this.u, GetUnitX(this.u), GetUnitY(this.u))
                else
                    set this.intervalCount = this.intervalCount - 0.031250000
                endif
            endif
        
            call SetWidgetLife(this.u, GetWidgetLife(this.u) + this.amount)
        endif
    implement CTLEnd
    
    private static method onCast takes nothing returns boolean
        local thistype this
        local unit u = GetTriggerUnit()
        local integer id = GetUnitUserData(u)
        local integer level = GetUnitAbilityLevel(u, ABIL_ID)
        
        if thistype.store[id] == 0 then
            set this = thistype.create()
            set this.u = u
            set thistype.store[id] = this
            
            call UnitAddAbility(u, DUM_ABIL_ID)
        else
            set this = thistype.store[id]
        endif
        
        set this.level = GetUnitAbilityLevel(u, ArcaneBolt.ID)
        set this.amount = GetHeal(level, u) * 0.031250000
        set this.interval = GetInterval(level)
        set this.intervalCount = this.interval
        
        set u = null
        
        return false
    endmethod
    
    private static method onInit takes nothing returns nothing
        static if PRELOAD then
            local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'hpea', 0, 0, 0)
            call UnitAddAbility(u, DUM_ABIL_ID)
            call RemoveUnit(u)
            set u = null
        endif
    
        call RegisterSpellEffectEvent(ABIL_ID, function thistype.onCast)
    endmethod
endstruct

endlibrary




On spellcast, releases 2 Arcane Bolts that seek out the nearest enemy unit within an area of 700, dealing damage on contact. Each bolt is released at a 0.8 seconds interval.

Level 1 - 20 damage.
Level 2 - 40 damage.
Level 3 - 55 damage.
Level 4 - 70 damage.

Passive

JASS:
library ArcaneBolts uses CTL, SpellEffectEvent, UnitIndexer

//===========================================================================
//                           CONFIGURABLES                        
//===========================================================================

globals
    private constant integer ABIL_ID = 'ABAB' // raw code of ability "Arcane Bolts"
    
    private constant integer DUMMY_ID = 'duAB' // raw code of unit "Arcane Bolts Dummy"
    private constant integer RED = 255 // red vertex color of projectile
    private constant integer GREEN = 255 // green vertex color of projectile
    private constant integer BLUE = 255 // blue vertex color of projectile
    private constant integer TRANS = 255 // transparency of projectile, where 0 is fully transparent
    private constant real SCALE = 1. // scale size of projectile
    private constant real HEIGHT = 100. // height of projectile
    private constant real SPEED = 700. // distance travelled per second by projectile
    private constant real COLLISION = 100. // collision contact size of projectile
    private constant real ANGLE_RATE = 520. // maximum turning degree of projectile per second, set to 0 to disable projectile arc
    private constant boolean RANDOM_SEEK = true // seeks target randomly if true, seeks closest target if false
    
    private constant real ENUM_RADIUS = 176. // max collision size of a unit in your map
    
    private constant boolean PRELOAD = true // preloads resources if true
    
    private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type
    private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type
endglobals

// area of effect
private constant function GetArea takes integer level returns real
    return 700.0
endfunction

// number of bolts produced per spell cast
private constant function GetBoltCount takes integer level returns integer
    return 2
endfunction

// damage dealt
private constant function GetDamage takes integer level returns real
    return 15. * level + 10.
endfunction

// delay between bolts
private constant function GetDelay takes integer level returns real
    return 0.8
endfunction

// target types allowed for dealing damage
private constant function GetFilter takes unit caster, unit target returns boolean
    return /*
    */ not IsUnitType(target, UNIT_TYPE_DEAD) and /* // target is alive
    */ IsUnitEnemy(target, GetOwningPlayer(caster)) and /* // target is an enemy of caster
    */ not IsUnitType(target, UNIT_TYPE_STRUCTURE) and /* // target is not a structure
    */ not IsUnitType(target, UNIT_TYPE_MECHANICAL) and /* // target is not mechanic
    */ not IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) //target is not magic immune
endfunction

//===========================================================================
//                          END CONFIGURABLES                        
//===========================================================================

globals
    private group G = bj_lastCreatedGroup
endglobals

private struct ArcaneBolt extends array
    readonly static constant integer ID = ABIL_ID
    private static constant real TRUE_SPEED = SPEED * 0.031250000
    private static constant real TRUE_COLLISION = COLLISION * COLLISION
    private static constant real PI_2 = bj_PI * 2
    private static constant real TRUE_ANGLE_RATE = ANGLE_RATE * 0.031250000 * bj_DEGTORAD
    
    private unit u
    private unit dummy
    private unit target
    private real damage
    
    private method fin takes nothing returns nothing
        call KillUnit(this.dummy)
        set this.u = null
        set this.dummy = null
        set this.target = null
        call this.destroy()
    endmethod
    
    implement CTL
        local real x
        local real y
        local real dx
        local real dy
        local real a
        local real facing
    implement CTLExpire
        if IsUnitType(this.target, UNIT_TYPE_DEAD) or GetUnitTypeId(this.target) == 0 or GetUnitTypeId(this.u) == 0 then
            call this.fin()
        else
            set x = GetUnitX(this.dummy)
            set y = GetUnitY(this.dummy)
            set dx = GetUnitX(this.target) - x
            set dy = GetUnitY(this.target) - y
            
            if dx * dx + dy * dy <= thistype.TRUE_COLLISION then
                call UnitDamageTarget(this.u, this.target, this.damage, true, false, ATK, DMG, null)
                call this.fin()
            else
                set a = Atan2(dy, dx)
                
                if ANGLE_RATE > 0 then
                    set facing = GetUnitFacing(this.dummy) * bj_DEGTORAD
                
                    if a < 0 then
                        set a = a + thistype.PI_2
                    endif
                    
                    if facing < a then
                        set facing = facing + thistype.PI_2
                    endif
                    
                    if facing - a < bj_PI then
                        set a = facing - thistype.TRUE_ANGLE_RATE
                    elseif facing - a > bj_PI then
                        set a = facing + thistype.TRUE_ANGLE_RATE
                    endif
                endif
                
                set x = x + thistype.TRUE_SPEED * Cos(a)
                set y = y + thistype.TRUE_SPEED * Sin(a)
                call SetUnitFacing(this.dummy, a * bj_RADTODEG)
                if x > WorldBounds.minX and y > WorldBounds.minY and x < WorldBounds.maxX and y < WorldBounds.maxY then
                    call SetUnitX(this.dummy, x)
                    call SetUnitY(this.dummy, y)
                endif
            endif
        endif
    implement CTLEnd

    public static method new takes unit caster, real x, real y returns thistype
        local thistype this
        local unit u
        local unit target = null
        local integer level = GetUnitAbilityLevel(caster, ABIL_ID)
        local real area = GetArea(level)

        static if RANDOM_SEEK then
            local integer rand = 0
            
            call GroupEnumUnitsInRange(G, x, y, area + ENUM_RADIUS, null)
            loop
                set u = FirstOfGroup(G)
                exitwhen u == null
                call GroupRemoveUnit(G, u)
                
                if IsUnitInRange(u, caster, area) and GetFilter(caster, u) then
                    set rand = rand + 1
                    
                    if GetRandomInt(1, rand) == 1 then
                        set target = u
                    endif
                endif
            endloop
        else
            local real dist = area * area
            local real r
            local real dx
            local real dy
            
            call GroupEnumUnitsInRange(G, x, y, area + ENUM_RADIUS, null)
            loop
                set u = FirstOfGroup(G)
                exitwhen u == null
                call GroupRemoveUnit(G, u)
                
                if IsUnitInRange(u, caster, area) and GetFilter(caster, u) then
                    set dx = GetUnitX(u) - x
                    set dy = GetUnitY(u) - y
                    set r = dx * dx + dy * dy
                    
                    if r <= dist then
                        set target = u
                        set dist = r
                    endif
                endif
            endloop
        endif
    
        if target != null then
            set this = thistype.create()
            set this.u = caster
            set this.dummy = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, x, y, GetRandomReal(0., 360.))
            set this.target = target
            set this.damage = GetDamage(level)
            
            call SetUnitVertexColor(this.dummy, RED, GREEN, BLUE, TRANS)
            call SetUnitScale(this.dummy, SCALE, 0, 0)
            call SetUnitFlyHeight(this.dummy, HEIGHT, 0)
        endif
        
        set u = null
        set target = null
        
        return this
    endmethod
endstruct

private struct Main extends array
    private static thistype array store
    
    private unit u
    private integer boltCount
    private real delay
    
    implement CTLExpire
        if GetUnitTypeId(this.u) == 0 or GetUnitAbilityLevel(this.u, ABIL_ID) == 0 then
            set thistype.store[GetUnitUserData(this.u)] = 0
        
            call this.destroy()
        elseif this.boltCount > 0 then
            if this.delay <= 0 then
                set this.boltCount = this.boltCount - 1
                set this.delay = GetDelay(GetUnitAbilityLevel(this.u, ABIL_ID))
                    
                call ArcaneBolt.new(this.u, GetUnitX(this.u), GetUnitY(this.u))
            else
                set this.delay = this.delay - 0.031250000
            endif
        endif
    implement CTLEnd

    private static method onCast takes nothing returns boolean
        local thistype this = thistype.store[GetUnitUserData(GetTriggerUnit())]
        
        if this != 0 then
            set this.boltCount = this.boltCount + GetBoltCount(GetUnitAbilityLevel(this.u, ABIL_ID))
        endif
    
        return false
    endmethod
    
    private static method onLearn takes nothing returns boolean
        local thistype this
        local integer level = GetUnitAbilityLevel(GetTriggerUnit(), ABIL_ID)
    
        if GetLearnedSkill() == ABIL_ID and level == 1 then
            set this = thistype.create()
            set this.u = GetTriggerUnit()
            set this.boltCount = 0
            set this.delay = GetDelay(level)
            set thistype.store[GetUnitUserData(this.u)] = this
        endif
    
        return false
    endmethod

    private static method onInit takes nothing returns nothing
        static if PRELOAD then
            call RemoveUnit(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, 0))
        endif
        
        call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_SKILL, function thistype.onLearn)
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
    endmethod
endstruct

endlibrary



Credits
Nestharus - CTL
- Unit Indexer
- WorldBounds
Magtheridon96 - RegisterPlayerUnitEvent
Bribe - SpellEffectEvent


Changelogs

- Initial relase


- Replaced GetUnitId() with GetUnitUserData()
- Added an equal to case for the angle comparison
- Removed the use of dynamic triggers in Arcane Bolts


- Structs are now private


Feedback will be appreciated.

Keywords:
artesia, hon, arcane, missile, bolt, dance, death, sorceress, mage
Contents

Untitled (Map)

Reviews
15 Feb 2016 IcemanBo: I rushed a bit. Check the latest post in thread. 13 Feb 2016 Bribe: The structs need to be private. 23:35, 23rd Oct 2013 PurgeandFire: Changes made. Approved. (old) Review (minor changes needed)...

Moderator

M

Moderator

15 Feb 2016
IcemanBo: I rushed a bit. Check the latest post in thread.

13 Feb 2016
Bribe:

The structs need to be private.

23:35, 23rd Oct 2013
PurgeandFire: Changes made. Approved.

(old) Review (minor changes needed):
http://www.hiveworkshop.com/forums/2435752-post5.html

VM or PM me if you have any questions. Otherwise I might not see the post.
 
Level 9
Joined
Dec 3, 2010
Messages
162
YAY!
You are back :D

Haven't tested this yet...
Do the arcane bolts arc in 2D? They do arc in HoN

Yep, they do arc in 2D. You can configure the turning rate as well.

In Arcane Missle:
This private static constant real TIMEOUT = 0.031250000 could be constant real TIMEOUT = 0.031250000 in your global block. Its not required for CTL.
In Dance of Death:
Null private unit u

Ah yeah, forgot to remove the constant vars. Will fix soon, thanks.
 
Nice job overall. Good to see some spells from you again.

Review:
  • Use GetUnitUserData(u) instead of GetUnitId(u). This will allow your spell to work off any indexer (except PUI, but I don't think that should be a big concern).
  • In Arcane Missile and Arcane Bolts, you have comparisons sort of like this:
    JASS:
    if facing - r < bj_PI then
        set facing = facing - TRUE_ANGLE_RATE
    elseif facing - r > bj_PI then
        set facing = facing + TRUE_ANGLE_RATE
    endif
    What about the case where facing - r = bj_PI? While the odds are astronomical, you should account for it with an >= or <=.
  • For Arcane Bolts, I don't think you really need dynamic triggers. You can just use a general spell cast trigger and check:
    if thistype.store[GetUnitUserData(GetTriggerUnit())] != 0 then
    And ofc, make sure that thistype.store[...] is set to 0 for units when you issue .destroy() or .fin().

Then it should be pretty much ready for approval. Thanks for making the review so easy for me. Normally spell packs take forever to review. :)
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
If they use scopes, new or uninitiated users trying to import the spell on a map would see generalized errors, they would struggle to fix that, but if the spell is written inside a library block then the errors would be easier to understand. I think...

I'm not against scopes though, I agree with your statement but some people are lazy, they won't bother learning why, just how.
 
Top