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

Summoning Nexus v1.0.2

CodeTooltip
Requires TimerUtils

JASS:
scope SummoningNexus initializer onInit
/**************************************************************
*
*   v1.0.2 by TriggerHappy
*
*   The caster conjurs orbs containing the souls of minions.
*
*   Level 1 - Summons 4 minions for 10 seconds. 
*   Level 2 - Summons 6 minions for 20 seconds. 
*   Level 3 - Summons 8 minions for 25 seconds. 
*
*   Requirements
*       TimerUtils         - http://www.wc3c.net/showthread.php?t=101322
*       xebasic (optional) - http://www.wc3c.net/showthread.php?t=101150
*
*   Credits
*       Vexorian for his scripts
*       Moyack and Spec for the ParabolaZ function
*
**************************************************************/

    globals
        private constant integer RAW_ID        = 'A000' // Spell raw code
        private constant integer DUMMY         = XE_DUMMY_UNITID // Dummy ID, incase you are not using xebasic.
        private constant integer LOCUST        = 'Aloc'
        private constant integer CROW_FORM     = 'Amrf'
        
        // The max number of units that can be summoned.
        // Increasing this number decreasing the instance limit.
        private constant integer MAX_SUMMONS   = 12
        
        private constant real TIMER_PERIOD     = 0.03 // How fast the timer is ran
        private constant real SPEED            = 10   // How fast the orbs move
        private constant real SPEED_INC        = 5    // Orbs speed increase
        private constant real ARC              = 0.8  // The arc of the orbs
        private constant real MOVE_DISTANCE    = 200  // How far away the orbs go
        
        private constant string EFFECT         = "Abilities\\Spells\\Other\\Parasite\\ParasiteTarget.mdl" // Orb Effect
        private constant string EXPLODE_EFFECT = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl"    // Summon FX
    endglobals
    
    // what unit is summoned.
    private constant function SUMMONED_UNIT takes integer level returns integer
        return 'ndr1'
    endfunction
    
    private constant function SPACING takes integer count returns real
        return 360.0/count // looks bad if the number is not even
    endfunction
    
    // how long the summons live for
    private constant function SUMMON_LIFE takes real level returns real
        if (level > 2) then
            set level = level - 0.5
        endif
        return 10.0*level 
    endfunction
    
    private constant function ParabolaZ takes real d, real h, real x returns real // moyack/Spec
        return ( 4 * h / d ) * ( d - x ) * ( x / d )
    endfunction
    
    // How many units are summoned
    private constant function SUMMON_COUNT takes integer level returns integer
        local integer i
        
        if (level == 1) then
            return 4
        else
            set i = (2*(level-1)) + 4
            if (i > MAX_SUMMONS) then
                return MAX_SUMMONS
            endif
            return i
        endif
    endfunction
    
/**************************************************************
*
*   DON'T EDIT BELOW THIS LINE 
*
**************************************************************/
    
    private struct data
        
        unit caster
        real x
        real y
        real speed = SPEED
        real dist  = 0
        real d2    = 0
        unit array fx[MAX_SUMMONS]
        real array cos[MAX_SUMMONS]
        real array sin[MAX_SUMMONS]
        real array dx[MAX_SUMMONS]
        real array dy[MAX_SUMMONS]
        
        integer count
        integer level
        
        player p
        
        method destroy takes nothing returns nothing
            local integer i = 0
            loop
                exitwhen i > this.count-1
                call RemoveUnit(this.fx[i])
                set this.fx[i] = null
                set i = i + 1
            endloop
            set this.caster = null
            call this.deallocate()
        endmethod
        
        static method callback takes nothing returns nothing
            local data this = GetTimerData(GetExpiredTimer())
            local integer b = 0
            local boolean a = false
            
            // Calculate how much distance is left and incrementally
            // increase the speed
            set this.dist   = this.d2-this.speed
            set this.speed  = this.speed + SPEED_INC
            
            // If effects are finished, destroy the instance
            if (this.dist <= 0) then
                call this.destroy()
                call ReleaseTimer(GetExpiredTimer())
                set a=true 
            endif
            
            loop
                exitwhen b > this.count-1
                set this.dx[b]  = this.x + this.speed * this.cos[b]
                set this.dy[b]  = this.y + this.speed * this.sin[b]
                
                call SetUnitX(this.fx[b], this.dx[b])
                call SetUnitY(this.fx[b], this.dy[b])
                
                call SetUnitFlyHeight(this.fx[b], ParabolaZ(this.d2, this.d2 * ARC, this.speed), 0)
                
                // If spell is finished then create the summoned units
                if (a) then
                    call DestroyEffect(AddSpecialEffect(EXPLODE_EFFECT, this.dx[b], this.dy[b]))
                    call UnitApplyTimedLife(CreateUnit(this.p, SUMMONED_UNIT(this.level), this.dx[b], this.dy[b], 270), 'BTLF', SUMMON_LIFE(this.level))
                endif
                
                set b = b + 1
            endloop
        endmethod
        
        static method create takes unit caster returns data
            local data this = data.allocate()
            local integer b = 0
            local real i    = 0
            local real c
            local real dx
            local real dy
            local integer id
            
            // Store caster info and other data inside the struct to avoid
            // extra function calls.
            set this.caster = caster
            set this.p      = GetOwningPlayer(caster)
            set this.level  = GetUnitAbilityLevel(this.caster, RAW_ID)
            set this.count  = SUMMON_COUNT(this.level)
            set this.x      = GetUnitX(this.caster)
            set this.y      = GetUnitY(this.caster)
            set c           = SPACING(this.count)
            
            // Create the circle of effects
            loop
                exitwhen i >= 360 or b > this.count-1
                // Store the angle and direction of the effects
                set this.cos[b] = Cos(i * bj_DEGTORAD)
                set this.sin[b] = Sin(i * bj_DEGTORAD)
                set this.dx[b]  = this.x + 90 * this.cos[b]
                set this.dy[b]  = this.y + 90 * this.sin[b]
                
                // Create a dummy unit to attach the effect
                set this.fx[b]  = CreateUnit(this.p, DUMMY, this.dx[b], this.dy[b], 0)
                
                // Give the dummy crow form so we can change it's height
                call UnitAddAbility(this.fx[b], CROW_FORM)
                
                // And locust to make it unselectable
                call UnitAddAbility(this.fx[b], LOCUST)
                
                // Apply the effect
                call AddSpecialEffectTarget(EFFECT, this.fx[b], "origin")
                
                // If it's the first iteration of the loop, store some data
                if (b==0) then
                    set dx        = (this.x+MOVE_DISTANCE) - this.dx[b]
                    set dy        = (this.y+MOVE_DISTANCE) - this.dy[b]
                    set this.dist = SquareRoot(dx * dx + dy * dy)
                    set this.d2   = this.dist
                endif
                
                // Apply the units height at an angle
                call SetUnitFlyHeight(this.fx[b], ParabolaZ(SPEED, SPEED * ARC, this.dist), 0)
                
                set b = b + 1
                set i = i + c
            endloop

            call TimerStart(NewTimerEx(this), TIMER_PERIOD, true, function data.callback)
            
            return this
        endmethod
        
    endstruct
    
    private function Actions takes nothing returns boolean
        if (GetSpellAbilityId() == RAW_ID) then
            call data.create(GetTriggerUnit())
        endif
        return false
    endfunction
    
    private function onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t, Filter(function Actions))
    endfunction

endscope
tooltip_sn.jpg

Keywords:
parabola, fountain, nexus, summon, summoning, epic shit
Contents

Summoning Nexus 1.0.2 (Map)

Reviews
17:08, 19th Jan 2010 The_Reborn_Devil: The coding looks good and the effects are nice. It's pretty unique too I think. Status: Approved Rating: Recommended

Moderator

M

Moderator

17:08, 19th Jan 2010
The_Reborn_Devil:
The coding looks good and the effects are nice. It's pretty unique too I think.

Status: Approved
Rating: Recommended
 
Level 10
Joined
Jul 12, 2009
Messages
318
Are the orbs supposed to be selectable/show a health bar? Seems like an oversight.

Also, the effect seems so simple as to be reproducible with only a dummy casting a modified Pocket Factory spell in a circle, no need for sliding unit-projectiles at all...
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
JASS:
    private constant function SUMMON_COUNT takes integer level returns integer
        local integer i = 4*level // How many units are summoned
        if (i < MAX_SUMMONS) then
            return i
        endif
        return 8
    endfunction

Shouldn't it be:
JASS:
    private constant function SUMMON_COUNT takes integer level returns integer
        local integer i = 4*level // How many units are summoned
        if (i < MAX_SUMMONS) then
            return i
        endif
        return MAX_SUMMONS
    endfunction

Since 8 seems a bit random, no?
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
Are the orbs supposed to be selectable/show a health bar? Seems like an oversight.

Also, the effect seems so simple as to be reproducible with only a dummy casting a modified Pocket Factory spell in a circle, no need for sliding unit-projectiles at all...

agree

another option would be using the panda's storm earth fire spell and a trigger which creates summons if the missiles die

and I really don't get why the dummys don't have locust o_O
 
The jump looks kinda ugly.

It looks fine, and actually good. IMO.

It summons skeletons? Come'on, thats really bad. You could create explosions there which raises skeletons if units die there, but this...

Uhm, you do know it's called summoning nexus right?

The effect has nothing to do with undeads at all.

I strongly disagree.

@Everyone else

I'll fix the locust and some other stuff.
 
Top