Spreading Plague v4.03

This bundle is marked as approved. It works and satisfies the submission rules.
  • Like
Reactions: deepstrasz and ILH

Spell Preview

Spell Description

Requirements

SP_GIF.jpg
SP_ICON.jpg
Spreading Plague
Temporarily infects the targeted unit, slightly increasing their
movement speed. Whenever the infected unit gets too close
to an ally, they will also be infected. Once the duration is
over, they will take damage based on their maximum hit
points. If any infected unit dies, they will deal AoE damage
to nearby units and turn into a zombie.​
  • GUI Unit Indexer
    • Adds unique infect timers for each infected unit

  • SimError (optional, but requires JNGP)
    • Simulates in-game error messages

Triggers

How to Install

Credits

Changelog

  • SP Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- !! CONFIG START !! --------
      • -------- Abilities --------
      • Set SP_Ability = Spreading Plague
      • -------- Order ID for SP_Ability --------
      • Set SP_Order_ID = channel
      • -------- Movement Speed Factor Ability --------
      • -------- NOTE: If you want to change the buff SFX, refer to this ability --------
      • Set SP_AbilityMSFactor = Spreading Plague (Movement Speed)
      • -------- --------
      • -------- Max Level SP_Ability Will Have --------
      • -------- NOTE: THIS IS REALLY IMPORTANT IF YOU WANT DAMAGE TO WORK PROPERLY --------
      • Set SP_MaxLevel = 3
      • -------- --------
      • -------- Radius for Infection to Transfer --------
      • Set SP_InfectRange = 130.00
      • -------- How Often to Infect a Nearby Unit in Seconds --------
      • Set SP_InfectTime = 0.60
      • -------- Percent Chance of a Nearby Unit Becoming Infected Per Level --------
      • -------- NOTE: Between 0.00 and 100.00 --------
      • Set SP_InfectChance[1] = 100.00
      • Set SP_InfectChance[2] = 100.00
      • Set SP_InfectChance[3] = 100.00
      • -------- Special Effect for Succesful Infection Transfer --------
      • Set SP_SFXInfect = Abilities\Spells\Undead\DeathCoil\DeathCoilSpecialArt.mdl
      • -------- Attachment Point For SFXInfect --------
      • Set SP_SFXInfect_AP = origin
      • -------- --------
      • -------- Percent of Infected Unit's Max Health Dealt as Damage Per Level --------
      • -------- NOTE: Damage is dealt once the duration of the debuff is over --------
      • Set SP_Damage[1] = 25.00
      • Set SP_Damage[2] = 35.00
      • Set SP_Damage[3] = 45.00
      • -------- Special Effect for Damage Dealt --------
      • Set SP_SFXDamage = Abilities\Weapons\ChimaeraAcidMissile\ChimaeraAcidMissile.mdl
      • -------- Attachment Point for SFXDamage --------
      • Set SP_SFXDamage_AP = origin
      • -------- --------
      • -------- Duration of Infection Per Level --------
      • Set SP_Duration[1] = 4.00
      • Set SP_Duration[2] = 6.00
      • Set SP_Duration[3] = 8.00
      • -------- --------
      • -------- Should There be a Limit to How Many can get Infected? --------
      • Set SP_InfectionLimit = False
      • -------- Infected Unit Limit Per Level --------
      • Set SP_MaxInfect[1] = 5
      • Set SP_MaxInfect[2] = 7
      • Set SP_MaxInfect[3] = 10
      • -------- --------
      • -------- Explosion Damage Per Level --------
      • Set SP_ExplosionDamage[1] = 100.00
      • Set SP_ExplosionDamage[2] = 150.00
      • Set SP_ExplosionDamage[3] = 200.00
      • -------- Radius for Death Explosion --------
      • Set SP_DeathAoE = 150.00
      • -------- Special Effect for Explosion --------
      • Set SP_SFXExplode = Abilities\Spells\Other\AcidBomb\BottleMissile.mdl
      • -------- --------
      • -------- Should Infected Unit Change Colors? --------
      • -------- NOTE: This will conflict with any other spells/systems that change the vertex color of units --------
      • -------- Also keep in mind this only works for units that have 100% vertex coloring across the board. Some units do not have that. --------
      • Set SP_ChangeColor = True
      • -------- Vertex Color Percentage --------
      • Set SP_Red = 60.00
      • Set SP_Green = 100.00
      • Set SP_Blue = 60.00
      • -------- --------
      • -------- Should it Spawn a Zombie? --------
      • Set SP_SpawnZombie = True
      • -------- Zombie Unit-Type --------
      • Set SP_UnitType[1] = Zombie (Level 1)
      • Set SP_UnitType[2] = Zombie (Level 2)
      • Set SP_UnitType[3] = Zombie (Level 3)
      • -------- Should Spawned Zombie be Temporary? --------
      • Set SP_ZombieExpire = True
      • -------- Zombie Duration --------
      • Set SP_ZombieDuration[1] = 10.00
      • Set SP_ZombieDuration[2] = 15.00
      • Set SP_ZombieDuration[3] = 20.00
      • -------- --------
      • -------- Other Damage Configurables --------
      • Set SP_AttackType = Spells
      • Set SP_DamageType = Normal
      • -------- !! CONFIG END !! --------
      • -------- --------
      • Set SP_PeriodicTimer = (Min(SP_InfectTime, 0.10))
      • Trigger - Add to SP Loop <gen> the event (Time - Every SP_PeriodicTimer seconds of game time)
      • For each (Integer SP_TempInt) from 1 to SP_MaxLevel, do (Actions)
        • Loop - Actions
          • Set SP_Damage[SP_TempInt] = (SP_Damage[SP_TempInt] / 100.00)

  • SP Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to SP_Ability
    • Actions
      • Set SP_SpellCount = (SP_SpellCount + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SP_SpellCount Equal to 1
        • Then - Actions
          • Trigger - Turn on SP Loop <gen>
        • Else - Actions
          • -------- loop is already on; do nothing --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SP_RecycledSize Equal to 0
        • Then - Actions
          • Set SP_IndexMax = (SP_IndexMax + 1)
          • Set SP_Spell_ID = SP_IndexMax
        • Else - Actions
          • Set SP_RecycledSize = (SP_RecycledSize - 1)
          • Set SP_Spell_ID = SP_RecycledStack[SP_RecycledSize]
      • Set SP_NodeNext[SP_Spell_ID] = 0
      • Set SP_NodeNext[SP_NodePrev[0]] = SP_Spell_ID
      • Set SP_NodePrev[SP_Spell_ID] = SP_NodePrev[0]
      • Set SP_NodePrev[0] = SP_Spell_ID
      • -------- --------
      • Set SP_Caster[SP_Spell_ID] = (Triggering unit)
      • Set SP_Owner[SP_Spell_ID] = (Triggering player)
      • Set SP_AbilityLvl[SP_Spell_ID] = (Level of SP_Ability for SP_Caster[SP_Spell_ID])
      • Set SP_CounterDuration[SP_Spell_ID] = 0.00
      • Set SP_GroupCount[SP_Spell_ID] = 0
      • -------- --------
      • Set SP_TempUnit = (Target unit of ability being cast)
      • Custom script: if udg_SP_GroupInfected[udg_SP_Spell_ID] == null then
      • Custom script: set udg_SP_GroupInfected[udg_SP_Spell_ID] = CreateGroup()
      • Custom script: endif
      • Unit Group - Add SP_TempUnit to SP_GroupInfected[SP_Spell_ID]
      • Unit Group - Add SP_TempUnit to SP_GroupCheck
      • Set SP_GroupCount[SP_Spell_ID] = (SP_GroupCount[SP_Spell_ID] + 1)
      • -------- --------
      • Special Effect - Create a special effect attached to the SP_SFXInfect_AP of SP_TempUnit using SP_SFXInfect
      • Special Effect - Destroy (Last created special effect)
      • Unit - Add SP_AbilityMSFactor to SP_TempUnit
      • -------- --------
      • -------- checking if user wants to change color of units --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SP_ChangeColor Equal to True
        • Then - Actions
          • Animation - Change SP_TempUnit's vertex coloring to (SP_Red%, SP_Green%, SP_Blue%) with 0.00% transparency
        • Else - Actions
          • -------- user does not want to change color of infected unit; do nothing --------
  • SP Cancel
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
      • (Issued order) Equal to (Order(SP_Order_ID))
      • (Level of SP_Ability for (Triggering unit)) Greater than 0
    • Actions
      • Set SP_TempUnit = (Target unit of issued order)
      • -------- simulates an ingame error message if the targeted unit is already infected --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (SP_TempUnit is in SP_GroupCheck) Equal to True
        • Then - Actions
          • Set SP_TempUnit = (Triggering unit)
          • Unit - Pause SP_TempUnit
          • Unit - Order SP_TempUnit to Stop
          • Unit - Unpause SP_TempUnit
          • -------- NOTE: SimError is optional, but requires JNGP to use --------
          • -------- if you do not want to use SimError, delete this custom script --------
          • Custom script: call SimError(GetTriggerPlayer(), "Target is already infected,")
        • Else - Actions
          • -------- TempUnit has not been infected yet; start new spell instance --------
  • SP Loop
    • Events
    • Conditions
    • Actions
      • Set SP_Spell_ID = 0
      • For each (Integer SP_LoopInt) from 1 to SP_SpellCount, do (Actions)
        • Loop - Actions
          • Set SP_Spell_ID = SP_NodeNext[SP_Spell_ID]
          • Set SP_CounterDuration[SP_Spell_ID] = (SP_CounterDuration[SP_Spell_ID] + SP_PeriodicTimer)
          • -------- checking if the instance duration has ended --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SP_CounterDuration[SP_Spell_ID] Greater than or equal to SP_Duration[SP_AbilityLvl[SP_Spell_ID]]
            • Then - Actions
              • -------- dealing damage to all infected units --------
              • Unit Group - Pick every unit in SP_GroupInfected[SP_Spell_ID] and do (Actions)
                • Loop - Actions
                  • Set SP_TempUnit = (Picked unit)
                  • Set SP_UnitID = (Custom value of SP_TempUnit)
                  • Set SP_TempReal = ((Max life of SP_TempUnit) x SP_Damage[SP_AbilityLvl[SP_Spell_ID]])
                  • Unit - Remove SP_AbilityMSFactor from SP_TempUnit
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • SP_ChangeColor Equal to True
                    • Then - Actions
                      • Animation - Change SP_TempUnit's vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
                    • Else - Actions
                      • -------- user does not want to change color of infected units; do nothing --------
                  • Special Effect - Create a special effect attached to the SP_SFXDamage_AP of SP_TempUnit using SP_SFXDamage
                  • Special Effect - Destroy (Last created special effect)
                  • Unit - Cause SP_Caster[SP_Spell_ID] to damage SP_TempUnit, dealing SP_TempReal damage of attack type SP_AttackType and damage type SP_DamageType
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (SP_TempUnit is alive) Equal to True
                    • Then - Actions
                      • Unit - Make SP_TempUnit Die normally on death
                    • Else - Actions
                      • -------- TempUnit is no longer alive; keep Explode on death marker --------
                  • Set SP_WillExplode[SP_UnitID] = False
                  • Unit Group - Remove SP_TempUnit from SP_GroupCheck
                  • Unit Group - Remove SP_TempUnit from SP_GroupInfected[SP_Spell_ID]
              • Custom script: call DestroyGroup(udg_SP_GroupInfected[udg_SP_Spell_ID])
              • Custom script: set udg_SP_GroupInfected[udg_SP_Spell_ID] = null
              • -------- --------
              • Set SP_RecycledStack[SP_RecycledSize] = SP_Spell_ID
              • Set SP_RecycledSize = (SP_RecycledSize + 1)
              • Set SP_NodeNext[SP_NodePrev[SP_Spell_ID]] = SP_NodeNext[SP_Spell_ID]
              • Set SP_NodePrev[SP_NodeNext[SP_Spell_ID]] = SP_NodePrev[SP_Spell_ID]
              • -------- --------
              • Set SP_SpellCount = (SP_SpellCount - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SP_SpellCount Equal to 0
                • Then - Actions
                  • Trigger - Turn off SP Loop <gen>
                • Else - Actions
                  • -------- there is still a spell instance running; do not turn loop off --------
            • Else - Actions
              • -------- creating unique infect timer for all infected units --------
              • Unit Group - Pick every unit in SP_GroupInfected[SP_Spell_ID] and do (Actions)
                • Loop - Actions
                  • Set SP_TempUnit = (Picked unit)
                  • Set SP_UnitID = (Custom value of SP_TempUnit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • SP_WillExplode[SP_UnitID] Equal to False
                    • Then - Actions
                      • Unit - Make SP_TempUnit Explode on death
                      • Set SP_WillExplode[SP_UnitID] = True
                      • Set SP_Node[SP_UnitID] = SP_Spell_ID
                    • Else - Actions
                      • -------- TempUnit has already been marked; do nothing --------
                  • Set SP_CounterInfect[SP_UnitID] = (SP_CounterInfect[SP_UnitID] + SP_PeriodicTimer)
                  • -------- checking if buffer time to infect has been reached --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • SP_CounterInfect[SP_UnitID] Greater than or equal to SP_InfectTime
                    • Then - Actions
                      • Set SP_CounterInfect[SP_UnitID] = 0.00
                      • Set SP_TempReal = (Random real number between 0.00 and 100.00)
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • SP_TempReal Less than or equal to SP_InfectChance[SP_AbilityLvl[SP_Spell_ID]]
                        • Then - Actions
                          • Set SP_TempLoc = (Position of SP_TempUnit)
                          • -------- looking for potential units to infect --------
                          • Custom script: set bj_wantDestroyGroup = true
                          • Unit Group - Pick every unit in (Units within SP_InfectRange of SP_TempLoc) and do (Actions)
                            • Loop - Actions
                              • Set SP_TempUnit = (Picked unit)
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (SP_TempUnit is A structure) Equal to False
                                  • (SP_TempUnit is A Hero) Equal to False
                                  • (SP_TempUnit is Mechanical) Equal to False
                                  • (SP_TempUnit is Magic Immune) Equal to False
                                  • (SP_TempUnit is in SP_GroupCheck) Equal to False
                                  • (SP_TempUnit is alive) Equal to True
                                  • (SP_TempUnit belongs to an enemy of SP_Owner[SP_Spell_ID]) Equal to True
                                  • Or - Any (Conditions) are true
                                    • Conditions
                                      • SP_InfectionLimit Equal to False
                                      • SP_GroupCount[SP_Spell_ID] Less than SP_MaxInfect[SP_AbilityLvl[SP_Spell_ID]]
                                • Then - Actions
                                  • Unit Group - Add SP_TempUnit to SP_GroupInfected[SP_Spell_ID]
                                  • Unit Group - Add SP_TempUnit to SP_GroupCheck
                                  • Set SP_GroupCount[SP_Spell_ID] = (SP_GroupCount[SP_Spell_ID] + 1)
                                  • Unit - Add SP_AbilityMSFactor to SP_TempUnit
                                  • Special Effect - Create a special effect attached to the SP_SFXInfect_AP of SP_TempUnit using SP_SFXInfect
                                  • Special Effect - Destroy (Last created special effect)
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • SP_ChangeColor Equal to True
                                    • Then - Actions
                                      • Animation - Change SP_TempUnit's vertex coloring to (SP_Red%, SP_Green%, SP_Blue%) with 0.00% transparency
                                    • Else - Actions
                                      • -------- user does not want to change color of infected units; do nothing --------
                                • Else - Actions
                                  • -------- TempUnit did not pass filters; do not infect them --------
                          • Custom script: call RemoveLocation(udg_SP_TempLoc)
                        • Else - Actions
                          • -------- InfectChance was not met; do not infect nearby units --------
                    • Else - Actions
                      • -------- buffer time to infect has not been reached; do not infect nearby units --------
  • SP Death
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Triggering unit) is in SP_GroupCheck) Equal to True
    • Actions
      • Set SP_TempUnit = (Triggering unit)
      • Set SP_UnitID = (Custom value of SP_TempUnit)
      • Set SP_TempInt = SP_Node[SP_UnitID]
      • -------- --------
      • Set SP_TempLoc = (Position of SP_TempUnit)
      • Special Effect - Create a special effect at SP_TempLoc using SP_SFXExplode
      • Special Effect - Destroy (Last created special effect)
      • -------- checking if user wants units to spawn from death --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SP_SpawnZombie Equal to True
        • Then - Actions
          • Set SP_TempReal = (Facing of SP_TempUnit)
          • Unit - Create 1 SP_UnitType[SP_AbilityLvl[SP_TempInt]] for SP_Owner[SP_TempInt] at SP_TempLoc facing SP_TempReal degrees
          • Set SP_TempUnit = (Last created unit)
          • -------- checking if user wants to make spawned units temporary --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SP_ZombieExpire Equal to True
            • Then - Actions
              • Unit - Add a SP_ZombieDuration[SP_AbilityLvl[SP_TempInt]] second Generic expiration timer to SP_TempUnit
            • Else - Actions
              • -------- user does not want an expiration timer on spawned units; do nothing --------
        • Else - Actions
          • -------- user does not want to spawn units; do nothing --------
      • -------- looking for all units within DeathAoE of dying unit --------
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within SP_DeathAoE of SP_TempLoc) and do (Actions)
        • Loop - Actions
          • Set SP_TempUnit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (SP_TempUnit is A structure) Equal to False
              • (SP_TempUnit is Magic Immune) Equal to False
              • (SP_TempUnit is alive) Equal to True
              • (SP_TempUnit belongs to an enemy of SP_Owner[SP_TempInt]) Equal to True
            • Then - Actions
              • Unit - Cause SP_Caster[SP_TempInt] to damage SP_TempUnit, dealing SP_ExplosionDamage[SP_AbilityLvl[SP_TempInt]] damage of attack type SP_AttackType and damage type SP_DamageType
            • Else - Actions
              • -------- TempUnit did not pass filters; do nothing --------
      • Unit Group - Remove SP_TempUnit from SP_GroupCheck
      • Unit Group - Remove SP_TempUnit from SP_GroupInfected[SP_TempInt]
      • Custom script: call RemoveLocation(udg_SP_TempLoc)

  1. Under Preferences, make sure you have "Automatically create
    unknown variables while pasting trigger data" checked

  2. Copy and paste the two custom abilities and buff into your map

  3. Copy and paste the Resources Folder into your map
    NOTE: If you already have a resource in the Resources
    folder imported into your map, you DO NOT have to reimport it
    If you do not want to use SimError, do not import it and remove
    the call SimError() custom script inside the SP Cancel trigger

  4. Copy and paste the Spreading Plague folder into your map

  5. Go to the SP Config trigger, and change the Ability and
    AbilityMSFactor variables to the corresponding objects you just
    imported
NOTE: You do not have to copy the Zombie units. You can make
your own in your map if you wish to spawn zombies :)
Make sure that AbilityMSFactor has the right buff data field in
Object Editor!​
User
Bribe - GUI Unit Indexer
Darkfish - original idea (added more features on top of his)
Vexorian - SimError

v4.03 (March 22, 2016)
  • Added an extra condition for SP Cancel to make sure that issued order is relative to a unit that has the SP_Ability
  • Fixed an if statement inside the SP Loop integrated with GUI Spell System still using AbilityLvl[] instead of Spell__Level

v4.02 (March 02, 2016)
  • Added a configurable for the percent chance of a nearby unit becoming infected
v4.01 (February 29, 2016)
  • Added an optional Spreading Plague folder that is integrated with GUI Spell System
  • Fixed issue of the caster still losing mana + spell going on cooldown when attempting to infect an infected unit
  • Removed unnecesary NodeLast[] variable for linked list; last spell instance now stores into NodePrev[0]
  • Removed If/Then/Else that would set NodeLast = NodePrev[Spell_ID] if NodeLast == Spell_ID
v4.00 (January 09, 2016)
  • Added a hero filter; heroes can no longer be infected
  • Changed data structure to linked listing
  • Fixed bug of infected units not spawning a zombie when they die DURING the duration of the infection
v3.00 (December 04, 2015)
  • Added a configurable for how often a unit can be infected
  • Added Bribe's GUI Unit Indexer
  • Changed Owner[] variable to now use Triggering Player instead of Owner of (Unit)
  • Changed loop to check if it is time to deindex before starting
  • Changed name of SP Init trigger to SP Cast
  • Removed unnecessary function call when turning off SP Loop (Turn off (This trigger) -> (Turn off SP Loop))
v2.00 (November 26, 2015)
  • Fixed death feature to now be relevant to the instance damage they die from
  • Removed SP Death trigger
  • Removed the use of a damage detection system
v1.06 (October 16, 2015)
  • Changed names of some variables
  • Removed unneccesary variables
v1.05 (September 22, 2015)
  • Added notes about SimError being optional
  • Fixed the way a variable would keep track of # of units infected with MaxLimit
  • Removed unneccesary If/Then/Else before infection block
v1.04 (September 18, 2015)
  • Added a new Buff SFX
  • Fixed CheckGroup & PickedUnitGLoc leak (originally wasn't destroying every iteration)
  • Fixed the transfer of SP_Group between deindexes
v1.03 (September 08, 2015)
  • Added a configurable for SFX attachment points
  • Added a configurable for attack and damage type
  • Added a few more instance variables (Owner, AbilityLvl, & GroupCount)
  • Fixed Group transfer issue between CurrentIndex & MaxIndex
  • Fixed CheckGroup to be a non-array
  • Fixed conditions for infecting so that there is now only one infection block
  • Fixed InfectedGroup to no longer be a local variable
v1.02 (September 03, 2015)
  • Added a configurable to add an expiration timer to Zombies
  • Added a configurable to set a max limit of infected units per cast
v1.01 (September 02, 2015)
  • Added a configurable for changing vertex color of infected units
  • Added a configurable for changing Damage SFX
  • Added a magic immune filter
  • Added a buff indicator
  • Fixed way SP_DyingUnitLoc was used in the SP Death trigger
  • Fixed a Picked unit function call in one of the groups to its correct corresponding variable
  • Removed movement speed modification from trigger and made it Object Editor Data
  • Removed debug message when an infected unit dies
v1.00 (September 02, 2015)
  • Uploaded

Keywords:
spreading, plague, necromancer, undead, spawn, zombie, minion, green, infect, infection, explosion, explode, unit, target, aoe, gui, mui, spell, syste
Contents

Spreading Plague v4.03 (Map)

Reviews
IcemanBo: re-approved. 10 Jan 2016 Bribe: Set back to pending on author's request while awaiting review of new version. IcemanBo: re-approved. 15:58, 20ndth Sep 2015 This resource has been Approved by BPower. Criticism: The spell is...

Moderator

M

Moderator

IcemanBo: re-approved.

10 Jan 2016
Bribe: Set back to pending on author's request while awaiting review of new version.

IcemanBo: re-approved.

15:58, 20ndth Sep 2015

This resource has been Approved by BPower.

Criticism:
The spell is MUI, leakless and working. The documentation is also done very well.
I realised that you set an optional upper bound for infected units per spell cast,
but when adding new units you don't increase the group count by 1 each time
a new unit is added to the group. It's the only small flaw in your code, which I found.
 
Colour of being infected should be configurable, as should whether or not a units colour is changed at all by the ability (as some units do not have an original vertex colouring of 100% across the board)

A buff should be applied to units that have been infected for the duration of the infection (using slow aura as a base and have it self-inflicted) the same buff can and should be used ot modify movement speeds as controlling it through triggers can lead to problems when interacting with other spells

You've left a debug message (the level of the ability display) in the script, should remove that

In SP Death you set the location variable SP_DyingUnitLoc to create the effect, destroy it and then set it to create the zombie, then destroy the location then immediately set it to the same point again afterwards, just set it once at the top and destroy it once

Magic immune enemies can currently be selected as infected, this shouldn't be the case (and if you wanted to keep it, it should be optional) as this does not follow standard WC3 spell convention

You reference Picked unit when you have SP_PickedUnitG set in the SP Loop trigger for the special effect (presumably an oversight)

Attack type and damage type could be configurable (though this is not really needed)

That covers my initial analysis
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
Colour of being infected should be configurable, as should whether or not a units colour is changed at all by the ability (as some units do not have an original vertex colouring of 100% across the board)

Done :) I thought about doing this, but totally forgot to due to excitement from uploading.

A buff should be applied to units that have been infected for the duration of the infection (using slow aura as a base and have it self-inflicted) the same buff can and should be used ot modify movement speeds as controlling it through triggers can lead to problems when interacting with other spells

I wanted to see how far I can go without using dummy units or abilities, however now that you bring it up, I can see this as a potential problem in the future with other spells ;_; i am a little confused by why you want me to use Slow Aura as the base spell? The spell is a unit-target spell, not AoE.

You've left a debug message (the level of the ability display) in the script, should remove that

Yes I should xP that was me testing to make sure the level of the ability happens before the de-index. I told myself to remove it, but the excitement has once again came back on top. Removed!

In SP Death you set the location variable SP_DyingUnitLoc to create the effect, destroy it and then set it to create the zombie, then destroy the location then immediately set it to the same point again afterwards, just set it once at the top and destroy it once

Oh silly me. I'm not sure why I did this ._. it might have something to do with me still trying to fix the spell at 4:30 in the morning. Fixed!

Magic immune enemies can currently be selected as infected, this shouldn't be the case (and if you wanted to keep it, it should be optional) as this does not follow standard WC3 spell convention

This completely slipped my mine, thank you!

You reference Picked unit when you have SP_PickedUnitG set in the SP Loop trigger for the special effect (presumably an oversight)

Thanks again.
 
Normally what you do with slow aura is you make a modification of Slow aura (tornado) and change the target to self - so it only affects the unit with the ability you can then with script add/remove the ability (and set the level to get different levels of slow) on affected units, the reason it's used over other things is that it doesn't appear in the command card and it'll hit two birds in one stone (managing the slow and giving the units a buff) Naturally it'll need a custom buff so that you get the right description and icon for the ability
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
Normally what you do with slow aura is you make a modification of Slow aura (tornado) and change the target to self - so it only affects the unit with the ability you can then with script add/remove the ability (and set the level to get different levels of slow) on affected units, the reason it's used over other things is that it doesn't appear in the command card and it'll hit two birds in one stone (managing the slow and giving the units a buff) Naturally it'll need a custom buff so that you get the right description and icon for the ability

Ahh okay :) thank you, I'm on it! Will be updating soon.
 
Hello KILLCIDE, here are some notes.

  • Why is "InfectedGroup" potentialy re-created onCast?
    It should exist and just never be destroyed.
  • The "CheckGroup" does not need to be array.
  • Level of ability should be indexed as well.
  • OwnerofCaster should be indexed as well.
  • The conditions to check for infection limit and the actual integer comparions to check infected units
    can be combined. And then there needs to be only 1 block to execute infection of a unit.
  • You could use a intger[array] variable to keep track of infected units for an instance.
    This would replace the "CountUnitsInGroup" function each time.
  • Change the periodic timeout to something smaller, 0.1 for example.
  • Why does the death trigger fire onDamage, but not onDeath?
  • onDeindex the group[lastIndex] should be nulled.
  • Make attack- and damage type configurable.
  • If a infected unit has died it should directly index or at next loop run.
  • The configuration part looks good and is described well.

Looks good, but still some changes required first.
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
The conditions to check for infection limit and the actual integer comparions to check infected units
can be combined. And then there needs to be only 1 block to execute infection of a unit.

Can you elaborate? I'm lost on how its possible to merge them into 1 block.

On a side note, I will be working on the fixes. Thank you.

Change the periodic timeout to something smaller, 0.1 for example.

Changing the periodic timer would make it an initial AoE spell if everyone is grouped up, which I don't want. I want the infect speed to be somewhat slow and not instant.

Why does the death trigger fire onDamage, but not onDeath?

If I do onDeath, the loop would have de-indexed everything by then. I still want the index of the caster who killed it to be the owner of the zombies + credited for the kills.

Yeah leaving a comment to say that I think the approach is completely wrong.

1. index all targets infected
2. loop through them in the loop trigger
3. pick all nearby allies and infect + index them

that's it really, easier, shorter, more effective.

I will be talking to you on skype !
 

Bribe

Code Moderator
Level 44
Joined
Sep 26, 2009
Messages
8,963
I'm not sure why you are using a DDS for SP_Death. Is it to make sure the unit explodes? If so, ExplodeUnitBJ (Unit - Explode Unit) is the wrong way to do it as the killing unit will not get the credit for the kill. You'd want to use "Unit - Make unit explode on death". If you were using DamageEngine, you'd just set DamageEventType to DamageTypeExplosive when you run that trigger.
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
I'm not sure why you are using a DDS for SP_Death. Is it to make sure the unit explodes?

It is to make sure that the unit is infected, which is why I calculate the damage before it actually kills the unit.

If so, ExplodeUnitBJ (Unit - Explode Unit) is the wrong way to do it as the killing unit will not get the credit for the kill. You'd want to use "Unit - Make unit explode on death"
I did not think about that problem you pointed out :) updated

If you were using DamageEngine, you'd just set DamageEventType to DamageTypeExplosive when you run that trigger

Oh are you talking about your Damage Engine? I feel more comfortable using Weeps since I've been using it the past summer xP
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
Years ago I included backwards compatibility with Weep's DDS so transitioning is pretty easy. But if you get to the point where you need to modify damage or detect if it was a spell, that's when you'd want to start making the switch.

Yes I saw :) I have been taking the time to read it because one of my next few spells I have in line require the detection of spell damage, but for now, I stick with the GUI friendly Weep. Thank you for your fast replies by the way! Anymore suggestions or fixes to the code you think I can add?
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
I think the units should be damaged by the caster each interval so it's not such a massive damage burst at the end. Units get damaged all at once so it's hard to see what happened (it just looks like they all blow up instantly with no apparent cause).

The spell was originally made as a request x) the user wanted the damage at the end. However, I do like the idea of it dealing DoT. That will be sometime in the future though, going to put a pause on my 2nd spell and practice on my 2D stuff! Thank you again, Bribe!
 
Don't make any other actions in loop then deindex/damage when time has come,
just like the example in the other spell I gave you.

The damage for user config is per 0.5 seconds. This is not intuitive.
Or note it in comments, or adapt the value to damage per second.

In GUI it is totaly okay to use the IsUnitAlive/Dead-BJ as condition.
But you can keep yours too if you want.
You currently do anyways take usage of both.. ^^

Changes were good.
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
Don't make any other actions in loop then deindex/damage when time has come,
just like the example in the other spell I gave you.
Will work on it! Thank you.

The damage for user config is per 0.5 seconds. This is not intuitive.
Or note it in comments, or adapt the value to damage per second.
The damage isn't per second, it only deals damage at the end of the instance. I have the loop set to 0.5 seconds because I don't want the infection to move so fast xD

EDIT: Ignore the last sentence. I just added a new config option that lets you set an infect buffer time. Requires Bribe's Unit Indexer now :)

In GUI it is totaly okay to use the IsUnitAlive/Dead-BJ as condition.
But you can keep yours too if you want.
You currently do anyways take usage of both.. ^^
I was just playing around with the whole 0.405 option xD I will revert back to the IsUnitAlive/Dead-BJ.
 
Last edited:

Bribe

Code Moderator
Level 44
Joined
Sep 26, 2009
Messages
8,963
Meh, checking life isn't a guaranteed way to assess if one is alive. Using JASS, you can use UNIT_TYPE_DEAD (no idea why this isn't included in GUI) or using a postprocessor like JassHelper you can declare the UnitAlive method which is superior.

In GUI, you could also import GUI Unit Event to have access to the unitalive array.
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
Updated! Hoping for another review xD

Meh, checking life isn't a guaranteed way to assess if one is alive. Using JASS, you can use UNIT_TYPE_DEAD (no idea why this isn't included in GUI) or using a postprocessor like JassHelper you can declare the UnitAlive method which is superior.

In GUI, you could also import GUI Unit Event to have access to the unitalive array.

It was just something I was playing around with x) I figured it would be faster to do a real comparison vs checking if a unit is alive or dead.
 
There is still the problem with deindex. If duration has expired there are still done actions.
Why I inist so much you to fix this is to get you in the right thinking.
It is just unlogical when an instance is actually over but still does operations.
It might cause unwanted results that may be just unnoticed, but maybe in other systems it may cause different bugs then.
Code:
Set Time[index] = Time[index] + TimeOut

If (Time[index] >= MAxTime or Any_Other_Deindex_Contion)
----
---- Then
---- ---- Deindex
----
---- Else
---- ---- Do some operations with instance[index]
Endif

Or vice versa of couse, but it should mimic this behaviour. If time has expired or anything else is wrong then directly deindex.

Also, the damage is still neither per second nor a comment explains it.
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
There is still the problem with deindex. If duration has expired there are still done actions.
Why I inist so much you to fix this is to get you in the right thinking.
It is just unlogical when an instance is actually over but still does operations.
It might cause unwanted results that may be just unnoticed, but maybe in other systems it may cause different bugs then.
Code:
Set Time[index] = Time[index] + TimeOut

If (Time[index] >= MAxTime or Any_Other_Deindex_Contion)
----
---- Then
---- ---- Deindex
----
---- Else
---- ---- Do some operations with instance[index]
Endif

Or vice versa of couse, but it should mimic this behaviour. If time has expired or anything else is wrong then directly deindex.
Updated loop to now deindex when it has to and not at next loop iteration :)


Also, the damage is still neither per second nor a comment explains it.
I figured people would have seen the spell description/GIF preview before looking at the triggers xD comments have been added.
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
Updated to v4.00. This should honestly be the final version not including any fixes moderators need me to do + maybe updating to Bribe's new spell system. I've spent the past few weeks learning linked listing, so I thought I'd give it a shot and update all my spells with it. Currently only doing it for this one before everything else.


v4.00 changes:
  • Added a Hero filter; Heroes can no longer be infected (thanks to Bribe for pointing this out)
  • Changed data structure to linked listing from dynamic indexing
  • Fixed an issue with infected units not spawning a zombie when they die during the duration; it was currently only spawning zombies if they died from the final damage
 
Level 37
Joined
Jul 22, 2015
Messages
3,489
v4.01 changes:
  • Added an optional Spreading Plague folder that is integrated with GUI Spell System
  • Fixed issue of the caster still losing mana + spell going on cooldown when attempting to infect an infected unit
  • Removed unnecesary NodeLast[] variable for linked list; last spell instance now stores into NodePrev[0]
  • Removed If/Then/Else that would set NodeLast = NodePrev[Spell_ID] if NodeLast == Spell_ID

I added a seperate readme file for the Spreading Plague that is integerated with GUI Spell System. Big thanks to Bribe for being extremely patient on explaining me how to use his system.
 

Ardenian

A

Ardenian

What do you think about adding a configuration that allows to set a chance that the next unit is infected ? As far as I can tell, the next unit gets infected with a 100% chance, it would be good to have a configuration variable there, too.
 

Ardenian

A

Ardenian

That's a great idea! Thank you for the suggestion. I will work on implementing it tomorrow :)

Hehe, that's great to hear :)
I thought about creating a virus system, but then I thought 'Hey, KILLCIDE already has that Spreading Plague, that's the same'
 
Top