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

Chaos Envoy V1.02

Spell created for http://www.hiveworkshop.com/forums/arena-226/zephyr-contest-10-what-lies-other-side-233773/

Currently this spell is a very slightly modified version of the contest entry (V1.00 being an exact replica) for the first version, view the contest thread

I would've liked to have uploaded this at the end of the contest, but since that'll probably be in a few months, I'm uploading it now


- Hugely Configurable
- Large Readme
- Accounts for terrain height
- Fun effects when casted on uneven terrain
- 3D Gravity Well
- Channeling spell
- Physics galore
- Comes with triggers to help with importing (Variable Creator)



124963d1367497077-zephyr-contest-10-what-lies-other-side-contest-entry-tooltip.png




JASS:
////////////////////////////////////////////////////////////////////
//                    CHAOS ENVOY V1.00                           //
//                                                                //
//  Author: Tank-Commander                                        //
//  Requires: Dummy.mdl                                           //
//  Purpose: Hero Ultimate, very powerful manipulation ability    //
//                                                                //
//  Notes:                                                        //
//    -  It's a channeling spell                                  //
//    -  Read the readme before you try modifying the config      //
//    -  Use the "Helpful files" to help you import the spell     //
//                                                                //
//  Credits:                                                      //
//    -  (Dummy.mdl) Vexorian                                     //
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
//  Chaos Envoy README                                            //
//                                                                //
//  This spell has a lot to configure so this readme will help    //
//  you set up your own Chaos Envoy spell to your liking          //
//  please read this through -fully- before attempting to change  //
//  the configuration                                             //
//                                                                //
//  If your editor does not automatically create variables for    //
//  JASS resources, please enable "automatically create unknown   //
//  variables while pasting trigger data" in the following path:  //
//  File -> Preferences ->  General                               //
//                                                                //
//  Once that is enabled, paste in the Variable Creator           //
//  (it can be deleted afterwards, it's just to create variables  //
//  and serves no other purpose)                                  //
//                                                                //
//  Contents:                                                     //
//                                                                //
//    1-- Setting SpellID and DummyID                             //
//    2-- Timer and Order                                         //
//    3-- AOE                                                     //
//    4-- Magnetism                                               //
//    5-- Aesthetics                                              //
//    6-- Main Damage                                             //
//    7-- Chaos Entity control                                    //
//    8-- Chais Entity damage                                     //
//    9-- Gravity, terrain and units                              //
//   10-- Attack, Damage, and weapon types                        //
//   11-- Unit Indexers                                           //
//                                                                //
//-------------------------------1--------------------------------//
//  Setting SpellID and DummyID:                                  //
//    To do this, find the spell you wish to set as the dummy     //
//    (or unit) then, find the data value of the spell/unit       //
//    if your editor is not already displaying data values then   //
//    you can enable the display by pressing Ctrl + D             //
//    before you panic, pressing Ctrl + D again, will revert the  //
//    the data value you're looking for will be in the unit       //
//    box in the object editor it should look like something      //
//    like this: u000                                             //
//                                                                //
//    there may be something after that like :uloc and then the   //
//    actual name in brackets, but you want this four character   //
//    code. To set it remeber the code and put it between         //
//    these two characters: ' '                                   //
//    e.g.:                                                       //
//      'u000'                                                    //
//                                                                //
//    Now, you can take that, and place it in the respective ID   //
//    return function the line should look like this:             //
//      return 'u000'                                             //
//                                                                //
//    When you have completed this you are ready to move on to    //
//    the next part.                                              //
//                                                                //
//-------------------------------2--------------------------------//
//  Timer and Order:                                              //
//    This spell has two timers and one order, one of the timers  //
//    is for how fast the loop runs, the other, is how long       //
//    after a unit is removed, is the instance recycled           //
//    (it has a timer so that death effects can play)             //
//                                                                //
//    The first timer, will need to be set to something low       //
//    but not below 0.03 to prevent lag, setting it to            //
//    something high (above 0.05) may remove some of the          //
//    smoothness of the effects, it's recommended that you leave  //
//    the value at 0.03, but you may wish to change it            //
//                                                                //
//    The second timer, can technically be any number you like    //
//    and in most cases, it won't make any difference provided    //
//    it's over a second, and if not, the only change is that     //
//    some effects to not display properly due to the unit being  //
//    removed before they finish playing, it is in seconds        //
//    so 1.00 == 1 second, pretty simple and straightforward      //
//                                                                //
//    The order: This is a bit more complex though still fairly   //
//    straightforward, find your spell in the object editor       //
//    you're looking for "Text - Order string - Use/turn on"      //
//    in most cases this should be "channel" because the spell    //
//    needs to be channeled to word, but if you want to change    //
//    it you can, though it's not recommended                     //
//                                                                //
//-------------------------------3--------------------------------//
//  AOE:                                                          //
//    The AOE configurables essentially control the area of the   //
//    magnetism, rather than the spread of the projectiles        //
//    as for the projectiles, that will be covered later          //
//    for now, this section will focus on the magnetism AOE       //
//                                                                //
//    The AOE controls how far away from the portal you can be    //
//    and still be affected by it's AOE, if a unit leaves the     //
//    portal AOE, then it will be dropped by the portal           //
//    The AOE variables ought to manage to keep the projectiles   //
//    within the portal, if it is too small in relation to the    //
//    other factors, the entities will also fall out, as well as  //
//    any units which were taken for the ride                     //
//                                                                //
//    "AOE Central" referrs to the boarders and how far they are  //
//    from the middle of the portal (also how far the entities    //
//    are created from the middle) experimenting with that may    //
//    give some interesting results, but remember the default     //
//    value of 100.00                                             //
//                                                                //
//-------------------------------4--------------------------------//
//  Magnetism:                                                    //
//    The Magnetism values need to be high,the base value should  //
//    be at least 10000.00 for it work correctly, having too      //
//    much magnetism (80000+) may cause some unforseen effects    //
//    Like units flying out of the top of the Map Z height, so    //
//    it's not really recommended (though you never know)         //
//    the increment can be anything really, the magnetism itself  //
//    will however alter the spread of the projectiles and units  //
//    if it is changed, if you want a maintained (or roughly      //
//    maintained pattern) I suggest an increment under 10000.00   //
//                                                                //
//    Magnetism Decay: this works a little differently, unlike    //
//    normal gravity where it is stronger the closer to the       //
//    center, this spell has an inverted gravity, it's stronger   //
//    the further away a unit is, and weaker in the center        //
//    the decay controls how the distance from the target is      //
//    divided up, i.e. the default value is 400                   //
//    say a unit 1200 points apart is in range, the strength of   //
//    the magnetism they experience is:                           //
//      MagnetismStrength * (1200/400) = MagnetismStrength * 3    //
//                                                                //
//    So they experience 3x the normal magnetism strength where   //
//    as if they were at range 400, they'd experience normal      //
//    magnetism, and less if they were even closer than that      //
//                                                                //
//-------------------------------5--------------------------------//
//  Aesthetics:                                                   //
//    There's a large number of aesthetic options available in    //
//    this spell, designed to give the user, the maximum amount   //
//    of options                                                  //
//                                                                //
//    Portal Angle: Controls the pitch angle of the portal, 90    //
//    is the upright position, 0 is on it's side                  //
//    and so on                                                   //
//                                                                //
//    Portal scale: Controls the size of the portal, growing      //
//    rates should be 0.00(i) i.e. 0.005 as to not make the       //
//    the portal grow too large 1 == 100%, 0.001 = 1%             //
//                                                                //
//    Portal Height: Controls how high from the terrain height    //
//    the portal is placed, having a low value here will cause    //
//    projectiles to instantly/quickly hit the ground, and units  //
//    will have lower(or possibly no) arc, will also mean more    //
//    units will be successfully caught by the terrain and not    //
//    pulled if you have TerrainMatters set to true, will also    //
//    effect the AOE of the projectiles (lower to the ground      //
//    means tighter spread, higher up means further apart)        //
//                                                                //
//    Portal/Boarder models: Set these to the model paths of the  //
//    models you desire, if you are getting them from the object  //
//    editor, remember to add a "\" to the pathname everywhere    //
//    there is already one, i.e. "path\path\path.mdl"             //
//    needs to be changed to "path\\path\\path.mdl"               //
//                                                                //
//    Boarder scale works the same way the portal scale does      //
//    so just follow the same steps, 0.25 to 0.50 works well for  //
//    boarders                                                    //
//                                                                //
//    the space taken per segment works in a way that 6.00 means  //
//    you will have 6 boarder pieces, setting to something like   //
//    100.00 will mean 100 segments, a number between 5 and 10    //
//    works well here (as to not flood with effects) keep it      //
//    relative to the scale you set up                            //
//                                                                //
//    Boarder height, again, works in the same way as a portal    //
//    height, should be roughly portal height + 50, but, if it    //
//    better suits your portal model, it can theoretically be     //
//    anything without having any impact to the rest of the       //
//    spell                                                       //
//                                                                //
//    Chaos Entity model: same as the other model sets, with      //
//    the filepaths, also consider that this is a projectile so   //
//    you ought to set it to something which'd work as a          //
//    projectile, like prehaps nether drakes, locusts, rockets    //
//    anything really which isn't a building or a ground unit     //
//                                                                //
//    Chaos Entity scale neednot explain how this works a third   //
//    time                                                        //
//                                                                //
//    Chaos Entity Z control, determines how much Z Velocity      //
//    each entity starts with, this in turn controls how far      //
//    out from the middle it goes and respectively how much       //
//    lower from the middle the projectiles go, setting this to   //
//    0 will mean they maintain their height throughout and do    //
//    not go up/down as normal, default is 6.00, playing around   //
//    with this can have unexpected results, to invert the flow   //
//    use a negative value                                        //
//-------------------------------6--------------------------------//
//  Main Damage:                                                  //
//    These controllers are all for the crush damage dealt by     //
//    units being thrown around by the spell, they do -not-       //
//    effect how much damage each entity does.                    //
//                                                                //
//    All of these are relatively self-explanatory, you can deal  //
//    both health and mana damage with these configurables        //
//    damagetypes/weapontypes/attacktypes are set later which     //
//    will control the multiplyers of all these things            //
//                                                                //
//-------------------------------7--------------------------------//
//  Chaos Entity Control:                                         //
//    These controllers are primarily for controlling the number  //
//    of chaos entities and how fast they appear                  //
//                                                                //
//    ChaosEntityCount: these controllers determine how many      //
//    leak through the portal each cycle of creation, having      //
//    a number higher than 45 at the max level as that will       //
//    cause lag on most machines (especially if multicasted       //
//    or other similar spells are around) 15 is the default at    //
//    level 3, anything under 30 is a relatively safe number      //
//                                                                //
//    ChaosEntityAOE: Controls how much area each missile covers  //
//    upon impact, anywhere from 50-120 is realistic, try to      //
//    keep it relative to the missile size (if it's large         //
//    150-200 may be more appropriate)                            //
//                                                                //
//    ChaosEntityRate: How long (in seconds) there is between     //
//    cycles of ChaosEntity leaks, 1-2 seconds works pretty well  //
//    remember to change the channelling duration of the spell    //
//    to match this (the longer the duration, the more cycled     //
//    leaks)                                                      //
//                                                                //
//-------------------------------8--------------------------------//
//  Chaos Entity Damage:                                          //
//     Like the other fairly straight forward, health and mana    //
//     damage, base and per level values, does not effect the     //
//     main damage (unit throwing around damage) at all, each     //
//     projectile individually will have this damage, it is not   //
//     relative to the distance from the projectile               //
//                                                                //
//-------------------------------9--------------------------------//
//  Gravity, terrain and units:                                   //
//    These control optional features and projectile fall arcs    //
//                                                                //
//    Gravity: This is the strength of the terrain gravity which  //
//    causes entities and units to fall at a given rate, higher   //
//    means a stronger gravity and the faster projectiles come    //
//    back down, 20 is Low gravity, negative numbers are          //
//    Antigrav (you will crash the map doing this, so don't)      //
//    60+ is high gravity, as such these will alter the spread    //
//    and AOE of your projectiles, as this is what determines     //
//    how fast they come back down                                //
//                                                                //
//    TerrainMatters: This function poses a question, do you      //
//    want terrain to matter, or do you want units pulled from    //
//    wherever they are, regardless of the terrain height they    //
//    at it by relativity, changing this to true or false will    //
//    not alter projectile destruction when falling, though will  //
//    when they're in the portal (none will be destroyed until    //
//    they start falling) true will let units brace against the   //
//    ground to prevent being pulled, false will mean they can't  //
//                                                                //
//    EffectsUnits: This function poses a different question, do  //
//    you want units effected at all, or do you just want your    //
//    flurry of projectiles to be the only means of damage, if    //
//    you don't want units to be effected, it's suggested you     //
//    lower the projectile interval time (or increase the         //
//    channeling time) and increase the damage &/or AOE of your   //
//    spell to still give it that ultimate-level power, except    //
//    if you don't intend to use this ability as an ultimate      //
//                                                                //
//------------------------------10--------------------------------//
//  Attack, Damage, and Weapon types:                             //
//    These features will determine your spells damage            //
//    multiplyers, you have controls for all three of these       //
//    things                                                      //
//                                                                //
//    However, knowing all of these different types takes quite   //
//    a bit of knowledge, however they are listed here to make    //
//    it easier:                                                  //
//                                                                //
//    Attack types all start with "ATTACK_TYPE_"                  //
//    CHAOS, HERO, MAGIC, MELEE, NORMAL, PIERCE, SIEGE            //
//                                                                //
//    Damage types all start with "DAMAGE_TYPE_"                  //
//    ACID, COLD, DEATH, DEFENSIVE, DEMOLITION, DISEASE, DIVINE   //
//    ENHANCED, FIRE, FORCE, LIGHTNING, MAGIC, MIND, NORMAL       //
//    PLANT, POSION, SHADOW_STRIKE, SLOW_POISON, SONIC            //
//    SPIRIT_LINK, UNIVERSAL, UNKNOWN                             //
//                                                                //
//    Weapon types all start with "WEAPON_TYPE_"                  //
//    Then add one of the following types:                        //
//    AXE, CLAW, METAL, ROCK, WOOD.                               //
//    Then add one of the classifications (note, some  types do   //
//    not have any of these)                                      //
//    HEAVY, MEDIUM, LIGHT                                        //
//    Then add one of these:                                      //
//    CHOP, SLICE, BASH, STAB                                     //
//                                                                //
//    Remember to include underscores "_" between each word       //
//    and if you don't care for weapon types, you can always use  //
//    WEAPON_TYPE_WHOKNOWS, or even better: null                  //
//                                                                //
//-------------------------------11-------------------------------//
//  Unit Indexers:                                                //
//    general unit indexers, neednot include any of the units     //
//    created by this spell, also, due to the high number of      //
//    entities created, intentionally excluding them, may be      //
//    benefiticial to your map.                                   //
//    to disclude these units from any unit indexer you may have  //
//    you can add this condition:                                 //
//                                                                //
//    and (GetUnitTypeId([unit variable]) != CE_DummyId()) then   //
//                                                                //
//    Adding that line to the end of your selection if statement  //
//    should prevent any of these units being added, remember to  //
//    change "[unit variable]" to match whatever variable you     //
//    stored the unit in i.e. TempUnit, Unit, u, U, etc.          //
//    (disclude the square brackets as well)                      //
//                                                                //
//    if you are using this with a GUI unit indexer, then you     //
//    will need to add some additional lines for this to work:    //
//                                                                //
//    Custom Script: set [variable] = CE_DummyId()                //
//    Custom Script: set [variable2] = GetUnitTypeId(unit)        //
//                                                                //
//    then if your if statement, check that those two variables   //
//    are not the same (also, both variables are integers)        //
//                                                                //
//----------------------------------------------------------------//
//                                                                //
//  That concludes the readme for the CHAOS ENVOY spell           //
//  thank you for reading and enjoy the spell                     //
//                                                                //
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
//  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.003
endfunction

constant function CE_PortalGrowthRatePerLevel takes nothing returns real
    return 0.002
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 50.00
endfunction

constant function CE_ChaosEntityHealthDamagePerLevel takes nothing returns real
    return 20.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 get the Z height of locations needed         //
////////////////////////////////////////////////////////////////////
function CE_GetZ takes real x, real y returns real
    call MoveLocation(udg_CE_ZLocation, x, y)
    return (GetLocationZ(udg_CE_ZLocation))
endfunction

////////////////////////////////////////////////////////////////////
//  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

endfunction

////////////////////////////////////////////////////////////////////
//  Function used to move units currently affected by a portal    //
//  while not allowing them outside of map bounds                 //
////////////////////////////////////////////////////////////////////
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

    //Setting the new locations X and Y for this instance
    set x2 = x + udg_CE_XVelocity[index]
    set y2 = y + udg_CE_YVelocity[index]
    //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 ((udg_CE_MapMinX <= x2) and (x2 <= udg_CE_MapMaxX) and (udg_CE_MapMinY <= y2)and (y2 <= udg_CE_MapMaxY)) then
        call SetUnitX(udg_CE_UnitIndex[index], x2)
        call SetUnitY(udg_CE_UnitIndex[index], y2)
    endif
    //Sets the correct fly height
    call SetUnitFlyHeight(udg_CE_UnitIndex[index], udg_CE_CurrentZ[index] - z, 0.00)
  
endfunction

////////////////////////////////////////////////////////////////////
//  Function used to detect if projectiles have crashed into      //
//  the ground and therefore need to either deal damage or be     //
//  damaged depending on what type of unit they are (unit or      //
//  chaos entity)                                                 //
////////////////////////////////////////////////////////////////////
function CE_ProjectileImpactDetection takes real z, real x, real y, integer index returns nothing
    //Creates locals
    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 udg_CE_Portal[index] = null
        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
  
    //Nulls variables
    set u = null
    set pl = null     
endfunction

////////////////////////////////////////////////////////////////////
//  Function used to clear instances of portals (when a portal    //
//  ends or if a new instance is casted when one is already       //
//  active, unit moves, etc.)                                     //
////////////////////////////////////////////////////////////////////
function CE_EndPortal takes unit u returns nothing
    //Creating local
    local integer index = 0
    //Deassociating all the units involves with this unit (will allow units and projectiles to fall)
    loop
        set index = index + 1
        exitwhen index > udg_CE_MaxIndex
          
        //Finds units with association to the eliminator unit (either the caster or the portal)
        if (udg_CE_OriginalCaster[index] == u) then
            set udg_CE_Portal[index] = null
          
            //Finds portal edges
            if (udg_CE_StageID[index] == 7) then
                //Removes those edges
                set udg_CE_StageID[index] = 4
                call DestroyEffect(udg_CE_CurrentEffect[index])
            elseif (udg_CE_StageID[index] != 4) then
                //Everything else
                set udg_CE_StageID[index] = 3
            endif
              
        endif
              
    endloop

endfunction

////////////////////////////////////////////////////////////////////
//  Function used to register new units (projectiles and          //
//  affected units) into the array so that the behave properly    //
////////////////////////////////////////////////////////////////////
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
    set udg_CE_LaunchZ[udg_CE_MaxIndex] = CE_GetZ(x2, y2)
    set udg_CE_TargetZ[udg_CE_MaxIndex] = z
  
    //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]
    set udg_CE_CasterX[udg_CE_MaxIndex] = udg_CE_CasterX[index]
    set udg_CE_CasterY[udg_CE_MaxIndex] = udg_CE_CasterY[index]
                      
    //Sets up the magnetism
    set udg_CE_MagnetismStrength[udg_CE_MaxIndex] = udg_CE_MagnetismStrength[index]
    set udg_CE_CurrentZ[udg_CE_MaxIndex] = udg_CE_LaunchZ[udg_CE_MaxIndex] + GetUnitFlyHeight(u)
    set udg_CE_YVelocity[udg_CE_MaxIndex] = YVel                     
    set udg_CE_XVelocity[udg_CE_MaxIndex] = XVel
    set udg_CE_ZVelocity[udg_CE_MaxIndex] = ZVel
  
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 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
  
    //Loops through all the units within the system
    loop
        set index = index + 1
        exitwhen index > udg_CE_MaxIndex
        set x = GetUnitX(udg_CE_UnitIndex[index])
        set y = GetUnitY(udg_CE_UnitIndex[index])
        
        //Note: Stages are arranged in order of most used (for efficiency)
        //      They are numbered in order of appearence in an instance
        //Finds units which are to be effected by the magnetism
        if (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 z = CE_GetZ(x, y)
            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]) or (GetUnitCurrentOrder(udg_CE_OriginalCaster[index]) != CE_Order()) or (GetUnitX(udg_CE_OriginalCaster[index]) != udg_CE_CasterX[index]) or (GetUnitY(udg_CE_OriginalCaster[index]) != udg_CE_CasterY[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 z = CE_GetZ(x, y)
            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 ((udg_CE_MapMinX <= x) and (x <= udg_CE_MapMaxX) and (udg_CE_MapMinY <= y) and (y <= udg_CE_MapMaxY)) then
                call SetUnitX(udg_CE_UnitIndex[index], x2)
                call SetUnitY(udg_CE_UnitIndex[index], y2)
            endif

            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 are initial portals of an instance
        elseif (udg_CE_StageID[index] == 1) then
            if (GetUnitCurrentOrder(udg_CE_OriginalCaster[index]) != CE_Order())  or (GetUnitX(udg_CE_OriginalCaster[index]) != udg_CE_CasterX[index]) or (GetUnitY(udg_CE_OriginalCaster[index]) != udg_CE_CasterY[index]) then
                set udg_CE_StageID[index] = 4
                call DestroyEffect(udg_CE_CurrentEffect[index])
                call CE_EndPortal(udg_CE_OriginalCaster[index])
            else
                //Initialising data and increasing the portal size
                set z = CE_GetZ(x, y) + CE_PortalHeight()
                set u = udg_CE_UnitIndex[index]
                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_CurrentDeathTimer[udg_CE_MaxIndex] = 0.00
                        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
          
                        //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())

                        //Setting up data of the new magnetised unit
                        call CE_RegisterUnit(index, z, x2, y2, u, 0.00, 0.00, CE_ChaosEntityZControl())

                        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_CurrentDeathTimer[udg_CE_MaxIndex] = 0.00
                            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 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
          
                set udg_CE_CurrentDeathTimer[index] = 0.00
              
                //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_CasterX[index] = udg_CE_CasterX[udg_CE_MaxIndex]
                set udg_CE_CasterY[index] = udg_CE_CasterY[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_CurrentProjectileDelay[index] = udg_CE_CurrentProjectileDelay[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
      
    endloop
  
    //Nulls variables
    set u = 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
    local integer index
    local integer iLevel
    local real rLevel
    local real x
    local real x2
    local real y
    local real y2
    local real Angle
  
    // Checks if the ability casted was the correct one
    if (GetSpellAbilityId() == CE_SpellID()) then
        //Assigning data to locals
        set u = GetTriggerUnit()
        set iLevel = GetUnitAbilityLevel(u, CE_SpellID())
        set rLevel = R2I(iLevel)
        set x = GetSpellTargetX()
        set x2 = GetUnitX(u)
        set y = GetSpellTargetY()
        set y2 = GetUnitY(u)
        set Angle = 0.00
        
        //Ends all previous instances of the spell associated with the unit               
        call CE_EndPortal(u)

        // 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_CasterX[udg_CE_MaxIndex] = x2
        set udg_CE_CasterY[udg_CE_MaxIndex] = y2
        set udg_CE_Portal[udg_CE_MaxIndex] = null
        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_OriginalCaster[udg_CE_MaxIndex] = GetTriggerUnit()
            set udg_CE_CurrentDeathTimer[udg_CE_MaxIndex] = 0.00
            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))
  
    //Sets up the map bounds the spell with use
    set udg_CE_MapMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
    set udg_CE_MapMinX = GetRectMinX(bj_mapInitialPlayableArea)
    set udg_CE_MapMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
    set udg_CE_MapMinY = GetRectMinY(bj_mapInitialPlayableArea)

    //Sets up the Z location finder
    set udg_CE_ZLocation = Location(0,0)
    //Nulls variables
    set CE = null
  
endfunction



Note: kinda jolty/laggy GIF, for the best idea of the spell's appearence, test it yourself in WC3.
124974d1367509744-zephyr-contest-10-what-lies-other-side-chaos-envoy.gif




-=V1.00=-
- Initial Upload
-=V1.01=-
- Exchanged a point with co-ordinates
-=V1.02=-
- Cache'd map bounds
- Changed Location Z finding
- [Removed unused Z2 variable (lol leftovers) brackets to indicate later change though not big enough change to warrant version number change]


Before you come posting any issues you have with the configuration (i.e. you don't want it to effect units, you want to change the gravity properly, etc.) make sure you have read through the entire readme. Thank you.

Enjoy and give credits if you use this spells in your map.

Keywords:
Physics, Galore, Gravity, Well, Throw, Chaos, Portal, Envoy, Entity, Ultimate, Channeling, Black Hole, Twisting, Nether, Death, Crush, Compact, Distor
Contents

Chaos Envoy (Map)

Reviews
10:29, 22nd Jun 2013 PurgeandFire: Nice spell overall. Code looks good, only issue is that z2 seems unused. Approved.

Moderator

M

Moderator

10:29, 22nd Jun 2013
PurgeandFire: Nice spell overall. Code looks good, only issue is that z2 seems unused. Approved.
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
852600 = channel

Cache Map Bounds.

Ah sorry for this very optional thingeh, you can just remove the parentheses in the if(inliner) ex: if someComparison then or if true != false then

you can create an alternative way for GetLocationZ:
JASS:
function GetZ takes real x, real y returns real
    call MoveLocation(udg_ZLoc, x, y)
    return GetLocationZ(udg_ZLoc)
endfunction
make sure to set the udg_ZLoc on start as Location(0,0)
 
852600 = channel

Just makes it more awkward to configure for people and only effects the compile time - no effect ingame

Almia said:
Cache Map Bounds.

Will do

Almia said:
Ah sorry for this very optional thingeh, you can just remove the parentheses in the if(inliner) ex: if someComparison then or if true != false then

Pointless to change, it still compiles to the same thing and is less readable like that

Almia said:
you can create an alternative way for GetLocationZ:
JASS:
function GetZ takes real x, real y returns real
    call MoveLocation(udg_ZLoc, x, y)
    return GetLocationZ(udg_ZLoc)
endfunction
make sure to set the udg_ZLoc on start as Location(0,0)

Will do
 
If you've imported the spell into your own map you need to make sure the configuration has been set up correctly (follow the Readme). Note that the dummy unit you use must have dummy.mdl set as its model or none of the effects work.

beyond that you need to be more specific about what the issue is (i.e. all the units are pulled/projectiles damage but you can't see them, units are pulled but no projectile damage, etc.)
 
Top