Can't access variable in Lua menu

Shout-Out

User Tag List

Results 1 to 7 of 7
  1. #1
    Nadromar's Avatar Contributor
    CoreCoins Purchaser
    Reputation
    369
    Join Date
    Oct 2006
    Posts
    510
    Thanks G/R
    15/28
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Can't access variable in Lua

    So i'm trying to write a boss script which does stuff every 5 seconds with this code:

    Code:
    local boss
    
    local function handleBossFight(eventId, delay, repeats)
        if (not boss:IsInCombat() or not boss:IsAlive()) then
            return
        end
        ...
    end
    
    
    local function onEnterCombat(event, creature, target)
        boss = creature
        CreateLuaEvent(handleBossFight, 5000, repeats)
    end
    
    
    RegisterCreatureEvent(BOSSID, 1, onEnterCombat)
    I'm getting the following error:
    Calling 'IsInCombat' on bad self (Creature expected, got pointer to nonexisting invalidated object userdata)

    Tried several other ways to access it but I just can't figure it out. :/
    Last edited by Nadromar; 04-14-2015 at 01:43 AM.

    Can't access variable in Lua
  2. #2
    Sklug's Avatar ★ Elder ★
    Reputation
    1084
    Join Date
    Mar 2008
    Posts
    1,210
    Thanks G/R
    210/224
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Nightfoxx View Post
    So i'm trying to write a boss script which does stuff every 5 seconds with this code:

    Code:
    local boss
    
    local function handleBossFight(eventId, delay, repeats)
        if (not boss:IsInCombat() or not boss:IsAlive()) then
            return
        end
        ...
    end
    
    
    local function onEnterCombat(event, creature, target)
        boss = creature
        CreateLuaEvent(handleBossFight, 5000, repeats)
    end
    
    
    RegisterCreatureEvent(BOSSID, 1, onEnterCombat)
    I'm getting the following error:
    Calling 'IsInCombat' on bad self (Creature expected, got pointer to nonexisting invalidated object userdata)

    Tried several other ways to access it but I just can't figure it out. :/
    I will be honest, I am not too familiar with LUA, but if you are getting that kind of error, it's typically because you are trying to call a function on an Object that has not been initialized, or does not exist. For example, let's say you call for a boolean return like the "IsInCombat" on the boss is going to produce an error if there is no boss, or you have no "target." This command is something you'd use on an existing object, so it will error if there isn't one. I think you are on the right track, but what I would probably recommend is maybe some work around, like identifying the boss first and maybe, setting the boss as a "Focus" target if it is found. This way you won't encounter errors if say, you lose the target for whatever reason, it is still your focus static target. This will help prevent lots of those types of errors. Rather than checking for the specific boss, instead you set boss as a focus target if he has been found, then instead of saying "not boss:IsInCombat()" like you did, you can first wrap it all in some like (and forgive my lack of LUA knowledge), but something like

    if Me.Focus != null && Me.Focus.IsAlive() then

    Again, just pseudo code but I am sure you get the idea...

    Hopefully this helps and hopefully someone can correct me if I am off.

  3. #3
    stoneharry's Avatar Moderator Harry


    Reputation
    1618
    Join Date
    Sep 2007
    Posts
    4,564
    Thanks G/R
    151/150
    Trade Feedback
    0 (0%)
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    I'm assuming you are using Eluna, but either way your original post is going about this in the wrong way.

    Code:
    local function handleBossFight(eventID, delay, repeats, pUnit)
        if (not pUnit:IsInCombat() or not pUnit:IsAlive()) then
            pUnit:RemoveEvents()
            return
        end
        -- My boss is going to do something now
    end
    
    local function onEnterCombat(event, pUnit, target)
        -- called every 5 seconds until unit:RemoveEvents() is called
        pUnit:RegisterEvent(handleBossFight, 5000, 0)
    end
    
    RegisterCreatureEvent(BOSSID, 1, onEnterCombat)
    It would be better to hook on death and leaving of combat than waiting for your function to detect the boss is no longer in combat.

    As an example on how to code where something will be instanced, you can see my code for this video below: https://www.youtube.com/watch?v=7W1pZwhCGLw

    Code:
    -- Constants
    local guardA_ID = 120001
    local guardB_ID = 120002
    local invisDummyID = 120003
    
    -- Instance tables
    CM = {}
    CM.VAR = {}
    
    -- Gossip start event
    function CM.VAR.OnGossipHello(event, player, creature)
    	player:GossipClearMenu()
    	player:GossipMenuAddItem(9, "< Placeholder Menu >", 120000, 1)
    	player:GossipMenuAddItem(0, "Nevermind.", 120000, 2)
    	player:GossipSendMenu(120000, creature)
    end
    
    function CM.VAR.OnGossipSelect(event, player, pUnit, sender, intid, code)
    	player:GossipComplete()
    	if intid == 1 then
    		pUnit:SetNPCFlags(0)
    		CM.VAR.beginEvent(pUnit)
    	end
    end
    
    RegisterCreatureGossipEvent(120000, 1, CM.VAR.OnGossipHello)
    RegisterCreatureGossipEvent(120000, 2, CM.VAR.OnGossipSelect)
    
    -- Utility
    function getNearbyCreature(id, pUnit)
    	if id == pUnit:GetEntry() then
    		return pUnit
    	end
    	local creatures = pUnit:GetCreaturesInRange(20, id)
    	if #creatures == 0 then
    		pUnit:SendUnitSay("ERROR: creatures == 0", 0)
    		return
    	end
    	if #creatures == 1 then
    		return creatures[1]
    	end
    	return creatures[math.random(1, #creatures)]
    end
    
    -- Start event
    function CM.VAR.beginEvent(pUnit)
    	local id = pUnit:GetInstanceId() or 1
    	CM[id] = CM[id] or {VAR={}}
    	local guardA = getNearbyCreature(guardA_ID, pUnit)
    	local guardB = getNearbyCreature(guardB_ID, pUnit)
    	pUnit:SendUnitSay("The crypts are filled with the undying, we must proceed carefully.", 0)
    	guardB:SetWalk(true)
    	guardB:MoveTo(0, 203, 104, 128.4)
    	guardA:SetWalk(true)
    	guardA:MoveTo(0, 197.3, 104.57, 128.42)
    	pUnit:SetWalk(true)
    	pUnit:MoveTo(0, 200, 107, 128.42)
    	CM[id].VAR.i = 0
    	pUnit:RegisterEvent(CM.VAR.eventTicker, 1000, 0)
    end
    
    -- Event ticker
    function CM.VAR.eventTicker(eventID, delay, repeats, pUnit)
    	local id = pUnit:GetInstanceId() or 1
    	CM[id] = CM[id] or {VAR={}}
    	CM[id].VAR.i = CM[id].VAR.i + 1
    	local i = CM[id].VAR.i
    	if i == 5 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		guardA:SendUnitSay("We've dealt with these kind before. This should be no problem.", 0)
    	elseif i == 9 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		guardA:CastSpell(guardA, 36858)
    		guardB:CastSpell(guardB, 36858)
    		local creature = guardA:SpawnCreature(120003, guardA:GetX(), guardA:GetY(), guardA:GetZ(), 0, 8, 10000)
    		creature:SetUInt32Value(0x0006 + 0x0035, 33554432)
    		creature:RegisterEvent(CM.VAR.MoveDummies, 1000, 8)
    		creature = guardB:SpawnCreature(120003, guardB:GetX(), guardB:GetY(), guardB:GetZ(), 0, 8, 10000)
    		creature:SetUInt32Value(0x0006 + 0x0035, 33554432)
    		creature:RegisterEvent(CM.VAR.MoveDummies, 1000, 8)
    	elseif i == 16 then
    		for _,v in pairs(pUnit:GetCreaturesInRange(70, 120003)) do
    			v:RemoveEvents()
    			v:DespawnOrUnsummon(0)
    		end
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		guardB:MoveTo(0, 203, 48, 128)
    		guardA:MoveTo(0, 198, 47, 128)
    		pUnit:MoveTo(0, 201, 51, 128)
    	elseif i == 20 then
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		guardB:SendUnitSay("How have their come to be so many down here?", 0)
    	elseif i == 25 then
    		pUnit:SendUnitSay("There must be a necromancer. It's the only possible scenario I can think of.", 0)
    	elseif i == 32 then
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		guardB:SendUnitSay("I don't like the sound of that.", 0)
    	elseif i == 41 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		pUnit:MoveTo(0, 193, 49, 128)
    		guardA:MoveTo(0, 193, 53, 128)
    		guardB:MoveTo(0, 193, 46, 128)
    	elseif i == 44 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		pUnit:MoveTo(0, 172, 49, 115)
    		guardB:MoveTo(0, 172, 45, 115)
    		guardA:MoveTo(0, 172, 52, 115)
    	elseif i == 56 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		pUnit:MoveTo(0, 166, 42, 115)
    		guardB:MoveTo(0, 170, 42, 115)
    		guardA:MoveTo(0, 163, 42, 115)
    	elseif i == 58 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		pUnit:MoveTo(0, 183, 22, 115)
    		guardB:MoveTo(0, 186, 25, 115)
    		guardA:MoveTo(0, 180, 17, 115)
    	elseif i == 73 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		pUnit:SetFacing(5.518449)
    		guardA:SetFacing(5.333883)
    		guardB:SetFacing(5.761922)
    	elseif i == 74 then
    		pUnit:SendUnitYell("Necromancer, prepare to face the light for your judgement has come!", 0)
    		pUnit:Emote(5)
    	elseif i == 76 then
    		local necro = pUnit:GetCreaturesInRange(40, 120006)[1]
    		necro:RemoveEvents()
    		necro:StopSpellCast(40193)
    		necro:CastSpell(necro, 67040, true)
    		for _,v in pairs(pUnit:GetCreaturesInRange(40, 120005)) do
    			v:CastSpell(v, 40927, true)
    			v:Emote(431)
    		end
    	elseif i == 78 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		pUnit:CastSpell(pUnit, 465, true)
    		pUnit:Emote(45)
    		guardA:Emote(45)
    		guardB:Emote(45)
    	elseif i == 81 then
    		local necro = pUnit:GetCreaturesInRange(40, 120006)[1]
    		necro:StopSpellCast(67040)
    		for _,v in pairs(pUnit:GetCreaturesInRange(40, 120005)) do
    			v:CastSpell(v, 47496, false)
    		end
    		pUnit:CastSpell(pUnit, 45922, true)
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		necro:SendUnitYell("You shall all perish!", 0)
    		necro:SetUInt32Value(0x0006 + 0x0035, 0)
    	elseif i == 87 then
    		local guardA = getNearbyCreature(guardA_ID, pUnit)
    		guardA:CastSpell(guardA, 45922, true)
    		local guardB = getNearbyCreature(guardB_ID, pUnit)
    		guardB:CastSpell(guardB, 45922, true)
    	elseif i == 100 then
    		pUnit:RemoveEvents()
    	end
    end
    
    -- Dummy projectile killing scourge at start
    function CM.VAR.MoveDummies(eventID, delay, repeats, pUnit)
    	pUnit:CastSpell(pUnit, 44880, true)
    	pUnit:CastSpell(pUnit, 43241, true)
    	pUnit:MoveTo(0, pUnit:GetX(), pUnit:GetY() - 10, pUnit:GetZ())
    	for _,v in pairs(pUnit:GetCreaturesInRange(8, 120004)) do
    		v:CastSpell(v, 16003, true)
    		pUnit:Kill(v)
    	end
    end
    
    -- Make trash walk around randomly
    function CM.VAR.FlashyTrashMoveAround(event, pUnit, ...)
    	if event == 5 then -- spawned
    		pUnit:SetUInt32Value(0x0006 + 0x0035, 2 + 131072)
    		pUnit:SetFaction(14)
    		pUnit:RegisterEvent(CM.VAR.MoveRandom_Call, math.random(100, 3000), 1)
    	else
    		pUnit:RemoveEvents()
    	end
    end
    
    function CM.VAR.MoveRandom_Call(eventID, delay, repeats, pUnit)
    	pUnit:MoveRandom(2)
    	pUnit:RegisterEvent(CM.VAR.MoveRandom_Call, math.random(100, 3000), 1)
    end
    
    RegisterCreatureEvent(120004, 5, CM.VAR.FlashyTrashMoveAround)
    RegisterCreatureEvent(120004, 4, CM.VAR.FlashyTrashMoveAround)
    
    
    -- Prisoners
    
    function CM.VAR.PrisonerSpawn(event, pUnit)
    	pUnit:SetUInt32Value(0x0006 + 0x0035, 2 + 131072)
    	if pUnit:GetEntry() == 120006 then
    		pUnit:RegisterEvent(CM.VAR.StranglePeople, 3100, 0)
    	else
    		local maxHealth = pUnit:GetMaxHealth() / 2
    		local amount = math.random(1, 10)
    		if (math.random(1,2) == 1) then
    			maxHealth = maxHealth + amount
    		else
    			maxHealth = maxHealth - amount
    		end
    		pUnit:SetHealth(maxHealth)
    	end
    end
    
    function CM.VAR.StranglePeople(eventID, delay, repeats, pUnit)
    	pUnit:StopSpellCast(40193)
    	local creature = getNearbyCreature(120005, pUnit)
    	if not creature then
    		pUnit:SendUnitSay("ERROR: No unit found.", 0)
    		return
    	end
    	creature:CastSpell(creature, 28136, true)
    	pUnit:CastSpell(creature, 40193, true)
    	creature:Emote(473)
    	creature:RegisterEvent(CM.VAR.StopEmote, 3000, 1)
    end
    
    function CM.VAR.StopEmote(id, delay, repeats, pUnit)
    	pUnit:Emote(20)
    end
    
    RegisterCreatureEvent(120005, 5, CM.VAR.PrisonerSpawn)
    RegisterCreatureEvent(120006, 5, CM.VAR.PrisonerSpawn)
    RegisterCreatureEvent(120006, 4, CM.VAR.FlashyTrashMoveAround)
    It is bad practice in general to store any sort of direct reference to the object in a variable outside of the scope of the function in question. If you must determine if it is the same npc as later and it is not a unique npc ID then store the GUID and find the creature that matches the stored GUID.

    You can store a player's GUID and get the object back by using:
    Code:
    local player = GetPlayerByGUID(playerGUID)
    Which can obviously return nil.
    Last edited by stoneharry; 04-14-2015 at 09:56 AM.

  4. #4
    Nadromar's Avatar Contributor
    CoreCoins Purchaser
    Reputation
    369
    Join Date
    Oct 2006
    Posts
    510
    Thanks G/R
    15/28
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah, the script was a trainwreck :P This solved it:

    Code:
    hpPercent = 100
    function onEnterCombat(event, creature, target)
        creature:SendUnitYell(MESSAGE_ON_START,0)
        creature:RegisterEvent(Update, 1000, 0)
        creature:RegisterEvent(Stage1, 5000, 0)
        creature:RegisterEvent(Stage2, 5000, 0)
        creature:RegisterEvent(Stage3, 5000, 0)
        creature:RegisterEvent(Stage4, 10000, 0)
    end
    function Update(event, delay, pCall, creature)
        hpPercent = creature:GetHealthPct()
    end
    function Stage1(event, delay, pCall, creature)
        if (hpPercent < 75 and not midStunActive) then
                 ...
            end
    end
    
    ...
    local function reset(creature)
        -- reset
        creature:RemoveEvents()
        hpPercent = 100
    end
    function onLeaveCombat(event, creature)
        reset(creature)
    end
    function onDied(event, creature, killer)
        reset(creature)
    end
    
    
    RegisterCreatureEvent(BOSSID, 1, onEnterCombat) -- on enter combat
    RegisterCreatureEvent(BOSSID, 2, onLeaveCombat) -- reset
    RegisterCreatureEvent(BOSSID, 4, onDied) -- reset
    Last edited by Nadromar; 04-14-2015 at 12:26 PM.

  5. #5
    stoneharry's Avatar Moderator Harry


    Reputation
    1618
    Join Date
    Sep 2007
    Posts
    4,564
    Thanks G/R
    151/150
    Trade Feedback
    0 (0%)
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Nightfoxx View Post
    Yeah, the script was a trainwreck :P This solved it:

    Code:
    hpPercent = 100
    function onEnterCombat(event, creature, target)
        creature:SendUnitYell(MESSAGE_ON_START,0)
        creature:RegisterEvent(Update, 1000, 0)
        creature:RegisterEvent(Stage1, 5000, 0)
        creature:RegisterEvent(Stage2, 5000, 0)
        creature:RegisterEvent(Stage3, 5000, 0)
        creature:RegisterEvent(Stage4, 10000, 0)
    end
    function Update(event, delay, pCall, creature)
        hpPercent = creature:GetHealthPct()
    end
    function Stage1(event, delay, pCall, creature)
        if (hpPercent < 75 and not midStunActive) then
                 ...
            end
    end
    
    ...
    local function reset(creature)
        -- reset
        creature:RemoveEvents()
        hpPercent = 100
    end
    function onLeaveCombat(event, creature)
        reset(creature)
    end
    function onDied(event, creature, killer)
        reset(creature)
    end
    
    
    RegisterCreatureEvent(BOSSID, 1, onEnterCombat) -- on enter combat
    RegisterCreatureEvent(BOSSID, 2, onLeaveCombat) -- reset
    RegisterCreatureEvent(BOSSID, 4, onDied) -- reset
    Try to avoid global variables at all times. Here's a clean up:

    Code:
    local MESSAGE_ON_START = "Hello world."
    
    local function onEnterCombat(event, creature, target)
        creature:SendUnitYell(MESSAGE_ON_START, 0)
        creature:RegisterEvent(Update, 1000, 0)
        creature:RegisterEvent(Stage1, 5000, 0)
        --[[creature:RegisterEvent(Stage2, 5000, 0)
        creature:RegisterEvent(Stage3, 5000, 0)
        creature:RegisterEvent(Stage4, 10000, 0)]]
    end
    
    function Stage1(event, delay, pCall, creature)
        if (creature:GetHealthPct() < 75 and not midStunActive) then
            ...
        end
    end
    
    local function resetCreature(event, creature, ...)
    	-- ... = optional further arguments
    	-- If you need to do event specific stuff, if event == 2, etc
        creature:RemoveEvents()
    end
    
    
    RegisterCreatureEvent(BOSSID, 1, onEnterCombat) -- on enter combat
    RegisterCreatureEvent(BOSSID, 2, resetCreature) -- reset
    RegisterCreatureEvent(BOSSID, 4, resetCreature) -- reset

  6. #6
    Nadromar's Avatar Contributor
    CoreCoins Purchaser
    Reputation
    369
    Join Date
    Oct 2006
    Posts
    510
    Thanks G/R
    15/28
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmh, would a global variable not be better since GetHealthPct() gets called in every stage? In stage 4 it would call it 4 times every 5sec.
    I do use global variables too much though.
    Last edited by Nadromar; 04-14-2015 at 10:03 PM.

  7. #7
    stoneharry's Avatar Moderator Harry


    Reputation
    1618
    Join Date
    Sep 2007
    Posts
    4,564
    Thanks G/R
    151/150
    Trade Feedback
    0 (0%)
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Nightfoxx View Post
    Hmh, would a global variable not be better since GetHealthPct() gets called in every stage? In stage 4 it would call it 4 times every 5sec.
    I do use global variables too much though.
    Nah, Lua calls native C functions. That is incredibly fast. It is much better to get it each function call than attempt to store that value as a variable - memory is much more expensive. And it's just not good programming to store stuff in global variables where it can be avoided - whether that is global within your class or wherever.

Similar Threads

  1. [HELP] Were can i find the latest LUA files??
    By emil94 in forum World of Warcraft Emulator Servers
    Replies: 3
    Last Post: 07-07-2008, 05:42 AM
  2. [Help] Can't access certain server webpages
    By Killerguy in forum World of Warcraft Emulator Servers
    Replies: 3
    Last Post: 05-30-2008, 10:35 PM
  3. I got scammed, on buying an account, but can still access it. What now?
    By irathernottell in forum World of Warcraft General
    Replies: 2
    Last Post: 05-21-2008, 03:44 PM
All times are GMT -5. The time now is 12:03 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search