units that goes near to the summoning area will be sucked slowly
////////////////////////////////////////////////////////////////////
// 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 identify targets for the magnetism or //
// damage of the spell depanding on what the current stage is //
////////////////////////////////////////////////////////////////////
function CE_TargetFilter takes unit u, player pl returns nothing
//Checks if the unit can be used as a target
if (IsUnitType(u, UNIT_TYPE_GROUND)) and (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)) and (IsUnitEnemy(u, pl)) and (GetUnitTypeId(u) != CE_DummyID()) and (not IsUnitInGroup(u, udg_CE_EffectedUnits)) and (not IsUnitType(u, UNIT_TYPE_DEAD)) then
call GroupAddUnit(udg_CE_TempGroup, u)
endif
//Nulling variables
set u = null
set pl = null
endfunction
////////////////////////////////////////////////////////////////////
// Function 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
//Creates locals
local location p
//Setting the new locations X and Y for this instance
set x2 = x + udg_CE_XVelocity[index]
set y2 = y + udg_CE_YVelocity[index]
set p = Location(x2,y2)
//Calculating the new velocities (will be used next time this runs)
set udg_CE_ZVelocity[index] = udg_CE_ZVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Sin(Angle2)
set udg_CE_XVelocity[index] = udg_CE_XVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Cos(Angle) * Cos(Angle2)
set udg_CE_YVelocity[index] = udg_CE_YVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Sin(Angle) * Cos(Angle2)
//Makes sure the new location is within the map bounds
if ((GetRectMinX(bj_mapInitialPlayableArea) <= GetLocationX(p)) and (GetLocationX(p) <= GetRectMaxX(bj_mapInitialPlayableArea)) and (GetRectMinY(bj_mapInitialPlayableArea) <= GetLocationY(p)) and (GetLocationY(p) <= GetRectMaxY(bj_mapInitialPlayableArea))) then
call SetUnitX(udg_CE_UnitIndex[index], x2)
call SetUnitY(udg_CE_UnitIndex[index], y2)
endif
//Removes the location
call RemoveLocation(p)
//Sets the correct fly height
call SetUnitFlyHeight(udg_CE_UnitIndex[index], udg_CE_CurrentZ[index] - z, 0.00)
//Nulling the variable
set p = null
endfunction
////////////////////////////////////////////////////////////////////
// Function 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
//Nulling variables
set u = null
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
local location p2
set p2 = Location(x2, y2)
set udg_CE_LaunchZ[udg_CE_MaxIndex] = GetLocationZ(p2)
set udg_CE_TargetZ[udg_CE_MaxIndex] = z
call RemoveLocation(p2)
//Sets up data for caster and portal it's being pulled into
set udg_CE_OriginalCaster[udg_CE_MaxIndex] = udg_CE_OriginalCaster[index]
set udg_CE_Portal[udg_CE_MaxIndex] = udg_CE_UnitIndex[index]
set udg_CE_AOE[udg_CE_MaxIndex] = udg_CE_AOE[index]
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] = GetUnitFlyHeight(u) + udg_CE_LaunchZ[udg_CE_MaxIndex]
set udg_CE_YVelocity[udg_CE_MaxIndex] = YVel
set udg_CE_XVelocity[udg_CE_MaxIndex] = XVel
set udg_CE_ZVelocity[udg_CE_MaxIndex] = ZVel
//Nulls variables
set u = null
set p2 = null
endfunction
////////////////////////////////////////////////////////////////////
// Main looping function, controls things from the magnetism //
// of the portal to the damage and projectile control within //
// the Chaos Rip //
////////////////////////////////////////////////////////////////////
function CE_Loop takes nothing returns nothing
//Setting up the local variables
local integer index = 0
local integer secondaryindex = 0
local real x
local real x2
local real y
local real y2
local real z
local real z2
local real dx
local real dy
local real Dist
local real Angle
local real Angle2
local real Magnetism
local real Radian
local player pl
local unit u
local location p
//Loops through all the units within the system
loop
set index = index + 1
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 p = Location(x, y)
set z = GetLocationZ(p)
call RemoveLocation(p)
set dy = y2 - y
set dx = x2 - x
set Dist = SquareRoot(dx * dx + dy * dy)
set Angle = Atan2(dy, dx)
set Angle2 = Atan2(udg_CE_TargetZ[index] - udg_CE_CurrentZ[index], Dist)
set Radian = SquareRoot((dx * dx) + (dy * dy) + (udg_CE_TargetZ[index] - udg_CE_CurrentZ[index]) * (udg_CE_TargetZ[index] - udg_CE_CurrentZ[index]))
//Calculates the magnetism strength for this instance
set Magnetism = udg_CE_MagnetismStrength[index] * (Dist / CE_MagnetismDecay())
if (Dist > udg_CE_AOE[index]) 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 p = Location(x, y)
set z = GetLocationZ(p)
set x2 = x + udg_CE_XVelocity[index]
set y2 = y + udg_CE_YVelocity[index]
set udg_CE_ZVelocity[index] = udg_CE_ZVelocity[index] - CE_Gravity()
set udg_CE_CurrentZ[index] = udg_CE_CurrentZ[index] + udg_CE_ZVelocity[index]
//Makes sure the projectile or unit does not leave the map bounds (may look a bit odd but is necessary)
if ((GetRectMinX(bj_mapInitialPlayableArea) <= GetLocationX(p)) and (GetLocationX(p) <= GetRectMaxX(bj_mapInitialPlayableArea)) and (GetRectMinY(bj_mapInitialPlayableArea) <= GetLocationY(p)) and (GetLocationY(p) <= GetRectMaxY(bj_mapInitialPlayableArea))) then
call SetUnitX(udg_CE_UnitIndex[index], x2)
call SetUnitY(udg_CE_UnitIndex[index], y2)
endif
call RemoveLocation(p)
call SetUnitFlyHeight(udg_CE_UnitIndex[index], udg_CE_CurrentZ[index] - z, 0.00)
call CE_ProjectileImpactDetection(z, x, y, index)
set Angle = Atan2(y2 - y, x2 - x)
if (GetUnitTypeId(udg_CE_UnitIndex[index]) == CE_DummyID()) then
call SetUnitAnimationByIndex(udg_CE_UnitIndex[index], R2I(Atan2(udg_CE_ZVelocity[index], SquareRoot((udg_CE_XVelocity[index] * udg_CE_XVelocity[index]) + (udg_CE_YVelocity[index] * udg_CE_YVelocity[index]))) * bj_RADTODEG + 0.5) + 90)
call SetUnitFacing(udg_CE_UnitIndex[index], Angle * bj_RADTODEG)
endif
//Finds units which 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 p = Location(x, y)
set z = GetLocationZ(p) + CE_PortalHeight()
set u = udg_CE_UnitIndex[index]
call RemoveLocation (p)
set udg_CE_CurrentSize[index] = udg_CE_CurrentSize[index] + udg_CE_GrowthRate[index]
set pl = GetOwningPlayer(udg_CE_OriginalCaster[index])
call SetUnitScale(udg_CE_UnitIndex[index], udg_CE_CurrentSize[index], 0.00, 0.00)
if (udg_CE_CurrentProjectileDelay[index] > CE_ChaosEntityRate()) then
//Creating New projectile wave
set Angle = 0
//Reset the delay timer
set udg_CE_CurrentProjectileDelay[index] = 0.00
loop
//Calculating position and initialising
set Angle = Angle + (360.00 / udg_CE_ChaosEntityCount[index])
set secondaryindex = secondaryindex + 1
set x2 = x + CE_AOECentral() * Cos(Angle * bj_DEGTORAD)
set y2 = y + CE_AOECentral() * Sin(Angle * bj_DEGTORAD)
set udg_CE_MaxIndex = udg_CE_MaxIndex + 1
set udg_CE_UnitIndex[udg_CE_MaxIndex] = CreateUnit(Player(14), CE_DummyID(), x2, y2, Angle)
set udg_CE_CurrentEffect[udg_CE_MaxIndex] = AddSpecialEffectTarget(CE_ChaosEntityModel(), udg_CE_UnitIndex[udg_CE_MaxIndex], "origin")
set udg_CE_HealthDamage[udg_CE_MaxIndex] = CE_ChaosEntityHealthDamageBase() + (CE_ChaosEntityHealthDamagePerLevel() * udg_CE_rLevel[index])
set udg_CE_ManaDamage[udg_CE_MaxIndex] = CE_ChaosEntityManaDamageBase() + (CE_ChaosEntityManaDamagePerLevel() * udg_CE_rLevel[index])
set udg_CE_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
//Setting up data of the new magnetised unit
call CE_RegisterUnit(index, z, x2, y2, u, 0.00, 0.00, CE_ChaosEntityZControl())
//Applying Aesthetics
call SetUnitScale(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_ChaosEntityScaleBase() + (CE_ChaosEntityScalePerLevel() * udg_CE_rLevel[index]), 0.00, 0.00)
call SetUnitFlyHeight(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalHeight(), 0.00)
call SetUnitAnimationByIndex(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalAngle())
call GroupAddUnit(udg_CE_EffectedUnits, udg_CE_UnitIndex[index])
exitwhen secondaryindex == udg_CE_ChaosEntityCount[index]
endloop
set secondaryindex = 0
else
//Increase the delay timer on the projectiles
set udg_CE_CurrentProjectileDelay[index] = udg_CE_CurrentProjectileDelay[index] + CE_TimerSpeed()
endif
if (CE_EffectsUnits()) then
call GroupEnumUnitsInRange(udg_CE_TempGroup2, x, y, udg_CE_AOE[index], null)
//Filters through all the units within the range of the portal which can be used as targets
loop
set u = FirstOfGroup(udg_CE_TempGroup2)
exitwhen u == null
call CE_TargetFilter(u, pl)
call GroupRemoveUnit(udg_CE_TempGroup2, u)
//Actions for units which have been found to be viable targets
if (IsUnitInGroup(u, udg_CE_TempGroup)) and (not IsUnitInGroup(u, udg_CE_EffectedUnits)) then
//Data initialisation
set x2 = GetUnitX(u)
set y2 = GetUnitY(u)
set dx = x2 - x
set dy = y2 - y
set Angle = Atan2(dy, dx)
set Dist = SquareRoot(dx * dx + dy * dy)
set udg_CE_MaxIndex = udg_CE_MaxIndex + 1
set udg_CE_UnitIndex[udg_CE_MaxIndex] = u
set udg_CE_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
set p = null
endfunction
////////////////////////////////////////////////////////////////////
// Function ran to create a new instance of the spell, inits a //
// portal, giving it the starting information it requires //
////////////////////////////////////////////////////////////////////
function TrigCE_AllocateData takes nothing returns boolean
// Sets up the variables required for creating units
local unit u
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))
//Nulls variables
set CE = null
endfunction
Right, making my entry post, any updates will be done on this post:
Spell: Chaos Envoy
Description:
Chaos Envoy
The caster reaches out to the heart of the twisting nether, creating a portal leaking chaotic entities and pulling nearby enemy units violently towards it; damaging them with crushing force. When the portal closes, all affected units and entities fall back to the ground.
Level 1 - 250 Crush damage, 70 Entity damage
Level 2 - 350 Crush damage, 90 Entity damage
Level 3 - 450 Crush damage, 110 Entity damage
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 // // // // // //-------------------------------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 // // // //----------------------------------------------------------------// // 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 identify targets for the magnetism or // // damage of the spell depanding on what the current stage is // //////////////////////////////////////////////////////////////////// function CE_TargetFilter takes unit u, player pl returns nothing //Checks if the unit can be used as a target if (IsUnitType(u, UNIT_TYPE_GROUND)) and (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)) and (IsUnitEnemy(u, pl)) and (GetUnitTypeId(u) != CE_DummyID()) and (not IsUnitInGroup(u, udg_CE_EffectedUnits)) and (not IsUnitType(u, UNIT_TYPE_DEAD)) then call GroupAddUnit(udg_CE_TempGroup, u) endif //Nulling variables set u = null set pl = null endfunction function CE_GravityMove takes real Magnetism, real Radian, real Angle, real Angle2, real x, real y, real x2, real y2, real z, integer index returns nothing local location p //Setting the new locations X and Y for this instance set x2 = x + udg_CE_XVelocity[index] set y2 = y + udg_CE_YVelocity[index] set p = Location(x2,y2) //Calculating the new velocities (will be used next time this runs) set udg_CE_ZVelocity[index] = udg_CE_ZVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Sin(Angle2) set udg_CE_XVelocity[index] = udg_CE_XVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Cos(Angle) * Cos(Angle2) set udg_CE_YVelocity[index] = udg_CE_YVelocity[index] + ((Magnetism / Radian) * CE_TimerSpeed()) * Sin(Angle) * Cos(Angle2) //Makes sure the new location is within the map bounds if ((GetRectMinX(bj_mapInitialPlayableArea) <= GetLocationX(p)) and (GetLocationX(p) <= GetRectMaxX(bj_mapInitialPlayableArea)) and (GetRectMinY(bj_mapInitialPlayableArea) <= GetLocationY(p)) and (GetLocationY(p) <= GetRectMaxY(bj_mapInitialPlayableArea))) then call SetUnitX(udg_CE_UnitIndex[index], x2) call SetUnitY(udg_CE_UnitIndex[index], y2) endif //Removes the location call RemoveLocation(p) //Sets the correct fly height call SetUnitFlyHeight(udg_CE_UnitIndex[index], udg_CE_CurrentZ[index] - z, 0.00) //Nulling the variable set p = null endfunction function CE_ProjectileImpactDetection takes real z, real x, real y, integer index returns nothing local unit u local player pl //Checks if there has been a crash if (udg_CE_CurrentZ[index] - z < 5.00) then //Yes it crashed, deassociating the unit set udg_CE_StageID[index] = 4 set 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 endfunction function CE_RegisterUnit takes integer index, real z, real x2, real y2, unit u, real YVel, real XVel, real ZVel returns nothing //Sets up data for the next magnetised unit local location p2 set p2 = Location(x2, y2) set udg_CE_LaunchZ[udg_CE_MaxIndex] = GetLocationZ(p2) set udg_CE_TargetZ[udg_CE_MaxIndex] = z call RemoveLocation(p2) //Sets up data for caster and portal it's being pulled into set udg_CE_OriginalCaster[udg_CE_MaxIndex] = udg_CE_OriginalCaster[index] set udg_CE_Portal[udg_CE_MaxIndex] = udg_CE_UnitIndex[index] set udg_CE_AOE[udg_CE_MaxIndex] = udg_CE_AOE[index] //Sets up the magnetism set udg_CE_MagnetismStrength[udg_CE_MaxIndex] = udg_CE_MagnetismStrength[index] set udg_CE_CurrentZ[udg_CE_MaxIndex] = GetUnitFlyHeight(u) + udg_CE_LaunchZ[udg_CE_MaxIndex] set udg_CE_YVelocity[udg_CE_MaxIndex] = YVel set udg_CE_XVelocity[udg_CE_MaxIndex] = XVel set udg_CE_ZVelocity[udg_CE_MaxIndex] = ZVel //Nulls variables set u = null set p2 = null endfunction //////////////////////////////////////////////////////////////////// // Main looping function, controls things from the magnetism // // of the portal to the damage and projectile control within // // the Chaos Rip // //////////////////////////////////////////////////////////////////// function CE_Loop takes nothing returns nothing //Setting up the local variables local integer index = 0 local integer secondaryindex = 0 local real x local real x2 local real y local real y2 local real z local real z2 local real dx local real dy local real Dist local real Angle local real Angle2 local real Magnetism local real Radian local player pl local unit u local location p //Loops through all the units within the system loop set index = index + 1 exitwhen index > udg_CE_MaxIndex set x = GetUnitX(udg_CE_UnitIndex[index]) set y = GetUnitY(udg_CE_UnitIndex[index]) //Finds units which are initial portals of an instance if (udg_CE_StageID[index] == 1) then if (GetUnitCurrentOrder(udg_CE_OriginalCaster[index]) != CE_Order()) then set udg_CE_StageID[index] = 4 call DestroyEffect(udg_CE_CurrentEffect[index]) //Deassociating all the units involves with this porta (will allow units and projectiles to fall) loop set secondaryindex = secondaryindex + 1 if (udg_CE_Portal[secondaryindex] == udg_CE_UnitIndex[index]) then set udg_CE_Portal[secondaryindex] = null if (udg_CE_StageID[secondaryindex] == 7) then set udg_CE_StageID[secondaryindex] = 4 call DestroyEffect(udg_CE_CurrentEffect[secondaryindex]) else set udg_CE_StageID[secondaryindex] = 3 endif endif exitwhen secondaryindex > udg_CE_MaxIndex endloop set secondaryindex = 0 else //Initialising data and increasing the portal size set p = Location(x, y) set z = GetLocationZ(p) + CE_PortalHeight() set u = udg_CE_UnitIndex[index] call RemoveLocation (p) set udg_CE_CurrentSize[index] = udg_CE_CurrentSize[index] + udg_CE_GrowthRate[index] set pl = GetOwningPlayer(udg_CE_OriginalCaster[index]) call SetUnitScale(udg_CE_UnitIndex[index], udg_CE_CurrentSize[index], 0.00, 0.00) if (udg_CE_CurrentProjectileDelay[index] > CE_ChaosEntityRate()) then //Creating New projectile wave set Angle = 0 //Reset the delay timer set udg_CE_CurrentProjectileDelay[index] = 0.00 loop //Calculating position and initialising set Angle = Angle + (360.00 / udg_CE_ChaosEntityCount[index]) set secondaryindex = secondaryindex + 1 set x2 = x + CE_AOECentral() * Cos(Angle * bj_DEGTORAD) set y2 = y + CE_AOECentral() * Sin(Angle * bj_DEGTORAD) set udg_CE_MaxIndex = udg_CE_MaxIndex + 1 set udg_CE_UnitIndex[udg_CE_MaxIndex] = CreateUnit(Player(14), CE_DummyID(), x2, y2, Angle) set udg_CE_CurrentEffect[udg_CE_MaxIndex] = AddSpecialEffectTarget(CE_ChaosEntityModel(), udg_CE_UnitIndex[udg_CE_MaxIndex], "origin") set udg_CE_HealthDamage[udg_CE_MaxIndex] = CE_ChaosEntityHealthDamageBase() + (CE_ChaosEntityHealthDamagePerLevel() * udg_CE_rLevel[index]) set udg_CE_ManaDamage[udg_CE_MaxIndex] = CE_ChaosEntityManaDamageBase() + (CE_ChaosEntityManaDamagePerLevel() * udg_CE_rLevel[index]) set udg_CE_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 //Setting up data of the new magnetised unit call CE_RegisterUnit(index, z, x2, y2, u, 0.00, 0.00, CE_ChaosEntityZControl()) //Applying Aesthetics call SetUnitScale(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_ChaosEntityScaleBase() + (CE_ChaosEntityScalePerLevel() * udg_CE_rLevel[index]), 0.00, 0.00) call SetUnitFlyHeight(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalHeight(), 0.00) call SetUnitAnimationByIndex(udg_CE_UnitIndex[udg_CE_MaxIndex], CE_PortalAngle()) call GroupAddUnit(udg_CE_EffectedUnits, udg_CE_UnitIndex[index]) exitwhen secondaryindex == udg_CE_ChaosEntityCount[index] endloop set secondaryindex = 0 else //Increase the delay timer on the projectiles set udg_CE_CurrentProjectileDelay[index] = udg_CE_CurrentProjectileDelay[index] + CE_TimerSpeed() endif if (CE_EffectsUnits()) then call GroupEnumUnitsInRange(udg_CE_TempGroup2, x, y, udg_CE_AOE[index], null) //Filters through all the units within the range of the portal which can be used as targets loop set u = FirstOfGroup(udg_CE_TempGroup2) exitwhen u == null call CE_TargetFilter(u, pl) call GroupRemoveUnit(udg_CE_TempGroup2, u) //Actions for units which have been found to be viable targets if (IsUnitInGroup(u, udg_CE_TempGroup)) and (not IsUnitInGroup(u, udg_CE_EffectedUnits)) then //Data initialisation set x2 = GetUnitX(u) set y2 = GetUnitY(u) set dx = x2 - x set dy = y2 - y set Angle = Atan2(dy, dx) set Dist = SquareRoot(dx * dx + dy * dy) set udg_CE_MaxIndex = udg_CE_MaxIndex + 1 set udg_CE_UnitIndex[udg_CE_MaxIndex] = u set udg_CE_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 are to be effected by the magnetism elseif (udg_CE_StageID[index] == 2) then //Initialises Magnetism factors set x2 = GetUnitX(udg_CE_Portal[index]) set y2 = GetUnitY(udg_CE_Portal[index]) //Sets up this instance of the movement set udg_CE_CurrentZ[index] = udg_CE_CurrentZ[index] + udg_CE_ZVelocity[index] //Sets up calculating the next movement set p = Location(x, y) set z = GetLocationZ(p) call RemoveLocation(p) set dy = y2 - y set dx = x2 - x set Dist = SquareRoot(dx * dx + dy * dy) set Angle = Atan2(dy, dx) set Angle2 = Atan2(udg_CE_TargetZ[index] - udg_CE_CurrentZ[index], Dist) set Radian = SquareRoot((dx * dx) + (dy * dy) + (udg_CE_TargetZ[index] - udg_CE_CurrentZ[index]) * (udg_CE_TargetZ[index] - udg_CE_CurrentZ[index])) //Calculates the magnetism strength for this instance set Magnetism = udg_CE_MagnetismStrength[index] * (Dist / CE_MagnetismDecay()) if (Dist > udg_CE_AOE[index]) then set udg_CE_StageID[index] = 3 endif //Checks if the unit or entity have crashed call CE_ProjectileImpactDetection(z, x, y, index) //Moves the unit or entity around the Portal call CE_GravityMove(Magnetism, Radian, Angle, Angle2, x, y, x2, y2, z, index) //Checks if the unit is an entity - if it is, then setting its animation and facing direction if (GetUnitTypeId(udg_CE_UnitIndex[index]) == CE_DummyID()) then call SetUnitAnimationByIndex(udg_CE_UnitIndex[index], R2I(Atan2(udg_CE_ZVelocity[index], SquareRoot((udg_CE_XVelocity[index] * udg_CE_XVelocity[index]) + (udg_CE_YVelocity[index] * udg_CE_YVelocity[index]))) * bj_RADTODEG + 0.5) + 90) call SetUnitFacing(udg_CE_UnitIndex[index], Angle * bj_RADTODEG) endif //Finds units which are falling out of the sky elseif (udg_CE_StageID[index] == 3) then set p = Location(x, y) set z = GetLocationZ(p) set x2 = x + udg_CE_XVelocity[index] set y2 = y + udg_CE_YVelocity[index] set udg_CE_ZVelocity[index] = udg_CE_ZVelocity[index] - CE_Gravity() set udg_CE_CurrentZ[index] = udg_CE_CurrentZ[index] + udg_CE_ZVelocity[index] //Makes sure the projectile or unit does not leave the map bounds (may look a bit odd but is necessary) if ((GetRectMinX(bj_mapInitialPlayableArea) <= GetLocationX(p)) and (GetLocationX(p) <= GetRectMaxX(bj_mapInitialPlayableArea)) and (GetRectMinY(bj_mapInitialPlayableArea) <= GetLocationY(p)) and (GetLocationY(p) <= GetRectMaxY(bj_mapInitialPlayableArea))) then call SetUnitX(udg_CE_UnitIndex[index], x2) call SetUnitY(udg_CE_UnitIndex[index], y2) endif call RemoveLocation(p) call SetUnitFlyHeight(udg_CE_UnitIndex[index], udg_CE_CurrentZ[index] - z, 0.00) call CE_ProjectileImpactDetection(z, x, y, index) set Angle = Atan2(y2 - y, x2 - x) if (GetUnitTypeId(udg_CE_UnitIndex[index]) == CE_DummyID()) then call SetUnitAnimationByIndex(udg_CE_UnitIndex[index], R2I(Atan2(udg_CE_ZVelocity[index], SquareRoot((udg_CE_XVelocity[index] * udg_CE_XVelocity[index]) + (udg_CE_YVelocity[index] * udg_CE_YVelocity[index]))) * bj_RADTODEG + 0.5) + 90) call SetUnitFacing(udg_CE_UnitIndex[index], Angle * bj_RADTODEG) endif //Finds units which need to be recycled elseif (udg_CE_StageID[index] == 4) then //Checks if the death timer has expired if (udg_CE_CurrentDeathTimer[index] >= CE_DeathTimer()) then 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_ChaosEntityCount[index] = udg_CE_ChaosEntityCount[udg_CE_MaxIndex] set udg_CE_CurrentDeathTimer[index] = udg_CE_CurrentDeathTimer[udg_CE_MaxIndex] set udg_CE_CurrentEffect[index] = udg_CE_CurrentEffect[udg_CE_MaxIndex] set udg_CE_CurrentSize[index] = udg_CE_CurrentSize[udg_CE_MaxIndex] set udg_CE_CurrentZ[index] = udg_CE_CurrentZ[udg_CE_MaxIndex] set udg_CE_GrowthRate[index] = udg_CE_GrowthRate[udg_CE_MaxIndex] set udg_CE_HealthDamage[index] = udg_CE_HealthDamage[udg_CE_MaxIndex] set udg_CE_LaunchZ[index] = udg_CE_LaunchZ[udg_CE_MaxIndex] set udg_CE_MagnetismStrength[index] = udg_CE_MagnetismStrength[udg_CE_MaxIndex] set udg_CE_ManaDamage[index] = udg_CE_ManaDamage[udg_CE_MaxIndex] set udg_CE_OriginalCaster[index] = udg_CE_OriginalCaster[udg_CE_MaxIndex] set udg_CE_Portal[index] = udg_CE_Portal[udg_CE_MaxIndex] set udg_CE_StageID[index] = udg_CE_StageID[udg_CE_MaxIndex] set udg_CE_TargetZ[index] = udg_CE_TargetZ[udg_CE_MaxIndex] set udg_CE_UnitIndex[index] = udg_CE_UnitIndex[udg_CE_MaxIndex] set udg_CE_XVelocity[index] = udg_CE_XVelocity[udg_CE_MaxIndex] set udg_CE_YVelocity[index] = udg_CE_YVelocity[udg_CE_MaxIndex] set udg_CE_ZVelocity[index] = udg_CE_ZVelocity[udg_CE_MaxIndex] set udg_CE_iLevel[index] = udg_CE_iLevel[udg_CE_MaxIndex] set udg_CE_rLevel[index] = udg_CE_rLevel[udg_CE_MaxIndex] set udg_CE_MaxIndex = udg_CE_MaxIndex - 1 set index = index - 1 //Stopping the timer if there are no more instances to run if (udg_CE_MaxIndex == 0) then call DestroyTimer(GetExpiredTimer()) endif else //If the death timer has not expired, increase how long it's been running set udg_CE_CurrentDeathTimer[index] = udg_CE_CurrentDeathTimer[index] + CE_TimerSpeed() endif endif endloop //Nulls variables set u = null set p = null endfunction //////////////////////////////////////////////////////////////////// // Function ran to create a new instance of the spell, inits a // // portal, giving it the starting information it requires // //////////////////////////////////////////////////////////////////// function TrigCE_AllocateData takes nothing returns boolean // Sets up the variables required for creating units local unit u = GetTriggerUnit() local integer iLevel = GetUnitAbilityLevel(u, CE_SpellID()) local real rLevel = I2R(iLevel) local real x = GetSpellTargetX() local real x2 = GetUnitX(u) local real y = GetSpellTargetY() local real y2 = GetUnitY(u) local real Angle = 0.00 // Checks if the ability casted was the correct one if (GetSpellAbilityId() == CE_SpellID()) then // Initialises new spell instance set udg_CE_MaxIndex = udg_CE_MaxIndex + 1 set udg_CE_UnitIndex[udg_CE_MaxIndex] = CreateUnit(Player(14), CE_DummyID(), x, y, Atan2(y - y2, x - x2)) set udg_CE_AOE[udg_CE_MaxIndex] = CE_AOEBase() + (CE_AOEPerLevel() * rLevel) set udg_CE_CurrentEffect[udg_CE_MaxIndex] = AddSpecialEffectTarget(CE_PortalModel(), udg_CE_UnitIndex[udg_CE_MaxIndex], "origin") set udg_CE_MagnetismStrength[udg_CE_MaxIndex] = CE_MagnetismBase() + (CE_MagnetismPerLevel() * rLevel) set udg_CE_GrowthRate[udg_CE_MaxIndex] = CE_PortalGrowthRateBase() + (CE_PortalGrowthRatePerLevel() * rLevel) set udg_CE_ChaosEntityCount[udg_CE_MaxIndex] = CE_ChaosEntityCountBase() + (CE_ChaosEntityCountPerLevel() * iLevel) set udg_CE_CurrentSize[udg_CE_MaxIndex]= CE_PortalStartScale() set udg_CE_CurrentProjectileDelay[udg_CE_MaxIndex] = 0.00 set udg_CE_CurrentDeathTimer[udg_CE_MaxIndex] = 0.00 set udg_CE_OriginalCaster[udg_CE_MaxIndex] = u set udg_CE_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_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)) //Nulls variables set CE = null endfunction
Information:
Pure JASS ~ 1200 lines (including readme and configuration)
Runs on standard World Editor without compile errors on saving
Large configuration to modify pretty much every attribute involved with the spell.
Physics galore
Fully MUI, Recycles correctly
Comes with a variable creator to help with importing to standard world editors
Variable Creator
Events
Conditions
Actions
Set CE_AOE[0] = 0.00
Set CE_ChaosEntityCount[0] = 0
Set CE_CurrentDeathTimer[0] = 0.00
Set CE_CurrentEffect[0] = CE_CurrentEffect[0]
Set CE_CurrentProjectileDelay[0] = 0.00
Set CE_CurrentSize[0] = 0.00
Set CE_CurrentZ[0] = 0.00
Set CE_EffectedUnits = CE_EffectedUnits
Set CE_GrowthRate[0] = 0.00
Set CE_HealthDamage[0] = 0.00
Set CE_LaunchZ[0] = 0.00
Set CE_MagnetismStrength[0] = 0.00
Set CE_ManaDamage[0] = 0.00
Set CE_MaxIndex = 0
Set CE_OriginalCaster[0] = CE_OriginalCaster[0]
Set CE_Portal[0] = CE_Portal[0]
Set CE_StageID[0] = 0
Set CE_TargetZ[0] = 0.00
Set CE_TempGroup = CE_TempGroup
Set CE_TempGroup2 = CE_TempGroup2
Set CE_UnitIndex[0] = CE_UnitIndex[0]
Set CE_XVelocity[0] = 0.00
Set CE_YVelocity[0] = 0.00
Set CE_ZVelocity[0] = 0.00
Set CE_iLevel[0] = 0
Set CE_rLevel[0] = 0.00
WIPS:
http://www.hiveworkshop.com/forums/...t-10-what-lies-other-side-233773/#post2328013
http://www.hiveworkshop.com/forums/...ies-other-side-233773/index3.html#post2328512
http://www.hiveworkshop.com/forums/...ies-other-side-233773/index5.html#post2329215
http://www.hiveworkshop.com/forums/...ies-other-side-233773/index5.html#post2329389
http://www.hiveworkshop.com/forums/...ies-other-side-233773/index6.html#post2329748
http://www.hiveworkshop.com/forums/...ies-other-side-233773/index7.html#post2329904
Screenshots (and a slightly jolty GIF)
(GetSpellAbilityId() == CE_SpellID())
library ArcanceWormholes /* v1.0
*************************************************************************************
*
* Arcane Wormholes
* ~ Almia
*
* --------------------------------------------------------------------------
*
* Description
*
* ------------------------------------------
*
* --------------------------------------------------------------------------
*
* */ requires /*
*
* ------------------------------------------
*
* */ Table /* [url]www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/[/url]
* */ MapBounds /* [url]www.hiveworkshop.com/forums/jass-resources-412/snippet-worldbounds-180494/[/url]
* */ WorldBounds /* [url]www.hiveworkshop.com/forums/jass-resources-412/snippet-mapbounds-222870/[/url]
*
* --------------------------------------------------------------------------
*
* Credits
*
* ------------------------------------------
*
* Nestharus
* Bribe
* Adiktuz
*
*************************************************************************************/
globals
/*
Ability main constants
*/
private constant real TIMEOUT = 0.031250000
/*
Main Ability Raw Code
*/
private constant integer MAIN = 'A000'
/*
Sub Ability Raw Code
*/
private constant integer SUB = 'A001'
/*
Dummy Raw Code
*/
private constant integer DUMMY = 'h000'
/*
Max Spell Charges
*/
private constant integer SPELL_CHARGES = 3
/*
Caster Orbs
*/
/*
Number of orbs spinning around the caster
*/
private constant integer CASTER_ORB_NUMBER = 3
/*
How far are they from the caster
*/
private constant real CASTER_ORB_DIST = 150.
/*
How fast the orbs spins around by angle
*/
private constant real CASTER_ORB_SPIN_SPEED = 90.
/*
Model Path of the caster orbs
*/
private constant string CASTER_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Orb Model Size
*/
private constant real CASTER_ORB_SIZE = 1.
/*
Orb Caster Height
*/
private constant real CASTER_ORB_Z = 50.
/*
Orb Missile
*/
/*
Missile Speed
*/
private constant real ORB_MISSILE_SPEED = 500.
/*
Missile Model
*/
private constant string ORB_MISSILE_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Missile Size
*/
private constant real ORB_MISSILE_SIZE = 1.
/*
Missile Height
*/
private constant real ORB_MISSILE_Z = 50.
/*
Missile Impact Effect
*/
private constant string ORB_IMPACT_EFFECt = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Portal
*/
/*
Portal Model
*/
private constant string PORTAL_MDL = "units\\nightelf\\Wisp\\Wisp.mdl"
/*
Portal Size
*/
private constant real PORTAL_SIZE = 1.
/*
Portal Height
*/
private constant real PORTAL_Z = 50.
/*
Portal Duration
*/
private constant real PORTAL_DURATION = 60.
/*
Portal Death Effect
*/
private constant string PORTAL_DEATH_SFX = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Portal Orbs
*/
/*
Number of orbs spinning around the portal
*/
private constant real PORTAL_ORB_NUMBER = 3
/*
How far the orbs are from the portal
*/
private constant real PORTAL_ORB_DIST = 150.
/*
Portal Orb Spin Speed
*/
private constant real PORTAL_ORB_SPIN_SPEED = 90.
/*
Portal Orb Model
*/
private constant string PORTAL_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Portal Orb Scale
*/
private constant real PORTAL_ORB_SIZE = 1.
/*
Portal Orb Z
*/
private constant real PORTAL_ORB_Z = 75.
/*
Teleportation Constants
*/
/*
Radius of units that will be also teleported
*/
private constant real TELEPORT_RADIUS = 500.
/*
Teleportation Delay
*/
private constant real TELEPORT_DELAY = 5.
/*
Teleportation On Cast Effect
*/
private constant string TELEPORT_CAST_SFX = "Abilities\\Spells\\Other\\Charm\\CharmTarget.mdl"
/*
Channeling Effect on Caster
*/
private constant string TELEPORT_CHANNEL_SFX = "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl"
/*
Random Effect Channel
*/
private constant string TELEPORT_RANDOM_SFX = "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl"
/*
Teleportation Success Effect
*/
private constant string TELEPORT_END_SFX = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Teleportation Impact Effect
*/
private constant string TELEPORT_IMPACT_SFX ="Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
/*
Teleportation Damage and Mana Burn Radius
*/
private constant real TELEPORT_IMPACT_RADIUS = 400. // Base value
/*
Teleportation Damage value
*/
private constant real TELEPORT_IMPACT_DAMAGE = 25. // Base Value
/*
Teleportation Mana Burn Value
*/
private constant real TELEPORT_IMPACT_BURN = 25. // Base Value
/*
Teleportation Mana Burn and Damage SFX
*/
private constant string TELEPORT_DMB_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
private constant string TELEPORT_DMB_ATTACH = "chest"
/*
Teleportation Orbs
*/
/*
Number of orbs spinning around the caster
*/
private constant real TELEPORT_ORB_NUMBER = 6
/*
How far the orbs are from the portal
*/
private constant real TELEPORT_ORB_DIST = TELEPORT_RADIUS
/*
Portal Orb Spin Speed
*/
private constant real TELEPORT_ORB_SPIN_SPEED = 90.
/*
Portal Orb Model
*/
private constant string TELEPORT_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Portal Orb Scale
*/
private constant real TELEPORT_ORB_SIZE = 1.
/*
Portal Orb Z
*/
private constant real TELEPORT_ORB_Z = 75.
/*
Effect created while orbs are moving
*/
private constant string TELEPORT_ORB_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
/*
Teleportation Impact Orbs
*/
/*
Number of orbs released
*/
private constant integer SHARD_NUMBER = 12
/*
Distance of orbs released
*/
private constant real SHARD_DIST = TELEPORT_IMPACT_RADIUS // Base Value
/*
Height
*/
private constant real SHARD_ARC_Z = 0.5
/*
Effect when orbs die
*/
private constant string SHARD_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
/*
Misc Globals
*/
private Table dtb
private timer t = CreateTimer()
private group g = CreateGroup()
endglobals
/*
Dummy Struct
*/
private struct Dummy extends array
static integer c
static Dummy array r
static unit array u
static unit array ru
method move takes real x, real y returns nothing
call SetUnitX(u[this], GetBoundedX(x))
call SetUnitY(u[this], GetBoundedY(y))
endmethod
static method create takes player p, real x, real y, real z returns Dummy
local Dummy this = r[0]
if 0 == this then
set this = c + 1
set c = this
set u[this] = CreateUnit(p, DUMMY, x, y, 0)
if UnitAddAbility(u[this], 'Amrf') and UnitRemoveAbility(u[this], 'Amrf') then
endif
else
set u[this] = ru[this]
set r[0] = r[this]
call this.move(x, y)
endif
call SetUnitFlyHeight(u[this], z, 0)
return this
endmethod
method destroy takes nothing returns nothing
set ru[this] = u[this]
set u[this] = null
set r[this] = r[0]
set r[0] = this
call this.move(WorldBounds.minX, WorldBounds.minY)
endmethod
endstruct
private struct Portal extends array
endstruct
private struct OrbMissile extends array
endstruct
private struct Orb extends array
endstruct
private struct ShardOrbs extends array
endstruct
private struct Spell extends array
endstruct
endlibrary
How can you think that I dont know that?^ the lines above that are locals so you cannot place them below...
function ...
local unit u
if (GetSpellAbilityId() == CE_SpellID()) then
//do shits
function TrigCE_AllocateData takes nothing returns boolean
// Sets up the variables required for creating units
local unit u = GetTriggerUnit()
local integer iLevel = GetUnitAbilityLevel(u, CE_SpellID())
local real rLevel = I2R(iLevel)
local real x = GetSpellTargetX()
local real x2 = GetUnitX(u)
local real y = GetSpellTargetY()
local real y2 = GetUnitY(u)
local real Angle = 0.00
// Checks if the ability casted was the correct one
if (GetSpellAbilityId() == CE_SpellID()) then
// Initialises new spell instance
because I looked at his trigger and saw that he was already doing that thing...
JASS:function TrigCE_AllocateData takes nothing returns boolean // Sets up the variables required for creating units local unit u = GetTriggerUnit() local integer iLevel = GetUnitAbilityLevel(u, CE_SpellID()) local real rLevel = I2R(iLevel) local real x = GetSpellTargetX() local real x2 = GetUnitX(u) local real y = GetSpellTargetY() local real y2 = GetUnitY(u) local real Angle = 0.00 // Checks if the ability casted was the correct one if (GetSpellAbilityId() == CE_SpellID()) then // Initialises new spell instance
function TrigCE_AllocateData takes nothing returns boolean
// Sets up the variables required for creating units
local unit u
local integer iLevel
local real rLevel
local real x
local real x2
local real y
local real y2
local real Angle = 0.00
// Checks if the ability casted was the correct one
if (GetSpellAbilityId() == CE_SpellID()) then
set u=GetTriggerUnit()
set iLevel=GetUnitAbilityLevel(u,CE_SpellID())
set rLevel = I2R(iLevel)
set x = GetSpellTargetX()
set x2 = GetUnitX(u)
set y = GetSpellTargetY()
set y2 = GetUnitY(u)
// Initialises new spell instance
library DummyUnitStack
struct DummyUnitStack
private static constant integer DUMMY_UNIT_ID='u000'
private static constant integer MIN_PRELOAD_BLOCK_SIZE=10 //How many units to preload when the preloading algorithm turns on, at a minimum?
private static constant integer PRELOAD_INIT_COUNT=2000 //How many units to preload during initialization (set to 0 to disable)
private static constant boolean DO_PIC=true
private static constant integer DYNAMIC_DEFERRED_PRELOAD_COUNT=100 //How many units should DummyUnitStack keep preloaded at a minimum?
private static constant boolean DO_DDPC=true
private static constant integer INITIAL_DEFERRED_PRELOAD_COUNT=2000 //How many units should be queued on the preloader on map start?
private static constant boolean DO_IDPC=true
private static constant integer MAX_PRELOADED_UNITS=5000
private static constant boolean DO_MPU=true
private static constant real SAFE_LOC_X=2460.
private static constant real SAFE_LOC_Y=2210.
private static constant real CLOCK_PERIOD=1./60.
private static unit array dummyStack
private static integer stackIndex=-1
private static integer deferredTodoCount=0
private static timer clock=CreateTimer()
private static method add takes boolean preloading returns unit
local unit u=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),thistype.DUMMY_UNIT_ID,thistype.SAFE_LOC_X,thistype.SAFE_LOC_Y,0.)
call UnitAddAbility(u,'Aloc')
call UnitAddAbility(u,'Arav')
if preloading then
set thistype.stackIndex=thistype.stackIndex+1
set thistype.dummyStack[thistype.stackIndex]=u
else
return u
endif
return null
endmethod
public static method deferredPreloader takes nothing returns nothing
set thistype.deferredTodoCount=thistype.deferredTodoCount-1
call thistype.add(true)
if thistype.deferredTodoCount<1 then
call PauseTimer(thistype.clock)
endif
endmethod
public static method get takes nothing returns unit
local unit result
if thistype.stackIndex!=-1 then
set thistype.stackIndex=thistype.stackIndex-1
set result=thistype.dummyStack[thistype.stackIndex+1]
else
set result=thistype.add(false)
endif
static if DO_DDPC then
if thistype.stackIndex<(thistype.DYNAMIC_DEFERRED_PRELOAD_COUNT-1) and thistype.deferredTodoCount<1 then
set thistype.deferredTodoCount=thistype.MIN_PRELOAD_BLOCK_SIZE
call TimerStart(thistype.clock,thistype.CLOCK_PERIOD,true,function thistype.deferredPreloader)
endif
endif
return result
endmethod
public static method release takes unit u returns nothing
static if DO_MPU then
if thistype.stackIndex>=thistype.MAX_PRELOADED_UNITS then
call RemoveUnit(u)
return
endif
endif
call SetUnitOwner(u,Player(PLAYER_NEUTRAL_PASSIVE),true)
call SetUnitX(u,thistype.SAFE_LOC_X)
call SetUnitY(u,thistype.SAFE_LOC_Y)
set thistype.stackIndex=thistype.stackIndex+1
set thistype.dummyStack[thistype.stackIndex]=u
endmethod
private static method onInit takes nothing returns nothing
local integer index=1
static if DO_PIC then
loop
exitwhen index>thistype.PRELOAD_INIT_COUNT
call thistype.add(true)
set index=index+1
endloop
endif
static if DO_IDPC then
set thistype.deferredTodoCount=thistype.INITIAL_DEFERRED_PRELOAD_COUNT
call TimerStart(thistype.clock,thistype.CLOCK_PERIOD,true,function thistype.deferredPreloader)
endif
endmethod
endstruct
endlibrary
Is it fine to use a 0.01 second wait?
In single player short waits alwas add 0.1-0.2 seconds into the time. So a 0.00 wait is actually 0.1-0.2 seconds in single player. Timers are much better and accurate.
(This is under the assumption that you're referring to GUI) By Timers do you mean the one created through theaction?
Timer - Create a One-Shot Timer...
library ArcanceWormholes /* v1.0
*************************************************************************************
*
* Arcane Wormholes
* ~ Almia
*
* --------------------------------------------------------------------------
*
* Description
*
* ------------------------------------------
*
* --------------------------------------------------------------------------
*
* */ requires /*
*
* ------------------------------------------
*
* */ Table /* [url]www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/[/url]
* */ WorldBounds /* [url]www.hiveworkshop.com/forums/jass-resources-412/snippet-worldbounds-180494/[/url]
* */ MapBounds /* [url]www.hiveworkshop.com/forums/jass-resources-412/snippet-mapbounds-222870/[/url]
*
* --------------------------------------------------------------------------
*
* Credits
*
* ------------------------------------------
*
* Nestharus
* Bribe
* Adiktuz
*
*************************************************************************************/
globals
/*
Ability main constants
*/
private constant real TIMEOUT = 0.031250000
/*
Main Ability Raw Code
*/
private constant integer MAIN = 'A000'
/*
Sub Ability Raw Code
*/
private constant integer SUB = 'A001'
/*
Dummy Raw Code
*/
private constant integer DUMMY = 'h000'
/*
Max Spell Charges
*/
private constant integer SPELL_CHARGES = 3
/*
Caster Orbs
*/
/*
Number of orbs spinning around the caster
*/
private constant integer CASTER_ORB_NUMBER = 3
/*
How far are they from the caster
*/
private constant real CASTER_ORB_DIST = 150.
/*
How fast the orbs spins around by angle
*/
private constant real CASTER_ORB_SPIN_SPEED = 90.
/*
Model Path of the caster orbs
*/
private constant string CASTER_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Orb Model Size
*/
private constant real CASTER_ORB_SIZE = 1.
/*
Orb Caster Height
*/
private constant real CASTER_ORB_Z = 50.
/*
Orb Missile
*/
/*
Missile Speed
*/
private constant real ORB_MISSILE_SPEED = 500.
/*
Missile Model
*/
private constant string ORB_MISSILE_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Missile Size
*/
private constant real ORB_MISSILE_SIZE = 1.
/*
Missile Height
*/
private constant real ORB_MISSILE_Z = 50.
/*
Missile Impact Effect
*/
private constant string ORB_IMPACT_EFFECt = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Portal
*/
/*
Portal Model
*/
private constant string PORTAL_MDL = "units\\nightelf\\Wisp\\Wisp.mdl"
/*
Portal Size
*/
private constant real PORTAL_SIZE = 1.
/*
Portal Height
*/
private constant real PORTAL_Z = 50.
/*
Portal Duration
*/
private constant real PORTAL_DURATION = 60.
/*
Portal Death Effect
*/
private constant string PORTAL_DEATH_SFX = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Portal Orbs
*/
/*
Number of orbs spinning around the portal
*/
private constant real PORTAL_ORB_NUMBER = 3
/*
How far the orbs are from the portal
*/
private constant real PORTAL_ORB_DIST = 150.
/*
Portal Orb Spin Speed
*/
private constant real PORTAL_ORB_SPIN_SPEED = 90.
/*
Portal Orb Model
*/
private constant string PORTAL_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Portal Orb Scale
*/
private constant real PORTAL_ORB_SIZE = 1.
/*
Portal Orb Z
*/
private constant real PORTAL_ORB_Z = 75.
/*
Teleportation Constants
*/
/*
Radius of units that will be also teleported
*/
private constant real TELEPORT_RADIUS = 500.
/*
Teleportation Delay
*/
private constant real TELEPORT_DELAY = 5.
/*
Teleportation On Cast Effect
*/
private constant string TELEPORT_CAST_SFX = "Abilities\\Spells\\Other\\Charm\\CharmTarget.mdl"
private constant string TELEPORT_CAST_ATTACH = "overhead"
/*
Channeling Effect on Caster
*/
private constant string TELEPORT_CHANNEL_SFX = "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl"
private constant string TELEPORT_CHANNEL_ATTACH = "origin"
/*
Random Effect Channel
*/
private constant string TELEPORT_RANDOM_SFX = "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl"
/*
Teleportation Success Effect
*/
private constant string TELEPORT_END_SFX = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Teleportation Impact Effect
*/
private constant string TELEPORT_IMPACT_SFX ="Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
/*
Teleportation Damage and Mana Burn Radius
*/
private constant real TELEPORT_IMPACT_RADIUS = 400. // Base value
/*
Teleportation Damage value
*/
private constant real TELEPORT_IMPACT_DAMAGE = 25. // Base Value
/*
Teleportation Mana Burn Value
*/
private constant real TELEPORT_IMPACT_BURN = 25. // Base Value
/*
Teleportation Mana Burn and Damage SFX
*/
private constant string TELEPORT_DMB_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
private constant string TELEPORT_DMB_ATTACH = "chest"
/*
Teleportation Orbs
*/
/*
Number of orbs spinning around the caster
*/
private constant real TELEPORT_ORB_NUMBER = 6
/*
How far the orbs are from the portal
*/
private constant real TELEPORT_ORB_DIST = TELEPORT_RADIUS
/*
Portal Orb Spin Speed
*/
private constant real TELEPORT_ORB_SPIN_SPEED = 90.
/*
Portal Orb Model
*/
private constant string TELEPORT_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Portal Orb Scale
*/
private constant real TELEPORT_ORB_SIZE = 1.
/*
Portal Orb Z
*/
private constant real TELEPORT_ORB_Z = 75.
/*
Effect created while orbs are moving
*/
private constant string TELEPORT_ORB_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
/*
Teleportation Impact Orbs
*/
/*
Number of orbs released
*/
private constant integer SHARD_NUMBER = 12
/*
Distance of orbs released
*/
private constant real SHARD_DIST = TELEPORT_IMPACT_RADIUS // Base Value
/*
Height
*/
private constant real SHARD_ARC_Z = 0.5
/*
Effect when orbs die
*/
private constant string SHARD_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
/*
Misc Globals
*/
private Table dtb
private timer pt = CreateTimer()
private timer st = CreateTimer()
private timer ot = CreateTimer()
private timer mt = CreateTimer()
private timer ct = CreateTimer()
private group g = CreateGroup()
endglobals
/*
List
*/
module List
static integer array n
static integer array p
static integer array r
static integer c = 0
static integer ic = 0
static method add takes nothing returns thistype
local thistype this = r[0]
if 0 == this then
set ic = ic + 1
set this = ic
else
set r[0] = r[this]
endif
set n[this] = 0
set p[this] = 0
set n[p[0]] = this
set p[0] = this
return this
endmethod
method remove takes nothing returns nothing
set n[p[this]] = n[this]
set p[n[this]] = p[this]
set r[this] = r[0]
set r[0] = this
endmethod
endmodule
/*
Dummy Struct
For spell dummies
*/
private struct Dummy extends array
static integer c = 0
static Dummy array r
static unit array u
static effect array e
method move takes real x, real y returns nothing
call SetUnitX(u[this], GetBoundedX(x))
call SetUnitY(u[this], GetBoundedY(y))
endmethod
static method create takes player p, real x, real y, real z, real face, string mdl, real scale returns Dummy
local Dummy this = r[0]
if 0 == this then
set this = c + 1
set c = this
set u[this] = CreateUnit(p, DUMMY, x, y, face)
if UnitAddAbility(u[this], 'Amrf') and UnitRemoveAbility(u[this], 'Amrf') then
endif
else
set r[0] = r[this]
call this.move(x, y)
call SetUnitOwner(u[this], p, false)
call SetUnitFacing(u[this], face)
endif
set e[this] = AddSpecialEffectTarget(mdl, u[this], "origin")
call SetUnitFlyHeight(u[this], z, 0)
call SetUnitScale(u[this], scale, 0, 0)
return this
endmethod
method destroy takes nothing returns nothing
call DestroyEffect(e[this])
set e[this] = null
set r[this] = r[0]
set r[0] = this
call SetUnitOwner(u[this], Player(15), false)
call this.move(WorldBounds.minX, WorldBounds.minY)
endmethod
endstruct
private struct OrbMissile extends array
endstruct
/*
Orb
Spinning dummies
*/
private struct Orb extends array
implement List
static Dummy array d
static real array dur
static real array speed
static real array dist
static real array angle
static unit array org
static method periodic takes nothing returns nothing
local Orb this = n[0]
local real x
local real y
loop
exitwhen 0 == this
if 0 < dur[this] then
set dur[this] = dur[this] - TIMEOUT
set angle[this] = angle[this] + speed[this]
set x = GetUnitX(org[this]) + dist[this] * Cos(angle[this] * bj_DEGTORAD)
set y = GetUnitY(org[this]) + dist[this] * Sin(angle[this] * bj_DEGTORAD)
call d[this].move(x, y)
else
call d[this].destroy()
set d[this] = 0
set dur[this] = 0
set speed[this] = 0
set dist[this] = 0
set org[this] = null
set angle[this] = 0
call this.remove()
set c = c - 1
if 0 == c then
call PauseTimer(ot)
endif
endif
set this = n[this]
endloop
endmethod
static method create takes string mdl, player p, unit o, real z, real sc, real ds, real s, real time, real a returns Orb
local Orb this = Orb.add()
set d[this] = Dummy.create(p, GetUnitX(o), GetUnitY(o), z, a, mdl, sc)
set speed[this] = s * TIMEOUT
set dist[this] = ds
set dur[this] = time
set angle[this] = a
set org[this] = o
set c = c + 1
if 1 == c then
call TimerStart(ot, TIMEOUT, true, function Orb.periodic)
endif
return this
endmethod
endstruct
private struct Portal extends array
implement List
static real array dur
static Dummy array pt
static method periodic takes nothing returns nothing
local integer i = n[0]
loop
exitwhen 0 == i
set i = n[i]
endloop
endmethod
static method create takes player pl, unit owner, real x, real y returns Portal
local Portal this = r[0]
if 0 == this then
set ic = ic + 1
set this = ic
else
set r[0] = r[this]
endif
set pt[this] = Dummy.create(pl, x, y, PORTAL_Z, 0, PORTAL_MDL, PORTAL_SIZE)
set n[this] = 0
set p[this] = 0
set n[p[0]] = this
set p[0] = this
set c = c + 1
if 1 == c then
endif
return this
endmethod
endstruct
private struct ShardOrbs extends array
implement List
endstruct
private struct Spell extends array
implement List
endstruct
endlibrary
Here are the tooltips for my summoned unit's abilities.
Once again, since the contest judging is meant to be for one ability and one sub ability, these can be ignored for the judging criteria (!)
UPS!!! I just noticed your comment today@moyackx
Indention.
And why not put the init and do effect as a method inside the data struct? its much faster.
UPS!!! I just noticed your comment today
Well, I think there won't be any problem with that.
library ArcanceWormholes /* v1.0
*************************************************************************************
*
* Arcane Wormholes
* ~ Almia
*
* --------------------------------------------------------------------------
*
* Description
*
* ------------------------------------------
*
* --------------------------------------------------------------------------
*
* */ requires /*
*
* ------------------------------------------
*
* */ SpellEffectEvent /*
* hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
* */ WorldBounds /*
* hiveworkshop.com/forums/jass-resources-412/snippet-worldbounds-180494/
* */ MapBounds /*
* hiveworkshop.com/forums/jass-resources-412/snippet-mapbounds-222870/
*
* --------------------------------------------------------------------------
*
* Credits
*
* ------------------------------------------
*
* Nestharus
* Bribe
* Adiktuz
*
*************************************************************************************/
globals
/*
Ability main constants
*/
private constant real TIMEOUT = 0.031250000
/*
Main Ability Raw Code
*/
private constant integer MAIN = 'A000'
/*
Sub Ability Raw Code
*/
private constant integer SUB = 'A001'
/*
Dummy Raw Code
*/
private constant integer DUMMY = 'h000'
/*
Max Spell Charges
*/
private constant integer SPELL_CHARGES = 3
/*
Effects created of all orbs
*/
private constant string ORB_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
/*
Caster Orbs
*/
/*
Number of orbs spinning around the caster
*/
private constant integer CASTER_ORB_NUMBER = 3
/*
How far are they from the caster
*/
private constant real CASTER_ORB_DIST = 150.
/*
How fast the orbs spins around by angle
*/
private constant real CASTER_ORB_SPIN_SPEED = 90.
/*
Model Path of the caster orbs
*/
private constant string CASTER_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Orb Model Size
*/
private constant real CASTER_ORB_SIZE = 1.
/*
Orb Caster Height
*/
private constant real CASTER_ORB_Z = 50.
/*
Orb Missile
*/
/*
Missile Speed
*/
private constant real ORB_MISSILE_SPEED = 500.
/*
Missile Model
*/
private constant string ORB_MISSILE_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Missile Size
*/
private constant real ORB_MISSILE_SIZE = 1.
/*
Missile Height
*/
private constant real ORB_MISSILE_Z = 50.
/*
Missile Impact Effect
*/
private constant string ORB_IMPACT_EFFECt = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Portal
*/
/*
Portal Model
*/
private constant string PORTAL_MDL = "units\\nightelf\\Wisp\\Wisp.mdl"
/*
Portal Size
*/
private constant real PORTAL_SIZE = 1.
/*
Portal Height
*/
private constant real PORTAL_Z = 50.
/*
Portal Duration
*/
private constant real PORTAL_DURATION = 60.
/*
Portal Death Effect
*/
private constant string PORTAL_DEATH_SFX = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Portal Orbs
*/
/*
Number of orbs spinning around the portal
*/
private constant real PORTAL_ORB_NUMBER = 3
/*
How far the orbs are from the portal
*/
private constant real PORTAL_ORB_DIST = 150.
/*
Portal Orb Spin Speed
*/
private constant real PORTAL_ORB_SPIN_SPEED = 90.
/*
Portal Orb Model
*/
private constant string PORTAL_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Portal Orb Scale
*/
private constant real PORTAL_ORB_SIZE = 1.
/*
Portal Orb Z
*/
private constant real PORTAL_ORB_Z = 75.
/*
Teleportation Constants
*/
/*
Radius of units that will be also teleported
*/
private constant real TELEPORT_RADIUS = 500.
/*
Teleportation Delay
*/
private constant real TELEPORT_DELAY = 5.
/*
Teleportation On Cast Effect
*/
private constant string TELEPORT_CAST_SFX = "Abilities\\Spells\\Other\\Charm\\CharmTarget.mdl"
private constant string TELEPORT_CAST_ATTACH = "overhead"
/*
Channeling Effect on Caster
*/
private constant string TELEPORT_CHANNEL_SFX = "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl"
private constant string TELEPORT_CHANNEL_ATTACH = "origin"
/*
Random Effect Channel
*/
private constant string TELEPORT_RANDOM_SFX = "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl"
/*
Teleportation Success Effect
*/
private constant string TELEPORT_END_SFX = "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
/*
Teleportation Impact Effect
*/
private constant string TELEPORT_IMPACT_SFX ="Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
/*
Teleportation Damage and Mana Burn Radius
*/
private constant real TELEPORT_IMPACT_RADIUS = 400. // Base value
/*
Teleportation Damage value
*/
private constant real TELEPORT_IMPACT_DAMAGE = 25. // Base Value
/*
Teleportation Mana Burn Value
*/
private constant real TELEPORT_IMPACT_BURN = 25. // Base Value
/*
Teleportation Mana Burn and Damage SFX
*/
private constant string TELEPORT_DMB_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
private constant string TELEPORT_DMB_ATTACH = "chest"
/*
Teleportation Orbs
*/
/*
Number of orbs spinning around the caster
*/
private constant real TELEPORT_ORB_NUMBER = 6
/*
How far the orbs are from the portal
*/
private constant real TELEPORT_ORB_DIST = TELEPORT_RADIUS
/*
Portal Orb Spin Speed
*/
private constant real TELEPORT_ORB_SPIN_SPEED = 90.
/*
Portal Orb Model
*/
private constant string TELEPORT_ORB_MDL = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
/*
Portal Orb Scale
*/
private constant real TELEPORT_ORB_SIZE = 1.
/*
Portal Orb Z
*/
private constant real TELEPORT_ORB_Z = 75.
/*
Teleportation Impact Orbs
*/
/*
Number of orbs released
*/
private constant integer SHARD_NUMBER = 12
/*
Distance of orbs released
*/
private constant real SHARD_DIST = TELEPORT_IMPACT_RADIUS // Base Value
/*
Height
*/
private constant real SHARD_ARC_Z = 0.5
/*
Effect when orbs die
*/
private constant string SHARD_SFX = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
/*
Misc Globals
*/
private hashtable ht
private timer pt = CreateTimer()
private timer st = CreateTimer()
private timer ot = CreateTimer()
private timer mt = CreateTimer()
private timer ct = CreateTimer()
private group g = CreateGroup()
endglobals
/*
List
*/
private module List
static integer array n
static integer array p
static integer array r
static integer c = 0
static integer ic = 0
static method add takes nothing returns thistype
local thistype this = r[0]
if 0 == this then
set ic = ic + 1
set this = ic
else
set r[0] = r[this]
endif
set n[this] = 0
set p[this] = 0
set n[p[0]] = this
set p[0] = this
return this
endmethod
method remove takes nothing returns nothing
set n[p[this]] = n[this]
set p[n[this]] = p[this]
set r[this] = r[0]
set r[0] = this
endmethod
endmodule
/*
Dummy Struct
For spell dummies
*/
private struct Dummy extends array
static integer c = 0
static Dummy array r
static unit array u
static effect array e
static boolean array dead
static real array tx
static real array ty
method operator angle= takes real a returns nothing
call SetUnitFacing(u[this], a)
endmethod
method operator isDead takes nothing returns boolean
return dead[this]
endmethod
method operator x takes nothing returns real
return tx[this]
endmethod
method operator y takes nothing returns real
return ty[this]
endmethod
method move takes real tmx, real tmy returns nothing
call SetUnitX(u[this], GetBoundedX(tmx))
call SetUnitY(u[this], GetBoundedY(tmy))
set tx[this] = tmx
set ty[this] = tmy
endmethod
static method create takes player p, real tmx, real tmy, real z, real face, string mdl, real scale returns Dummy
local Dummy this = r[0]
if 0 == this then
set this = c + 1
set c = this
set u[this] = CreateUnit(p, DUMMY, tmx, tmy, face)
if UnitAddAbility(u[this], 'Amrf') and UnitRemoveAbility(u[this], 'Amrf') then
endif
set tx[this] = tmx
set ty[this] = tmy
else
set r[0] = r[this]
call this.move(tmx, tmy)
call SetUnitOwner(u[this], p, false)
call SetUnitFacing(u[this], face)
endif
set dead[this] = false
set e[this] = AddSpecialEffectTarget(mdl, u[this], "origin")
call SetUnitFlyHeight(u[this], z, 0)
call SetUnitScale(u[this], scale, 0, 0)
return this
endmethod
method destroy takes nothing returns nothing
call DestroyEffect(e[this])
set dead[this] = true
set e[this] = null
set r[this] = r[0]
set r[0] = this
call SetUnitOwner(u[this], Player(15), false)
call this.move(WorldBounds.minX, WorldBounds.minY)
endmethod
endstruct
/************************
*
* Orb Struct
* Spinning dummies
*
*************************/
private struct Orb extends array
implement List
static Dummy array d
static real array dur
static real array speed
static real array dist
static real array angle
static unit array org
static method periodic takes nothing returns nothing
local Orb this = n[0]
local real x
local real y
loop
exitwhen 0 == this
if 0 < dur[this] then
set dur[this] = dur[this] - TIMEOUT
set angle[this] = angle[this] + speed[this]
set x = GetUnitX(org[this]) + dist[this] * Cos(angle[this] * bj_DEGTORAD)
set y = GetUnitY(org[this]) + dist[this] * Sin(angle[this] * bj_DEGTORAD)
set d[this].angle = angle[this]
call DestroyEffect(AddSpecialEffect(ORB_SFX, x, y))
call d[this].move(x, y)
else
call d[this].destroy()
set d[this] = 0
set dur[this] = 0
set speed[this] = 0
set dist[this] = 0
set org[this] = null
set angle[this] = 0
call this.remove()
set c = c - 1
if 0 == c then
call PauseTimer(ot)
endif
endif
set this = n[this]
endloop
endmethod
static method create takes string mdl, player p, unit o, real z, real sc, real ds, real s, real time, real a returns Orb
local Orb this = Orb.add()
set d[this] = Dummy.create(p, GetUnitX(o), GetUnitY(o), z, a, mdl, sc)
set speed[this] = s * TIMEOUT
set dist[this] = ds
set dur[this] = time
set angle[this] = a
set org[this] = o
set c = c + 1
if 1 == c then
call TimerStart(ot, TIMEOUT, true, function Orb.periodic)
endif
return this
endmethod
endstruct
/*******************************
*
* Portal Struct
*
*******************************/
private struct Portal extends array
implement List
static real array dur
static Dummy array po
static unit array o
static method periodic takes nothing returns nothing
local Portal this = n[0]
local integer id
local integer i
loop
exitwhen 0 == this
if 0 < dur[this] then
set dur[this] = dur[this] - TIMEOUT
else
call this.remove()
set id = GetHandleId(o[this])
set i = LoadInteger(ht, id, 0)
if i < SPELL_CHARGES then
call SaveInteger(ht, id, 0, i + 1)
endif
call po[this].destroy()
set po[this] = 0
set dur[this] = 0
endif
set this = n[this]
endloop
endmethod
static method create takes player pl, unit owner, real x, real y returns Portal
local Portal this = Portal.add()
local integer i = 0
set po[this] = Dummy.create(pl, x, y, PORTAL_Z, 0, PORTAL_MDL, PORTAL_SIZE)
set o[this] = owner
loop
exitwhen i == PORTAL_ORB_NUMBER
set i = i + 1
call Orb.create(PORTAL_ORB_MDL, pl, owner, PORTAL_ORB_Z, PORTAL_ORB_SIZE, PORTAL_ORB_DIST, PORTAL_ORB_SPIN_SPEED, PORTAL_DURATION, i * (360./ PORTAL_ORB_NUMBER))
endloop
set c = c + 1
if 1 == c then
call TimerStart(pt, TIMEOUT, true, function Portal.periodic)
endif
return this
endmethod
endstruct
private struct OrbMissile extends array
implement List
static Dummy array d
static unit array o
static real array di
static real array a
static method periodic takes nothing returns nothing
local OrbMissile this = n[0]
local real x
local real y
loop
exitwhen 0 == this
if 0 < di[this] then
set di[this] = di[this] + (ORB_MISSILE_SPEED * TIMEOUT)
set x = d[this].x + di[this] * Cos(a[this] * bj_DEGTORAD)
set y = d[this].y + di[this] * Sin(a[this] * bj_DEGTORAD)
call d[this].move(x, y)
set d[this].angle = a[this]
call DestroyEffect(AddSpecialEffect(ORB_SFX, x, y))
else
call d[this].destroy()
call Portal.create(GetOwningPlayer(o[this]), o[this], d[this].x, d[this].y)
set d[this] = 0
set di[this] = 0
set a[this] = 0
set o[this] = null
set c = c - 1
if 0 == c then
call PauseTimer(mt)
endif
endif
set this = n[this]
endloop
endmethod
static method create takes player p, unit owner, real dist, real angle returns OrbMissile
local OrbMissile this = OrbMissile.add()
local real x = GetUnitX(owner)
local real y = GetUnitX(owner)
set d[this] = Dummy.create(p, x, y, ORB_MISSILE_Z, angle, ORB_MISSILE_MDL, ORB_MISSILE_SIZE)
set a[this] = angle
set o[this] = owner
set di[this] = dist
return this
endmethod
endstruct
private struct ShardOrbs extends array
implement List
endstruct
private struct Spell extends array
implement List
endstruct
endlibrary
Curious, I take it those skulls mark the edge of the area medusa can stay within? I'm a bit concerned about sfx spam on that one (since it seems even more spammy than mine XD) but it looks great nonetheless ^^
/*
Spell Name: Swirling Portal
Created by: mckill2009 (entry for Zephyr Contest #10 ~ What lies on the other side)
REQUIRED LIBRARIES and CREDITS:
- CTL by Nesthaurus
- Table by Bribe
- RegisterPlayerUnitEvent by Magtheridon96
- SpellEffectEvent by Bribe
- IsUnitChanneling by Magtheridon96
- GroupUtils by Rising Dusk
*/
scope SwirlingPortal
globals
//Configurable Block
private constant integer SPELL_ID = 'A000' //based on Rain of Fire
private constant integer DUMMY_ID = 'h003'
private constant integer MISSILE_ID = 'h000'
private constant real PULL_TOLERANCE = 4 //recommended, pull from center
private constant real PORTAL_SHAPE = 6 //changes the 'shape' of the portal, recommended setting 1-7
private constant real OFFSET_SPEED = 1.5 //this affects PORTAL_SHAPE, recommemded setting 1.5
private constant real AOE = 400 //This should synchronize with the AOE from object editor
private constant real SKELETON_LIFE = 15
private constant string MOONSOON = "Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl"
private constant string STAR = "Abilities\\Spells\\NightElf\\Starfall\\StarfallCaster.mdl"
private constant string SUMMON_SKELETONS = "Abilities\\Spells\\Undead\\RaiseSkeletonWarrior\\RaiseSkeleton.mdl"
private constant boolean ENABLE_CHANCE = true
//Non-configurable Block
private Table c
private group g = CreateGroup()
private integer array monsterId
private integer array skeletonId
private real PartAoe
private integer Count = 0
endglobals
//===Configurable Block
private function GetChance takes integer i returns integer
return 10 * i
endfunction
private function GetCountSkeletons takes integer i returns integer
return 3 * i
endfunction
//===Non-configurable Block
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private function Pull takes unit caster, real xCenter, real yCenter, real aoe returns nothing
local unit first
local real angle
local real x
local real y
call GroupEnumUnitsInRange(g, xCenter, yCenter, aoe, null)
loop
set first = FirstOfGroup(g)
exitwhen first==null
if UnitAlive(first) and IsUnitEnemy(caster, GetOwningPlayer(first)) and not IsUnitType(first, UNIT_TYPE_STRUCTURE) and not IsUnitType(first, UNIT_TYPE_FLYING) then
set x = GetUnitX(first)
set y = GetUnitY(first)
set angle = Atan2(yCenter-y, xCenter-x)
call SetUnitX(first, x+PULL_TOLERANCE*Cos(angle))
call SetUnitY(first, y+PULL_TOLERANCE*Sin(angle))
endif
call GroupRemoveUnit(g, first)
endloop
endfunction
private function CountUnits takes nothing returns nothing
local unit u = GetEnumUnit()
if UnitAlive(u) then
set Count = Count + 1
endif
endfunction
//=====================================================
private struct Fire extends array
unit missile
real angle
real xDist
real yDist
real distance
integer casterId
implement CTLExpire
if .distance > 0 then
set .distance = .distance - OFFSET_SPEED
call SetUnitX(.missile, .xDist+.distance * Cos(.angle))
call SetUnitY(.missile, .yDist+.distance * Sin(.angle))
else
set c[.casterId] = c[.casterId]-1
call KillUnit(.missile)
if c[.casterId]==0 and c.boolean[casterId] then
call DestroyEffect(AddSpecialEffect(MOONSOON, .xDist, .yDist))
call DestroyEffect(c.effect[casterId])
call KillUnit(c.unit[casterId])
//DOOOOOOOOOOOOOOOOOOOOOO
endif
set .missile = null
call .destroy()
endif
implement CTLEnd
static method fire takes unit u, real angle, real xTo, real yTo, integer Id returns nothing
local thistype this = create()
set .missile = u
set .angle = angle
set .xDist = xTo
set .yDist = yTo
set .distance = SquareRoot((xTo-GetUnitX(u))*(xTo-GetUnitX(u))+(yTo-GetUnitY(u))*(yTo-GetUnitY(u)))
set .casterId = Id
endmethod
endstruct
private struct SP extends array
unit caster
unit dummy
unit monster
real angle
real offset
real offsetBack
real xSpell
real ySpell
real delay
integer casterId
integer level
integer maxSkeletons
boolean isChanneling
boolean skelOn
group skeletonG
implement CTL
local unit missile
local unit skeleton
local real xRandom
local real yRandom
local real randomAngle
implement CTLExpire
if IsUnitChanneling(.caster) and .isChanneling then
if AOE > .offset then
set .offset = .offset + OFFSET_SPEED
set .angle = .angle + PORTAL_SHAPE
call SetUnitX(.dummy, .xSpell + .offset * Cos(.angle))
call SetUnitY(.dummy, .ySpell + .offset * Sin(.angle))
set missile = CreateUnit(Player(15), MISSILE_ID, GetUnitX(.dummy), GetUnitY(.dummy), 0)
set c[.casterId] = c[.casterId]+1
call Fire.fire(missile, .angle, .xSpell, .ySpell, .casterId)
call Pull(.caster, .xSpell, .ySpell, .offset)
set missile = null
elseif .offsetBack > 0 then
set .offsetBack = .offsetBack - OFFSET_SPEED
call Pull(.caster, .xSpell, .ySpell, .offsetBack)
else
set .skelOn = false
call IssueImmediateOrder(.caster, "stop")
endif
static if ENABLE_CHANCE then
set .delay = .delay + 0.03125
if .delay > 1 then
set .delay = 0
if (.offset > PartAoe) and (GetRandomInt(0,100) < GetChance(.level)) and .skelOn then
set Count = 0
call ForGroup(.skeletonG, function CountUnits)
if Count < .maxSkeletons then
set randomAngle = GetRandomReal(0, 6.2)
if AOE > .offset then
set xRandom = .xSpell+GetRandomReal(10, .offset)*Cos(randomAngle)
set yRandom = .ySpell+GetRandomReal(10, .offset)*Sin(randomAngle)
else
set xRandom = .xSpell+GetRandomReal(10, .offsetBack)*Cos(randomAngle)
set yRandom = .ySpell+GetRandomReal(10, .offsetBack)*Sin(randomAngle)
endif
set skeleton = CreateUnit(GetOwningPlayer(.caster), skeletonId[GetRandomInt(0,1)],xRandom, yRandom, 0)
call UnitApplyTimedLife(skeleton, 'BTLF', SKELETON_LIFE)
call GroupAddUnit(.skeletonG, skeleton)
call DestroyEffect(AddSpecialEffect(SUMMON_SKELETONS, xRandom, yRandom))
set skeleton = null
endif
endif
endif
endif
else
set c.boolean[casterId ] = false
call KillUnit(.dummy)
call DestroyEffect(c.effect[casterId])
call ReleaseGroup(.skeletonG)
set .caster = null
set .dummy = null
call .destroy()
endif
implement CTLEnd
static method run takes nothing returns nothing
local thistype this = create()
set .caster = GetTriggerUnit()
set .xSpell = GetSpellTargetX()
set .ySpell = GetSpellTargetY()
set .dummy = CreateUnit(Player(15), DUMMY_ID, .xSpell, .ySpell, 0)
set .level = GetUnitAbilityLevel(.caster, SPELL_ID)
set .delay = 0
set .offset = 10
set .offsetBack = AOE
set .angle = 0
set .isChanneling = true
set .skelOn = true
set .casterId = GetHandleId(.caster)
set .maxSkeletons = GetCountSkeletons(.level)
set .skeletonG = NewGroup()
set c[casterId] = 0
set c.boolean[casterId] = true
set c.unit[casterId] = .dummy
set c.effect[casterId] = AddSpecialEffect(STAR, .xSpell, .ySpell)
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.run)
set c = Table.create()
set PartAoe = AOE*0.7
set skeletonId[0] = 'uske'
set skeletonId[1] = 'uskm'
//DOOOOOOOOOOOOOOOOOOOOOOOOO
set monsterId[0] = 123
endmethod
endstruct
endscope
coz you cant call a private method outside it called for...@mckill
why not private?
/*
Spell Name: Swirling Portal
Created by: mckill2009 (entry for Zephyr Contest #10 ~ What lies on the other side)
REQUIRED LIBRARIES and CREDITS:
- CTL by Nesthaurus
- Table by Bribe
- SpellEffectEvent by Bribe
- IsUnitChanneling by Magtheridon96
- GroupUtils by Rising Dusk
- IsTerrainWalkable by Anitarf
- WorldBounds by Nesthaurus
- Jumper by mckill2009
HOW TO INSTALL:
- Copy all the objects (units/abilities/buffs) to your map
- Change the rawID of the SPELL_ID, DUMMY_ID and MISSILE_ID if needed
- Copy the folder 'SwirlingPortal' to your map
- Add the SwirlingPortal ability to your hero
*/
scope SwirlingPortal
globals
//Configurable Block
private constant integer SPELL_ID = 'A000' //based on Rain of Fire, change the rawID if necessary
private constant integer DUMMY_ID = 'h000' //change the rawID if necessary
private constant integer MISSILE_ID = 'h001' //change the rawID if necessary
private constant integer MAX_MONSTER = 5 //used in randomizing the demon (see the onInit)
private constant integer MAX_SKELETON = 2 //used in randomizing the skeletons (see the onInit)
private constant real PULL_TOLERANCE = 4 //recommended, pull from center
private constant real PORTAL_SHAPE = 2 //changes the 'shape' of the portal, recommended setting 1-7
private constant real OFFSET_SPEED = 1.5 //this affects PORTAL_SHAPE, recommemded setting 1.5
private constant real AOE = 400 //This should synchronize with the AOE from object editor
private constant real FLY_SPEED = 10
private constant real FLY_HEIGHT = 350
private constant real FLY_DISTANCE = 400
private constant real SKELETON_LIFE = 15
private constant string MOONSOON = "Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl"
private constant string STAR = "Abilities\\Spells\\NightElf\\Starfall\\StarfallCaster.mdl"
private constant string SUMMON_SKELETONS = "Abilities\\Spells\\Undead\\RaiseSkeletonWarrior\\RaiseSkeleton.mdl"
private constant string SUMMON_DEMON = "Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl"
private constant string JUMP_SFX = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
private constant boolean ENABLE_CHANCE = true
//Non-configurable Block
private Table c
private group g = CreateGroup()
private integer array monsterId
private integer array skeletonId
private real PartAoe
private integer Count = 0
endglobals
//===Configurable Block
private function GetChance takes integer i returns integer
return 10 * i
endfunction
private function GetCountSkeletons takes integer i returns integer
return 3 * i
endfunction
private function FilterUnits takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_FLYING)
endfunction
//===Non-configurable Block
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
private function GetParabolaZ takes real h, real d, real x returns real
return (4 * h / d) * (d - x) * (x / d)
endfunction
private function Pull takes unit caster, real xCenter, real yCenter, real aoe returns nothing
local unit first
local real angle
local real x
local real y
call GroupEnumUnitsInRange(g, xCenter, yCenter, aoe, null)
loop
set first = FirstOfGroup(g)
exitwhen first==null
if IsUnitEnemy(caster, GetOwningPlayer(first)) and FilterUnits(first) then
set x = GetUnitX(first)
set y = GetUnitY(first)
set angle = Atan2(yCenter-y, xCenter-x)
call SetUnitX(first, x+PULL_TOLERANCE*Cos(angle))
call SetUnitY(first, y+PULL_TOLERANCE*Sin(angle))
endif
call GroupRemoveUnit(g, first)
endloop
endfunction
private function CountUnits takes nothing returns nothing
local unit u = GetEnumUnit()
if UnitAlive(u) then
set Count = Count + 1
endif
set u = null
endfunction
//=====================================================
private struct Fire extends array
unit missile
real angle
real xDist
real yDist
real distance
integer casterId
method jump takes unit monster returns nothing
local unit first
local real randomAngle = GetRandomReal(-bj_PI, bj_PI)
local Jumper j
call GroupEnumUnitsInRange(g, .xDist, .yDist, AOE, null)
loop
set first = FirstOfGroup(g)
exitwhen first==null
if IsUnitEnemy(monster, GetOwningPlayer(first)) and FilterUnits(first) then
set j = j.jump(first)
set j.angle = GetRandomReal(-bj_PI, bj_PI)
set j.distance = FLY_DISTANCE
set j.height = FLY_HEIGHT
set j.speed = FLY_SPEED
endif
call GroupRemoveUnit(g, first)
endloop
endmethod
implement CTL
local unit monster
local integer hID
implement CTLExpire
if .distance > 0 then
set .distance = .distance - OFFSET_SPEED
call SetUnitX(.missile, .xDist+.distance * Cos(.angle))
call SetUnitY(.missile, .yDist+.distance * Sin(.angle))
else
set c[.casterId] = c[.casterId]-1
call KillUnit(.missile)
if c[.casterId]==0 and c.boolean[.casterId] then
call DestroyEffect(AddSpecialEffect(MOONSOON, .xDist, .yDist))
call DestroyEffect(c.effect[.casterId])
set monster = CreateUnit(GetOwningPlayer(.missile), monsterId[GetRandomInt(1, MAX_MONSTER)], .xDist, .yDist, 0)
call DestroyEffect(AddSpecialEffect(SUMMON_DEMON, GetUnitX(monster), GetUnitY(monster)))
call DestroyEffect(AddSpecialEffect(JUMP_SFX, GetUnitX(monster), GetUnitY(monster)))
call jump(monster)
set monster = null
endif
set .missile = null
call .destroy()
endif
implement CTLEnd
static method fire takes unit u, real angle, real xTo, real yTo, integer Id returns nothing
local thistype this = create()
set .missile = u
set .angle = angle
set .xDist = xTo
set .yDist = yTo
set .distance = SquareRoot((xTo-GetUnitX(u))*(xTo-GetUnitX(u))+(yTo-GetUnitY(u))*(yTo-GetUnitY(u)))
set .casterId = Id
endmethod
endstruct
private struct SP extends array
unit caster
unit dummy
unit monster
real angle
real offset
real offsetBack
real xSpell
real ySpell
real delay
integer casterId
integer level
integer maxSkeletons
boolean isChanneling
boolean skelOn
group skeletonG
player pl
implement CTL
local unit missile
local unit skeleton
local real xRandom
local real yRandom
local real randomAngle
implement CTLExpire
if IsUnitChanneling(.caster) and .isChanneling then
if AOE > .offset then
set .offset = .offset + OFFSET_SPEED
set .angle = .angle + PORTAL_SHAPE
call SetUnitX(.dummy, .xSpell + .offset * Cos(.angle))
call SetUnitY(.dummy, .ySpell + .offset * Sin(.angle))
set missile = CreateUnit(.pl, MISSILE_ID, GetUnitX(.dummy), GetUnitY(.dummy), 0)
set c[.casterId] = c[.casterId]+1
call Fire.fire(missile, .angle, .xSpell, .ySpell, .casterId)
call Pull(.caster, .xSpell, .ySpell, .offset)
set missile = null
elseif .offsetBack > 0 then
set .offsetBack = .offsetBack - OFFSET_SPEED
call Pull(.caster, .xSpell, .ySpell, .offsetBack)
else
set .skelOn = false
call IssueImmediateOrder(.caster, "stop")
endif
static if ENABLE_CHANCE then
set .delay = .delay + 0.03125
if .delay > 1 then
set .delay = 0
if (.offset > PartAoe) and (GetRandomInt(0,100) < GetChance(.level)) and .skelOn then
set Count = 0
call ForGroup(.skeletonG, function CountUnits)
if Count < .maxSkeletons then
set randomAngle = GetRandomReal(-bj_PI, bj_PI)
if AOE > .offset then
set xRandom = .xSpell+GetRandomReal(10, .offset)*Cos(randomAngle)
set yRandom = .ySpell+GetRandomReal(10, .offset)*Sin(randomAngle)
else
set xRandom = .xSpell+GetRandomReal(10, .offsetBack)*Cos(randomAngle)
set yRandom = .ySpell+GetRandomReal(10, .offsetBack)*Sin(randomAngle)
endif
set skeleton = CreateUnit(GetOwningPlayer(.caster), skeletonId[GetRandomInt(1,MAX_SKELETON)],xRandom, yRandom, 0)
call UnitApplyTimedLife(skeleton, 'BTLF', SKELETON_LIFE)
call GroupAddUnit(.skeletonG, skeleton)
call DestroyEffect(AddSpecialEffect(SUMMON_SKELETONS, xRandom, yRandom))
set skeleton = null
endif
endif
endif
endif
else
set c.boolean[casterId ] = false
call KillUnit(.dummy)
call DestroyEffect(c.effect[casterId])
call ReleaseGroup(.skeletonG)
set .caster = null
set .dummy = null
call .destroy()
endif
implement CTLEnd
static method run takes nothing returns nothing
local thistype this = create()
set .caster = GetTriggerUnit()
set .xSpell = GetSpellTargetX()
set .ySpell = GetSpellTargetY()
set .dummy = CreateUnit(Player(15), DUMMY_ID, .xSpell, .ySpell, 0)
set .level = GetUnitAbilityLevel(.caster, SPELL_ID)
set .delay = 0
set .offset = 10
set .offsetBack = AOE
set .angle = 0
set .isChanneling = true
set .skelOn = true
set .casterId = GetHandleId(.caster)
set .maxSkeletons = GetCountSkeletons(.level)
set .pl = GetTriggerPlayer()
set .skeletonG = NewGroup()
set c[casterId] = 0
set c.boolean[casterId] = true
set c.effect[casterId] = AddSpecialEffect(STAR, .xSpell, .ySpell)
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.run)
set c = Table.create()
set PartAoe = AOE*0.7
//uses MAX_SKELETON
set skeletonId[1] = 'uske'
set skeletonId[2] = 'uskm'
//uses MAX_MONSTER
set monsterId[1] = 'nbal'
set monsterId[2] = 'nvde'
set monsterId[3] = 'ndrv'
set monsterId[4] = 'nrvd'
set monsterId[5] = 'nerw'
endmethod
endstruct
endscope