////////////////////////////////////////////////////////////////////
// DEVASTATION ENVOY V1.00 //
// //
// Author: Tank-Commander //
// Requires: Dummy.mdl //
// Purpose: Spam-cast spell //
// //
// Notes: //
// - Read the readme before you try modifying the config //
// - Use the "Helpful files" to help you import the spell //
// //
// Credits: //
// - (Dummy.mdl) Vexorian //
// //
// //
// If you have used this spell in your map, you are required //
// to give credits to Tank-Commander for the creation of it //
// If you take a snippet from this code for physics reasons //
// or whatever else, if possible, also give credit for its //
// source origin //
// //
// Importing: Remember to import Dummy.mdl and possibly the //
// object data when importing this spell (just the ability and //
// dummy unit) note that importing the dummy unit object should //
// be done AFTER importing Dummy.mdl, if not, then you will //
// need to set the model of the dummy to Dummy.mdl yourself, if //
// you would like to change what your dummy unit is you can, //
// but it will still need Dummy.mdl for this spell to work //
// If you have problems, make sure you read the readme first //
// and follow it to the best of your abilities before posting //
// comments //
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// README: //
// Before modifying this spell a few things need to be //
// understood and read, this is one of those things, while //
// most modification can be considered intuitive, it still //
// helps to read through these intstructions, as they will //
// inform you about how to configure this spell to your //
// desire. //
//----------------------------------------------------------------//
// Initial importing: The variable creator trigger can be //
// imported first and if you have the correct settings (file, //
// preferences, General, automatically create unknown variables //
// checked, then when you pasta in the variable creator it //
// will automatically give you all the variables you need for //
// this spell //
//----------------------------------------------------------------//
// This configuration is ordered by category of use, and not //
// alphabetically, the ones you're most likely to want to //
// change, are earlier in the readme, the most essential being //
// first. These categories are: //
// //
// - Data Values: The most essential to change, otherwise the //
// spell will simply not function //
// //
// - ChronoKinetic: Fancy word for affecting the flow of time //
// Contains things like the duration of the //
// spell, the Timer speed and Shard Spawn rate //
// //
// - Power: Controls the aspects of the speed of the shards //
// based on the Mass, and Radius of the Portal //
// //
// - Damage: Controls the AOE and damage (health and mana) //
// values each individual Shard has //
// //
// - Aesthetics: Controls the Appearences of the ability - the //
// models used, the scales of those models and //
// so on //
// //
// - Damage Information: Contains things like weapontypes and //
// damage types, etc. //
// //
// - Other Attributes: Contains the world gravity, death timer //
// Height let and the celestial Gravitational //
// constant. //
//----------------------------------------------------------------//
// DATA VALUES //
//----------------------------------------------------------------//
// Dummy ID: This is the raw data of the dummy unit, to see //
// raw data in the object editor, press Ctrl + D, doing this //
// again will switch it back, if you want to change this dummy //
// unit, follow as displayed (use the first 4 characters in //
// the raw data and put them in ' markers) //
constant function DE_DummyID takes nothing returns integer
return 'u000'
endfunction
//----------------------------------------------------------------//
// Spell ID: This is done in the same manner as the Dummy ID //
// except that this time, you're doing it with ability raw //
// data, see the dummy unit if you do not know already how to //
// view raw data //
constant function DE_SpellID takes nothing returns integer
return 'A000'
endfunction
//----------------------------------------------------------------//
// CHRONOKINETIC //
//----------------------------------------------------------------//
// Timer Speed: The default for this is 0.03, it determines how //
// many times per second these triggers are ran, normally you //
// want to leave this at 0.03, but 0.04 and prehaps 0.05 //
// would be good options if you computer lags a bit. //
constant function DE_TimerSpeed takes nothing returns real
return 0.03
endfunction
//----------------------------------------------------------------//
// Duration Base: Determines how long each cast will last as a //
// base value - this is to help give better control when //
// scaling abilities while not having to change values for each //
// level, cutting out a lot of configuration time, the value is //
// in seconds (1.00 = 1second) //
constant function DE_DurationBase takes nothing returns real
return 1.00
endfunction
//----------------------------------------------------------------//
// Duration Per Level: Deter,omes jpw ;pmg eacj casy wo;; as a //
// per level value - at level one this will be applied once, //
// twice at level two and so forth, it is added on to the base //
// value to come to the actual duration of the spell instance //
constant function DE_DurationPerLevel takes nothing returns real
return 0.50
endfunction
//----------------------------------------------------------------//
// Spawn Rate Base: A base value, this controls how many //
// seconds there are between each Shard being created, if this //
// is the same or lower (the sum total of the Base and Per //
// Level) is lower or equal to the timer speed, then one Shard //
// will be made every Timer Speed seconds (Time is a decimal //
// value, 0.5 is half a second) //
constant function DE_SpawnRateBase takes nothing returns real
return 0.15
endfunction
//----------------------------------------------------------------//
// Spawn Rate Per Level: The other part to the spawn rate //
// remember that it's a decimal value and the lower it is, the //
// faster Shards are created, so for this per level you'll //
// normally either want a negative value, or 0.00, though you //
// are not limited to such values //
constant function DE_SpawnRatePerLevel takes nothing returns real
return -0.03
endfunction
//----------------------------------------------------------------//
// POWER //
//----------------------------------------------------------------//
// Radius Base: This Base value determines how far out from the //
// center the shards are created, it also affects the gravity //
// strength of the Portal - the smaller the radius in relation //
// to it's Mass, the higher the gravitational effect and the //
// more volatile the Shards will be //
constant function DE_RadiusBase takes nothing returns real
return 100.00
endfunction
//----------------------------------------------------------------//
// Radius Per Level: The per level component to the Radius, //
// works the same all the other per level factors, giving this //
// a negative value will make your Portal smaller but more //
// volatile each level, and a positive value will make it large //
// and more stable //
constant function DE_RadiusPerLevel takes nothing returns real
return 0.00
endfunction
//----------------------------------------------------------------//
// Mass Base: the Mass within the Portal, the main strength of //
// the gravitational pull, larger numbers will decrease //
// stability and increase the speed the Shards move, lowering //
// it makes it more stable, but unlike the Radius, it does not //
// affect the size of your Portal, works well for a baseline //
// when testing different levels of instability or stability //
// when getting your preferences for the spell //
constant function DE_MassBase takes nothing returns real
return 800.00
endfunction
//----------------------------------------------------------------//
// Mass Per Level: the Per level component of the Mass can make //
// the spell more stable or volatile as it levels up without //
// changing it's size, remember that it is applied once at level //
// one, so the values 800 and 400 (the defaults) yeild 1200 //
// Mass at level one //
constant function DE_MassPerLevel takes nothing returns real
return 400.00
endfunction
//----------------------------------------------------------------//
// DAMAGE //
//----------------------------------------------------------------//
// Shard AOE Base: Determines the area of effect of the shards //
// 90 is melee range, 40 is directly on top, 20 is probably too //
// small an area to work and 400 to large, try different values //
// and see what you like //
constant function DE_ShardAOEBase takes nothing returns real
return 90.00
endfunction
//----------------------------------------------------------------//
// Shard AEO Per Level: Normally not used, but here for your //
// preferences, allows you to adjust the area of effect of your //
// shards as they level up, normally only making the area larger //
// makes logical sense, or not changing it at all //
constant function DE_ShardAOEPerLevel takes nothing returns real
return 0.00
endfunction
//----------------------------------------------------------------//
// Health Damage Base: This is the damage the spell deals to //
// all the units within the AOE on impact with a shard, you'll //
// want to make this fairly relative to the number of shards //
// you have, 75 shards with 100 damage each is 7500 damage in //
// one cast of the spell - that's a lot of potential damage in //
// a spell which has no cooldown by default, note that this //
// damage is not true damage - enemies will have their armour //
// applied and reduce this damage based on their armour type //
// vs your damage type //
constant function DE_HealthDamageBase takes nothing returns real
return 75.00
endfunction
//----------------------------------------------------------------//
// Health Damage Per Level: For changing the amount of damage //
// you want to deal with each shard as you level up, normally //
// this is your main source of increased damage as the spell //
// levels up rather than the other factors, it makes little //
// sense to not have this as a positive value of some number //
// (25% of your total level 1 damage seems like a good number, //
// i.e. if your combined level one damage is 100, roughly 25 of //
// that damage should probably be coming from this per level //
// value //
constant function DE_HealthDamagePerLevel takes nothing returns real
return 25.00
endfunction
//----------------------------------------------------------------//
// Mana Damage Base: Unlike Health damage the mana damage is //
// true damage - no matter how much armour they have, exactly //
// these values will be subtracted from their mana, normally //
// this is 0 as mana damage is mostly useless except vs certain //
// enemies, but it's still good to have the option to be able //
// to have it if you want //
constant function DE_ManaDamageBase takes nothing returns real
return 0.00
endfunction
//----------------------------------------------------------------//
// Mana Damage Per Level: Per level component of the normally //
// disused mana damage, not any real sense in having a below 0 //
// amount here, since it'll only make it weaker, like the //
// health damage I suggest this to be 25% of your total mana //
// damage of your level 1 version //
constant function DE_ManaDamagePerLevel takes nothing returns real
return 0.00
endfunction
//----------------------------------------------------------------//
// AESTHETICS //
//----------------------------------------------------------------//
// Portal Model: This determines the model used for your //
// main portal, you want to use the model path and paste it //
// into the double quotes or " markers, if the path has only //
// single slashes (\) you'll need to changeb it to double slash //
// (\\) before you save, the spell will not work if you do not //
// do this (if you acidentally save with the single slash (\) //
// it will still save but you may find yourself having a //
// lingering Progress bar at full percentage, you can ignore it //
// for the most part, but if you have it, you probably haven't //
// entered this field correctly. Get the model paths from the //
// Object editor - find the model you want (the model, not the //
// unit, in the models list, select it and hit enter twice, //
// then select the path (will look similar to this default //
// value, and paste in it here) I suggest doing this with a //
// unit of no value (changing the model to get the model path) //
// and then reset the field afterwards to get the unit back to //
// normal //
constant function DE_PortalModel takes nothing returns string
return "Abilities\\Weapons\\WitchDoctorMissile\\WitchDoctorMissile.mdl"
endfunction
//----------------------------------------------------------------//
// Shard Model: The model used for your individual shards, //
// follow the steps in the "Portal Model" section if you need //
// information on how to change these values successfully //
constant function DE_ShardModel takes nothing returns string
return "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"
endfunction
//----------------------------------------------------------------//
// Impact Model: The model used for your individual shards, //
// follow the steps in the "Portal Model" section if you need //
// information on how to change these values successfully //
constant function DE_ImpactModel takes nothing returns string
return "Abilities\\Weapons\\SteamTank\\SteamTankImpact.mdl"
endfunction
//----------------------------------------------------------------//
// Attachment Point: This determines where on the unit the //
// model is placed, "origin", "chest", "head", "overhead" are //
// all good places to put the model, switch them around to see //
// which you prefer the most, "foot" and "hand" are less so as //
// they're offsetted from the center //
constant function DE_AttachmentPoint takes nothing returns string
return "origin"
endfunction
//----------------------------------------------------------------//
// Portal Height Base: This is how height the portal is off the //
// floor (it is added onto the terrain Z) you'll want it a good //
// distance off the ground (unles you want Shards to smack into //
// the ground while the spell is still going off, which is a //
// viable thing to do for this spell) but not so high as to //
// send the Shards halfway across the map, 400 is default //
constant function DE_PortalHeightBase takes nothing returns real
return 400.00
endfunction
//----------------------------------------------------------------//
// Portal Height Per Level: The per level for the height of the //
// portal, generally this'll be set at 0 as the spell changes //
// more on functionality, than on effectiveness depending on //
// height - so changing this value as it levels up will not //
// necessarily make it any stronger or weaker //
constant function DE_PortalHeightPerLevel takes nothing returns real
return 0.00
endfunction
//----------------------------------------------------------------//
// Portal Scale Base: this is the scale of the portal model //
// it's a decimal percentage (1.00 = 100%) as the largest part //
// of the spell you'll normally want this at, at least 100% //
// depending on the model, generally a good idea to try to line //
// it up with your portal radius as to get the best effect out //
// of it //
constant function DE_PortalScaleBase takes nothing returns real
return 2.00
endfunction
//----------------------------------------------------------------//
// Portal Scale Per Level: Used for changing the portal scale //
// as it levels up - good in combination with radius change per //
// level as to stay correct relatively //
constant function DE_PortalScalePerLevel takes nothing returns real
return 1.00
endfunction
//----------------------------------------------------------------//
// Shard Scale Base: Scales the Shards that are created by the //
// portal, normally you'll want them significantly smaller that //
// the portal 10% (0.10) is a good size, but for some models a //
// bit bigger might be good, be sure to play around with this //
// to get the size you want and looks best in your opinion //
constant function DE_ShardScaleBase takes nothing returns real
return 0.10
endfunction
//----------------------------------------------------------------//
// Shard Scale Per Level: Also for use with making the portal //
// seem relatively the same size as it levels up - or simply //
// to make them bigger to show increased AOE, Damage, more or //
// less to show anything about the spell being stronger as it //
// levels up and becomes more powerful //
constant function DE_ShardScalePerLevel takes nothing returns real
return 0.00
endfunction
//----------------------------------------------------------------//
// DAMAGE INFORMATION //
//----------------------------------------------------------------//
// Damage Type: These determine the damagetypes, changing this //
// will modify the damage multiplyers vs certain enemies //
// the standard is DAMAGE_TYPE_MAGIC, note that this spell //
// automatically discludes magic immunes, so changing this //
// damage type will not make them start taking damage //
constant function DE_AttackType takes nothing returns attacktype
return ATTACK_TYPE_MAGIC
endfunction
//----------------------------------------------------------------//
// Attack Type: This is very much so basically the same as //
// Damage Type, generally you'll want this to match with it //
// as such the default is ATTACK_TYPE_MAGIC, though Damagetype //
// is a key factor for determining bonuses rather than this //
// but unlike weapontype, you cannot have null as a setting //
constant function DE_DamageType takes nothing returns damagetype
return DAMAGE_TYPE_MAGIC
endfunction
//----------------------------------------------------------------//
// Weapon Type: This alters what kind of weapon type is used by //
// the spell, those without knowledge of weapontypes don't //
// worry, you're not missing much, this spell doesn't really //
// use it, hence the default of null, but if you want to use //
// them, no reason to not. //
constant function DE_WeaponType takes nothing returns weapontype
return null
endfunction
//----------------------------------------------------------------//
// OTHER ATTRIBUTES //
//----------------------------------------------------------------//
// Gravity: Determines the worldly gravity strength used to //
// pull the shards back to the ground after they have been //
// freed from the portal, having a lower gravity increases the //
// spread range, higher lowers it, the default is 1/8 of the //
// earthly gravity of 9.81, beng 1.22625 //
constant function DE_Gravity takes nothing returns real
return 1.22625
endfunction
//----------------------------------------------------------------//
// Gravitational Constant: This is the constant reprisented by //
// G in Celestial Physics and Mechanics. Normally it's //
// 6.67384 x 10^-11 N (m/kg)^2 but for Warcraft purposes I //
// cranked it up a bit, (x 10^11 to be exact) changing it may //
// yeild interesting results, but I take no responcibility if //
// you do something silly and crash the game by making it //
// really high //
constant function DE_GravitationalConstant takes nothing returns real
return 6.67384
endfunction
//----------------------------------------------------------------//
// Height Let: This is a small let so that projectiles nearly //
// touching the floor, will be treated as actually touching it //
// This is to prevent graphical errors because models cannot //
// sink into the floor by reducing their fly height //
// 5 is default 10 is probably the max you can reasonably give //
// this //
constant function DE_HeightLet takes nothing returns real
return 5.00
endfunction
//----------------------------------------------------------------//
// Death Timer: Determines how long after the death of a dummy //
// will it be removed from the game completely, this is so //
// death effects, if any can finish playing before the unit is //
// removed, 1.8 is default, 2 is probably excessive and in some //
// cases it's possible that 1 could be too little //
constant function DE_DeathTimer takes nothing returns real
return 1.80
endfunction
//----------------------------------------------------------------//
// You have now reached the end of the configuration, below are //
// the functions used to run the spell, beyond this point if //
// you find any constant values (indicated in Blue like the //
// other constants here if you have standard syntax highlighting //
// they're there for a reason and don't fiddle with them, to //
// actually make any modifications I hope you're an experienced //
// programmer, though do not hassle for help because I don't //
// take responcibility for other people's programming skills //
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function used for finding the Z height of a location, since //
// it cannot be done with co-ordinates, a recycled location is //
// used constantly. //
////////////////////////////////////////////////////////////////////
function DE_GetZ takes real x, real y returns real
//Gets the location Z of the selected location
call MoveLocation(udg_DE_ZLoc, x, y)
return GetLocationZ(udg_DE_ZLoc)
endfunction
////////////////////////////////////////////////////////////////////
// Target filter function - passed units and players and checks //
// if the unit is allowed to be targetted by this spell //
////////////////////////////////////////////////////////////////////
function DE_TargetFilter takes unit u, player pl returns boolean
//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) != DE_DummyID()) and (not IsUnitType(u, UNIT_TYPE_DEAD)) then
return true
endif
return false
endfunction
////////////////////////////////////////////////////////////////////
// Function for running the main parts of the spell, creates //
// new shards and destroys old portals, and does all the //
// recycling and damaging of targets, as well as shard movement //
////////////////////////////////////////////////////////////////////
function DE_Loop takes nothing returns nothing
//Sets up all the locals needed for this section
local integer TempInt = 0
local integer TempInt2 = 0
local integer TempNode = 0
local integer Node = 0
local real Angle
local real Angle2
local real Distance
local real x
local real x2
local real dx
local real y
local real y2
local real dy
local real z
local unit u
local player pl
loop
//Moves to the next node
set TempInt = TempInt + 1
exitwhen TempInt > udg_DE_SpellCounter
set Node = udg_DE_NextNode[Node]
if (udg_DE_StageID[Node] == 2) then
//Initialises data required for movement
set x = GetUnitX(udg_DE_Unit[Node])
set y = GetUnitY(udg_DE_Unit[Node])
set udg_DE_CurrentZ[Node] = udg_DE_CurrentZ[Node] + udg_DE_ZVelocity[Node]
set z = DE_GetZ(x, y)
set dy = udg_DE_PortalY[Node] - y
set dx = udg_DE_PortalX[Node] - x
set Angle = Atan2(dy, dx)
set Angle2 = Atan2(udg_DE_PortalZ[Node] - udg_DE_CurrentZ[Node], SquareRoot(dx * dx + dy * dy))
//Checks if the projectile has crashed
if (udg_DE_CurrentZ[Node] - z < DE_HeightLet()) then
//Yes it crashed, deassociating the unit
set udg_DE_StageID[Node] = 3
set pl = GetOwningPlayer(udg_DE_OriginalCaster[Node])
call DestroyEffect(udg_DE_CurrentEffect[Node])
call DestroyEffect(AddSpecialEffect(DE_ImpactModel(), x, y))
//Select Units to damage
call GroupEnumUnitsInRange(udg_DE_TempGroup, x, y, udg_DE_ShardAOE[Node], null)
loop
//Scanning through
set u = FirstOfGroup(udg_DE_TempGroup)
exitwhen u == null
//Select all the units which are to be damaged
if DE_TargetFilter(u, pl) then
//Dealing health and mana damage
call UnitDamageTarget(udg_DE_OriginalCaster[Node], u, udg_DE_HealthDamage[Node], true, false, DE_AttackType(), DE_DamageType(), DE_WeaponType())
call SetUnitState(u, UNIT_STATE_MANA, (GetUnitState(u,UNIT_STATE_MANA) - udg_DE_ManaDamage[Node]))
endif
//Remove the unit from the unit group
call GroupRemoveUnit(udg_DE_TempGroup, u)
endloop
//Removes the projectile
call KillUnit(udg_DE_Unit[Node])
//Nulls variables
set u = null
set pl = null
else
//Setting the new locations X and Y for this instance
set x2 = x + udg_DE_XVelocity[Node]
set y2 = y + udg_DE_YVelocity[Node]
if (IsUnitInGroup(udg_DE_Unit[Node], udg_DE_GravitatedShard)) then
//Calculating the new velocities (will be used next time this runs)
set udg_DE_ZVelocity[Node] = udg_DE_ZVelocity[Node] + udg_DE_BaseVelocity[Node] * Sin(Angle2)
set udg_DE_XVelocity[Node] = udg_DE_XVelocity[Node] + udg_DE_BaseVelocity[Node] * Cos(Angle) * Cos(Angle2)
set udg_DE_YVelocity[Node] = udg_DE_YVelocity[Node] + udg_DE_BaseVelocity[Node] * Sin(Angle) * Cos(Angle2)
else
set udg_DE_ZVelocity[Node] = udg_DE_ZVelocity[Node] - DE_Gravity()
endif
//Makes sure the new location is within the map bounds
if ((udg_DE_MapMinX <= x2) and (x2 <= udg_DE_MapMaxX) and (udg_DE_MapMinY <= y2)and (y2 <= udg_DE_MapMaxY)) then
call SetUnitX(udg_DE_Unit[Node], x2)
call SetUnitY(udg_DE_Unit[Node], y2)
endif
//Sets the correct fly height
call SetUnitFlyHeight(udg_DE_Unit[Node], udg_DE_CurrentZ[Node] - z, 0.00)
endif
elseif (udg_DE_StageID[Node] == 1) then
//Increases the duration of both artificial wait timers
set udg_DE_CurrentShardDelay[Node] = udg_DE_CurrentShardDelay[Node] + DE_TimerSpeed()
set udg_DE_CurrentDuration[Node] = udg_DE_CurrentDuration[Node] + DE_TimerSpeed()
//Checks if the spell has ran out of duration
if(udg_DE_CurrentDuration[Node] >= udg_DE_Duration[Node]) then
set udg_DE_StageID[Node] = 3
call DestroyEffect(udg_DE_CurrentEffect[Node])
//Finds all the affected Shards and releases them
loop
set TempInt2 = TempInt2 + 1
exitwhen TempInt2 > udg_DE_SpellCounter
set TempNode = udg_DE_NextNode[TempNode]
if (udg_DE_Portal[TempNode] == udg_DE_Unit[Node]) then
call GroupRemoveUnit (udg_DE_GravitatedShard, udg_DE_Unit[TempNode])
endif
endloop
//Checks if it's time to make a new shard
elseif (udg_DE_CurrentShardDelay[Node] >= udg_DE_SpawnRate[Node]) then
//Resets the timer
set udg_DE_CurrentShardDelay[Node] = 0.00
//Sets up a random place to put the new Shard
set Angle = GetRandomReal(0, 360)
set Angle2 = GetRandomReal(0, 180)
set Distance = Cos(Angle2) * udg_DE_Radius[Node]
if (Distance < 0) then
set Distance = Distance * -1
endif
set udg_DE_SpellCounter = udg_DE_SpellCounter + 1
set x = udg_DE_PortalX[Node] + Distance * Cos(Angle * bj_DEGTORAD)
set y = udg_DE_PortalY[Node] + Distance * Sin(Angle * bj_DEGTORAD)
set z = Sin(Angle2) * udg_DE_Radius[Node] + udg_DE_PortalZ[Node]
//Checking for recycleable Nodes
if (udg_DE_RecycleableNodes == 0) then
set udg_DE_NodeNumber = udg_DE_NodeNumber + 1
set TempNode = udg_DE_NodeNumber
else
set udg_DE_RecycleableNodes = udg_DE_RecycleableNodes - 1
set TempNode = udg_DE_RecycleNodes[udg_DE_RecycleableNodes]
endif
//Sets up this Node
set udg_DE_NextNode[TempNode] = 0
set udg_DE_NextNode[udg_DE_LastNode] = TempNode
set udg_DE_PrevNode[TempNode] = udg_DE_LastNode
set udg_DE_LastNode = TempNode
//Sets up the data for the Shard
set udg_DE_HealthDamage[TempNode] = udg_DE_HealthDamage[Node]
set udg_DE_ManaDamage[TempNode] = udg_DE_ManaDamage[Node]
set udg_DE_Portal[TempNode] = udg_DE_Unit[Node]
set udg_DE_PortalX[TempNode] = udg_DE_PortalX[Node]
set udg_DE_PortalY[TempNode] = udg_DE_PortalY[Node]
set udg_DE_PortalZ[TempNode] = udg_DE_PortalZ[Node]
set udg_DE_ShardAOE[TempNode] = udg_DE_ShardAOE[Node]
set udg_DE_OriginalCaster[TempNode] = udg_DE_OriginalCaster[Node]
set udg_DE_BaseVelocity[TempNode] = udg_DE_BaseVelocity[Node]
set udg_DE_CurrentZ[TempNode] = z
set udg_DE_StageID[TempNode] = 2
//Sets up initialisation Velocities (this is to give the shards a bit of a kick of instability in their orbit)
set udg_DE_ZVelocity[TempNode] = udg_DE_BaseVelocity[TempNode] * Sin(Angle2)
set udg_DE_XVelocity[TempNode] = udg_DE_BaseVelocity[TempNode] * Cos(Angle) * Cos(Angle2)
set udg_DE_YVelocity[TempNode] = udg_DE_BaseVelocity[TempNode] * Sin(Angle) * Cos(Angle2)
//Creates the unit and applies Aesthetics
set udg_DE_Unit[TempNode] = CreateUnit(Player(14), DE_DummyID(), x, y, 0.00)
if UnitAddAbility(udg_DE_Unit[TempNode], 'Amrf') and UnitRemoveAbility(udg_DE_Unit[TempNode], 'Amrf') then
endif
set udg_DE_CurrentEffect[TempNode] = AddSpecialEffectTarget(DE_ShardModel(), udg_DE_Unit[TempNode], DE_AttachmentPoint())
call SetUnitScale(udg_DE_Unit[TempNode], udg_DE_ShardScale[Node], 0.00, 0.00)
call SetUnitFlyHeight(udg_DE_Unit[TempNode], z, 0.00)
//Adds them to the group of Gravitated Shards
call GroupAddUnit(udg_DE_GravitatedShard, udg_DE_Unit[TempNode])
endif
elseif (udg_DE_CurrentDeathTimer[Node] < DE_DeathTimer()) then
set udg_DE_CurrentDeathTimer[Node] = 0.00
//Removes the projectile
call RemoveUnit(udg_DE_Unit[Node])
if (udg_DE_LastNode == Node) then
set udg_DE_LastNode = udg_DE_PrevNode[Node]
endif
//Recycles the node
set udg_DE_RecycleNodes[udg_DE_RecycleableNodes] = Node
set udg_DE_RecycleableNodes = udg_DE_RecycleableNodes + 1
set udg_DE_NextNode[udg_DE_PrevNode[Node]] = udg_DE_NextNode[Node]
set udg_DE_PrevNode[udg_DE_NextNode[Node]] = udg_DE_PrevNode[Node]
set udg_DE_SpellCounter = udg_DE_SpellCounter - 1
set TempInt = TempInt - 1
//Destroys the timer when not in use
if (udg_DE_SpellCounter == 0) then
call DestroyTimer(GetExpiredTimer())
endif
else
set udg_DE_CurrentDeathTimer[Node] = udg_DE_CurrentDeathTimer[Node] + DE_TimerSpeed()
endif
endloop
endfunction
////////////////////////////////////////////////////////////////////
// Function runs when a new instance is to be created - runs //
// as a condition but always returns false, creates a new //
// portal if the correct spell was cast //
////////////////////////////////////////////////////////////////////
function DE_NewInstance takes nothing returns boolean
//Sets up locals
local unit u
local integer Node
local real rLevel
local real x
local real y
//Checks if the spell cast is the correct spell
if (GetSpellAbilityId() == DE_SpellID()) then
set u = GetTriggerUnit()
set x = GetSpellTargetX()
set y = GetSpellTargetY()
set rLevel = I2R(GetUnitAbilityLevel(u, DE_SpellID()))
//Checking for recycleable Nodes
if (udg_DE_RecycleableNodes == 0) then
set udg_DE_NodeNumber = udg_DE_NodeNumber + 1
set Node = udg_DE_NodeNumber
else
set udg_DE_RecycleableNodes = udg_DE_RecycleableNodes - 1
set Node = udg_DE_RecycleNodes[udg_DE_RecycleableNodes]
endif
//Sets up this Node
set udg_DE_NextNode[Node] = 0
set udg_DE_NextNode[udg_DE_LastNode] = Node
set udg_DE_PrevNode[Node] = udg_DE_LastNode
set udg_DE_LastNode = Node
//Sets up the portal data
set udg_DE_PortalHeight[Node] = DE_PortalHeightBase() + (DE_PortalHeightPerLevel() * rLevel)
set udg_DE_Mass[Node] = DE_MassBase() + (DE_MassPerLevel() * rLevel)
set udg_DE_Radius[Node] = DE_RadiusBase() + (DE_RadiusPerLevel() * rLevel)
set udg_DE_BaseVelocity[Node] = ((DE_GravitationalConstant() * udg_DE_Mass[Node]) / udg_DE_Radius[Node]) * DE_TimerSpeed()
set udg_DE_HealthDamage[Node] = DE_HealthDamageBase() + (DE_HealthDamagePerLevel() * rLevel)
set udg_DE_ManaDamage[Node] = DE_ManaDamageBase() + (DE_ManaDamagePerLevel() * rLevel)
set udg_DE_SpawnRate[Node] = DE_SpawnRateBase() + (DE_SpawnRatePerLevel() * rLevel)
set udg_DE_Duration[Node] = DE_DurationBase() + (DE_DurationPerLevel() * rLevel)
set udg_DE_ShardScale[Node] = DE_ShardScaleBase() + (DE_ShardScalePerLevel() * rLevel)
set udg_DE_ShardAOE[Node] = DE_ShardAOEBase() + (DE_ShardAOEPerLevel() * rLevel)
set udg_DE_PortalX[Node] = x
set udg_DE_PortalY[Node] = y
set udg_DE_PortalZ[Node] = udg_DE_PortalHeight[Node] + DE_GetZ(x, y)
set udg_DE_CurrentShardDelay[Node] = 0.00
set udg_DE_CurrentDuration[Node] = 0.00
set udg_DE_OriginalCaster[Node] = u
set udg_DE_StageID[Node] = 1
set udg_DE_SpellCounter = udg_DE_SpellCounter + 1
//Creates the unit and applies Aesthetics
set udg_DE_Unit[Node] = CreateUnit(Player(14), DE_DummyID(), x, y, 0.00)
if UnitAddAbility(udg_DE_Unit[Node], 'Amrf') and UnitRemoveAbility(udg_DE_Unit[Node], 'Amrf') then
endif
set udg_DE_CurrentEffect[Node] = AddSpecialEffectTarget(DE_PortalModel(), udg_DE_Unit[Node], DE_AttachmentPoint())
call SetUnitScale(udg_DE_Unit[Node], DE_PortalScaleBase() + (DE_PortalScalePerLevel() * rLevel), 0.00, 0.00)
call SetUnitFlyHeight(udg_DE_Unit[Node], udg_DE_PortalHeight[Node], 0.00)
//Checks if it's the only portal on the map
if (udg_DE_SpellCounter == 1) then
call TimerStart(CreateTimer(), DE_TimerSpeed(), true, function DE_Loop)
endif
//Nulls variables
set u = null
endif
return false
endfunction
////////////////////////////////////////////////////////////////////
// Function for setting up the other functions and initialising //
// the map bounds variables and Z finder for locations //
////////////////////////////////////////////////////////////////////
function InitTrig_DE_DevastationEnvoy takes nothing returns nothing
//Sets up locals
local trigger DE = CreateTrigger()
local integer index = 0
//Initialise the event for every player
loop
call TriggerRegisterPlayerUnitEvent(DE, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(DE, Condition(function DE_NewInstance))
//Sets up the map bounds the spell with use
set udg_DE_MapMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
set udg_DE_MapMinX = GetRectMinX(bj_mapInitialPlayableArea)
set udg_DE_MapMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
set udg_DE_MapMinY = GetRectMinY(bj_mapInitialPlayableArea)
//Sets up the Z location finder
set udg_DE_ZLoc = Location(0,0)
//Nulls variables
set DE = null
endfunction
////////////////////////////////////////////////////////////////////
// End of the spell //
////////////////////////////////////////////////////////////////////