////////////////////////////////////////////////////////////////////
// SOUL TEAR AURA V1.00 //
// //
// Author: Tank-Commander //
// Requires: Dummy.mdl //
// Purpose: Tide-turner //
// //
// Notes: //
// - Read the readme before you try modifying the config //
// - Use the "Helpful files" to help you import the spell //
// //
// Credits: //
// - (Dummy.mdl) Vexorian //
// //
// //
// If you have used this spell in your map, you are required //
// to give credits to Tank-Commander for the creation of it //
// If you would like to use snippets of code from this for //
// whatever, getting permission and crediting the source/linking //
// would be much appreciated. //
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// README: //
// Before modifying this spell a few things need to be //
// understood and read, this is one of those things, while //
// most modification can be considered intuitive, it still //
// helps to read through these intstructions, as they will //
// inform you about how to configure this spell to your //
// desire. //
//----------------------------------------------------------------//
// Initial importing: The variable creator trigger can be //
// imported first and if you have the correct settings (file, //
// preferences, General, automatically create unknown variables //
// checked, then when you paste in the variable creator it //
// will automatically give you all the variables you need for //
// this spell //
//----------------------------------------------------------------//
// Effect Sets: The simple trigger comment "Effect Sets" is for //
// temporarily storing effect strings so that they can be added //
// to the spell more easily, as well as for storing multiple //
// sets without having to re-find the effect strings, largely //
// for finding the set you wish to use and trying out various //
// combinations //
//----------------------------------------------------------------//
// This configuration is ordered by category of use, and not //
// alphabetically, the ones you're most likely to want to //
// change, are earlier in the readme, the most essential being //
// first. These categories are: //
// //
// - Data Values: The most essential to change, otherwise the //
// spell will simply not function //
// //
// - ChronoKinetic: Fancy word for affecting the flow of time //
// Contains things like the duration of the //
// spell, the Timer speed and Fragment removal //
// //
// - Aesthetics: Controls the Appearences of the ability - the //
// models used, the scales of those models and //
// so on //
// //
// - Damage: Controls the AOE and damage (health and mana) //
// values each section of the spell has/uses //
// as well as projectile speeds and movement //
// (since it affects how effective the aura is) //
// //
// - Damage Information: Contains things like weapontypes and //
// damage types, etc. //
// //
// - Other Attributes: Contains the collision size of the //
// Fragments, causes them to detonate //
//----------------------------------------------------------------//
// DATA VALUES //
//----------------------------------------------------------------//
// Ability ID: This is the raw data of the Aura ability, to see //
// raw data in the object editor, press Ctrl + D, doing this //
// again will switch it back, if you want to change this Spell //
// follow as displayed (use the first 4 characters in the raw //
// data and put them in ' markers) //
constant function STA_AbilityID takes nothing returns integer
return 'A000'
endfunction
//----------------------------------------------------------------//
// Buff Ability ID: This is the ability used to apply the buff //
// icon/description to affected units, in order to make the //
// aura function near-exactly to normal Warcraft 3 auras, also //
// unlike most Auras, this enabled magic-immunes to be filtered //
// out from being effected, while not giving them the buff icon //
// it also removes dependance on the the dummy ability having //
// any range, so the dummy Ability used for the aura can be any //
// passive spell, or even an active one with it's own effect. //
// This Buff ability should be based off Slow Aura (Tornado) as //
// it does not display on the command panel of units which have //
// it as an ability, this is to improve visuals, it should have //
// all values which affect units set to 0, though if you want a //
// slowing effect added (attack &/or movespeed) to the aura //
// then these values can be modified to add it, set the buff //
// you want displayed on units set as it's buff, it should also //
// have AOE set to 0 just in case. //
constant function STA_BuffAbilityID takes nothing returns integer
return 'A001'
endfunction
//----------------------------------------------------------------//
// Dummy ID: This is done in the same manner as the Ability ID //
// except that this time, you're doing it with unit raw date //
// see the dummy unit if you do not know already how to view //
// raw data //
constant function STA_DummyID takes nothing returns integer
return 'u000'
endfunction
//----------------------------------------------------------------//
// CHRONOKINETIC //
//----------------------------------------------------------------//
// Timer Speed: The default for this is ~0.03, it determines how //
// many times per second these triggers are ran, normally you //
// want to leave this at ~0.03, but 0.04 and prehaps 0.05 //
// would be good options if you computer lags a bit. //
constant function STA_TimerRate takes nothing returns real
return 0.031250000
endfunction
//----------------------------------------------------------------//
// Check Timer Rate: The default value for this is 0.25, this //
// timer is used for checking the map for all units which have //
// the aura, and primarily serves to initialise these units //
// which wouldn't be picked up by the standard "learn" method //
// this includes units which are created at runtime through //
// trigger actions, ones already placed on the map and those //
// which are trained, starting with the aura //
constant function STA_CheckTimerRate takes nothing returns real
return 0.25
endfunction
//----------------------------------------------------------------//
// Check Timer Periodic: Determines whether or not the Check //
// Timer runs constantly all the time without stopping, thus //
// allowing it to pick up more than pre-placed units, this //
// should always be set to false if no units will gain this //
// ability through any means other than learning it, or being //
// preplaced unit on the map, as it would just be wasteful //
constant function STA_CheckTimerPeriodic takes nothing returns boolean
return false
endfunction
//----------------------------------------------------------------//
// Dummy Removal Delay: Determines how long after the death of a //
// fragment, for it be removed from the game completely, this is //
// so death effects, can finish playing before the unit is //
// removed, 1.8 is default, 2 is probably excessive and in some //
// cases it's possible that 1 could be too little //
constant function STA_DummyRemovalDelay takes nothing returns real
return 1.8
endfunction
//----------------------------------------------------------------//
// Effect Reduction Delay: Determines how long between each //
// bonus damage effect, before another one can be created, this //
// is because without this the effect would spam causing //
// a significant FPS drop, 0.5 is the defaults value of this //
constant function STA_EffectReductionDelay takes nothing returns real
return 0.5
endfunction
//----------------------------------------------------------------//
// AESTHETICS //
//----------------------------------------------------------------//
// Note: Effects must have valid pathnames and must not be set //
// to null values, otherwise graphical errors are likely to //
// occur, if an effect can be left null, it will be marked //
//----------------------------------------------------------------//
// Aura Effect: This determines the model used for your main //
// aura, you want to use the model path and paste it into the //
// double quotes or " markers, if the path has only single //
// slashes (\) you'll need to changeb it to double slash (\\) //
// before you save, the spell will not work if you do not do //
// this (if you acidentally save with the single slash (\) it //
// will still save but you may find yourself having a lingering //
// progress bar at full percentage, you can ignore it for the //
// most part, but if you have it, you probably haven't entered //
// this field correctly. Get the model paths from the Object //
// editor - find the model you want (the model, not the unit, //
// in the models list, select it and hit enter twice, then //
// select the path (will look similar to this default value, //
// and paste in it here) I suggest doing this with a unit of no //
// value (changing the model to get the model path) and then //
// reset the field afterwards to get the unit back to normal, //
// this function must return a valid value, to make "remove" //
// effects from the spell (for those without "Use" functions //
// to disable them) you can enter the path of dummy.mdl (this //
// can differ from map to map depending on how you imported it) //
// and this will cause the system to create invisible effects //
// so that the spell can still run properly //
constant function STA_AuraEffect takes nothing returns string
return "Abilities\\Spells\\Undead\\RegenerationAura\\ObsidianRegenAura.mdl"
endfunction
//----------------------------------------------------------------//
// Soul Fragment Effect:This determines the effect displayed on //
// enemies who are within the AOE of the aura, it is the buff //
// effect of the spell, and therefore must have a valid value //
constant function STA_SoulFragmentEffect takes nothing returns string
return "Abilities\\Spells\\Undead\\Curse\\CurseTarget.mdl"
endfunction
//----------------------------------------------------------------//
// Soul Fragment Projectile Effect: This is the effect used for //
// the projectiles or "spirits" that strike enemy targets which //
// activate the effect of the aura on impact, the same effect //
// is used for "spirits" that appear on unit death. //
constant function STA_SoulFragmentProjectileEffect takes nothing returns string
return "Abilities\\Weapons\\GreenDragonMissile\\GreenDragonMissile.mdl"
endfunction
//----------------------------------------------------------------//
// Initial Damage Effect: This determines the effect used when //
// a unit is hit by the homing spirits and activate the initial //
// effect, this is one of the few effects that can be null but //
// only if "Use Initial Damage Effect" is set to false //
constant function STA_InitialDamageEffect takes nothing returns string
return "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
endfunction
//----------------------------------------------------------------//
// Death Damage Effect: This determines the effect used when //
// a spirit created by a dying unit detonates dealing damage //
// typically this will be the same as "Initial Damage Effect" //
// and can also be null if "Use Death Damage Effect" is false //
constant function STA_DeathDamageEffect takes nothing returns string
return "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
endfunction
//----------------------------------------------------------------//
// Bonus Damage Effect: This determines the effect created when //
// a unit takes bonus magic damage from the aura, it's limited //
// by the "Effect Reduction Delay" value, it cannot be set to //
// null, however //
constant function STA_BonusDamageEffect takes nothing returns string
return "Abilities\\Spells\\Items\\AIil\\AIilTarget.mdl"
endfunction
//----------------------------------------------------------------//
// Heal Effect: This is the effect used when the hero creating //
// the aura effect dies and nearby enemies are healed afterward //
// this should have a positive look unless the value you give //
// for the damage value of the heal effect is set to a negative //
// if "Use Heal Effect" is false, then this can be set to null //
constant function STA_HealEffect takes nothing returns string
return "Abilities\\Spells\\Human\\DispelMagic\\DispelMagicTarget.mdl"
endfunction
//----------------------------------------------------------------//
// Aura Attachment Point: Set this to the desired attachment //
// point of the aura, typically this will be "origin" as most //
// warcraft 3 auras use it for this effect valid attachment //
// points include: "origin", "overhead", "head", "chest", and //
// "left, [limb]", "right, [limb]" limbs: "foot", "hand" //
constant function STA_AuraAttachmentPoint takes nothing returns string
return "origin"
endfunction
//----------------------------------------------------------------//
// Soul Fragment Attachment Point: This is the attachment point //
// of where the buff of being effected will appear, typically //
// this will be set to "overhead" as most Warcraft 3 auras use //
constant function STA_SoulFragmentAttachmentPoint takes nothing returns string
return "overhead"
endfunction
//----------------------------------------------------------------//
// Soul Fragmnet Projectile Attachment Point: The attachment //
// point for the projectile on the dummy unit, what this is set //
// to doesn't particularly make much difference so long as it's //
// valid, try various settings to get one you like the look of //
// typically, it'll be set to chest, just to centre it //
constant function STA_SoulFragmentProjectileAttachmentPoint takes nothing returns string
return "origin"
endfunction
//----------------------------------------------------------------//
// Initial Damage Attachment Point: This is the attachment //
// point of the effect created when the "Spirits" hit units to //
// activate the aura effect on them, this also doesn't normally //
// make any difference, typically it will be set to the same //
// value as "Soul Fragment Projectile Attachment Point" //
constant function STA_InitialDamageAttachmentPoint takes nothing returns string
return "chest"
endfunction
//----------------------------------------------------------------//
// Death Damage Attachment Point: Determines the attachment //
// point for the effect created when "Spirits" made by a unit //
// dying impact, this is typically set to the same value as //
// "Soul Fragment Projectile Attachment Point" but it doesn't //
// really make any difference so long as it's valid //
constant function STA_DeathDamageAttachmentPoint takes nothing returns string
return "chest"
endfunction
//----------------------------------------------------------------//
// BonusDamageAttachmentPoint: Determines the attachment point //
// of the effect generated when a unit takes bonus damage as a //
// result of the aura, "origin", "chest", and "overhead" all //
// suit this effect depending on the model used, for most it //
// looks/works best with "chest", however any can be used //
constant function STA_BonusDamageAttachmentPoint takes nothing returns string
return "chest"
endfunction
//----------------------------------------------------------------//
// Heal Effect Attachment Point: Controls the attachment point //
// of the heal effect created when the unit/hero with the aura //
// has died, similar to the bonus damage "origin", "chest" and //
// "overhead" are all good matches for this attachment point //
// for the same reason //
constant function STA_HealEffectAttachmentPoint takes nothing returns string
return "chest"
endfunction
//----------------------------------------------------------------//
// Soul Fragment Projectile Scale Base: This determines the //
// size of the projectiles created by the aura, the value is a //
// percentage, so 1 = 100%, and thus the default size of the //
// effect, depending on the effect used this will often need to //
// be a fractional value. Default is 0.6 or .6 //
constant function STA_SoulFragmentProjectileScaleBase takes nothing returns real
return .6
endfunction
//----------------------------------------------------------------//
// Soul Fragment Projectile Scale Per Level: The extra size //
// given to projectiles for every level of the spell, this is //
// normally 0, but available if users wish to alter the size //
// to make the spell appear more menacing as it levels up //
constant function STA_SoulFragmentProjectileScalePerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Soul Fragment Height Start Offset: This is the height added //
// on to the base height of the unit creating the effect, that //
// projectiles start at, 0 will be at their feet, 30 will often //
// be chets height, and 60 overhead, try out various heights to //
// see what you feel fits best //
constant function STA_SoulFragmentHeightStartOffset takes nothing returns real
return 100.
endfunction
//----------------------------------------------------------------//
// Soul Fragment Height End Offset: The same as above but for //
// the height added onto the target's fly height that will be //
// reached when the "Spirit"/Projectile hits the target rather //
// than start at, again 0 is foot height, 30 is chest and 60 is //
// overhead, typically this value is lower than the start height //
constant function STA_SoulFragmentHeightEndOffset takes nothing returns real
return 90.
endfunction
//----------------------------------------------------------------//
// Use Initial Damage Effect: This boolean value determines if //
// the effect generated by the "spirits" or projectiles hitting //
// their target to start the effect of the ability is used, //
// setting to false will remove it, and thus the model used for //
// the effect can be null, as giving it a value will not make //
// any difference //
constant function STA_UseInitialDamageEffect takes nothing returns boolean
return true
endfunction
//----------------------------------------------------------------//
// Use Death Damage Effect: Similar to the above boolean but //
// this one is for the effect created when projectiles made by //
// units dying impact and detonate, again setting it to false //
// removes the effect and thus enabled the value to be set to //
// null for the model string //
constant function STA_UseDeathDamageEffect takes nothing returns boolean
return true
endfunction
//----------------------------------------------------------------//
// Use Heal Effect: Once again the same as above, however in //
// this case for the effect generated when units are healed from //
// the Hero/Unit with the aura dying. unless the feature is //
// removed (setting the amount healed to 0) it makes sense for //
// this value to be set to true //
constant function STA_UseHealEffect takes nothing returns boolean
return true
endfunction
//----------------------------------------------------------------//
// DAMAGE //
//----------------------------------------------------------------//
// AOE Base: This is your basic area of effect for your ability //
// it should be the highest AOE of the ability as such, //
// typically, this value should be at least 200, units in this //
// area will have Fragment launched at them and begin the bonus //
// damage effect //
constant function STA_AOEBase takes nothing returns real
return 275.
endfunction
//----------------------------------------------------------------//
// AOE Per Level: This is the amount of extra AOE given on top //
// of the basic AOE for each level of the spell that the hero //
// has,this will also be applied for level one //
constant function STA_AOEPerLevel takes nothing returns real
return 75.
endfunction
//----------------------------------------------------------------//
// Search AOE Base: Determines how far away from the location //
// of a dying unit effected by the aura, will be considered a //
// valid target, keep in mind, targets which are effected by //
// the aura, even if a different unit is the source, are valid //
// If this is set to 0, alone with "Search AOE Per Level", the //
// effect of damage being done by units dying will be removed //
constant function STA_SearchAOEBase takes nothing returns real
return 90.
endfunction
//----------------------------------------------------------------//
// Search AOE Per Level: The Per Level value of the Search AOE //
// Base value, typically this will be a fraction of the base //
// value between 1/2 and 1/4 of the base value for balance //
// if this is set to 0, as well as "Search AOE Base", the effect //
// of extra damage being done by units dying will be removed //
constant function STA_SearchAOEPerLevel takes nothing returns real
return 35.
endfunction
//----------------------------------------------------------------//
// Impact AOE Base: Determines the AOE of the damaging effect //
// when a "Spirit" inflicts damage, this applies for both the //
// initial, homing projectiles, and the non-homing ones created //
// by unit death, this should be higher than the collision size //
// in order to avoid damageless impacts, and should be between //
// values of 50-100 typically, default is 75 //
constant function STA_ImpactAOEBase takes nothing returns real
return 75.
endfunction
//----------------------------------------------------------------//
// Impact AOE Per Level: Determines how much extra AOE damage //
// effects have on top of the Impact AOE Base, and applies at //
// level one, as with all Per Level values, typically this is //
// set between 0-20 for balancing reasons and to reduce chain //
// killing becoming too common/likely to take out huge sections //
// of enemies //
constant function STA_ImpactAOEPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Soul Fragment Projectile Speed Base: This is the true value //
// speed of projectiles, and how far the projectiles will move //
// per second, having a particularly high value (over 1000) will //
// likely cause accuracy issues and overshooting with the spell //
// a value between 200-500 is typical, default value is 288 //
constant function STA_SoulFragmentProjectileSpeedBase takes nothing returns real
return 288.
endfunction
//----------------------------------------------------------------//
// Soul Fragment Projectile Speed Per Level: The per level //
// counterpart of "Soul Fragment Projectile Speed Base", when //
// combined with that value, the total should not exceed 1200 //
// for the reasons described above, remember that this applies //
// even on the first level, a value between 0-200 is typical //
// default value is 192 //
constant function STA_SoulFragmentProjectileSpeedPerLevel takes nothing returns real
return 192.
endfunction
//----------------------------------------------------------------//
// Soul Fragment Projectile Hit Time Base: This is the optional //
// movement type of the projectiles, which alters the velocity //
// based on how long it takes for them to hit their target in //
// seconds, creating a rather different effect from using true //
// speed, this value in combination with the per level size //
// should not become lower than 1/6th of a second if inaccuracy //
// issues are to be avoided (units farther away with a short //
// hit time, generate much higher true speeds on the projectile) //
// WARNING: if the sum of this value and its per level side end //
// up with values less than 0.5, depending on the impact AOE //
// used by the spell, not only may inaccuracy occur, but the //
// game may crash due to projectiles getting too fast. This //
// normally occurs because the real speed applied to the //
// projectile exceeds the AOE of the impact area; with the //
// default set up, this means that the projectile has to be //
// moving at over 2500m/s, while applying this value to the real //
// speed option for the spell is unlikely to cause crashing; //
// it cannot be done here as if targets move away from the aura //
// projectiles speed up (in order to maintain the hit time) //
// meaning that if a projectile overshoots, it will only get //
// even faster, and typically leave the map (causing crash) //
constant function STA_SoulFragmentProjectileHitTimeBase takes nothing returns real
return 2.
endfunction
//----------------------------------------------------------------//
// Soul Fragment Projectile Hit Time Per Level: One of the only //
// values which is typically negative, this is so that the time //
// taken to hit targets is reduced every level, so that they //
// move faster, making this a positive value will makes them //
// slower, remember; this applies to level 1, as well. default //
// value is -0.4. Keep in mind that if the total becomes very //
// small, inaccuracy issues may occur (and possibly game crash) //
constant function STA_SoulFragmentProjectileHitTimePerLevel takes nothing returns real
return -0.5
endfunction
//----------------------------------------------------------------//
// Soul Fragment Movement Type: Determines the form of movement //
// used by the projectiles, true activated the Hit Time values //
// while false enables the Projectile Speed values or true //
// speed, the effect generated by the different movement types //
// are very different, so try out both if you're unsure //
constant function STA_SoulFragmentMovementType takes nothing returns boolean
return false
endfunction
//----------------------------------------------------------------//
// Initial Effect Health Damage Base: This is the amount of hp //
// damage dealt when the "Spirits"/Projectiles first hit enemy //
// units and start the effect of the aura on them reducing it //
// to 0 removes all damage and makes the first stage simply an //
// activation effect. The true damage dealt by this effect is //
// affected by type of damage used by the aura //
constant function STA_InitialEffectHealthDamageBase takes nothing returns real
return 25.
endfunction
//----------------------------------------------------------------//
// Initial Effect Health Damage Per Level: The per level side //
// to the base health damage, added on to the base value even //
// at level 1 as with all per level values. to remove the //
// effect this should also be set to 0 //
constant function STA_InitialEffectHealthDamagePerLevel takes nothing returns real
return 10.
endfunction
//----------------------------------------------------------------//
// Initial Effect Mana Damage Base: Determines how much mana //
// damage is done by the initial activation effect of the aura //
// typically this is 0, but is available if users wish to have //
// it, this is a true value and is thus unaffected by the type //
// of damage used by the aura if set to a negative value, it //
// will restore mana to targets rather than remove it //
constant function STA_InitialEffectManaDamageBase takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Initial Effect Mana Damage Per Level: Determines how much //
// extra mana damage is dealt by the spell per level, typically //
// also set to 0, but again available if users wish to have it //
constant function STA_InitialEffectManaDamagePerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Death Health Damage Base: This is the amount of Hp damage //
// dealt by "Spirits"/Projectiles created by units dying with //
// the aura affecting them, actual damage dealt by this is //
// altered by the type of damage used by the spell rather than //
// a fixed value, typically this is the main damage dealing part //
// of the ability and causes chain-kills even with low values //
constant function STA_DeathHealthDamageBase takes nothing returns real
return 10.
endfunction
//----------------------------------------------------------------//
// Death Health Damage Per Level: The extra amount of Hp damage //
// dealt by the "Spirits"/Projectiles created by units dying //
// with the aura affecting them, very similar to the Base part //
constant function STA_DeathHealthDamagePerLevel takes nothing returns real
return 20.
endfunction
//----------------------------------------------------------------//
// Death Mana Damage Base: The Base mana damage dealt by the //
// "Spirits"/Projectiles created by units dying with the aura //
// affecting them, this is true damage and is thus unaffected //
// by the type of damage used by the spell, setting this to a //
// negative value will restore mana rather than damage enemies //
constant function STA_DeathManaDamageBase takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Death Mana Damage Per Level: The per level counterpart to //
// "Death Mana Damage Base", also true damage and added on to //
// all levels (multiplied by the level of the ability) //
constant function STA_DeathManaDamagePerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Bonus Health Damage Percent Base: Determines the amount of //
// bonus Hp damage dealt by all damage sources on the affected //
// units, only activated after they have been hit by the //
// initial "Spirit"/Projectile. This is a percentage value thus //
// setting this value to 1 = 100% damage increase, typically //
// this should be a low percentage, as damage adds up quickly //
// the resulting damage of this is affected by the damage type //
// used by the ability, default value is 0.1 or .1 (10%) //
constant function STA_BonusHealthDamagePercentBase takes nothing returns real
return .05
endfunction
//----------------------------------------------------------------//
// Bonus Health Damage Percent Per Level: The Per Level side to //
// The "Bonus Health Damage Percent Base", typically a lower //
// fractional number, 0.05 or .5 is the default (5%) //
constant function STA_BonusHealthDamagePercentPerLevel takes nothing returns real
return .025
endfunction
//----------------------------------------------------------------//
// Bonus Mana Damage Percent Base: Determines the amount of //
// bonus Mana damage dealt by all mana damage sources to the //
// affected units, only starts applying once they have been hit //
// by the initial "Spirit"/Projectile. Also a percentage value //
// but a True value, thus unaffected by the damage type of the //
// ability, setting it to a negative value will restore mana //
// instead of destroying it //
constant function STA_BonusManaDamagePercentBase takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Bonus Mana Damage Percent Per Level: A Per Level counterpart //
// to the Base value, typically lower than that Base value, and //
// even then often less than 10% or 0.1 (.1) //
constant function STA_BonusManaDamagePercentPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Hero Health Heal Base: This is the amount of health restored //
// to enemy units when the hero generating the aura has been //
// slain, default value is 100, this is a true value and thus //
// ingores damage type used by the spell, unlike all other //
// health damage dealt by this aura. Setting this to a negative //
// value will cause it to deal damage rather than heal enemies //
// WARNING: This damage does not recognise the damage source, //
// Units killed by this effect will NOT give gold to the owner //
// of the unit with the aura, nor count as them having killed //
// those units //
constant function STA_HeroHealthHealBase takes nothing returns real
return 100.
endfunction
//----------------------------------------------------------------//
// Hero Health Heal Per Level: The extra health given to units //
// when the unit/hero generating the aura has been slain, this //
// is added on to the Base value (multiplied by the level of //
// the aura) and is a true value //
constant function STA_HeroHealthHealPerLevel takes nothing returns real
return 50.
endfunction
//----------------------------------------------------------------//
// Hero Mana Heal Base: Determines the amount of mana given to //
// units when the unit/hero creating the aura is slain, it is a //
// true value thus unaffected by the damagetype used by the //
// aura, setting this to a negative value will remove mana //
// rather than add it //
constant function STA_HeroManaHealBase takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Hero Mana Heal Per Level: The extra amount of mana given to //
// units when the unit/hero creating the aura is slain, also a //
// true value and added on (multiplied by the level of the aura) //
// to the base value, setting this to a negative value will //
// remove mana rather than add it //
constant function STA_HeroManaHealPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// DAMAGE INFORMATION //
//----------------------------------------------------------------//
// Damage Type: These determine the damagetypes, changing this //
// will modify the damage multiplyers vs certain enemies //
// the standard is DAMAGE_TYPE_MAGIC, note that this spell //
// automatically discludes magic immunes, so changing this //
// damage type will not make them start taking damage //
constant function STA_AttackType takes nothing returns attacktype
return ATTACK_TYPE_MAGIC
endfunction
//----------------------------------------------------------------//
// Attack Type: This is very much so basically the same as //
// Damage Type, generally you'll want this to match with it //
// as such the default is ATTACK_TYPE_MAGIC, though Damagetype //
// is a key factor for determining bonuses rather than this //
// but unlike weapontype, you cannot have null as a setting //
constant function STA_DamageType takes nothing returns damagetype
return DAMAGE_TYPE_MAGIC
endfunction
//----------------------------------------------------------------//
// Weapon Type: This alters what kind of weapon type is used by //
// the spell, those without knowledge of weapontypes don't //
// worry, you're not missing much, this spell doesn't really //
// use it, hence the default of null, but if you want to use //
// them, no reason to not. //
constant function STA_WeaponType takes nothing returns weapontype
return null
endfunction
//----------------------------------------------------------------//
// OTHER ATTRIBUTES //
//----------------------------------------------------------------//
// Collision Size: Used for determining at what point has a //
// Fragment hit a target, you typically want this value above //
// 30 but below 90, and it should always be larger than the //
// Damage AOE of the spell, otherwise the system will register //
// a collision, and then fail to deal any damage to the units //
constant function STA_CollisionSize takes nothing returns real
return 30.
endfunction
// Dummy Owner: Used for what player owns all the dummy units //
// typically this is Player(14) but can really be used any //
// player number that is not in use in the map this spell is //
// used in //
constant function STA_DummyOwner takes nothing returns player
return Player(14)
endfunction
//----------------------------------------------------------------//
// You have now reached the end of the configuration, below are //
// the functions used to run the spell, beyond this point if //
// you find any constant values (indicated in Blue like the //
// other constants here if you have standard syntax highlighting //
// they're there for a reason and don't fiddle with them, to //
// actually make any modifications I hope you're an experienced //
// programmer, though do not hassle for help because I don't //
// take responcibility for other people's programming skills //
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function used to get the z height of locations needed by the //
// spell, since it can only be done with locations, this one //
// is reused throughout, instead of creating/destroying them //
////////////////////////////////////////////////////////////////////
function STA_GetZ takes real x, real y returns real
//Gets the location Z of the selected location
call MoveLocation(udg_STA_ZLoc, x, y)
return GetLocationZ(udg_STA_ZLoc)
endfunction
////////////////////////////////////////////////////////////////////
// Function used to calculate the speed of which any given //
// projectile must travel based on the form of movement that //
// has been selected in the configuration by the user //
////////////////////////////////////////////////////////////////////
function STA_GetSpeed takes integer Node, real Distance returns real
//Calculate Speed
if (STA_SoulFragmentMovementType()) then
return (Distance / udg_STA_SoulProjectileHitTime[Node]) * STA_TimerRate()
else
return udg_STA_SoulProjectileSpeed[Node] * STA_TimerRate()
endif
endfunction
////////////////////////////////////////////////////////////////////
// Function used to recycle instances, so that they can used //
// again later, keeping the total array sizes smaller //
////////////////////////////////////////////////////////////////////
function STA_Recycle takes integer Node, timer T returns nothing
if (udg_STA_LastNode == Node) then
set udg_STA_LastNode = udg_STA_PrevNode[Node]
endif
//Recycles the node
set udg_STA_RecycleNodes[udg_STA_RecyclableNodes] = Node
set udg_STA_RecyclableNodes = udg_STA_RecyclableNodes + 1
set udg_STA_NextNode[udg_STA_PrevNode[Node]] = udg_STA_NextNode[Node]
set udg_STA_PrevNode[udg_STA_NextNode[Node]] = udg_STA_PrevNode[Node]
set udg_STA_AbilityCounter = udg_STA_AbilityCounter - 1
//Checks if there are no iterations of the aura left
//this is ,mostly an "in-case" part of the script, as it
//is unlikely that this ever returns true (only if a unit unlearns the ability)
if (udg_STA_AbilityCounter == 0) then
call DestroyTimer(T)
endif
endfunction
/////////////////////////////////////////////////////////////////////
// Target filter function - passed units and players and checks //
// if the unit is allowed to be targetted by this ability //
/////////////////////////////////////////////////////////////////////
function STA_TargetFilter takes unit u, player pl returns boolean
//Checks if the unit can be used as a target
if (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)) and (IsUnitEnemy(u, pl)) and (GetUnitTypeId(u) != STA_DummyID()) and not(IsUnitType(u, UNIT_TYPE_DEAD) or GetUnitTypeId(u) == 0) then
return true
endif
return false
endfunction
////////////////////////////////////////////////////////////////////
// This function handles the damage dealt to units by the //
// projectiles, including health and mana in one function, //
// since both forms of projectile use the same damage method //
////////////////////////////////////////////////////////////////////
function STA_SoulProjectileDamage takes real x, real y, integer Node returns nothing
//Declare Locals
local unit u
local player pl = udg_STA_OwningPlayer[Node]
//Finds units within the AOE of the impact point which may be damaged
call GroupEnumUnitsInRange(udg_STA_TempGroup, x, y, udg_STA_ImpactAOE[udg_STA_CasterNode[Node]], null)
loop
//Scanning through
set u = FirstOfGroup(udg_STA_TempGroup)
exitwhen u == null
//Select all the units which are to be damaged
if (STA_TargetFilter(u, pl)) then
call UnitDamageTarget(udg_STA_Caster[Node], u, udg_STA_HealthDamage[Node], false, false, STA_AttackType(), STA_DamageType(), STA_WeaponType())
call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MANA) - udg_STA_ManaDamage[Node])
endif
//Remove the unit from the unit group
call GroupRemoveUnit(udg_STA_TempGroup, u)
endloop
//Null variables
set pl = null
endfunction
////////////////////////////////////////////////////////////////////
// Function used to create each projectile and set up all the //
// information they need to run, since both the caster and the //
// affected units can produce these projectiles //
////////////////////////////////////////////////////////////////////
function STA_CreateProjectile takes real x, real y, real z, real zSpeed, real Speed, real Angle, real Distance, real HealthDamage, real ManaDamage, integer Node, boolean Type, integer Target returns nothing
//Create Locals
local integer TempNode
//Adds a new instance to the linked list
set udg_STA_AbilityCounter = udg_STA_AbilityCounter + 1
//Checking for recycleable Nodes
if (udg_STA_RecyclableNodes == 0) then
set udg_STA_NodeNumber = udg_STA_NodeNumber + 1
set TempNode = udg_STA_NodeNumber
else
set udg_STA_RecyclableNodes = udg_STA_RecyclableNodes - 1
set TempNode = udg_STA_RecycleNodes[udg_STA_RecyclableNodes]
endif
//Adds a new instance
set udg_STA_NextNode[TempNode] = 0
set udg_STA_NextNode[udg_STA_LastNode] = TempNode
set udg_STA_PrevNode[TempNode] = udg_STA_LastNode
set udg_STA_LastNode = TempNode
set udg_STA_Caster[TempNode] = udg_STA_Caster[Node]
set udg_STA_CasterNode[TempNode] = udg_STA_CasterNode[Node]
set udg_STA_OwningPlayer[TempNode] = udg_STA_OwningPlayer[Node]
//Creates the unit and sets up aesthetics
set udg_STA_Unit[TempNode] = CreateUnit(STA_DummyOwner(), STA_DummyID(), x, y, Angle)
if UnitAddAbility(udg_STA_Unit[TempNode], 'Amrf') and UnitRemoveAbility(udg_STA_Unit[TempNode], 'Amrf') then
endif
set udg_STA_CurrentEffect[TempNode] = AddSpecialEffectTarget(STA_SoulFragmentProjectileEffect(), udg_STA_Unit[TempNode], STA_SoulFragmentProjectileAttachmentPoint())
call SetUnitScale(udg_STA_Unit[TempNode], udg_STA_SoulFragmentScale[Node],0.,0.)
call SetUnitFlyHeight(udg_STA_Unit[TempNode], z - STA_GetZ(x, y), 0)
//Sets up the values it needs to run properly
set udg_STA_StageID[TempNode] = 3
set udg_STA_ZSpeed[TempNode] = zSpeed
set udg_STA_Speed[TempNode] = Speed
set udg_STA_HealthDamage[TempNode] = HealthDamage
set udg_STA_ManaDamage[TempNode] = ManaDamage
set udg_STA_FragmentType[TempNode] = Type
set udg_STA_DistanceTravelled[TempNode] = 0.
//Checks if it's an initial projectile
//or one made when a unit dies
if (Type) then
//Sets up the target of the projectile
set udg_STA_Target[TempNode] = udg_STA_Unit[Target]
set udg_STA_TargetID[TempNode] = Target
else
//Set the distance the projectile can travel
set udg_STA_MaxDistance[TempNode] = Distance
//Resets projectile data (prevents errors when recycling)
set udg_STA_TargetID[TempNode] = 0
set udg_STA_Target[TempNode] = null
endif
endfunction
////////////////////////////////////////////////////////////////////
// Function used to find all units associated with a caster and //
// remove the effects, apply healing to units that have ceased //
// to be affected, and destroy projectiles that were created by //
// the aura (they do not deal damage when this occurs //
////////////////////////////////////////////////////////////////////
function STA_AuraEnd takes integer Node returns nothing
//Declare locals
local integer TempInt = 0
local integer TempNode = 0
//Begin search for units
loop
//Moves to the next node
set TempInt = TempInt + 1
exitwhen TempInt > udg_STA_AbilityCounter
set TempNode = udg_STA_NextNode[TempNode]
//Finds units which "belong" to this instance
if (udg_STA_Caster[TempNode] == udg_STA_Caster[Node]) then
//Checks the type of unit (2 = affected unit, 3 = Projectile)
if (udg_STA_StageID[TempNode] == 2) then
//Checks if the heal effect is in use
if (STA_UseHealEffect()) then
call DestroyEffect(AddSpecialEffectTarget(STA_HealEffect(), udg_STA_Unit[TempNode], STA_HealEffectAttachmentPoint()))
endif
//Heals the units
call SetWidgetLife(udg_STA_Unit[TempNode], udg_STA_CurrentHealth[TempNode] + udg_STA_HeroHealthHeal[Node])
call SetUnitState(udg_STA_Unit[TempNode], UNIT_STATE_MANA, udg_STA_CurrentMana[TempNode] + udg_STA_HeroManaHeal[Node])
//Recycles the instance and enables reselection as a target
call DestroyEffect(udg_STA_CurrentEffect[TempNode])
call UnitRemoveAbility(udg_STA_Unit[TempNode], STA_BuffAbilityID())
call GroupRemoveUnit(udg_STA_AffectedUnits,udg_STA_Unit[TempNode])
call STA_Recycle(TempNode, GetExpiredTimer())
set TempInt = TempInt - 1
elseif (udg_STA_StageID[TempNode] == 3) then
//Checks if the death damage effect is enabled
if (STA_UseDeathDamageEffect()) then
call DestroyEffect(AddSpecialEffectTarget(STA_DeathDamageEffect(), udg_STA_Unit[TempNode], STA_DeathDamageAttachmentPoint()))
endif
//Destroys the effect and starts the recycling process for projectiles
call DestroyEffect(udg_STA_CurrentEffect[TempNode])
set udg_STA_StageID[TempNode] = 4
endif
endif
endloop
endfunction
////////////////////////////////////////////////////////////////////
// Function used to update the stats for Heros generating the //
// aura, so that level ups are in effect instantly //
////////////////////////////////////////////////////////////////////
function STA_UpdateAura takes integer Node returns nothing
//Updates all the stat values of the hero when it levels up
set udg_STA_SoulFragmentScale[Node] = STA_SoulFragmentProjectileScaleBase() + (STA_SoulFragmentProjectileScalePerLevel() * udg_STA_Level[Node])
set udg_STA_AOE[Node] = STA_AOEBase() + (STA_AOEPerLevel() * udg_STA_Level[Node])
set udg_STA_SearchAOE[Node] = STA_SearchAOEBase() + (STA_SearchAOEPerLevel() * udg_STA_Level[Node])
set udg_STA_ImpactAOE[Node] = STA_ImpactAOEBase() + (STA_ImpactAOEPerLevel() * udg_STA_Level[Node])
set udg_STA_SoulProjectileSpeed[Node] = STA_SoulFragmentProjectileSpeedBase() + (STA_SoulFragmentProjectileSpeedPerLevel() * udg_STA_Level[Node])
set udg_STA_SoulProjectileHitTime[Node] = STA_SoulFragmentProjectileHitTimeBase() + (STA_SoulFragmentProjectileHitTimePerLevel() * udg_STA_Level[Node])
set udg_STA_InitialEffectHealthDamage[Node] = STA_InitialEffectHealthDamageBase() + (STA_InitialEffectHealthDamagePerLevel() * udg_STA_Level[Node])
set udg_STA_InitialEffectManaDamage[Node] = STA_InitialEffectManaDamageBase() + (STA_InitialEffectManaDamagePerLevel() * udg_STA_Level[Node])
set udg_STA_DeathHealthDamage[Node] = STA_DeathHealthDamageBase() + (STA_DeathHealthDamagePerLevel() * udg_STA_Level[Node])
set udg_STA_DeathManaDamage[Node] = STA_DeathManaDamageBase() + (STA_DeathManaDamagePerLevel() * udg_STA_Level[Node])
set udg_STA_BonusHealthDamagePercent[Node] = STA_BonusHealthDamagePercentBase() + (STA_BonusHealthDamagePercentPerLevel() * udg_STA_Level[Node])
set udg_STA_BonusManaDamagePercent[Node] = STA_BonusManaDamagePercentBase() + (STA_BonusManaDamagePercentPerLevel() * udg_STA_Level[Node])
set udg_STA_HeroHealthHeal[Node] = STA_HeroHealthHealBase() + (STA_HeroHealthHealPerLevel() * udg_STA_Level[Node])
set udg_STA_HeroManaHeal[Node] = STA_HeroManaHealBase() + (STA_HeroManaHealPerLevel() * udg_STA_Level[Node])
endfunction
////////////////////////////////////////////////////////////////////
// The main loop function of the spell, it handles the main //
// operations of the ability such as assigning new units, //
// moving projectiles and dealing bonus damage to units //
////////////////////////////////////////////////////////////////////
function STA_Loop takes nothing returns nothing
//Declare Locals
local integer Node = 0
local integer TempNode = 0
local integer TempInt = 0
local integer TempInt2 = 0
local real TempReal
local real TempReal2
local real TempReal3
local real x
local real y
local real x2
local real y2
local real z
local real z2
local real Angle
local unit u
local player pl
//Main loop
loop
//Moves to the next node
set TempInt = TempInt + 1
exitwhen TempInt > udg_STA_AbilityCounter
set Node = udg_STA_NextNode[Node]
//Checks which node the unit belongs to
//Ordered to be more efficient and labelled
//In order of occurence:
//StageID = 3, Projectiles
if (udg_STA_StageID[Node] == 3) then
set x = GetUnitX(udg_STA_Unit[Node])
set y = GetUnitY(udg_STA_Unit[Node])
//Calculate the next position
set x2 = x + udg_STA_Speed[Node] * Cos(GetUnitFacing(udg_STA_Unit[Node]) * bj_DEGTORAD)
set y2 = y + udg_STA_Speed[Node] * Sin(GetUnitFacing(udg_STA_Unit[Node]) * bj_DEGTORAD)
//Check the difference in height between it's current point and next point
set TempReal = STA_GetZ(x, y)
set TempReal2 = STA_GetZ(x2, y2)
//Account for height difference
if not(TempReal == TempReal2) then
set TempReal = TempReal - TempReal2
else
set TempReal = 0
endif
//Move the projectile
call SetUnitX(udg_STA_Unit[Node], x2)
call SetUnitY(udg_STA_Unit[Node], y2)
call SetUnitFlyHeight(udg_STA_Unit[Node], GetUnitFlyHeight(udg_STA_Unit[Node]) + udg_STA_ZSpeed[Node] + TempReal, 0.)
set udg_STA_DistanceTravelled[Node] = udg_STA_DistanceTravelled[Node] + udg_STA_Speed[Node]
//Checks the kind of projectile that it is
if (udg_STA_FragmentType[Node] == true) then
//Checks the distance from the target
set x2 = GetUnitX(udg_STA_Target[Node])
set y2 = GetUnitY(udg_STA_Target[Node])
set TempReal = SquareRoot(Pow(x - x2, 2) + Pow(y - y2, 2))
//Checks for a collision
if (TempReal > STA_CollisionSize()) then
//No collision, recalculate movement
set Angle = Atan2(y2 - y, x2 - x)
call SetUnitFacing(udg_STA_Unit[Node], bj_RADTODEG * Angle)
//Calculate Z heights
set z = STA_GetZ(x,y) + GetUnitFlyHeight(udg_STA_Unit[Node])
set z2 = STA_GetZ(x2, y2) + GetUnitFlyHeight(udg_STA_Target[Node]) + STA_SoulFragmentHeightEndOffset()
//Calculate Speed
if (STA_SoulFragmentMovementType() == true) then
set udg_STA_Speed[Node] = (TempReal + udg_STA_DistanceTravelled[Node] / udg_STA_SoulProjectileHitTime[udg_STA_CasterNode[Node]]) * STA_TimerRate()
endif
//Calculate change is Z speed needed
set udg_STA_ZSpeed[Node] = (z2 - z) / (TempReal / udg_STA_Speed[Node])
else
//Collision occured, enable aura effect
set udg_STA_Disabled[udg_STA_TargetID[Node]] = false
call STA_SoulProjectileDamage(x,y,Node)
set udg_STA_StageID[Node] = 4
call DestroyEffect(udg_STA_CurrentEffect[Node])
//Check if the death damage effect is in use
if (STA_UseInitialDamageEffect()) then
call DestroyEffect(AddSpecialEffectTarget(STA_InitialDamageEffect(), udg_STA_Unit[Node], STA_InitialDamageAttachmentPoint()))
endif
endif
//If not homing, check if it's reached it's destination
elseif (udg_STA_DistanceTravelled[Node] >= udg_STA_MaxDistance[Node]) then
//Cause Damage
call STA_SoulProjectileDamage(x,y,Node)
set udg_STA_StageID[Node] = 4
call DestroyEffect(udg_STA_CurrentEffect[Node])
//Check if the death damage effect is in use
if (STA_UseDeathDamageEffect()) then
call DestroyEffect(AddSpecialEffectTarget(STA_DeathDamageEffect(), udg_STA_Unit[Node], STA_DeathDamageAttachmentPoint()))
endif
endif
//StageID = 2, Affected units
elseif (udg_STA_StageID[Node] == 2) and (not udg_STA_Disabled[Node]) then
//Find the units current stats
set TempReal = GetWidgetLife(udg_STA_Unit[Node])
set TempReal2 = GetUnitState(udg_STA_Unit[Node], UNIT_STATE_MANA)
//Increase the effect delay timer
set udg_STA_EffectDelayTimer[Node] = udg_STA_EffectDelayTimer[Node] + STA_TimerRate()
//Check if either of the values have been reduced since the last iteration
if (TempReal < udg_STA_CurrentHealth[Node]) or (TempReal2 < udg_STA_CurrentMana[Node]) then
//Check if the effect is able to be used
if (udg_STA_EffectDelayTimer[Node] >= STA_EffectReductionDelay()) then
set udg_STA_EffectDelayTimer[Node] = 0.
call DestroyEffect(AddSpecialEffectTarget(STA_BonusDamageEffect(), udg_STA_Unit[Node], STA_BonusDamageAttachmentPoint()))
endif
//Check if a health reduction has occured
if (TempReal < udg_STA_CurrentHealth[Node]) then
//Apply bonus damage
set TempReal = (udg_STA_CurrentHealth[Node] - TempReal) * udg_STA_BonusHealthDamagePercent[udg_STA_CasterNode[Node]]
call UnitDamageTarget(udg_STA_Caster[Node], udg_STA_Unit[Node], TempReal, false, false, STA_AttackType(), STA_DamageType(), STA_WeaponType())
set udg_STA_CurrentHealth[Node] = GetWidgetLife(udg_STA_Unit[Node])
endif
//Check if a mana reduction has occured
if (TempReal2 < udg_STA_CurrentMana[Node]) then
//Apply bonus damage
set TempReal2 = (udg_STA_CurrentMana[Node] - TempReal2) * udg_STA_BonusManaDamagePercent[udg_STA_CasterNode[Node]]
call SetUnitState(udg_STA_Unit[Node], UNIT_STATE_MANA, TempReal2)
endif
endif
//Set up positions
set x = GetUnitX(udg_STA_Unit[Node])
set y = GetUnitY(udg_STA_Unit[Node])
set x2 = GetUnitX(udg_STA_Caster[Node])
set y2 = GetUnitY(udg_STA_Caster[Node])
set TempReal = SquareRoot(Pow(x - x2, 2) + Pow(y - y2, 2))
//Check if the unit is still close enough to be affected by the aura
if (TempReal > udg_STA_AOE[udg_STA_CasterNode[Node]]) then
//Outside range, deallocate unit
call DestroyEffect(udg_STA_CurrentEffect[Node])
call UnitRemoveAbility(udg_STA_Unit[Node], STA_BuffAbilityID())
call GroupRemoveUnit(udg_STA_AffectedUnits,udg_STA_Unit[Node])
call STA_Recycle(Node, GetExpiredTimer())
set TempInt = TempInt - 1
else
//Check if the unit is still alive
if (IsUnitType(udg_STA_Unit[Node], UNIT_TYPE_DEAD) or GetUnitTypeId(udg_STA_Unit[Node]) == 0)then
//Remove units related to this aura and end the effect
set TempInt2 = 0
set TempNode = 0
loop
//Moves to the next node
set TempInt2 = TempInt2 + 1
exitwhen TempInt2 > udg_STA_AbilityCounter
set TempNode = udg_STA_NextNode[TempNode]
//Finds projectiles that are homing in on this unit
if (udg_STA_Target[TempNode] == udg_STA_Unit[Node]) and (udg_STA_StageID[TempNode] == 3) then
//Destroy them (without damage) and recycle
call DestroyEffect(udg_STA_CurrentEffect[TempNode])
call DestroyEffect(AddSpecialEffectTarget(STA_DeathDamageEffect(), udg_STA_Unit[TempNode], STA_DeathDamageAttachmentPoint()))
set udg_STA_StageID[TempNode] = 4
endif
endloop
//Find units nearby which can be targets
call GroupEnumUnitsInRange(udg_STA_TempGroup, x, y, udg_STA_SearchAOE[udg_STA_CasterNode[Node]], null)
set pl = udg_STA_OwningPlayer[Node]
loop
//Scanning through
set u = FirstOfGroup(udg_STA_TempGroup)
exitwhen u == null
//Select all the units to create projectiles to attack
if (STA_TargetFilter(u, pl)) and (IsUnitInGroup(u, udg_STA_AffectedUnits)) then
//Set up data for the Soul Fragment Projectile
set x2 = GetUnitX(u)
set y2 = GetUnitY(u)
set z = STA_GetZ(x,y) + GetUnitFlyHeight(udg_STA_Unit[Node]) + STA_SoulFragmentHeightStartOffset()
set z2 = STA_GetZ(x2, y2) + GetUnitFlyHeight(u) + STA_SoulFragmentHeightEndOffset()
set TempReal = SquareRoot(Pow(x - x2, 2) + Pow(y - y2, 2))
//Calculate Speed
set TempReal2 = STA_GetSpeed(udg_STA_CasterNode[Node], TempReal)
//Calculate Z Speed and angle
set TempReal3 = (z2 - z) / (TempReal / TempReal2)
set Angle = bj_RADTODEG * Atan2(y2 - y, x2 - x)
//Create Projectile
call STA_CreateProjectile(x, y, z, TempReal3, TempReal2, Angle, TempReal, udg_STA_DeathHealthDamage[udg_STA_CasterNode[Node]], udg_STA_DeathManaDamage[udg_STA_CasterNode[Node]], udg_STA_CasterNode[Node], false, 0)
endif
//Remove the unit from the unit group
call GroupRemoveUnit(udg_STA_TempGroup, u)
endloop
//Remove effect
call DestroyEffect(udg_STA_CurrentEffect[Node])
//Recycle instance and enable re-selection as a target
call GroupRemoveUnit(udg_STA_AffectedUnits,udg_STA_Unit[Node])
call STA_Recycle(Node, GetExpiredTimer())
set TempInt = TempInt - 1
//Null variables
set pl = null
endif
endif
//StageID = 1, Aura source units/heros
elseif (udg_STA_StageID[Node] == 1) then
//Check if the unit has died
if (IsUnitType(udg_STA_Caster[Node], UNIT_TYPE_DEAD) or GetUnitTypeId(udg_STA_Caster[Node]) == 0) then
//The Hero is Dead, end the aura
call STA_AuraEnd(Node)
//Checks if the unit was removed from the game
if (GetUnitTypeId(udg_STA_Caster[Node]) == 0) then
//Unit removed, clear up instance
call DestroyEffect(udg_STA_CurrentEffect[Node])
call STA_AuraEnd(Node)
//Recycle the index
call STA_Recycle(Node, GetExpiredTimer())
set TempInt = TempInt - 1
endif
else
//Find the position of the unit
set x = GetUnitX(udg_STA_Caster[Node])
set y = GetUnitY(udg_STA_Caster[Node])
//Select potential targets of the aura
set pl = udg_STA_OwningPlayer[Node]
call GroupEnumUnitsInRange(udg_STA_TempGroup, x, y, udg_STA_AOE[Node], null)
loop
//Scanning through
set u = FirstOfGroup(udg_STA_TempGroup)
exitwhen u == null
//Select all the units which are to be affected and create projectiles
if (STA_TargetFilter(u, pl)) and (not(IsUnitInGroup(u, udg_STA_AffectedUnits))) then
//Prevent this unit from being selected again
call GroupAddUnit(udg_STA_AffectedUnits,u)
//Adds instance to the linked list
set udg_STA_AbilityCounter = udg_STA_AbilityCounter + 1
//Checking for recycleable Nodes
if (udg_STA_RecyclableNodes == 0) then
set udg_STA_NodeNumber = udg_STA_NodeNumber + 1
set TempNode = udg_STA_NodeNumber
else
set udg_STA_RecyclableNodes = udg_STA_RecyclableNodes - 1
set TempNode = udg_STA_RecycleNodes[udg_STA_RecyclableNodes]
endif
//Sets up this Node
set udg_STA_NextNode[TempNode] = 0
set udg_STA_NextNode[udg_STA_LastNode] = TempNode
set udg_STA_PrevNode[TempNode] = udg_STA_LastNode
set udg_STA_LastNode = TempNode
//Sets up data for this unit
set udg_STA_Caster[TempNode] = udg_STA_Caster[Node]
set udg_STA_CasterNode[TempNode] = Node
set udg_STA_Unit[TempNode] = u
set udg_STA_OwningPlayer[TempNode] = udg_STA_OwningPlayer[Node]
set udg_STA_CurrentEffect[TempNode] = AddSpecialEffectTarget(STA_SoulFragmentEffect(), u, STA_SoulFragmentAttachmentPoint())
set udg_STA_Disabled[TempNode] = true
set udg_STA_StageID[TempNode] = 2
set udg_STA_CasterNode[TempNode] = Node
set udg_STA_CurrentHealth[TempNode] = GetWidgetLife(u)
set udg_STA_CurrentMana[TempNode] = GetUnitState(u, UNIT_STATE_MANA)
//Add buff ability
call UnitAddAbility(u, STA_BuffAbilityID())
call SetUnitAbilityLevel(u, STA_BuffAbilityID(), R2I(udg_STA_Level[Node]))
//Set up data for the Soul Fragment Projectile
set x2 = GetUnitX(u)
set y2 = GetUnitY(u)
set z = STA_GetZ(x,y) + GetUnitFlyHeight(udg_STA_Caster[Node]) + STA_SoulFragmentHeightStartOffset()
set z2 = STA_GetZ(x2, y2) + GetUnitFlyHeight(u) + STA_SoulFragmentHeightEndOffset()
set TempReal = SquareRoot(Pow(x - x2, 2) + Pow(y - y2, 2))
//Calculate Speed
set TempReal2 = STA_GetSpeed(Node, TempReal)
//Calculate the needed z change
set TempReal = (z2 - z) / (TempReal / TempReal2)
//Find the facing angle needed
set Angle = bj_RADTODEG * Atan2(y2 - y, x2 - x)
//Create Projectile
call STA_CreateProjectile(x, y, z, TempReal, TempReal2, Angle, 0, udg_STA_InitialEffectHealthDamage[Node], udg_STA_InitialEffectManaDamage[Node], Node, true, TempNode)
endif
//Remove the unit from the unit group
call GroupRemoveUnit(udg_STA_TempGroup, u)
endloop
//Find the level of the aura ability
set TempReal = I2R(GetUnitAbilityLevel(udg_STA_Caster[Node], STA_AbilityID()))
//Check if the level has changed
if (TempReal != udg_STA_Level[Node]) then
if (TempReal == 0) then
//The unit has forgotten the ability, end it's instance
call DestroyEffect(udg_STA_CurrentEffect[Node])
call GroupRemoveUnit(udg_STA_CasterGroup,udg_STA_Caster[Node])
call STA_AuraEnd(Node)
//Recycle the index
call STA_Recycle(Node, GetExpiredTimer())
set TempInt = TempInt - 1
else
//Update the aura
set udg_STA_Level[Node] = TempReal
call STA_UpdateAura(Node)
endif
endif
//Null variables
set pl = null
endif
//StageID = 4, Projectiles to clear up (so death animations can play)
elseif (udg_STA_StageID[Node] == 4) and (udg_STA_CurrentDeathTimer[Node] >= STA_DummyRemovalDelay()) then
set udg_STA_CurrentDeathTimer[Node] = 0.00
//Removes the projectile
call RemoveUnit(udg_STA_Unit[Node])
//Recycles the instance
call STA_Recycle(Node, GetExpiredTimer())
set TempInt = TempInt - 1
else
//Increases the death delay timer
set udg_STA_CurrentDeathTimer[Node] = udg_STA_CurrentDeathTimer[Node] + STA_TimerRate()
endif
endloop
endfunction
////////////////////////////////////////////////////////////////////
// Caster assignment function, when a new unit learns an ability //
// or if the unit is found to have the ability through the //
// STA_EnableUnits function, this function is then called and //
// the unit is passed to potentially add it to the system //
// this then checks if the unit is registered as a caster in //
// the linked list, if it is, then it doesn't need to be added //
// however, if it doesn't exist as a caster, then the unit will //
// be assigned to a node and added to the spell //
////////////////////////////////////////////////////////////////////
function STA_NewAura takes unit u returns nothing
//Set up locals
local integer Node = 0
//If the unit wasn't found as a caster, add it as one
if not(IsUnitInGroup(u, udg_STA_CasterGroup)) then
set udg_STA_AbilityCounter = udg_STA_AbilityCounter + 1
//Checking for recycleable Nodes
if (udg_STA_RecyclableNodes == 0) then
set udg_STA_NodeNumber = udg_STA_NodeNumber + 1
set Node = udg_STA_NodeNumber
else
set udg_STA_RecyclableNodes = udg_STA_RecyclableNodes - 1
set Node = udg_STA_RecycleNodes[udg_STA_RecyclableNodes]
endif
//Sets up this Node
set udg_STA_NextNode[Node] = 0
set udg_STA_NextNode[udg_STA_LastNode] = Node
set udg_STA_PrevNode[Node] = udg_STA_LastNode
set udg_STA_LastNode = Node
//Set up the data needed for the Aura
set udg_STA_Level[Node] = I2R(GetUnitAbilityLevel(u, STA_AbilityID()))
set udg_STA_StageID[Node] = 1
set udg_STA_Caster[Node] = u
set udg_STA_CasterNode[Node] = Node
set udg_STA_OwningPlayer[Node] = GetOwningPlayer(u)
set udg_STA_CurrentEffect[Node] = AddSpecialEffectTarget(STA_AuraEffect(), u, STA_AuraAttachmentPoint())
call GroupAddUnit(udg_STA_CasterGroup,u)
call STA_UpdateAura(Node)
//Applies timer if this is the only instance of the aura
if (udg_STA_AbilityCounter == 1) then
call TimerStart(CreateTimer(), STA_TimerRate(), true, function STA_Loop)
endif
endif
endfunction
////////////////////////////////////////////////////////////////////
// This function runs whenever a unit learns an ability, it //
// checks if the learnt ability is the one used for the aura, //
// if it turns out that it is, then it passed the unit to the //
// STA_NewAura function to potentially add it to the system //
////////////////////////////////////////////////////////////////////
function STA_LearnAbility takes nothing returns boolean
//Create Locals
local unit u
//Checks if the learnt ability by the triggering unit is the aura ability
if (GetLearnedSkill() == STA_AbilityID()) then
//Attempts to add the unit
set u = GetTriggerUnit()
call STA_NewAura(u)
//Nulls variables
set u = null
endif
//return a false value as there is no point returning anything else
return false
endfunction
////////////////////////////////////////////////////////////////////
// This function's primary purpose is to add all preplaced units //
// with the aura on the map to the system, however it can also //
// be utilised for units which are added at runtime with the //
// aura so that they can function correctly despite not running //
// the other trigger (the same goes with trained units) //
////////////////////////////////////////////////////////////////////
function STA_EnableUnits takes nothing returns boolean
//Sets up locals
local unit u
//Adds all units on the map to a unit group
call GroupEnumUnitsInRect(udg_STA_TempGroup, bj_mapInitialPlayableArea, null)
//Scans through the unit group looking for units with the Aura ability
loop
set u = FirstOfGroup(udg_STA_TempGroup)
exitwhen u == null
//Checks that the selected unit has the aura as an ability
if (GetUnitAbilityLevel(u, STA_AbilityID()) > 0) then
//Attempts to add the unit
call STA_NewAura(u)
endif
call GroupRemoveUnit(udg_STA_TempGroup, u)
endloop
//Checks if this function will run constantly, if not then destroy the trigger
if (not(STA_CheckTimerPeriodic())) then
call DestroyTrigger(GetTriggeringTrigger())
endif
//return a false value as there is no point returning anything else
return false
endfunction
////////////////////////////////////////////////////////////////////
// Initialisation trigger, applies the conditions to triggers //
// and sets up the global location used to get location Z's //
////////////////////////////////////////////////////////////////////
function InitTrig_Soul_Tear_Aura takes nothing returns nothing
//Set up locals
local trigger STA = CreateTrigger()
local integer index = 0
//Set up hero learning trigger
loop
//Applies the even to each player in turn
call TriggerRegisterPlayerUnitEvent(STA, Player(index), EVENT_PLAYER_HERO_SKILL, null)
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
//Applies the function to add new units to the linked list when they learn abilities
call TriggerAddCondition(STA, Condition(function STA_LearnAbility))
//Set up initial hero enabling trigger
set STA = CreateTrigger()
//Sets up the event listener, if the function is periodic, then it will run constantly instead of just at the start
call TriggerRegisterTimerEvent(STA, STA_CheckTimerRate(), STA_CheckTimerPeriodic())
call TriggerAddCondition(STA, Condition(function STA_EnableUnits))
//Set up the location used to find Z heights
set udg_STA_ZLoc = Location(0,0)
endfunction
////////////////////////////////////////////////////////////////////
// End of the spell //
////////////////////////////////////////////////////////////////////