////////////////////////////////////////////////////////////////////
// ARCANE BARRAGE V1.01 //
// Author: Tank-Commander //
// Purpose: A powerful keepaway ability for forcing enemies //
// to retreat //
// Requires: BUS Channel (Boss Ultimates Spellpack) //
// Master Projectile System //
// - Both created by Tank-Commander //
// //
// Notes: //
// - Read the readme before you try modifying the config //
// - Use the "Helpful files" to help you import the system //
// //
// Credits: //
// - (Dummy.mdl) Vexorian //
// - (Darkness_Bomb.mdl) nGy //
// //
// If you have used this spellpack 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 //
// //
// While the remaining object editor based data is not required //
// to function (provided they're replaced with equivelents) //
// it's recommended that they are also imported, if their data //
// value are not the same as listed in the configuration, those //
// configurables will need to be changed to work correctly //
//----------------------------------------------------------------//
// MISC //
//----------------------------------------------------------------//
// TimerSpeed: the time in seconds between each iteration of //
// the main loop function (default is 0.031250000) it's //
// recommended you leave it like that //
constant function AB_TimerSpeed takes nothing returns real
return 0.031250000
endfunction
//----------------------------------------------------------------//
// Event: This is the number used to differentiate it from //
// other channel abilities - make sure this does not conflict //
// with any other BUS Channel-using abilities //
constant function AB_Event takes nothing returns integer
return 5
endfunction
//----------------------------------------------------------------//
// Ability: This is the data value of the ability used as the //
// base, make sure it is based off channel (to view raw data //
// press ctrl + d, pressing again switches back) //
constant function AB_Ability takes nothing returns integer
return 'A000'
endfunction
//----------------------------------------------------------------//
// MaxLevel: This is the maximum level of the ability - this //
// ensures that a projectile is registered for each level of //
// the ability
constant function AB_MaxLevel takes nothing returns integer
return 3
endfunction
//----------------------------------------------------------------//
// CHANNEL //
//----------------------------------------------------------------//
// ChannelType: This is the name of the channel, multiple //
// abilities can use the same channel
constant function AB_ChannelType takes nothing returns string
return "ArcaneBarrage"
endfunction
//----------------------------------------------------------------//
// Duration: This is how long the channel period for the spell //
// lasts for (in seconds) //
constant function AB_ChannelDurationBase takes nothing returns real
return 3.
endfunction
// //
constant function AB_ChannelDurationPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Effect: This is the filepath of the effect used for the //
// channel //
constant function AB_ChannelEffect takes nothing returns string
return "Abilities\\Spells\\Other\\BlackArrow\\BlackArrowMissile.mdl"
endfunction
//----------------------------------------------------------------//
// AOE: This is how far away from the caster the effects are //
// created //
constant function AB_ChannelMinAOE takes nothing returns real
return 200.
endfunction
// //
constant function AB_ChannelMaxAOE takes nothing returns real
return 300.
endfunction
//----------------------------------------------------------------//
// AbsorbAOE: This is how close to the caster the channel //
// effects must get to the caster before they are removed //
constant function AB_ChannelAbsorbAOE takes nothing returns real
return 50.
endfunction
//----------------------------------------------------------------//
// Size: This is how big each channel effect can be (1 = 100% //
// of their base size) //
constant function AB_ChannelMinSize takes nothing returns real
return 0.1
endfunction
// //
constant function AB_ChannelMaxSize takes nothing returns real
return 1.
endfunction
//----------------------------------------------------------------//
// SpawnRate: This is how many channel effects sets are created //
// per second that the unit is mid-channel //
constant function AB_ChannelSpawnRate takes nothing returns real
return 50.
endfunction
//----------------------------------------------------------------//
// SpawnCount: This is the amount of channel effects are created //
// every time a set is made //
constant function AB_ChannelSpawnCount takes nothing returns integer
return 2
endfunction
//----------------------------------------------------------------//
// Power: This is how storngly channel effects are pulled //
// towards the caster //
constant function AB_ChannelPower takes nothing returns real
return 90.
endfunction
//----------------------------------------------------------------//
// Hue: These are the values for the colour change of the unit //
// if colour change is enabled (255 = full colour) //
constant function AB_ChannelHueRed takes nothing returns integer
return 255
endfunction
// //
constant function AB_ChannelHueGreen takes nothing returns integer
return 0
endfunction
// //
constant function AB_ChannelHueBlue takes nothing returns integer
return 255
endfunction
// //
constant function AB_ChannelHueAlpha takes nothing returns integer
return 255
endfunction
//----------------------------------------------------------------//
// HueSpeed: This is how fast the unit oscillates between //
// the colour change and full colour - this value x 2 is how //
// long it takes to complete 1 full cycle //
constant function AB_ChannelHueSpeed takes nothing returns real
return 0.75
endfunction
//----------------------------------------------------------------//
// HaveHue: This determines whether or not this ability uses //
// a Hue change //
constant function AB_HaveHue takes nothing returns boolean
return true
endfunction
//----------------------------------------------------------------//
// PROJECTILE //
//----------------------------------------------------------------//
// MasterName: This is the name given to the projectile used //
// by the ability so that it can be uniquely identified //
constant function AB_MasterName takes nothing returns string
return "AB_Master"
endfunction
//----------------------------------------------------------------//
// Model: This is the filepath for the model used as the //
// projectile //
constant function AB_ProjectileModel takes nothing returns string
return "war3mapImported\\DarknessBomb.mdx"
endfunction
//----------------------------------------------------------------//
// DeathModel: This is the filepath for the model for when it //
// hits the target or the groun //
constant function AB_ProjectileDeathModel takes nothing returns string
return "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
endfunction
//----------------------------------------------------------------//
// Scale: This is the size of the projectile (1 = 100% of the //
// model's base size) //
constant function AB_ProjectileScaleBase takes nothing returns real
return 1.
endfunction
// //
constant function AB_ProjectileScalePerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// AOE: This is how close to the target the projectile must //
// get to damage it - it also gives the projectile this AOE to //
// nearby enemies //
constant function AB_ProjectileAOEBase takes nothing returns real
return 100.
endfunction
// //
constant function AB_ProjectileAOEPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// HealthDamage: This is the amount of damage each projectile //
// deals to the target's health //
constant function AB_HealthDamageBase takes nothing returns real
return 40.
endfunction
// //
constant function AB_HealthDamagePerLevel takes nothing returns real
return 40.
endfunction
//----------------------------------------------------------------//
// ManaDamage: This is the amount of damage each projectile //
// deals to the target's mana //
constant function AB_ManaDamageBase takes nothing returns real
return 0.
endfunction
// //
constant function AB_ManaDamagePerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// Accel: This is how much the speed of the projectiles are //
// multiplied by each loop iteration //
constant function AB_AccelBase takes nothing returns real
return 1.01
endfunction
// //
constant function AB_AccelPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// TurnRate: This is the strength of the pull each projectile //
// has toward the target //
constant function AB_TurnRateBase takes nothing returns real
return 5.
endfunction
// //
constant function AB_TurnRatePerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// TurnEff: This is the efficiency of converting existing //
// speed toward the target (1 = 1/2 converted each loop //
// iteration //
constant function AB_TurnEffBase takes nothing returns real
return 0.3
endfunction
// //
constant function AB_TurnEffPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// AimOffset: This is how far above the target unit the //
// projectiles will aim at //
constant function AB_AimOffsetBase takes nothing returns real
return 50.
endfunction
// //
constant function AB_AimOffsetPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// AttackType: This is the type of attack used by the //
// projectile damage
constant function AB_AttackType takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
//----------------------------------------------------------------//
// DamageType: This is the type of damage used by the //
// projectile damage //
constant function AB_DamageType takes nothing returns damagetype
return DAMAGE_TYPE_NORMAL
endfunction
//----------------------------------------------------------------//
// MAIN ABILITY //
//----------------------------------------------------------------//
// AffectedEffect: This is the effect used for units that //
// are currently being targetted by the projectiles //
constant function AB_AffectedEffect takes nothing returns string
return "Abilities\\Spells\\Undead\\Curse\\CurseTarget.mdl"
endfunction
//----------------------------------------------------------------//
// ReleaseEffect: This is the effect used for units that have //
// just left the AOE or completed being shot at with //
// projectiles //
constant function AB_ReleaseEffect takes nothing returns string
return "war3mapImported\\Dummy.mdl"
endfunction
//----------------------------------------------------------------//
// AttachmentPoint: This is the attachment point the above //
// effects are attached to //
constant function AB_AttachmentPoint takes nothing returns string
return "overhead"
endfunction
//----------------------------------------------------------------//
// AOE: This is the range which targetted units need to leave //
// to stop being shot at with projectiles //
constant function AB_AOEBase takes nothing returns real
return 600.
endfunction
// //
constant function AB_AOEPerLevel takes nothing returns real
return 100.
endfunction
//----------------------------------------------------------------//
// Duration: This is the time in seconds that units being //
// targetted will be shot at for //
constant function AB_DurationBase takes nothing returns real
return 2.
endfunction
// //
constant function AB_DurationPerLevel takes nothing returns real
return 1.
endfunction
//----------------------------------------------------------------//
// FireRate: This is the amount of projectiles that are fired //
// per second //
constant function AB_FireRateBase takes nothing returns real
return 3.
endfunction
// //
constant function AB_FireRatePerLevel takes nothing returns real
return 1.
endfunction
//----------------------------------------------------------------//
// FirePower: This is the velocity at which projectiles are //
// launched
constant function AB_FirePowerBase takes nothing returns real
return 180.
endfunction
// //
constant function AB_FirePowerPerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// FireAngle: This is the +-range of possible angles projectiles //
// can be fired at in radians (PI/2 = 90 degrees) giving 180 //
// degrees of possible values //
constant function AB_FireAngleBase takes nothing returns real
return bj_PI / 2
endfunction
// //
constant function AB_FireAnglePerLevel takes nothing returns real
return 0.
endfunction
//----------------------------------------------------------------//
// FireAngleOrientation: This is the angle offset from the //
// caster to target that projectiles will be launched from //
// only "0" and bj_PI are sensible values for this as 0 is //
// towards them and bj_PI is away from them //
constant function AB_FireAngleOrientation takes nothing returns real
return bj_PI
endfunction
//----------------------------------------------------------------//
// GroundHeightOffset: This is the offset projectiles are //
// launched from when fired by a ground unit to keep them from //
// instantly hitting the ground (and looking visually wrong) //
constant function AB_GroundHeightOffset takes nothing returns real
return 50.
endfunction
//----------------------------------------------------------------//
// END OF CONFIGURATION //
//----------------------------------------------------------------//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Loop function used to create new projectiles, check that the //
// target is still within range of the ability and recycle //
// completed instances //
////////////////////////////////////////////////////////////////////
function AB_ArcaneBarrageLoop takes nothing returns nothing
//Locals
local integer Node = 0
local real x
local real x2
local real y
local real y2
local real Angle
local real Angle2
//Cycle through each node
loop
set Node = udg_AB_NextNode[Node]
exitwhen Node == 0
//Get location of unit and target
set x = GetUnitX(udg_AB_Unit[Node])
set x2 = GetUnitX(udg_AB_Target[Node])
set y = GetUnitY(udg_AB_Unit[Node])
set y2 = GetUnitY(udg_AB_Target[Node])
//Decrease duration timer
set udg_AB_Duration[Node] = udg_AB_Duration[Node] - AB_TimerSpeed()
//Check if the instance has ended
if(udg_AB_Duration[Node] <= 0.) or ((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y) > udg_AB_AOE[Node]) then
//Clean up effects
call DestroyEffect(udg_AB_Effect[Node])
call DestroyEffect(AddSpecialEffectTarget(AB_ReleaseEffect(), udg_AB_Target[Node], AB_AttachmentPoint()))
set udg_AB_Effect[Node] = null
set udg_AB_Unit[Node] = null
set udg_AB_Target[Node] = null
//Recycle
set udg_AB_RecycleNodes[udg_AB_RecyclableNodes] = Node
set udg_AB_RecyclableNodes = udg_AB_RecyclableNodes + 1
set udg_AB_NextNode[udg_AB_PrevNode[Node]] = udg_AB_NextNode[Node]
set udg_AB_PrevNode[udg_AB_NextNode[Node]] = udg_AB_PrevNode[Node]
//Disable timer if this was the last instance
if (udg_AB_PrevNode[0] == 0) then
call PauseTimer(udg_AB_Timer)
endif
else
//Update firing timer
set udg_AB_FireTimer[Node] = udg_AB_FireTimer[Node] - AB_TimerSpeed()
if (udg_AB_FireTimer[Node] <= 0.) then
//Create projectile
set udg_AB_FireTimer[Node] = udg_AB_FireRate[Node]
set Angle = GetRandomReal(-1 * udg_AB_FireAngle[Node], udg_AB_FireAngle[Node])
set Angle2 = Atan2(y2 - y, x2 - x) + AB_FireAngleOrientation()
call MPS_CreateProjectile(udg_AB_Unit[Node], udg_AB_Ammo[Node], udg_AB_FirePower[Node], Cos(Angle), Angle + Angle2, x, y, udg_AB_FireHeight[Node], udg_AB_Target[Node], x2, y2)
endif
endif
endloop
endfunction
////////////////////////////////////////////////////////////////////
// Function used when the channel has been completed //
// sets up spell data and adds units to the linked list //
////////////////////////////////////////////////////////////////////
function AB_ArcaneBarrageEvent takes nothing returns boolean
//Set up locals
local real rLevel = GetUnitAbilityLevel(udg_BUS_Unit, AB_Ability())
local integer Node
local real z = GetUnitFlyHeight(udg_BUS_Unit)
//Extra offset for ground units
if (IsUnitType(udg_BUS_Unit, UNIT_TYPE_GROUND)) then
set z = z + AB_GroundHeightOffset()
endif
//Set up Node
if (udg_AB_RecyclableNodes == 0) then
set udg_AB_NodeNumber = udg_AB_NodeNumber + 1
set Node = udg_AB_NodeNumber
else
set udg_AB_RecyclableNodes = udg_AB_RecyclableNodes - 1
set Node = udg_AB_RecycleNodes[udg_AB_RecyclableNodes]
endif
set udg_AB_NextNode[Node] = 0
set udg_AB_NextNode[udg_AB_PrevNode[0]] = Node
set udg_AB_PrevNode[Node] = udg_AB_PrevNode[0]
set udg_AB_PrevNode[0] = Node
//Set up Ability Data
set udg_AB_Unit[Node] = udg_BUS_Unit
set udg_AB_Target[Node] = udg_BUS_Target
set udg_AB_AOE[Node] = AB_AOEBase() + (AB_AOEPerLevel() * rLevel)
set udg_AB_AOE[Node] = udg_AB_AOE[Node] * udg_AB_AOE[Node]
set udg_AB_Ammo[Node] = MPS_GetAmmoByName(AB_MasterName() + R2S(rLevel))
set udg_AB_Duration[Node] = AB_DurationBase() + (AB_DurationPerLevel() * rLevel)
set udg_AB_FireAngle[Node] = AB_FireAngleBase() + (AB_FireAnglePerLevel() * rLevel)
set udg_AB_FirePower[Node] = AB_FirePowerBase() + (AB_FirePowerPerLevel() * rLevel)
set udg_AB_FireRate[Node] = 1. / (AB_FireRateBase() + (AB_FireRatePerLevel () * rLevel))
set udg_AB_FireHeight[Node] = z
set udg_AB_FireTimer[Node] = udg_AB_FireRate[Node]
set udg_AB_Effect[Node] = AddSpecialEffectTarget(AB_AffectedEffect(), udg_AB_Target[Node], AB_AttachmentPoint())
//Start timer if this is the only instance
if (udg_AB_PrevNode[Node] == 0) then
call TimerStart(udg_AB_Timer, AB_TimerSpeed(), true, function AB_ArcaneBarrageLoop)
endif
return false
endfunction
////////////////////////////////////////////////////////////////////
// Function used to start the channel process when the abiliyt //
// has been cast //
////////////////////////////////////////////////////////////////////
function AB_ArcaneBarrageStart takes nothing returns boolean
local unit u
//Start the channel
if (GetSpellAbilityId() == AB_Ability()) then
set u = GetTriggerUnit()
call BUS_StartChannel(BUS_GetChannelByName(AB_ChannelType()), u, GetSpellTargetUnit(), 0., 0., AB_ChannelDurationBase() + (GetUnitAbilityLevel(u, AB_Ability()) * AB_ChannelDurationPerLevel()), AB_Event(), AB_HaveHue())
set u = null
endif
return false
endfunction
////////////////////////////////////////////////////////////////////
// Function used to register the triggers, events, channel and //
// master projectile all used by this spell //
////////////////////////////////////////////////////////////////////
function InitTrig_Arcane_Barrage takes nothing returns nothing
//Set up local variables
local trigger t = CreateTrigger()
local integer i = 0
//Set up triggers
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function AB_ArcaneBarrageStart))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_BUSC_Event", EQUAL, AB_Event())
call TriggerAddCondition(t, Condition(function AB_ArcaneBarrageEvent))
//Set up Channel
set udg_BUSCR_Name[0] = AB_ChannelType()
set udg_BUSCR_Effect[0] = AB_ChannelEffect()
set udg_BUSCR_MinAOE[0] = AB_ChannelMinAOE()
set udg_BUSCR_MaxAOE[0] = AB_ChannelMaxAOE()
set udg_BUSCR_AbsorbAOE[0] = AB_ChannelAbsorbAOE()
set udg_BUSCR_MinSize[0] = AB_ChannelMinSize()
set udg_BUSCR_MaxSize[0] = AB_ChannelMaxSize()
set udg_BUSCR_SpawnRate[0] = AB_ChannelSpawnRate()
set udg_BUSCR_SpawnCount[0] = AB_ChannelSpawnCount()
set udg_BUSCR_Power[0] = AB_ChannelPower()
set udg_BUSCR_HueRed[0] = AB_ChannelHueRed()
set udg_BUSCR_HueGreen[0] = AB_ChannelHueGreen()
set udg_BUSCR_HueBlue[0] = AB_ChannelHueBlue()
set udg_BUSCR_HueAlpha[0] = AB_ChannelHueAlpha()
set udg_BUSCR_HueSpeed[0] = AB_ChannelHueSpeed()
call BUS_RegisterChannel(0)
//Set up Master Projectile
set i = 0
loop
set i = i + 1
exitwhen i > AB_MaxLevel()
set udg_MPS_ProjectileName[0] = (AB_MasterName() + I2S(i) )
set udg_MPS_ProjectileModel[0] = AB_ProjectileModel()
set udg_MPS_ProjectileDeathModel[0] = AB_ProjectileDeathModel()
set udg_MPS_ProjectileModelScale[0] = AB_ProjectileScaleBase() + (AB_ProjectileScalePerLevel() * i)
set udg_MPS_ProjectileAOE[0] = AB_ProjectileAOEBase() + (AB_ProjectileAOEPerLevel() * i)
set udg_MPS_ProjectileHealthDamage[0] = AB_HealthDamageBase() + (AB_HealthDamagePerLevel() * i)
set udg_MPS_ProjectileManaDamage[0] = AB_ManaDamageBase() + (AB_ManaDamagePerLevel() * i)
set udg_MPS_ProjectileAcceleration[0] = AB_AccelBase() + (AB_AccelPerLevel() * i)
set udg_MPS_ProjectileTurnRate[0] = AB_TurnRateBase() + (AB_TurnRatePerLevel() * i)
set udg_MPS_ProjectileTurnEfficiency[0] = AB_TurnEffBase() + (AB_TurnEffPerLevel() * i)
set udg_MPS_ProjectileTargetAimOffset[0] = AB_AimOffsetBase() + (AB_AimOffsetPerLevel() * i)
set udg_MPS_ProjectileAttackType[0] = AB_AttackType()
set udg_MPS_ProjectileDamageType[0] = AB_DamageType()
call MPS_RegisterAmmo(0)
endloop
endfunction
////////////////////////////////////////////////////////////////////
//END OF THE SPELL //
////////////////////////////////////////////////////////////////////