Thread Tools Display Modes
04-11-20, 12:34 AM   #1
TransformedBG
A Fallenroot Satyr
Join Date: Oct 2010
Posts: 23
Just trying to revive an old add... need a little help

Not sure what all has changed, but i was trying to revive my old level announcer addon, and i haven't really touched it since probably BC... anyways... For the most part most of my functions work... I just dont know why i cant access global variables any more.. havent kept up with that.


simple lua file
Code:
local me = UnitName("player") -- Gets players Name
local lvl = UnitLevel("player")+1 --Gets Current Player Level (used to have an addon that +1 to this but i cant add to this level gets a global nil)
local race = UnitClass("player") --local varable to record what race you are.
local realm = GetRealmName(); -- Gets Realm name

--[[List to define chat channels]]--
channel_list = {}
channel_list["chan"] = {
"SAY",
"GUILD",
"PARTY",
"RAID",
"BATTLEGROUND",
}

--[[List to define different randomized quotes]]--
quote_this = {}
quote_this["level"] = {
"This has been a test of the Emergancy Ding System! "..me.."is now " ..lvl..".",
"My ding a ling. My ding a ling... looks like im level "..lvl.."!!!",
"DING, DING, DING... Looks like "..me.."just hit "..lvl.."!",
"Check this guys! Im now a level "..lvl.." "..race.."!",
"If you heard it once, you have heard it "..lvl.." times. DING!",
"Go ahead and just say grats alread! Cause i just hit level "..lvl.."!",
"Warning, Warnning,"..me.." You Just Hit Level "..lvl.."!",
"My microwave Dings and so do I! "..lvl.. " levels done!",
"Whats the difference between a rogue and a noob, they both pick locks! DING! That makes "..lvl.."!",
"This aint no AutoDing, okay well maybe a little... DING! now im level "..lvl.."!",
"Mama says every time a player Dings an angel gets its wings. DING level"..lvl.."!",
"Oh what is that noise? Sounds like someone just Dinged! Could it be "..me.."?! Woo hoo im level "..lvl.."!",
}


function GLUA_OnLoad(self)-- Loads on player login --
	self:RegisterEvent("PLAYER_LEVEL_UP");
	self:RegisterEvent("GUILD_ROSTER_UPDATE");
	self:RegisterEvent("CHAT_MSG_GUILD");
	GLUA_LoadMessage();
	--lvl = Level_Up()
end

function GLUA_LoadMessage()
	DEFAULT_CHAT_FRAME:AddMessage("Guild Level Up Announcer has been initialized!")
	DEFAULT_CHAT_FRAME:AddMessage(" Ver. 1.13.14");
end

function GLUA_Message(quotes, channel)
	SendChatMessage(quotes, channel, nil, nil); --sends the chat message, party is just a filler for now testing
end

function GLUA_Channel()
	local num = 1 --you are Solo
		if UnitInParty("player")  then
			--print("party")
			num = 3 -- your in a party
		end
		if UnitInRaid("player") then
			--print("raid")
			num = 4 --Your in a raid group
		end
		if UnitInBattleground("player") then
			--print("Battleground")
			num = 5 --You are Battleground
		end
	return num
end

function GLUA_Quotes()
	local list = quote_this["level"]
	local quote = list[math.random(table.getn(list))]
	return quote
end

function GLUA_GUILD_CHECK(test)
	test = GetGuildInfo("player")
		if (test == nil)then
			test = false 
			return test
		end
   test = true
   return test
end

function GLUA_OnEvent(self, event, ...)
	if (event == "PLAYER_LEVEL_UP") then --if a player levels up do the following
		--print("Player Leveled Up = " .. event)
		local quote_to_share = GLUA_Quotes()
		local chanX = channel_list["chan"]
		local chan_number= GLUA_Channel()
			GLUA_Message(quote_to_share, chanX[chan_number]) -- send message to party or raid
		local check_guild = GLUA_GUILD_CHECK(check_guild)
		if (check_guild == true) then
			print("not in a guild")
			GLUA_Message(quote_to_share, chanX[2]) -- return a second message to guild
		end
	end
end
simple xml
Code:
<UI xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
	<Script file="GLUA.lua" />

	<Frame name="GLUAFrame" hidden="false">
		<Scripts>
			<OnLoad>GLUA_OnLoad(self)</OnLoad>
			<OnEvent>GLUA_OnEvent(self, event, ...)</OnEvent>
		</Scripts>
	</Frame>
</UI>
I had a bunch of this's all over, and figured out how to get rid of them.. but i feel like from looking around i need to do something like put my add on in a container or something. Im just trying to remember all this. like i said its been a while.

if i run the functions in wow doing /run GLUA_XXX most of them work. Only thing is OnEvent when its actually called by game (I simply call it /Run GLUA_OnEvent("player","PLAYER_LEVEL_UP); it doesnt error) where when its auto called im getting:
1x [ADDON_ACTION_BLOCKED] AddOn 'GLUA' tried to call the protected function 'UNKNOWN()'.
!BugGrabber\BugGrabber.lua:519: in function <!BugGrabber\BugGrabber.lua:519>
[C]: ?
[C]: in function `SendChatMessage'
GLUA\GLUA-1.0.1.1.lua:70: in function `GLUA_Message'
GLUA\GLUA-1.0.1.1.lua:115: in function `GLUA_OnEvent'
[string "*:OnEvent"]:1: in function <[string "*:OnEvent"]:1>
  Reply With Quote
04-11-20, 10:50 AM   #2
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,892
This is the new go to place for API help for WoW
https://wow.gamepedia.com/World_of_Warcraft_API

I would suggest looking at some small recent addons to see how things are coded now to give you a start and then slowly relearn some of the addon stuff thats still hidden somewhere in your programming memory

What I find useful is to create a template addon so to speak that has the pure basics and then build any specifics into it for any addon I want to write.

For example:
This is a simple addon template that nearly all of my addons have used as their starting point. Feel free to utilise yourself if you want.

Good Luck

Lua Code:
  1. --[[ Localise the Addon Wide Data Table ]]--
  2. local addonName, addonData = ...
  3.  
  4. --[[ Localise any Addon Wide Sub Tables that are frequently accessed ]]--
  5. local Translate = addonData.Translate
  6.  
  7. --[[ Addon Specific Functionality ]]--
  8. ...
  9.  
  10.  
  11. --[[ Monitor registered events ]]--
  12. local function EventWatcher(self,event,...)
  13.     -- Store the arguments into an array to access when needed
  14.     local args = { ... }
  15.  
  16.     if event == "PLAYER_ENTERING_WORLD" then
  17.        -- Deal with player entering world
  18.    elseif event == "ADDON_LOADED" then
  19.       -- Deal with any addons being loaded that you want to watch for ( args[1] is addon being loaded )
  20.     end
  21.  
  22. end
  23.  
  24. local f = CreateFrame("Frame")
  25. f:RegisterEvent("ADDON_LOADED")
  26. f:RegisterEvent("PLAYER_ENTERING_WORLD")
  27. f:SetScript("OnEvent", EventWatcher)
__________________
  Reply With Quote
04-11-20, 02:51 PM   #3
TransformedBG
A Fallenroot Satyr
Join Date: Oct 2010
Posts: 23
Thanks appreciate that. With covid and free time im looking to get back into coding. Its just hard trying to find a good source.

Just out of curiosity what does the frame in your template do? Is that like a wrapper for the code? And your functions are just kind of listening?

Other question is if you look at my list of quotes they used a global variable previously but it doesnt seem i can update say lvl, without doing it like i am. Which i dont think is a problem, but im trying to figure out how i woulm thanks
  Reply With Quote
04-11-20, 03:36 PM   #4
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,892
Yes its an invisible frame that handles event management.

It can easily be replaced with a visual and functional frame.


UnitLevel("player") will only work after the Player has Logged into the game so the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event will give you access to the players level, so adding 1 to a nil value could cause an error or set it to 1 or keep it at nil ( I've never tried +1 on a nil value ). The UNIT_LEVEL event will allow you to track the changes when they happen. Just use arg1 of the events parameters rather than UnitLevel("player") in the UNIT_LEVEL event code.
__________________
  Reply With Quote
04-11-20, 11:21 PM   #5
TransformedBG
A Fallenroot Satyr
Join Date: Oct 2010
Posts: 23
So i still have to be doing something wrong... when i call EventWatcher (/run EventWatcher("PLAYER_LEVEL_UP") i get the message as i am supposed to. I can see the addon loaded, etc.


Code:
--[[ Localise the Addon Wide Data Table ]]--
local addonName, addonData = ...

--[[ Localise any Addon Wide Sub Tables that are frequently accessed ]]--
local Translate = addonData.Translate

GLUA = {}
GLUA.GLUA_Frame = CreateFrame("Frame")
GLUA.GLUA_Frame:RegisterEvent("ADDON_LOADED")
GLUA.GLUA_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
GLUA.GLUA_Frame:RegisterEvent("PLAYER_LEVEL_UP")
GLUA.GLUA_Frame:RegisterEvent("CHAT_MSG_GUILD")
GLUA.GLUA_Frame:RegisterEvent("GUILD_ROSTER_UPDATE")

GLUA.GLUA_Frame:SetScript("OnEvent", function(self,event,...)--EventWatcher)
	EventWatcher(event,...)
end)

local me = UnitName("player") -- Gets players Name
local lvl = UnitLevel("player")+1 --Gets Current Player Level 
local race = UnitClass("player") --local varable to record what race you are.
local realm = GetRealmName(); -- Gets Realm name

--[[List to define chat channels]]--
channel_list = {}
channel_list["chan"] = {
"SAY",
"GUILD",
"PARTY",
"RAID",
"BATTLEGROUND",
}

--[[List to define different randomized quotes]]--
quote_this = {}
quote_this["level"] = {
"This has been a test of the Emergancy Ding System! "..me.."is now " ..lvl..".",
"My ding a ling. My ding a ling... looks like im level "..lvl.."!!!",
"DING, DING, DING... Looks like "..me.."just hit "..lvl.."!",
"Check this guys! Im now a level "..lvl.." "..race.."!",
"If you heard it once, you have heard it "..lvl.." times. DING!",
"Go ahead and just say grats alread! Cause i just hit level "..lvl.."!",
"Warning, Warnning,"..me.." You Just Hit Level "..lvl.."!",
"My microwave Dings and so do I! "..lvl.. " levels done!",
"Whats the difference between a rogue and a noob, they both pick locks! DING! That makes "..lvl.."!",
"This aint no AutoDing, okay well maybe a little... DING! now im level "..lvl.."!",
"Mama says every time a player Dings an angel gets its wings. DING level"..lvl.."!",
"Oh what is that noise? Sounds like someone just Dinged! Could it be "..me.."?! Woo hoo im level "..lvl.."!",
}

function GLUA_OnLoad()-- Loads on player login --
	DEFAULT_CHAT_FRAME:AddMessage("Guild Level Up Announcer has been initialized!")
	DEFAULT_CHAT_FRAME:AddMessage(" Ver. 1.13.14");
end

function GLUA_Message(quotes, channel)
	SendChatMessage(quotes, channel, nil, nil); --sends the chat message, party is just a filler for now testing
end

function GLUA_Channel()
	local num = 1 --you are Solo
		if UnitInParty("player")  then
			--print("party")
			num = 3 -- your in a party
		end
		if UnitInRaid("player") then
			--print("raid")
			num = 4 --Your in a raid group
		end
		if UnitInBattleground("player") then
			--print("Battleground")
			num = 5 --You are Battleground
		end
	return num
end

function GLUA_Quotes()
	local list = quote_this["level"]
	local quote = list[math.random(table.getn(list))]
	return quote
end

function GLUA_GUILD_CHECK(test)
	test = GetGuildInfo("player")
		if (test == nil)then
			test = false 
			return test
		end
   test = true
   return test
end

--[[ Monitor registered events ]]--
function EventWatcher(event,...)
	-- Store the arguments into an array to access when needed
    local args = { ... }
	
	if event == "PLAYER_ENTERING_WORLD" then
       -- Deal with player entering world
	   print("Someone did something in the world")
	end
    if event == "ADDON_LOADED" then
      -- Deal with any addons being loaded that you want to watch for ( args[1] is addon being loaded )
	  print("GLUA Addon Loaded")
	end
	if event == "PLAYER_LEVEL_UP" then --if a player levels up do the following
		print("Player Leveled Up = " .. event)
		local quote_to_share = GLUA_Quotes()
		local chanX = channel_list["chan"]
		local chan_number= GLUA_Channel()
			GLUA_Message(quote_to_share, chanX[chan_number]) -- send message to party or raid
		local check_guild = GLUA_GUILD_CHECK(check_guild)
		--[[if (check_guild == true) then
			print("not in a guild")
			GLUA_Message(quote_to_share, chanX[2]) -- return a second message to guild
		end]]--
	end
end
Code:
1x [ADDON_ACTION_BLOCKED] AddOn 'GLUA' tried to call the protected function 'UNKNOWN()'.
!BugGrabber\BugGrabber.lua:519: in function <!BugGrabber\BugGrabber.lua:519>
[C]: ?
[C]: in function `SendChatMessage'
GLUA\GLUA-1.0.1.1.lua:71: in function `GLUA_Message'
GLUA\GLUA-1.0.1.1.lua:124: in function `EventWatcher'
GLUA\GLUA-1.0.1.1.lua:30: in function <GLUA\GLUA.lua:29>

Locals:
InCombatSkipped
I noticed your template had the function as a local function.... is that needed? if i leave it like that i get the nil value error...

My problem seems to be when i call my GLUA_Message function, which calls to my table and randomly picks a quote, then says to send that message to self, party, bg, raid, and guild if in one. im getting the protected function unknown.... So from looking at your link it spears SendChatMessage is a protected function now...

Because i can get it to print "Player Leveled up = PLAYER_LEVEL_UP. meaning i get to line 121 of my code . I can add print("calling SendChatMessage with "..quote_to_share.." on channel number "..chan_number.."!") to line 126 unter ocal chan_number=GLUA_Channel() and see that its call the quote and level properly, just cant send the chat message. and by adding print(quotes) and print(channel) i can see that it passes the correct values to it..

The only thing i can think is that Locals:InCombatSkipped in the error, may not be letting me pass it to a secure function.. i guess i would need to check out of combat?
  Reply With Quote
04-12-20, 12:01 AM   #6
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
SendChatMessage needs a hardware event (key press or mouse click) for the SAY channel (and YELL but you're not using that). It cannot be called from code just based on an event or some other condition.

The code you have should work OK for Party, Raid and Guild shoutouts... for now, as those channels don't require the hardware event..
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 04-12-20 at 01:25 AM.
  Reply With Quote
04-12-20, 02:19 AM   #7
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,892
Thumbs up

Originally Posted by TransformedBG View Post

I noticed your template had the function as a local function.... is that needed? if i leave it like that i get the nil value error...
Hmm, it should work fine as a local function. By the time your own function is accessing it, it should be in the files local environment and accessible to it.
You are duplicating some areas .. You have your GLUA global table which has its own frame which has an event watcher .. so rather than call the event watch function I gave you as a template you can just use your own event watcher function.

Lua Code:
  1. GLUA = {}
  2. GLUA.GLUA_Frame = CreateFrame("Frame")
  3. GLUA.GLUA_Frame:RegisterEvent("ADDON_LOADED")
  4. GLUA.GLUA_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
  5. GLUA.GLUA_Frame:RegisterEvent("PLAYER_LEVEL_UP")
  6. GLUA.GLUA_Frame:RegisterEvent("CHAT_MSG_GUILD")
  7. GLUA.GLUA_Frame:RegisterEvent("GUILD_ROSTER_UPDATE")
  8.  
  9. GLUA.GLUA_Frame:SetScript("OnEvent", function(self,event,...)--EventWatcher)
  10.       .. put the code inside EventWatcher in here
  11. end)

Also, as a side note. Unless you want other addons to use GLUA in their own addons you can make GLUA either local or a part of the addonData table which is just for your addons.



The following is why I use local and addon wide values and rarely use globals.

If you don't have these functions as local functions you could break addons that have similar names in their *global* function names and you could be overriding their functionality with yours.

If the functionality/data is only needed in the file local is the best situation.
If the functionality/data is needed across your whole addon and you want more manageable files you can split your files up and have different types of functionality stored in different files and all share the same data.

EG. Translation Files

This could be your enUS translate file
Lua Code:
  1. local addonName,addonData = ...
  2. addonData.Locale = GetLocale()
  3. addonData.Translate =
  4. {
  5.       ["Translate Key 1"] = "Translate Value in this locales language"
  6. }

This would be one of your foreign languages
Lua Code:
  1. local addonName,addonData = ...
  2. if ( addonData.Locale == "frFR" ) then    
  3.     addonData.Translate = {
  4.       ["Translate Key 1"] = "Translate Value in this locales language"
  5.     }
  6. end

Just rinse and repeat your supported languages with your chosen default as the main translation file and any supported in additional files.

The addonData.Locale is set in the main translation file and is accessible in all files loaded after.

Your main code then only has to call addonData.Translate["Translate Key 1"] for this example and it will automatically pick the correct language for the user if it is supported or fall back to the default language.

This multi file system relies on loading order to work properly so you will have to identify which files need to be loaded before another one so that any functions/values etc are in the addons memory before they are called.

So to reiterate...

You have global values/functions that are accessible by any addon and could inadvertently override another addons functionality or break it altogether.

You have addon wide values/functions that are accessible by the addon it is placed in. Think of it as local to your addon rather than local to a file/function etc.

You have local values/functions that are only available in the confines of the code blocks they are used in. Either a file wide local value or a function wide local value or even a loop wide local value.


Local values are always your best option if you only want that block of code to access it.

Addon wide values are your next best option if you want those values accessible amongst multiple files in a bigger or more manageable addon.

Global values should only be used if you intend to override a functionality in another addon or blizzards own functionality. Bear in mind that unless these were intended to be overridden you may have unintended problems.


For example:
In my latest addon project I intend to have global functions with unique names that will allow other addons to be plugins to my addon project to modify certain elements.

So I would have a bunch of *untouchable* local or addon wide functionality and then a global function say for example :
Lua Code:
  1. function Xrystal_Override<Module>(data)  
  2. {
  3. .. code to replace default module data with customised module data ..  
  4. }
And the other addon would be able to set up their module data and then call the Xrystal_Override<Module>(...) passing in the data table they created for that module as follows:
Lua Code:
  1. local displayData = { ... }
  2. Xrystal_OverrideDisplay(displayData)

This could be used for example to allow users of your addon to create translation plugins to your addon that will be accessible by your addon via their addon registering their data for your addons use. Or to replace the layout of your addons default UI with one that think would work better for themselves and other people.
__________________

Last edited by Xrystal : 04-12-20 at 02:27 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Just trying to revive an old add... need a little help

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off