• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Zephyr Contest #10 - What lies on the other side

Status
Not open for further replies.
Level 30
Joined
Nov 29, 2012
Messages
6,637
My idea is: Summons a portal at the Center of the map and after 10 seconds random and different Demonic units will spawn all around the map and at the end of the spell, it will summon a giant Demon at the location of the portal..... Hope I can do this....

Added more ideas to continue and make it somehow good: When the Giant Demon is summoned, for 5 seconds he will be given an Passive Immolation Spell to signify the arrival of the destruction. Dealing damage to nearby enemies. After the 5 seconds duration, Immolation will disappear also!
 
Last edited:
me join :D
attachment.php
 

Attachments

  • wip1.jpg
    wip1.jpg
    67.2 KB · Views: 153
Level 30
Joined
Nov 29, 2012
Messages
6,637
Here's my wip, but it's kind of weak compared to the others'...

2013-05-01%2017_51_53-Warcraft%20III.jpg



I wanted to post the triggers, but I just couldn't put in the trigger tag, or you could say that I was a little embarrassed for my coding.

(Thanks to defskull for his Lightning System)

From the looks of it, its quite nice. I like that lightning.:thumbs_up:

me join :D
attachment.php

Really, just a portal? Try showing some more detail into your WiP even it is just a WiP. But please avoid taking my comment as an offense to you.
 
I was playing around with my physics and decided I have a better idea than I had before (imo) I may or may not keep pulling the units, but it's primarily going to be a summon spell (albeit summoning projectiles because they're funner than units) We'll see when I'm done playing around with my configuration, but enjoy the teaser WIP I have for what I'm currently doing (can you guess?)

Edit: Now we're getting places (new WIP)
 

Attachments

  • TinyWIP3.png
    TinyWIP3.png
    301.2 KB · Views: 98
  • TinyWIP4.png
    TinyWIP4.png
    240.8 KB · Views: 119
Last edited:
I have almost completed my entry, all that's left to do is instance recycling and then making the tooltip/description and adding a readme (though the code is already commented, almost completely)

Here's some screenshots fo the (basically final) product, I made whether or not you want units effected by the gravity optional (though, unless your map is -highly- open I would really not suggest it, units stuck on cliffs and in trees can be a bit difficult to account for) but it's fun for the test map eitherway. You cannot throw units out of the map bounds however, the gravity is mostly for the manipulation of the projectiles generated by my portal spell, it's first and foremost a summoning spell, though, would throwing units halfway across the map in a fast fashion count as half-teleportation? Joking aside here's the screenshots, oh and you can cancel the spell at any time and the units/projectiles will drop out the sky

First one: Funky stuff happens on uneven terrain (nothing major, just thought it was fun to note, half-intended feature actually, adds a bit of spice)

Second one: Flat terrain, standard look, it's hard to catch this work in action because of the fast movement, but it [biased opinion] looks great [/biased opinion]

Third: Yes underneath all that there is indeed a portal

Edit: Before anybody says "sfx spam" I say, yes, yes there is, but none goes to waste and if your computer runs on a 10 yr. old processor/graphics card, you can always change the configurables and fix that
 

Attachments

  • TinyWIP7.png
    TinyWIP7.png
    107.3 KB · Views: 85
  • TinyWIP6.png
    TinyWIP6.png
    244.7 KB · Views: 77
  • TinyWIP5.png
    TinyWIP5.png
    635.1 KB · Views: 105
Level 30
Joined
Nov 29, 2012
Messages
6,637
I have almost completed my entry, all that's left to do is instance recycling and then making the tooltip/description and adding a readme (though the code is already commented, almost completely)

Here's some screenshots fo the (basically final) product, I made whether or not you want units effected by the gravity optional (though, unless your map is -highly- open I would really not suggest it, units stuck on cliffs and in trees can be a bit difficult to account for) but it's fun for the test map eitherway. You cannot throw units out of the map bounds however, the gravity is mostly for the manipulation of the projectiles generated by my portal spell, it's first and foremost a summoning spell, though, would throwing units halfway across the map in a fast fashion count as half-teleportation? Joking aside here's the screenshots, oh and you can cancel the spell at any time and the units/projectiles will drop out the sky

First one: Funky stuff happens on uneven terrain (nothing major, just thought it was fun to note, half-intended feature actually, adds a bit of spice)

Second one: Flat terrain, standard look, it's hard to catch this work in action because of the fast movement, but it [biased opinion] looks great [/biased opinion]

Third: Yes underneath all that there is indeed a portal

You, sir are so fast that I didnt started yet because I am busy with other projects. You can have my +2 REP! I salute you!
 
Level 15
Joined
Feb 15, 2006
Messages
851
My entry (WIP): Evil Extirpation.

Description:
The Evil Messenger extirpates from the land itself all the power of Evil in the shape of raging spirits. Each of them can deal up to 13 damage and, in the process, the evil from nearby enemy units is extracted from themselves, dealing some additional damage.

Level 1 - Deals additional 5 damage, lasts 15 seconds.
Level 2 - Deals additional 8 damage, lasts 20 seconds.
Level 3 - Deals additional 11 damage, lasts 25 seconds.

Source Code:
JASS:
/* ==================================================
   ||           EVIL EXTIRPATION SPELL             ||
   ||                By moyackx                    ||
   ||               Version 1.0.                   ||
   ||                   2013                       ||
   ||         For the Zephyr Contest #10:          ||
   ||         What lies on the other side          ||
   ==================================================
   
   Description:
   ------------
   The Evil Messenger extirps from the land itself all
   the power of Evil in the shape of raging spirits.
   Each of them can deal up to 13 damage and, in the 
   process, the evil from nearby enemy units is
   extracted from themselves, dealing some additional
   damage.
   
   How To install:
   ---------------
   1. Copy & paste the "Evil Extirpation" ability, buff
      and effect in your map
   2. Copy this code in your map.
   3. Edit the CONFIGURATION PART with the new Ability
      (ABIL) and unit type summoned (DUID). Adjust the
      other values too.
   4. Enjoy :D
   
   Don't forget this code requires Alloc2 to run
   properly. This code is in this test ma or you can
   download it here:
   [url]http://wc3jass.com/5012/snippet-allocloop-aka-alloc-2/[/url]
*/

library EvilExtirpation initializer init requires Alloc
/* CONFIGURTATION PART */
globals
    private constant integer ABIL = 'A000' // the Ability rawcode
    private constant integer DUID = 'n001' // the spirit unit type
    private constant real    DT   = 0.3    // Sets the periodic Check Frecuency
    private constant real    AOE  = 700.   // Spell Area of Effect
    private constant real    MAXH = 2000.  // Maximum Height flight for spirit units
    private constant real    HRATE= 200.   // Sets the elevation rate
    private constant real    DDUR = 2.5    // Sets the duration of spirits
    private constant boolean ALOC = false  // Defines if we apply locust ability to the spirits
endglobals
/* END CONFIGURATION PART */

private struct data extends array
    static timer T = CreateTimer()
    static integer I = 0
    unit caster
    integer order
    
    implement AllocLoop
    
    method destroy takes nothing returns nothing
        set .caster = null
        set thistype.I = thistype.I - 1
        if thistype.I == 0 then
            call PauseTimer(thistype.T)
        endif
        call .deallocate()
    endmethod
    
    static method Loop takes nothing returns nothing
        local unit u
        implement loop
            set u = CreateUnit(GetOwningPlayer(this.caster), DUID, GetUnitX(this.caster) + GetRandomReal(-AOE, AOE), GetUnitY(this.caster) + GetRandomReal(-AOE, AOE), GetRandomReal(0, 360))
            call DestroyEffect(AddSpellEffectById(ABIL, EFFECT_TYPE_TARGET, GetUnitX(u), GetUnitY(u)))
            call UnitAddAbility(u, 'Arav') // Add the storm Crow Form ability, to make it fly...
            call SetUnitFlyHeight(u, MAXH, HRATE)
            call UnitApplyTimedLife(u, 0, DDUR)
            if ALOC then
                call UnitAddAbility(u, 'Aloc')
            endif
            if this.order != GetUnitCurrentOrder(this.caster) then
                call this.destroy()
            endif
        implement endloop
        set u = null
    endmethod
    
    static method Start takes unit c returns thistype
        local thistype this = thistype.allocate()
        set this.caster = c
        set this.order = GetUnitCurrentOrder(c)
        set thistype.I = thistype.I + 1
        if thistype.I == 1 then
            call TimerStart(thistype.T, DT, true, function thistype.Loop)
        endif
        return this
    endmethod
endstruct

private function DoEffect takes nothing returns boolean
    if GetSpellAbilityId() == ABIL then
        call data.Start(GetTriggerUnit())
    endif
    return false
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function DoEffect))
    set t = null
endfunction

endlibrary
Video:

 

Attachments

  • Evil Extirpation.w3x
    23.7 KB · Views: 59
Last edited:
Level 20
Joined
Apr 14, 2012
Messages
2,901
My entry: Evil Extirpation.

Description:
The Evil Messenger extirpates from the land itself all the power of Evil in the shape of raging spirits. Each of them can deal up to 13 damage and, in the process, the evil from nearby enemy units is extracted from themselves, dealing some additional damage.

Level 1 - Deals additional 5 damage, lasts 15 seconds.
Level 2 - Deals additional 8 damage, lasts 20 seconds.
Level 3 - Deals additional 11 damage, lasts 25 seconds.

Video coming soon...

Heck that was fast... !
 
@moyackx

Wow you are fast!
Anyways,so that i can work faster,i chose to code my entry in JASS(because if i write it in vJASS,many people will criticize it mainly on timers)

edit
anyways,i'll write in vJASS.

and here's a simple WIP
JASS:
library ArcanceWormholes /* v1.0
*************************************************************************************
*
*    Arcane Wormholes
*       ~ Almia
*
*    --------------------------------------------------------------------------
*
*        Description
*
*        ------------------------------------------
*
*    --------------------------------------------------------------------------
*
*        */ requires /*
*
*        ------------------------------------------
*
*
*************************************************************************************/
    globals
	    /*
		   Ability main constants
		*/
	    private constant real TIMEOUT = 0.031250000
	    /*
		    Main Ability Raw Code
		*/
		private constant integer MAIN = 'A000'
		/*
		    Sub Ability Raw Code
		*/
		private constant integer SUB = 'A001'
		/*
		    Dummy Raw Code
		*/
		private constant integer DUMMY = 'h000'
		
		/*
		    Caster Orbs
		*/
		
	    /*
		    Number of orbs spinning around the caster
		*/
		private constant integer CASTER_ORB_NUMBER = 3
		/*
		    How far are they from the caster
		*/
		private constant real CASTER_ORB_DIST = 150.
		/*
		    How fast the orbs spins around by angle
		*/
		private constant real CASTER_ORB_SPIN_SPEED = 90.
		/*
		    Model Path of the caster orbs
		*/
		private constant string CASTER_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
		/*
		    Orb Model Size
		*/
		private constant real CASTER_ORB_SIZE = 1.
		/*
		    Orb Caster Height
		*/
		private constant real CASTER_ORB_Z = 50.
		
		/*
		    Orb Missile
		*/
		
		/*
		    Missile Speed
		*/
		private constant real ORB_MISSILE_SPEED = 500.
		/*
		    Missile Model
		*/
		private constant string ORB_MISSILE_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
		/*
		    Missile Size
		*/
		private constant real ORB_MISSILE_SIZE = 1.
		/*
		    Missile Height
		*/
		private constant real ORB_MISSILE_Z = 50.
		/*
		    Missile Impact Effect
		*/
		private constant string ORB_IMPACT_EFFECt =  "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
		
		/*
		    Portal
		*/
		
		/*
		    Portal Model
		*/
		private constant string PORTAL_MDL = "units\\nightelf\\Wisp\\Wisp.mdl"
		/*
		    Portal Size
		*/
		private constant real PORTAL_SIZE = 1.
		/*
		    Portal Height
		*/
		private constant real PORTAL_Z = 50.
		/*
		    Portal Duration
		*/
		private constant real PORTAL_DURATION = 60.
		/*
		    Portal Death Effect
		*/
		private constant real PORTAL_DEATH_SFX = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
		
		/*
		    Portal Orbs
		*/
		
		/*
		    Number of orbs spinning around the portal
		*/
		private constant real PORTAL_ORB_NUMBER = 3
		/*
		    How far the orbs are from the portal
		*/
		private constant real PORTAL_ORB_DIST = 150.
		/*
		    Portal Orb Spin Speed
		*/
		private constant real PORTAL_ORB_SPIN_SPEED = 90.
		/*
		    Portal Orb Model
		*/
		private constant string PORTAL_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
        /*
		    Portal Orb Scale
		*/
		private constant real PORTAL_ORB_SIZE = 1.
		/*
		   Portal Orb Z
		*/
		private constant real PORTAL_ORB_Z = 75.
		
		/*
		    Teleportation Constants
		*/
		
		/*
		    Radius of units that will be also teleported
		*/
		private constant real TELEPORT_RADIUS = 500.
		/*
		    Teleportation Delay
		*/
		private constant real TELEPORT_DELAY = 5.
		/*
		    Teleportation Success Effect
		*/
		private constant string TELEPORT_END_SFX = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
		/*
		    Teleportation Impact Effect
		*/
		private constant string TELEPORT_IMPACT_SFX ="Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
		/*
		    Teleportation Damage and Mana Burn Radius
		*/
		private constant real TELEPORT_IMPACT_RADIUS = 400. // Base value
		/*
		    Teleportation Damage value
		*/
		private constant real TELEPORT_IMPACT_DAMAGE = 25. // Base Value
		/*
		    Teleportation Mana Burn Value
		*/
		private constant real TELEPORT_IMPACT_BURN = 25. // Base Value
		/*
		    Teleportation Mana Burn and Damage SFX
		*/
		private constant string TELEPORT_DMB_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
		private constant string TELEPORT_DMB_ATTACH = "chest"
		
		/*
		    Misc Globals
		*/
		private Table tb
		private timer t = CreateTimer()
		private group g = CreateGroup()
	endglobals
endlibrary
 
Last edited:
@Tank commander - you could add support for Indexers to disable indexing of your dummies. Lets say you already have MUI/MPI version - take 12 ppl; use this 12 times and then multicast periodicaly. It'll soak up ton of indexes, granted typical map got it's own set of units, this could lead to overloading 8191 number what would crash the thread.
 
@Tank commander - you could add support for Indexers to disable indexing of your dummies. Lets say you already have MUI/MPI version - take 12 ppl; use this 12 times and then multicast periodicaly. It'll soak up ton of indexes, granted typical map got it's own set of units, this could lead to overloading 8191 number what would crash the thread.

hmm, could be a good idea, atm with my current configuration each (max level) instance is generating. . .60 projectiles and 6 entities marking the edges of the portal (including the portal) so I'm not quite sure of the risk of passing the 8191 number, but not indexing them would still certainly help, especially if somewbody tries using my test configuration which had. . .360 projectiles and 6 entities blah blah blah (at least I know it didn't lag with the 360!)
 
Just writing my Readme before submitting my entry, here's the final screenshots I'll be submitting and the (current) code (will be working on refinements as well and any missed things)

It's a standard JASS spell


JASS:
////////////////////////////////////////////////////////////////////
//  Configuration of the spell can be done here, consult the      //
//  readme for more information on how to do this                 //
////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////
//  Controller for the spell to be used as the  //
//  dummy ability and unit as the dummy unit    //
//////////////////////////////////////////////////
constant function CE_SpellID takes nothing returns integer
    return 'A001'
endfunction

constant function CE_DummyID takes nothing returns integer
    return 'u000'
endfunction

//////////////////////////////////////////////////
//  Controller for the timer speed (0.03 is     //
//  the standard timeout)                       //
//////////////////////////////////////////////////
constant function CE_TimerSpeed takes nothing returns real
    return 0.03
endfunction

//////////////////////////////////////////////////
//  Controller for how long a unit lasts        //
//  after it's usefulness has expired           //
//  (mostly for effects to play)                //
//////////////////////////////////////////////////
constant function CE_DeathTimer takes nothing returns real
    return 2.00
endfunction

//////////////////////////////////////////////////
//  Controller for the order attached to the    //
//  Dummy ability                               //
//////////////////////////////////////////////////
constant function CE_Order takes nothing returns integer
    return OrderId("channel")
endfunction

//////////////////////////////////////////////////
//  Controllers for the Portal AOE (magnetism)  //
//  projectiles will ignore this AOE other      //
//  than for staying attached to the portal     //
//  until it disappates, if this value is       //
//  too small, projectiles will "fall out"      //
//////////////////////////////////////////////////
constant function CE_AOEBase takes nothing returns real
    return 250.00
endfunction

constant function CE_AOEPerLevel takes nothing returns real
    return 100.00
endfunction

//////////////////////////////////////////////////
// Controllers for the centre of the portal     //
//////////////////////////////////////////////////
constant function CE_AOECentral takes nothing returns real
    return 100.00
endfunction
//////////////////////////////////////////////////
//  Controllers for the magnetism strength      //
//  of the portal (playing around may give      //
//  odd results)                                //
//////////////////////////////////////////////////
constant function CE_MagnetismBase takes nothing returns real
    return 30000.00
endfunction

constant function CE_MagnetismPerLevel takes nothing returns real
    return 7500.00
endfunction

//////////////////////////////////////////////////
//  Controllerfor the Magnetism decay, this is  //
//  how far from the portal, until a larger     //
//  proportion of magnetism is used             //
//  (exponential)                               //
//////////////////////////////////////////////////
constant function CE_MagnetismDecay takes nothing returns real
    return 400.00
endfunction

//////////////////////////////////////////////////
//  Constrollers for the portal aesthetics      //
//////////////////////////////////////////////////

//////////////////////////////////////////////////
//  Constroller for the angle of the model      //
//  (90 is upright)                             //
//////////////////////////////////////////////////
constant function CE_PortalAngle takes nothing returns integer
    return 90
endfunction

//////////////////////////////////////////////////
//  Controllers for the scale of the portal     //
//////////////////////////////////////////////////
constant function CE_PortalStartScale takes nothing returns real
    return 2.00
endfunction

constant function CE_PortalGrowthRateBase takes nothing returns real
    return 0.005
endfunction

constant function CE_PortalGrowthRatePerLevel takes nothing returns real
    return 0.000
endfunction

//////////////////////////////////////////////////
//  Controller for how heigh up the portal is   //
//  (will change how units/projectiles behave   //
//  with the portal)                            //
//////////////////////////////////////////////////
constant function CE_PortalHeight takes nothing returns real
    return 400.00
endfunction

//////////////////////////////////////////////////
//  Controllers for the models used for the     //
//  portal and it's boarders                    //
//////////////////////////////////////////////////
constant function CE_PortalModel takes nothing returns string
    return "Abilities\\Spells\\Undead\\Possession\\PossessionCaster.mdl"
endfunction

constant function CE_PortalBoarderModel takes nothing returns string
    return "Abilities\\Spells\\Undead\\AntiMagicShell\\AntiMagicShell.mdl"
endfunction

//////////////////////////////////////////////////
//  Controller for the size of the boarders     //
//////////////////////////////////////////////////
constant function CE_PortalBoarderScale takes nothing returns real
    return 0.25
endfunction

//////////////////////////////////////////////////
//  Controller for how many boarder segments    //
//  the spell has (6.00 gives 6 boarders)       //
//////////////////////////////////////////////////
constant function CE_PortalBoarderSpaceTakenPerSegment takes nothing returns real
    return 6.00
endfunction

//////////////////////////////////////////////////
//  Controller for how heigh the boarders of    //
//  the portal are set (should be about the     //
//  height of the poral + 50)                   //
//////////////////////////////////////////////////
constant function CE_PortalBoarderHeight takes nothing returns real
    return 450.00
endfunction

//////////////////////////////////////////////////
//  Controllers for the size of the projectiles //
//////////////////////////////////////////////////
constant function CE_ChaosEntityScaleBase takes nothing returns real
    return 0.75
endfunction

constant function CE_ChaosEntityScalePerLevel takes nothing returns real
    return 0.00
endfunction

//////////////////////////////////////////////////
//  Controller for the models of the            //
//  projectiles                                 //
//////////////////////////////////////////////////
constant function CE_ChaosEntityModel takes nothing returns string
    return "Abilities\\Spells\\Undead\\OrbOfDeath\\AnnihilationMissile.mdl"
endfunction

//////////////////////////////////////////////////
//  Controller for the initial z velocity of    //
//  chaos entities, changes the aesthetic look  //
//  and the damage spread of the spell          //
//////////////////////////////////////////////////
constant function CE_ChaosEntityZControl takes nothing returns real
    return 6.00
endfunction

//////////////////////////////////////////////////
//  End of the aesthetics configuration         //
//////////////////////////////////////////////////

//////////////////////////////////////////////////
//  Controllers for spell damage                //
//  (Non projectile)                            //
//////////////////////////////////////////////////
constant function CE_HealthDamageBase takes nothing returns real
    return 200.00
endfunction

constant function CE_HealthDamagePerLevel takes nothing returns real
    return 50.00
endfunction

constant function CE_ManaDamageBase takes nothing returns real
    return 0.00
endfunction

constant function CE_ManaDamagePerLevel takes nothing returns real
    return 0.00
endfunction

//////////////////////////////////////////////////
//  Controllers for the number of projectiles   //
//  generated by the spell per cycle            //
//////////////////////////////////////////////////
constant function CE_ChaosEntityCountBase takes nothing returns integer
    return 0
endfunction

constant function CE_ChaosEntityCountPerLevel takes nothing returns integer
    return 5
endfunction

//////////////////////////////////////////////////
//  Controller for the AOE of the chaos         //
//  entities                                    //
//////////////////////////////////////////////////
constant function CE_ChaosEntityAOE takes nothing returns real
    return 125.00
endfunction

//////////////////////////////////////////////////
//  Controller for the Chaos entity creation    //
//  rate (in seconds)                           //
//////////////////////////////////////////////////

constant function CE_ChaosEntityRate takes nothing returns real
    return 1.50
endfunction

//////////////////////////////////////////////////
//  Controllers for the damage dealt by the     //
//  Projectiles                                 //
//////////////////////////////////////////////////
constant function CE_ChaosEntityHealthDamageBase takes nothing returns real
    return 20.00
endfunction

constant function CE_ChaosEntityHealthDamagePerLevel takes nothing returns real
    return 5.00
endfunction

constant function CE_ChaosEntityManaDamageBase takes nothing returns real
    return 0.00
endfunction

constant function CE_ChaosEntityManaDamagePerLevel takes nothing returns real
    return 0.00
endfunction

//////////////////////////////////////////////////
//  Controller for how strong the terrain       //
//  gravity is (makes units return to the       //
//  ground when the rip ends)                   //
//////////////////////////////////////////////////
constant function CE_Gravity takes nothing returns real
    return 40.00 * CE_TimerSpeed()
endfunction

//////////////////////////////////////////////////
//  Controller for whether or not the terrain   //
//  heights effect the spell (arcs hitting      //
//  into it and such)                           //
//////////////////////////////////////////////////
constant function CE_TerrainMatters takes nothing returns boolean
    return true
endfunction

//////////////////////////////////////////////////
//  Controller for whether or not units are     //
//  pulled into the Portal                      //
//////////////////////////////////////////////////
constant function CE_EffectsUnits takes nothing returns boolean
    return true
endfunction

//////////////////////////////////////////////////
//  Controllers for the damage types and such   //
//////////////////////////////////////////////////
constant function CE_MainDamageType takes nothing returns damagetype
    return DAMAGE_TYPE_MAGIC
endfunction

constant function CE_ChaosEntityDamageType takes nothing returns damagetype
    return DAMAGE_TYPE_NORMAL
endfunction

constant function CE_MainAttackType takes nothing returns attacktype
    return ATTACK_TYPE_MAGIC
endfunction

constant function CE_ChaosEntityAttackType takes nothing returns attacktype
    return ATTACK_TYPE_NORMAL
endfunction

constant function CE_MainWeaponType takes nothing returns weapontype
    return null
endfunction

constant function CE_ChaosEntityWeaponType takes nothing returns weapontype
    return null
endfunction

////////////////////////////////////////////////////////////////////
//  End of the configuration of the spell, beyond this is the     //
//  programming used to run the spell, if you do not understand   //
//  JASS, then it is not recommended that you scroll any further  //
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
//  Function used to identify targets for the magnetism or        //
//  damage of the spell depanding on what the current stage is    //
////////////////////////////////////////////////////////////////////
function CE_TargetFilter takes unit u, player pl returns nothing

    //Checks if the unit can be used as a target
    if (IsUnitType(u, UNIT_TYPE_GROUND)) and (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)) and (IsUnitEnemy(u, pl)) and (GetUnitTypeId(u) != CE_DummyID()) and (not IsUnitInGroup(u, udg_CE_EffectedUnits)) and (not IsUnitType(u, UNIT_TYPE_DEAD)) then
        call GroupAddUnit(udg_CE_TempGroup, u)
    endif
    
    //Nulling variables
    set u = null
    set pl = null

endfunction

function CE_GravityMove takes real Magnetism, real Radian, real Angle, real Angle2, real x, real y, real x2, real y2, real z, integer index returns nothing
    local location p
    
    //Setting the new locations X and Y for this instance
    set x2 = x + udg_CE_XVelocity[index]
    set y2 = y + udg_CE_YVelocity[index]
    set p = Location(x2,y2)
    //Calculating the new velocities (will be used next time this runs)
    set udg_CE_ZVelocity[index] = udg_CE_ZVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Sin(Angle2)
    set udg_CE_XVelocity[index] = udg_CE_XVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Cos(Angle) * Cos(Angle2)
    set udg_CE_YVelocity[index] = udg_CE_YVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Sin(Angle) * Cos(Angle2)
    
    //Makes sure the new location is within the map bounds
    if ((GetRectMinX(bj_mapInitialPlayableArea) <= GetLocationX(p)) and (GetLocationX(p) <= GetRectMaxX(bj_mapInitialPlayableArea)) and (GetRectMinY(bj_mapInitialPlayableArea) <= GetLocationY(p)) and (GetLocationY(p) <= GetRectMaxY(bj_mapInitialPlayableArea))) then
        call SetUnitX(udg_CE_UnitIndex[index], x2)
        call SetUnitY(udg_CE_UnitIndex[index], y2)
    endif
    //Removes the location
    call RemoveLocation(p)
    //Sets the correct fly height
    call SetUnitFlyHeight(udg_CE_UnitIndex[index], udg_CE_CurrentZ[index] - z, 0.00)
    
    //Nulling the variable
    set p = null
    
endfunction

function CE_ProjectileImpactDetection takes real z, real x, real y, integer index returns nothing
    local unit u
    local player pl
    
    //Checks if there has been a crash
    if (udg_CE_CurrentZ[index] - z < 5.00) then
        //Yes it crashed, deassociating the unit
        set udg_CE_StageID[index] = 4
        set pl = GetOwningPlayer(udg_CE_OriginalCaster[index])
        
        if (GetUnitTypeId(udg_CE_UnitIndex[index]) == CE_DummyID()) then
            call DestroyEffect(udg_CE_CurrentEffect[index])
            //Select Units to damage
            call GroupEnumUnitsInRange(udg_CE_TempGroup2, x, y, CE_ChaosEntityAOE(), null)              
                
            loop
                //Scanning through
                set u = FirstOfGroup(udg_CE_TempGroup2)
                exitwhen u == null
                call CE_TargetFilter(u, pl)
                call GroupRemoveUnit(udg_CE_TempGroup2, u)
                    
                //Select all the units which are to be damaged
                if (IsUnitInGroup(u, udg_CE_TempGroup)) then
                    //Dealing health and mana damage
                    call UnitDamageTarget(udg_CE_OriginalCaster[index], u, udg_CE_HealthDamage[index], true, false, CE_ChaosEntityAttackType(), CE_ChaosEntityDamageType(), CE_ChaosEntityWeaponType())
                    call SetUnitState(u, UNIT_STATE_MANA, (GetUnitState(u,UNIT_STATE_MANA) - udg_CE_ManaDamage[index]))
                    call GroupRemoveUnit(udg_CE_TempGroup, u)
                endif
                    
            endloop
                    
            //Removes the projectile
            call KillUnit(udg_CE_UnitIndex[index])                
        else
            //Dealing health and mana damage
            call UnitDamageTarget(udg_CE_OriginalCaster[index], udg_CE_UnitIndex[index], udg_CE_HealthDamage[index], true, false, CE_MainAttackType(), CE_MainDamageType(), CE_MainWeaponType())
            call SetUnitState(udg_CE_UnitIndex[index], UNIT_STATE_MANA, (GetUnitState(udg_CE_UnitIndex[index],UNIT_STATE_MANA) - udg_CE_ManaDamage[index]))
            //Allowing the unit to be reselected as a target for another instance
            call GroupRemoveUnit(udg_CE_EffectedUnits, udg_CE_UnitIndex[index])
            //Enabling the unit's pathing again
            call SetUnitPathing(udg_CE_UnitIndex[index], true )
        endif
                
    endif
            
endfunction
 
function CE_RegisterUnit takes integer index, real z, real x2, real y2, unit u, real YVel, real XVel, real ZVel returns nothing
    //Sets up data for the next magnetised unit
    local location p2
    set p2 = Location(x2, y2)
    set udg_CE_LaunchZ[udg_CE_MaxIndex] = GetLocationZ(p2)
    set udg_CE_TargetZ[udg_CE_MaxIndex] = z
    call RemoveLocation(p2)
    
    //Sets up data for caster and portal it's being pulled into
    set udg_CE_OriginalCaster[udg_CE_MaxIndex] = udg_CE_OriginalCaster[index]
    set udg_CE_Portal[udg_CE_MaxIndex] = udg_CE_UnitIndex[index]
    set udg_CE_AOE[udg_CE_MaxIndex] = udg_CE_AOE[index]
                        
    //Sets up the magnetism
    set udg_CE_MagnetismStrength[udg_CE_MaxIndex] = udg_CE_MagnetismStrength[index]
    set udg_CE_CurrentZ[udg_CE_MaxIndex] = GetUnitFlyHeight(u) + udg_CE_LaunchZ[udg_CE_MaxIndex]
    set udg_CE_YVelocity[udg_CE_MaxIndex] = YVel                      
    set udg_CE_XVelocity[udg_CE_MaxIndex] = XVel
    set udg_CE_ZVelocity[udg_CE_MaxIndex] = ZVel
    
    //Nulls variables
    set u = null
    set p2 = null
    
endfunction

////////////////////////////////////////////////////////////////////
//  Main looping function, controls things from the magnetism     //
//  of the portal to the damage and projectile control within     //
//  the Chaos Rip                                                 //
////////////////////////////////////////////////////////////////////
function CE_Loop takes nothing returns nothing
    //Setting up the local variables
    local integer index = 0
    local integer secondaryindex = 0
    local real x
    local real x2
    local real y
    local real y2
    local real z
    local real z2
    local real dx
    local real dy
    local real Dist
    local real Angle
    local real Angle2
    local real Magnetism
    local real Radian
    local player pl
    local unit u
    local location p
    
    //Loops through all the units within the system
    loop
        set index = index + 1
        set x = GetUnitX(udg_CE_UnitIndex[index])
        set y = GetUnitY(udg_CE_UnitIndex[index])
         
        //Finds units which are initial portals of an instance
        if (udg_CE_StageID[index] == 1) then
            if (GetUnitCurrentOrder(udg_CE_OriginalCaster[index]) != CE_Order()) then
                set udg_CE_StageID[index] = 4
                call DestroyEffect(udg_CE_CurrentEffect[index]) 
                
                //Deassociating all the units involves with this porta (will allow units and projectiles to fall)
                loop
                    set secondaryindex = secondaryindex + 1
                    
                    if (udg_CE_Portal[secondaryindex] == udg_CE_UnitIndex[index]) then
                        set udg_CE_Portal[secondaryindex] = null
                        
                        if (udg_CE_StageID[secondaryindex] == 7) then
                            set udg_CE_StageID[secondaryindex] = 4
                            call DestroyEffect(udg_CE_CurrentEffect[secondaryindex])
                        else
                            set udg_CE_StageID[secondaryindex] = 3
                        endif
                    
                    endif
                    
                    exitwhen secondaryindex > udg_CE_MaxIndex
                endloop
                
                set secondaryindex = 0
            else
                //Initialising data and increasing the portal size
                set p = Location(x, y)
                set z = GetLocationZ(p) + CE_PortalHeight()
                set u = udg_CE_UnitIndex[index]
                call RemoveLocation (p)
                set udg_CE_CurrentSize[index] = udg_CE_CurrentSize[index] + udg_CE_GrowthRate[index]
                set pl = GetOwningPlayer(udg_CE_OriginalCaster[index])
                call SetUnitScale(udg_CE_UnitIndex[index], udg_CE_CurrentSize[index], 0.00, 0.00)


                if (udg_CE_CurrentProjectileDelay[index] > CE_ChaosEntityRate()) then
                    //Creating New projectile wave
                    set Angle = 0
                    //Reset the delay timer
                    set udg_CE_CurrentProjectileDelay[index] = 0.00

                    loop
                        //Calculating position and initialising
                        set Angle = Angle + (360.00 / udg_CE_ChaosEntityCount[index])
                        set secondaryindex = secondaryindex + 1
                        set x2 = x + CE_AOECentral() * Cos(Angle * bj_DEGTORAD)
                        set y2 = y + CE_AOECentral() * Sin(Angle * bj_DEGTORAD)
                        set udg_CE_MaxIndex = udg_CE_MaxIndex + 1
                        set udg_CE_UnitIndex[udg_CE_MaxIndex] = CreateUnit(Player(14), CE_DummyID(), x2, y2, Angle)
                        set udg_CE_CurrentEffect[udg_CE_MaxIndex] = AddSpecialEffectTarget(CE_ChaosEntityModel(), udg_CE_UnitIndex[udg_CE_MaxIndex], "origin")
                        set udg_CE_HealthDamage[udg_CE_MaxIndex] = CE_ChaosEntityHealthDamageBase() + (CE_ChaosEntityHealthDamagePerLevel() * udg_CE_rLevel[index])
                        set udg_CE_ManaDamage[udg_CE_MaxIndex] = CE_ChaosEntityManaDamageBase() + (CE_ChaosEntityManaDamagePerLevel() * udg_CE_rLevel[index])
                        set udg_CE_StageID[udg_CE_MaxIndex] = 2
                        set udg_CE_Portal[udg_CE_MaxIndex] = u
                        //Makes terrain height changing possible if not already
                        if UnitAddAbility(udg_CE_UnitIndex[udg_CE_MaxIndex], 'Amrf') and UnitRemoveAbility(udg_CE_UnitIndex[udg_CE_MaxIndex], 'Amrf') then
                        endif
                            
                        //Setting up data of the new magnetised unit
                        call CE_RegisterUnit(index, z, x2, y2, u, 0.00, 0.00, CE_ChaosEntityZControl())
            
                        //Applying Aesthetics
                        call SetUnitScale(udg_CE_UnitIndex[udg_CE_MaxIndex],  CE_ChaosEntityScaleBase() + (CE_ChaosEntityScalePerLevel() * udg_CE_rLevel[index]), 0.00, 0.00)
                        call SetUnitFlyHeight(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalHeight(), 0.00)
                        call SetUnitAnimationByIndex(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalAngle())

                        call GroupAddUnit(udg_CE_EffectedUnits, udg_CE_UnitIndex[index])
            
                        exitwhen secondaryindex > udg_CE_ChaosEntityCount[index]
                    endloop
                    
                    set secondaryindex = 0
                else
                    //Increase the delay timer on the projectiles
                    set udg_CE_CurrentProjectileDelay[index] = udg_CE_CurrentProjectileDelay[index] + CE_TimerSpeed()
                endif

                if (CE_EffectsUnits()) then
                    call GroupEnumUnitsInRange(udg_CE_TempGroup2, x, y, udg_CE_AOE[index], null)              

                    //Filters through all the units within the range of the portal which can be used as targets
                    loop
                        set u = FirstOfGroup(udg_CE_TempGroup2)
                        exitwhen u == null
                        call CE_TargetFilter(u, pl)
                        call GroupRemoveUnit(udg_CE_TempGroup2, u)
                    
                        //Actions for units which have been found to be viable targets
                        if (IsUnitInGroup(u, udg_CE_TempGroup)) and (not IsUnitInGroup(u, udg_CE_EffectedUnits)) then
                            //Data initialisation
                            set x2 = GetUnitX(u)
                            set y2 = GetUnitY(u)
                            set dx = x2 - x
                            set dy = y2 - y
                            set Angle = Atan2(dy, dx)
                            set Dist = SquareRoot(dx * dx + dy * dy)
                            set udg_CE_MaxIndex = udg_CE_MaxIndex + 1
                            set udg_CE_UnitIndex[udg_CE_MaxIndex] = u
                            set udg_CE_HealthDamage[udg_CE_MaxIndex] = udg_CE_HealthDamage[index]
                            set udg_CE_ManaDamage[udg_CE_MaxIndex] = udg_CE_ManaDamage[index]
                       
                            //Makes terrain height changing possible if not already
                            if UnitAddAbility(udg_CE_UnitIndex[udg_CE_MaxIndex], 'Amrf') and UnitRemoveAbility(udg_CE_UnitIndex[udg_CE_MaxIndex], 'Amrf') then
                            endif
                            
                            call SetUnitPathing(u, false ) 
                            set udg_CE_StageID[udg_CE_MaxIndex] = 2
                            //Sets up data for the next magnetised unit
                            call CE_RegisterUnit(index, z, x2, y2, u, 0.00, 0.00, 6.00)

                            //Makes this unit unselectable as a target until the end of this spell instance
                            call GroupAddUnit(udg_CE_EffectedUnits, u)
                            call GroupRemoveUnit(udg_CE_TempGroup, u)
                        endif

                    endloop
                    
                endif         

            endif

        //Finds units which are to be effected by the magnetism
        elseif (udg_CE_StageID[index] == 2) then
            //Initialises Magnetism factors
            set x2 = GetUnitX(udg_CE_Portal[index])
            set y2 = GetUnitY(udg_CE_Portal[index])
            //Sets up this instance of the movement
            set udg_CE_CurrentZ[index] = udg_CE_CurrentZ[index] + udg_CE_ZVelocity[index]
            
            //Sets up calculating the next movement
            set p = Location(x, y)
            set z = GetLocationZ(p)
            call RemoveLocation(p)
            set dy = y2 - y
            set dx = x2 - x
            set Dist = SquareRoot(dx * dx + dy * dy)
            set Angle = Atan2(dy, dx)
            set Angle2 = Atan2(udg_CE_TargetZ[index] - udg_CE_CurrentZ[index], Dist)
            set Radian = SquareRoot((dx * dx) + (dy * dy) + (udg_CE_TargetZ[index] - udg_CE_CurrentZ[index]) * (udg_CE_TargetZ[index] - udg_CE_CurrentZ[index]))
            //Calculates the magnetism strength for this instance
            set Magnetism = udg_CE_MagnetismStrength[index] * (Dist / CE_MagnetismDecay())

            if (Dist > udg_CE_AOE[index]) then
                set udg_CE_StageID[index] = 3
            endif
            
            //Checks if the unit or entity have crashed
            call CE_ProjectileImpactDetection(z, x, y, index)
            
            //Moves the unit or entity around the Portal
            call CE_GravityMove(Magnetism, Radian, Angle, Angle2, x, y, x2, y2, z, index)

            //Checks if the unit is an entity - if it is, then setting its animation and facing direction
            if (GetUnitTypeId(udg_CE_UnitIndex[index]) == CE_DummyID()) then
                call SetUnitAnimationByIndex(udg_CE_UnitIndex[index], R2I(Atan2(udg_CE_ZVelocity[index], SquareRoot((udg_CE_XVelocity[index] * udg_CE_XVelocity[index]) + (udg_CE_YVelocity[index] * udg_CE_YVelocity[index]))) * bj_RADTODEG + 0.5) + 90)
                call SetUnitFacing(udg_CE_UnitIndex[index], Angle * bj_RADTODEG)
            endif

        //Finds units which are falling out of the sky
        elseif (udg_CE_StageID[index] == 3) then
            set p = Location(x, y)
            set z = GetLocationZ(p)
            set x2 = x + udg_CE_XVelocity[index]
            set y2 = y + udg_CE_YVelocity[index]  
            set udg_CE_ZVelocity[index] = udg_CE_ZVelocity[index] - CE_Gravity()
            set udg_CE_CurrentZ[index] = udg_CE_CurrentZ[index] + udg_CE_ZVelocity[index] 

            //Makes sure the projectile or unit does not leave the map bounds (may look a bit odd but is necessary)
            if ((GetRectMinX(bj_mapInitialPlayableArea) <= GetLocationX(p)) and (GetLocationX(p) <= GetRectMaxX(bj_mapInitialPlayableArea)) and (GetRectMinY(bj_mapInitialPlayableArea) <= GetLocationY(p)) and (GetLocationY(p) <= GetRectMaxY(bj_mapInitialPlayableArea))) then
                call SetUnitX(udg_CE_UnitIndex[index], x2)
                call SetUnitY(udg_CE_UnitIndex[index], y2)
            endif
            
            call RemoveLocation(p)
            call SetUnitFlyHeight(udg_CE_UnitIndex[index],  udg_CE_CurrentZ[index] - z, 0.00)
    
            call CE_ProjectileImpactDetection(z, x, y, index)

            set Angle = Atan2(y2 - y, x2 - x)
            if (GetUnitTypeId(udg_CE_UnitIndex[index]) == CE_DummyID()) then
                call SetUnitAnimationByIndex(udg_CE_UnitIndex[index], R2I(Atan2(udg_CE_ZVelocity[index], SquareRoot((udg_CE_XVelocity[index] * udg_CE_XVelocity[index]) + (udg_CE_YVelocity[index] * udg_CE_YVelocity[index]))) * bj_RADTODEG + 0.5) + 90)
                call SetUnitFacing(udg_CE_UnitIndex[index], Angle * bj_RADTODEG)
            endif
            
        //Finds units which need to be recycled
        elseif (udg_CE_StageID[index] == 4) then
        
            //Checks if the death timer has expired
            if (udg_CE_CurrentDeathTimer[index] == CE_DeathTimer()) then
            
                //Removing projectiles from the game
                if (GetUnitTypeId(udg_CE_UnitIndex[index]) == CE_DummyID()) then
                    call RemoveUnit(udg_CE_UnitIndex[index])
                endif  
                
                //Recycling the instance of the spell
                set udg_CE_AOE[index] = udg_CE_AOE[udg_CE_MaxIndex]
                set udg_CE_ChaosEntityCount[index] = udg_CE_ChaosEntityCount[udg_CE_MaxIndex]
                set udg_CE_CurrentDeathTimer[index] = udg_CE_CurrentDeathTimer[udg_CE_MaxIndex]
                set udg_CE_CurrentEffect[index] = udg_CE_CurrentEffect[udg_CE_MaxIndex]
                set udg_CE_CurrentSize[index] = udg_CE_CurrentSize[udg_CE_MaxIndex]
                set udg_CE_CurrentZ[index] = udg_CE_CurrentZ[udg_CE_MaxIndex]
                set udg_CE_GrowthRate[index] = udg_CE_GrowthRate[udg_CE_MaxIndex]
                set udg_CE_HealthDamage[index] = udg_CE_HealthDamage[udg_CE_MaxIndex]
                set udg_CE_LaunchZ[index] = udg_CE_LaunchZ[udg_CE_MaxIndex]
                set udg_CE_MagnetismStrength[index] = udg_CE_MagnetismStrength[udg_CE_MaxIndex]
                set udg_CE_ManaDamage[index] = udg_CE_ManaDamage[udg_CE_MaxIndex]
                set udg_CE_OriginalCaster[index] = udg_CE_OriginalCaster[udg_CE_MaxIndex]
                set udg_CE_Portal[index] = udg_CE_Portal[udg_CE_MaxIndex]
                set udg_CE_StageID[index] = udg_CE_StageID[udg_CE_MaxIndex]
                set udg_CE_TargetZ[index] = udg_CE_TargetZ[udg_CE_MaxIndex]
                set udg_CE_UnitIndex[index] = udg_CE_UnitIndex[udg_CE_MaxIndex]
                set udg_CE_XVelocity[index] = udg_CE_XVelocity[udg_CE_MaxIndex]
                set udg_CE_YVelocity[index] = udg_CE_YVelocity[udg_CE_MaxIndex]
                set udg_CE_ZVelocity[index] = udg_CE_ZVelocity[udg_CE_MaxIndex]
                set udg_CE_iLevel[index] = udg_CE_iLevel[udg_CE_MaxIndex]
                set udg_CE_rLevel[index] = udg_CE_rLevel[udg_CE_MaxIndex]
                set udg_CE_MaxIndex = udg_CE_MaxIndex - 1
                set index = index - 1
                
                //Stopping the timer if there are no more instances to run
                if (udg_CE_MaxIndex == 0) then
                    call DestroyTimer(GetExpiredTimer())
                endif

            else
                //If the death timer has not expired, increase how long it's been running
                set udg_CE_CurrentDeathTimer[index] = udg_CE_CurrentDeathTimer[index] + CE_TimerSpeed()
            endif
            
        endif
        
        exitwhen index > udg_CE_MaxIndex
    endloop
    
    //Nulls variables
    set u = null
    set p = null
    
endfunction

////////////////////////////////////////////////////////////////////
//  Function ran to create a new instance of the spell, inits a   //
//  portal, giving it the starting information it requires        //
////////////////////////////////////////////////////////////////////
function TrigCE_AllocateData takes nothing returns boolean
    // Sets up the variables required for creating units
    local unit u = GetTriggerUnit()
    local integer iLevel = GetUnitAbilityLevel(u, CE_SpellID())
    local real rLevel = I2R(iLevel)
    local real x = GetSpellTargetX()
    local real x2 = GetUnitX(u)
    local real y = GetSpellTargetY()
    local real y2 = GetUnitY(u)
    local real Angle = 0.00
    
    // Checks if the ability casted was the correct one
    if (GetSpellAbilityId() == CE_SpellID()) then
        // Initialises  new spell instance
        set udg_CE_MaxIndex = udg_CE_MaxIndex + 1
        set udg_CE_UnitIndex[udg_CE_MaxIndex] = CreateUnit(Player(14), CE_DummyID(), x, y, Atan2(y - y2, x - x2))
        set udg_CE_AOE[udg_CE_MaxIndex] = CE_AOEBase() + (CE_AOEPerLevel() * rLevel)
        set udg_CE_CurrentEffect[udg_CE_MaxIndex] = AddSpecialEffectTarget(CE_PortalModel(), udg_CE_UnitIndex[udg_CE_MaxIndex], "origin")
        set udg_CE_MagnetismStrength[udg_CE_MaxIndex] = CE_MagnetismBase() + (CE_MagnetismPerLevel() * rLevel)
        set udg_CE_GrowthRate[udg_CE_MaxIndex] = CE_PortalGrowthRateBase() + (CE_PortalGrowthRatePerLevel() * rLevel)
        set udg_CE_ChaosEntityCount[udg_CE_MaxIndex] = CE_ChaosEntityCountBase() + (CE_ChaosEntityCountPerLevel() * iLevel)
        set udg_CE_CurrentSize[udg_CE_MaxIndex]= CE_PortalStartScale()
        set udg_CE_CurrentProjectileDelay[udg_CE_MaxIndex] = 0.00
        set udg_CE_CurrentDeathTimer[udg_CE_MaxIndex] = 0.00
        set udg_CE_OriginalCaster[udg_CE_MaxIndex] = u
        set udg_CE_iLevel[udg_CE_MaxIndex] = iLevel
        set udg_CE_rLevel[udg_CE_MaxIndex] = rLevel
        set udg_CE_StageID[udg_CE_MaxIndex] = 1
        set udg_CE_HealthDamage[udg_CE_MaxIndex] = CE_HealthDamageBase() + (CE_HealthDamagePerLevel() * rLevel)
        set udg_CE_ManaDamage[udg_CE_MaxIndex] = CE_ManaDamageBase() + (CE_ManaDamagePerLevel() * rLevel)
        
        //Makes terrain height changing possible if not already
        if UnitAddAbility(udg_CE_UnitIndex[udg_CE_MaxIndex], 'Amrf') and UnitRemoveAbility(udg_CE_UnitIndex[udg_CE_MaxIndex], 'Amrf') then
        endif
        
        //Sets up the aesthetics of the portal
        call SetUnitScale(udg_CE_UnitIndex[udg_CE_MaxIndex], udg_CE_CurrentSize[udg_CE_MaxIndex], 0.00, 0.00)
        call SetUnitFlyHeight(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalHeight(), 0.00)
        call SetUnitAnimationByIndex(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalAngle())
        
        //If no timer is currently running (Max Index was 0 before this) create a new one
        if (udg_CE_MaxIndex == 1) then
            call TimerStart(CreateTimer(), CE_TimerSpeed(), true, function CE_Loop)
        endif
        
        set u = udg_CE_UnitIndex[udg_CE_MaxIndex]
        
        //Creating Aesthetic portal boarder
        loop
            //Calculating position and initialising
            set Angle = Angle + (360.00 / CE_PortalBoarderSpaceTakenPerSegment())
            set x2 = x + CE_AOECentral() * Cos(Angle * bj_DEGTORAD)
            set y2 = y + CE_AOECentral() * Sin(Angle * bj_DEGTORAD)
            set udg_CE_MaxIndex = udg_CE_MaxIndex + 1
            set udg_CE_UnitIndex[udg_CE_MaxIndex] = CreateUnit(Player(14), CE_DummyID(), x2, y2, Angle)
            set udg_CE_CurrentEffect[udg_CE_MaxIndex] = AddSpecialEffectTarget(CE_PortalBoarderModel(), udg_CE_UnitIndex[udg_CE_MaxIndex], "origin")
            set udg_CE_StageID[udg_CE_MaxIndex] = 7
            set udg_CE_Portal[udg_CE_MaxIndex] = u

            //Makes terrain height changing possible if not already
            if UnitAddAbility(udg_CE_UnitIndex[udg_CE_MaxIndex], 'Amrf') and UnitRemoveAbility(udg_CE_UnitIndex[udg_CE_MaxIndex], 'Amrf') then
            endif
            
            //Applying Aesthetics
            call SetUnitScale(udg_CE_UnitIndex[udg_CE_MaxIndex],  CE_PortalBoarderScale(), 0.00, 0.00)
            call SetUnitFlyHeight(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalBoarderHeight(), 0.00)
            call SetUnitAnimationByIndex(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalAngle())
            
            exitwhen Angle >= 360.00
        endloop
        
    endif
    
    //Nulls variables
    set u = null
    return false
    
endfunction

////////////////////////////////////////////////////////////////////
//  Function used to start up the spell, initialises events       //
//  and conditions needed for the spell to run correctly          //
////////////////////////////////////////////////////////////////////
function InitTrig_CE_ChaosEnvoy takes nothing returns nothing
    local trigger CE = CreateTrigger()
    local integer index = 0

    //Initialise the event for every player
    loop
        call TriggerRegisterPlayerUnitEvent(CE, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    
    call TriggerAddCondition(CE, Condition(function TrigCE_AllocateData))
    
    //Nulls variables
    set CE = null
    
endfunction


The work-in-progress README is a bit above that, btw, whom do I credit for dummy.mdl? my brain tells me Vexorian, but, I do not trust my memory

oh and lets not forget giving you guys the tooltip and why not throw in the test map terrain (after all, the spell is terrain-height sensitive (unless you turn that feature off)

Edit: will make a point to fix any typo's/grammar mistakes/etc. on the tooltip as well

Edit2: Also might make a GIF, it's hard to appreciate the physics with a still-image
 

Attachments

  • TinyWIP8.png
    TinyWIP8.png
    239.7 KB · Views: 97
  • TinyWIP9.png
    TinyWIP9.png
    278.5 KB · Views: 254
  • Contest Entry Test Map.png
    Contest Entry Test Map.png
    1.7 MB · Views: 83
  • Contest Entry Tooltip.png
    Contest Entry Tooltip.png
    101.9 KB · Views: 3,842
Last edited:
The Triggerables

Remove MasterTrainer and Hell_Master ,because they are mainly mappers :D

@moyackx
Indention.
And why not put the init and do effect as a method inside the data struct? its much faster.

Anyways, Struct WIPS
JASS:
struct Orbs extends array
endstruct

struct OrbMissile extends array
endstruct

struct ShardOrbs extends array
endstruct

struct Portal extends array
endstruct

struct Spell extends array
endstruct
The 4 structs above Spell are dummies.
 
Status
Not open for further replies.
Top