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

Zephyr Contest #14 - Unique Summoning

Status
Not open for further replies.
Level 22
Joined
Feb 6, 2014
Messages
2,466
Aerial Aid [Work in Progress]

WIP #1

I can't use ScreenToGif because it requires some .NET framework or something which I don't currently have because I recently did a factory reset so I'll just upload my WIP map with my WIP code.
Disclaimer: My current WC3 version is 1.24 so I don't know if it will work for 1.26.


JASS:
scope AerialAid/*

    *************************** Aerial Aid aplha version *****************************
                                    by Flux
    
  SPELL DESCRIPTION:
    Calls an unmanned aerial vehicle (UAV) containing your army of robotic minions. 
    The UAV is equuipped with 2/3/4 guns which fires at enemy units in its field of 
    sight targeting heroes and units with low hitpoints. Upon activation, 'Aerial Aid' 
    is replaced by the sub-skill 'Deploy Paratroopers' which commands your robotic army 
    to parachute from the UAV.

    
  SPELL NOTES (Default Configuration):
    - Heroes have higher priority than units with lower hitpoints.
    - The target location will be the midpoint of the line connecting
      the spawn location and expire location.
    - The UAV will reach the target point when half of the UAV duration has
      elapsed.
    - UAV guns can only hit units within the field of sight of the UAV. The
      field of sight has a conic shape and cannot hit units directly below it.
    - The falling entrance and rising exit of the UAV is not part of the
      spell duration, and the UAV is not active during that time.
    
    To do list (Order by Priority):
        - Fix Object Editor Data (including creating my own screenshot icon for this contest)
        - Use a better lightning model for the target something that looks like a laser.
        - Create SFX where the Plane will go, something like a runway light SFX.
        - Add Snipe Target SFX.
        - Instead of a new unit-type per level, consider using BonusMod.
          In the end, it will require 1 troope fly-type, 1 troop ground-type, 1 transform ability 
          and 1 uav-unitType in all levels.
        - Fix World Bounds stuffs.
        - Instead of a gun with instant gun shot, consider using a missile projectile.
  
    
  CREDITS:
      Bribe         - MissileRecycler, SpellEffectEvent, Table
      NatDis        - Dwarven Air Force DF 35 Fighter
      Fingolfin     - Parachute Model
      Tranquil      - Snipe Target Model
      Magtheridon96 - RegisterPlayerUnitEvent
*/

    native UnitAlive takes unit u returns boolean
    
    globals
        //Rawcodes
        private constant integer SPELL_ID = 'Aaer'
        private constant integer SPELL_ID_DEPLOY = 'Adpy'
        private constant integer HIDE_ID = 'Ahde'
        
        //Dummy Unit Properties
        private constant integer DUMMY_ID = 'dumi'
        private constant player DUMMY_OWNER = Player(14)
        
        //Periodic Timing of the Spell
        private constant real TIMEOUT = 0.03125
        
        //Visual Effects
        private constant string PARACHUTE_MODEL = "war3mapImported\\Parachute.mdl"
        private constant string TARGET_MODEL = "war3mapImported\\SniperTarget.mdl"
        private constant string TARGET_ATTACHMENT = "overhead"
        private constant string LASER_CODE = "DRAL"
        
        //Attack and Damage types
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
        private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
        
        
        //************************************************************************************
        //**************************** PLANE CONFIGURATION ***********************************
        //************************************************************************************
        private constant real PLANE_HEIGHT_INITIAL = 1200
        private constant real PLANE_HEIGHT = 600
        private constant real PLANE_FALL_SPEED = 700   
        
        //************************************************************************************
        //***************************** GUN CONFIGURATION ************************************
        //************************************************************************************
        //Minumum distance from the plane to hit
        //It won't hit units having an azimuthal distance less than MIN_HIT_DISTANCE to the plane.
        private constant real MIN_HIT_DISTANCE = 450
        
        //Conic Radius for the Plane Gun (degrees)
        private constant real PLANE_SIGHT_ANGLE = 45
        
        //Plane Gun will prioritize targeting hero
        private constant boolean PRIORITIZE_HERO = true
        
        //************************************************************************************
        //************************ PARATROOPER CONFIGURATION *********************************
        //************************************************************************************
        
        //Is the number of paratroopers that can spawn limited per spell?
        private constant boolean LIMIT_SPAWN = true
        
        //When the Paratrooper's height is below GND_HEIGHT, it is now targeted
        //as a ground unit
        private constant real GND_HEIGHT = 100
        
        //Does the Paratroopers have a Timed Life?
        private constant boolean APPLY_TIMED_LIFE = true
        
        //When the current height of the Paratrooper is less than PARACHUTE_ACTIVATE, it will
        //activate its
        private constant real PARACHUTE_ACTIVATE = 400
        
        //How fast Paratroopers accelerates when their parachute is not yet used (speed per second)
        private constant real PARATROOPER_GRAVITY = 150
        
        //How fast Paratroopers will fall upon using their parachute (displacement per second)
        private constant real PARACHUTE_FALL_SPEED = 180
        
        //When the Paratrooper hits the ground at this z-speed (displacement per second), it will die!
        private constant real SPEED_WITH_DAMAGE = 400
        
        //The lower the values, the greater the friction (for calculation simplicity)
        private constant real DRAG_COEFFICIENT = 0.3
        
    endglobals
    
    //************************************************************************************
    //*************************** PLANE CONFIGURATION ************************************
    //************************************************************************************
    
    //The rawcode of the Plane per level
    private function PlaneId takes integer lvl returns integer
        return 'uav0' + lvl //uav1, uav2, uav3
    endfunction
    
    //How fast the Plane moves (per second)
    private function PlaneSpeed takes integer lvl returns real
        return 350.0 + 50.0*lvl
    endfunction
    
    //How long the Plane will last
    private function Duration takes integer lvl returns real
        return 8.0 + 0.0*lvl    //0.0*lvl exist to make the function inline
    endfunction
    
    //************************************************************************************
    //***************************** GUN CONFIGURATION ************************************
    //************************************************************************************
    
    //Search radius for gun target
    private function GunRadius takes integer lvl returns real
        return 900.
    endfunction
    
    //How fast the gun fires
    private function GunFiringRate takes integer lvl returns real
        return 0.2                  //Every 0.2 second, each gun will fire
    endfunction
    
    //Damage per gun bullet
    private function GunDamage takes integer lvl returns real
        return 3.0 + 2.0*lvl        //5, 7, 9     
    endfunction
    
    //Number of Plane's gun per level
    private function GunCount takes integer lvl returns integer
        return 1 + lvl              //2, 3, 4
    endfunction
    
    //What gets hit by the Gun
    private function TargetFilter takes unit u, player owner returns boolean
        return UnitAlive(u) and IsUnitEnemy(u, owner)
    endfunction
    
    //Position of Guns with reference to the Plane's center when the Plane is facing 0 degrees.
    //gunNumber starts at 1
    private function GunOffsetX takes integer gunNumber, integer totalGunNumber returns real
        return 0. + 0*gunNumber + 0*totalGunNumber    //All guns will belong to the same x-axis of the Plane
    endfunction
    
    private function GunOffsetY takes integer gunNumber, integer totalGunNumber returns real
        if totalGunNumber == 2 then
            return -150. + gunNumber*100   //-50, 50
        elseif totalGunNumber == 3 then
            return -100. + gunNumber*50   //-50, 0, 50
        elseif totalGunNumber == 4 then
            return -100. + gunNumber*40   //-60, -20, 20, 60
        endif
        return 0.
    endfunction
    
    //************************************************************************************
    //************************** PARATROOPER CONFIGURATION *******************************
    //************************************************************************************
    
    //ParatrooperGroups will spawnrate (second)
    private function SpawnRate takes integer lvl returns real
        return 0.5 + 0.0*lvl       //Every 0.5 second, a ParatrooperGroup will spawn
    endfunction
    
    static if LIMIT_SPAWN then
        //The maximum number of paratroopers the spell can spawn
        private function MaxSpawnCount takes integer lvl returns integer
            return 4 + 2*lvl            //6, 8, 10
        endfunction
    endif
    
    //The rawcode of the Flying Paratrooper per level
    private function ParatrooperOnAirId takes integer lvl returns integer
        return 'trp3' + lvl //trp4, trp5, trp6
    endfunction
    
    //Inorder to make it realistic, Paratroopers are first considered flying units and
    //when it reaches GND_HEIGHT, it will now be considered as a ground unit.
    //This is the rawcode of the transform ability needed for the fly->ground transformation
    private function TransformAbility takes integer lvl returns integer
        return 'Atf0' + lvl //Atf1, Atf2, Atf3
    endfunction
    
    static if APPLY_TIMED_LIFE then
        //Only applicable if APPLY_TIMED_LIFE = true
        //Determines how long each Paratrooper last.
        private function TimedLife takes integer lvl returns real
            return 7.0 + 1.0*lvl
        endfunction
    endif
    
    globals
        private location l = Location(0, 0)
    endglobals
    
    private struct Paratrooper
        
        private unit robot
        private unit parachute
        private effect parachuteModel
        private boolean activated 
        private integer transform
        
        //Movement
        private real z
        private real dz 
        
        private thistype next
        private thistype prev
        
        private static timer t = CreateTimer()
        
        //constants to avoid repeating calculations
        //constants to fill in the TIMEOUT
        private static constant real GRAVITY = -PARATROOPER_GRAVITY*TIMEOUT
        private static constant real SPEED_DAMAGE = SPEED_WITH_DAMAGE*TIMEOUT
        private static constant real TERMINAL_VELOCITY = -PARACHUTE_FALL_SPEED*TIMEOUT
        
        //Calls when the robot landed
        private method destroy takes nothing returns nothing
            //Remove from List
            set .prev.next = .next
            set .next.prev = .prev
            //Remove Parachute
            call DestroyEffect(.parachuteModel)
            static if LIBRARY_DummyRecycler then
                call AddRecycleTimer(.parachute, 3.0)
            elseif LIBRARY_MissileRecycler then
                call RecycleMissile(.parachute)
            else
                //Enough time for the parachute to play death animation
                call UnitApplyTimedLife(.parachute, 'BTLF', 2)
            endif
            set .parachuteModel = null
            set .robot = null
            set .parachute = null
            call .deallocate()
        endmethod
        
        //! textmacro PARATROOPER_UPDATE
            set .z = .z + .dz
            if .activated then
                if .dz < TERMINAL_VELOCITY then
                    //Apply drag (air-resistance)
                    set .dz = .dz*DRAG_COEFFICIENT
                    if .dz > TERMINAL_VELOCITY then
                        set .dz = TERMINAL_VELOCITY
                    endif
                else
                    //increase speed due to gravity until it reaches terminal velocity
                    set .dz = .dz + GRAVITY
                endif
            else
                set .dz = .dz + GRAVITY
                if .z < PARACHUTE_ACTIVATE then
                    set .activated = true
                    //Create the Parachute
                    static if LIBRARY_DummyRecycler then
                        set .parachute = GetRecycledUnit(GetUnitX(.robot), GetUnitY(.robot), false, GetRandomReal(0, 360))
                    elseif LIBRARY_MissileRecycler then
                        set .parachute = GetRecycledMissile(GetUnitX(.robot), GetUnitY(.robot), 0, GetRandomReal(0, 360))
                    else
                        set .parachute = CreateUnit(DUMMY_OWNER, DUMMY_ID, GetUnitX(.robot), GetUnitY(.robot), GetRandomReal(0, 360))
                    endif
                    set .parachuteModel = AddSpecialEffectTarget(PARACHUTE_MODEL, .parachute, "origin")
                    call SetUnitFlyHeight(.parachute, .z, 0)
                endif
            endif
            if .z <= 0 then
                call SetUnitFlyHeight(.parachute, .z, 0)
                //For realism effect
                if .dz < -SPEED_DAMAGE then
                    call KillUnit(.robot)
                endif
                call .destroy()
            else
                call SetUnitFlyHeight(.robot, .z, 0)
                if .activated then
                    call SetUnitFlyHeight(.parachute, .z, 0)
                endif
                if .z < GND_HEIGHT and .transform != 0 then
                    call UnitAddAbility(.robot, .transform)
                    call UnitRemoveAbility(.robot, .transform)
                    set .transform = 0
                endif
            endif
        //! endtextmacro
        
        private static method pickAll takes nothing returns nothing
            local thistype this = thistype(0).next
            loop
                exitwhen this == 0
                //! runtextmacro PARATROOPER_UPDATE()
                set this = .next
            endloop
        endmethod
        
        static method create takes player owner, integer lvl, real x, real y, real z returns thistype
            local thistype this = .allocate()
            local real spd = 0
            
            //Paratrooper Initialization
            set .transform = TransformAbility(lvl)
            set .activated = false
            set .z = z
            set .dz = 0
            
            //Create the Robot
            set .robot = CreateUnit(owner, ParatrooperOnAirId(lvl), x, y, GetRandomReal(0, 360))
            static if APPLY_TIMED_LIFE then
                call UnitApplyTimedLife(.robot, 'BTLF', TimedLife(lvl))
            endif
            call SetUnitFlyHeight(.robot, .z, 0)
            static if not CAN_BE_HIT then
                call UnitAddAbility(.robot, 'Avul')
            endif
            //Linked-list
            set .next = 0
            set .prev = thistype(0).prev
            set .next.prev = this
            set .prev.next = this
            if .prev == 0 then
                call TimerStart(t, TIMEOUT, true, function thistype.pickAll)
            endif
            return this
        endmethod
        
    endstruct
    
    //Missile launched by the Gun
    private struct Missile
    endstruct
    
    private struct Gun
        
        private lightning laser
        private boolean hidden
        private effect targetSfx
        readonly unit target
        private real dx
        private real dy
    
        
        readonly thistype next
        readonly thistype prev
        
        method destroy takes nothing returns nothing
            //Remove from List
            set .prev.next = .next
            set .next.prev = .prev
            if .laser != null then
                call DestroyLightning(.laser)
                set .laser = null
            endif
            set .target = null
            call .deallocate()
        endmethod
        
        method update takes unit newTarget, real x, real y, real z returns nothing
            local real targetX
            local real targetY
            if newTarget == null then
                if not .hidden then
                    set .hidden = true
                    call SetLightningColor(.laser, 0, 0, 0, 0)
                endif
            else
                if .hidden then
                    set .hidden = false
                    call SetLightningColor(.laser, 1, 1, 1, 1)
                endif
                set targetX = GetUnitX(newTarget)
                set targetY = GetUnitY(newTarget)
                call MoveLocation(l, targetX, targetY)
                call MoveLightningEx(.laser, false, x + .dx, y + .dy, z, targetX, targetY, GetLocationZ(l))
            endif
            set .target = newTarget
        endmethod
        
        static method head takes nothing returns thistype
            local thistype this = .allocate()
            set .next = 0
            set .prev = 0
            return this
        endmethod
        
        static method create takes thistype head, real dx, real dy returns thistype
            local thistype this = .allocate()
            set .laser = AddLightning(LASER_CODE, false, 0, 0, 1, 1)
            set .hidden = true
            set .dx = dx
            set .dy = dy

            call SetLightningColor(.laser, 0, 0, 0, 0)
            set .next = head.next
            set .prev = head
            set .next.prev = this
            set .prev.next = this
            return this
        endmethod
        
    endstruct
    
    
    //The self-sorting list, using an Insertion Sort algorithm
    private struct List
    
        private real value
        readonly unit unit
        readonly thistype next
        readonly thistype prev
        
        method destroy takes nothing returns nothing
            //Remove List
            set .prev.next = .next
            set .next.prev = .prev
            set .value = 0
            set .next = 0
            set .unit = null
            call .deallocate()
        endmethod
        
        static method empty takes nothing returns nothing
            local thistype this = thistype(0).next
            loop
                exitwhen this == 0
                call .destroy()
                set this = thistype(0).next
            endloop
        endmethod
        
        static method add takes unit u, real hp, integer count returns nothing
            local thistype node = thistype(0).next  //head node is thistype(0)
            local boolean insert = true
            local thistype this
            static if PRIORITIZE_HERO then
                local boolean isHero = IsUnitType(u, UNIT_TYPE_HERO)
            endif
            //Insert in the current list
            loop
                exitwhen node == 0 
                static if PRIORITIZE_HERO then
                    if isHero then
                        exitwhen hp < node.value or not IsUnitType(node.unit, UNIT_TYPE_HERO)
                    else
                        exitwhen hp < node.value and not IsUnitType(node.unit, UNIT_TYPE_HERO)
                    endif
                else
                     exitwhen hp < node.value
                endif
                set count = count - 1
                //If it will not get included in the count anyway, end the insertion and do not insert it in the list
                if count == 0 then
                    set insert = false
                    exitwhen true
                endif
                set node = node.next
            endloop
            //Insert 'this' before 'node'
            if insert then
                set this = .allocate()
                set .unit = u
                set .value = hp
                set .next = node
                set .prev = node.prev
                set .next.prev = this
                set .prev.next = this
            endif
        endmethod
    endstruct

    
    private struct Plane
        
        //Spell Mechanics
        private unit caster
        private unit plane
        private player owner
        private effect planeModel
        private integer lvl
        private boolean toggled
        
        //Gun-related
        private Gun gunHead
        private real radius
        private integer gunCount
        private real gunDamage
        private real gunFireTime
        
        //Paratrooper-related
        private real robotSpawnRate
        private boolean deploy
        static if LIMIT_SPAWN then
            private integer spawnCtr    //number of paratrooper deployed
        endif
        
        //Timing
        private real gunCtr     //counter for gun firing rate
        private real robotCtr   //counter for paratrooper deployment
        private real duration
        
        //Movement
        private real x
        private real y
        private real z
        private real angle
        private real dx
        private real dy
        private real dz
        
        private thistype next
        private thistype prev
        
        private static timer t = CreateTimer()
        private static group g = CreateGroup()
        
        static if LIBRARY_Table then
            private static Table tb
        else
            private static hashtable hash = InitHashtable()
        endif
        
        private method destroy takes nothing returns nothing
            //Remove from List
            set .prev.next = .next
            set .next.prev = .prev
            //Destroy Handles
            call DestroyEffect(.planeModel)
            call RemoveUnit(.plane)
            //For perfect clean-up
            set .caster = null
            set .planeModel = null
            set .plane = null
            //Recycle Index
            call .deallocate()
        endmethod

            
        //! textmacro UAV_UPDATE
            set gun = .gunHead.next
            //Movement
            set .x = .x + .dx
            set .y = .y + .dy
            call SetUnitX(.plane, .x)
            call SetUnitY(.plane, .y)
            if .duration > 0 then
                if .z > PLANE_HEIGHT then
                    set .z = .z + .dz
                    if .z < PLANE_HEIGHT then
                        set .z = PLANE_HEIGHT
                    endif
                    call SetUnitFlyHeight(.plane, .z, 0)
                endif
                //Will only do some action if it has stable height
                if .z == PLANE_HEIGHT then
                    set .duration = .duration - TIMEOUT
                    //Targeting
                    call GroupEnumUnitsInRange(g, .x, .y, .radius, null)
                    loop
                        set u = FirstOfGroup(g)
                        exitwhen u == null
                        call GroupRemoveUnit(g, u)
                        if TargetFilter(u, .owner) then
                            set diffX = GetUnitX(u) - .x
                            set diffY = GetUnitY(u) - .y
                            //If greater than minimum distance
                            if diffX*diffX + diffY*diffY >= MIN_HIT_DISTANCE*MIN_HIT_DISTANCE then
                                //if within angle of sight
                                if RAbsBJ(.angle - Atan2(diffY, diffX)) <= PLANE_SIGHT_ANGLE*bj_DEGTORAD then
                                    //Add the Picked Unit to the Self-Sorting List
                                    call List.add(u, GetWidgetLife(u), .gunCount)
                                endif
                            endif
                        endif
                    endloop
                    //Update Gun Targets
                    set list = List(0).next
                    loop
                        exitwhen gun == 0
                        call gun.update(list.unit, .x, .y, .z)
                        set list = list.next
                        //No idle gun if there are less targets
                        if list == 0 then
                            set list = List(0).next
                        endif
                        set gun = gun.next
                    endloop
                    //Empty the list
                    call List.empty()
                    //Are the guns ready?
                    set .gunCtr = .gunCtr + TIMEOUT
                    if .gunCtr >= .gunFireTime then
                        set .gunCtr = .gunCtr - .gunFireTime
                        set gun = .gunHead.next
                        loop
                            exitwhen gun == 0 or gun.target == null
                            call UnitDamageTarget(.caster, gun.target, .gunDamage, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                            set gun = gun.next
                        endloop
                    endif
                    //Are paratroopers commanded to deploy?
                    if .deploy then
                        set .robotCtr = .robotCtr + TIMEOUT
                        if .robotCtr >= .robotSpawnRate then
                            set .robotCtr = .robotCtr - .robotSpawnRate
                            static if LIMIT_SPAWN then
                                if .spawnCtr < MaxSpawnCount(.lvl) then
                                    call Paratrooper.create(.owner, .lvl, .x, .y, .z)
                                    set .spawnCtr = .spawnCtr + 1
                                endif
                            else
                                call Paratrooper.create(.owner, .lvl, .x, .y, .z)
                            endif
                        endif
                    endif
                endif
            else
                //Toggle Ability
                if .toggled then
                    set .toggled = false
                    call UnitRemoveAbility(.caster, HIDE_ID)
                    call UnitRemoveAbility(.caster, SPELL_ID_DEPLOY)
                endif
                //Destroy Guns
                if .gunHead != 0 then
                    loop
                        exitwhen gun == 0
                        call gun.destroy()
                        set gun = .gunHead.next
                    endloop
                    call .gunHead.destroy()
                    set .gunHead = 0
                endif
                //Make the plane rise again until it is no longer seen in the screen
                set .z = .z - .dz
                if .z > PLANE_HEIGHT_INITIAL then
                    call .destroy()
                else
                    call SetUnitFlyHeight(.plane, .z, 0)
                endif
            endif
        //! endtextmacro

        
        private static method pickAll takes nothing returns nothing
            local thistype this = thistype(0).next
            //update local variables
            local unit u 
            local real diffX
            local real diffY
            local Gun gun
            local List list
            loop
                exitwhen this == 0
                //! runtextmacro UAV_UPDATE()
                set this = .next
            endloop
        endmethod
        
        private static method onCast takes nothing returns boolean
            local thistype this = .allocate()
            local integer i = 1
            local real x
            local real y
            local real cos
            local real sin
            local real spd
            local real gunX
            local real gunY
        
            //Spell Initialization
            set .caster = GetTriggerUnit()
            set .owner = GetTriggerPlayer()
            set .deploy = false
            set .lvl = GetUnitAbilityLevel(.caster, SPELL_ID)
            static if LIMIT_SPAWN then
                set .spawnCtr = 0
            endif
            set .gunHead = Gun.head()
            set .gunCtr = 0
            set .gunFireTime = GunFiringRate(.lvl)
            set .gunDamage = GunDamage(.lvl)
            set .robotCtr = 0
            set .robotSpawnRate = SpawnRate(.lvl)
            set .duration = Duration(.lvl)
            set .radius = GunRadius(.lvl)
            set x = GetSpellTargetX()
            set y = GetSpellTargetY()
            set .angle = Atan2(y - GetUnitY(.caster), x - GetUnitX(.caster))
            set cos = Cos(.angle)
            set sin = Sin(.angle)
            set .gunCount = GunCount(.lvl)
            loop
                exitwhen i > .gunCount
                set gunX = GunOffsetX(i, .gunCount)
                set gunY = GunOffsetY(i, .gunCount)
                call Gun.create(.gunHead, gunX*cos - gunY*sin, gunY*cos + gunX*sin)
                set i = i + 1
            endloop
            set spd = PlaneSpeed(.lvl)*TIMEOUT
            //Calculate the spawn loc based on duration and target location with an offset for the rise/fall of the plane
            set .x = x - (0.5*.duration + (PLANE_HEIGHT_INITIAL - PLANE_HEIGHT)/PLANE_FALL_SPEED)*PlaneSpeed(.lvl)*cos
            set .y = y - (0.5*.duration + (PLANE_HEIGHT_INITIAL - PLANE_HEIGHT)/PLANE_FALL_SPEED)*PlaneSpeed(.lvl)*sin
            set .z = PLANE_HEIGHT_INITIAL
            set .dx = spd*cos
            set .dy = spd*sin
            set .dz = -PLANE_FALL_SPEED*TIMEOUT
            set .plane = CreateUnit(.owner, PlaneId(.lvl), .x, .y, angle*bj_RADTODEG)
            call UnitRemoveAbility(.plane, 'Amov')
            call SetUnitFlyHeight(.plane, .z, 0)
            
            //Store caster handle id for onDeploy data retrieval
            static if LIBRARY_Table then
                set tb[GetHandleId(.caster)] = this
            else
                call SaveInteger(hash, GetHandleId(.caster), 0, this)
            endif
            
            //Toggle Ability
            set .toggled = true
            call UnitAddAbility(.caster, HIDE_ID)
            call UnitAddAbility(.caster, SPELL_ID_DEPLOY)
            
            //Linked-list
            set .next = 0
            set .prev = thistype(0).prev
            set .next.prev = this
            set .prev.next = this
            if .prev == 0 then
                call TimerStart(t, TIMEOUT, true, function thistype.pickAll)
            endif
            return false
        endmethod
        
        private static method onDeploy takes nothing returns boolean
            static if LIBRARY_Table then
                local thistype this = tb[GetHandleId(GetTriggerUnit())]
            else
                local thistype this = LoadInteger(hash, GetHandleId(GetTriggerUnit()), 0)
            endif
            
            set .deploy = true
            
            //Toggle Ability
            set .toggled = false
            call UnitRemoveAbility(.caster, HIDE_ID)
            call UnitRemoveAbility(.caster, SPELL_ID_DEPLOY)
            
            return false
        endmethod
        
        static if not LIBRARY_SpellEffectEvent then
            private static method castCondition takes nothing returns boolean
                return (GetSpellAbilityId() == SPELL_ID and thistype.onCast() )
            endmethod
        endif
        
        static if not LIBRARY_SpellEffectEvent then
            private static method releaseCondition takes nothing returns boolean
                return (GetSpellAbilityId() == SPELL_ID_DEPLOY and thistype.onDeploy() )
            endmethod
        endif

        
        private static method onInit takes nothing returns nothing
            local integer i = 0
            static if LIBRARY_SpellEffectEvent then
                call RegisterSpellEffectEvent(SPELL_ID, function thistype.onCast)
                call RegisterSpellEffectEvent(SPELL_ID_DEPLOY, function thistype.onDeploy)
            else
                local trigger t = CreateTrigger()
                call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                call TriggerAddCondition(t, Condition(function thistype.castCondition))
                call TriggerAddCondition(t, Condition(function thistype.releaseCondition))
            endif
            static if LIBRARY_Table then
                set tb = Table.create()
            endif
            loop
                exitwhen i == bj_MAX_PLAYER_SLOTS
                call SetPlayerAbilityAvailable(Player(i), HIDE_ID, false)
                set i = i + 1
            endloop
        endmethod
    
    endstruct

endscope
 

Attachments

  • Aerial Aid v1.00.w3x
    200 KB · Views: 68
YES.jpg


Finished writing 2 out of 3 core effects of the summoned unit.

I might as well finish my entry tomorrow
 
Don't post your entry into the spell section before the
contest deadline for entries has expired. It's unfair towards
other contest attendees.

Fair play please.

You can just ignore the spell submissions. That's how Magtheridon96 and other moderators handles it in the past

or just for the sake of the contest, close the thread so that noone can give a review
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
You can just ignore the spell submissions.

The issue is the contestant getting a spell review from other users who are possibly unaware of the contest. I saw a contestant upload their submission within seconds of their initial upload, and I would have given an extensive review if it were not for the fact I knew that the concept was their contest entry. Deleting the submission or closing the thread would be the only solution.
 
Level 9
Joined
Oct 14, 2013
Messages
238
OK here is some clarification. First of all I didn't know about it. Second, I previously attached my map to my post and meatmuffin told me that I shouldn't do it that way. And since I didn't know anywhere else to upload my map I posted it in the spell section.

And by the way, I thought it was like the previous cinematic contest where all the submissions posted their entries in the cinematic section or in youtube. So, no one is trying to foul play.

and
I'm temporary hiding these submissions.
They will be visible again to the community after the contest deadline.
Thank you for doing that. I didn't want to post my entry in any other place. I can say, your action was the best thing that I could have hoped for.
 
Level 9
Joined
Oct 14, 2013
Messages
238
You should attach the map, not link it to a pastebin.

Most people won't bother looking at your attached map.

Look at this comment. I had done the same thing but I thought maybe I should do something else.

Edit
BPower, there's no need to unhide the submission. Please delete it right away. As I said earlier I don't want it in spell section or any other sections. And for the record if anyone hadn't noticed yet, I've removed all my maps from this site and this spell is not an exception. Once again no foul play intended.

When somebody like meatmuffin says something that can be misguiding, nobody gives a shit about it, and when I go and do the wrong thing, the spam they make over the issue is really upsetting.

Delete it, delete my entry, do whatever you like to do. It's no longer important for me to win if it's foul play!!
 
Level 11
Joined
Jul 25, 2014
Messages
490
What I meant by posting a map along with a wip and nothing else, is that it is better to post images/gifs/code instead of the actual map.

There's no reason for you to get, to be blunt, butthurt, it is just common knowledge that you shouldn't upload it to the spell section, it's like sending your work to your teacher, get your mistakes pointed out, fix them, send it to the same teacher again and get a perfect grade.

Luckily, nobody noticed it yet and nobody pointed out anything so there's no foul play at all.
 
Level 9
Joined
Oct 14, 2013
Messages
238
What I meant by posting a map along with a wip and nothing else, is that it is better to post images/gifs/code instead of the actual map.

There's no reason for you to get, to be blunt, butthurt, it is just common knowledge that you shouldn't upload it to the spell section, it's like sending your work to your teacher, get your mistakes pointed out, fix them, send it to the same teacher again and get a perfect grade.

Luckily, nobody noticed it yet and nobody pointed out anything so there's no foul play at all.

If you had looked more carefully, I had attached the map to my post, then why would you go and say you should attach it? I guess You didn't know what you were saying and made me do something that I felt is not right and put me in a situation that I hate to be - the foul player. And now you try to stand corrected. Accept your mistake man! You should've shut it, cause there was nothing wrong with my post there. Get over your addiction to post unnecessary comments, please.

Edit
I just noticed that it is going to become like the hell I went through in the Zephyr contest #12. So I withdraw my entry, because arguing over a f**king simple mistake for hundreds of pages is like poison for my nerves.
I'm gone. I've had enough of this shit!
Deleting my entry!!

More Edit
Man! the ratio of the time that I've wasted over this site and the satisfaction I received for it, is almost 100 to 5. I woke up full of energy that finally I finished my work and let's go check if somebody wrote any comments about it. But of all the things that I expected, this shit??? I somehow feel tired.

I had a feeling man! Just look at my first comment in this thread. I somehow knew it!
I recently was working on some 3-player episodic maps. But, if it's what I will get then why bother? (I don't know, maybe because my rep is low)

And maybe looking at this:
There's no reason for you to get, to be blunt, butthurt, it is just common knowledge that you shouldn't upload it to the spell section
I think maybe My common knowledge can't keep up with the quality that apparently some of you have. Makes me wonder Why these threads have a moderator or something to guide people if they misunderstand something?

I mean look at the usefulness and simplicity that this comment has:
Loner-Magixxar, a little tip. Check out the other entries for naming conventions of variables.:) (It's supposed to follow standard submission guidelines.)
Now that's what I call a quality comment.
 
Last edited:
Level 11
Joined
Jul 25, 2014
Messages
490
@Loner-Magixxar,

Why exactly are you bashing me? I would accept my mistake if I had made one in the first place. The only thing that I meant with my first post is exactly what your "good commment" by IcemanBo, says - a tip. I just advised you to attach your code or an image instead of the actual map (and if you still want to do the map WIP, it's better to attach the map rather than linking it to a pastebin) because it is more convenient to check for users.

I'm curious to hear what you call "an unnecessary comment of mine". You're just accusing me of something I haven't done.
 
Level 13
Joined
Jun 20, 2014
Messages
479
Entry Post: Empirean Call of the Damned

Description

Creates a summoning circle which allows the caster to conjure demons from another realm. Acolytes may help the caster during the summoning to reduce the summoning time and summon additional units.
Triggers


  • Call of the Damned Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- --------
      • -------- Main Ability --------
      • Set CD_Ability = Call of the Damned
      • -------- --------
      • -------- Orderstring of the Main ability --------
      • Set CD_AbilityOrder = starfall
      • -------- --------
      • -------- Ability that switches the Main Ability with the Fake Ability --------
      • -------- Note: This is necessary to avoid double casting the ability by the same unit --------
      • Set CD_SwitchAbility = Switch Call of the Damned
      • -------- --------
      • -------- Unit-type of the summoned unit which will appear on the center --------
      • -------- Note: Its usually the strongest unit in the batch --------
      • Set CD_SummonedUnitType[1] = Doom Guard - level 1
      • Set CD_SummonedUnitType[2] = Doom Guard - level 2
      • Set CD_SummonedUnitType[3] = Doom Guard - level 3
      • Set CD_SummonedUnitType[4] = Doom Guard - level 4
      • -------- --------
      • -------- The number of summoned units which will appear in the center of the circle --------
      • Set CD_SummonedUnitCount[1] = 1
      • Set CD_SummonedUnitCount[2] = 1
      • Set CD_SummonedUnitCount[3] = 1
      • Set CD_SummonedUnitCount[4] = 1
      • -------- --------
      • -------- Unit-type of the bonus unit that comes with the summoned unit once the summoning is complete --------
      • Set CD_BonusUnitType[1] = Fel Beast - level 1
      • Set CD_BonusUnitType[2] = Fel Beast - level 2
      • Set CD_BonusUnitType[3] = Fel Beast - level 3
      • Set CD_BonusUnitType[4] = Fel Beast - level 4
      • -------- --------
      • -------- The number of additional units that are summoned with each apprentice --------
      • -------- Note: When i mentioned apprentice im referring to acolytes --------
      • Set CD_BonusUnitCount[1] = 1
      • Set CD_BonusUnitCount[2] = 1
      • Set CD_BonusUnitCount[3] = 1
      • Set CD_BonusUnitCount[4] = 1
      • -------- --------
      • -------- How long will the summoned units last in our realm --------
      • -------- Note: If you want the summoned units to be permanent then make the value equal to zero (0) --------
      • Set CD_SummonedUnitDuration[1] = 120.00
      • Set CD_SummonedUnitDuration[2] = 120.00
      • Set CD_SummonedUnitDuration[3] = 120.00
      • Set CD_SummonedUnitDuration[4] = 120.00
      • -------- --------
      • -------- How long will it take to finish summoning --------
      • -------- Note: It should be less than the casting time of the main ability --------
      • Set CD_CastingTime[1] = 30.00
      • Set CD_CastingTime[2] = 30.00
      • Set CD_CastingTime[3] = 30.00
      • Set CD_CastingTime[4] = 30.00
      • -------- --------
      • -------- How many apprentice are allowed to help the caster --------
      • Set CD_ApprenticeUnitAllowed[1] = 2
      • Set CD_ApprenticeUnitAllowed[2] = 3
      • Set CD_ApprenticeUnitAllowed[3] = 4
      • Set CD_ApprenticeUnitAllowed[4] = 5
      • -------- --------
      • -------- The amount of casting time reduced when an apprentice helps the caster --------
      • Set CD_CastingTimeReduction[1] = 2.00
      • Set CD_CastingTimeReduction[2] = 2.00
      • Set CD_CastingTimeReduction[3] = 2.00
      • Set CD_CastingTimeReduction[4] = 2.00
      • -------- --------
      • -------- How large is the detection radius of each formation circle dedicated for the apprentice --------
      • Set CD_ApprenticeAoE[1] = 100.00
      • Set CD_ApprenticeAoE[2] = 100.00
      • Set CD_ApprenticeAoE[3] = 100.00
      • Set CD_ApprenticeAoE[4] = 100.00
      • -------- --------
      • -------- The actual size of the summoning circle --------
      • -------- Note: this is not the actual model circle but it determines how far are the apprentices from the center --------
      • Set CD_SummoningCircleAoE[1] = 500.00
      • Set CD_SummoningCircleAoE[2] = 500.00
      • Set CD_SummoningCircleAoE[3] = 500.00
      • Set CD_SummoningCircleAoE[4] = 500.00
      • -------- --------
      • -------- How far from the center of the summoning circle will the bonus units appear --------
      • Set CD_BonusUnitOffset[1] = 250.00
      • Set CD_BonusUnitOffset[2] = 250.00
      • Set CD_BonusUnitOffset[3] = 250.00
      • Set CD_BonusUnitOffset[4] = 250.00
      • -------- --------
      • -------- How large is the summoning circle model --------
      • -------- Note: the value comes in %. meaning 200 = 2x the size of the actual model --------
      • Set CD_SummoningCircleSize[1] = 300.00
      • Set CD_SummoningCircleSize[2] = 300.00
      • Set CD_SummoningCircleSize[3] = 300.00
      • Set CD_SummoningCircleSize[4] = 300.00
      • -------- --------
      • -------- Model used as the summoning circle --------
      • Set CD_SummoningCircleSFX = SharedModels\UBirth.mdl
      • -------- --------
      • -------- Transparency of the summoning circle --------
      • -------- Note:for this model i need a transparency to remove the creepy claw in it --------
      • Set CD_SummoningCircleTransparency = 1.00
      • -------- --------
      • -------- Model used once the summoning is complete/cancelled --------
      • Set CD_CleanSFX = Objects\Spawnmodels\Undead\UDeathMedium\UDeath.mdl
      • -------- --------
      • -------- The amount of time before the summoning circle vanishes when the summoning is complete/cancelled --------
      • -------- Note: the value is 2.10 to fit the spell visuals --------
      • Set CD_SummoningCircleDelay = 2.10
      • -------- --------
      • -------- Special effects found at the center of the summoning circle while summoning for added visuals --------
      • Set CD_SummoningGroundSFX1 = Abilities\Spells\Undead\Unsummon\UnsummonTarget.mdl
      • Set CD_SummoningGroundSFX2 = Abilities\Spells\Undead\Darksummoning\DarkSummonTarget.mdl
      • -------- --------
      • -------- The model used as indicator on where the caster stands and where the acolytes must stand --------
      • Set CD_FormationSFX = Abilities\Spells\Undead\Darksummoning\DarkSummonTarget.mdl
      • -------- --------
      • -------- The model used to indicate that the acolytes are helping the caster summon --------
      • Set CD_NotifySFX = Abilities\Spells\Items\TomeOfRetraining\TomeOfRetrainingCaster.mdl
      • -------- --------
      • -------- The model used as an indicator that the summoning has been successful --------
      • -------- Note: It appears at the center of the circle --------
      • Set CD_SpawnSFX = Doodads\Cinematic\ShimmeringPortal\ShimmeringPortal.mdl
      • -------- --------
      • -------- The animation of the substitute units --------
      • -------- Note: Substitute unit looks like the helping unit the only difference is they cannot be selected --------
      • -------- and are only there for the visuals --------
      • Set CD_SubstituteAnimation = work
      • -------- --------
      • -------- The interval on which the animation of the substitute units are called while summoning --------
      • -------- Note: Substitute unit looks like the helping unit the only difference is they cannot be selected --------
      • -------- and are only there for the visuals --------
      • Set CD_SubstituteInterval = 2.26
      • -------- --------
      • -------- The model used for the flying souls during the summoning ritual --------
      • Set CD_SoulSFX = Abilities\Weapons\ZigguratMissile\ZigguratMissile.mdl
      • -------- --------
      • -------- The maximum height of the souls --------
      • Set CD_SoulMaxHeight = 500.00
      • -------- --------
      • -------- The rotation of the souls --------
      • -------- Note: True of clockwise and False if counter-clockwise --------
      • Set CD_IsClockwise = True
      • -------- --------
      • -------- The speed of the rotation of the souls around the center of the circle --------
      • Set CD_SoulTurnRate = 3.00
      • -------- --------
      • -------- The amount of time before the soul reaches the center from the outside of the circle --------
      • Set CD_SoulDelay = 1.00
      • -------- --------
      • -------- The rate on which the souls are ascending or descending --------
      • Set CD_SoulHeightSpeed = 5.00
      • -------- --------
      • -------- The Unit-Type of the unit that can help with the summoning --------
      • Set CD_ApprenticeUnitType = Acolyte
      • -------- --------
      • -------- The Unit-Type of the substitute unit --------
      • -------- Note: Substitute unit looks like the helping unit the only difference is they cannot be selected --------
      • -------- and are only there for the visuals --------
      • Set CD_SubstituteUnitType = Apprentice
      • -------- --------
      • -------- The Unit-Type of the multipurpose dummy --------
      • Set CD_DummyUnitType = Dummy
      • -------- --------
      • -------- NECESSARRY ACTIONS --------
      • -------- Note: Do NOT tamper unless you know what you are doing --------
      • -------- --------
      • -------- Disable the switch ability to all players --------
      • For each (Integer CD_TempInt) from 1 to 12, do (Actions)
        • Loop - Actions
          • Player - Disable Switch Call of the Damned for (Player(CD_TempInt))
      • -------- --------
      • -------- Preload --------
      • Set CD_Point1 = (Random point in (Playable map area))
      • Unit - Create 1 CD_DummyUnitType for Neutral Passive at CD_Point1 facing Default building facing degrees
      • Set CD_Harvester = (Last created unit)
      • -------- --------
      • Unit - Add CD_Ability to CD_Harvester
      • Unit - Remove CD_Ability from CD_Harvester
      • -------- --------
      • Unit - Add Harvest (Gold and Lumber) to CD_Harvester
      • -------- --------
      • Custom script: call RemoveLocation(udg_CD_Point1)



  • Call of the Damned Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to CD_Ability
    • Actions
      • -------- --------
      • -------- Set current index --------
      • Set CD_Index1 = (CD_Index1 + 1)
      • -------- --------
      • -------- Store necessary values --------
      • Set CD_CasterUnit[CD_Index1] = (Triggering unit)
      • Set CD_Player[CD_Index1] = (Triggering player)
      • Set CD_Level[CD_Index1] = (Level of CD_Ability for CD_CasterUnit[CD_Index1])
      • -------- --------
      • -------- Set necessary points --------
      • Set CD_Point1 = (Position of CD_CasterUnit[CD_Index1])
      • Set CD_Point2 = (CD_Point1 offset by CD_SummoningCircleAoE[CD_Level[CD_Index1]] towards (Facing of CD_CasterUnit[CD_Index1]) degrees)
      • -------- --------
      • -------- clearing the path --------
      • Destructible - Pick every destructible within (CD_SummoningCircleAoE[CD_Level[CD_Index1]] + CD_ApprenticeAoE[CD_Level[CD_Index1]]) of CD_Point2 and do (Actions)
        • Loop - Actions
          • Set CD_Destructible = (Picked destructible)
          • Unit - Order CD_Harvester to Harvest CD_Destructible
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Current order of CD_Harvester) Equal to (Order(harvest))
            • Then - Actions
              • Destructible - Kill CD_Destructible
              • Unit - Order CD_Harvester to Stop
            • Else - Actions
      • -------- --------
      • -------- Calculate angles 360 (full circle) divided by the number of allowed helper + 1 --------
      • -------- to create the perfect gap between the caster and the summoners --------
      • Set CD_TempAngle = (Angle from CD_Point2 to CD_Point1)
      • Set CD_AngleAdjustment = (360.00 / ((Real(CD_ApprenticeUnitAllowed[CD_Level[CD_Index1]])) + 1.00))
      • -------- --------
      • -------- Create the dummy for the summoning circle on where the other models will be attached --------
      • Unit - Create 1 CD_DummyUnitType for Neutral Passive at CD_Point2 facing CD_TempAngle degrees
      • Set CD_SummoningCircleUnit[CD_Index1] = (Last created unit)
      • -------- --------
      • -------- Change the size and transparency of the summoning circle --------
      • Animation - Change CD_SummoningCircleUnit[CD_Index1]'s size to (CD_SummoningCircleSize[CD_Level[CD_Index1]]%, 100.00%, 100.00%) of its original size
      • Animation - Change CD_SummoningCircleUnit[CD_Index1]'s vertex coloring to (100.00%, 100.00%, 100.00%) with CD_SummoningCircleTransparency% transparency
      • -------- --------
      • -------- Apply the summoning circle model --------
      • Special Effect - Create a special effect attached to the origin of CD_SummoningCircleUnit[CD_Index1] using CD_SummoningCircleSFX
      • Set CD_SummoningCircleEffect[CD_Index1] = (Last created special effect)
      • -------- --------
      • -------- Apply the models found at the center of the summoning circle --------
      • Special Effect - Create a special effect at CD_Point2 using CD_SummoningGroundSFX1
      • Set CD_SummoningGroundEffect1[CD_Index1] = (Last created special effect)
      • Special Effect - Create a special effect at CD_Point2 using CD_SummoningGroundSFX2
      • Set CD_SummoningGroundEffect2[CD_Index1] = (Last created special effect)
      • -------- --------
      • -------- LOGIC --------
      • -------- add the anti double cast --------
      • Unit - Add Switch Call of the Damned to CD_CasterUnit[CD_Index1]
      • -------- --------
      • -------- time left before the summoning is complete --------
      • Set CD_CastingTimeLeft[CD_Index1] = CD_CastingTime[CD_Level[CD_Index1]]
      • -------- --------
      • -------- flag to indicate that the summoning is not done yet --------
      • Set CD_IsComplete[CD_Index1] = False
      • -------- --------
      • -------- flag to indicate that the slot is for the caster --------
      • Set CD_DefaultState = True
      • -------- --------
      • -------- dispose unneeded point --------
      • Custom script: call RemoveLocation(udg_CD_Point1)
      • -------- --------
      • -------- FORMATION CIRCLE --------
      • -------- loops to number of allowed helpers + the caster --------
      • For each (Integer CD_Looper2) from 1 to (CD_ApprenticeUnitAllowed[CD_Level[CD_Index1]] + 1), do (Actions)
        • Loop - Actions
          • -------- --------
          • -------- set current index --------
          • Set CD_Index2 = (CD_Index2 + 1)
          • -------- --------
          • -------- make a reference to the caster --------
          • Set CD_CasterId[CD_Index2] = CD_CasterUnit[CD_Index1]
          • -------- --------
          • -------- recycle the point variable and make a point towards the angle that we calculated earlier --------
          • Set CD_Point1 = (CD_Point2 offset by CD_SummoningCircleAoE[CD_Level[CD_Index1]] towards CD_TempAngle degrees)
          • -------- --------
          • -------- recycle the point variable and make a point towards the angle that we calculated earlier --------
          • -------- creates an indicator where helpers must stand --------
          • Unit - Create 1 CD_DummyUnitType for Neutral Passive at CD_Point1 facing CD_Angle[CD_Index2] degrees
          • Set CD_FormationUnit[CD_Index2] = (Last created unit)
          • -------- --------
          • -------- applies the model for the indicator --------
          • Special Effect - Create a special effect attached to the origin of CD_FormationUnit[CD_Index2] using CD_FormationSFX
          • Set CD_FormationEffect[CD_Index2] = (Last created special effect)
          • -------- --------
          • -------- indicates whether the spot has been occupied --------
          • -------- the default state is true for the caster so that no helper may occupy it --------
          • Set CD_IsOccupied[CD_Index2] = CD_DefaultState
          • -------- --------
          • -------- defaultstate is true if its the main caster --------
          • -------- it is also true if the spot has been occupied by a helper --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CD_DefaultState Equal to True
            • Then - Actions
              • -------- --------
              • -------- animation time default --------
              • Set CD_SubstituteTimeLeft[CD_Index2] = 0.00
              • -------- --------
              • -------- all about the soul --------
              • Set CD_SoulAngle[CD_Index2] = CD_TempAngle
              • Set CD_SoulDistance[CD_Index2] = CD_SummoningCircleAoE[CD_Level[CD_Index1]]
              • Set CD_SoulSpeed[CD_Index2] = (CD_SummoningCircleAoE[CD_Level[CD_Index1]] / (CD_SoulDelay / 0.03))
              • Set CD_SoulCurrentHeight[CD_Index2] = 0.00
              • -------- --------
              • Set CD_IsInward[CD_Index2] = True
              • Set CD_IsUpward[CD_Index2] = True
              • -------- --------
              • Unit - Create 1 CD_DummyUnitType for Neutral Passive at CD_Point1 facing CD_Angle[CD_Index2] degrees
              • Set CD_SoulUnit[CD_Index2] = (Last created unit)
              • -------- --------
              • Unit - Add Storm Crow Form to CD_SoulUnit[CD_Index2]
              • Unit - Remove Storm Crow Form from CD_SoulUnit[CD_Index2]
              • -------- --------
              • Special Effect - Create a special effect attached to the origin of CD_SoulUnit[CD_Index2] using CD_SoulSFX
              • Set CD_SoulEffect[CD_Index2] = (Last created special effect)
              • -------- --------
              • -------- change the value of default state to create vacant spots --------
              • Set CD_DefaultState = False
            • Else - Actions
          • -------- --------
          • -------- clean up --------
          • Custom script: call RemoveLocation(udg_CD_Point1)
          • -------- --------
          • -------- adjust and store angles for later use --------
          • Set CD_Angle[CD_Index2] = CD_TempAngle
          • Set CD_TempAngle = (CD_TempAngle + CD_AngleAdjustment)
          • -------- --------
      • -------- --------
      • -------- dispose point --------
      • Custom script: call RemoveLocation(udg_CD_Point2)
      • -------- --------
      • -------- start summoning --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CD_Index1 Equal to 1
        • Then - Actions
          • Trigger - Turn on Call of the Damned Effect <gen>
        • Else - Actions



  • Call of the Damned Effect
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- --------
      • -------- enumerates through all the casters --------
      • For each (Integer CD_Looper1) from 1 to CD_Index1, do (Actions)
        • Loop - Actions
          • -------- --------
          • -------- checks if the caster is still casting --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Current order of CD_CasterUnit[CD_Looper1]) Equal to (Order(CD_AbilityOrder))
            • Then - Actions
              • -------- --------
              • -------- checks if the casting is complete --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CD_CastingTimeLeft[CD_Looper1] Greater than 0.00
                • Then - Actions
                  • Set CD_CastingTimeLeft[CD_Looper1] = (CD_CastingTimeLeft[CD_Looper1] - 0.03)
                • Else - Actions
                  • Set CD_IsComplete[CD_Looper1] = True
                  • Unit - Order CD_CasterUnit[CD_Looper1] to Stop
              • -------- --------
              • -------- enumerates all the available spots and souls --------
              • For each (Integer CD_Looper2) from 1 to CD_Index2, do (Actions)
                • Loop - Actions
                  • -------- --------
                  • -------- checks if its for the right caster --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • CD_CasterId[CD_Looper2] Equal to CD_CasterUnit[CD_Looper1]
                    • Then - Actions
                      • -------- --------
                      • -------- checks if the spot is already occupied --------
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • CD_IsOccupied[CD_Looper2] Equal to True
                        • Then - Actions
                          • -------- --------
                          • -------- checks if its time to animate --------
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • CD_SubstituteTimeLeft[CD_Looper2] Greater than 0.00
                            • Then - Actions
                              • Set CD_SubstituteTimeLeft[CD_Looper2] = (CD_SubstituteTimeLeft[CD_Looper2] - 0.03)
                            • Else - Actions
                              • -------- --------
                              • -------- animate substitute unit and create notify special effect --------
                              • Set CD_Point1 = (Position of CD_FormationUnit[CD_Looper2])
                              • -------- --------
                              • Set CD_SubstituteTimeLeft[CD_Looper2] = CD_SubstituteInterval
                              • -------- --------
                              • Animation - Play CD_SubstituteUnit[CD_Looper2]'s CD_SubstituteAnimation animation
                              • -------- --------
                              • Special Effect - Create a special effect at CD_Point1 using CD_NotifySFX
                              • Special Effect - Destroy (Last created special effect)
                              • -------- --------
                              • Custom script: call RemoveLocation(udg_CD_Point1)
                          • -------- --------
                          • -------- SOUL ANIMATION --------
                          • -------- --------
                          • -------- soul rotation --------
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • CD_IsClockwise Equal to True
                            • Then - Actions
                              • Set CD_SoulAngle[CD_Looper2] = (CD_SoulAngle[CD_Looper2] - CD_SoulTurnRate)
                            • Else - Actions
                              • Set CD_SoulAngle[CD_Looper2] = (CD_SoulAngle[CD_Looper2] + CD_SoulTurnRate)
                          • -------- --------
                          • -------- soul distance --------
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • CD_IsInward[CD_Looper2] Equal to True
                            • Then - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • CD_SoulDistance[CD_Looper2] Greater than 0.00
                                • Then - Actions
                                  • Set CD_SoulDistance[CD_Looper2] = (CD_SoulDistance[CD_Looper2] - CD_SoulSpeed[CD_Looper2])
                                • Else - Actions
                                  • Set CD_IsInward[CD_Looper2] = False
                            • Else - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • CD_SoulDistance[CD_Looper2] Less than CD_SummoningCircleAoE[CD_Level[CD_Looper1]]
                                • Then - Actions
                                  • Set CD_SoulDistance[CD_Looper2] = (CD_SoulDistance[CD_Looper2] + CD_SoulSpeed[CD_Looper2])
                                • Else - Actions
                                  • Set CD_IsInward[CD_Looper2] = True
                          • -------- --------
                          • -------- soul height --------
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • CD_IsUpward[CD_Looper2] Equal to True
                            • Then - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • CD_SoulCurrentHeight[CD_Looper2] Less than CD_SoulMaxHeight
                                • Then - Actions
                                  • Set CD_SoulCurrentHeight[CD_Looper2] = (CD_SoulCurrentHeight[CD_Looper2] + CD_SoulHeightSpeed)
                                • Else - Actions
                                  • Set CD_IsUpward[CD_Looper2] = False
                            • Else - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • CD_SoulCurrentHeight[CD_Looper2] Greater than 0.00
                                • Then - Actions
                                  • Set CD_SoulCurrentHeight[CD_Looper2] = (CD_SoulCurrentHeight[CD_Looper2] - CD_SoulHeightSpeed)
                                • Else - Actions
                                  • Set CD_IsUpward[CD_Looper2] = True
                          • -------- --------
                          • -------- move soul to correct position --------
                          • Set CD_Point1 = (Position of CD_SummoningCircleUnit[CD_Looper1])
                          • Set CD_Point2 = (CD_Point1 offset by CD_SoulDistance[CD_Looper2] towards CD_SoulAngle[CD_Looper2] degrees)
                          • -------- --------
                          • Animation - Change CD_SoulUnit[CD_Looper2] flying height to CD_SoulCurrentHeight[CD_Looper2] at 0.00
                          • -------- --------
                          • Custom script: call SetUnitY(udg_CD_SoulUnit[udg_CD_Looper2], GetLocationY(udg_CD_Point2))
                          • Custom script: call SetUnitX(udg_CD_SoulUnit[udg_CD_Looper2], GetLocationX(udg_CD_Point2))
                          • -------- --------
                          • Custom script: call RemoveLocation(udg_CD_Point1)
                          • Custom script: call RemoveLocation(udg_CD_Point2)
                        • Else - Actions
                          • -------- --------
                          • -------- checks if nearby helper unit-type is nearby --------
                          • Set CD_Point1 = (Position of CD_FormationUnit[CD_Looper2])
                          • Set CD_TempGroup = (Units within CD_ApprenticeAoE[CD_Level[CD_Looper1]] of CD_Point1)
                          • -------- --------
                          • Unit Group - Pick every unit in CD_TempGroup and do (Actions)
                            • Loop - Actions
                              • -------- --------
                              • Set CD_TempUnit = (Picked unit)
                              • -------- --------
                              • -------- checks if nearby units are valid helpers --------
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (Unit-type of CD_TempUnit) Equal to CD_ApprenticeUnitType
                                  • (CD_TempUnit is alive) Equal to True
                                  • (Owner of CD_TempUnit) Equal to CD_Player[CD_Looper1]
                                • Then - Actions
                                  • -------- --------
                                  • -------- necessarry check if the spot has been occupied in case there are more than one nearby helper --------
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • CD_IsOccupied[CD_Looper2] Equal to False
                                    • Then - Actions
                                      • -------- --------
                                      • -------- spot is not occupied --------
                                      • Set CD_IsOccupied[CD_Looper2] = True
                                      • -------- --------
                                      • -------- hide the helper unit --------
                                      • Set CD_HiddenUnit[CD_Looper2] = CD_TempUnit
                                      • Unit - Make CD_HiddenUnit[CD_Looper2] Invulnerable
                                      • Unit - Hide CD_HiddenUnit[CD_Looper2]
                                      • -------- --------
                                      • -------- souls --------
                                      • Set CD_SoulAngle[CD_Looper2] = CD_Angle[CD_Looper2]
                                      • Set CD_SoulDistance[CD_Looper2] = CD_SummoningCircleAoE[CD_Level[CD_Looper1]]
                                      • Set CD_SoulSpeed[CD_Looper2] = (CD_SummoningCircleAoE[CD_Level[CD_Looper1]] / (CD_SoulDelay / 0.03))
                                      • Set CD_SoulCurrentHeight[CD_Looper2] = 0.00
                                      • -------- --------
                                      • Set CD_IsInward[CD_Looper2] = True
                                      • Set CD_IsUpward[CD_Looper2] = True
                                      • -------- --------
                                      • Unit - Create 1 CD_DummyUnitType for Neutral Passive at CD_Point1 facing CD_Angle[CD_Looper2] degrees
                                      • Set CD_SoulUnit[CD_Looper2] = (Last created unit)
                                      • -------- --------
                                      • Unit - Add Storm Crow Form to CD_SoulUnit[CD_Looper2]
                                      • Unit - Remove Storm Crow Form from CD_SoulUnit[CD_Looper2]
                                      • -------- --------
                                      • Special Effect - Create a special effect attached to the origin of CD_SoulUnit[CD_Looper2] using CD_SoulSFX
                                      • Set CD_SoulEffect[CD_Looper2] = (Last created special effect)
                                      • -------- --------
                                      • Unit - Create 1 CD_SubstituteUnitType for Neutral Passive at CD_Point1 facing (CD_Angle[CD_Looper2] + 180.00) degrees
                                      • Set CD_SubstituteUnit[CD_Looper2] = (Last created unit)
                                      • -------- --------
                                      • -------- animation time left --------
                                      • Set CD_SubstituteTimeLeft[CD_Looper2] = 0.00
                                      • -------- --------
                                      • -------- casting time reduction --------
                                      • Set CD_CastingTimeLeft[CD_Looper1] = (CD_CastingTimeLeft[CD_Looper1] - CD_CastingTimeReduction[CD_Level[CD_Looper1]])
                                    • Else - Actions
                                • Else - Actions
                                  • -------- --------
                                  • Set CD_TempUnit = No unit
                          • -------- --------
                          • Custom script: call DestroyGroup(udg_CD_TempGroup)
                          • -------- --------
                          • Custom script: call RemoveLocation(udg_CD_Point1)
                    • Else - Actions
            • Else - Actions
              • -------- --------
              • -------- checks if the summoning is complete --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CD_IsComplete[CD_Looper1] Equal to True
                • Then - Actions
                  • -------- --------
                  • Set CD_Point1 = (Position of CD_SummoningCircleUnit[CD_Looper1])
                  • -------- --------
                  • Special Effect - Create a special effect at CD_Point1 using CD_SpawnSFX
                  • Special Effect - Destroy (Last created special effect)
                  • -------- --------
                  • -------- create summoned units --------
                  • -------- it will loop as many summoned units are needed --------
                  • For each (Integer CD_TempInt) from 1 to CD_SummonedUnitCount[CD_Level[CD_Looper1]], do (Actions)
                    • Loop - Actions
                      • -------- --------
                      • Unit - Create 1 CD_SummonedUnitType[CD_Level[CD_Looper1]] for CD_Player[CD_Looper1] at CD_Point1 facing (Facing of CD_SummoningCircleUnit[CD_Looper1]) degrees
                      • Set CD_TempUnit = (Last created unit)
                      • -------- --------
                      • Unit - Add a CD_SummonedUnitDuration[CD_Level[CD_Looper1]] second Generic expiration timer to CD_TempUnit
                      • Unit - Add classification of Summoned to CD_TempUnit
                  • -------- --------
                  • For each (Integer CD_Looper2) from 1 to CD_Index2, do (Actions)
                    • Loop - Actions
                      • -------- --------
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • CD_CasterId[CD_Looper2] Equal to CD_CasterUnit[CD_Looper1]
                          • CD_IsOccupied[CD_Looper2] Equal to True
                        • Then - Actions
                          • -------- --------
                          • Set CD_Point2 = (CD_Point1 offset by CD_BonusUnitOffset[CD_Level[CD_Looper1]] towards CD_Angle[CD_Looper2] degrees)
                          • -------- create summoned units --------
                          • -------- it will loop as many summoned units are needed --------
                          • For each (Integer CD_TempInt) from 1 to CD_BonusUnitCount[CD_Level[CD_Looper1]], do (Actions)
                            • Loop - Actions
                              • -------- --------
                              • Unit - Create 1 CD_BonusUnitType[CD_Level[CD_Looper1]] for CD_Player[CD_Looper1] at CD_Point2 facing CD_Angle[CD_Looper2] degrees
                              • Set CD_TempUnit = (Last created unit)
                              • -------- --------
                              • Unit - Add a CD_SummonedUnitDuration[CD_Level[CD_Looper1]] second Generic expiration timer to CD_TempUnit
                              • Unit - Add classification of Summoned to CD_TempUnit
                          • -------- --------
                          • Custom script: call RemoveLocation(udg_CD_Point2)
                        • Else - Actions
                  • -------- --------
                  • Custom script: call RemoveLocation(udg_CD_Point1)
                • Else - Actions
              • -------- --------
              • -------- DEINDEXING --------
              • For each (Integer CD_Looper2) from 1 to CD_Index2, do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • CD_CasterId[CD_Looper2] Equal to CD_CasterUnit[CD_Looper1]
                    • Then - Actions
                      • -------- --------
                      • Special Effect - Destroy CD_SoulEffect[CD_Looper2]
                      • Special Effect - Destroy CD_FormationEffect[CD_Looper2]
                      • -------- --------
                      • Unit - Add a 0.01 second Generic expiration timer to CD_FormationUnit[CD_Looper2]
                      • Unit - Add a 0.01 second Generic expiration timer to CD_SubstituteUnit[CD_Looper2]
                      • Unit - Add a 0.01 second Generic expiration timer to CD_SoulUnit[CD_Looper2]
                      • -------- --------
                      • Unit - Unhide CD_HiddenUnit[CD_Looper2]
                      • Unit - Make CD_HiddenUnit[CD_Looper2] Vulnerable
                      • -------- --------
                      • Set CD_CasterId[CD_Looper2] = CD_CasterId[CD_Index2]
                      • -------- --------
                      • Set CD_HiddenUnit[CD_Looper2] = CD_HiddenUnit[CD_Index2]
                      • -------- --------
                      • Set CD_Angle[CD_Looper2] = CD_Angle[CD_Index2]
                      • -------- --------
                      • Set CD_FormationUnit[CD_Looper2] = CD_FormationUnit[CD_Index2]
                      • Set CD_FormationEffect[CD_Looper2] = CD_FormationEffect[CD_Index2]
                      • -------- --------
                      • Set CD_IsOccupied[CD_Looper2] = CD_IsOccupied[CD_Index2]
                      • -------- --------
                      • Set CD_SoulUnit[CD_Looper2] = CD_SoulUnit[CD_Index2]
                      • -------- --------
                      • Set CD_IsUpward[CD_Looper2] = CD_IsUpward[CD_Index2]
                      • Set CD_IsInward[CD_Looper2] = CD_IsInward[CD_Index2]
                      • -------- --------
                      • Set CD_SoulAngle[CD_Looper2] = CD_SoulAngle[CD_Index2]
                      • Set CD_SoulCurrentHeight[CD_Looper2] = CD_SoulCurrentHeight[CD_Index2]
                      • Set CD_SoulDistance[CD_Looper2] = CD_SoulDistance[CD_Index2]
                      • Set CD_SoulSpeed[CD_Looper2] = CD_SoulSpeed[CD_Index2]
                      • -------- --------
                      • Set CD_SubstituteTimeLeft[CD_Looper2] = CD_SubstituteTimeLeft[CD_Index2]
                      • Set CD_SubstituteUnit[CD_Looper2] = CD_SubstituteUnit[CD_Index2]
                      • -------- --------
                      • Set CD_Looper2 = (CD_Looper2 - 1)
                      • Set CD_Index2 = (CD_Index2 - 1)
                    • Else - Actions
              • -------- --------
              • Special Effect - Create a special effect attached to the origin of CD_SummoningCircleUnit[CD_Looper1] using CD_CleanSFX
              • Special Effect - Destroy (Last created special effect)
              • -------- --------
              • Special Effect - Destroy CD_SummoningCircleEffect[CD_Looper1]
              • Special Effect - Destroy CD_SummoningGroundEffect1[CD_Looper1]
              • Special Effect - Destroy CD_SummoningGroundEffect2[CD_Looper1]
              • -------- --------
              • Unit - Add a CD_SummoningCircleDelay second Generic expiration timer to CD_SummoningCircleUnit[CD_Looper1]
              • -------- --------
              • Unit - Remove CD_SwitchAbility from CD_CasterUnit[CD_Looper1]
              • -------- --------
              • Set CD_CasterUnit[CD_Looper1] = CD_CasterUnit[CD_Index1]
              • Set CD_Level[CD_Looper1] = CD_Level[CD_Index1]
              • Set CD_Player[CD_Looper1] = CD_Player[CD_Index1]
              • -------- --------
              • Set CD_CastingTimeLeft[CD_Looper1] = CD_CastingTimeLeft[CD_Index1]
              • -------- --------
              • Set CD_SummoningCircleUnit[CD_Looper1] = CD_SummoningCircleUnit[CD_Index1]
              • Set CD_SummoningCircleEffect[CD_Looper1] = CD_SummoningCircleEffect[CD_Index1]
              • Set CD_SummoningGroundEffect1[CD_Looper1] = CD_SummoningGroundEffect1[CD_Index1]
              • Set CD_SummoningGroundEffect2[CD_Looper1] = CD_SummoningGroundEffect2[CD_Index1]
              • -------- --------
              • Set CD_Looper1 = (CD_Looper1 - 1)
              • Set CD_Index1 = (CD_Index1 - 1)
              • -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CD_Index1 Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions

Tooltip

Summoning


attachment.php


Level 1

Level 2

Level 3

Level 4

Summoned


attachment.php


attachment.php


attachment.php


attachment.php


attachment.php




Credits

Credits to Vexorian for his dummy.mdx
 

Attachments

  • Empirean Call of the Damned.w3x
    67 KB · Views: 67
  • Image1.png
    Image1.png
    614.2 KB · Views: 403
  • Image2.png
    Image2.png
    777.4 KB · Views: 394
  • Image3.png
    Image3.png
    61.3 KB · Views: 406
  • Image4.png
    Image4.png
    652.4 KB · Views: 386
  • Image5.png
    Image5.png
    626.6 KB · Views: 387
  • Image6.png
    Image6.png
    651.3 KB · Views: 422
Last edited:
Just wanted to notify you guys that I'm going to be away from my PC for a few days so I won't be able to update the table (will update it with all the entries/WIPs I notice) if I've missed any (Almia's on the previous page and xxdingo93xx's link on this page and Empirean's entry post please notify me through either PM or VM so I can quickly add all the ones I'll be missing /am presently missing onto the table when I get back
 
May I present to you...my abonimation




attachment.php

Details

GIFs

Video


Features

  • 2293 lines of a(bomination)wesomeness (comments included)
  • 1/4 of the said lines are configurables (estimated lol)
  • Great visuals (self-proclaimed)
  • Can go from simple, light visuals to complex, heavy visuals
  • can cause Arachnophobia (needs mythbusting)
  • Eyecandy spell
Things I could have done

Things I could have done but some limits affects it:
  • Timed life indicator
  • Abilities for the devourer(that represents the behaviors)
  • Much better tooltip(current tooltip hits the max character limit)


Spawn

Aura

Shockwave

Swarm

Death

154505d1462513273-zephyr-contest-14-unique-summoning-hell-noo.gif
aura.jpg
shockwave.jpg
swarm.jpg
death.jpg


(Sorry for the video quality)



Disclaimer : no spiders were harmed in the making of the spell
 

Attachments

  • tooltip.png
    tooltip.png
    296.7 KB · Views: 451
  • Almia - Summon Devourer.w3x
    98.6 KB · Views: 64
Last edited by a moderator:
Level 4
Joined
Apr 28, 2016
Messages
33
My third WIP, still on work for bug spell. I use some of import buffs, adding buff when dies and on summoning too.

3oEjI4yjP2EI6bjnKE.gif


There are many cool WIP in this contest, i'm so envy because i still can't do like them :(
 
Level 20
Joined
Apr 14, 2012
Messages
2,901
Guys I'm dropping out; my spell making skills dropped out on me. Can't make the mother and child circles spin around each other. Sad.

Gl hf to the other contestants ^^
I'll be using the results of this contest to further my understanding of spell-making. *Evil laugh fades proportionally to increasing distance between me and this post*
 
Level 17
Joined
Sep 8, 2007
Messages
994
@dingo
Not at all, but since we are talking about standards, spell should have 3 or more levels

Hummmmm okay, well let's see how it goes then.
I feel like most of the contestants spawn a whole army of creeps with their spells, btw. Could make it imbalanced. This is also another point I was thinking by writing wc3 standards, because 90-95% of the wc3 standard heroes can't summon multiple creeps with one spell (except for a few, like keeper of grove's force of nature or archimonde's dark portal).
And considering that, I think once we get to the poll, voting users probably will value those mass-summon spells more.
 
Status
Not open for further replies.
Top