You are not logged in.

Applications: [GameMaster: OPEN] | [Volunteer Testers: OPEN]


This forum will be permanently shut down on Friday 13.07.2018
Please copy or save all important information from old forum before they will be deactivated
We have moved to new board. https://forum.runesofmagic.gameforge.com/Come join us.

1

Saturday, June 30th 2012, 6:45am

Adding an anti spam mechanism to an existing addon

Hello.
I use an addon for roleplaying purposes. What it does is makes the character say an inchantation when he/she casts a spell. The name of the addon is called FFT casting. However, this addon can spam the chat if the character uses a spell over and over. For example. I have a priest, if my priest casts urgent heal multiple times. The incantation for it will spam the general chat channel each time its said.

For some time I have gotten around this by making macros that does the same thing mostly for the spells that are prone to be spammed quite a bit. But problem is I have to copy this to other characters, which brings me back to this addon.

I would figure it would be easiest to modify this addon (as I have been doing so just a little bit already) to incorporate a sort of anti spam mechanism or cooldown to how often the speeches are done. I would do it myself, but I have very very very breif knowledge on coding stuff like this. I only understand most of what this addon does because of reading the commands and knowing the basics of how coding works. I would really like this addon expanded upon, but I dont have the ability.

Here is the entire LUA of the addon. As you can see its simple.


Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
-- Copyright (c) 2009, Lewis Linn White Jr.
-- All rights reserved.

-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

--   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
--   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
--   * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
-- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
-- OF SUCH DAMAGE.


local FFTCasting = {}
FFTCasting.VERSION = "0.2"

_G.FFTCasting = FFTCasting
local frame = _G.FFTCasting_Frame

local castingOn = true

SLASH_FFTCasting1 = "/fftcasting"
SlashCmdList['FFTCasting'] = function(editBox, msg)
    if string.lower(msg) == "off" then
        castingOn = false
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned off.")
    elseif string.lower(msg) == "on" then
        castingOn = true
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned on.")
    else
        DEFAULT_CHAT_FRAME:AddMessage("Not a valid argument: '" .. msg .. "'")
    end
end

function FFTCasting.Say(messageToSay)
    SendChatMessage(messageToSay, "SAY")
end

frame:RegisterEvent("CASTING_START")

function FFTCasting:OnEvent(event, ...)
    FFTCasting[event](...)
end

function FFTCasting.CASTING_START(spellName, ...)
    if spellName == "Flame" then whatToSay = "Star fire, awake and deliver your judgement!"
        elseif spellName == "Plasma Arrow" then whatToSay = "Clear with a mighty breeze!"
        elseif spellName == "Electric Bolt" then whatToSay = "Heavenly bolts, bring God's justice!"
        elseif spellName == "Meteor Shower" then whatToSay = "Time has come...crash down on the wicked!"
        elseif spellName == "Electric Explosion" then whatToSay = "Angry spirits of the world strike now!"
        elseif spellName == "Static Field" then whatToSay = "Absorb power in the sky and strike!"
        elseif spellName == "Rising Tide" then whatToSay = "Effortless water, break your silence, attack!"
        elseif spellName == Urgent Heal then whatToSay = "Life's refreshing breeze, heal from the sky!"
        elseif spellName == "Heal" then whatToSay = "Ancient light, rise and revive!"
        elseif spellName == "Resurrection" then whatToSay = "Spirits of life, give a new life to the soul!"
        elseif spellName == "Group Heal" then whatToSay = "Heavenly wind, carry us to fountain of power!"
        elseif spellName == "Ice Fog" then whatToSay = "Freezing wind, speak of forgotten truths!"
        elseif spellName == "Chain of Light" then whatToSay = "Bright light, shine down on bloody impurity!"
        else do return end
    end
    if whatToSay ~= nil and spellName ~= nil and castingOn then
        local whatToSayWithSpellName = whatToSay .. " " .. spellName .. "!"
        FFTCasting.Say(whatToSayWithSpellName)
    end
end



Hoping I can get some feedback on this. I've been using this addon for years. And wanted to suggest this for years but never really gotten around to it.

Heres the XML file

Source code

1
2
3
4
5
6
7
8
9
<Ui xmlns="http://www.runewaker.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.runewaker.com/UI.xsd">
    <Frame name="FFTCasting_Frame">
        <Scripts>
            <OnEvent>
                FFTCasting:OnEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
            </OnEvent>
        </Scripts>
    </Frame>
</Ui>
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

2

Saturday, June 30th 2012, 6:55am

Seems to be missing the XML file since the code uses

Source code

1
local frame = _G.FFTCasting_Frame

But you don't have FFTCasting_Frame declared or defined anywere in the code.

As for commenting on the code, well you could simplify the event function by dumping the massive if-else construct and using a lookup table keyed to the spell names.

Use a table something along the lines of (just a few entries to give you the gist of this):

Source code

1
2
3
4
local WhatToSay = {
    ['Flame'] = "Star fire, awake and deliver your judgement!",
    ['Plasma Arrow'] = "Clear with a mighty breeze!",
}

Now the callback can be:

Source code

1
2
3
4
5
function FFTCasting.CASTING_START(spellName, ...)
    if WhatToSay[(spellName or '')] then
        FFTCasting.Say(WhatToSay[spellName] .. " " .. spellName .. "!")
     end
end

Now you can simply add more entries to your lookup table.
2013... The year from hell....

3

Saturday, June 30th 2012, 7:10am

I included the XML file just now.

Theres also a .toc file if thats needed.
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

4

Saturday, June 30th 2012, 7:14am

The TOC shouldn't be needed unless someone wants to try it out. I was just curious about the frame but I see it is just there for the events.

Anyway, I commented briefly on the code (edited previous post). Now I have to go to bed...
2013... The year from hell....

5

Saturday, June 30th 2012, 7:36am

Thanks. I'll check it out and see if I can apply it correctly.E

Edit: I applied it perfectly. It works just as before. Just with a slightly cleaner coding look now. Just tested it to be sure with just flame and plasma arrow coded. And it went off just fine. Added the others in. The cleaner coding I would imagine would help better in incorporating the anti spam mechanism.

Since your heading to bed. I'll await anything else you may have to add. Unless anyone else is willing to help.

And if this goes well. I'd be glad to share the revised addon publicly.
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

6

Saturday, June 30th 2012, 6:17pm

Weeee... it's nitpicking time!

What I'll mention can be ignored, since it's more how I'd do things as opposed to being specifically better as was the case with the lookup table since not only is it cleaner, it will run in constant time regardless of the number of spells being checked for.

First, since the frame is only being used for receiving the CASTING_START event, I'd would ditch the XML entirely and define the frame in code. This allows removing the double indirection of the event callback as well as keeping the global namespace cleaner by removing the global create by the frame as it isn't needed.

Create the frame like this (it replaces the line where you set the frame variable):

Source code

1
2
3
4
5
6
7
-- Create the frame
local frame = CreateUIComponent("Frame", "FFTCasting_Frame", "UIParent")
_G['FFTCasting_Frame'] = nil    -- remove the global created by CreateUIComponent

-- Set the frame's OnEvent callback
frame:SetScripts("OnEvent", [=[ FFTCasting[event](arg1) ]=])
frame:RegisterEvent("CASTING_START")    -- this line was moved to here for code consistency

You can ditch the FFTCasting:OnEvent function as it is no longer needed.

For the slash command, I'd set a local variable to equal the lowercase version of the msg string and use it in the if statements. This avoid repeatedly calling string.lower for each string comparison. Something like:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
SlashCmdList['FFTCasting'] = function(editBox, msg)
    local option = string.lower(msg)

    if option == "off" then
        castingOn = false
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned off.")
    elseif option == "on" then
        castingOn = true
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned on.")
    else
        DEFAULT_CHAT_FRAME:AddMessage("Not a valid argument: '" .. msg .. "'")
    end
end


Finally, add an extra option to the above so that if no argument is given to the slash command (msg == "") then display some help text so that the user can always find out what they are.

Edit:
Almost forgot, consider adding a message at the end to tell user the add-on is loaded and ready. Also a good opportunity to remind the user what the slash command is.
2013... The year from hell....

7

Saturday, June 30th 2012, 9:47pm

I tried to implement the suggestions into the lua. But sinse then, it seems like something became broken.
The speeches no longer trigger.

Heres the code minus the comment code at the beginning.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
local FFTCasting = {}
FFTCasting.VERSION = "0.2"

_G.FFTCasting = FFTCasting

-- Create the frame
local frame = CreateUIComponent("Frame", "FFTCasting_Frame", "UIParent")
_G['FFTCasting_Frame'] = nil    -- remove the global created by CreateUIComponent

-- Set the frame's OnEvent callback
frame:SetScripts("OnEvent", [=[ FFTCasting[event](arg1) ]=])
frame:RegisterEvent("CASTING_START")    -- this line was moved to here for code consistency

local castingOn = true

SLASH_FFTCasting1 = "/fftcasting"
SlashCmdList['FFTCasting'] = function(editBox, msg)
    local option = string.lower(msg)

    if option == "off" then
        castingOn = false
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned off.")
    elseif option == "on" then
        castingOn = true
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned on.")
    DEFAULT_CHAT_FRAME:AddMessage("FFTCasting is now loaded and ready, type /fftcasting to deactivate")
    else
        DEFAULT_CHAT_FRAME:AddMessage("Not a valid argument: '" type /fftcasting to activate or deactivate "'")
    end
end

function FFTCasting.Say(messageToSay)
    SendChatMessage(messageToSay, "SAY")

end

local WhatToSay = {
    ['Flame'] = "Star fire, awake and deliver your judgement!",
    ['Plasma Arrow'] = "Clear with a mighty breeze!",
    ['Electric Bolt'] = "Heavenly bolts, bring God's justice!" ,
    [' Meteor Shower '] = "Time has come...crash down on the wicked!" ,
    [' Electric Explosion '] = "Angry spirits of the world strike now!" ,
    [' Static Field '] = "Absorb power in the sky and strike!" ,
    [' Rising Tide '] = "Effortless water, break your silence, attack!" ,
    [' Urgent Heal '] = "Life's refreshing breeze, heal from the sky!" ,
    [' Heal '] = "Ancient light, rise and revive!" ,
    [' Resurrection '] = "Spirits of life, give a new life to the soul!" ,
    [' Group Heal '] = "Heavenly wind, carry us to fountain of power!" ,
    [' Ice Fog '] = "Freezing wind, speak of forgotten truths!" ,
    [' Chain of Light '] = "Bright light, shine down on bloody impurity!" ,
    [' Thunderstorm '] = "Winds of destruction, take hold and deliver your wrath!" ,
    [' Earth Surge '] = "Earth, groan and awaken your might. Show my foe your Power and strength!" ,
    [' Phoenix '] = "Flames, Burst!" ,
}
function FFTCasting.CASTING_START(spellName, ...)
    if WhatToSay[(spellName or '')] then
        FFTCasting.Say(WhatToSay[spellName] .. " " .. spellName .. "!")
     end
end


I also got rid of the XML file
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

8

Sunday, July 1st 2012, 6:36am

You forgot to remove the double quotes when you modified the default message in the slash command. The line should read:

Source code

1
DEFAULT_CHAT_FRAME:AddMessage("Not a valid argument: type /fftcasting to activate or deactivate")

I suspect this is what is causing the code not to compile and therefore making the add-on not actually be loaded.
2013... The year from hell....

9

Sunday, July 1st 2012, 7:05am

Oh I see. I assumed that was supposed to be there. Well thanks to that. its back working like before now.

Though testing it out. It doesnt seem to activate or deactivate when typing the slash command. It continues to give the non valid argument message in all variations of /fftcasting.

But it seemed to have that problem originally already. Trying to figure out why so can get to the main thing wanted in it if the coding seems cleaned up enough for it.
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

10

Sunday, July 1st 2012, 11:34am

To turn on

Source code

1
/fftcasting on


to turn off

Source code

1
/fftcasting off


Kinda shows why I mentioned you need to have those help messages :D
2013... The year from hell....

11

Sunday, July 1st 2012, 12:50pm

Ah I see. LOL.
Thought it just flips on and off just by typeing the slash command.

Yeah.. think I'd add that in. Lol.
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

12

Monday, July 2nd 2012, 10:57pm

So now thats all done.
Can I get some help in assembling a sort anti spam mechanism, something like of a global cooldown for the speeches, or a cooldown for each speech. Or both?
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

13

Monday, July 2nd 2012, 11:47pm

Sorry I'd forgotten about the original question... hehe.

Anyway, now that I got you to put all the text to say in a lookup table, we can leverage this for individual "cooldowns" for those sayings. We can also implement a global one as well.

First thing is to decide if you want these so called cooldowns time based or count based. That is, do the sayings only happen after X amount of time or every X times it is cast. I'd do time based personally, but doing a count based version shouldn't be hard to do.

For timing things, an update callback for the frame will need to be used. So add this after the creation of the frame

Source code

1
frame:SetScripts("OnUpdate", [=[ FFTCasting.OnUpdateHandler(elapsedTime) ]=] )


Since a global cooldown is also wanted, we need to declare a couple of variables for those as well. At the top of the code, add this:

Source code

1
2
local FFTGlobalCooldown = 5    -- 5 second global cooldown
local FFTCurGlobalTime = 0


Now to modify the lookup table itself. Instead of just strings, have each entry a table containing the string to say, and the desired cooldown time (I'll use 10 seconds for this example) as well as the current cooldown time (Again, I'll just show the first two entries, you can then modify as desired)

Source code

1
2
3
4
local WhatToSay = {
    ['Flame'] = { text = "Star fire, awake and deliver your judgement!", cooldown = 10, curtime = 0 },
    ['Plasma Arrow'] = { text = "Clear with a mighty breeze!", cooldown = 10, curtime = 0 },
}



As we've modified this table, we'll now need to also change the event callback so that it uses the correct string as well as check for the cooldowns. So the first thing to do is to verify if the global cooldown has elapsed and if not exit the event callback. Otherwise we then check if the spell's cooldown has expired and if not we again exit otherwise we do the saying and then kick start both the global cooldown and the spell's cooldown. So the function becomes:

Source code

1
2
3
4
5
6
7
8
9
10
11
function FFTCasting.CASTING_START(spellName, ...)
    if FFTCurGlobalTime <= 0 then
        if WhatToSay[(spellName or '')] then
            if WhatToSay[spellName].curtime <= 0 then
                FFTCasting.Say(WhatToSay[spellName].text .. " " .. spellName .. "!")
                FFTCurGlobalTime = FFTGlobalCooldown
                WhatToSay[spellName].curtime = WhatToSay[spellName].cooldown
            end
        end
    end
end


So now to add the frame's update function. The parameter being passed to this function will be the time, in seconds, since the game last called this update function. so all we need do is remove this amount of time off all the cooldown timers.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
function FFTCasting.OnUpdateHandler(elapsed)   
    local adjustedTime = FFTCurGlobalTime - elasped

    -- Set the new global timer value, capping it to 0 if negative
    FFTCurGlobalTime = adjustedTime < 0 and 0 or adjustedTime

    for k,v in pairs(WhatToSay) do
        if v.curtime > 0 then
            adjustedTime = v.curtime - elasped
            v.curtime = adjustedTime < 0 and 0 or adjustedTime
        end
    end
end


That should do the trick.
2013... The year from hell....

14

Tuesday, July 3rd 2012, 7:13am

Okay I put in the code parts in. The speeches arent triggering anymore.

Here is all whats down now.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
 -- Copyright (c) 2009, Lewis Linn White Jr.-- All rights reserved.


-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:


--   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
--   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
--   * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.


-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
-- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
-- OF SUCH DAMAGE.


local FFTGlobalCooldown = 5    -- 5 second global cooldown
local FFTCurGlobalTime = 0
local FFTCasting = {}
FFTCasting.VERSION = "0.4"


_G.FFTCasting = FFTCasting


-- Create the frame
local frame = CreateUIComponent("Frame", "FFTCasting_Frame", "UIParent")
_G['FFTCasting_Frame'] = nil    -- remove the global created by CreateUIComponent


-- Set the frame's OnEvent callback
frame:SetScripts("OnEvent", [=[ FFTCasting[event](arg1) ]=])
frame:RegisterEvent("CASTING_START")    -- this line was moved to here for code consistency
frame:SetScripts("OnUpdate", [=[ FFTCasting.OnUpdateHandler(elapsedTime) ]=] )


local castingOn = true


SLASH_FFTCasting1 = "/fftcasting"
SlashCmdList['FFTCasting'] = function(editBox, msg)
    local option = string.lower(msg)


    if option == "off" then
        castingOn = false
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned off.")
    elseif option == "on" then
        castingOn = true
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned on.")
	DEFAULT_CHAT_FRAME:AddMessage("FFTCasting is now loaded and ready, type /fftcasting to deactivate")
    else
        DEFAULT_CHAT_FRAME:AddMessage("Not a valid argument: type '/fftcasting' on to activate or '/fftcasting off' deactivate")
    end
end


DEFAULT_CHAT_FRAME:AddMessage("FFTCasting is now loaded and ready, type '/fftcasting off' to deactivate and '/fftcasting on' to reactivate")


function FFTCasting.Say(messageToSay)
    SendChatMessage(messageToSay, "SAY")


end


local WhatToSay = {
    ['Flame'] = { text = "Star fire, awake and deliver your judgement!", cooldown = 10, curtime = 0 },
    ['Plasma Arrow'] = { text = "Clear with a mighty breeze!", cooldown = 10, curtime = 0 },
    ['Electric Bolt'] = { text = "Heavenly bolts, bring God's justice!" , cooldown = 10, curtime = 0 },
    ['Meteor Shower'] = { text = "Time has come...crash down on the wicked!" , cooldown = 10, curtime = 0 },
    ['Electric Explosion'] = "Angry spirits of the world strike now!" , cooldown = 10, curtime = 0 },
    ['Static Field'] = { text = "Absorb power in the sky and strike!" , cooldown = 10, curtime = 0 },
    ['Rising Tide'] = { text = "Effortless water, break your silence, attack!" , cooldown = 10, curtime = 0 },
    ['Urgent Heal'] = { text = "Life's refreshing breeze, heal from the sky!" , cooldown = 10, curtime = 0 },
    ['Heal'] = { text = "Ancient light, rise and revive!" , cooldown = 10, curtime = 0 },
    ['Resurrection'] = { text = "Spirits of life, give a new life to the soul!" , cooldown = 10, curtime = 0 },
    ['Group Heal'] = "Heavenly wind, carry us to fountain of power!" , cooldown = 10, curtime = 0 },
    ['Ice Fog'] = { text = "Freezing wind, speak of forgotten truths!" , cooldown = 10, curtime = 0 },
    ['Chain of Light'] = { text = "Bright light, shine down on bloody impurity!" , cooldown = 10, curtime = 0 },
    ['Thunderstorm'] = { text = "Winds of destruction, take hold and deliver your wrath!" , cooldown = 10, curtime = 0 },
    ['Earth Surge'] = { text = "Earth, groan and awaken your might. Show my foe your Power and strength!" , cooldown = 10, curtime = 0 },
    ['Phoenix'] = "Flames, Burst!" , cooldown = 10, curtime = 0 },
    ['Psychic Arrows'] = { text = "Dark, sinister ambitions, take form and strike!" , cooldown = 10, curtime = 0 },
    ['Soul Pain'] = { text = "Depths of the soul, go into agony and despair." , cooldown = 10, curtime = 0 },
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
    [''] = "" ,
}
function FFTCasting.CASTING_START(spellName, ...)
    if FFTCurGlobalTime <= 0 then
        if WhatToSay[(spellName or '')] then
            if WhatToSay[spellName].curtime <= 0 then
                FFTCasting.Say(WhatToSay[spellName].text .. " " .. spellName .. "!")
                FFTCurGlobalTime = FFTGlobalCooldown
                WhatToSay[spellName].curtime = WhatToSay[spellName].cooldown
            end
        end
    end
end


function FFTCasting.OnUpdateHandler(elapsed)   
    local adjustedTime = FFTCurGlobalTime - elasped


    -- Set the new global timer value, capping it to 0 if negative
    FFTCurGlobalTime = adjustedTime < 0 and 0 or adjustedTime


    for k,v in pairs(WhatToSay) do
        if v.curtime > 0 then
            adjustedTime = v.curtime - elasped
            v.curtime = adjustedTime < 0 and 0 or adjustedTime
        end
    end
end 


I changed the version number. And added in a few more spells and some blanks to add more if wanted.
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

15

Tuesday, July 3rd 2012, 12:07pm

Quoted from "ReagenL;542869"

Okay I put in the code parts in. The speeches arent triggering anymore.

...snip...

I changed the version number. And added in a few more spells and some blanks to add more if wanted.

Those blank entries are likely what is causing the issues. Get rid of them. The code relies on the fact that there are no entries named with the empty string. Specifically this line:

Source code

1
        if WhatToSay[(spellName or '')] then


Having multiple entries with the same name like that will likely make the code not compile (you probably are getting an error message in game, see the glowing green dot next to the minimap).

Further still, those entries only had a string and not a full table so even if the code does somehow compile and manages to get into the part where it check the spell cooldowns, it would then encounter runtime errors as there are no table entries for the cooldown and current time.
2013... The year from hell....

16

Tuesday, July 3rd 2012, 10:26pm

ALright I got rid of the blanks. There still seems to be a problem. Speeches still dont show. Is there another way to get error messages to appear?
I dont see a glowing green dot next to my minimap. Though my minmaps settings are changed a little.
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

17

Wednesday, July 4th 2012, 3:23am

Edit:
Woopsies... my bad. Apparently I can't type worth a [bleeeep].

In the function FFTCasting.OnUpdateHandler, I receive the argument in a variable called elapsed but inside the function itself I used elasped (note the spelling). Change the two places that say elasped to elapsed and it should all be good.

You can more or less ignore the rest of this post...
/Edit

There used to be an add-on called A Bug Catcher that would add a new debug message window, but I haven't seen it on Curse or Curseforge for some time now.

So we are left trying to debug manually. First add some messages to the CASTING_START event to see what is going on.
change the function to

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function FFTCasting.CASTING_START(spellName, ...)
    DEFAULT_CHAT_FRAME:AddMessage("In CASTING_START event")
    if FFTCurGlobalTime <= 0 then
       DEFAULT_CHAT_FRAME:AddMessage("Global Cooldown is 0")
        if WhatToSay[(spellName or '')] then
           DEFAULT_CHAT_FRAME:AddMessage("Found entry for "..spellName)
            if WhatToSay[spellName].curtime <= 0 then
               DEFAULT_CHAT_FRAME:AddMessage(spellName.." cooldown time is 0")
                FFTCasting.Say(WhatToSay[spellName].text .. " " .. spellName .. "!")
                FFTCurGlobalTime = FFTGlobalCooldown
                WhatToSay[spellName].curtime = WhatToSay[spellName].cooldown
            end
        end
    end
   DEFAULT_CHAT_FRAME:AddMessage("-------")
end

This should tell you if it gets into the event and up to where it gets.
2013... The year from hell....

18

Thursday, July 5th 2012, 2:03am

I added in what was said. Something still seems to be up. Not getting anything.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
-- Copyright (c) 2009, Lewis Linn White Jr.-- All rights reserved.


-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:


--   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
--   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
--   * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.


-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
-- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
-- OF SUCH DAMAGE.


local FFTGlobalCooldown = 5    -- 5 second global cooldown
local FFTCurGlobalTime = 0
local FFTCasting = {}
FFTCasting.VERSION = "0.4"


_G.FFTCasting = FFTCasting


-- Create the frame
local frame = CreateUIComponent("Frame", "FFTCasting_Frame", "UIParent")
_G['FFTCasting_Frame'] = nil    -- remove the global created by CreateUIComponent


-- Set the frame's OnEvent callback
frame:SetScripts("OnEvent", [=[ FFTCasting[event](arg1) ]=])
frame:RegisterEvent("CASTING_START")    -- this line was moved to here for code consistency
frame:SetScripts("OnUpdate", [=[ FFTCasting.OnUpdateHandler(elapsedTime) ]=] )


local castingOn = true


SLASH_FFTCasting1 = "/fftcasting"
SlashCmdList['FFTCasting'] = function(editBox, msg)
    local option = string.lower(msg)


    if option == "off" then
        castingOn = false
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned off.")
    elseif option == "on" then
        castingOn = true
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned on.")
	DEFAULT_CHAT_FRAME:AddMessage("FFTCasting is now loaded and ready, type /fftcasting to deactivate")
    else
        DEFAULT_CHAT_FRAME:AddMessage("Not a valid argument: type '/fftcasting' on to activate or '/fftcasting off' deactivate")
    end
end


DEFAULT_CHAT_FRAME:AddMessage("FFTCasting is now loaded and ready, type '/fftcasting off' to deactivate and '/fftcasting on' to reactivate")


function FFTCasting.Say(messageToSay)
    SendChatMessage(messageToSay, "SAY")


end


local WhatToSay = {
    ['Flame'] = { text = "Star fire, awake and deliver your judgement!", cooldown = 10, curtime = 0 },
    ['Plasma Arrow'] = { text = "Clear with a mighty breeze!", cooldown = 10, curtime = 0 },
    ['Electric Bolt'] = { text = "Heavenly bolts, bring God's justice!" , cooldown = 10, curtime = 0 },
    ['Meteor Shower'] = { text = "Time has come...crash down on the wicked!" , cooldown = 10, curtime = 0 },
    ['Electric Explosion'] = "Angry spirits of the world strike now!" , cooldown = 10, curtime = 0 },
    ['Static Field'] = { text = "Absorb power in the sky and strike!" , cooldown = 10, curtime = 0 },
    ['Rising Tide'] = { text = "Effortless water, break your silence, attack!" , cooldown = 10, curtime = 0 },
    ['Urgent Heal'] = { text = "Life's refreshing breeze, heal from the sky!" , cooldown = 10, curtime = 0 },
    ['Heal'] = { text = "Ancient light, rise and revive!" , cooldown = 10, curtime = 0 },
    ['Resurrection'] = { text = "Spirits of life, give a new life to the soul!" , cooldown = 10, curtime = 0 },
    ['Group Heal'] = "Heavenly wind, carry us to fountain of power!" , cooldown = 10, curtime = 0 },
    ['Ice Fog'] = { text = "Freezing wind, speak of forgotten truths!" , cooldown = 10, curtime = 0 },
    ['Chain of Light'] = { text = "Bright light, shine down on bloody impurity!" , cooldown = 10, curtime = 0 },
    ['Thunderstorm'] = { text = "Winds of destruction, take hold and deliver your wrath!" , cooldown = 10, curtime = 0 },
    ['Earth Surge'] = { text = "Earth, groan and awaken your might. Show my foe your Power and strength!" , cooldown = 10, curtime = 0 },
    ['Phoenix'] = "Flames, Burst!" , cooldown = 10, curtime = 0 },
    ['Psychic Arrows'] = { text = "Dark, sinister ambitions, take form and strike!" , cooldown = 10, curtime = 0 },
    ['Soul Pain'] = { text = "Depths of the soul, go into agony and despair." , cooldown = 10, curtime = 0 },
}
function FFTCasting.CASTING_START(spellName, ...)
    DEFAULT_CHAT_FRAME:AddMessage("In CASTING_START event")
    if FFTCurGlobalTime <= 0 then
       DEFAULT_CHAT_FRAME:AddMessage("Global Cooldown is 0")
        if WhatToSay[(spellName or '')] then
           DEFAULT_CHAT_FRAME:AddMessage("Found entry for "..spellName)
            if WhatToSay[spellName].curtime <= 0 then
               DEFAULT_CHAT_FRAME:AddMessage(spellName.." cooldown time is 0")
                FFTCasting.Say(WhatToSay[spellName].text .. " " .. spellName .. "!")
                FFTCurGlobalTime = FFTGlobalCooldown
                WhatToSay[spellName].curtime = WhatToSay[spellName].cooldown
            end
        end
    end
   DEFAULT_CHAT_FRAME:AddMessage("-------")
end


function FFTCasting.OnUpdateHandler(elapsed)   
    local adjustedTime = FFTCurGlobalTime - elapsed


    -- Set the new global timer value, capping it to 0 if negative
    FFTCurGlobalTime = adjustedTime < 0 and 0 or adjustedTime


    for k,v in pairs(WhatToSay) do
        if v.curtime > 0 then
            adjustedTime = v.curtime - elapsed
            v.curtime = adjustedTime < 0 and 0 or adjustedTime
        end
    end
end


Thats the whole thing as it is now.
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda

Peryl

Intermediate

Posts: 313

Location: Elsewhere

  • Send private message

19

Thursday, July 5th 2012, 6:49pm

You are missing some open braces (and the text = part) in the look up table. Specifically for Electric Explosion, Group Heal, and Phoenix. Make sure all table entries are correct.

You can also remove those debugging messages from the CASTING_START event function (though you might want to wait until things start working for that).
2013... The year from hell....

20

Sunday, July 8th 2012, 8:25pm

Alright I've done that.
Everything has been working. Or so I thought.

When I thought everything was working, I was thinking how to put into chat when typing /fftcasting cd (with having cd being an additional option to off and on) To say what the global cooldown is. But i couldnt figure out how to get that to show in a message as a variable.

Also I've came across an error that seems seperate to that. When casting, the speeches arent going off, and it seems theres some sort of error with the Onevent function. It says something about string(?). I couldnt see it completely. It was cut off over the casting bar.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
-- Copyright (c) 2009, Lewis Linn White Jr.-- All rights reserved.


-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:


--   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
--   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
--   * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.


-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
-- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
-- OF SUCH DAMAGE.


local FFTGlobalCooldown = 5    -- 5 second global cooldown
local FFTCurGlobalTime = 1
local FFTCasting = {}
FFTCasting.VERSION = "0.5"


_G.FFTCasting = FFTCasting


-- Create the frame
local frame = CreateUIComponent("Frame", "FFTCasting_Frame", "UIParent")
_G['FFTCasting_Frame'] = nil    -- remove the global created by CreateUIComponent


-- Set the frame's OnEvent callback
frame:SetScripts("OnEvent", [=[ FFTCasting[event](arg1) ]=])
frame:RegisterEvent("CASTING_START")    -- this line was moved to here for code consistency
frame:SetScripts("OnUpdate", [=[ FFTCasting.OnUpdateHandler(elapsedTime) ]=] )


local castingOn = true
SLASH_FFTCasting1 = "/fftcasting"
SlashCmdList['FFTCasting'] = function(editBox, msg)
    local option = string.lower(msg)


    if option == "off" then
        castingOn = false
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned off.")
    elseif option == "on" then
        castingOn = true
        DEFAULT_CHAT_FRAME:AddMessage("FFTCasting has been turned on.")
	DEFAULT_CHAT_FRAME:AddMessage("FFTCasting is now loaded and ready, type '/fftcasting off' to deactivate")
    elseif option == "cd" then
        DEFAULT_CHAT_FRAME:AddMessage("Testing")
    else
        DEFAULT_CHAT_FRAME:AddMessage("Not a valid argument: type '/fftcasting on' to activate or '/fftcasting off' deactivate")
    end
end


DEFAULT_CHAT_FRAME:AddMessage("FFTCasting is now loaded and ready, type '/fftcasting off' to deactivate and '/fftcasting on' to reactivate")


Heres the first half of the code. Everything else is the same except the CASTING_START function was removed, and corrected the missing " [text = " part.
Roleplayer in Govinda
Leader of the roleplay guild Immortal Covenant
Reagen -- 50/39 K/M-- Govinda
Xushin -- 29/54 W/M-- Govinda
Foroque -- 29/27 M/Wd --Govinda
Olan -- 22/27 P/K -- Govinda
Shivaa -- 40/40 P/S -- Govinda
Shayn -- 50/37 R/M -- Govinda
Raiden -- 22/0 M/x -- Govinda
Dieiyna -- 38/38 D/W -- Govinda