I decided to make some simple comparison scripts to show the old way of scripting vs the new way of scripting. I will make multiple scenarios where the new way of scripting helps out, and will describe the problem and solution in each one.
1. Monstrosity - Privatising Variables
OLD WAY
local killcount = 0 local entry = 555 function Monstrosity_OnKill(pUnit, event) killcount = killcount + 1 if (killcount > 2) then pUnit:SendChatMessage(14, 0, "RAWR! I have killed many people!") end end RegisterUnitEvent(entry, 3, "Monstrosity_OnKill")Problems:
- The killcount variable is shared among all units who use this script, therefore the script will malfunction if you have more than one of mob '555' spawned.
- The functions are all globals which is unorganised and lowers performance.
- local entry is fine because it is never changed. It is constant.
MONSTROSITY = {}
local entry = 555
function MONSTROSITY.OnKill(pUnit, event)
local sUnit = tostring(pUnit)
if (MONSTROSITY[sUnit] == nil) then --this is initialising sub-tables
MONSTROSITY[sUnit] = {}
MONSTROSITY[sUnit].killsCount = 0
end
MONSTROSITY[sUnit].killsCount = MONSTROSITY[sUnit].killsCount + 1
if (MONSTROSITY[sUnit].killsCount > 2) then
pUnit:SendChatMessage(14, 0, "RAWR! I have killed many people!")
end
end
RegisterUnitEvent(entry, 3, "MONSTROSITY.OnKill")
Solutions:- We created a global table "MONSTROSITY" to hold all of our functions, which is more organised and makes the functions within the MONSTROSITY table instead of floating around as globals
- We ensure that the MONSTROSITY table isn't full of nils by initialising the sub-tables. Since we only need to initialise once, we check that the sub-table is nil first.
- We have privatised the killsCount variable, so instead of being shared by all mobs with entry '555', it is not shared, and is kept private to each pUnit.
2. Mages - 2 interactive units
OLD WAY
local mage1
local mage2
function Mage1_OnSpawn(pUnit, event)
mage1 = pUnit
end
function Mage2_OnSpawn(pUnit, event)
mage2 = pUnit
end
function Mage1_OnCombat(pUnit, event)
pUnit:RegisterEvent("Mage1_Check_Mage2_HP", 1000, 0)
end
function Mage1_Check_Mage2_HP(pUnit, event)
if (mage2:GetHealthPct() < 20) then
pUnit:SendChatMessage(14, 0, "No! My brother is in danger!")
end
end
RegisterUnitEvent(750, 18, "Mage1_OnSpawn")
RegisterUnitEvent(750, 1, "Mage1_OnCombat")
RegisterUnitEvent(751, 18, "Mage2_OnSpawn")
Problems:- The mage1 and mage2 variables are being shared around with all units with entry id '750' or '751', so having more than 1 group of these mages will not work.
- The functions are all globals which is unorganised and lowers performance.
MAGES = {}
function MAGES.Mage1_OnSpawn(pUnit, event)
local sUnit = tostring(pUnit)
if (MAGES[sUnit] == nil) then
MAGES[sUnit] = {}
end
local mage2 = pUnit:GetCreatureNearestCoords(pUnit:GetX(), pUnit:GetY(), pUnit:GetZ(), 751)
MAGES[sUnit].partner = mage2
end
function MAGES.Mage2_OnSpawn(pUnit, event)
local sUnit = tostring(pUnit)
if (MAGES[sUnit] == nil) then
MAGES[sUnit] = {}
end
local mage1 = pUnit:GetCreatureNearestCoords(pUnit:GetX(), pUnit:GetY(), pUnit:GetZ(), 750)
MAGES[sUnit].partner = mage1
end
function MAGES.Mage1_OnCombat(pUnit, event)
pUnit:RegisterEvent("MAGES.Mage1_Check_Mage2_HP", 1000, 0)
end
function MAGES.Mage1_Check_Mage2_HP(pUnit, event)
local sUnit = tostring(pUnit)
if (MAGES[sUnit].partner:GetHealthPct() < 20) then
pUnit:SendChatMessage(14, 0, "No! My brother is in danger!")
end
end
RegisterUnitEvent(750, 18, "MAGES.Mage1_OnSpawn")
RegisterUnitEvent(750, 1, "MAGES.Mage1_OnCombat")
RegisterUnitEvent(751, 18, "MAGES.Mage2_OnSpawn")
Solutions:- We created a global table "MAGES" to hold all of our functions, which is more organised and makes the functions within the MAGES table instead of floating around as globals
- OnSpawn we make sure that our table isn't nil by initialising sub-tables.
- Each mage finds their partner using the GetCreatureNearestCoords function, and stores it in a private table so they can access it later, eliminating the global variables!
3. Instance - Waves of Adds
OLD WAY
local wave = 0
local mob1, mob2, mob3
function MadScientist_SpawnWave(pUnit, event)
if (wave == 1) then
pUnit:SendChatMessage(14, 0, "Go, my front line minions!")
pUnit:SpawnCreature(320, pUnit:GetX(), pUnit:GetY(), pUnit:GetZ(), 0, 14, 0)
pUnit:SpawnCreature(321, pUnit:GetX(), pUnit:GetY(), pUnit:GetZ(), 0, 14, 0)
elseif (wave == 2) then
pUnit:SendChatMessage(14, 0, "Go, my lieutenant!")
pUnit:SpawnCreature(322, pUnit:GetX(), pUnit:GetY(), pUnit:GetZ(), 0, 14, 0)
end
pUnit:RegisterEvent("MadScientist_CheckDead", 1000, 0)
end
function MadScientist_CheckDead(pUnit, event)
if (wave == 1)
if (mob1:IsDead() == true and mob2:IsDead() == true) then
wave = wave+1
pUnit:RegisterEvent("MadScientist_SpawnWave", 5000, 1)
end
elseif (wave == 2)
if (mob3:IsDead() == true) then
wave = wave+1
pUnit:SendChatMessage(14, 0, "How could you defeat my waves of monsters!?")
end
end
end
function Minion1_OnSpawn(pUnit, event)
mob1 = pUnit
end
function Minion2_OnSpawn(pUnit, event)
mob2 = pUnit
end
function Minion1_OnSpawn(pUnit, event)
mob3 = pUnit
end
RegisterUnitEvent(319, 1, "MadScientist_SpawnWave")
RegisterUnitEvent(320, 18, "Minion1_OnSpawn")
RegisterUnitEvent(321, 18, "Minion2_OnSpawn")
RegisterUnitEvent(322, 18, "Minion3_OnSpawn")
Problems:- Since the variables (mob1, mob2, mob3, wave) are all shared, when two different groups enter the instance, the script will malfunction.
- The functions are all globals which is unorganised and lowers performance.
INSTANCE_ASYLUM = {}
function INSTANCE_ASYLUM.MadScientist_SpawnWave(pUnit, event)
local iid = pUnit:GetInstanceID()
if (INSTANCE_ASYLUM[iid] == nil) then
INSTANCE_ASYLUM[iid] = {}
INSTANCE_ASYLUM[iid].wave = 1
end
if (INSTANCE_ASYLUM[iid].wave == 1) then
pUnit:SendChatMessage(14, 0, "Go, my front line minions!")
INSTANCE_ASYLUM[iid].mob1 = pUnit:SpawnCreature(320, pUnit:GetX(), pUnit:GetY(), pUnit:GetZ(), 0, 14, 0)
INSTANCE_ASYLUM[iid].mob2 = pUnit:SpawnCreature(321, pUnit:GetX(), pUnit:GetY(), pUnit:GetZ(), 0, 14, 0)
elseif (INSTANCE_ASYLUM[iid].wave == 2) then
pUnit:SendChatMessage(14, 0, "Go, my lieutenant!")
INSTANCE_ASYLUM[iid].mob3 = pUnit:SpawnCreature(322, pUnit:GetX(), pUnit:GetY(), pUnit:GetZ(), 0, 14, 0)
end
pUnit:RegisterEvent("INSTANCE_ASYLUM.MadScientist_CheckDead", 1000, 0)
end
function INSTANCE_ASYLUM.MadScientist_CheckDead(pUnit, event)
local iid = pUnit:GetInstanceID()
if (INSTANCE_ASYLUM[iid].wave == 1)
if (INSTANCE_ASYLUM[iid].mob1:IsDead() == true and INSTANCE_ASYLUM[iid].mob2:IsDead() == true) then
INSTANCE_ASYLUM[iid].wave = INSTANCE_ASYLUM[iid].wave+1
pUnit:RegisterEvent("INSTANCE_ASYLUM.MadScientist_SpawnWave", 5000, 1)
end
elseif (INSTANCE_ASYLUM[iid].wave == 2)
if (INSTANCE_ASYLUM[iid].mob3:IsDead() == true) then
INSTANCE_ASYLUM[iid].wave = INSTANCE_ASYLUM[iid].wave+1
pUnit:SendChatMessage(14, 0, "How could you defeat my waves of monsters!?")
end
end
end
RegisterUnitEvent(319, 1, "INSTANCE_ASYLUM.MadScientist_SpawnWave")
Solutions:- We created a global table "INSTANCE_ASYLUM" to hold all of our functions, which is more organised and we added the functions to the table instead of making them floating around as globals
- Since we need units within a specific instance to share variables, we use their instance ID as the key. This is unique per-instance, so it's ideal for the sharing of wave, mob1/2/3.
- We eliminate the global variables by storing the spawns in the instance's table. SpawnCreature actually returns the spawned creature, which comes in handy here.
















