- Joined
- May 26, 2009
- Messages
- 1,829
Jeeze Almia, Hopefully it lives up to expectations for all that effort XD
I'm nearly done - just need to clean stuff up (code lines aren't neatly ordered and all that, configure it to a state I'm happy with (nerf production rate), add the priming to prevent that first cast lag and then thoroughly testing it
Here's a preview of the full effect
Edit: And just because I haven't posted an image of it yet, here's one showing the team colouring of the Buffs
I'm nearly done - just need to clean stuff up (code lines aren't neatly ordered and all that, configure it to a state I'm happy with (nerf production rate), add the priming to prevent that first cast lag and then thoroughly testing it
Here's a preview of the full effect

JASS:
////////////////////////////////////////////////////////////////////
// NANO PLAGUE V1.00 //
// Author: Tank-Commander //
// Purpose: Sacrafice yourself to decimate mechanical forces //
// //
// Requires: //
// - Custom Stat System (Created by Doomlord) //
// - SimError (Created by Vexorian) //
// - BoundInt (Created by Magtheridon96) //
// The requirements of the CSS are in the map header //
// //
// Notes: //
// - Read the readme before you try modifying the config //
// - Use the "Helpful files" to help you import the system //
// //
// Credits: //
// - (Dummy.mdl) Vexorian //
// - Others mentioned in the requirements //
// //
// 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. //
////////////////////////////////////////////////////////////////////
constant function NP_TimerSpeed takes nothing returns real
return 0.031250000
endfunction
constant function NP_AbilityID takes nothing returns integer
return 'A001'
endfunction
constant function NP_InfectAbilityID takes nothing returns integer
return 'A002'
endfunction
constant function NP_DummyID takes nothing returns integer
return 'u000'
endfunction
constant function NP_UseTeamColouredBuff takes nothing returns boolean
return true
endfunction
constant function NP_TCBuffDummyID takes nothing returns integer
return 'u001'
endfunction
constant function NP_BuffID takes nothing returns integer
return 'A000'
endfunction
constant function NP_BuffFacing takes nothing returns real
return 270.
endfunction
constant function NP_SummonedUnitID takes nothing returns integer
return 'u002'
endfunction
constant function NP_SummonBuffID takes nothing returns integer
return 'B001'
endfunction
constant function NP_AutoInfect takes nothing returns boolean
return true
endfunction
constant function NP_AttackOrder takes nothing returns integer
return 851983
endfunction
constant function NP_DummyPlayerID takes nothing returns player
return Player(14)
endfunction
constant function NP_AttachmentPoint takes nothing returns string
return "origin"
endfunction
constant function NP_BuffModel takes nothing returns string
return "Units\\Creeps\\HeroTinkerFactory\\HeroTinkerFactory.mdl"
endfunction
constant function NP_BuffSpawnModel takes nothing returns string
return "Abilities\\Spells\\Other\\Charm\\CharmTarget.mdl"
endfunction
constant function NP_ProjectileModel takes nothing returns string
return "Units\\Creeps\\HeroTinkerFactory\\HeroTinkerFactoryMissle.mdl"
endfunction
constant function NP_SpawnBuffModel takes nothing returns string
return "Objects\\Spawnmodels\\Other\\ToonBoom\\ToonBoom.mdl"
endfunction
constant function NP_InfectionLimit takes nothing returns integer
return 3
endfunction
constant function NP_BuffHeightOffset takes nothing returns real
return 150.
endfunction
constant function NP_BuffOffset takes nothing returns real
return 70.
endfunction
constant function NP_Gravity takes nothing returns real
return 1.20
endfunction
function NP_AOE takes real level returns real
return 250 + (50 * level)
endfunction
function NP_BuffSize takes real level returns real
return 0.275 + (0.025 * level)
endfunction
function NP_ProjectileSize takes real level returns real
return 0.8 + (0.025 * level)
endfunction
function NP_ProjectileFlightTime takes real level returns real
return 2 + (-0.2 * level)
endfunction
function NP_InfectDuration takes real level returns real
return 4 + (1 * level)
endfunction
function NP_InfectDPSHealth takes real level returns real
return 25 + (25 * level)
endfunction
function NP_InfectDPSMana takes real level returns real
return 0.
endfunction
function NP_InfectBonusDamageHealth takes real level returns real
return 30 * level
endfunction
function NP_InfectBonusDamageMana takes real level returns real
return 0.
endfunction
function NP_InstantDuplicationChance takes real level returns real
return 0.05 * level
endfunction
function NP_ProductionPS takes real level returns real
return 2.5 + (0.5 * level)
endfunction
function NP_SummonDuration takes real level returns real
return 6 + (2 * level)
endfunction
function NP_SummonSize takes real level returns real
return 0.15 + (0.05 * level)
endfunction
function NP_SummonHealthBonus takes integer level returns integer
return -50 + 50 * level
endfunction
function NP_SummonHealthRegenBonus takes integer level returns integer
return 1 * level
endfunction
function NP_SummonArmourBonus takes integer level returns integer
return -1 + (1 * level)
endfunction
function NP_SummonAttackDamageBonus takes integer level returns integer
return 5 * level
endfunction
function NP_SummonAttackSpeedBonus takes integer level returns integer
return 0
endfunction
function NP_SwarmStrengthAttackBonus takes integer SwarmStrength returns integer
return R2I(0.2 * SwarmStrength)
endfunction
constant function NP_AttackType takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
constant function NP_DamageType takes nothing returns damagetype
return DAMAGE_TYPE_NORMAL
endfunction
constant function NP_WeaponType takes nothing returns weapontype
return null
endfunction
constant function NP_InfectionStageID takes nothing returns integer
return 1
endfunction
constant function NP_ProjectileStageID takes nothing returns integer
return 2
endfunction
constant function NP_NanobotStageID takes nothing returns integer
return 3
endfunction
constant function NP_BuffStageID takes nothing returns integer
return 4
endfunction
constant function NP_WaitingStageID takes nothing returns integer
return 5
endfunction
//----------------------------------------------------------------//
// END OF CONFIGURATION //
//----------------------------------------------------------------//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function used to get the Z location height at a given point //
////////////////////////////////////////////////////////////////////
function NP_GetZ takes real x, real y returns real
call MoveLocation(udg_NP_ZLoc, x, y)
return GetLocationZ(udg_NP_ZLoc)
endfunction
////////////////////////////////////////////////////////////////////
// Function used to make sure that the location is within the //
// map bounds so that units cannot be moved outside of it and //
// get permanently stuck //
////////////////////////////////////////////////////////////////////
function NP_ValidateLocation takes real x, real y returns boolean
//Check if the point is within the map bounds
return (x < udg_NP_MapMaxX) and (x > udg_NP_MapMinX) and (y < udg_NP_MapMaxY) and (y > udg_NP_MapMinY)
endfunction
////////////////////////////////////////////////////////////////////
// Function used to remove instances from the linked list once //
// they have expired //
////////////////////////////////////////////////////////////////////
function NP_RecycleNode takes integer Node returns nothing
set udg_NP_RecycleNodes[udg_NP_RecyclableNodes] = Node
set udg_NP_RecyclableNodes = udg_NP_RecyclableNodes + 1
set udg_NP_NextNode[udg_NP_PrevNode[Node]] = udg_NP_NextNode[Node]
set udg_NP_PrevNode[udg_NP_NextNode[Node]] = udg_NP_PrevNode[Node]
//Stop the timer if this was the last instance
if (udg_NP_PrevNode[0] == 0) then
call PauseTimer(udg_NP_Timer)
endif
endfunction
////////////////////////////////////////////////////////////////////
// Function used to add new nodes to the linked list used by the //
// system //
////////////////////////////////////////////////////////////////////
function NP_CreateNode takes nothing returns integer
local integer Node
if (udg_NP_RecyclableNodes == 0) then
set udg_NP_NodeNumber = udg_NP_NodeNumber + 1
set Node = udg_NP_NodeNumber
else
set udg_NP_RecyclableNodes = udg_NP_RecyclableNodes - 1
set Node = udg_NP_RecycleNodes[udg_NP_RecyclableNodes]
endif
set udg_NP_NextNode[Node] = 0
set udg_NP_NextNode[udg_NP_PrevNode[0]] = Node
set udg_NP_PrevNode[Node] = udg_NP_PrevNode[0]
set udg_NP_PrevNode[0] = Node
return Node
endfunction
////////////////////////////////////////////////////////////////////
// Function used to tell if the passed unit is infected with a //
// specific instance //
////////////////////////////////////////////////////////////////////
function NP_IsInfected takes unit u, integer instance returns boolean
local integer Node = 0
loop
set Node = udg_NP_NextNode[Node]
exitwhen Node == 0 or (udg_NP_Instance[Node] == instance and udg_NP_Unit[Node] == u)
endloop
return udg_NP_Instance[Node] == instance and udg_NP_Unit[Node] == u
endfunction
////////////////////////////////////////////////////////////////////
// Function used to get the total amount of infections a given //
// unit currently has //
////////////////////////////////////////////////////////////////////
function NP_GetInfections takes unit u returns integer
local integer Node = 0
local integer infections = 0
loop
set Node = udg_NP_NextNode[Node]
exitwhen Node == 0
if udg_NP_Unit[Node] == u then
set infections = infections + 1
endif
endloop
return infections
endfunction
////////////////////////////////////////////////////////////////////
// Function used to attribute each infection to the original //
// unique cast of the ability, as each unit can be infected //
// multiple times, this is only used for getting summoned units //
////////////////////////////////////////////////////////////////////
function NP_GetNode takes unit u returns integer
local integer Node = 0
loop
set Node = udg_NP_NextNode[Node]
exitwhen Node == 0 or udg_NP_Unit[Node] == u
endloop
return Node
endfunction
////////////////////////////////////////////////////////////////////
// Function used to move all buffs on an infected unit when a //
// buff has either been added or removed from the unit //
////////////////////////////////////////////////////////////////////
function NP_MoveBuffs takes unit u, integer buffCount returns nothing
//Set up locals
local integer Node = 0
local real angle = 0.
local real increment = (bj_PI * 2) / buffCount
local integer tempInt = 0
//Locate all buffs belonging to this unit
loop
set Node = udg_NP_NextNode[Node]
exitwhen tempInt == buffCount
if udg_NP_Caster[Node] == u and udg_NP_StageID[Node] == NP_BuffStageID() then
//Set up their new position
if buffCount > 1 then
set udg_NP_Offset[Node] = NP_BuffOffset()
set angle = angle + increment
set udg_NP_BuffAngle[Node] = angle
else
set udg_NP_Offset[Node] = 0.
set udg_NP_BuffAngle[Node] = 0.
endif
set tempInt = tempInt + 1
endif
endloop
endfunction
////////////////////////////////////////////////////////////////////
// Function used to remove the infection buff from units and //
// subsequently rearrange all others using the MoveBuff function //
////////////////////////////////////////////////////////////////////
function NP_DestroyBuff takes integer Node, unit u returns nothing
local integer infections = NP_GetInfections(u)
//Remove the buff and recycle it
call NP_RecycleNode(Node)
call KillUnit(udg_NP_Unit[Node])
if not(NP_UseTeamColouredBuff()) then
call DestroyEffect(udg_NP_CurrentEffect[Node])
endif
//Rearrange remaining buffs
if infections > 1 then
call NP_MoveBuffs(u, infections - 1)
endif
endfunction
////////////////////////////////////////////////////////////////////
// Function used to add the infection buff to units and //
// subsequently rearrange all others using the MoveBuff function //
////////////////////////////////////////////////////////////////////
function NP_CreateBuff takes unit u, integer buffCount, real level, player pl returns integer
//set up locals
local integer Node = NP_CreateNode()
//Create new buff
if NP_UseTeamColouredBuff() then
set udg_NP_Unit[Node] = CreateUnit(NP_DummyPlayerID(), NP_TCBuffDummyID(), GetUnitX(u), GetUnitY(u), NP_BuffFacing())
call SetUnitColor(udg_NP_Unit[Node], GetPlayerColor(pl))
else
set udg_NP_Unit[Node] = CreateUnit(NP_DummyPlayerID(), NP_DummyID(), GetUnitX(u), GetUnitY(u), NP_BuffFacing())
set udg_NP_CurrentEffect[Node] = AddSpecialEffectTarget(NP_BuffModel(), udg_NP_Unit[Node], NP_AttachmentPoint())
endif
//Set up buff data
call PauseUnit(udg_NP_Unit[Node], true)
if UnitAddAbility(udg_NP_Unit[Node], 'Amrf') and UnitRemoveAbility(udg_NP_Unit[Node], 'Amrf') then
endif
call SetUnitScale(udg_NP_Unit[Node], NP_BuffSize(level), 0., 0.)
call SetUnitFlyHeight(udg_NP_Unit[Node], GetUnitFlyHeight(u) + NP_BuffHeightOffset(), 0.)
set udg_NP_Caster[Node] = u
set udg_NP_StageID[Node] = NP_BuffStageID()
//Create spawn effect on the affected unit
call DestroyEffect(AddSpecialEffectTarget(NP_BuffSpawnModel(), u, NP_AttachmentPoint()))
//Move all Buffs to fit around the circle
call NP_MoveBuffs(u, buffCount)
//Return the newly created buff
return Node
endfunction
////////////////////////////////////////////////////////////////////
// Function used to produce new nanobots either from a virus //
// or from the instant duplication effect //
////////////////////////////////////////////////////////////////////
function NP_CreateProjectile takes real x, real y, real z, integer Node returns nothing
local integer tempNode = NP_CreateNode()
local real x2
local real y2
local real offset
local real angle = GetRandomReal(-bj_PI, bj_PI)
local real tempReal = udg_NP_ProjectileFlightTime[udg_NP_Instance[Node]] / NP_TimerSpeed()
local real dy
local real dx
//Get target centre
if udg_NP_TargetSelf[Node] then
set x2 = GetUnitX(udg_NP_Unit[Node])
set y2 = GetUnitY(udg_NP_Unit[Node])
else
set x2 = udg_NP_TargetX[Node]
set y2 = udg_NP_TargetY[Node]
endif
//Get random location from the target point (Uniform distribution)
set offset = GetRandomReal(0, udg_NP_AOE[udg_NP_Instance[Node]]) + GetRandomReal(0, udg_NP_AOE[udg_NP_Instance[Node]])
if offset > udg_NP_AOE[udg_NP_Instance[Node]] then
set offset = 2 * udg_NP_AOE[udg_NP_Instance[Node]] - offset
endif
set x2 = x2 + offset * Cos(angle)
set y2 = y2 + offset * Sin(angle)
//Create projectile
set udg_NP_StageID[tempNode] = NP_ProjectileStageID()
set udg_NP_Unit[tempNode] = CreateUnit(NP_DummyPlayerID(), NP_DummyID(), x, y, angle * bj_RADTODEG)
set udg_NP_Instance[tempNode] = udg_NP_Instance[Node]
call SetUnitScale(udg_NP_Unit[tempNode], udg_NP_ProjectileSize[udg_NP_Instance[Node]], 0., 0.)
set udg_NP_CurrentEffect[tempNode] = AddSpecialEffectTarget(NP_ProjectileModel(), udg_NP_Unit[tempNode], NP_AttachmentPoint())
if UnitAddAbility(udg_NP_Unit[tempNode], 'Amrf') and UnitRemoveAbility(udg_NP_Unit[tempNode], 'Amrf') then
endif
call DestroyEffect(AddSpecialEffectTarget(NP_SpawnBuffModel(), udg_NP_Unit[tempNode], NP_AttachmentPoint()))
call SetUnitFlyHeight(udg_NP_Unit[tempNode], z, 0.)
set udg_NP_CurrentZ[tempNode] = z + NP_GetZ(x, y)
call PauseUnit(udg_NP_Unit[tempNode], true)
//Set up movement
set udg_NP_XVel[tempNode] = (x2 - x) / (udg_NP_ProjectileFlightTime[udg_NP_Instance[Node]] / NP_TimerSpeed())
set udg_NP_YVel[tempNode] = (y2 - y) / (udg_NP_ProjectileFlightTime[udg_NP_Instance[Node]] / NP_TimerSpeed())
set udg_NP_ZVel[tempNode] = ((NP_GetZ(x2, y2) - udg_NP_CurrentZ[tempNode]) + ((NP_Gravity() * (tempReal * tempReal)) / 2)) / tempReal
endfunction
////////////////////////////////////////////////////////////////////
// Function used to run the main engine of the spell, handles //
// creation of new units, buff control and projectile control //
////////////////////////////////////////////////////////////////////
function NP_Loop takes nothing returns nothing
//Set up locals
local integer Node = 0
local integer tempNode = 0
local real x
local real y
local real x2
local real y2
loop
set Node = udg_NP_NextNode[Node]
exitwhen Node == 0
//Infections which are producing nanobots
if udg_NP_StageID[Node] == NP_InfectionStageID() then
//Check if the infection is over
if udg_NP_InfectionDuration[Node] > 0. and not(IsUnitType(udg_NP_Unit[Node], UNIT_TYPE_DEAD)) then
//Deal infection damage
set udg_NP_SwarmStrengthBonus[Node] = NP_SwarmStrengthAttackBonus(udg_NP_SwarmStrength[Node])
call UnitDamageTarget(udg_NP_Caster[Node], udg_NP_Unit[Node], udg_NP_InfectionDamageHealth[udg_NP_Instance[Node]], true, false, NP_AttackType(), NP_DamageType(), NP_WeaponType())
call SetUnitState(udg_NP_Unit[Node], UNIT_STATE_MANA, GetUnitState(udg_NP_Unit[Node], UNIT_STATE_MANA) - udg_NP_InfectionDamageMana[udg_NP_Instance[Node]])
set udg_NP_InfectionDuration[Node] = udg_NP_InfectionDuration[Node] - NP_TimerSpeed()
//Check if it's time to produce a new nanobot
if udg_NP_CurrentProductionDelay[Node] <= 0. then
set udg_NP_CurrentProductionDelay[Node] = udg_NP_ProductionDelay[udg_NP_Instance[Node]]
//Produce new nanobot
call NP_CreateProjectile(GetUnitX(udg_NP_Unit[udg_NP_BuffNode[Node]]), GetUnitY(udg_NP_Unit[udg_NP_BuffNode[Node]]), GetUnitFlyHeight(udg_NP_Unit[udg_NP_BuffNode[Node]]), Node)
set udg_NP_SwarmStrength[udg_NP_Instance[Node]] = udg_NP_SwarmStrength[udg_NP_Instance[Node]] + 1
else
set udg_NP_CurrentProductionDelay[Node] = udg_NP_CurrentProductionDelay[Node] - NP_TimerSpeed()
endif
else
set udg_NP_StageID[Node] = NP_WaitingStageID()
set udg_NP_SwarmStrength[udg_NP_Instance[Node]] = udg_NP_SwarmStrength[udg_NP_Instance[Node]] - 1
endif
//Projectiles
elseif udg_NP_StageID[Node] == NP_ProjectileStageID() then
//Move projectiles
set x = GetUnitX(udg_NP_Unit[Node]) + udg_NP_XVel[Node]
set y = GetUnitY(udg_NP_Unit[Node]) + udg_NP_YVel[Node]
set udg_NP_ZVel[Node] = udg_NP_ZVel[Node] - NP_Gravity()
set udg_NP_CurrentZ[Node] = udg_NP_CurrentZ[Node] + udg_NP_ZVel[Node]
if NP_ValidateLocation(x, y) then
call SetUnitX(udg_NP_Unit[Node], x)
call SetUnitY(udg_NP_Unit[Node], y)
endif
set x2 = udg_NP_CurrentZ[Node] - NP_GetZ(x,y)
call SetUnitFlyHeight(udg_NP_Unit[Node], x2, 0.)
if x2 < 0 then
//Crash, remove projectile data
call DestroyEffect(udg_NP_CurrentEffect[Node])
call KillUnit(udg_NP_Unit[Node])
call NP_RecycleNode(Node)
//Create summon
set tempNode = NP_CreateNode()
set udg_NP_Unit[tempNode] = CreateUnit(udg_NP_Player[udg_NP_Instance[Node]], NP_SummonedUnitID(), x, y, GetUnitFacing(udg_NP_Unit[Node]))
call UnitApplyTimedLife(udg_NP_Unit[tempNode], NP_SummonBuffID(), udg_NP_SummonDuration[udg_NP_Instance[Node]])
call SetUnitScale(udg_NP_Unit[tempNode], udg_NP_SummonSize[udg_NP_Instance[Node]], 0., 0.)
call UnitAddAbility(udg_NP_Unit[tempNode], NP_InfectAbilityID())
call SetUnitAbilityLevel(udg_NP_Unit[tempNode], NP_InfectAbilityID(), udg_NP_SummonLevel[udg_NP_Instance[Node]])
//Apply bonuses
call CSS_AddBonus(udg_NP_Unit[tempNode], udg_NP_SummonArmour[udg_NP_Instance[Node]], 0)
call CSS_AddBonus(udg_NP_Unit[tempNode], udg_NP_SummonAttackSpeed[udg_NP_Instance[Node]], 1)
call CSS_AddBonus(udg_NP_Unit[tempNode], udg_NP_SummonAttackDamage[udg_NP_Instance[Node]], 2)
call CSS_AddBonus(udg_NP_Unit[tempNode], udg_NP_SummonHealthRegen[udg_NP_Instance[Node]], 6)
call CSS_AddBonus(udg_NP_Unit[tempNode], udg_NP_SummonHealth[udg_NP_Instance[Node]], 8)
//Set up logic
set udg_NP_StageID[tempNode] = NP_NanobotStageID()
set udg_NP_Instance[tempNode] = udg_NP_Instance[Node]
set udg_NP_Caster[tempNode] = udg_NP_Caster[udg_NP_Instance[Node]]
endif
//Nanobots produced by the spell
elseif udg_NP_StageID[Node] == NP_NanobotStageID() then
//Check if it's still alive
if (IsUnitType(udg_NP_Unit[Node], UNIT_TYPE_DEAD)) then
set udg_NP_SwarmStrength[udg_NP_Instance[Node]] = udg_NP_SwarmStrength[udg_NP_Instance[Node]] - 1
call NP_RecycleNode(Node)
else
//Apply buff
call CSS_ClearBonus(udg_NP_Unit[Node], 2)
call CSS_AddBonus(udg_NP_Unit[Node], udg_NP_SummonAttackDamage[udg_NP_Instance[Node]] + udg_NP_SwarmStrengthBonus[udg_NP_Instance[Node]], 2)
endif
//Infection buffs
elseif udg_NP_StageID[Node] == NP_BuffStageID() then
//Update location of Buffs
set x = GetUnitX(udg_NP_Caster[Node])
set y = GetUnitY(udg_NP_Caster[Node])
set x2 = x + udg_NP_Offset[Node] * Cos(udg_NP_BuffAngle[Node])
set y2 = y + udg_NP_Offset[Node] * Sin(udg_NP_BuffAngle[Node])
call SetUnitX(udg_NP_Unit[Node], x2)
call SetUnitY(udg_NP_Unit[Node], y2)
call SetUnitFlyHeight(udg_NP_Unit[Node], GetUnitFlyHeight(udg_NP_Caster[Node]) + NP_BuffHeightOffset() + (NP_GetZ(x, y) - NP_GetZ(x2, y2)), 0.)
//Infection instances that are no longer producing
elseif udg_NP_SwarmStrength[udg_NP_Instance[Node]] > 0 then
set udg_NP_SwarmStrengthBonus[Node] = NP_SwarmStrengthAttackBonus(udg_NP_SwarmStrength[Node])
else
call NP_DestroyBuff(udg_NP_BuffNode[Node], udg_NP_Unit[Node])
call NP_RecycleNode(Node)
//If the unit has no other infections, remove the buff
if NP_GetInfections(udg_NP_Unit[Node]) == 0 then
call UnitRemoveAbility(udg_NP_Unit[Node], NP_BuffID())
endif
endif
endloop
endfunction
////////////////////////////////////////////////////////////////////
// Function used to start an instance of the plague //
////////////////////////////////////////////////////////////////////
function NP_StartPlague takes nothing returns boolean
//Set up locals
local integer Node
local integer SpellID = GetSpellAbilityId()
local integer instance
local integer infections
local integer ilevel
local real level
local unit u
local unit u2
local boolean bNew = false
local boolean bTargetSelf = false
//Check if something was infected
if SpellID == NP_AbilityID() or SpellID == NP_InfectAbilityID() then
set u = GetSpellTargetUnit()
set u2 = GetTriggerUnit()
//Check if a the unit was infected by a summoned unit or by itself
if SpellID == NP_InfectAbilityID() then
set infections = NP_GetInfections(u)
set instance = NP_GetNode(u2)
//Check if the unit has been infected from this instance before
if NP_IsInfected(u, udg_NP_Instance[instance]) or (infections >= NP_InfectionLimit()) then
//Deal bonus damage when attempting to infect
call UnitDamageTarget(u2, u, udg_NP_HealthDamage[instance], true, false, NP_AttackType(), NP_DamageType(), NP_WeaponType())
call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MANA) - udg_NP_ManaDamage[instance])
//Instantly create a clone
if GetRandomReal(0, 1) <= udg_NP_DuplicationChance[udg_NP_Instance[instance]] then
call NP_CreateProjectile(GetUnitX(udg_NP_Unit[instance]), GetUnitY(udg_NP_Unit[instance]), GetUnitFlyHeight(udg_NP_Unit[instance]), udg_NP_Instance[instance])
endif
else
//Remove the infecting unit
set bTargetSelf = true
call RemoveUnit(udg_NP_Unit[instance])
call NP_RecycleNode(instance)
set bNew = true
endif
else
//Prevent targetting of other units
if not(u == u2) then
set u = u2
else
set bTargetSelf = true
endif
set infections = NP_GetInfections(u)
if infections < NP_InfectionLimit() then
set bNew = true
endif
endif
//Check if a new instance needs to be created
if (bNew) then
//Initialise Noe
set Node = NP_CreateNode()
if udg_NP_PrevNode[Node] == 0 then
call TimerStart(udg_NP_Timer, NP_TimerSpeed(), true, function NP_Loop)
endif
//Set up plague data
set level = GetUnitAbilityLevel(u2, SpellID)
set ilevel = R2I(level)
set udg_NP_Unit[Node] = u
set udg_NP_Player[Node] = GetTriggerPlayer()
set udg_NP_BuffNode[Node] = NP_CreateBuff(u, infections + 1, level, udg_NP_Player[Node])
set udg_NP_TargetSelf[Node] = bTargetSelf
set udg_NP_TargetX[Node] = GetSpellTargetX()
set udg_NP_TargetY[Node] = GetSpellTargetY()
set udg_NP_ProductionDelay[Node] = 1 / NP_ProductionPS(level)
set udg_NP_CurrentProductionDelay[Node] = udg_NP_ProductionDelay[Node]
set udg_NP_InfectionDuration[Node] = NP_InfectDuration(level)
set udg_NP_StageID[Node] = NP_InfectionStageID()
//Pass instance along if the unit was infected by an existing plague
if SpellID == NP_InfectAbilityID() then
set udg_NP_Instance[Node] = udg_NP_Instance[instance]
set udg_NP_Caster[Node] = udg_NP_Caster[instance]
set udg_NP_SwarmStrength[Node] = 0
else
//Set up data only needed by the original instance
set udg_NP_Instance[Node] = Node
set udg_NP_Caster[Node] = u
set udg_NP_SwarmStrength[Node] = 1
set udg_NP_AOE[Node] = NP_AOE(level)
set udg_NP_ProjectileSize[Node] = NP_ProjectileSize(level)
set udg_NP_ProjectileFlightTime[Node] = NP_ProjectileFlightTime(level)
set udg_NP_InfectionDamageHealth[Node] = NP_InfectDPSHealth(level) * NP_TimerSpeed()
set udg_NP_InfectionDamageMana[Node] = NP_InfectDPSMana(level) * NP_TimerSpeed()
set udg_NP_DuplicationChance[Node] = NP_InstantDuplicationChance(level)
set udg_NP_HealthDamage[Node] = NP_InfectBonusDamageHealth(level)
set udg_NP_ManaDamage[Node] = NP_InfectBonusDamageMana(level)
set udg_NP_SummonDuration[Node] = NP_SummonDuration(level)
set udg_NP_SummonSize[Node] = NP_SummonSize(level)
set udg_NP_SummonHealth[Node] = NP_SummonHealthBonus(ilevel)
set udg_NP_SummonHealthRegen[Node] = NP_SummonHealthRegenBonus(ilevel)
set udg_NP_SummonArmour[Node] = NP_SummonArmourBonus(ilevel)
set udg_NP_SummonAttackDamage[Node] = NP_SummonAttackDamageBonus(ilevel)
set udg_NP_SummonAttackSpeed[Node] = NP_SummonAttackSpeedBonus(ilevel)
set udg_NP_SummonLevel[Node] = ilevel
endif
//Add buff if this is the first infection
if infections == 0 then
call UnitAddAbility(udg_NP_Unit[Node], NP_BuffID())
endif
endif
set u2 = null
set u = null
endif
return false
endfunction
////////////////////////////////////////////////////////////////////
// Function used to enable automatic infections //
////////////////////////////////////////////////////////////////////
function NP_AutoInfection takes nothing returns boolean
local unit u = GetAttacker()
if GetUnitTypeId(u) == NP_SummonedUnitID() then
call IssueTargetOrderById(u, NP_AttackOrder(), GetTriggerUnit())
endif
return false
endfunction
////////////////////////////////////////////////////////////////////
// Function used to register the trigger of the ability //
////////////////////////////////////////////////////////////////////
function InitTrig_Nano_Plague takes nothing returns nothing
//Set up local variables
local trigger t = CreateTrigger()
//Set up trigger
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function NP_StartPlague))
set udg_NP_ZLoc = Location(0., 0.)
//Create the trigger which automates the infection process if wanted
if NP_AutoInfect() then
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddCondition(t, Condition(function NP_AutoInfection))
endif
//Sets up the variables used to make sure a point is within the map area
set udg_NP_MapMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
set udg_NP_MapMinX = GetRectMinX(bj_mapInitialPlayableArea)
set udg_NP_MapMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
set udg_NP_MapMinY = GetRectMinY(bj_mapInitialPlayableArea)
endfunction
////////////////////////////////////////////////////////////////////
//END OF THE SPELL //
////////////////////////////////////////////////////////////////////
Edit: And just because I haven't posted an image of it yet, here's one showing the team colouring of the Buffs
Attachments
Last edited: