diff --git a/Chatreader.lua b/Chatreader.lua
new file mode 100644
index 0000000..3190c04
--- /dev/null
+++ b/Chatreader.lua
@@ -0,0 +1,300 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+TicketTab = "General";
+
+-- 1d2h3m4s to number in seconds
+function GMGenie.timeStrToSeconds(timeStr)
+ local days = string.match(timeStr, "([0-9]*)d");
+ if not days then
+ days = 0;
+ end
+ local hours = string.match(timeStr, "([0-9]*)h");
+ if not hours then
+ hours = 0;
+ end
+ local minutes = string.match(timeStr, "([0-9]*)m");
+ if not minutes then
+ minutes = 0;
+ end
+ local seconds = string.match(timeStr, "([0-9]*)s");
+ if not seconds then
+ seconds = 0;
+ end
+ return (((((tonumber(days) * 24) + tonumber(hours)) * 60) + tonumber(minutes)) * 60) + tonumber(seconds);
+end
+
+-- Read from chat
+local ORIG_ChatFrame_MessageEventHandler = ChatFrame_MessageEventHandler;
+function ChatFrame_MessageEventHandler(self, event, ...)
+ local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15 = ...;
+
+ local ActionTaken = false;
+
+ -- development code to analize chat messages
+ --local excapedarg = string.gsub(arg1, "%|", "%%");
+ --GMGenie.showGMMessage("1: " .. excapedarg);
+
+ -- check for system messages of interest
+ if (event == "CHAT_MSG_SYSTEM") then
+ -- Showing list of open tickets whose creator is online.
+ if string.find(arg1, "Showing list of open tickets") then
+ Chronos.scheduleByName('ticketreupdate', 0.5, GMGenie.Tickets.update);
+ ActionTaken = true;
+ end
+ -- ticket list or reading ticket
+ local ticketId, name, createStr, lastModifiedStr, rest = string.match(arg1, "^%|cffaaffaaTicket%|r:%|cffaaccff%s([0-9]+).%|r%s%|cff00ff00Created%sby%|r:%|cff00ccff%s(.+)%|r%s%|cff00ff00Created%|r:%|cff00ccff%s([a-zA-Z0-9%s]+)%sago%|r%s%|cff00ff00Last%schange%|r:%|cff00ccff%s([a-zA-Z0-9%s]+)%sago%|r%s(.*)$");
+
+ if ticketId and name and createStr and lastModifiedStr then
+ ticketId = tonumber(ticketId);
+ local createStamp = GMGenie.timeStrToSeconds(createStr);
+ local lastModifiedStamp = GMGenie.timeStrToSeconds(lastModifiedStr);
+ if GMGenie.Tickets.tempList then
+ GMGenie.Tickets.listTicket(ticketId, name, createStr, createStamp, lastModifiedStr, lastModifiedStamp);
+ end
+
+ local assignedTo = string.match(rest, "%|cff00ff00Assigned%sto%|r:%|cff00ccff%s([a-zA-Z]+)%|r%s");
+ if assignedTo then
+ GMGenie.Tickets.setAssigned(ticketId, assignedTo);
+ end
+ local message = string.match(rest, "%|cff00ff00Ticket%sMessage%|r:%s%[(.-)%]%|r");
+ local ticketCorrect = false;
+ if message then
+ ticketCorrect = GMGenie.Tickets.readTicket(ticketId, message);
+ else
+ local message = string.match(rest, "%|cff00ff00Ticket%sMessage%|r:%s%[(.*)");
+ if message then
+ ticketCorrect = GMGenie.Tickets.readTicket(ticketId, message);
+ if ticketCorrect then
+ GMGenie.Tickets.messageOpen = true;
+ end
+ end
+ end
+
+ local comment = string.match(rest, "%|cff00ff00GM%sComment%|r:%s%[(.*)%]%|r");
+ if comment then
+ GMGenie.Tickets.comment(ticketId, comment);
+ end
+
+ if ticketCorrect or GMGenie.Tickets.tempList then
+ ActionTaken = true;
+ end
+ elseif GMGenie.Tickets.messageOpen then
+ ActionTaken = true;
+ local message, rest = string.match(arg1, "(.-)%]%|r(.*)");
+ if message then
+ GMGenie.Tickets.messageOpen = false;
+ GMGenie.Tickets.addLine(message);
+ else
+ if string.find(arg1, "%]%|r") then
+ rest = string.match(arg1, "%]%|r(.*)");
+ GMGenie.Tickets.messageOpen = false;
+ else
+ GMGenie.Tickets.addLine(arg1);
+ end
+ end
+
+ if rest then
+ local comment = string.match(rest, "%|cff00ff00GM%sComment%|r:%s%[(.*)%]%|r");
+ if comment and GMGenie.Tickets.currentTicket['ticketId'] then
+ GMGenie.Tickets.comment(GMGenie.Tickets.currentTicket['ticketId'], comment);
+ end
+ end
+ else
+ -- Ticket edited
+ local name, ticketId = string.match(arg1, "^%|cff00ff00Character%|r%|cffff00ff%s([a-zA-Z]+)%s%|r%|cff00ff00edited%shis/her%sticket:%|r%|cffff00ff%s([0-9]+).%|r$");
+ if name and ticketId then
+ if GMGenie.Tickets.isOpen() then
+ GMGenie.Tickets.refresh();
+ end
+ ActionTaken = true;
+ end
+ -- Ticket abandoned
+ local name, ticketId = string.match(arg1, "^%|cff00ff00Character%|r%|cffff00ff%s([a-zA-Z]+)%s%|r%|cff00ff00abandoned%sticket%sentry:%|r%|cffff00ff%s([0-9]+).%|r$");
+ if name and ticketId then
+ if GMGenie.Tickets.isOpen() then
+ GMGenie.Tickets.refresh();
+ end
+ ActionTaken = true;
+ end
+ -- New Ticket
+ local name, ticketId = string.match(arg1, "^%|cff00ff00New%sticket%sfrom%|r%|cffff00ff%s([a-zA-Z]+).%|r%s%|cff00ff00Ticket%sentry:%|r%|cffff00ff%s([0-9]+).%|r$");
+ if name and ticketId then
+ if GMGenie.Tickets.isOpen() then
+ GMGenie.Tickets.refresh();
+ end
+ ActionTaken = true;
+ end
+ end
+
+ -- read coords from chat
+ if GMGenie.Spawns.waitingForGps == 1 then
+ if string.find(arg1, "^You are outdoors") or string.find(arg1, "^no VMAP available for area info") then
+ ActionTaken = true;
+ end
+ local map = string.match(arg1, "^Map:%s([0-9]+)%s");
+ if map then
+ GMGenie.Spawns.waitingForGps = 2;
+ GMGenie.Spawns.setMap(map);
+ ActionTaken = true;
+ end
+ end
+ if GMGenie.Spawns.waitingForGps == 2 then
+ local x, y, z, o = string.match(arg1, "^X:%s([0-9%.%-]+)%sY:%s([0-9%.%-]+)%sZ:%s([0-9%.%-]+)%sOrientation:%s([0-9%.%-]+)$");
+ if x and y and z and o then
+ GMGenie.Spawns.waitingForGps = 3;
+ GMGenie.Spawns.move(x, y, z, o);
+ ActionTaken = true;
+ end
+ end
+ if GMGenie.Spawns.waitingForGps == 3 then
+ if string.find(arg1, "^grid") or string.find(arg1, "^ ZoneX") then
+ ActionTaken = true;
+ end
+ if string.find(arg1, "^GroundZ") then
+ GMGenie.Spawns.waitingForGps = 0;
+ ActionTaken = true;
+ end
+ end
+
+ if GMGenie.Spy.waitingForPin or GMGenie.Macros.Discipline.IpBan.waitingForPin then
+ if string.find(arg1, "Player not found!") then
+ GMGenie.Spy.waitingForPin = false;
+ GMGenie.Macros.Discipline.IpBan.waitingForPin = false;
+ else
+ if GMGenie.Spy.waitingForPin then
+ local offline, name1, name2, guid = string.match(arg1, "Player ?(.*) %|cffffffff%|Hplayer:(.*)%|h%[(.*)%]%|h%|r %(guid: (.*)%)");
+ local phase = string.match(arg1, "Phase: (.*)");
+ local account, accountId, gmLevel = string.match(arg1, "Account: (.*) %(ID: (.*)%), GMLevel: (.*)");
+ local login, failedLogins = string.match(arg1, "Last Login: (.*) %(Failed Logins: (.*)%)");
+ local os, latency, email = string.match(arg1, "OS: (.*) %- Latency: (.*) ms %- Mail: (.*)");
+ local ip, locked = string.match(arg1, "Last IP: (.*) %(Locked: (.*)%)");
+ local level, xpCurrent, xpMax = string.match(arg1, "Level: (.*) %((.*)/(.*) XP");
+ local race, class = string.match(arg1, "Race: (.*), (.*)");
+ local alive = string.match(arg1, "Alive %?: (.*)");
+ local money = string.match(arg1, "Money: (.*)");
+ local map, area, zone = string.match(arg1, "Map: (.*), Area: (.*), Zone: (.*)");
+ local guild, guildId = string.match(arg1, "Guild: (.*) %(ID: (.*)%)");
+ local guildRank = string.match(arg1, "Rank: (.*)");
+ local playedTime = string.match(arg1, "Played time: (.*)");
+
+
+ if offline then
+ GMGenie.Spy.processPin01(offline, name1, guid, arg1);
+ ActionTaken = true;
+ end
+ if phase then
+ GMGenie.Spy.processPin02(phase, arg1);
+ ActionTaken = true;
+ end
+ if account then
+ GMGenie.Spy.processPin03(account, accountId, gmLevel, arg1);
+ ActionTaken = true;
+ end
+ if login then
+ GMGenie.Spy.processPin04(login, failedLogins, arg1);
+ ActionTaken = true;
+ end
+ if os then
+ GMGenie.Spy.processPin05(os, latency, email, arg1);
+ ActionTaken = true;
+ end
+ if ip then
+ GMGenie.Spy.processPin06(ip, locked, arg1);
+ ActionTaken = true;
+ end
+ if level then
+ GMGenie.Spy.processPin07(level, xpCurrent, xpMax, arg1);
+ ActionTaken = true;
+ end
+ if race then
+ GMGenie.Spy.processPin08(race, class, arg1);
+ ActionTaken = true;
+ end
+ if alive then
+ GMGenie.Spy.processPin09(alive, arg1);
+ ActionTaken = true;
+ end
+ if money then
+ GMGenie.Spy.processPin10(money, arg1);
+ ActionTaken = true;
+ end
+ if map then
+ GMGenie.Spy.processPin11(map, area, zone, arg1);
+ ActionTaken = true;
+ end
+ if guild then
+ GMGenie.Spy.processPin12(guild, guildId, arg1);
+ ActionTaken = true;
+ end
+ if guildRank then
+ GMGenie.Spy.processPin13(guildRank, arg1);
+ ActionTaken = true;
+ end
+ if playedTime then
+ GMGenie.Spy.processPin14(playedTime, arg1);
+ ActionTaken = true;
+ end
+ else
+ local ip, locked = string.match(arg1, "Last IP: (.*) %(Locked: (.*)%)")
+
+ if ip then
+ GMGenie.Macros.Discipline.IpBan.processPin(ip);
+ ActionTaken = true;
+ end
+ end
+ end
+ end
+
+ if GMGenie.Spawns.waitingForObject then
+ local name, guid, id = string.match(arg1, "%|cffffffff%|Hgameobject:.*%|h%[(.*)%]%|h%|r%sGUID:%s(.*)%sID:%s(.*)");
+ if name and guid and id then
+ GMGenie.Spawns.deleteObject(name, guid, id);
+ ActionTaken = true;
+ elseif string.find(arg1, "X:%s.*%sY:%s.*%sZ:%s.*%sMapId:%s.*") or string.find(arg1, "Orientation:%s.*") or string.find(arg1, "Phasemask%s.*") then
+ ActionTaken = true;
+ elseif string.find(arg1, "SpawnTime:%sFull:.*%sRemain:.*") then
+ ActionTaken = true;
+ GMGenie.Spawns.waitingForObject = false;
+ elseif string.find(arg1, "Nothing found!") then
+ GMGenie.Spawns.waitingForObject = false;
+ end
+ end
+
+ if GMGenie.Spawns.waitingForObjectDelete then
+ if string.find(arg1, "Game Object %(GUID: .*%) removed") then
+ ActionTaken = true;
+ GMGenie.Spawns.waitingForObjectDelete = false;
+ end
+ end
+
+ local charName = UnitName("player");
+ if string.match(arg1, "%|cffffffff%|Hplayer:" .. charName .. "%|h%[" .. charName .. "%]%|h%|r%'s Fly Mode on") then
+ GMGenie.Hud.flyStatus(true);
+ elseif string.match(arg1, "%|cffffffff%|Hplayer:" .. charName .. "%|h%[" .. charName .. "%]%|h%|r%'s Fly Mode off") then
+ GMGenie.Hud.flyStatus(false);
+ elseif arg1 == "Accepting Whisper: ON" or arg1 == "Accepting Whisper: on" then
+ GMGenie.Hud.whisperStatus(true);
+ elseif arg1 == "Accepting Whisper: OFF" or arg1 == "Accepting Whisper: off" then
+ GMGenie.Hud.whisperStatus(false);
+ elseif arg1 == "You are: visible" then
+ GMGenie.Hud.visibilityStatus(true);
+ elseif arg1 == "You are: invisible" then
+ GMGenie.Hud.visibilityStatus(false);
+ end
+
+ local characterName = string.match(arg1, "%|cFFFFBF00%[AntiCheat%]%:%|cFFFFFFFF %[(.*)%] %|cFF00FFFFdetected as possible cheater%.");
+ if characterName then
+ arg1 = "|cFFFFBF00[AntiCheat]:|r |Hanticheat:" .. characterName .. "|h[" .. characterName .. "]|h detected as possible cheater.";
+ end
+ end
+
+ -- if nothing was done, just display the message
+ if not ActionTaken then
+ ORIG_ChatFrame_MessageEventHandler(self, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15);
+ end
+end
\ No newline at end of file
diff --git a/Chronos/Chronos.lua b/Chronos/Chronos.lua
new file mode 100644
index 0000000..d36e99f
--- /dev/null
+++ b/Chronos/Chronos.lua
@@ -0,0 +1,860 @@
+--[[
+--
+-- Chronos
+-- Keeper of Time
+--
+-- By AnduinLothar, Alexander Brazie, and Thott
+--
+-- Chronos manages time. You can schedule a function to be called
+-- in X seconds, with or without an id. You can request a timer,
+-- which tracks the elapsed duration since the timer was started.
+--
+-- To use as an embeddable addon:
+-- - Put the Chronos folder inside your Interface/AddOns// folder.
+-- - Add Chronos\Chronos.xml to your toc or load it in your xml before your localization files.
+-- - Add Chronos to the OptionalDeps in your toc
+--
+-- To use as an addon library:
+-- - Put the Chronos folder inside your Interface/AddOns/ folder.
+-- - Add Chronos to the Dependencies in your toc
+--
+-- Please see below or see http://www.wowwiki.com/Chronos_(addon) for details.
+--
+-- $LastChangedBy: karlkfi $
+-- $Date: 2006-12-21 06:19:14 -0600 (Thu, 21 Dec 2006) $
+-- $Rev: 4467 $
+--
+--]]
+
+local CHRONOS_REV = 2.12;
+
+local isBetterInstanceLoaded = (Chronos and Chronos.version and Chronos.version >= CHRONOS_REV);
+
+if (not isBetterInstanceLoaded) then
+
+ if (not Chronos) then
+ Chronos = {};
+ end
+
+ Chronos.version = CHRONOS_REV;
+
+ ------------------------------------------------------------------------------
+ --[[ Variables ]] --
+ ------------------------------------------------------------------------------
+
+ Chronos.online = true;
+
+ CHRONOS_DEBUG = false;
+ CHRONOS_DEBUG_WARNINGS = false;
+
+ -- Chronos Data
+ if (not ChronosData) then
+ ChronosData = {};
+ end
+
+ -- Chronos Recycled Tables Storage
+ if (not Chronos.tables) then
+ Chronos.tables = {};
+ end
+
+ -- Initialize the Timers
+ if (not ChronosData.timers) then
+ ChronosData.timers = {};
+ end
+
+ -- Initialize the perform-over-time task list
+ if (not ChronosData.tasks) then
+ ChronosData.tasks = {};
+ end
+
+ -- Maximum items per frame
+ Chronos.MAX_TASKS_PER_FRAME = 100;
+
+ -- Maximum steps per task
+ Chronos.MAX_STEPS_PER_TASK = 300;
+
+ -- Maximum time delay per frame
+ Chronos.MAX_TIME_PER_STEP = .3;
+
+ Chronos.emptyTable = {};
+
+ ------------------------------------------------------------------------------
+ --[[ User Functions ]] --
+ ------------------------------------------------------------------------------
+
+ --[[
+ -- debug(boolean)
+ --
+ -- Toggles debug mode
+ ]] --
+ function Chronos.debug(enable)
+ if (enable) then
+ ChronosFrame:SetScript("OnUpdate", Chronos.OnUpdate_Debug);
+ CHRONOS_DEBUG = true;
+ CHRONOS_DEBUG_WARNINGS = true;
+ else
+ ChronosFrame:SetScript("OnUpdate", Chronos.OnUpdate_Quick);
+ CHRONOS_DEBUG = false;
+ CHRONOS_DEBUG_WARNINGS = false;
+ end
+ end
+
+ --[[
+ -- Scheduling functions
+ -- Parts rewritten by AnduinLothar for efficiency
+ -- Parts rewritten by Thott for speed
+ -- Written by Alexander
+ -- Original by Thott
+ --
+ -- Usage: Chronos.schedule(when,handler,arg1,arg2,etc)
+ --
+ -- After seconds pass (values less than one and fractional values are
+ -- fine), handler is called with the specified arguments, i.e.:
+ -- handler(arg1,arg2,etc)
+ --
+ -- If you'd like to have something done every X seconds, reschedule
+ -- it each time in the handler or preferably use scheduleRepeating.
+ --
+ -- Also, please note that there is a limit to the number of
+ -- scheduled tasks that can be performed per xml object at the
+ -- same time.
+ --]]
+ function Chronos.schedule(when, handler, ...)
+ if (not Chronos.online) then
+ return;
+ end
+ if (not handler) then
+ Chronos.printError("ERROR: nil handler passed to Chronos.schedule()");
+ return;
+ end
+
+ --local memstart = collectgarbage("count");
+ -- -- Assign an id
+ -- local id = "";
+ -- if ( not this ) then
+ -- id = "Keybinding";
+ -- else
+ -- id = self:GetName();
+ -- end
+ -- if ( not id ) then
+ -- id = "_DEFAULT";
+ -- end
+ -- if ( not when ) then
+ -- Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: ", id , " has sent no interval for this function. ", when );
+ -- return;
+ -- end
+
+ -- -- Ensure we're not looping ChronosFrame
+ -- if ( id == "ChronosFrame" and ChronosData.lastID ) then
+ -- id = ChronosData.lastID;
+ -- end
+
+ -- use recycled tables to avoid excessive garbage collection -AnduinLothar
+ --tinsert(ChronosData.sched, Chronos.getTable())
+ --local i = #ChronosData.sched
+ local recTable = Chronos.getTable()
+ -- ChronosData.sched[i].id = id;
+ recTable.time = when + GetTime();
+ recTable.handler = handler;
+ recTable.args = Chronos.getArgTable(...);
+
+ -- task list is a heap, add new
+ local i = #ChronosData.sched + 1
+ while (i > 1) do
+ if (recTable.time < ChronosData.sched[i - 1].time) then
+ i = i - 1;
+ else
+ break
+ end
+ end
+ tinsert(ChronosData.sched, i, recTable)
+
+ -- Debug print
+ --Chronos.printDebugError("CHRONOS_DEBUG", "Scheduled "..handler.." in "..when.." seconds from "..id );
+ --Chronos.printError("Memory change in schedule: "..memstart.."->"..memend.." = "..memend-memstart);
+ end
+
+
+ --[[
+ -- Chronos.scheduleByName(name, delay, function, arg1, ... );
+ --
+ -- Same as Chronos.schedule, except it takes a schedule name argument.
+ -- Only one event can be scheduled with a given name at any one time.
+ -- Thus if one exists, and another one is scheduled, the first one
+ -- is deleted, then the second one added.
+ --
+ --]]
+ function Chronos.scheduleByName(name, when, handler, ...)
+ if (not name) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: No name specified to Chronos.scheduleByName");
+ return;
+ end
+ local namedSchedule = ChronosData.byName[name];
+ if (namedSchedule and handler) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: scheduleByName is reasigning \"" .. name .. "\".");
+ Chronos.releaseTable(ChronosData.byName[name]);
+ else
+ if (not handler) then
+ if (not namedSchedule) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: No handler specified to Chronos.scheduleByName, no previous entry found for scheduled entry \"" .. name .. "\".");
+ return;
+ end
+ if (not namedSchedule.handler) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: No handler specified to Chronos.scheduleByName, no handler could be found in previous entry of \"" .. name .. "\" either.");
+ return;
+ end
+ handler = namedSchedule.handler;
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos: scheduleByName is updating \"" .. name .. "\" to time: " .. when);
+ else
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos: scheduleByName is asigning \"" .. name .. "\".");
+ end
+ end
+ ChronosData.byName[name] = Chronos.getTable();
+ namedSchedule = ChronosData.byName[name];
+ namedSchedule.time = when + GetTime()
+ namedSchedule.handler = handler;
+ namedSchedule.args = Chronos.getArgTable(...);
+ end
+
+ --[[
+ -- unscheduleByName(name);
+ --
+ -- Removes an entry that was created with scheduleByName()
+ --
+ -- Args:
+ -- name - the name used
+ --
+ --]]
+ function Chronos.unscheduleByName(name)
+ if (not Chronos.online) then
+ return;
+ end
+ if (not name) then
+ Chronos.printError("No name specified to Chronos.unscheduleByName");
+ return;
+ end
+ if (ChronosData.byName[name]) then
+ Chronos.releaseTable(ChronosData.byName[name]);
+ ChronosData.byName[name] = nil;
+ end
+
+ -- Debug print
+ --Chronos.printDebugError("CHRONOS_DEBUG", "Cancelled scheduled timer of name ",name);
+ end
+
+ --[[
+ -- unscheduleRepeating(name);
+ -- Mirrors unscheduleByName for backwards compatibility
+ --]]
+ Chronos.unscheduleRepeating = Chronos.unscheduleByName;
+
+ --[[
+ -- isScheduledByName(name)
+ -- Returns the amount of time left if it is indeed scheduled by name!
+ --
+ -- returns:
+ -- number - time remaining
+ -- nil - not scheduled
+ --
+ --]]
+ function Chronos.isScheduledByName(name)
+ if (not Chronos.online) then
+ return;
+ end
+ if (not name) then
+ Chronos.printError("No name specified to Chronos.isScheduledByName " .. (self:GetName() or "unknown"));
+ return;
+ end
+ local namedSchedule = ChronosData.byName[name];
+ if (namedSchedule) then
+ return namedSchedule.time - GetTime();
+ end
+
+ -- Debug print
+ --Chronos.printDebugError("CHRONOS_DEBUG", "Did not find timer of name ",name);
+ return nil;
+ end
+
+ --[[
+ -- isScheduledRepeating(name)
+ -- Mirrors isScheduledByName for backwards compatibility
+ --]]
+ Chronos.isScheduledRepeating = Chronos.isScheduledByName;
+
+ --[[
+ -- Chronos.scheduleRepeating(name, delay, function);
+ --
+ -- Same as Chronos.scheduleByName, except it repeats without recalling and takes no arguments.
+ --
+ --]]
+ function Chronos.scheduleRepeating(name, when, handler)
+ if (not name) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: No name specified to Chronos.scheduleRepeating");
+ return;
+ end
+ local namedSchedule = ChronosData.byName[name];
+ if (namedSchedule and handler) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: scheduleRepeating is reasigning " .. name);
+ Chronos.releaseTable(ChronosData.byName[name]);
+ else
+ if (not handler) then
+ if (not namedSchedule) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: No handler specified to Chronos.scheduleRepeating, no previous entry found for scheduled entry '" .. name .. "'.");
+ return;
+ end
+ if (not namedSchedule.handler) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: No handler specified to Chronos.scheduleRepeating, no handler could be found in previous entry '" .. name .. "' either.");
+ return;
+ end
+ handler = namedSchedule.handler;
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos: scheduleRepeating is updating '" .. name .. "' to time: " .. when);
+ else
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos: scheduleRepeating is asigning '" .. name .. "'.");
+ end
+ end
+ ChronosData.byName[name] = Chronos.getTable();
+ namedSchedule = ChronosData.byName[name];
+ namedSchedule.time = when + GetTime();
+ namedSchedule.period = when;
+ namedSchedule.handler = handler;
+ namedSchedule.repeating = true;
+ end
+
+ --[[
+ -- Chronos.flushByName(name, when);
+ --
+ -- Updates the ByName or Repeating event to flush at the time specified. If no time is specified flush will be immediate. If it is a Repeating event the timer will be reset.
+ --
+ --]]
+ function Chronos.flushByName(name, when)
+ if (not name) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: No name specified to Chronos.flushByName");
+ return;
+ elseif (not ChronosData.byName[name]) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos Error Detection: no previous entry found for Chronos.flushByName entry '" .. name .. "'.");
+ return;
+ end
+ if (not when) then
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos: flushing '" .. name .. "'.");
+ when = GetTime();
+ else
+ Chronos.printDebugError("CHRONOS_DEBUG_WARNINGS", "Chronos: flushing '" .. name .. "' in " .. when .. " seconds.");
+ when = when + GetTime();
+ end
+ ChronosData.byName[name].time = when;
+ end
+
+ --[[
+ -- Chronos.startTimer([ID]);
+ -- Starts a timer on a particular
+ --
+ -- Args
+ -- ID - optional parameter to identify who is asking for a timer.
+ --
+ -- If ID does not exist, self:GetName() is used.
+ --
+ -- When you want to get the amount of time passed since startTimer(ID) is called,
+ -- call getTimer(ID) and it will return the number in seconds.
+ --
+ --]]
+ function Chronos.startTimer(id)
+ if (not Chronos.online) then
+ return;
+ end
+
+ if (not id) then
+ id = self:GetName();
+ end
+
+ -- Create a table for this id's timers
+ if (not ChronosData.timers[id]) then
+ ChronosData.timers[id] = Chronos.getTable();
+ end
+
+ -- Clear out an entry if the table is too big.
+ if (#ChronosData.timers[id] > Chronos.MAX_TASKS_PER_FRAME) then
+ Chronos.printError("Too many Chronos timers created for id " .. tostring(id));
+ return;
+ end
+
+ -- Add a new timer entry
+ table.insert(ChronosData.timers[id], GetTime());
+ end
+
+
+ --[[
+ -- endTimer([id]);
+ --
+ -- Ends the timer and returns the amount of time passed.
+ --
+ -- args:
+ -- id - ID for the timer. If not specified, then ID will
+ -- be self:GetName()
+ --
+ -- returns:
+ -- (Number delta, Number start, Number end)
+ --
+ -- delta - the amount of time passed in seconds.
+ -- start - the starting time
+ -- now - the time the endTimer was called.
+ --]]
+
+ function Chronos.endTimer(id)
+ if (not Chronos.online) then
+ return;
+ end
+
+ if (not id) then
+ id = self:GetName();
+ end
+
+ if (not ChronosData.timers[id] or #ChronosData.timers[id] == 0) then
+ return nil;
+ end
+
+ local now = GetTime();
+
+ -- Grab the last timer called
+ local startTime = tremove(ChronosData.timers[id]);
+
+ return (now - startTime), startTime, now;
+ end
+
+
+ --[[
+ -- getTimer([id]);
+ --
+ -- Gets the timer and returns the amount of time passed.
+ -- Does not terminate the timer.
+ --
+ -- args:
+ -- id - ID for the timer. If not specified, then ID will
+ -- be self:GetName()
+ --
+ -- returns:
+ -- (Number delta, Number start, Number end)
+ --
+ -- delta - the amount of time passed in seconds.
+ -- start - the starting time
+ -- now - the time the endTimer was called.
+ --]]
+
+ function Chronos.getTimer(id)
+ if (not Chronos.online) then
+ return;
+ end
+
+ if (not id) then
+ id = self:GetName();
+ end
+
+ local now = GetTime();
+ if (not ChronosData.timers[id] or #ChronosData.timers[id] == 0) then
+ return 0, 0, now;
+ end
+
+ -- Grab the last timer called
+ local startTime = ChronosData.timers[id][#ChronosData.timers[id]];
+
+ return (now - startTime), startTime, now;
+ end
+
+ --[[
+ -- isTimerActive([id])
+ -- returns true if the timer exists.
+ --
+ -- args:
+ -- id - ID for the timer. If not specified, then ID will
+ -- be self:GetName()
+ --
+ -- returns:
+ -- true - exists
+ -- false - does not
+ --]]
+ function Chronos.isTimerActive(id)
+ if (not Chronos.online) then
+ return;
+ end
+
+ if (not id) then
+ id = self:GetName();
+ end
+
+ -- Create a table for this id's timers
+ if (not ChronosData.timers[id]) then
+ return false;
+ end
+
+ return true;
+ end
+
+ --[[
+ -- getTime()
+ --
+ -- returns the Chronos internal elapsed time.
+ --
+ -- returns:
+ -- (elapsedTime)
+ --
+ -- elapsedTime - time in seconds since Chronos initialized
+ --]]
+ function Chronos.getTime()
+ return ChronosData.elapsedTime;
+ end
+
+ --[[
+ -- Chronos.afterInit(func, ...)
+ -- Performs func after the game has truely started.
+ -- By Thott
+ --]]
+ function Chronos.afterInit(func, ...)
+ local id;
+ if (this) then
+ id = self:GetName();
+ else
+ id = "unknown";
+ end
+ --if(id == "SkyFrame") then
+ -- Chronos.printError("Ignoring Sky init");
+ -- return;
+ --end
+ if (ChronosData.initialized) then
+ func(...);
+ else
+ if (not ChronosData.afterInit) then
+ ChronosData.afterInit = Chronos.getTable();
+ Chronos.schedule(0.2, Chronos.initCheck);
+ end
+ local recTable = Chronos.getTable();
+ recTable.func = func;
+ recTable.args = Chronos.getArgTable(...);
+ recTable.id = id;
+ tinsert(ChronosData.afterInit, recTable);
+ end
+ end
+
+
+ ------------------------------------------------------------------------------
+ --[[ Table Recycling ]] --
+ ------------------------------------------------------------------------------
+ function Chronos.getTable(...)
+ local stack = Chronos.tables;
+ if (not stack) then
+ Chronos.tables = {};
+ stack = Chronos.tables;
+ return {};
+ end
+ local recTable;
+ if (#stack >= 1) then
+ recTable = tremove(stack)
+ else
+ recTable = {};
+ end
+ for i = 1, select("#", ...) do
+ recTable[i] = select(i, ...);
+ end
+ return recTable;
+ end
+
+ -- Release a table to be nilled and used again.
+ -- Optionally pass in an unpack(...) as the 2nd arg so that you can return the args:
+ -- return Chronos.releaseTable(t1, unpack(t1))
+ function Chronos.releaseTable(t1, ...)
+ if (type(t1) ~= "table") then
+ return;
+ end
+
+ local stack = Chronos.tables;
+ if (not stack) then
+ Chronos.tables = {};
+ stack = Chronos.tables;
+ end
+
+ for k, v in pairs(t1) do
+ t1[k] = nil;
+ end
+
+ tinsert(stack, t1);
+ return ...;
+ end
+
+
+ ------------------------------------------------------------------------------
+ --[[ Helpers Functions ]] --
+ ------------------------------------------------------------------------------
+ function Chronos.getArgTable(...)
+ if (select('#', ...) == 0) then
+ return Chronos.emptyTable;
+ else
+ return Chronos.getTable(...);
+ end
+ end
+
+ function Chronos.run(func, args)
+ if (func) then
+ if (args) then
+ return func(unpack(args));
+ else
+ return func();
+ end
+ end
+ end
+
+ function Chronos.printError(text)
+ ChatFrame1:AddMessage(text, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b, 1.0, UIERRORS_HOLD_TIME);
+ end
+
+ function Chronos.printDebugError(var, text)
+ if (var) and (getglobal(var)) then
+ Chronos.printError(text);
+ end
+ end
+
+ ------------------------------------------------------------------------------
+ --[[ Frame Script Helpers ]] --
+ ------------------------------------------------------------------------------
+ function Chronos.chatColorsInit()
+ ChronosData.chatColorsInitialized = true;
+ ChronosFrame:UnregisterEvent("UPDATE_CHAT_COLOR");
+ end
+
+ function Chronos.initCheck()
+ if (not ChronosData.initialized) then
+ if (UnitName("player") and UnitName("player") ~= UKNOWNBEING and UnitName("player") ~= UNKNOWNBEING and UnitName("player") ~= UNKNOWNOBJECT and ChronosData.variablesLoaded and ChronosData.enteredWorld and ChronosData.chatColorsInitialized) then
+ ChronosData.initialized = true;
+ Chronos.schedule(1, Chronos.initCheck);
+ return;
+ else
+ Chronos.schedule(0.2, Chronos.initCheck);
+ return;
+ end
+ end
+ if (ChronosData.afterInit) then
+ local i = ChronosData.afterInit_i;
+ if (not i) then
+ i = 1;
+ end
+ ChronosData.afterInit_i = i + 1;
+ --Chronos.printError("afterInit: processing ",i," of ",ChronosData.afterInit.n," initialization functions, id: ",ChronosData.afterInit[i].id);
+ Chronos.run(ChronosData.afterInit[i].func, ChronosData.afterInit[i].args);
+ if (i == #ChronosData.afterInit) then
+ for i, v in ipairs(ChronosData.afterInit) do
+ Chronos.releaseTable(v);
+ end
+ Chronos.releaseTable(ChronosData.afterInit);
+ ChronosData.afterInit = nil;
+ ChronosData.afterInit_i = nil;
+ else
+ Chronos.schedule(0.1, Chronos.initCheck);
+ return;
+ end
+ end
+ end
+
+ --[[
+ -- Sends a chat command through the standard editbox
+ --]]
+ function Chronos.SendChatCommand(command)
+ local text = ChatFrameEditBox:GetText();
+ ChatFrameEditBox:SetText(command);
+ ChatEdit_SendText(ChatFrameEditBox);
+ ChatFrameEditBox:SetText(text);
+ end
+
+ function Chronos.RegisterSlashCommands()
+ --Needs to be able Variables load if you want to use Sky
+ local chronosFunc = function(msg)
+ local _, _, seconds, command = string.find(msg, "([%d\.]+)%s+(.*)");
+ if (seconds and command) then
+ Chronos.schedule(seconds, Chronos.SendChatCommand, command);
+ else
+ Chronos.printError(SCHEDULE_USAGE1);
+ Chronos.printError(SCHEDULE_USAGE2);
+ end
+ end
+ if (Satellite) then
+ Satellite.registerSlashCommand({
+ id = "Schedule";
+ commands = SCHEDULE_COMM;
+ onExecute = chronosFunc;
+ helpText = SCHEDULE_DESC;
+ replace = true;
+ });
+ else
+ SlashCmdList["CHRONOS_SCHEDULE"] = chronosFunc;
+ for i = 1, #SCHEDULE_COMM do setglobal("SLASH_CHRONOS_SCHEDULE" .. i, SCHEDULE_COMM[i]); end
+ end
+ end
+
+ ------------------------------------------------------------------------------
+ --[[ Frame Scripts ]] --
+ ------------------------------------------------------------------------------
+ function Chronos.OnLoad()
+ Chronos.framecount = 0;
+
+ if (not ChronosData.byName) then
+ ChronosData.byName = {};
+ end
+ if (not ChronosData.repeating) then
+ ChronosData.repeating = {};
+ end
+ if (not ChronosData.sched) then
+ ChronosData.sched = {};
+ end
+ ChronosData.elapsedTime = 0;
+
+ Chronos.afterInit(Chronos.RegisterSlashCommands);
+ end
+
+ function Chronos.OnEvent(self, event, ...)
+ if (event == "ADDON_LOADED") then
+ ChronosData.variablesLoaded = true;
+ ChronosFrame:Show();
+ elseif (event == "PLAYER_ENTERING_WORLD") then
+ ChronosData.enteredWorld = true;
+ Chronos.online = true;
+ elseif (event == "PLAYER_LEAVING_WORLD") then
+ Chronos.online = false;
+ elseif (event == "UPDATE_CHAT_COLOR") then
+ Chronos.scheduleByName("ChronosAfterChatColorInit", 1, Chronos.chatColorsInit);
+ end
+ end
+
+ function Chronos.OnUpdate_Quick(self, arg1)
+ if (not Chronos.online) then
+ return;
+ end
+ if (not ChronosData.variablesLoaded) then
+ return;
+ end
+
+ if (ChronosData.elapsedTime) then
+ ChronosData.elapsedTime = ChronosData.elapsedTime + arg1;
+ else
+ ChronosData.elapsedTime = arg1;
+ end
+
+ -- Execute scheduled tasks that are ready, pulling them off the front of the list queue.
+ local now = GetTime();
+ local i;
+ local task;
+ while (#ChronosData.sched > 0) do
+ if (not ChronosData.sched[1].time) then
+ --Sea.io.printTable(ChronosData.sched[1]);
+ tremove(ChronosData.sched, 1);
+ elseif (ChronosData.sched[1].time <= now) then
+ task = tremove(ChronosData.sched, 1);
+ Chronos.run(task.handler, task.args);
+ Chronos.releaseTable(task);
+ else
+ break;
+ end
+ end
+
+ -- Execute named scheduled tasks that are ready.
+ local k, v = next(ChronosData.byName);
+ local newK, newV;
+ while (k ~= nil) do
+ newK, newV = next(ChronosData.byName, k);
+ if (not v.time) then
+ --Sea.io.printTable(v);
+ ChronosData.byName[k] = nil;
+ elseif (v.time <= now) then
+ if (v.repeating) then
+ ChronosData.byName[k].time = now + v.period;
+ v.handler();
+ else
+ Chronos.run(v.handler, v.args);
+ Chronos.releaseTable(ChronosData.byName[k]);
+ ChronosData.byName[k] = nil;
+ end
+ end
+ k, v = newK, newV;
+ end
+ end
+
+ function Chronos.OnUpdate_Debug(self, arg1)
+ if (not Chronos.online) then
+ return;
+ end
+ if (not ChronosData.variablesLoaded) then
+ return;
+ end
+ local memstart = collectgarbage("count");
+
+ if (ChronosData.elapsedTime) then
+ ChronosData.elapsedTime = ChronosData.elapsedTime + arg1;
+ else
+ ChronosData.elapsedTime = arg1;
+ end
+
+ local now = GetTime();
+ local i;
+ local task;
+ -- Execute scheduled tasks that are ready, popping them off the heap.
+ while (#ChronosData.sched > 0) do
+ if (ChronosData.sched[1].time <= now) then
+ task = tremove(ChronosData.sched, 1);
+ Chronos.run(task.handler, task.args);
+ Chronos.releaseTable(task);
+ else
+ break;
+ end
+ end
+
+ local memend = collectgarbage("count");
+ if (memend - memstart > 0) then
+ Chronos.printError("gcmemleak from ChronosData.sched in OnUpdate: " .. (memend - memstart));
+ end
+
+ -- Execute named scheduled tasks that are ready.
+ memstart = memend;
+ local k, v = next(ChronosData.byName);
+ local newK, newV;
+ while (k ~= nil) do
+ newK, newV = next(ChronosData.byName, k);
+ if (v.time <= now) then
+ local m = collectgarbage("count");
+ if (v.repeating) then
+ ChronosData.byName[k].time = now + v.period;
+ v.handler();
+ else
+ Chronos.run(v.handler, v.args);
+ Chronos.releaseTable(ChronosData.byName[k]);
+ ChronosData.byName[k] = nil;
+ end
+ local mm = collectgarbage("count");
+ memstart = memstart + mm - m;
+ end
+ k, v = newK, newV;
+ end
+
+ memend = collectgarbage("count");
+ if (memend - memstart > 0) then
+ Chronos.printError("gcmemleak from ChronosData.byName in OnUpdate: " .. (memend - memstart));
+ end
+ end
+
+ ------------------------------------------------------------------------------
+ --[[ Frame Script Assignment ]] --
+ ------------------------------------------------------------------------------
+
+ Chronos.OnUpdate_Quick();
+
+ --Event Driver
+ if (not ChronosFrame) then
+ CreateFrame("Frame", "ChronosFrame");
+ end
+ ChronosFrame:Hide();
+ --Event Registration
+ ChronosFrame:RegisterEvent("ADDON_LOADED");
+ ChronosFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
+ ChronosFrame:RegisterEvent("PLAYER_LEAVING_WORLD");
+ ChronosFrame:RegisterEvent("UPDATE_CHAT_COLOR");
+ --Frame Scripts
+ ChronosFrame:SetScript("OnEvent", Chronos.OnEvent);
+ ChronosFrame:SetScript("OnUpdate", Chronos.OnUpdate_Quick);
+ --OnLoad Call
+ Chronos.OnLoad();
+end
+
diff --git a/Chronos/Chronos.toc b/Chronos/Chronos.toc
new file mode 100644
index 0000000..52d3cb2
--- /dev/null
+++ b/Chronos/Chronos.toc
@@ -0,0 +1,7 @@
+## Interface: 20400
+## Title: Chronos
+## Notes: Embeddable Time Keeping and Scheduling System
+## Notes-deDE: Sammlung nützlicher Funktionen zum Zeitmanagement, welche von einigen anderen AddOns verwendet werden.
+## Author: Alexander Brazie, Thott, AnduinLothar
+## X-Website: http://www.wowinterface.com/downloads/info4328-Chronos.html
+Chronos.xml
\ No newline at end of file
diff --git a/Chronos/Chronos.xml b/Chronos/Chronos.xml
new file mode 100644
index 0000000..f727726
--- /dev/null
+++ b/Chronos/Chronos.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Chronos/localization.cn.lua b/Chronos/localization.cn.lua
new file mode 100644
index 0000000..a924cbb
--- /dev/null
+++ b/Chronos/localization.cn.lua
@@ -0,0 +1,10 @@
+--------------------------------------------------
+-- localization.cn.lua (Chinese)
+-- $LastChangedBy: Gryphon $
+-- $Date: 2007-02-02 16:41:28 -0600 (Fri, 02 Feb 2007) $
+-- Translation:
+
+if (GetLocale() == "zhCN") then
+
+ -- Please submit your translation to karlkfi@yahoo.com
+end
diff --git a/Chronos/localization.de.lua b/Chronos/localization.de.lua
new file mode 100644
index 0000000..8b6f2db
--- /dev/null
+++ b/Chronos/localization.de.lua
@@ -0,0 +1,14 @@
+--------------------------------------------------
+-- localization.de.lua (German)
+-- $LastChangedBy: Gryphon $
+-- $Date: 2007-02-02 16:41:28 -0600 (Fri, 02 Feb 2007) $
+-- Translation: pc, StarDust
+
+if (GetLocale() == "deDE") then
+
+ -- Chat Configuration
+ SCHEDULE_COMM = { "/in", "/pause", "/verz\195\182gern" };
+ SCHEDULE_DESC = "/in [ ...]";
+ SCHEDULE_USAGE1 = "Funktionsweise: /in [ ...] |cFFCC9966[Hinweis: /in KANN KEINE Zauber wirken um die Erstellung von Bots zu verhindern]|r";
+ SCHEDULE_USAGE2 = "Startet mit den Parametern nach Sekunden.";
+end
\ No newline at end of file
diff --git a/Chronos/localization.en.lua b/Chronos/localization.en.lua
new file mode 100644
index 0000000..9f25041
--- /dev/null
+++ b/Chronos/localization.en.lua
@@ -0,0 +1,13 @@
+--------------------------------------------------
+-- localization.en.lua (English)
+-- $LastChangedBy: Gryphon $
+-- $Date: 2007-02-02 16:41:28 -0600 (Fri, 02 Feb 2007) $
+-- Translation:
+
+-- Default Locale enGB
+
+-- Chat Configuration
+SCHEDULE_COMM = { "/in", "/pause", "/delay" };
+SCHEDULE_DESC = "/in [ ...] |cFFCC9966[Note: /in CANNOT cast spells to prevent creation of bots]|r";
+SCHEDULE_USAGE1 = "Usage: /in [ ...]";
+SCHEDULE_USAGE2 = "Runs with arguments after seconds pass.";
\ No newline at end of file
diff --git a/Chronos/localization.es.lua b/Chronos/localization.es.lua
new file mode 100644
index 0000000..7dadfc1
--- /dev/null
+++ b/Chronos/localization.es.lua
@@ -0,0 +1,14 @@
+--------------------------------------------------
+-- localization.es.lua (Spanish)
+-- $LastChangedBy: Gryphon $
+-- $Date: 2007-02-02 16:41:28 -0600 (Fri, 02 Feb 2007) $
+-- Translation: NeKRoMaNT
+
+if (GetLocale() == "esES") then
+
+ -- Chat Configuration
+ SCHEDULE_COMM = { "/in", "/pause", "/delay" };
+ SCHEDULE_DESC = "/in [ ...] |cFFCC9966[Nota: /in NO puede realizar hechizos para evitar la creaci�n de bots]|r";
+ SCHEDULE_USAGE1 = "Uso: /in [ ...]";
+ SCHEDULE_USAGE2 = "Ejecuta con argumentos tras segundos.";
+end
diff --git a/Chronos/localization.fr.lua b/Chronos/localization.fr.lua
new file mode 100644
index 0000000..60406b7
--- /dev/null
+++ b/Chronos/localization.fr.lua
@@ -0,0 +1,14 @@
+--------------------------------------------------
+-- localization.fr.lua (French)
+-- $LastChangedBy: Gryphon $
+-- $Date: 2007-02-02 16:41:28 -0600 (Fri, 02 Feb 2007) $
+-- Translation: Vjeux, Sasmira
+
+if (GetLocale() == "frFR") then
+
+ -- Chat Configuration
+ SCHEDULE_COMM = { "/in", "/pause", "/delay" };
+ SCHEDULE_DESC = "/in [ ...] |cFFCC9966[Note: /in NE PEUT PAS lancer de sorts pour emp\195\170cher la cr\195\169ation de bots]|r";
+ SCHEDULE_USAGE1 = "Utilisation : /in [ ...]";
+ SCHEDULE_USAGE2 = "Lance la avec les arguments apr\195\168s secondes.";
+end
\ No newline at end of file
diff --git a/Chronos/localization.kr.lua b/Chronos/localization.kr.lua
new file mode 100644
index 0000000..485cb64
--- /dev/null
+++ b/Chronos/localization.kr.lua
@@ -0,0 +1,10 @@
+--------------------------------------------------
+-- localization.kr.lua (Korean)
+-- $LastChangedBy: Gryphon $
+-- $Date: 2007-02-02 16:41:28 -0600 (Fri, 02 Feb 2007) $
+-- Translation:
+
+if (GetLocale() == "koKR") then
+
+ -- Please submit your translation to karlkfi@yahoo.com
+end
diff --git a/Chronos/localization.ru.lua b/Chronos/localization.ru.lua
new file mode 100644
index 0000000..fa1c5f9
--- /dev/null
+++ b/Chronos/localization.ru.lua
@@ -0,0 +1,10 @@
+--------------------------------------------------
+-- localization.ru.lua (Russian)
+-- $LastChangedBy: Gryphon $
+-- $Date: 2007-02-02 16:41:28 -0600 (Fri, 02 Feb 2007) $
+-- Translation:
+
+if (GetLocale() == "ruRU") then
+
+ -- Please submit your translation to karlkfi@yahoo.com
+end
diff --git a/Chronos/localization.tw.lua b/Chronos/localization.tw.lua
new file mode 100644
index 0000000..6f3296d
--- /dev/null
+++ b/Chronos/localization.tw.lua
@@ -0,0 +1,10 @@
+--------------------------------------------------
+-- localization.tw.lua (Chinese Traditional)
+-- $LastChangedBy: Gryphon $
+-- $Date: 2007-02-02 16:41:28 -0600 (Fri, 02 Feb 2007) $
+-- Translation:
+
+if (GetLocale() == "zhTW") then
+
+ -- Please submit your translation to karlkfi@yahoo.com
+end
diff --git a/GMGenie red.xml b/GMGenie red.xml
new file mode 100644
index 0000000..4cff1e7
--- /dev/null
+++ b/GMGenie red.xml
@@ -0,0 +1,493 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetTextInsets(5, 5, 0, 2);
+ self:SetBackdropColor(0,0,0);
+
+
+ self:ClearFocus();
+
+
+ self:ClearFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetBackdropColor(0,0,0);
+
+
+
+
+
+
+ self:GetParent():SetWidth(self:GetParent():GetParent():GetWidth());
+ self:GetParent():SetHeight(self:GetParent():GetParent():GetHeight());
+ self:SetWidth(self:GetParent():GetParent():GetWidth());
+ self:SetHeight(self:GetParent():GetParent():GetHeight());
+ self:SetTextInsets(5, 5, 5, 5);
+
+
+ ScrollingEdit_OnTextChanged(self, self:GetParent());
+
+
+ ScrollingEdit_OnCursorChanged(self, x, y-10, w, h);
+
+
+ ScrollingEdit_OnUpdate(self, elapsed, self:GetParent());
+
+
+ self:ClearFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetBackdropColor(0,0,0);
+
+ CloseDropDownMenus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HideUIPanel(GMGenie_Tooltip);
+
+
+
+
+
+
+
+
+
+ GameTooltip_OnLoad(self);
+ self:SetPadding(16);
+ self:RegisterForDrag("LeftButton");
+
+
+ self:StartMoving();
+
+
+ self:StopMovingOrSizing();
+ ValidateFramePosition(self);
+
+
+ GameTooltip_OnHide(self);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.minimap.draggingFrame_OnUpdate();
+
+
+
+
+
+
+ self:RegisterForClicks("LeftButtonUp","RightButtonUp");
+ self:RegisterForDrag("LeftButton","RightButton");
+
+
+ self:LockHighlight();
+ GMGenie_Minimap_DraggingFrame:Show();
+
+
+ self:UnlockHighlight()
+ GMGenie_Minimap_DraggingFrame:Hide();
+
+
+ GMGenie.Hud.toggle();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GMGenie.lua b/GMGenie.lua
new file mode 100644
index 0000000..e65a521
--- /dev/null
+++ b/GMGenie.lua
@@ -0,0 +1,127 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie = {};
+GMGenie_SavedVars = {};
+
+function GMGenie.showGMMessage(msg)
+ DEFAULT_CHAT_FRAME:AddMessage("|cFFFF0000[GMGenie]|cffffffff: " .. msg);
+end
+
+function GMGenie.pairsByKeys(t, f)
+ local a = {}
+ local b = {}
+ for n in pairs(t) do
+ table.insert(a, n);
+ end
+ table.sort(a, f);
+ for name, value in pairs(a) do
+ table.insert(b, t[value]);
+ end
+ return b;
+end
+
+function GMGenie.pairsByKeys2(t, f)
+ local a = {}
+ local b = {}
+ for n in pairs(t) do
+ table.insert(a, n);
+ end
+ table.sort(a, f);
+ for name, value in pairs(a) do
+ table.insert(b, value);
+ end
+ return b;
+end
+
+function GMGenie.onLoad()
+ GMGenie.loadSettings();
+
+ GMGenie.Hud.onLoad();
+
+ GMGenie.Macros.onLoad();
+ GMGenie.Spawns.onLoad();
+
+ UIDropDownMenu_Initialize(GMGenie_Spy_InfoWindow_DropdownbuttonsTwo, GMGenie.Spy.loadDropdown, "MENU");
+
+ GMGenie.optionsOnLoad();
+ GMGenie.Tickets.optionsOnLoad();
+ GMGenie.Macros.Whispers.optionsOnLoad();
+ GMGenie.Macros.Mail.optionsOnLoad();
+ GMGenie.Macros.Tele.optionsOnLoad();
+ GMGenie.Macros.Discipline.optionsOnLoad()
+ GMGenie.Spawns.optionsOnLoad();
+
+ GMGenie.minimap.reposition();
+ GMGenie.Tickets.onLoad();
+
+ -- Please do not remove the copyright notice, it would be a violation of the gpl.
+ GMGenie.showGMMessage("GMGenie 0.7.3 by Chocochaos ((c) 2011-2014). The latest version of GM Genie can always be found at http://chocochaos.com/gmgenie/");
+end
+
+local frame = CreateFrame("FRAME");
+frame:RegisterEvent("ADDON_LOADED");
+
+function frame:OnEvent(event, arg1)
+ if event == "ADDON_LOADED" and arg1 == "GMGenie" then
+ GMGenie.onLoad();
+ end
+end
+
+frame:SetScript("OnEvent", frame.OnEvent);
+
+GMGenie.minimap = {};
+
+-- add this to your SavedVariables or as a separate SavedVariable to store its position
+
+
+-- Call this in a mod's initialization to move the minimap button to its saved position (also used in its movement)
+-- ** do not call from the mod's OnLoad, VARIABLES_LOADED or later is fine. **
+function GMGenie.minimap.reposition()
+ GMGenie_Minimap:SetPoint("TOPLEFT", "Minimap", "TOPLEFT", 52 - (80 * cos(GMGenie_SavedVars.minimapPos)), (80 * sin(GMGenie_SavedVars.minimapPos)) - 52)
+end
+
+-- Only while the button is dragged this is called every frame
+function GMGenie.minimap.draggingFrame_OnUpdate()
+ local xpos, ypos = GetCursorPosition()
+ local xmin, ymin = Minimap:GetLeft(), Minimap:GetBottom()
+
+ xpos = xmin - xpos / UIParent:GetScale() + 70 -- get coordinates as differences from the center of the minimap
+ ypos = ypos / UIParent:GetScale() - ymin - 70
+
+ GMGenie_SavedVars.minimapPos = math.deg(math.atan2(ypos, xpos)) -- save the degrees we are relative to the minimap center
+ GMGenie.minimap.reposition() -- move the button
+end
+
+function GMGenie.loadWindow(window, title, refresh, refreshScript)
+ local name = window:GetName();
+ window:RegisterForClicks("LeftButtonUp", "RightButtonUp");
+ getglobal(name .. "_Title_Text"):SetText(title);
+ if refresh then
+ getglobal(name .. '_Refresh'):Show();
+ getglobal(name .. '_Title'):SetWidth(window:GetWidth() - 32);
+ if refreshScript then
+ getglobal(name .. '_Refresh'):SetScript("OnClick", refreshScript);
+ end
+ else
+ getglobal(name .. '_Refresh'):Hide();
+ getglobal(name .. '_Title'):SetWidth(window:GetWidth() - 16);
+ end
+
+ getglobal(name .. '_Main'):SetWidth(window:GetWidth());
+ getglobal(name .. '_Main'):SetHeight(window:GetHeight() - 14);
+end
+
+function GMGenie.loadEditBox(window)
+ local name = window:GetName();
+
+ getglobal(name .. '_Frame_Text'):SetTextInsets(5, 5, 5, 5);
+ getglobal(name .. '_Frame'):SetWidth(window:GetWidth());
+ getglobal(name .. '_Frame'):SetHeight(window:GetHeight());
+ getglobal(name .. '_Frame_Text'):SetWidth(getglobal(name .. '_Frame'):GetWidth());
+ getglobal(name .. '_Frame_Text'):SetHeight(getglobal(name .. '_Frame'):GetHeight());
+end
\ No newline at end of file
diff --git a/GMGenie.toc b/GMGenie.toc
new file mode 100644
index 0000000..5bed6ce
--- /dev/null
+++ b/GMGenie.toc
@@ -0,0 +1,47 @@
+# This file is part of Game Master Genie.
+# Copyright 2011-2014 Chocochaos
+#
+# Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+# Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+## Interface: 40300
+## Title: GM Genie
+## Note: Game Master Genie v0.7.3 by Chocochaos
+## Author: Chocochaos
+## Version: 0.7.3
+## DefaultState: Enabled
+## SavedVariables: GMGenie_SavedVars
+GMGenie.xml
+Chronos\Chronos.xml
+GMGenie.lua
+Savedvariables.lua
+Chatreader.lua
+Hud.lua
+Hud.xml
+Macros.lua
+Macros.Discipline.lua
+Macros.Mail.lua
+Macros.Tele.lua
+Macros.Whispers.lua
+Macros.Whispers.xml
+Tickets.lua
+Tickets.xml
+Spawns.lua
+Spawns.xml
+Spy.lua
+Spy.xml
+Options\GMGenie.lua
+Options\GMGenie.xml
+Options\Tickets.lua
+Options\Tickets.xml
+Options\Macros.Discipline.lua
+Options\Macros.Discipline.xml
+Options\Macros.Mail.lua
+Options\Macros.Mail.xml
+Options\Macros.Tele.lua
+Options\Macros.Tele.xml
+Options\Macros.Whispers.lua
+Options\Macros.Whispers.xml
+Options\Spawns.lua
+Options\Spawns.xml
\ No newline at end of file
diff --git a/GMGenie.xml b/GMGenie.xml
new file mode 100644
index 0000000..9535d4c
--- /dev/null
+++ b/GMGenie.xml
@@ -0,0 +1,440 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HideUIPanel(self:GetParent());
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:StartMoving();
+ self:StopMovingOrSizing();
+ self:StopMovingOrSizing();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetTextInsets(5, 5, 0, 2);
+ self:SetBackdropColor(0,0,0);
+
+
+ self:ClearFocus();
+
+
+ self:ClearFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetBackdropColor(0,0,0);
+
+
+
+
+
+
+ ScrollingEdit_OnTextChanged(self, self:GetParent());
+
+
+ ScrollingEdit_OnCursorChanged(self, x, y-10, w, h);
+
+
+ ScrollingEdit_OnUpdate(self, elapsed, self:GetParent());
+
+
+ self:ClearFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetBackdropColor(0,0,0);
+
+ CloseDropDownMenus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HideUIPanel(GMGenie_Tooltip);
+
+
+
+
+
+
+
+
+
+ GameTooltip_OnLoad(self);
+ self:SetPadding(16);
+ self:RegisterForDrag("LeftButton");
+
+
+ self:StartMoving();
+
+
+ self:StopMovingOrSizing();
+ ValidateFramePosition(self);
+
+
+ GameTooltip_OnHide(self);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.minimap.draggingFrame_OnUpdate();
+
+
+
+
+
+
+ self:RegisterForClicks("LeftButtonUp","RightButtonUp");
+ self:RegisterForDrag("LeftButton","RightButton");
+
+
+ self:LockHighlight();
+ GMGenie_Minimap_DraggingFrame:Show();
+
+
+ self:UnlockHighlight()
+ GMGenie_Minimap_DraggingFrame:Hide();
+
+
+ GMGenie.Hud.toggle();
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Hud.lua b/Hud.lua
new file mode 100644
index 0000000..dcdc84a
--- /dev/null
+++ b/Hud.lua
@@ -0,0 +1,167 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Hud = {};
+
+function GMGenie.Hud.onLoad()
+ GMGenie_Hud:RegisterEvent("PLAYER_ENTERING_WORLD");
+ GMGenie_Hud:RegisterEvent("UI_ERROR_MESSAGE");
+ GMGenie_Hud:SetScript("OnEvent", GMGenie.Hud.readNotice);
+
+ GMGenie_Hud_GM:SetAttribute("macrotext1", "/run GMGenie.Hud.toggleGm();");
+ GMGenie_Hud_Chat:SetAttribute("macrotext1", "/run GMGenie.Hud.toggleChat();");
+ GMGenie_Hud_Visibility:SetAttribute("macrotext1", "/run GMGenie.Hud.toggleVisibility();");
+ GMGenie_Hud_Whisper:SetAttribute("macrotext1", "/run GMGenie.Hud.toggleWhisper();");
+ GMGenie_Hud_Fly:SetAttribute("macrotext1", "/target " .. UnitName("player") .. " \n/run GMGenie.Hud.toggleFly();");
+
+ if GMGenie_SavedVars.hudClosed then
+ GMGenie.Hud.toggle();
+ end
+
+ Chronos.schedule(1, GMGenie.Hud.checkStatus);
+ GMGenie.Hud.flyStatus(false);
+end
+
+function GMGenie.Hud.toggle()
+ if GMGenie_Hud:IsVisible() then
+ GMGenie_Hud:Hide();
+ GMGenie_SavedVars.hudClosed = true;
+ else
+ GMGenie_Hud:Show();
+ GMGenie_SavedVars.hudClosed = false;
+ end
+end
+
+--------------------------------------------------
+------------ HUD status functionality ------------
+--------------------------------------------------
+function GMGenie.Hud.checkStatus()
+ SendChatMessage(".gm", "GUILD");
+ SendChatMessage(".gm chat", "GUILD");
+ SendChatMessage(".gm visible", "GUILD");
+ SendChatMessage(".whispers", "GUILD");
+end
+
+function GMGenie.Hud.gmStatus(status)
+ GMGenie.Hud.gm = status;
+ if status then
+ GMGenie_Hud_GM:SetText("|cffffffffGM mode ON|r");
+ else
+ GMGenie_Hud_GM:SetText("|cffbfbfffGM mode OFF|r");
+ end
+end
+
+function GMGenie.Hud.chatStatus(status)
+ GMGenie.Hud.chat = status;
+ if status then
+ GMGenie_Hud_Chat:SetText("|cffffffffChat badge ON|r");
+ else
+ GMGenie_Hud_Chat:SetText("|cffbfbfffChat badge OFF|r");
+ end
+end
+
+function GMGenie.Hud.visibilityStatus(status)
+ GMGenie.Hud.visibility = status;
+ if status then
+ GMGenie_Hud_Visibility:SetText("|cffffffffYou are VISIBLE|r");
+ else
+ GMGenie_Hud_Visibility:SetText("|cffbfbfffYou are INVISIBLE|r");
+ end
+end
+
+function GMGenie.Hud.whisperStatus(status)
+ GMGenie.Hud.whisper = status;
+ if status then
+ GMGenie_Hud_Whisper:SetText("|cffffffffWhispers are ON|r");
+ else
+ GMGenie_Hud_Whisper:SetText("|cffbfbfffWhispers are OFF|r");
+ end
+end
+
+function GMGenie.Hud.flyStatus(status)
+ GMGenie.Hud.fly = status;
+ if status then
+ GMGenie_Hud_Fly:SetText("|cffffffffFlight mode ON|r");
+ else
+ GMGenie_Hud_Fly:SetText("|cffbfbfffFlight mode OFF|r");
+ end
+end
+
+function GMGenie.Hud.readNotice(self, event, notice)
+ if event == "UI_ERROR_MESSAGE" then
+ if notice == "GM mode is ON" then
+ GMGenie.Hud.gmStatus(true);
+ elseif notice == "GM mode is OFF" then
+ GMGenie.Hud.gmStatus(false);
+ elseif notice == "GM Chat Badge is ON" then
+ GMGenie.Hud.chatStatus(true);
+ elseif notice == "GM Chat Badge is OFF" then
+ GMGenie.Hud.chatStatus(false);
+ elseif notice == "You are now visible." then
+ GMGenie.Hud.visibilityStatus(true);
+ elseif notice == "You are now invisible." then
+ GMGenie.Hud.visibilityStatus(false);
+ GMGenie.Hud.toggleWhisper(GMGenie.Hud.whisper);
+ end
+ elseif event == "PLAYER_ENTERING_WORLD" and GMGenie.Hud.fly == true then
+ GMGenie.Hud.toggleFly(GMGenie.Hud.fly);
+ end
+end
+
+function GMGenie.Hud.toggleGm(status)
+ if (not GMGenie.Hud.gm and status == nil) or status == true then
+ SendChatMessage(".gm on", "GUILD");
+ else
+ SendChatMessage(".gm off", "GUILD");
+ end
+end
+
+function GMGenie.Hud.toggleChat(status)
+ if (not GMGenie.Hud.chat and status == nil) or status == true then
+ SendChatMessage(".gm chat on", "GUILD");
+ else
+ SendChatMessage(".gm chat off", "GUILD");
+ end
+end
+
+function GMGenie.Hud.toggleVisibility(status)
+ if (not GMGenie.Hud.visibility and status == nil) or status == true then
+ SendChatMessage(".gm visible on", "GUILD");
+ else
+ SendChatMessage(".gm visible off", "GUILD");
+ end
+end
+
+function GMGenie.Hud.toggleWhisper(status)
+ if (not GMGenie.Hud.whisper and status == nil) or status == true then
+ SendChatMessage(".whispers on", "GUILD");
+ else
+ SendChatMessage(".whispers off", "GUILD");
+ end
+end
+
+function GMGenie.Hud.toggleFly(status)
+ if UnitName("target") == UnitName("player") or UnitName("target") == nil then
+ if (not GMGenie.Hud.fly and status == nil) or status == true then
+ SendChatMessage(".gm fly on", "GUILD");
+ else
+ SendChatMessage(".gm fly off", "GUILD");
+ end
+ else
+ GMGenie.showGMMessage("Could not target self to change flight mode.");
+ end
+end
+
+function GMGenie.Hud.setSpeed()
+ if UnitName("target") == UnitName("player") or UnitName("target") == nil then
+ local speed = GMGenie_Hud_Speed:GetText();
+ GMGenie_Hud_Speed:ClearFocus();
+ SendChatMessage(".mod speed all " .. speed, "GUILD");
+ else
+ GMGenie.showGMMessage("Be sure to target yourself before setting the speed.");
+ end
+end
\ No newline at end of file
diff --git a/Hud.xml b/Hud.xml
new file mode 100644
index 0000000..ca9b654
--- /dev/null
+++ b/Hud.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadWindow(self, 'GM Genie', true, function() GMGenie.Hud.checkStatus(); end);
+
+
+ self:ClearAllPoints();
+ self:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Hud.setSpeed();
+
+
+
+
+
+
+
+
+
+ GMGenie.Hud.setSpeed();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.toggle();
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.toggle();
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Macros.Discipline.lua b/Macros.Discipline.lua
new file mode 100644
index 0000000..aaccefe
--- /dev/null
+++ b/Macros.Discipline.lua
@@ -0,0 +1,269 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Macros.Discipline = {};
+GMGenie.Macros.Discipline.Mute = {};
+GMGenie.Macros.Discipline.CharBan = {};
+GMGenie.Macros.Discipline.AccBan = {};
+GMGenie.Macros.Discipline.IpBan = {};
+
+function GMGenie.Macros.Discipline.Mute.run(name, title)
+ if GMGenie_SavedVars.mute[title]["announceToServer"] then
+ SendChatMessage('.name ' .. name .. ' has been muted for ' .. GMGenie_SavedVars.mute[title]["duration"] .. ' minutes. Reason: ' .. GMGenie_SavedVars.mute[title]["reason"], "GUILD");
+ else
+ SendChatMessage('.gmname ' .. name .. ' has been muted for ' .. GMGenie_SavedVars.mute[title]["duration"] .. ' minutes. Reason: ' .. GMGenie_SavedVars.mute[title]["reason"], "GUILD");
+ end
+ SendChatMessage('.mute ' .. name .. ' ' .. GMGenie_SavedVars.mute[title]["duration"] .. ' ' .. GMGenie_SavedVars.mute[title]["reason"], "GUILD");
+end
+
+function GMGenie.Macros.Discipline.Mute.runFromSpy(self)
+ CloseDropDownMenus();
+ if GMGenie.Spy.currentRequest["name"] then
+ GMGenie.Macros.Discipline.Mute.run(GMGenie.Spy.currentRequest["name"], self.value);
+ end
+end
+
+function GMGenie.Macros.Discipline.Mute.addToUnitMenu()
+ UnitPopupMenus["GMGenie_Mute"] = {};
+ local MuteTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.mute);
+ for index, name in pairs(MuteTemp) do
+ table.insert(UnitPopupMenus["GMGenie_Mute"], "GMGenie_Mute_" .. name);
+ UnitPopupButtons["GMGenie_Mute_" .. name] = { text = name, dist = 0, };
+ end
+
+ table.insert(UnitPopupMenus["GMGenie_Mute"], "GMGenie_DisciplineOptions");
+ UnitPopupButtons["GMGenie_DisciplineOptions"] = { text = "Manage macros", dist = 0, };
+end
+
+function GMGenie.Macros.Discipline.Mute.loadDropdown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.isTitle = true;
+ info.text = "Mutes";
+ UIDropDownMenu_AddButton(info, level);
+
+ local MuteTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.mute);
+ for index, name in pairs(MuteTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Macros.Discipline.Mute.runFromSpy;
+ info.value = name;
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Macros";
+ info.func = GMGenie.Macros.Discipline.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+
+
+function GMGenie.Macros.Discipline.CharBan.run(name, title)
+ if GMGenie_SavedVars.charBan[title]["announceToServer"] then
+ SendChatMessage('.name ' .. name .. ' has been banned for ' .. GMGenie_SavedVars.charBan[title]["duration"] .. '. Reason: ' .. GMGenie_SavedVars.charBan[title]["reason"], "GUILD");
+ else
+ SendChatMessage('.gmname ' .. name .. ' has been banned for ' .. GMGenie_SavedVars.charBan[title]["duration"] .. '. Reason: ' .. GMGenie_SavedVars.charBan[title]["reason"], "GUILD");
+ end
+ SendChatMessage('.ban char ' .. name .. ' ' .. GMGenie_SavedVars.charBan[title]["duration"] .. ' ' .. GMGenie_SavedVars.charBan[title]["reason"], "GUILD");
+end
+
+function GMGenie.Macros.Discipline.CharBan.runFromSpy(self)
+ CloseDropDownMenus();
+ if GMGenie.Spy.currentRequest["name"] then
+ GMGenie.Macros.Discipline.CharBan.run(GMGenie.Spy.currentRequest["name"], self.value);
+ end
+end
+
+function GMGenie.Macros.Discipline.CharBan.addToUnitMenu()
+ UnitPopupMenus["GMGenie_CharBan"] = {};
+ local CharBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.charBan);
+ for index, name in pairs(CharBanTemp) do
+ table.insert(UnitPopupMenus["GMGenie_CharBan"], "GMGenie_CharBan_" .. name);
+ UnitPopupButtons["GMGenie_CharBan_" .. name] = { text = name, dist = 0, };
+ end
+
+ table.insert(UnitPopupMenus["GMGenie_CharBan"], "GMGenie_DisciplineOptions");
+ UnitPopupButtons["GMGenie_DisciplineOptions"] = { text = "Manage macros", dist = 0, };
+end
+
+function GMGenie.Macros.Discipline.CharBan.loadDropdown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.isTitle = true;
+ info.text = "Character Bans";
+ UIDropDownMenu_AddButton(info, level);
+
+ local CharBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.charBan);
+ for index, name in pairs(CharBanTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Macros.Discipline.CharBan.runFromSpy;
+ info.value = name;
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Macros";
+ info.func = GMGenie.Macros.Discipline.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+
+
+function GMGenie.Macros.Discipline.AccBan.run(name, title)
+ if GMGenie_SavedVars.accBan[title]["announceToServer"] then
+ SendChatMessage('.name ' .. name .. ' has been account banned for ' .. GMGenie_SavedVars.accBan[title]["duration"] .. '. Reason: ' .. GMGenie_SavedVars.accBan[title]["reason"], "GUILD");
+ else
+ SendChatMessage('.gmname ' .. name .. ' has been account banned for ' .. GMGenie_SavedVars.accBan[title]["duration"] .. '. Reason: ' .. GMGenie_SavedVars.accBan[title]["reason"], "GUILD");
+ end
+ SendChatMessage('.ban playeraccount ' .. name .. ' ' .. GMGenie_SavedVars.accBan[title]["duration"] .. ' ' .. GMGenie_SavedVars.accBan[title]["reason"], "GUILD");
+end
+
+function GMGenie.Macros.Discipline.AccBan.runFromSpy(self)
+ CloseDropDownMenus();
+ if GMGenie.Spy.currentRequest["name"] then
+ GMGenie.Macros.Discipline.AccBan.run(GMGenie.Spy.currentRequest["name"], self.value);
+ end
+end
+
+function GMGenie.Macros.Discipline.AccBan.addToUnitMenu()
+ UnitPopupMenus["GMGenie_AccBan"] = {};
+ local AccBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.accBan);
+ for index, name in pairs(AccBanTemp) do
+ table.insert(UnitPopupMenus["GMGenie_AccBan"], "GMGenie_AccBan_" .. name);
+ UnitPopupButtons["GMGenie_AccBan_" .. name] = { text = name, dist = 0, };
+ end
+
+ table.insert(UnitPopupMenus["GMGenie_AccBan"], "GMGenie_DisciplineOptions");
+ UnitPopupButtons["GMGenie_DisciplineOptions"] = { text = "Manage macros", dist = 0, };
+end
+
+function GMGenie.Macros.Discipline.AccBan.loadDropdown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.isTitle = true;
+ info.text = "Account Bans";
+ UIDropDownMenu_AddButton(info, level);
+
+ local AccBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.accBan);
+ for index, name in pairs(AccBanTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Macros.Discipline.AccBan.runFromSpy;
+ info.value = name;
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Macros";
+ info.func = GMGenie.Macros.Discipline.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+
+
+
+
+
+
+
+
+
+GMGenie.Macros.Discipline.IpBan.name = false;
+GMGenie.Macros.Discipline.IpBan.duration = false;
+GMGenie.Macros.Discipline.IpBan.reason = false;
+GMGenie.Macros.Discipline.IpBan.announceToServer = false;
+
+function GMGenie.Macros.Discipline.IpBan.processPin(ip)
+ GMGenie.Macros.Discipline.IpBan.waitingForPin = false;
+
+ if GMGenie.Macros.Discipline.IpBan.announceToServer then
+ SendChatMessage('.name ' .. GMGenie.Macros.Discipline.IpBan.name .. ' has been ip banned for ' .. GMGenie.Macros.Discipline.IpBan.duration .. '. Reason: ' .. GMGenie.Macros.Discipline.IpBan.reason, "GUILD");
+ end
+ SendChatMessage('.gmname ' .. GMGenie.Macros.Discipline.IpBan.name .. ' has been ip banned (' .. ip .. ') for ' .. GMGenie.Macros.Discipline.IpBan.duration .. '. Reason: ' .. GMGenie.Macros.Discipline.IpBan.reason, "GUILD");
+
+ SendChatMessage('.ban ip ' .. ip .. " " .. GMGenie.Macros.Discipline.IpBan.duration .. " " .. GMGenie.Macros.Discipline.IpBan.reason, "GUILD");
+ Chronos.unscheduleByName('ipbanprotection');
+end
+
+function GMGenie.Macros.Discipline.IpBan.fail()
+ GMGenie.Macros.Discipline.IpBan.waitingForPin = false;
+ GMGenie.showGMMessage("IP ban on " .. GMGenie.Macros.Discipline.IpBan.name .. " failed. This could be due to server lag. Please try again.");
+end
+
+function GMGenie.Macros.Discipline.IpBan.run(name, title)
+ GMGenie.Macros.Discipline.IpBan.waitingForPin = true;
+ SendChatMessage('.pin ' .. name, "GUILD");
+ GMGenie.Macros.Discipline.IpBan.name = name;
+ GMGenie.Macros.Discipline.IpBan.duration = GMGenie_SavedVars.ipBan[title]["duration"];
+ GMGenie.Macros.Discipline.IpBan.reason = GMGenie_SavedVars.ipBan[title]["reason"];
+ GMGenie.Macros.Discipline.IpBan.announceToServer = GMGenie_SavedVars.ipBan[title]["announceToServer"];
+
+ Chronos.scheduleByName('ipbanprotection', 2, GMGenie.Macros.Discipline.IpBan.fail);
+end
+
+function GMGenie.Macros.Discipline.IpBan.runFromSpy(self)
+ CloseDropDownMenus();
+ if GMGenie.Spy.currentRequest["name"] then
+ GMGenie.Macros.Discipline.IpBan.run(GMGenie.Spy.currentRequest["name"], self.value);
+ end
+end
+
+function GMGenie.Macros.Discipline.IpBan.addToUnitMenu()
+ UnitPopupMenus["GMGenie_IpBan"] = {};
+ local IpBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.ipBan);
+ for index, name in pairs(IpBanTemp) do
+ table.insert(UnitPopupMenus["GMGenie_IpBan"], "GMGenie_IpBan_" .. name);
+ UnitPopupButtons["GMGenie_IpBan_" .. name] = { text = name, dist = 0, };
+ end
+
+ table.insert(UnitPopupMenus["GMGenie_IpBan"], "GMGenie_DisciplineOptions");
+ UnitPopupButtons["GMGenie_DisciplineOptions"] = { text = "Manage macros", dist = 0, };
+end
+
+function GMGenie.Macros.Discipline.IpBan.loadDropdown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.isTitle = true;
+ info.text = "Ip Bans";
+ UIDropDownMenu_AddButton(info, level);
+
+ local IpBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.ipBan);
+ for index, name in pairs(IpBanTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Macros.Discipline.IpBan.runFromSpy;
+ info.value = name;
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Macros";
+ info.func = GMGenie.Macros.Discipline.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
\ No newline at end of file
diff --git a/Macros.Mail.lua b/Macros.Mail.lua
new file mode 100644
index 0000000..e5f1cbb
--- /dev/null
+++ b/Macros.Mail.lua
@@ -0,0 +1,73 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Macros.Mail = {};
+
+GMGenie.Macros.Mail.curMailMessage = '';
+
+
+function GMGenie.Macros.Mail.run(name, title)
+ local text = GMGenie_SavedVars.mail[title].macro;
+ local text = string.gsub(text, "NAME", name);
+ local lines = { strsplit("\n", text) };
+ local subject = GMGenie_SavedVars.mail[title].subject;
+
+ for index, line in pairs(lines) do
+ local command = '.send mail ' .. name .. ' "' .. subject;
+ if #lines > 1 then
+ command = command .. ' ' .. index .. '/' .. (#lines);
+ end
+ local command = command .. '" "' .. line .. '"';
+ SendChatMessage(command, "GUILD");
+ end
+end
+
+function GMGenie.Macros.Mail.runFromSpy(self)
+ CloseDropDownMenus();
+ if GMGenie.Spy.currentRequest["name"] then
+ GMGenie.Macros.Mail.run(GMGenie.Spy.currentRequest["name"], self.value);
+ end
+end
+
+function GMGenie.Macros.Mail.addToUnitMenu()
+ UnitPopupMenus["GMGenie_Mail"] = {};
+ local MailTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.mail);
+ for index, name in pairs(MailTemp) do
+ table.insert(UnitPopupMenus["GMGenie_Mail"], "GMGenie_Mail_" .. name);
+ UnitPopupButtons["GMGenie_Mail_" .. name] = { text = name, dist = 0, };
+ end
+
+ table.insert(UnitPopupMenus["GMGenie_Mail"], "GMGenie_MailOptions");
+ UnitPopupButtons["GMGenie_MailOptions"] = { text = "Manage macros", dist = 0, };
+end
+
+function GMGenie.Macros.Mail.loadDropdown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.isTitle = true;
+ info.text = "Mail Macros";
+ UIDropDownMenu_AddButton(info, level);
+
+ local MailTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.mail);
+ for index, name in pairs(MailTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Macros.Mail.runFromSpy;
+ info.value = name;
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Macros";
+ info.func = GMGenie.Macros.Mail.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
\ No newline at end of file
diff --git a/Macros.Tele.lua b/Macros.Tele.lua
new file mode 100644
index 0000000..dae9a23
--- /dev/null
+++ b/Macros.Tele.lua
@@ -0,0 +1,62 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Macros.Tele = {};
+
+function GMGenie.Macros.Tele.run(name, title)
+ if GMGenie_SavedVars.tele[title] == "RECALL" then
+ SendChatMessage('.recall ' .. name, "GUILD");
+ else
+ SendChatMessage('.tele name ' .. name .. ' ' .. GMGenie_SavedVars.tele[title], "GUILD");
+ end
+end
+
+function GMGenie.Macros.Tele.runFromSpy(self)
+ CloseDropDownMenus();
+ if GMGenie.Spy.currentRequest["name"] then
+ GMGenie.Macros.Tele.run(GMGenie.Spy.currentRequest["name"], self.value);
+ end
+end
+
+function GMGenie.Macros.Tele.addToUnitMenu()
+ UnitPopupMenus["GMGenie_Tele"] = {};
+ local TeleTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.tele);
+ for index, name in pairs(TeleTemp) do
+ table.insert(UnitPopupMenus["GMGenie_Tele"], "GMGenie_Tele_" .. name);
+ UnitPopupButtons["GMGenie_Tele_" .. name] = { text = name, dist = 0, };
+ end
+
+ table.insert(UnitPopupMenus["GMGenie_Tele"], "GMGenie_TeleOptions");
+ UnitPopupButtons["GMGenie_TeleOptions"] = { text = "Manage macros", dist = 0, };
+end
+
+function GMGenie.Macros.Tele.loadDropdown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.isTitle = true;
+ info.text = "Teleport Macros";
+ UIDropDownMenu_AddButton(info, level);
+
+ local TeleTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.tele);
+ for index, name in pairs(TeleTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Macros.Tele.runFromSpy;
+ info.value = name;
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Macros";
+ info.func = GMGenie.Macros.Tele.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
\ No newline at end of file
diff --git a/Macros.Whispers.lua b/Macros.Whispers.lua
new file mode 100644
index 0000000..7689864
--- /dev/null
+++ b/Macros.Whispers.lua
@@ -0,0 +1,89 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Macros.Whispers = {};
+
+GMGenie.Macros.Whispers.curWhisperMessage = '';
+
+
+function GMGenie.Macros.Whispers.run(name, title)
+ GMGenie_Macros_Whispers_SubjectPopup:Hide();
+ GMGenie_Macros_Whispers_SubjectPopup_Subject:SetText('');
+ local msg = string.gsub(GMGenie_SavedVars.whispers[title], "NAME", name);
+ if string.find(msg, "SUBJECT") then
+ GMGenie.Macros.Whispers.curWhisperMessage = msg;
+ GMGenie.Macros.Whispers.curName = name;
+ GMGenie_Macros_Whispers_SubjectPopup:Show();
+ GMGenie_Macros_Whispers_SubjectPopup_Subject:SetFocus();
+ else
+ local args = { strsplit("\n", msg) };
+ for index, text in pairs(args) do
+ SendChatMessage(text, "WHISPER", nil, name);
+ end
+ end
+end
+
+function GMGenie.Macros.Whispers.runFromSpy(self)
+ CloseDropDownMenus();
+ if GMGenie.Spy.currentRequest["name"] then
+ GMGenie.Macros.Whispers.run(GMGenie.Spy.currentRequest["name"], self.value);
+ end
+end
+
+function GMGenie.Macros.Whispers.sendWithSubject()
+ GMGenie_Macros_Whispers_SubjectPopup:Hide();
+ local subject = GMGenie_Macros_Whispers_SubjectPopup_Subject:GetText();
+ GMGenie_Macros_Whispers_SubjectPopup_Subject:SetText('');
+
+ local msg = string.gsub(GMGenie.Macros.Whispers.curWhisperMessage, "SUBJECT", subject);
+ local args = { strsplit("\n", msg) };
+ for index, text in pairs(args) do
+ SendChatMessage(text, "WHISPER", nil, GMGenie.Macros.Whispers.curName);
+ end
+
+ GMGenie.Macros.Whispers.curWhisperMessage = '';
+end
+
+function GMGenie.Macros.Whispers.addToUnitMenu()
+ UnitPopupMenus["GMGenie_Whispers"] = {};
+
+ local whispersTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.whispers);
+ for index, name in pairs(whispersTemp) do
+ table.insert(UnitPopupMenus["GMGenie_Whispers"], "GMGenie_Whispers_" .. name);
+ UnitPopupButtons["GMGenie_Whispers_" .. name] = { text = name, dist = 0, };
+ end
+
+ table.insert(UnitPopupMenus["GMGenie_Whispers"], "GMGenie_WhisperOptions");
+ UnitPopupButtons["GMGenie_WhisperOptions"] = { text = "Manage macros", dist = 0, };
+end
+
+function GMGenie.Macros.Whispers.loadDropdown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.isTitle = true;
+ info.text = "Whisper Macros";
+ UIDropDownMenu_AddButton(info, level);
+
+ local whispersTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.whispers);
+ for index, name in pairs(whispersTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Macros.Whispers.runFromSpy;
+ info.value = name;
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Macros";
+ info.func = GMGenie.Macros.Whispers.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
\ No newline at end of file
diff --git a/Macros.Whispers.xml b/Macros.Whispers.xml
new file mode 100644
index 0000000..e9c68ea
--- /dev/null
+++ b/Macros.Whispers.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadWindow(self, 'Whisper Subject', false, nil);
+ self:ClearAllPoints();
+ self:SetPoint("TOP", GMGenie_Spy_InfoWindow, "BOTTOM");
+
+
+ self:ClearAllPoints();
+ self:SetPoint("TOP", GMGenie_Spy_InfoWindow, "BOTTOM");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Whispers.sendWithSubject();
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Whispers.sendWithSubject();
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Macros.lua b/Macros.lua
new file mode 100644
index 0000000..7d62116
--- /dev/null
+++ b/Macros.lua
@@ -0,0 +1,296 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Macros = {};
+
+function GMGenie.Macros.onLoad()
+ GMGenie.Macros.menuItems = {};
+
+ UnitPopupButtons["GMGenie_Commands"] = { text = "Quick Commands", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "Commands");
+ UnitPopupMenus["GMGenie_Commands"] = {};
+
+ UnitPopupButtons["GMGenie_Revive"] = { text = "Revive", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Commands"], "GMGenie_Revive");
+ UnitPopupButtons["GMGenie_Appear"] = { text = "Appear", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Commands"], "GMGenie_Appear");
+ UnitPopupButtons["GMGenie_Summon"] = { text = "Summon", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Commands"], "GMGenie_Summon");
+ UnitPopupButtons["GMGenie_Freeze"] = { text = "Freeze", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Commands"], "GMGenie_Freeze");
+ UnitPopupButtons["GMGenie_Unfreeze"] = { text = "Unfreeze", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Commands"], "GMGenie_Unfreeze");
+ UnitPopupButtons["GMGenie_Spy"] = { text = "Spy", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Commands"], "GMGenie_Spy");
+
+ UnitPopupButtons["GMGenie_Character"] = { text = "Character", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "Character");
+ UnitPopupMenus["GMGenie_Character"] = {};
+
+ UnitPopupButtons["GMGenie_Character_Rename"] = { text = "Rename", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Character"], "GMGenie_Character_Rename");
+ UnitPopupButtons["GMGenie_Character_Customize"] = { text = "Customize", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Character"], "GMGenie_Character_Customize");
+ UnitPopupButtons["GMGenie_Character_Changerace"] = { text = "Change Race", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Character"], "GMGenie_Character_Changerace");
+ UnitPopupButtons["GMGenie_Character_Changefaction"] = { text = "Change Faction", dist = 0 };
+ table.insert(UnitPopupMenus["GMGenie_Character"], "GMGenie_Character_Changefaction");
+
+ UnitPopupButtons["GMGenie_Whispers"] = { text = "Whisper Macros", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "Whispers");
+ GMGenie.Macros.Whispers.addToUnitMenu();
+
+ UnitPopupButtons["GMGenie_Mail"] = { text = "Mail Macros", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "Mail");
+ GMGenie.Macros.Mail.addToUnitMenu();
+
+ UnitPopupButtons["GMGenie_Tele"] = { text = "Teleport Macros", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "Tele");
+ GMGenie.Macros.Tele.addToUnitMenu();
+
+ UnitPopupButtons["GMGenie_Mute"] = { text = "Mutes", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "Mute");
+ GMGenie.Macros.Discipline.Mute.addToUnitMenu();
+
+ UnitPopupButtons["GMGenie_CharBan"] = { text = "Character Bans", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "CharBan");
+ GMGenie.Macros.Discipline.CharBan.addToUnitMenu();
+
+ UnitPopupButtons["GMGenie_AccBan"] = { text = "Account Bans", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "AccBan");
+ GMGenie.Macros.Discipline.AccBan.addToUnitMenu();
+
+ UnitPopupButtons["GMGenie_IpBan"] = { text = "Ip Bans", dist = 0, nested = 1 };
+ table.insert(GMGenie.Macros.menuItems, "IpBan");
+ GMGenie.Macros.Discipline.IpBan.addToUnitMenu();
+
+ for i, button in ipairs(GMGenie.Macros.menuItems) do
+ table.insert(UnitPopupMenus["PLAYER"], #UnitPopupMenus["PLAYER"] - 1, "GMGenie_" .. button);
+ table.insert(UnitPopupMenus["FRIEND"], #UnitPopupMenus["FRIEND"] - 1, "GMGenie_" .. button);
+ table.insert(UnitPopupMenus["PARTY"], #UnitPopupMenus["PARTY"] - 1, "GMGenie_" .. button);
+ table.insert(UnitPopupMenus["RAID_PLAYER"], #UnitPopupMenus["RAID_PLAYER"] - 1, "GMGenie_" .. button);
+ table.insert(UnitPopupMenus["TEAM"], #UnitPopupMenus["TEAM"] - 1, "GMGenie_" .. button);
+ table.insert(UnitPopupMenus["CHAT_ROSTER"], #UnitPopupMenus["CHAT_ROSTER"] - 1, "GMGenie_" .. button);
+ end
+
+ hooksecurefunc("UnitPopup_OnClick", GMGenie.Macros.contextMenuClick);
+ UIDropDownMenu_Initialize(GMGenie_Spy_InfoWindow_DropdownbuttonsOne, GMGenie.Macros.loadDropdown, "MENU");
+end
+
+function GMGenie.Macros.contextMenuClick(self)
+ local dropdownFrame = UIDROPDOWNMENU_INIT_MENU;
+ local button = self.value;
+ local name = dropdownFrame.name;
+ local startPos = string.find(button, "GMGenie_");
+
+ if (startPos == 1) then
+ button = string.sub(button, 9);
+
+ if button == "Revive" then
+ GMGenie.Macros.revive(name);
+ elseif button == "Appear" then
+ GMGenie.Macros.appear(name);
+ elseif button == "Summon" then
+ GMGenie.Macros.summon(name);
+ elseif button == "Freeze" then
+ GMGenie.Macros.freeze(name);
+ elseif button == "Unfreeze" then
+ GMGenie.Macros.unfreeze(name);
+ elseif button == "Spy" then
+ GMGenie.Spy.spy(name);
+ elseif button == "Character_Rename" then
+ GMGenie.Macros.rename(name);
+ elseif button == "Character_Customize" then
+ GMGenie.Macros.customize(name);
+ elseif button == "Character_Changerace" then
+ GMGenie.Macros.changerace(name);
+ elseif button == "Character_Changefaction" then
+ GMGenie.Macros.changefaction(name);
+ elseif button == "WhisperOptions" then
+ GMGenie.Macros.Whispers.showOptions();
+ elseif button == "MailOptions" then
+ GMGenie.Macros.Mail.showOptions();
+ elseif button == "TeleOptions" then
+ GMGenie.Macros.Tele.showOptions();
+ elseif button == "DisciplineOptions" then
+ GMGenie.Macros.Discipline.showOptions();
+ else
+ local isWhisperMacro = string.find(button, "Whispers_");
+ local isMailMacro = string.find(button, "Mail_");
+ local isTeleMacro = string.find(button, "Tele_");
+ local isMuteMacro = string.find(button, "Mute_");
+ local isCharBanMacro = string.find(button, "CharBan_");
+ local isAccBanMacro = string.find(button, "AccBan_");
+ local isIpBanMacro = string.find(button, "IpBan_");
+ if isWhisperMacro == 1 then
+ GMGenie.Macros.Whispers.run(name, string.sub(button, 10));
+ elseif isMailMacro == 1 then
+ GMGenie.Macros.Mail.run(name, string.sub(button, 6));
+ elseif isTeleMacro == 1 then
+ GMGenie.Macros.Tele.run(name, string.sub(button, 6));
+ elseif isMuteMacro == 1 then
+ GMGenie.Macros.Discipline.Mute.run(name, string.sub(button, 6));
+ elseif isCharBanMacro == 1 then
+ GMGenie.Macros.Discipline.CharBan.run(name, string.sub(button, 9));
+ elseif isAccBanMacro == 1 then
+ GMGenie.Macros.Discipline.AccBan.run(name, string.sub(button, 8));
+ elseif isIpBanMacro == 1 then
+ GMGenie.Macros.Discipline.IpBan.run(name, string.sub(button, 7));
+ end
+ end
+ end
+
+ CloseDropDownMenus();
+end
+
+function GMGenie.Macros.loadDropdown(self, level)
+ local level = level or 1;
+
+ if level == 1 then
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = true;
+ info.notCheckable = true;
+ info.text = "Character";
+ info.value = "character";
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = true;
+ info.notCheckable = true;
+ info.text = "Whisper Macros";
+ info.value = "whispers";
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = true;
+ info.notCheckable = true;
+ info.text = "Mail Macros";
+ info.value = "mail";
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = true;
+ info.notCheckable = true;
+ info.text = "Teleport Macros";
+ info.value = "tele";
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = true;
+ info.notCheckable = true;
+ info.text = "Mutes";
+ info.value = "mute";
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = true;
+ info.notCheckable = true;
+ info.text = "Character Bans";
+ info.value = "charBan";
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = true;
+ info.notCheckable = true;
+ info.text = "Account Bans";
+ info.value = "accBan";
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = true;
+ info.notCheckable = true;
+ info.text = "Ip Bans";
+ info.value = "ipBan";
+ UIDropDownMenu_AddButton(info, level);
+
+ elseif level == 2 then
+ if UIDROPDOWNMENU_MENU_VALUE == "character" then
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Rename";
+ info.func = GMGenie.Spy.rename;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Customize";
+ info.func = GMGenie.Spy.customize;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Change Faction";
+ info.func = GMGenie.Spy.changefaction;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Change Race";
+ info.func = GMGenie.Spy.changerace;
+ UIDropDownMenu_AddButton(info, level);
+
+ elseif UIDROPDOWNMENU_MENU_VALUE == "whispers" then
+ GMGenie.Macros.Whispers.loadDropdown(self, level);
+ elseif UIDROPDOWNMENU_MENU_VALUE == "mail" then
+ GMGenie.Macros.Mail.loadDropdown(self, level);
+ elseif UIDROPDOWNMENU_MENU_VALUE == "tele" then
+ GMGenie.Macros.Tele.loadDropdown(self, level);
+ elseif UIDROPDOWNMENU_MENU_VALUE == "mute" then
+ GMGenie.Macros.Discipline.Mute.loadDropdown(self, level);
+ elseif UIDROPDOWNMENU_MENU_VALUE == "charBan" then
+ GMGenie.Macros.Discipline.CharBan.loadDropdown(self, level);
+ elseif UIDROPDOWNMENU_MENU_VALUE == "accBan" then
+ GMGenie.Macros.Discipline.AccBan.loadDropdown(self, level);
+ elseif UIDROPDOWNMENU_MENU_VALUE == "ipBan" then
+ GMGenie.Macros.Discipline.IpBan.loadDropdown(self, level);
+ end
+ end
+end
+
+function GMGenie.Macros.revive(name)
+ SendChatMessage(".revive " .. name, "GUILD");
+end
+
+function GMGenie.Macros.appear(name)
+ SendChatMessage(".appear " .. name, "GUILD");
+end
+
+function GMGenie.Macros.summon(name)
+ SendChatMessage(".summon " .. name, "GUILD");
+end
+
+function GMGenie.Macros.freeze(name)
+ SendChatMessage(".freeze " .. name, "GUILD");
+end
+
+function GMGenie.Macros.unfreeze(name)
+ SendChatMessage(".unfreeze " .. name, "GUILD");
+end
+
+function GMGenie.Macros.antiCheatPlayer(name)
+ SendChatMessage(".anticheat player " .. name, "GUILD");
+end
+
+function GMGenie.Macros.rename(name)
+ SendChatMessage(".char rename " .. name, "GUILD");
+end
+
+function GMGenie.Macros.customize(name)
+ SendChatMessage(".char customize " .. name, "GUILD");
+end
+
+function GMGenie.Macros.changefaction(name)
+ SendChatMessage(".char changefaction " .. name, "GUILD");
+end
+
+function GMGenie.Macros.changerace(name)
+ SendChatMessage(".char changerace " .. name, "GUILD");
+end
\ No newline at end of file
diff --git a/Options/GMGenie.lua b/Options/GMGenie.lua
new file mode 100644
index 0000000..fed2384
--- /dev/null
+++ b/Options/GMGenie.lua
@@ -0,0 +1,43 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+-- ADD TicketTab = "General";
+
+function GMGenie.optionsOkay()
+ GMGenie_SavedVars.GMSyncChannel = GMGenie_OptionsWindow_GMSyncChannel:GetText();
+ if (GMGenie_OptionsWindow_EnableWIMIntergration:GetChecked()) then GMGenie_SavedVars.WIMIntegration = true; else GMGenie_SavedVars.WIMIntegration = false; end
+end
+
+function GMGenie.optionsDefault()
+ GMGenie.setDefault({ "WIMIntegration", "GMSyncChannel" });
+ GMGenie.Tickets.optionsUpdate();
+end
+
+function GMGenie.optionsOnLoad()
+ local panel = getglobal("GMGenie_OptionsWindow");
+ panel.name = "GM Genie";
+ panel.parent = nil;
+ panel.okay = GMGenie.optionsOkay;
+ panel.cancel = GMGenie.optionsUpdate;
+ panel.default = GMGenie.optionsDefault;
+
+ InterfaceOptions_AddCategory(panel);
+
+ getglobal("GMGenie_OptionsWindow_Title"):SetText("Game Master Genie");
+ getglobal("GMGenie_OptionsWindow_SubText"):SetText("Here you can change the settings for GM Genie.");
+
+ GMGenie.optionsUpdate();
+end
+
+function GMGenie.optionsUpdate()
+ GMGenie_OptionsWindow_GMSyncChannel:SetText(GMGenie_SavedVars.GMSyncChannel);
+ GMGenie_OptionsWindow_EnableWIMIntergration:SetChecked(GMGenie_SavedVars.WIMIntegration);
+end
+
+function GMGenie.showOptions()
+ InterfaceOptionsFrame_OpenToCategory("GM Genie");
+end
\ No newline at end of file
diff --git a/Options/GMGenie.xml b/Options/GMGenie.xml
new file mode 100644
index 0000000..7488ef5
--- /dev/null
+++ b/Options/GMGenie.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("Enable WIM Integration");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Options/Macros.Discipline.lua b/Options/Macros.Discipline.lua
new file mode 100644
index 0000000..78fab0f
--- /dev/null
+++ b/Options/Macros.Discipline.lua
@@ -0,0 +1,297 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+function GMGenie.Macros.Discipline.optionsOnLoad()
+ local panel = getglobal("GMGenie_Macros_Discipline_OptionsFrame");
+ panel.name = "Discipline Macros";
+ panel.parent = "GM Genie";
+ InterfaceOptions_AddCategory(panel);
+
+ GMGenie_Macros_Discipline_OptionsWindow_Title:SetText("Discipline Macros");
+ GMGenie_Macros_Discipline_OptionsWindow_SubText:SetText("Here you add and update mute and ban macros, which will be available from the playerinfo window and the player context menus.");
+
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Macros_Discipline_OptionsWindow_Mute_Dropdownbuttons"), GMGenie.Macros.Discipline.Mute.loadOptionsDropdown, "MENU");
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Macros_Discipline_OptionsWindow_CharBan_Dropdownbuttons"), GMGenie.Macros.Discipline.CharBan.loadOptionsDropdown, "MENU");
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Macros_Discipline_OptionsWindow_AccBan_Dropdownbuttons"), GMGenie.Macros.Discipline.AccBan.loadOptionsDropdown, "MENU");
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Macros_Discipline_OptionsWindow_IpBan_Dropdownbuttons"), GMGenie.Macros.Discipline.IpBan.loadOptionsDropdown, "MENU");
+end
+
+function GMGenie.Macros.Discipline.showOptions()
+ InterfaceOptionsFrame_OpenToCategory("Discipline Macros");
+end
+
+
+--Mute
+GMGenie.Macros.Discipline.Mute.currentEditing = nil;
+
+function GMGenie.Macros.Discipline.Mute.loadOptionsDropdown()
+ local MuteTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.mute);
+ for index, name in pairs(MuteTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Macros.Discipline.Mute.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Macros.Discipline.Mute.edit(self)
+ GMGenie.Macros.Discipline.Mute.currentEditing = self.value;
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Name:SetText(self.value);
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Duration:SetText(GMGenie_SavedVars.mute[self.value]["duration"]);
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Reason:SetText(GMGenie_SavedVars.mute[self.value]["reason"]);
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_AnnounceToServer:SetChecked(GMGenie_SavedVars.mute[self.value]["announceToServer"]);
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Save:SetText("Save");
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Delete:Enable();
+end
+
+function GMGenie.Macros.Discipline.Mute.save()
+ local name = GMGenie_Macros_Discipline_OptionsWindow_Mute_Name:GetText();
+ local duration = GMGenie_Macros_Discipline_OptionsWindow_Mute_Duration:GetText();
+ local reason = GMGenie_Macros_Discipline_OptionsWindow_Mute_Reason:GetText();
+ local announceToServer = GMGenie_Macros_Discipline_OptionsWindow_Mute_AnnounceToServer:GetChecked();
+
+ if name and duration and reason then
+ GMGenie_SavedVars.mute[name] = { duration = duration, reason = reason, announceToServer = announceToServer };
+
+ if GMGenie.Macros.Discipline.Mute.currentEditing then
+ if (name ~= GMGenie.Macros.Discipline.Mute.currentEditing) then
+ GMGenie_SavedVars.mute[GMGenie.Macros.Discipline.Mute.currentEditing] = nil;
+ GMGenie.Macros.Discipline.Mute.currentEditing = name;
+ end
+ else
+ GMGenie.Macros.Discipline.Mute.currentEditing = name;
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Save:SetText("Save");
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Delete:Enable();
+ end
+ end
+ GMGenie.Macros.Discipline.Mute.addToUnitMenu();
+end
+
+function GMGenie.Macros.Discipline.Mute.delete()
+ local name = GMGenie_Macros_Discipline_OptionsWindow_Mute_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.mute[name] = nil;
+ GMGenie.Macros.Discipline.Mute.cleanForm();
+ end
+ GMGenie.Macros.Discipline.Mute.addToUnitMenu();
+end
+
+function GMGenie.Macros.Discipline.Mute.cleanForm()
+ GMGenie.Macros.Discipline.Mute.currentEditing = nil;
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Name:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Duration:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Reason:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_AnnounceToServer:SetChecked(false);
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Save:SetText("Add");
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Delete:Disable();
+end
+
+
+--CharBan
+GMGenie.Macros.Discipline.CharBan.currentEditing = nil;
+
+function GMGenie.Macros.Discipline.CharBan.loadOptionsDropdown()
+ local CharBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.charBan);
+ for index, name in pairs(CharBanTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Macros.Discipline.CharBan.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Macros.Discipline.CharBan.edit(self)
+ GMGenie.Macros.Discipline.CharBan.currentEditing = self.value;
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Name:SetText(self.value);
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Duration:SetText(GMGenie_SavedVars.charBan[self.value]["duration"]);
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Reason:SetText(GMGenie_SavedVars.charBan[self.value]["reason"]);
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_AnnounceToServer:SetChecked(GMGenie_SavedVars.charBan[self.value]["announceToServer"]);
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Save:SetText("Save");
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Delete:Enable();
+end
+
+function GMGenie.Macros.Discipline.CharBan.save()
+ local name = GMGenie_Macros_Discipline_OptionsWindow_CharBan_Name:GetText();
+ local duration = GMGenie_Macros_Discipline_OptionsWindow_CharBan_Duration:GetText();
+ local reason = GMGenie_Macros_Discipline_OptionsWindow_CharBan_Reason:GetText();
+ local announceToServer = GMGenie_Macros_Discipline_OptionsWindow_CharBan_AnnounceToServer:GetChecked();
+
+ if name and duration and reason then
+ GMGenie_SavedVars.charBan[name] = { duration = duration, reason = reason, announceToServer = announceToServer };
+
+ if GMGenie.Macros.Discipline.CharBan.currentEditing then
+ if (name ~= GMGenie.Macros.Discipline.CharBan.currentEditing) then
+ GMGenie_SavedVars.charBan[GMGenie.Macros.Discipline.CharBan.currentEditing] = nil;
+ GMGenie.Macros.Discipline.CharBan.currentEditing = name;
+ end
+ else
+ GMGenie.Macros.Discipline.CharBan.currentEditing = name;
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Save:SetText("Save");
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Delete:Enable();
+ end
+ end
+ GMGenie.Macros.Discipline.CharBan.addToUnitMenu();
+end
+
+function GMGenie.Macros.Discipline.CharBan.delete()
+ local name = GMGenie_Macros_Discipline_OptionsWindow_CharBan_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.charBan[name] = nil;
+ GMGenie.Macros.Discipline.CharBan.cleanForm();
+ end
+ GMGenie.Macros.Discipline.CharBan.addToUnitMenu();
+end
+
+function GMGenie.Macros.Discipline.CharBan.cleanForm()
+ GMGenie.Macros.Discipline.CharBan.currentEditing = nil;
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Name:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Duration:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Reason:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_AnnounceToServer:SetChecked(false);
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Save:SetText("Add");
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Delete:Disable();
+end
+
+
+--AccBan
+GMGenie.Macros.Discipline.AccBan.currentEditing = nil;
+
+function GMGenie.Macros.Discipline.AccBan.loadOptionsDropdown()
+ local AccBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.accBan);
+ for index, name in pairs(AccBanTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Macros.Discipline.AccBan.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Macros.Discipline.AccBan.edit(self)
+ GMGenie.Macros.Discipline.AccBan.currentEditing = self.value;
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Name:SetText(self.value);
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Duration:SetText(GMGenie_SavedVars.accBan[self.value]["duration"]);
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Reason:SetText(GMGenie_SavedVars.accBan[self.value]["reason"]);
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_AnnounceToServer:SetChecked(GMGenie_SavedVars.accBan[self.value]["announceToServer"]);
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Save:SetText("Save");
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Delete:Enable();
+end
+
+function GMGenie.Macros.Discipline.AccBan.save()
+ local name = GMGenie_Macros_Discipline_OptionsWindow_AccBan_Name:GetText();
+ local duration = GMGenie_Macros_Discipline_OptionsWindow_AccBan_Duration:GetText();
+ local reason = GMGenie_Macros_Discipline_OptionsWindow_AccBan_Reason:GetText();
+ local announceToServer = GMGenie_Macros_Discipline_OptionsWindow_AccBan_AnnounceToServer:GetChecked();
+
+ if name and duration and reason then
+ GMGenie_SavedVars.accBan[name] = { duration = duration, reason = reason, announceToServer = announceToServer };
+
+ if GMGenie.Macros.Discipline.AccBan.currentEditing then
+ if (name ~= GMGenie.Macros.Discipline.AccBan.currentEditing) then
+ GMGenie_SavedVars.accBan[GMGenie.Macros.Discipline.AccBan.currentEditing] = nil;
+ GMGenie.Macros.Discipline.AccBan.currentEditing = name;
+ end
+ else
+ GMGenie.Macros.Discipline.AccBan.currentEditing = name;
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Save:SetText("Save");
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Delete:Enable();
+ end
+ end
+ GMGenie.Macros.Discipline.AccBan.addToUnitMenu();
+end
+
+function GMGenie.Macros.Discipline.AccBan.delete()
+ local name = GMGenie_Macros_Discipline_OptionsWindow_AccBan_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.accBan[name] = nil;
+ GMGenie.Macros.Discipline.AccBan.cleanForm();
+ end
+ GMGenie.Macros.Discipline.AccBan.addToUnitMenu();
+end
+
+function GMGenie.Macros.Discipline.AccBan.cleanForm()
+ GMGenie.Macros.Discipline.AccBan.currentEditing = nil;
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Name:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Duration:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Reason:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_AnnounceToServer:SetChecked(false);
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Save:SetText("Add");
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Delete:Disable();
+end
+
+
+--IpBan
+GMGenie.Macros.Discipline.IpBan.currentEditing = nil;
+
+function GMGenie.Macros.Discipline.IpBan.loadOptionsDropdown()
+ local IpBanTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.ipBan);
+ for index, name in pairs(IpBanTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Macros.Discipline.IpBan.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Macros.Discipline.IpBan.edit(self)
+ GMGenie.Macros.Discipline.IpBan.currentEditing = self.value;
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Name:SetText(self.value);
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Duration:SetText(GMGenie_SavedVars.ipBan[self.value]["duration"]);
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Reason:SetText(GMGenie_SavedVars.ipBan[self.value]["reason"]);
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_AnnounceToServer:SetChecked(GMGenie_SavedVars.ipBan[self.value]["announceToServer"]);
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Save:SetText("Save");
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Delete:Enable();
+end
+
+function GMGenie.Macros.Discipline.IpBan.save()
+ local name = GMGenie_Macros_Discipline_OptionsWindow_IpBan_Name:GetText();
+ local duration = GMGenie_Macros_Discipline_OptionsWindow_IpBan_Duration:GetText();
+ local reason = GMGenie_Macros_Discipline_OptionsWindow_IpBan_Reason:GetText();
+ local announceToServer = GMGenie_Macros_Discipline_OptionsWindow_IpBan_AnnounceToServer:GetChecked();
+
+ if name and duration and reason then
+ GMGenie_SavedVars.ipBan[name] = { duration = duration, reason = reason, announceToServer = announceToServer };
+
+ if GMGenie.Macros.Discipline.IpBan.currentEditing then
+ if (name ~= GMGenie.Macros.Discipline.IpBan.currentEditing) then
+ GMGenie_SavedVars.ipBan[GMGenie.Macros.Discipline.IpBan.currentEditing] = nil;
+ GMGenie.Macros.Discipline.IpBan.currentEditing = name;
+ end
+ else
+ GMGenie.Macros.Discipline.IpBan.currentEditing = name;
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Save:SetText("Save");
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Delete:Enable();
+ end
+ end
+ GMGenie.Macros.Discipline.IpBan.addToUnitMenu();
+end
+
+function GMGenie.Macros.Discipline.IpBan.delete()
+ local name = GMGenie_Macros_Discipline_OptionsWindow_IpBan_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.ipBan[name] = nil;
+ GMGenie.Macros.Discipline.IpBan.cleanForm();
+ end
+ GMGenie.Macros.Discipline.IpBan.addToUnitMenu();
+end
+
+function GMGenie.Macros.Discipline.IpBan.cleanForm()
+ GMGenie.Macros.Discipline.IpBan.currentEditing = nil;
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Name:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Duration:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Reason:SetText("");
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_AnnounceToServer:SetChecked(false);
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Save:SetText("Add");
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Delete:Disable();
+end
\ No newline at end of file
diff --git a/Options/Macros.Discipline.xml b/Options/Macros.Discipline.xml
new file mode 100644
index 0000000..bb6cb0b
--- /dev/null
+++ b/Options/Macros.Discipline.xml
@@ -0,0 +1,973 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil,
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Dropdownbuttons,
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.Mute.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("Announce to server");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Duration:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Reason:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_Mute_Name:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.Mute.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.Mute.save();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil,
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Dropdownbuttons,
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.CharBan.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("Announce to server");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Duration:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Reason:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_CharBan_Name:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.CharBan.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.CharBan.save();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil,
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Dropdownbuttons,
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.AccBan.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("Announce to server");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Duration:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Reason:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_AccBan_Name:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.AccBan.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.AccBan.save();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil,
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Dropdownbuttons,
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.IpBan.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("Announce to server");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Duration:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Reason:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Discipline_OptionsWindow_IpBan_Name:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.IpBan.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Discipline.IpBan.save();
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Options/Macros.Mail.lua b/Options/Macros.Mail.lua
new file mode 100644
index 0000000..2fe94bc
--- /dev/null
+++ b/Options/Macros.Mail.lua
@@ -0,0 +1,118 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+function GMGenie.Macros.Mail.optionsOnLoad()
+ local panel = getglobal("GMGenie_Macros_Mail_OptionsWindow");
+ panel.name = "Mail Macros";
+ panel.parent = "GM Genie";
+
+ InterfaceOptions_AddCategory(panel);
+
+ getglobal(panel:GetName() .. "_Title"):SetText("Mail Macros");
+ getglobal(panel:GetName() .. "_SubText"):SetText("Here you add and update mail macros, which will be available from the ticket interface and the player context menus.");
+ GMGenie_Macros_Mail_OptionsWindow_Info_Text:SetText("Note: every newline in the mail macro will be a separate mail. It is not possible to have newlines within one mail.\nNote: If the text in the box turns red that means one of the lines (messages) has become too long and might get cut off when sending a mail.\n\nTip: use NAME (in full caps) to use the players' name in the mail text.");
+
+ getglobal("GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text"):SetScript("OnTextChanged", GMGenie.Macros.Mail.updateMacroText);
+
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Macros_Mail_OptionsWindow_Dropdownbuttons"), GMGenie.Macros.Mail.loadOptionsDropdown, "MENU");
+end
+
+function GMGenie.Macros.Mail.updateMacroText()
+ ScrollingEdit_OnTextChanged(getglobal("GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text"), getglobal("GMGenie_Macros_Mail_OptionsWindow_Macro_Frame"));
+ GMGenie.Macros.Mail.checkMacroLength();
+end
+
+function GMGenie.Macros.Mail.checkMacroLength()
+ local macro = GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text:GetText();
+ local macro = string.gsub(macro, "NAME", "abcdefghijkl");
+ local lines = { strsplit("\n", macro) };
+
+ local maxlength = 226 - string.len(GMGenie_Macros_Mail_OptionsWindow_Subject:GetText());
+ if #lines > 1 then
+ maxlength = maxlength - 4;
+ end
+ for index, line in pairs(lines) do
+ if string.len(line) > maxlength then
+ GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text:SetTextColor(255, 0, 0);
+ else
+ GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text:SetTextColor(255, 255, 255);
+ end
+ end
+end
+
+GMGenie.Macros.Mail.currentEditing = nil;
+
+function GMGenie.Macros.Mail.loadOptionsDropdown()
+ local MailTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.mail);
+ for index, name in pairs(MailTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Macros.Mail.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Macros.Mail.test()
+ if GMGenie.Macros.Mail.currentEditing then
+ GMGenie.Macros.Mail.run(UnitName("player"), GMGenie.Macros.Mail.currentEditing);
+ end
+end
+
+function GMGenie.Macros.Mail.edit(self)
+ GMGenie.Macros.Mail.currentEditing = self.value;
+ GMGenie_Macros_Mail_OptionsWindow_Name:SetText(self.value);
+ GMGenie_Macros_Mail_OptionsWindow_Subject:SetText(GMGenie_SavedVars.mail[self.value]["subject"]);
+ GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text:SetText(GMGenie_SavedVars.mail[self.value]["macro"]);
+ GMGenie_Macros_Mail_OptionsWindow_Save:SetText("Save");
+ GMGenie_Macros_Mail_OptionsWindow_Delete:Enable();
+end
+
+function GMGenie.Macros.Mail.save()
+ local name = GMGenie_Macros_Mail_OptionsWindow_Name:GetText();
+ local subject = GMGenie_Macros_Mail_OptionsWindow_Subject:GetText();
+ local macro = GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text:GetText();
+
+ if name and macro and subject and name ~= "" then
+ GMGenie_SavedVars.mail[name] = { macro = macro, subject = subject };
+
+ if GMGenie.Macros.Mail.currentEditing then
+ if (name ~= GMGenie.Macros.Mail.currentEditing) then
+ GMGenie_SavedVars.mail[GMGenie.Macros.Mail.currentEditing] = nil;
+ GMGenie.Macros.Mail.currentEditing = name;
+ end
+ else
+ GMGenie.Macros.Mail.currentEditing = name;
+ GMGenie_Macros_Mail_OptionsWindow_Save:SetText("Save");
+ GMGenie_Macros_Mail_OptionsWindow_Delete:Enable();
+ end
+ end
+ GMGenie.Macros.Mail.addToUnitMenu();
+end
+
+function GMGenie.Macros.Mail.delete()
+ local name = GMGenie_Macros_Mail_OptionsWindow_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.mail[name] = nil;
+ GMGenie.Macros.Mail.cleanForm();
+ end
+ GMGenie.Macros.Mail.addToUnitMenu();
+end
+
+function GMGenie.Macros.Mail.cleanForm()
+ GMGenie.Macros.Mail.currentEditing = nil;
+ GMGenie_Macros_Mail_OptionsWindow_Name:SetText("");
+ GMGenie_Macros_Mail_OptionsWindow_Subject:SetText("");
+ GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text:SetText("");
+ GMGenie_Macros_Mail_OptionsWindow_Save:SetText("Add");
+ GMGenie_Macros_Mail_OptionsWindow_Delete:Disable();
+end
+
+function GMGenie.Macros.Mail.showOptions()
+ InterfaceOptionsFrame_OpenToCategory("Mail Macros");
+end
\ No newline at end of file
diff --git a/Options/Macros.Mail.xml b/Options/Macros.Mail.xml
new file mode 100644
index 0000000..76b7ac5
--- /dev/null
+++ b/Options/Macros.Mail.xml
@@ -0,0 +1,237 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Macros_Mail_OptionsWindow_Dropdownbuttons,
+ GMGenie_Macros_Mail_OptionsWindow_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Mail.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Mail_OptionsWindow_Subject:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Mail_OptionsWindow_Macro_Frame_Text:SetFocus();
+
+
+ GMGenie.Macros.Mail.checkMacroLength();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadEditBox(self);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Mail.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Mail.save();
+ GMGenie.Macros.Mail.test();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Mail.save();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Options/Macros.Tele.lua b/Options/Macros.Tele.lua
new file mode 100644
index 0000000..73c1d36
--- /dev/null
+++ b/Options/Macros.Tele.lua
@@ -0,0 +1,91 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+function GMGenie.Macros.Tele.optionsOnLoad()
+ local panel = getglobal("GMGenie_Macros_Tele_OptionsWindow");
+ panel.name = "Teleport Macros";
+ panel.parent = "GM Genie";
+
+ InterfaceOptions_AddCategory(panel);
+
+ getglobal(panel:GetName() .. "_Title"):SetText("Teleport Macros");
+ getglobal(panel:GetName() .. "_SubText"):SetText("Here you add and update teleport macros, which will be available from the ticket interface and the player context menus.");
+
+ GMGenie_Macros_Tele_OptionsWindow_Info_Text:SetText("Tip: use RECALL (in full caps) as the location to return a player to wherever they were before they were teleported or summoned by a GM.");
+
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Macros_Tele_OptionsWindow_Dropdownbuttons"), GMGenie.Macros.Tele.loadOptionsDropdown, "MENU");
+end
+
+GMGenie.Macros.Tele.currentEditing = nil;
+
+function GMGenie.Macros.Tele.loadOptionsDropdown()
+ local TeleTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.tele);
+ for index, name in pairs(TeleTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Macros.Tele.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Macros.Tele.test()
+ if GMGenie.Macros.Tele.currentEditing then
+ GMGenie.Macros.Tele.run(UnitName("player"), GMGenie.Macros.Tele.currentEditing);
+ end
+end
+
+function GMGenie.Macros.Tele.edit(self)
+ GMGenie.Macros.Tele.currentEditing = self.value;
+ GMGenie_Macros_Tele_OptionsWindow_Name:SetText(self.value);
+ GMGenie_Macros_Tele_OptionsWindow_Location:SetText(GMGenie_SavedVars.tele[self.value]);
+ GMGenie_Macros_Tele_OptionsWindow_Save:SetText("Save");
+ GMGenie_Macros_Tele_OptionsWindow_Delete:Enable();
+end
+
+function GMGenie.Macros.Tele.save()
+ local name = GMGenie_Macros_Tele_OptionsWindow_Name:GetText();
+ local location = GMGenie_Macros_Tele_OptionsWindow_Location:GetText();
+
+ if name and location then
+ GMGenie_SavedVars.tele[name] = location;
+
+ if GMGenie.Macros.Tele.currentEditing then
+ if (name ~= GMGenie.Macros.Tele.currentEditing) then
+ GMGenie_SavedVars.tele[GMGenie.Macros.Tele.currentEditing] = nil;
+ GMGenie.Macros.Tele.currentEditing = name;
+ end
+ else
+ GMGenie.Macros.Tele.currentEditing = name;
+ GMGenie_Macros_Tele_OptionsWindow_Save:SetText("Save");
+ GMGenie_Macros_Tele_OptionsWindow_Delete:Enable();
+ end
+ end
+ GMGenie.Macros.Tele.addToUnitMenu();
+end
+
+function GMGenie.Macros.Tele.delete()
+ local name = GMGenie_Macros_Tele_OptionsWindow_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.tele[name] = nil;
+ GMGenie.Macros.Tele.cleanForm();
+ end
+ GMGenie.Macros.Tele.addToUnitMenu();
+end
+
+function GMGenie.Macros.Tele.cleanForm()
+ GMGenie.Macros.Tele.currentEditing = nil;
+ GMGenie_Macros_Tele_OptionsWindow_Name:SetText("");
+ GMGenie_Macros_Tele_OptionsWindow_Location:SetText("");
+ GMGenie_Macros_Tele_OptionsWindow_Save:SetText("Add");
+ GMGenie_Macros_Tele_OptionsWindow_Delete:Disable();
+end
+
+function GMGenie.Macros.Tele.showOptions()
+ InterfaceOptionsFrame_OpenToCategory("Teleport Macros");
+end
\ No newline at end of file
diff --git a/Options/Macros.Tele.xml b/Options/Macros.Tele.xml
new file mode 100644
index 0000000..9ae8713
--- /dev/null
+++ b/Options/Macros.Tele.xml
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Macros_Tele_OptionsWindow_Dropdownbuttons,
+ GMGenie_Macros_Tele_OptionsWindow_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Tele.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Tele_OptionsWindow_Location:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Tele_OptionsWindow_Name:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Tele.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Tele.save();
+ GMGenie.Macros.Tele.test();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Tele.save();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Options/Macros.Whispers.lua b/Options/Macros.Whispers.lua
new file mode 100644
index 0000000..23cf5c6
--- /dev/null
+++ b/Options/Macros.Whispers.lua
@@ -0,0 +1,112 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+function GMGenie.Macros.Whispers.optionsOnLoad()
+ local panel = getglobal("GMGenie_Macros_Whispers_OptionsWindow");
+ panel.name = "Whisper Macros";
+ panel.parent = "GM Genie";
+
+ InterfaceOptions_AddCategory(panel);
+
+ getglobal(panel:GetName() .. "_Title"):SetText("Whisper Macros");
+ getglobal(panel:GetName() .. "_SubText"):SetText("Here you add and update whisper macros, which will be available from the ticket interface and the player context menus.");
+ GMGenie_Macros_Whispers_OptionsWindow_Info_Text:SetText("Note: every newline in the whisper macro will be a separate whisper. It is not possible to have newlines within one whisper.\nNote: If the text in the box turns red that means one of the lines (messages) has become too long and might get cut off when sending a whisper.\n\nTip: use NAME (in full caps) to use the players' name in the whisper text. Use SUBJECT (also in full caps), to get a pop up box where you can enter a subject for the message. SUBJECT in your macro will be replaced by this.");
+
+ getglobal("GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text"):SetScript("OnTextChanged", GMGenie.Macros.Whispers.updateMacroText);
+
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Macros_Whispers_OptionsWindow_Dropdownbuttons"), GMGenie.Macros.Whispers.loadOptionsDropdown, "MENU");
+end
+
+function GMGenie.Macros.Whispers.updateMacroText()
+ ScrollingEdit_OnTextChanged(getglobal("GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text"), getglobal("GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame"));
+ GMGenie.Macros.Whispers.checkMacroLength();
+end
+
+function GMGenie.Macros.Whispers.checkMacroLength()
+ local macro = GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text:GetText();
+ local macro = string.gsub(macro, "NAME", "abcdefghijkl");
+ local lines = { strsplit("\n", macro) };
+
+ for index, line in pairs(lines) do
+ if string.len(line) > 255 then
+ GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text:SetTextColor(255, 0, 0);
+ else
+ GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text:SetTextColor(255, 255, 255);
+ end
+ end
+end
+
+
+GMGenie.Macros.Whispers.currentEditing = nil;
+
+function GMGenie.Macros.Whispers.loadOptionsDropdown()
+ local whispersTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.whispers);
+ for index, name in pairs(whispersTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Macros.Whispers.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Macros.Whispers.edit(self)
+ GMGenie.Macros.Whispers.currentEditing = self.value;
+ GMGenie_Macros_Whispers_OptionsWindow_Name:SetText(self.value);
+ GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text:SetText(GMGenie_SavedVars.whispers[self.value]);
+ GMGenie_Macros_Whispers_OptionsWindow_Save:SetText("Save");
+ GMGenie_Macros_Whispers_OptionsWindow_Delete:Enable();
+end
+
+function GMGenie.Macros.Whispers.save()
+ local name = GMGenie_Macros_Whispers_OptionsWindow_Name:GetText();
+ local macro = GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text:GetText();
+
+ if name and macro and name ~= "" then
+ GMGenie_SavedVars.whispers[name] = macro;
+
+ if GMGenie.Macros.Whispers.currentEditing then
+ if (name ~= GMGenie.Macros.Whispers.currentEditing) then
+ GMGenie_SavedVars.whispers[GMGenie.Macros.Whispers.currentEditing] = nil;
+ GMGenie.Macros.Whispers.currentEditing = name;
+ end
+ else
+ GMGenie.Macros.Whispers.currentEditing = name;
+ GMGenie_Macros_Whispers_OptionsWindow_Save:SetText("Save");
+ GMGenie_Macros_Whispers_OptionsWindow_Delete:Enable();
+ end
+ end
+ GMGenie.Macros.Whispers.addToUnitMenu();
+end
+
+function GMGenie.Macros.Whispers.delete()
+ local name = GMGenie_Macros_Whispers_OptionsWindow_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.whispers[name] = nil;
+ GMGenie.Macros.Whispers.cleanForm();
+ end
+ GMGenie.Macros.Whispers.addToUnitMenu();
+end
+
+function GMGenie.Macros.Whispers.cleanForm()
+ GMGenie.Macros.Whispers.currentEditing = nil;
+ GMGenie_Macros_Whispers_OptionsWindow_Name:SetText("");
+ GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text:SetText("");
+ GMGenie_Macros_Whispers_OptionsWindow_Save:SetText("Add");
+ GMGenie_Macros_Whispers_OptionsWindow_Delete:Disable();
+end
+
+function GMGenie.Macros.Whispers.showOptions()
+ InterfaceOptionsFrame_OpenToCategory("Whisper Macros");
+end
+
+function GMGenie.Macros.Whispers.test()
+ if GMGenie.Macros.Whispers.currentEditing then
+ GMGenie.Macros.Whispers.run(UnitName("player"), GMGenie.Macros.Whispers.currentEditing);
+ end
+end
\ No newline at end of file
diff --git a/Options/Macros.Whispers.xml b/Options/Macros.Whispers.xml
new file mode 100644
index 0000000..c4542f3
--- /dev/null
+++ b/Options/Macros.Whispers.xml
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Macros_Whispers_OptionsWindow_Dropdownbuttons,
+ GMGenie_Macros_Whispers_OptionsWindow_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Whispers.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Macros_Whispers_OptionsWindow_Macro_Frame_Text:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadEditBox(self);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Whispers.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Whispers.save();
+ GMGenie.Macros.Whispers.test();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Macros.Whispers.save();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Options/Spawns.lua b/Options/Spawns.lua
new file mode 100644
index 0000000..44e5ee1
--- /dev/null
+++ b/Options/Spawns.lua
@@ -0,0 +1,140 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+function GMGenie.Spawns.optionsOnLoad()
+ local panel = getglobal("GMGenie_Spawns_OptionsWindow");
+ panel.name = "Builder";
+ panel.parent = "GM Genie";
+
+ InterfaceOptions_AddCategory(panel);
+
+ getglobal(panel:GetName() .. "_Title"):SetText("Builder Presets");
+ getglobal(panel:GetName() .. "_SubText"):SetText("Here you add and update preset NPCs and objects, which will be available from the builder interface.");
+
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Spawns_OptionsWindow_Objects_Dropdownbuttons"), GMGenie.Spawns.Objects.loadOptionsDropdown, "MENU");
+ UIDropDownMenu_Initialize(getglobal("GMGenie_Spawns_OptionsWindow_Npcs_Dropdownbuttons"), GMGenie.Spawns.Npcs.loadOptionsDropdown, "MENU");
+end
+
+function GMGenie.Spawns.showOptions()
+ InterfaceOptionsFrame_OpenToCategory("Builder");
+end
+
+GMGenie.Spawns.Objects = {};
+
+function GMGenie.Spawns.Objects.loadOptionsDropdown()
+ local objectsTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.objects);
+ for index, name in pairs(objectsTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Spawns.Objects.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Spawns.Objects.edit(self)
+ GMGenie.Spawns.Objects.currentEditing = self.value;
+ GMGenie_Spawns_OptionsWindow_Objects_Id:SetText(GMGenie_SavedVars.objects[self.value]);
+ GMGenie_Spawns_OptionsWindow_Objects_Name:SetText(self.value);
+ GMGenie_Spawns_OptionsWindow_Objects_Save:SetText("Save");
+ GMGenie_Spawns_OptionsWindow_Objects_Delete:Enable();
+end
+
+function GMGenie.Spawns.Objects.save()
+ local id = GMGenie_Spawns_OptionsWindow_Objects_Id:GetText();
+ local name = GMGenie_Spawns_OptionsWindow_Objects_Name:GetText();
+
+ if id and name then
+ GMGenie_SavedVars.objects[name] = id;
+
+ if GMGenie.Spawns.Objects.currentEditing then
+ if (id ~= GMGenie.Spawns.Objects.currentEditing) then
+ GMGenie_SavedVars.objects[GMGenie.Spawns.Objects.currentEditing] = nil;
+ GMGenie.Spawns.Objects.currentEditing = name;
+ end
+ else
+ GMGenie.Spawns.Objects.currentEditing = name;
+ GMGenie_Spawns_OptionsWindow_Objects_Save:SetText("Save");
+ GMGenie_Spawns_OptionsWindow_Objects_Delete:Enable();
+ end
+ end
+end
+
+function GMGenie.Spawns.Objects.delete()
+ local name = GMGenie_Spawns_OptionsWindow_Objects_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.objects[name] = nil;
+ GMGenie.Spawns.Objects.cleanForm();
+ end
+end
+
+function GMGenie.Spawns.Objects.cleanForm()
+ GMGenie.Spawns.Objects.currentEditing = nil;
+ GMGenie_Spawns_OptionsWindow_Objects_Id:SetText("");
+ GMGenie_Spawns_OptionsWindow_Objects_Name:SetText("");
+ GMGenie_Spawns_OptionsWindow_Objects_Save:SetText("Add");
+ GMGenie_Spawns_OptionsWindow_Objects_Delete:Disable();
+end
+
+GMGenie.Spawns.Npcs = {};
+
+function GMGenie.Spawns.Npcs.loadOptionsDropdown()
+ local npcsTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.npcs);
+ for index, name in pairs(npcsTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = name;
+ info.value = name;
+ info.func = GMGenie.Spawns.Npcs.edit;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function GMGenie.Spawns.Npcs.edit(self)
+ GMGenie.Spawns.Npcs.currentEditing = self.value;
+ GMGenie_Spawns_OptionsWindow_Npcs_Id:SetText(GMGenie_SavedVars.npcs[self.value]);
+ GMGenie_Spawns_OptionsWindow_Npcs_Name:SetText(self.value);
+ GMGenie_Spawns_OptionsWindow_Npcs_Save:SetText("Save");
+ GMGenie_Spawns_OptionsWindow_Npcs_Delete:Enable();
+end
+
+function GMGenie.Spawns.Npcs.save()
+ local id = GMGenie_Spawns_OptionsWindow_Npcs_Id:GetText();
+ local name = GMGenie_Spawns_OptionsWindow_Npcs_Name:GetText();
+
+ if id and name then
+ GMGenie_SavedVars.npcs[name] = id;
+
+ if GMGenie.Spawns.Npcs.currentEditing then
+ if (id ~= GMGenie.Spawns.Npcs.currentEditing) then
+ GMGenie_SavedVars.npcs[GMGenie.Spawns.Npcs.currentEditing] = nil;
+ GMGenie.Spawns.Npcs.currentEditing = name;
+ end
+ else
+ GMGenie.Spawns.Npcs.currentEditing = name;
+ GMGenie_Spawns_OptionsWindow_Npcs_Save:SetText("Save");
+ GMGenie_Spawns_OptionsWindow_Npcs_Delete:Enable();
+ end
+ end
+end
+
+function GMGenie.Spawns.Npcs.delete()
+ local name = GMGenie_Spawns_OptionsWindow_Npcs_Name:GetText();
+
+ if name and name ~= "" then
+ GMGenie_SavedVars.npcs[name] = nil;
+ GMGenie.Spawns.Npcs.cleanForm();
+ end
+end
+
+function GMGenie.Spawns.Npcs.cleanForm()
+ GMGenie.Spawns.Npcs.currentEditing = nil;
+ GMGenie_Spawns_OptionsWindow_Npcs_Id:SetText("");
+ GMGenie_Spawns_OptionsWindow_Npcs_Name:SetText("");
+ GMGenie_Spawns_OptionsWindow_Npcs_Save:SetText("Add");
+ GMGenie_Spawns_OptionsWindow_Npcs_Delete:Disable();
+end
\ No newline at end of file
diff --git a/Options/Spawns.xml b/Options/Spawns.xml
new file mode 100644
index 0000000..b9dc741
--- /dev/null
+++ b/Options/Spawns.xml
@@ -0,0 +1,350 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_OptionsWindow_Objects_Dropdownbuttons,
+ GMGenie_Spawns_OptionsWindow_Objects_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.Objects.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Spawns_OptionsWindow_Objects_Name:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Spawns_OptionsWindow_Objects_Id:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.Objects.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.Objects.save();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_OptionsWindow_Npcs_Dropdownbuttons,
+ GMGenie_Spawns_OptionsWindow_Npcs_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.Npcs.cleanForm();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Spawns_OptionsWindow_Npcs_Name:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie_Spawns_OptionsWindow_Npcs_Id:SetFocus();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.Npcs.delete();
+
+
+ self:Disable();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.Npcs.save();
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Options/Tickets.lua b/Options/Tickets.lua
new file mode 100644
index 0000000..1443723
--- /dev/null
+++ b/Options/Tickets.lua
@@ -0,0 +1,54 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+-- ADD TicketTab = "General";
+
+function GMGenie.Tickets.optionsOkay()
+ if (GMGenie_Tickets_OptionsWindow_swapWindows:GetChecked()) then GMGenie_SavedVars.swapTicketWindows = true; else GMGenie_SavedVars.swapTicketWindows = false; end
+ if (GMGenie_Tickets_OptionsWindow_useSpy:GetChecked()) then GMGenie_SavedVars.useSpy = true; else GMGenie_SavedVars.useSpy = false; end
+end
+
+function GMGenie.Tickets.toggleOfflineTickets()
+ if GMGenie_SavedVars.showOfflineTickets then
+ GMGenie_SavedVars.showOfflineTickets = false;
+ else
+ GMGenie_SavedVars.showOfflineTickets = true;
+ end
+ GMGenie.Tickets.optionsUpdate();
+ GMGenie.Tickets.refresh();
+end
+
+function GMGenie.Tickets.optionsDefault()
+ GMGenie.setDefault({ "showOfflineTickets", "swapTicketWindows", "useSpy" });
+ GMGenie.Tickets.optionsUpdate();
+end
+
+function GMGenie.Tickets.optionsOnLoad()
+ local panel = getglobal("GMGenie_Tickets_OptionsWindow");
+ panel.name = "Tickets";
+ panel.parent = "GM Genie";
+ panel.okay = GMGenie.Tickets.optionsOkay;
+ panel.cancel = GMGenie.Tickets.optionsUpdate;
+ panel.default = GMGenie.Tickets.optionsDefault;
+
+ InterfaceOptions_AddCategory(panel);
+
+ getglobal("GMGenie_Tickets_OptionsWindow_Title"):SetText("Tickets");
+ getglobal("GMGenie_Tickets_OptionsWindow_SubText"):SetText("Here you can change the settings for the ticket tracker.");
+
+ GMGenie.Tickets.optionsUpdate();
+end
+
+function GMGenie.Tickets.optionsUpdate()
+ getglobal("GMGenie_Tickets_OptionsWindow_showOffline"):SetChecked(GMGenie_SavedVars.showOfflineTickets);
+ getglobal("GMGenie_Tickets_OptionsWindow_swapWindows"):SetChecked(GMGenie_SavedVars.swapTicketWindows);
+ getglobal("GMGenie_Tickets_OptionsWindow_useSpy"):SetChecked(GMGenie_SavedVars.useSpy);
+end
+
+function GMGenie.Tickets.ShowOptions()
+ InterfaceOptionsFrame_OpenToCategory("Tickets");
+end
\ No newline at end of file
diff --git a/Options/Tickets.xml b/Options/Tickets.xml
new file mode 100644
index 0000000..9ee7c44
--- /dev/null
+++ b/Options/Tickets.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("Show offline tickets");
+
+
+ GMGenie.Tickets.toggleOfflineTickets();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("Close ticket list when reading a ticket.");
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("Open playerinfo window when reading a ticket.");
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index c0bf647..784e0dd 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,201 @@
-GMGenie
+**[Download most recent release (0.7.2).](http://www.chocochaos.com/gmgenie/GMGenie%200.7.2.zip)**
+
+
+
+About Game Master Genie
=======
-World of Warcraft addon for use by Game Masters on private servers running TrinityCore. Compatible with client versions 3.3.5 and 4.3.4.
+
+
+GM Genie is an all-round GM addon for Trinitycore, aimed at making common tasks easier and quicker to accomplish. It provides tools for managing tickets, interacting with players on the server, building/spawning and much much more.
+
+GM Genie is not and is never going to be a collection of buttons just to eliminate the need to type commands. I have personally never understood how that is useful in any way, so please don't make requests to add button x for command y, it is not going to happen. However, if you have ideas for new functionality that could provide new possibilities or make existing tasks vastly easier, be sure to mention them!
+
+
+
+Download
+=======
+
+**[Download most recent release (0.7.2).](http://www.chocochaos.com/gmgenie/GMGenie%200.7.2.zip)**
+
+**[Download older versions.](http://www.chocochaos.com/gmgenie/old/)**
+
+
+
+Current Functionaility
+=======
+
+* **Hud aka the main window**
+ Shows the amount of open tickets, both online and offline. Shows gm status and allows changing it. And provides quick access to the ticket and builder interface.
+* **Tickets**
+ May not sound all too interesting, but decent ticket addons are hard to find these days. This one is extra cool as it has some neat functionality, including but not limited to:
+ * Read marking: easily see which tickets have and have not yet been read.
+ * Differentiation between online and offline tickets, including the option to hide offline tickets if you wish.
+ * Sort by tickets by id, name, creation date, modified date or assigned to.
+ * Show who else is reading the ticket while you are reading it.
+ * Quickly assigning the ticket to yourself with a single click, or to someone else by right clicking.
+ * The ability to set comments from within the ticket window, instantly updating the comment if someone else has the ticket open as well.
+ * Fully integrated with the awesome spy (see below).
+* **Spy aka playerinfo**
+ Spy is a window showing all relevant info from the usefull playerinfo command. In addition, it provides access to several quick commands, macros and advanced character tools. Spy is opened automatically when a ticket is opened, and can be initialized manually by typing /why charactername or by right clicking a name in chat, going to quick commands and clicking spy.
+ * Appear, summon, freeze, unfreeze, revive, rename, customize, change race, change class, etc.
+ * Lookup other accounts and characters from the player.
+ * Show any current or past bans.
+ * Quick ccess to all whisper, mail and discipline macros (see below).
+* **Player macros**
+ There are three types of player macros: whisper macros (which send pre-defined whispers), mail macros (to send pre-defined mails) and discipline macros (for any kind of pre-defined mutes or bans).
+ Macros can be easily defined from the interface settings. Each type comes with several neat options to customise the macros to your needs.
+ The macros can be accessed from the spy window, and when right clicking a player in chat (or somewhere else, as long as there is normally a player menu on right click).
+* **Builder**
+ The builder allows exact movement, rotation and spawning of npcs and objects. The combination of these two options make it a pretty powerful tool that can be used to make almost anything in-game.
+ In addition there is also a window to make "spawn macros". Usage requires a basic understanding of lua. A few examples:
+ * A cirlce with 18 chairs:
+
+ for i=1, 18, 1 do
+ go(5, 0, 0, 180, -1, 1, 176232);
+ go(5, 0, 0, 200, -1, 0, 0);
+ end
+
+ * A spiral of torches going up:
+
+ for i=1, 400, 1 do
+ local rotate = 2+0.05*(2.71828183^(0.0125*i))
+ local up = rotate/100;
+ go(0.25, 0, up, rotate, -1, 1, 180352);
+ end
+
+ An example of what can be accomplished once you are familiar with the builder:
+ [http://www.youtube.com/watch?v=A_4r1vEJ3MQ](http://www.youtube.com/watch?v=A_4r1vEJ3MQ)
+
+The above certainly isn't a complete list of what the addon can do, but there's no point making a wall of text that no one will read anyway. I'd highly encourage just testing some things out and see what it can do for you. If you know lua, a peek at the source code may also shed some light on the functionality.
+
+The addon is released under the GPL (v3), so feel free to modify, redistribute or whatever you'd like to do with it. If you find any bugs, have ideas for improvements, want to provide a patch or whatever, please feel free to post it here.
+
+
+
+Reposts and modifications
+=======
+
+Since GM Genie is under an open source license, any modifications and redistributions of the addon are explicitely allowed, as long as copyright and license notices remain intact.
+
+However, I would appreciate it if you could drop me a message if you post/publish GM Genie somewhere. Partly because I like to know where it is being spread, but also so I can add new versions to those threads when they are released. It would be a shame if everyone keeps using some ancient version because it was once posted on a forum, and never updated there.
+
+You can drop me an e-mail at gmgenie [at] chocochaos [dot] com
+
+It's not a requirement to inform me, but I would appreciate it =)
+
+
+
+Changelog
+=======
+
+Version 0.7.3
+-------
+
+* Small changes and fixes:
+ - Code cleanup in several areas.
+ - Fixed the spy window (the new TrinityCore output format broke it).
+ - Security fix for ip banning functionality.
+
+Version 0.7.2
+-------
+
+* Cataclysm (up until 4.3.4) is now supported. Some quick testing has been done, but there may also be some issues that I missed. Consider cataclysm support to be in beta for now. Also, please note that the addon should still work fine in Wrath of the Lich King.
+ - Replaced all references to global variable this, event and arg1 with something else that does work.
+ - Manually updated the chronos library. Replaced the VARIABLES_LOADED event with ADDON_LOADED. AceTimer was also considered, but would have required more work to implement.
+ - Changed the loading process of GMGenie windows and textareas, so that backgrounds are once again loaded and the size is set correctly.
+ - Updated the interface version to 40300.
+* Small changes and fixes
+ - Fixed a small lua error on first load of the addon (related to the minimap button position).
+
+Version 0.7.1
+-------
+
+* Small changes and fixes
+ - When there is a large amount of offline tickets online tickets will now show up properly once again.
+
+Version 0.7
+-------
+
+* General changes:
+ - New hud, replacing the old minimap menu. This hud also shows gm/chat/visibility/whisper/fly/speed status, and allows changing it.
+ - When porting to a different map flight mode is automatically re-enabled (if it was enabled previously).
+ - Hyperlinks for gameobjects, gameobjects entries, creatures and creature entries now give a nice dropdown with usefull options when you click on them, instead of an annoying lua error. Options include: spawning/removing, porting to and listing spawned creatures/gameobjects.
+ - Generally a more consistent interface.
+ - Names in anticheat messages are now clickable (left click opens the spy window, makes you invisible, appears and show the kind of cheats detected, right click opens the usual player menu). This was tested on a non-standard anti-cheat though, so it may not work on all servers.
+* Changes to ticket interface:
+ - When showing offline tickets is enabled, offline tickets show up in red.
+ - Previously read tickets show up in a little darker colour than unread tickets.
+ - The ticket you're currently reading is shown in white.
+ - Refresh button moved to the top of the window, settings button removed (settings can be accessed through the interface options, like for all addons).
+ - Ticket count at the bottom of the window now separates online and offline tickets.
+ - Fixed a bug where some tickets would incorrectly be highlighted (as if they were being read) in the list.
+* Changes to the spy (playerinfo) window:
+ - You can now right click in the spy window to copy the playerinfo.
+ - A refresh button has been added at the top of the window.
+ - Latencies of 1k and higher now show up in red. Stripped the ms of the latency so that larger numbers fit in.
+ - Fixed using /spy without a name (using target instead when no name is specified).
+
+Version 0.6.1
+-------
+
+* Small changes and fixes
+ - Viewing ticket comments bugged out for tickets with multiple lines of text.
+
+Version 0.6
+-------
+
+* Major visible changes
+ - Ticket comment and assign/unassign fully fixed and implemented.
+ - Added mute and ban macros, with the option to announce to the server.
+ - The ticket window now shows other GMs reading the ticket, provided the GMs are in the same guild.
+ - Added character customisation options to the macro menus.
+* Small changes and fixes
+ - Fixed a very rare lua error in the ticket tracker.
+ - When pressing enter or escape in a text box it now automatically looses focus.
+ - Fixed all lua errors while tabbing through text boxes in the settings.
+
+Version 0.5
+-------
+
+* Major visible changes:
+ - Added teleport macros.
+ - Added an extra dropdown to the spy window for advanced commands (currently lookup player and baninfo).
+ - Added an advanced building tool (can be opened with /builder).
+ - Overhauled user interface.
+ - Added a minimap button with a menu for GM Genie. The button shows the number of tickets.
+* Small changes and fixes
+ - Fixed the previous and next page buttons that were missing from the ticket window.
+ - Double click the window title to reset it to it's default position.
+ - Made the text at the bottom of the ticket window a button (doesn't look like one but it is!). You can use it to easily turn offlines tickets on and off.
+ - Changed the spy window to show more detailed location information and include the player's phase (if online).
+ - Changed the (Un)root button from a secure button to a normal button and named in (Un)freeze. Now also works for players not in range and offline players. Also added freeze and unfreeze to the quick commands menu.
+ - Fix a bug where refreshing the spy window would sometimes give an error.
+ - Further code cleanup.
+ - Fixed a lua error when trying to open a ticket while the list was being refreshed.
+ - Fixed the auto-refresh of the ticket window and count.
+
+Version 0.3.1
+-------
+
+* Small changes and fixes
+ - Fixed a bug where dropdowns were loaded before checking saved variables, resulting in LUA errors is the defaults needed to be loaded.
+
+Version 0.3
+-------
+
+* Major visible changes:
+ - Added several quick commands (revive, appear, summon, spy) on right clicking someone's name.
+ - Added mail macros.
+ - Added dropdowns for mail and whisper macros when spying someone and when right clicking a name in the game.
+* Small changes and fixes
+ - Changed the regular expression to read ticket listings and tickets from chat, so that it now allows spaces in the created and last modified time (this will make the addon work on new TC revisions).
+ - Fixed a bug where tickets with an empty line at the start would not display correctly.
+ - All regular expressions and functions to read from chat moved to Chatreader.lua.
+ - Load saved variabled in Savedvariables.lua and allow setting defaults in that file (this allows creating a default preset for a server-specific distribution of GM Genie).
+ - Big code cleanup in several areas. Consistent naming for variables and functions, as far as possible without creating unnescessary extra variables.
+
+Version 0.2 and older
+-------
+
+No changelogs kept.
\ No newline at end of file
diff --git a/Reposts and modifications.txt b/Reposts and modifications.txt
new file mode 100644
index 0000000..7d22e25
--- /dev/null
+++ b/Reposts and modifications.txt
@@ -0,0 +1,12 @@
+Dear user,
+
+Since GM Genie is under an open source license, any modifications and redistributions of the addon are explicitely allowed, as long as copyright and license notes remain intact.
+
+However, I would appreciate it if you could drop me a message if you post/publish GM Genie somewhere. Partly because I like to know where it is being spread, but also so I can add new versions to those threads when they are released. It would be a shame if everyone keeps using some ancient version because it was once posted on a forum, and never updated there.
+You can drop me an e-mail at gmgenie@chocochaos.com
+
+It's not a requirement to inform me, but I would greatly appreciate it =)
+
+Regards,
+
+Chocochaos
\ No newline at end of file
diff --git a/Savedvariables.lua b/Savedvariables.lua
new file mode 100644
index 0000000..ce4030a
--- /dev/null
+++ b/Savedvariables.lua
@@ -0,0 +1,40 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.defaultSettings = {
+ ["GMSyncChannel"] = "GM_Sync_Channel",
+ ["whispers"] = {},
+ ["mail"] = {},
+ ["tele"] = {},
+ ['objects'] = {},
+ ['npcs'] = {},
+ ['mute'] = {},
+ ['charBan'] = {},
+ ['accBan'] = {},
+ ['ipBan'] = {},
+ ["WIMIntegration"] = false,
+ ["useSpy"] = true,
+ ["swapTicketWindows"] = false,
+ ["showOfflineTickets"] = false,
+ ["minimapPos"] = 45,
+ ['hudClosed'] = false,
+ ['ticketsDone'] = 0,
+}
+
+function GMGenie.loadSettings()
+ for name, value in pairs(GMGenie.defaultSettings) do
+ if not GMGenie_SavedVars[name] then
+ GMGenie_SavedVars[name] = value;
+ end
+ end
+end
+
+function GMGenie.setDefault(names)
+ for i, name in ipairs(names) do
+ GMGenie_SavedVars[name] = GMGenie.defaultSettings[name];
+ end
+end
\ No newline at end of file
diff --git a/Spawns.lua b/Spawns.lua
new file mode 100644
index 0000000..3758556
--- /dev/null
+++ b/Spawns.lua
@@ -0,0 +1,621 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Spawns = {};
+
+GMGenie.Spawns.direction = { forwardBackward = 1, leftRight = 1, upDown = 1, rotate = 1 };
+GMGenie.Spawns.waitingForGps = 0;
+GMGenie.Spawns.waitingForObject = false;
+GMGenie.Spawns.waitingForObjectDelete = false;
+GMGenie.Spawns.currentCoords = {};
+GMGenie.Spawns.macroScheduleTime = 0;
+
+function GMGenie.Spawns.onLoad()
+ UIDropDownMenu_Initialize(GMGenie_Spawns_Main_ForwardBackward_Dropdownbuttons, GMGenie.Spawns.loadDropdownForwardBackward, "MENU");
+ UIDropDownMenu_Initialize(GMGenie_Spawns_Main_LeftRight_Dropdownbuttons, GMGenie.Spawns.loadDropdownLeftRight, "MENU");
+ UIDropDownMenu_Initialize(GMGenie_Spawns_Main_UpDown_Dropdownbuttons, GMGenie.Spawns.loadDropdownUpDown, "MENU");
+ UIDropDownMenu_Initialize(GMGenie_Spawns_Main_Rotate_Dropdownbuttons, GMGenie.Spawns.loadDropdownRotate, "MENU");
+ UIDropDownMenu_Initialize(GMGenie_Spawns_Main_Object_Dropdownbuttons, GMGenie.Spawns.loadObjectDropdown, "MENU");
+ UIDropDownMenu_Initialize(GMGenie_Spawns_Main_Npc_Dropdownbuttons, GMGenie.Spawns.loadNpcDropdown, "MENU");
+ GMGenie.Spawns.Hyperlink.onLoad();
+end
+
+function GMGenie.Spawns.loadDropdownForwardBackward(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'forward';
+ info.func = GMGenie.Spawns.setForwardBackward;
+ info.value = 1;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'backward';
+ info.func = GMGenie.Spawns.setForwardBackward;
+ info.value = -1;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+function GMGenie.Spawns.setForwardBackward(self)
+ CloseDropDownMenus();
+ GMGenie.Spawns.direction.forwardBackward = self.value;
+ GMGenie.Spawns.updateView();
+end
+
+function GMGenie.Spawns.loadDropdownLeftRight(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'left';
+ info.func = GMGenie.Spawns.setLeftRight;
+ info.value = 1;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'right';
+ info.func = GMGenie.Spawns.setLeftRight;
+ info.value = -1;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+function GMGenie.Spawns.setLeftRight(self)
+ CloseDropDownMenus();
+ GMGenie.Spawns.direction.leftRight = self.value;
+ GMGenie.Spawns.updateView();
+end
+
+function GMGenie.Spawns.loadDropdownUpDown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'up';
+ info.func = GMGenie.Spawns.setUpDown;
+ info.value = 1;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'down';
+ info.func = GMGenie.Spawns.setUpDown;
+ info.value = -1;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+function GMGenie.Spawns.setUpDown(self)
+ CloseDropDownMenus();
+ GMGenie.Spawns.direction.upDown = self.value;
+ GMGenie.Spawns.updateView();
+end
+
+function GMGenie.Spawns.loadDropdownRotate(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Rotate left';
+ info.func = GMGenie.Spawns.setRotate;
+ info.value = 1;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Rotate right';
+ info.func = GMGenie.Spawns.setRotate;
+ info.value = -1;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Face north';
+ info.func = GMGenie.Spawns.setRotate;
+ info.value = 0;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Face east';
+ info.func = GMGenie.Spawns.setRotate;
+ info.value = 90;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Face south';
+ info.func = GMGenie.Spawns.setRotate;
+ info.value = 180;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Face west';
+ info.func = GMGenie.Spawns.setRotate;
+ info.value = 270;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+function GMGenie.Spawns.setRotate(self)
+ CloseDropDownMenus();
+ GMGenie.Spawns.direction.rotate = self.value;
+ GMGenie.Spawns.updateView();
+end
+
+function GMGenie.Spawns.updateView()
+ if GMGenie.Spawns.direction.forwardBackward == 1 then
+ GMGenie_Spawns_Main_ForwardBackward_Direction:SetText('forward');
+ else
+ GMGenie_Spawns_Main_ForwardBackward_Direction:SetText('backward');
+ end
+
+ if GMGenie.Spawns.direction.leftRight == 1 then
+ GMGenie_Spawns_Main_LeftRight_Direction:SetText('left');
+ else
+ GMGenie_Spawns_Main_LeftRight_Direction:SetText('right');
+ end
+
+ if GMGenie.Spawns.direction.upDown == 1 then
+ GMGenie_Spawns_Main_UpDown_Direction:SetText('up');
+ else
+ GMGenie_Spawns_Main_UpDown_Direction:SetText('down');
+ end
+
+ if GMGenie.Spawns.direction.rotate == 1 then
+ GMGenie_Spawns_Main_Rotate_Direction:SetText('Rotate left');
+ GMGenie_Spawns_Main_Rotate_Amount:Show();
+ elseif GMGenie.Spawns.direction.rotate == -1 then
+ GMGenie_Spawns_Main_Rotate_Direction:SetText('Rotate right');
+ GMGenie_Spawns_Main_Rotate_Amount:Show();
+ elseif GMGenie.Spawns.direction.rotate == 0 then
+ GMGenie_Spawns_Main_Rotate_Direction:SetText('Face north');
+ GMGenie_Spawns_Main_Rotate_Amount:Hide();
+ elseif GMGenie.Spawns.direction.rotate == 90 then
+ GMGenie_Spawns_Main_Rotate_Direction:SetText('Face east');
+ GMGenie_Spawns_Main_Rotate_Amount:Hide();
+ elseif GMGenie.Spawns.direction.rotate == 180 then
+ GMGenie_Spawns_Main_Rotate_Direction:SetText('Face south');
+ GMGenie_Spawns_Main_Rotate_Amount:Hide();
+ elseif GMGenie.Spawns.direction.rotate == 270 then
+ GMGenie_Spawns_Main_Rotate_Direction:SetText('Face west');
+ GMGenie_Spawns_Main_Rotate_Amount:Hide();
+ end
+
+ if not GMGenie.Spawns.currentCoords.x then
+ GMGenie_Spawns_Main_Coords_X:SetText('X:');
+ else
+ local x = tostring(GMGenie.Spawns.currentCoords.x);
+ if string.len(x) > 10 then
+ x = string.sub(x, 1, 10);
+ end
+ GMGenie_Spawns_Main_Coords_X:SetText('X: ' .. x);
+ end
+
+ if not GMGenie.Spawns.currentCoords.y then
+ GMGenie_Spawns_Main_Coords_Y:SetText('Y:');
+ else
+ local y = tostring(GMGenie.Spawns.currentCoords.y);
+ if string.len(y) > 10 then
+ y = string.sub(y, 1, 10);
+ end
+ GMGenie_Spawns_Main_Coords_Y:SetText('Y: ' .. y);
+ end
+
+ if not GMGenie.Spawns.currentCoords.z then
+ GMGenie_Spawns_Main_Coords_Z:SetText('Z:');
+ else
+ local z = tostring(GMGenie.Spawns.currentCoords.z);
+ if string.len(z) > 10 then
+ z = string.sub(z, 1, 10);
+ end
+ GMGenie_Spawns_Main_Coords_Z:SetText('Z: ' .. z);
+ end
+
+ if not GMGenie.Spawns.currentCoords.o then
+ GMGenie_Spawns_Main_Coords_O:SetText('O:');
+ else
+ local o = tostring(GMGenie.Spawns.currentCoords.o);
+ if string.len(o) > 10 then
+ o = string.sub(o, 1, 10);
+ end
+ GMGenie_Spawns_Main_Coords_O:SetText('O: ' .. o);
+ end
+end
+
+function GMGenie.Spawns.clearFocus()
+ GMGenie_Spawns_Main_ForwardBackward_Amount:ClearFocus();
+ GMGenie_Spawns_Main_LeftRight_Amount:ClearFocus();
+ GMGenie_Spawns_Main_UpDown_Amount:ClearFocus();
+ GMGenie_Spawns_Main_Rotate_Amount:ClearFocus();
+ GMGenie_Spawns_Main_Npc_Id:ClearFocus();
+ GMGenie_Spawns_Main_Object_Id:ClearFocus();
+ GMGenie_Spawns_Macro_Macro_Frame_Text:ClearFocus();
+end
+
+
+
+function GMGenie.Spawns.initiateMove(option)
+ GMGenie.Spawns.currentSpawnOption = option;
+ if not (GMGenie.Spawns.currentCoords.x and GMGenie.Spawns.currentCoords.y and GMGenie.Spawns.currentCoords.z and GMGenie.Spawns.currentCoords.o and GMGenie.Spawns.currentCoords.map) then
+ SendChatMessage(".gps", "GUILD");
+ GMGenie.Spawns.waitingForGps = 1;
+ else
+ GMGenie.Spawns.move(GMGenie.Spawns.currentCoords.x, GMGenie.Spawns.currentCoords.y, GMGenie.Spawns.currentCoords.z, GMGenie.Spawns.currentCoords.o);
+ end
+ GMGenie.Spawns.clearFocus();
+end
+
+function GMGenie.Spawns.setMap(map)
+ GMGenie.Spawns.currentCoords.map = map;
+end
+
+function GMGenie.Spawns.move(x, y, z, o)
+
+ local forwardBackward = GMGenie_Spawns_Main_ForwardBackward_Amount:GetText();
+ if not forwardBackward or forwardBackward == "" then
+ forwardBackward = 0;
+ end
+ local leftRight = GMGenie_Spawns_Main_LeftRight_Amount:GetText();
+ if not leftRight or leftRight == "" then
+ leftRight = 0;
+ end
+ local upDown = GMGenie_Spawns_Main_UpDown_Amount:GetText();
+ if not upDown or upDown == "" then
+ upDown = 0;
+ end
+ local rotate = GMGenie_Spawns_Main_Rotate_Amount:GetText();
+ if not rotate or rotate == "" then
+ rotate = 0;
+ end
+
+ forwardBackward = tonumber(forwardBackward) * GMGenie.Spawns.direction.forwardBackward;
+ leftRight = tonumber(leftRight) * GMGenie.Spawns.direction.leftRight;
+ upDown = tonumber(upDown);
+ rotate = tonumber(rotate);
+
+ x = tonumber(x);
+ y = tonumber(y);
+ z = tonumber(z);
+ o = deg(tonumber(o));
+
+ if GMGenie.Spawns.currentSpawnOption == -1 then
+ forwardBackward = -1 * forwardBackward;
+ leftRight = -1 * leftRight;
+ upDown = -1 * upDown;
+ rotate = -1 * rotate;
+ elseif GMGenie.Spawns.currentSpawnOption == 1 then
+ Chronos.scheduleByName('spawnobject', 0.25, GMGenie.Spawns.object, GMGenie_Spawns_Main_Object_Id:GetText());
+ elseif GMGenie.Spawns.currentSpawnOption == 2 then
+ Chronos.scheduleByName('spawnnpc', 0.25, GMGenie.Spawns.npc, GMGenie_Spawns_Main_Npc_Id:GetText());
+ end
+
+ local tempO = o;
+ if GMGenie.Spawns.currentSpawnOption == -1 then
+ if GMGenie.Spawns.direction.rotate == 1 or GMGenie.Spawns.direction.rotate == -1 then
+ tempO = o + (rotate * GMGenie.Spawns.direction.rotate);
+ else
+ tempO = GMGenie.Spawns.direction.rotate;
+ end
+ end
+
+ x = x + ((cos(tempO) * forwardBackward) + (cos(270 - tempO) * leftRight));
+ y = y + ((sin(tempO) * forwardBackward) - (sin(270 - tempO) * leftRight));
+ z = z + (upDown * GMGenie.Spawns.direction.upDown);
+
+ if GMGenie.Spawns.direction.rotate == 1 or GMGenie.Spawns.direction.rotate == -1 then
+ o = o + (rotate * GMGenie.Spawns.direction.rotate);
+ else
+ o = GMGenie.Spawns.direction.rotate;
+ end
+
+ o = rad(o);
+
+ GMGenie.Spawns.currentCoords.x = x;
+ GMGenie.Spawns.currentCoords.y = y;
+ GMGenie.Spawns.currentCoords.z = z;
+ GMGenie.Spawns.currentCoords.o = o;
+
+ SendChatMessage(".go xyz " .. x .. " " .. y .. " " .. z .. " " .. GMGenie.Spawns.currentCoords.map .. " " .. o, "GUILD");
+ GMGenie.Spawns.updateView();
+end
+
+function GMGenie.Spawns.object(objectId)
+ if not objectId or objectId == "" then
+ return false;
+ end
+ objectId = tonumber(objectId);
+
+ SendChatMessage(".gobject add " .. objectId, "GUILD");
+end
+
+function GMGenie.Spawns.npc(npcId)
+ if not npcId or npcId == "" then
+ return false;
+ end
+ npcId = tonumber(npcId);
+
+ SendChatMessage(".npc add " .. npcId, "GUILD");
+end
+
+function GMGenie.Spawns.resetCoords()
+ GMGenie.Spawns.currentCoords = {};
+ GMGenie.Spawns.updateView();
+end
+
+function GMGenie.Spawns.targetObject()
+ GMGenie.Spawns.waitingForObject = true;
+ SendChatMessage(".gobject target", "GUILD");
+end
+
+function GMGenie.Spawns.deleteObject(name, guid, id)
+ GMGenie.Spawns.waitingForObjectDelete = true;
+ SendChatMessage(".gobject del " .. guid, "GUILD");
+ GMGenie.showGMMessage("Deleting object: " .. name .. " GUID: " .. guid .. " ID: " .. id);
+end
+
+function GMGenie.Spawns.deleteNpc()
+ SendChatMessage(".npc del");
+end
+
+function GMGenie.Spawns.toggleMacroWindow()
+ local frame = GMGenie_Spawns_Macro;
+ if frame:IsVisible() then
+ frame:Hide();
+ else
+ frame:Show();
+ end
+end
+
+function GMGenie.Spawns.scheduleGo(forwardBackward, leftRight, upDown, rotate, rotateDir, option, id)
+ Chronos.schedule(GMGenie.Spawns.macroScheduleTime, GMGenie.Spawns.go, forwardBackward, leftRight, upDown, rotate, rotateDir, option, id)
+ GMGenie.Spawns.macroScheduleTime = 1 + GMGenie.Spawns.macroScheduleTime;
+end
+
+function GMGenie.Spawns.go(forwardBackward, leftRight, upDown, rotate, rotateDir, option, id)
+ GMGenie.Spawns.direction = { forwardBackward = 1, leftRight = 1, upDown = 1, rotate = rotateDir };
+ GMGenie_Spawns_Main_ForwardBackward_Amount:SetText(forwardBackward);
+ GMGenie_Spawns_Main_LeftRight_Amount:SetText(leftRight);
+ GMGenie_Spawns_Main_UpDown_Amount:SetText(upDown);
+ GMGenie_Spawns_Main_Rotate_Amount:SetText(rotate);
+
+ GMGenie_Spawns_Main_Object_Id:SetText("");
+ GMGenie_Spawns_Main_Npc_Id:SetText("");
+ if option == 1 then
+ GMGenie_Spawns_Main_Object_Id:SetText(id);
+ elseif option == 2 then
+ GMGenie_Spawns_Main_Npc_Id:SetText(id);
+ end
+
+ GMGenie.Spawns.updateView();
+ GMGenie.Spawns.clearFocus();
+
+ GMGenie.Spawns.initiateMove(option);
+
+ GMGenie.Spawns.macroScheduleTime = 2 + GMGenie.Spawns.macroScheduleTime;
+end
+
+function GMGenie.Spawns.runMacro()
+ GMGenie.Spawns.macroScheduleTime = 0;
+ local macroText = GMGenie_Spawns_Macro_Macro_Frame_Text:GetText();
+ macroText = string.gsub(macroText, "go", "GMGenie.Spawns.scheduleGo");
+ GMGenie.showGMMessage("Running spawn macro, do not interfere!");
+ RunScript(macroText);
+end
+
+function GMGenie.Spawns.toggle()
+ local frame = GMGenie_Spawns_Main;
+ if frame:IsVisible() then
+ frame:Hide();
+ else
+ frame:Show();
+ end
+end
+
+function GMGenie.Spawns.loadObjectDropdown(self, level)
+ local objectsTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.objects);
+ for index, name in pairs(objectsTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Spawns.selectObject;
+ info.value = GMGenie_SavedVars.objects[name];
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Presets";
+ info.func = GMGenie.Spawns.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+function GMGenie.Spawns.loadNpcDropdown(self, level)
+ local npcsTemp = GMGenie.pairsByKeys2(GMGenie_SavedVars.npcs);
+ for index, name in pairs(npcsTemp) do
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = name;
+ info.func = GMGenie.Spawns.selectNpc;
+ info.value = GMGenie_SavedVars.npcs[name];
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = "Manage Presets";
+ info.func = GMGenie.Spawns.showOptions;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+function GMGenie.Spawns.selectObject(self)
+ CloseDropDownMenus();
+ GMGenie_Spawns_Main_Object_Id:SetText(self.value);
+end
+
+function GMGenie.Spawns.selectNpc(self)
+ CloseDropDownMenus();
+ GMGenie_Spawns_Main_Npc_Id:SetText(self.value);
+end
+
+
+
+GMGenie.Spawns.Hyperlink = {};
+GMGenie.Spawns.Hyperlink.name = '';
+GMGenie.Spawns.Hyperlink.id = '';
+GMGenie.Spawns.Hyperlink.type = '';
+
+function GMGenie.Spawns.Hyperlink.onLoad()
+ UIDropDownMenu_Initialize(GMGenie_Spawns_Hyperlink_Menu, GMGenie.Spawns.Hyperlink.loadMenu, "MENU");
+end
+
+function GMGenie.Spawns.Hyperlink.loadMenu(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.isTitle = true;
+ info.text = GMGenie.Spawns.Hyperlink.name;
+ info.fontObject = GenieFontNormalSmall;
+ UIDropDownMenu_AddButton(info, level);
+
+ if GMGenie.Spawns.Hyperlink.type == "gameobject_entry" or GMGenie.Spawns.Hyperlink.type == "creature_entry" then
+ local name;
+ if GMGenie.Spawns.Hyperlink.type == "gameobject_entry" then
+ name = 'gameobject';
+ else
+ name = 'creature';
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Spawn ' .. name .. ' here';
+ info.func = GMGenie.Spawns.Hyperlink.spawnHere;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Add ' .. name .. ' to presets';
+ info.func = GMGenie.Spawns.Hyperlink.addPreset;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'List spawned ' .. name .. 's';
+ info.func = GMGenie.Spawns.Hyperlink.list;
+ UIDropDownMenu_AddButton(info, level);
+ elseif GMGenie.Spawns.Hyperlink.type == "gameobject" or GMGenie.Spawns.Hyperlink.type == "creature" then
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Go to ' .. GMGenie.Spawns.Hyperlink.type;
+ info.func = GMGenie.Spawns.Hyperlink.goTo;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Remove ' .. GMGenie.Spawns.Hyperlink.type;
+ info.func = GMGenie.Spawns.Hyperlink.remove;
+ UIDropDownMenu_AddButton(info, level);
+ end
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Close menu';
+ UIDropDownMenu_AddButton(info, level);
+end
+
+function GMGenie.Spawns.Hyperlink.spawnHere()
+ if GMGenie.Spawns.Hyperlink.type == "gameobject_entry" then
+ SendChatMessage(".gob add " .. GMGenie.Spawns.Hyperlink.id, "GUILD");
+ elseif GMGenie.Spawns.Hyperlink.type == "creature_entry" then
+ SendChatMessage(".npc add " .. GMGenie.Spawns.Hyperlink.id, "GUILD");
+ else
+ GMGnie.showGMMessage("Could not spawn link type " .. GMGenie.Spawns.Hyperlink.type);
+ end
+end
+
+function GMGenie.Spawns.Hyperlink.addPreset()
+ if GMGenie.Spawns.Hyperlink.type == "gameobject_entry" then
+ GMGenie_SavedVars.objects[GMGenie.Spawns.Hyperlink.name] = GMGenie.Spawns.Hyperlink.id;
+ elseif GMGenie.Spawns.Hyperlink.type == "creature_entry" then
+ GMGenie_SavedVars.npcs[GMGenie.Spawns.Hyperlink.name] = GMGenie.Spawns.Hyperlink.id;
+ else
+ GMGnie.showGMMessage("Could not add preset for link type " .. GMGenie.Spawns.Hyperlink.type);
+ end
+end
+
+function GMGenie.Spawns.Hyperlink.list()
+ if GMGenie.Spawns.Hyperlink.type == "gameobject_entry" then
+ SendChatMessage(".list object " .. GMGenie.Spawns.Hyperlink.id, "GUILD");
+ elseif GMGenie.Spawns.Hyperlink.type == "creature_entry" then
+ SendChatMessage(".list creature " .. GMGenie.Spawns.Hyperlink.id, "GUILD");
+ else
+ GMGnie.showGMMessage("Could not list link type " .. GMGenie.Spawns.Hyperlink.type);
+ end
+end
+
+function GMGenie.Spawns.Hyperlink.goTo()
+ if GMGenie.Spawns.Hyperlink.type == "gameobject" then
+ SendChatMessage(".go object " .. GMGenie.Spawns.Hyperlink.id, "GUILD");
+ elseif GMGenie.Spawns.Hyperlink.type == "creature" then
+ SendChatMessage(".go creature " .. GMGenie.Spawns.Hyperlink.id, "GUILD");
+ else
+ GMGnie.showGMMessage("Could not port to link type " .. GMGenie.Spawns.Hyperlink.type);
+ end
+end
+
+function GMGenie.Spawns.Hyperlink.remove()
+ if GMGenie.Spawns.Hyperlink.type == "gameobject" then
+ SendChatMessage(".gob delete " .. GMGenie.Spawns.Hyperlink.id, "GUILD");
+ elseif GMGenie.Spawns.Hyperlink.type == "creature" then
+ SendChatMessage(".npc delete " .. GMGenie.Spawns.Hyperlink.id, "GUILD");
+ else
+ GMGnie.showGMMessage("Could not remove link type " .. GMGenie.Spawns.Hyperlink.type);
+ end
+end
+
+function GMGenie.Spawns.Hyperlink.toggle(link, text)
+ if not link or link == GMGenie.Spawns.Hyperlink.link then
+ GMGenie.Spawns.Hyperlink.name = '';
+ GMGenie.Spawns.Hyperlink.id = '';
+ GMGenie.Spawns.Hyperlink.type = '';
+ else
+ local type, id = strsplit(":", link);
+ GMGenie.Spawns.Hyperlink.type = type;
+ GMGenie.Spawns.Hyperlink.id = id;
+ GMGenie.Spawns.Hyperlink.name = string.match(text, "%[(.*)%]");
+ end
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_Hyperlink_Menu, 'cursor', 0, 0);
+end
+
+local Saved_SetItemRef = SetItemRef;
+function SetItemRef(link, text, button, chatFrame)
+ if (strsub(link, 1, 16) == "gameobject_entry") or (strsub(link, 1, 14) == "creature_entry") or (strsub(link, 1, 10) == "gameobject") or (strsub(link, 1, 8) == "creature") then
+ GMGenie.Spawns.Hyperlink.toggle(link, text);
+ return;
+ end
+ Saved_SetItemRef(link, text, button, chatFrame);
+end
+
+-- add slash command to open/close builder widnow
+SLASH_SPAWNS1 = "/builder";
+SLASH_SPAWNS2 = "/spawns";
+SlashCmdList["SPAWNS"] = GMGenie.Spawns.toggle;
\ No newline at end of file
diff --git a/Spawns.xml b/Spawns.xml
new file mode 100644
index 0000000..743c20b
--- /dev/null
+++ b/Spawns.xml
@@ -0,0 +1,632 @@
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadWindow(self, 'Builder', false, nil);
+
+
+ self:ClearAllPoints();
+ self:SetPoint("LEFT");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_Main_ForwardBackward_Dropdownbuttons,
+ GMGenie_Spawns_Main_ForwardBackward_Direction, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_Main_LeftRight_Dropdownbuttons,
+ GMGenie_Spawns_Main_LeftRight_Direction, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_Main_UpDown_Dropdownbuttons,
+ GMGenie_Spawns_Main_UpDown_Direction, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_Main_Rotate_Dropdownbuttons,
+ GMGenie_Spawns_Main_Rotate_Direction, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_Main_Object_Dropdownbuttons,
+ GMGenie_Spawns_Main_Object_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spawns_Main_Npc_Dropdownbuttons,
+ GMGenie_Spawns_Main_Npc_Dropdown, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.initiateMove(0);
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.initiateMove(-1);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.object(GMGenie_Spawns_Main_Object_Id:GetText());
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.npc(GMGenie_Spawns_Main_Npc_Id:GetText());
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.initiateMove(1);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.initiateMove(2);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.targetObject();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.deleteNpc();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.resetCoords();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.toggleMacroWindow();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadWindow(self, 'Spawn Macro', false, nil);
+
+
+ self:ClearAllPoints();
+ self:SetPoint("LEFT", "GMGenie_Spawns_Main", "RIGHT");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadEditBox(self);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spawns.runMacro();
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Spy.lua b/Spy.lua
new file mode 100644
index 0000000..c73f7d3
--- /dev/null
+++ b/Spy.lua
@@ -0,0 +1,267 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Spy = {};
+GMGenie.Spy.waitingForPin = false;
+GMGenie.Spy.pinCache = "";
+
+function GMGenie.Spy.antiCheat(name)
+ GMGenie.Spy.spy(name);
+ GMGenie.Spy.antiCheatPlayer();
+ GMGenie.Hud.toggleVisibility(false);
+ GMGenie.Spy.appear();
+end
+
+function GMGenie.Spy.spy(name)
+ if not name or string.len(name) < 1 or name == "%t" then
+ name = UnitName("target");
+ end
+ if name and string.len(name) > 1 then
+ GMGenie.Spy.waitingForPin = true;
+ GMGenie.Spy.currentRequest = { account = "", accountId = "", class = "", email = "", gmLevel = "", guid = "", guild = "", ip = "", latency = "", level = "", location = "", login = "", money = "", name = "", phase = "", playedTime = "", race = "" };
+ GMGenie.Spy.clearCache();
+ GMGenie.Spy.resetBoxes();
+ GMGenie.Spy.currentRequest["name"] = name;
+
+ GMGenie.Spy.clearCache();
+ SendChatMessage(".pin " .. name, "GUILD");
+ else
+ GMGenie.showGMMessage("Please enter a name or make sure you have someone targeted.");
+ end
+end
+
+function GMGenie.Spy.clearCache()
+ GMGenie.Spy.pinCache = "";
+end
+
+function GMGenie.Spy.addToCache(pin)
+ GMGenie.Spy.pinCache = GMGenie.Spy.pinCache .. pin .. "\n";
+end
+
+function GMGenie.Spy.processPin01(offline, name1, guid, pin)
+ GMGenie.Spy.currentRequest["name"] = name1;
+ GMGenie.Spy.currentRequest["offline"] = offline;
+ GMGenie.Spy.currentRequest["guid"] = guid;
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin02(phase, pin)
+ GMGenie.Spy.currentRequest["phase"] = phase;
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin03(account, accountId, gmLevel, pin)
+ GMGenie.Spy.currentRequest["account"] = account;
+ GMGenie.Spy.currentRequest["accountId"] = accountId;
+ GMGenie.Spy.currentRequest["gmLevel"] = gmLevel;
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin04(login, failedLogins, pin)
+ GMGenie.Spy.currentRequest["login"] = login;
+ -- todo failedLogins
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin05(os, latency, email, pin)
+ -- todo os
+ GMGenie.Spy.currentRequest["email"] = email;
+ GMGenie.Spy.currentRequest["latency"] = latency;
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin06(ip, locked, pin)
+ GMGenie.Spy.currentRequest["ip"] = ip;
+ -- todo locked
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin07(level, xpCurrent, xpMax, pin)
+ GMGenie.Spy.currentRequest["level"] = level;
+ -- todo xp
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin08(race, class, pin)
+ GMGenie.Spy.currentRequest["race"] = race;
+ GMGenie.Spy.currentRequest["class"] = class;
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin09(alive, pin)
+ -- todo alive
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin10(money, pin)
+ GMGenie.Spy.currentRequest["money"] = money;
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin11(map, area, zone, pin)
+ GMGenie.Spy.currentRequest["location"] = map;
+ if map ~= area then
+ GMGenie.Spy.currentRequest["location"] = area .. ', ' .. GMGenie.Spy.currentRequest["location"];
+ end
+ if string.upper(zone) ~= '' then
+ GMGenie.Spy.currentRequest["location"] = zone .. ', ' .. GMGenie.Spy.currentRequest["location"];
+ end
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin12(guild, guildId, pin)
+ GMGenie.Spy.currentRequest["guild"] = '<' .. guild .. '> (' .. guildId .. ')';
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin13(guildRank, pin)
+ GMGenie.Spy.currentRequest["guild"] = '"' .. guildRank .. '" of ' .. GMGenie.Spy.currentRequest["guild"];
+
+ GMGenie.Spy.addToCache(pin);
+end
+
+function GMGenie.Spy.processPin14(playedTime, pin)
+ GMGenie.Spy.currentRequest["playedTime"] = playedTime;
+
+ GMGenie.Spy.addToCache(pin);
+
+ GMGenie.Spy.waitingForPin = false;
+ GMGenie.Spy.resetBoxes();
+ GMGenie_Spy_InfoWindow:Show();
+end
+
+function GMGenie.Spy.resetBoxes()
+ GMGenie_Spy_InfoWindow_Info_CharInfo:SetText("Level " .. GMGenie.Spy.currentRequest["level"] .. " " .. GMGenie.Spy.currentRequest["race"] .. " " .. GMGenie.Spy.currentRequest["class"]);
+ GMGenie_Spy_InfoWindow_Info_Guild:SetText(GMGenie.Spy.currentRequest["guild"]);
+ GMGenie_Spy_InfoWindow_Title_Text:SetText(GMGenie.Spy.currentRequest["name"]);
+ GMGenie_Spy_InfoWindow_Character_Name:SetText(GMGenie.Spy.currentRequest["name"]);
+ GMGenie_Spy_InfoWindow_Character_Id:SetText(GMGenie.Spy.currentRequest["guid"]);
+ GMGenie_Spy_InfoWindow_Account_Name:SetText(GMGenie.Spy.currentRequest["account"]);
+ GMGenie_Spy_InfoWindow_Account_Id:SetText(GMGenie.Spy.currentRequest["accountId"]);
+ GMGenie_Spy_InfoWindow_Email_Email:SetText(GMGenie.Spy.currentRequest["email"]);
+ GMGenie_Spy_InfoWindow_IpLat_Ip:SetText(GMGenie.Spy.currentRequest["ip"]);
+ if tonumber(GMGenie.Spy.currentRequest["latency"]) and tonumber(GMGenie.Spy.currentRequest["latency"]) > 1000 then
+ GMGenie_Spy_InfoWindow_IpLat_Latency:SetFontObject(GenieFontRedSmall);
+ else
+ GMGenie_Spy_InfoWindow_IpLat_Latency:SetFontObject(GenieFontHighlightSmall);
+ end
+ GMGenie_Spy_InfoWindow_IpLat_Latency:SetText(GMGenie.Spy.currentRequest["latency"]);
+ GMGenie_Spy_InfoWindow_LastLogin_LastLogin:SetText(GMGenie.Spy.currentRequest["login"]);
+ GMGenie_Spy_InfoWindow_PlayedGM_PlayedTime:SetText(GMGenie.Spy.currentRequest["playedTime"]);
+ GMGenie_Spy_InfoWindow_PlayedGM_GM:SetText(GMGenie.Spy.currentRequest["gmLevel"]);
+ GMGenie_Spy_InfoWindow_MoneyPhase_Money:SetText(GMGenie.Spy.currentRequest["money"]);
+ GMGenie_Spy_InfoWindow_MoneyPhase_Phase:SetText(GMGenie.Spy.currentRequest["phase"]);
+ GMGenie_Spy_InfoWindow_Location_Location:SetText(GMGenie.Spy.currentRequest["location"]);
+ GMGenie_Spy_InfoWindow_Location_Location:SetCursorPosition(0);
+end
+
+function GMGenie.Spy.loadDropdown(self, level)
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Ban Info';
+ info.func = GMGenie.Spy.banInfo;
+ UIDropDownMenu_AddButton(info, level);
+
+ local info = UIDropDownMenu_CreateInfo();
+ info.hasArrow = false;
+ info.notCheckable = true;
+ info.text = 'Lookup Player';
+ info.func = GMGenie.Spy.lookupPlayer;
+ UIDropDownMenu_AddButton(info, level);
+end
+
+SLASH_SPY1 = "/spy";
+SlashCmdList["SPY"] = GMGenie.Spy.spy;
+
+function GMGenie.Spy.copyPin()
+ GMGenie.showGMMessage(GMGenie.Spy.pinCache);
+end
+
+function GMGenie.Spy.whisper()
+ ChatFrame_SendTell(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.summon()
+ GMGenie.Macros.summon(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.appear()
+ GMGenie.Macros.appear(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.revive()
+ GMGenie.Macros.revive(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.freeze()
+ GMGenie.Macros.freeze(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.unfreeze()
+ GMGenie.Macros.unfreeze(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.rename()
+ GMGenie.Macros.rename(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.antiCheatPlayer()
+ GMGenie.Macros.antiCheatPlayer(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.customize()
+ GMGenie.Macros.customize(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.changefaction()
+ GMGenie.Macros.changefaction(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.changerace()
+ GMGenie.Macros.changerace(GMGenie.Spy.currentRequest["name"]);
+end
+
+function GMGenie.Spy.banInfo()
+ CloseDropDownMenus()
+ SendChatMessage(".baninfo account " .. GMGenie.Spy.currentRequest["account"], "GUILD");
+ SendChatMessage(".baninfo character " .. GMGenie.Spy.currentRequest["name"], "GUILD");
+ SendChatMessage(".baninfo ip " .. GMGenie.Spy.currentRequest["ip"], "GUILD");
+end
+
+function GMGenie.Spy.lookupPlayer()
+ CloseDropDownMenus()
+ SendChatMessage(".lookup player account " .. GMGenie.Spy.currentRequest["account"], "GUILD");
+ SendChatMessage(".lookup player email " .. GMGenie.Spy.currentRequest["email"], "GUILD");
+ SendChatMessage(".lookup player ip " .. GMGenie.Spy.currentRequest["ip"], "GUILD");
+end
+
+local Saved_SetItemRef = SetItemRef;
+function SetItemRef(link, text, button, chatFrame)
+ if (strsub(link, 1, 9) == "anticheat") then
+ local type, name = strsplit(":", link);
+ if (button == "LeftButton") then
+ GMGenie.Spy.antiCheat(name);
+ elseif (button == "RightButton") then
+ FriendsFrame_ShowDropdown(name, 1);
+ end
+ return;
+ end
+ Saved_SetItemRef(link, text, button, chatFrame);
+end
\ No newline at end of file
diff --git a/Spy.xml b/Spy.xml
new file mode 100644
index 0000000..39ece11
--- /dev/null
+++ b/Spy.xml
@@ -0,0 +1,573 @@
+
+
+
+
+
+ GMGenie.Spy.resetBoxes();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:ClearAllPoints();
+ self:SetPoint("LEFT", GMGenie_Tickets_View, "RIGHT");
+
+
+ if (button == "RightButton") then
+ GMGenie.Spy.copyPin();
+ end
+
+
+ GMGenie.loadWindow(self, 'Loading...', true, function()
+ GMGenie.Spy.spy(GMGenie.Spy.currentRequest["name"]); end);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spy.whisper();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_NONE");
+ GameTooltip:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -CONTAINER_OFFSET_X - 13,
+ CONTAINER_OFFSET_Y);
+ GameTooltip:AddLine("Whisper");
+ GameTooltip:AddLine("Left click to send a whisper to ".. GMGenie.Spy.currentRequest["name"]
+ ..".");
+ GameTooltip:Show();
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spy_InfoWindow_DropdownbuttonsOne,
+ GMGenie_Spy_InfoWindow_Macros, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ToggleDropDownMenu(1, nil, GMGenie_Spy_InfoWindow_DropdownbuttonsTwo,
+ GMGenie_Spy_InfoWindow_Advanced, 0, 0);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Spy.revive();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_NONE");
+ GameTooltip:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -CONTAINER_OFFSET_X - 13,
+ CONTAINER_OFFSET_Y);
+ GameTooltip:AddLine("Revive");
+ GameTooltip:AddLine("Revive player ".. GMGenie.Spy.currentRequest["name"] ..".");
+ GameTooltip:Show();
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if (button == "RightButton") then
+ GMGenie.Spy.unfreeze();
+ else
+ GMGenie.Spy.freeze();
+ end
+
+
+ self:RegisterForClicks("LeftButtonUp","RightButtonUp");
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_NONE");
+ GameTooltip:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -CONTAINER_OFFSET_X - 13,
+ CONTAINER_OFFSET_Y);
+ GameTooltip:AddLine("Freeze / Unfreeze");
+ GameTooltip:AddLine("Left click to freeze.");
+ GameTooltip:AddLine("Right click to unfreeze.");
+ GameTooltip:Show();
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:RegisterForClicks("LeftButtonUp","RightButtonUp");
+
+
+ if (button == "RightButton") then
+ GMGenie.Spy.summon();
+ else
+ GMGenie.Spy.appear();
+ end
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_NONE");
+ GameTooltip:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -CONTAINER_OFFSET_X - 13,
+ CONTAINER_OFFSET_Y);
+ GameTooltip:AddLine("Appear/Summon");
+ GameTooltip:AddLine("Left click to appear.");
+ GameTooltip:AddLine("Right click to summon.");
+ GameTooltip:Show();
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Textures/Genie.tga b/Textures/Genie.tga
new file mode 100644
index 0000000..a0e05d9
Binary files /dev/null and b/Textures/Genie.tga differ
diff --git a/Tickets.lua b/Tickets.lua
new file mode 100644
index 0000000..a24ab42
--- /dev/null
+++ b/Tickets.lua
@@ -0,0 +1,496 @@
+--This file is part of Game Master Genie.
+--Copyright 2011-2014 Chocochaos
+
+--Game Master Genie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
+--Game Master Genie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--You should have received a copy of the GNU General Public License along with Game Master Genie. If not, see .
+
+GMGenie.Tickets = {};
+
+-- config
+GMGenie.Tickets.perPage = 10;
+
+-- vars
+GMGenie.Tickets.pages = 1;
+GMGenie.Tickets.tickets = 0;
+GMGenie.Tickets.onlineTickets = 0;
+GMGenie.Tickets.currentPage = 1;
+GMGenie.Tickets.currentTicket = { ["num"] = 0, ["ticketId"] = 0, ['name'] = "", ["message"] = "" };
+GMGenie.Tickets.order = "ticketId";
+GMGenie.Tickets.ascDesc = false;
+GMGenie.Tickets.messageOpen = false;
+GMGenie.Tickets.done = 0;
+GMGenie.Tickets.syncList = {};
+GMGenie.Tickets.loadingOnline = false;
+--GMGenie.Tickets.Colours = { ["onlineUnread"] = "ffbfbfff", ["onlineRead"] = "ffffffff", ["offlineUnread"] = "ff5f5f80", ["offlineRead"] = "ff808080" };
+GMGenie.Tickets.Colours = { ["current"] = "ffffffff", ["onlineUnread"] = "ffbfbfff", ["onlineRead"] = "ff5f5f7f", ["offlineUnread"] = "ffff0000", ["offlineRead"] = "ff7f0000" };
+
+-- ticket list
+GMGenie.Tickets.list = {};
+GMGenie.Tickets.read = {};
+GMGenie.Tickets.idToNum = {};
+
+function GMGenie.Tickets.onLoad()
+ Chronos.scheduleRepeating('ticketrefresh', 60, GMGenie.Tickets.refresh);
+ GMGenie.Tickets.refresh();
+ GMGenie.Tickets.done = GMGenie_SavedVars.ticketsDone;
+end
+
+-- refresh ticket list & schedule next refresh
+function GMGenie.Tickets.refresh()
+ if not GMGenie.Tickets.tempList then
+ -- create empty list
+ GMGenie.Tickets.tempList = {};
+ GMGenie.Tickets.idToNum = {};
+ GMGenie.Tickets.tickets = 0;
+ GMGenie.Tickets.onlineTickets = 0;
+ GMGenie.Tickets.loadingOnline = false;
+ -- get ticket list
+ SendChatMessage(".ticket list", "GUILD");
+ -- schedule next refresh
+ Chronos.scheduleByName('ticketreupdate', 3, GMGenie.Tickets.update);
+ elseif GMGenie.Tickets.loadingOnline then
+ SendChatMessage(".ticket onlinelist", "GUILD");
+ Chronos.scheduleByName('ticketreupdate', 3, GMGenie.Tickets.update);
+ end
+end
+
+-- add ticket from chat list to the addon list
+function GMGenie.Tickets.listTicket(ticketId, name, createStr, createStamp, lastModifiedStr, lastModifiedStamp)
+ local ticketInfo = { ["ticketId"] = ticketId, ["name"] = name, ["createStr"] = createStr, ["createStamp"] = createStamp, ["lastModifiedStr"] = lastModifiedStr, ["lastModifiedStamp"] = lastModifiedStamp, ["assignedTo"] = "", ['online'] = GMGenie.Tickets.loadingOnline };
+ if GMGenie.Tickets.tempList and not GMGenie.Tickets.idToNum[ticketId] and not GMGenie.Tickets.loadingOnline then
+ -- add to temp list if page is being refreshed
+ table.insert(GMGenie.Tickets.tempList, ticketInfo);
+ GMGenie.Tickets.tickets = GMGenie.Tickets.tickets + 1;
+ GMGenie.Tickets.idToNum[ticketId] = GMGenie.Tickets.tickets;
+ elseif GMGenie.Tickets.tempList and GMGenie.Tickets.loadingOnline then
+ GMGenie.Tickets.onlineTickets = GMGenie.Tickets.onlineTickets + 1;
+ if GMGenie.Tickets.idToNum[ticketId] then
+ GMGenie.Tickets.tempList[GMGenie.Tickets.idToNum[ticketId]] = ticketInfo;
+ else
+ table.insert(GMGenie.Tickets.tempList, ticketInfo);
+ GMGenie.Tickets.tickets = GMGenie.Tickets.tickets + 1;
+ GMGenie.Tickets.idToNum[ticketId] = GMGenie.Tickets.tickets;
+ end
+ end
+ -- if no new tickets come in the chat for 1 second, update the list
+ Chronos.scheduleByName('ticketreupdate', 0.25, GMGenie.Tickets.update);
+end
+
+-- set assignedTo for a ticket
+function GMGenie.Tickets.setAssigned(ticketId, assignedTo)
+ -- ticket list currently being refreshed or not?
+ if GMGenie.Tickets.tempList and GMGenie.Tickets.idToNum[ticketId] then
+ GMGenie.Tickets.tempList[GMGenie.Tickets.idToNum[ticketId]]["assignedTo"] = assignedTo;
+ elseif GMGenie.Tickets.idToNum[ticketId] then
+ GMGenie.Tickets.list[GMGenie.Tickets.idToNum[ticketId]]["assignedTo"] = assignedTo;
+ else
+ Chronos.schedule(0.2, GMGenie.Tickets.setAssigned, ticketId, assignedTo);
+ end
+end
+
+-- update ticket list
+function GMGenie.Tickets.update()
+ -- Check onlines too?
+ if not GMGenie.Tickets.loadingOnline then
+ GMGenie.Tickets.loadingOnline = true;
+ GMGenie.Tickets.refresh();
+ else
+ GMGenie.Tickets.loadingOnline = false;
+
+ -- move temp list to current list and empty temp list
+ if GMGenie.Tickets.tempList then
+ GMGenie.Tickets.list = GMGenie.Tickets.tempList;
+ GMGenie.Tickets.tempList = nil;
+ end
+ -- calc number of pages
+ if GMGenie_SavedVars.showOfflineTickets then
+ GMGenie.Tickets.pages = math.ceil(GMGenie.Tickets.tickets / GMGenie.Tickets.perPage);
+ else
+ GMGenie.Tickets.pages = math.ceil(GMGenie.Tickets.onlineTickets / GMGenie.Tickets.perPage);
+ end
+ -- allways at least 1 page
+ if GMGenie.Tickets.pages < 1 then
+ GMGenie.Tickets.pages = 1;
+ end
+ -- does the page currently being viewed still exist?
+ if GMGenie.Tickets.currentPage > GMGenie.Tickets.pages then
+ GMGenie.Tickets.currentPage = GMGenie.Tickets.pages;
+ end
+ -- order ticket list
+ GMGenie.Tickets.sort();
+ end
+end
+
+-- change ordering for ticket list
+function GMGenie.Tickets.changeOrder(order)
+ if GMGenie.Tickets.order == order then
+ if GMGenie.Tickets.ascDesc then
+ GMGenie.Tickets.ascDesc = false;
+ else
+ GMGenie.Tickets.ascDesc = true;
+ end
+ else
+ GMGenie.Tickets.order = order;
+ GMGenie.Tickets.ascDesc = false;
+ end
+ GMGenie.Tickets.currentPage = 1;
+ GMGenie.Tickets.sort();
+end
+
+-- order ticket list
+function GMGenie.Tickets.sort()
+ if GMGenie.Tickets.ascDesc then
+ table.sort(GMGenie.Tickets.list, function(a, b) return a[GMGenie.Tickets.order] > b[GMGenie.Tickets.order] end);
+ else
+ table.sort(GMGenie.Tickets.list, function(a, b) return a[GMGenie.Tickets.order] < b[GMGenie.Tickets.order] end);
+ end
+
+ -- update idToNum table
+ GMGenie.Tickets.idToNum = {};
+ for ticketNum, ticketInfo in ipairs(GMGenie.Tickets.list) do
+ GMGenie.Tickets.idToNum[ticketInfo["ticketId"]] = ticketNum;
+ end
+
+ -- update the ticket window
+ GMGenie.Tickets.updateView();
+end
+
+-- update the ticket window
+function GMGenie.Tickets.updateView()
+ -- Page x of y (z tickets)
+ local offlineCount = GMGenie.Tickets.tickets - GMGenie.Tickets.onlineTickets;
+
+ local plural = { ["total"] = "s", ["online"] = "s", ["offline"] = "s" };
+ if GMGenie.Tickets.onlineTickets == 1 then
+ plural["online"] = "";
+ end
+ if offlineCount == 1 then
+ plural["offline"] = "";
+ end
+ if GMGenie.Tickets.tickets == 1 then
+ plural["total"] = "";
+ end
+
+ GMGenie_Tickets_Main_Info_Text:SetText(GMGenie.Tickets.tickets .. " ticket" .. plural["total"] .. " (|c" .. GMGenie.Tickets.Colours["onlineUnread"] .. GMGenie.Tickets.onlineTickets .. " online,|r |c" .. GMGenie.Tickets.Colours["offlineUnread"] .. offlineCount .. " offline|r), " .. GMGenie.Tickets.done .. " done");
+ GMGenie_Tickets_Main_Info_Page:SetText("Page " .. GMGenie.Tickets.currentPage .. " of " .. GMGenie.Tickets.pages);
+
+ GMGenie_Hud_Tickets:SetText("Tickets (|c" .. GMGenie.Tickets.Colours["onlineUnread"] .. GMGenie.Tickets.onlineTickets .. "|r / |c" .. GMGenie.Tickets.Colours["offlineUnread"] .. offlineCount .. "|r)");
+
+ -- previous page
+ if (GMGenie.Tickets.currentPage == 1) then
+ GMGenie_Tickets_Main_Previous:Disable();
+ else
+ GMGenie_Tickets_Main_Previous:Enable();
+ end
+
+ -- next page
+ if (GMGenie.Tickets.currentPage == GMGenie.Tickets.pages) then
+ GMGenie_Tickets_Main_Next:Disable();
+ else
+ GMGenie_Tickets_Main_Next:Enable();
+ end
+
+ -- start and end of the list on the current page
+ local minTicket = 1 + ((GMGenie.Tickets.currentPage - 1) * GMGenie.Tickets.perPage);
+ local maxTicket = GMGenie.Tickets.currentPage * GMGenie.Tickets.perPage;
+ local num = 1;
+ local i = 0;
+
+ -- reset num
+ GMGenie.Tickets.currentTicket["num"] = 0;
+
+ -- loop through tickets
+ for ticketNum, ticketInfo in ipairs(GMGenie.Tickets.list) do
+ -- Show ticket?
+ if ticketInfo["online"] or GMGenie_SavedVars.showOfflineTickets then
+ i = i + 1;
+ if i >= minTicket and i <= maxTicket then
+ -- colour in list
+ local colour;
+ if ticketInfo["ticketId"] == GMGenie.Tickets.currentTicket["ticketId"] then
+ colour = GMGenie.Tickets.Colours["current"];
+ else
+ if GMGenie.Tickets.read[ticketInfo["ticketId"]] then
+ if ticketInfo["online"] then
+ colour = GMGenie.Tickets.Colours["onlineRead"];
+ else
+ colour = GMGenie.Tickets.Colours["offlineRead"];
+ end
+ else
+ if ticketInfo["online"] then
+ colour = GMGenie.Tickets.Colours["onlineUnread"];
+ else
+ colour = GMGenie.Tickets.Colours["offlineUnread"];
+ end
+ end
+ end
+
+ -- set ticket info
+ getglobal("TicketStatusButton" .. num .. "_ticketId"):SetText("|c" .. colour .. ticketInfo["ticketId"] .. "|r");
+ getglobal("TicketStatusButton" .. num .. "_name"):SetText("|c" .. colour .. ticketInfo["name"] .. "|r");
+ getglobal("TicketStatusButton" .. num .. "_createStr"):SetText("|c" .. colour .. ticketInfo["createStr"] .. "|r");
+ getglobal("TicketStatusButton" .. num .. "_lastModifiedStr"):SetText("|c" .. colour .. ticketInfo["lastModifiedStr"] .. "|r");
+ getglobal("TicketStatusButton" .. num .. "_assignedTo"):SetText("|c" .. colour .. ticketInfo["assignedTo"] .. "|r");
+ getglobal("TicketStatusButton" .. num):Show();
+
+ getglobal("TicketStatusButton" .. num).ticketId = ticketInfo["ticketId"];
+
+ -- number on the ticket window
+ num = num + 1;
+ end
+ end
+ end
+ if num <= GMGenie.Tickets.perPage then
+ for num = num, GMGenie.Tickets.perPage do
+ getglobal("TicketStatusButton" .. num):Hide();
+ end
+ end
+end
+
+-- next page
+function GMGenie.Tickets.goToNext()
+ if GMGenie.Tickets.currentPage < GMGenie.Tickets.pages then
+ GMGenie.Tickets.currentPage = GMGenie.Tickets.currentPage + 1;
+ GMGenie.Tickets.updateView();
+ end
+end
+
+-- previous page
+function GMGenie.Tickets.goToPrevious()
+ if GMGenie.Tickets.currentPage > 1 then
+ GMGenie.Tickets.currentPage = GMGenie.Tickets.currentPage - 1;
+ GMGenie.Tickets.updateView();
+ end
+end
+
+-- mark ticket as read
+function GMGenie.Tickets.markAsRead(ticketId)
+ GMGenie.Tickets.read[ticketId] = true;
+ GMGenie.Tickets.updateView();
+end
+
+-- mark ticket as unread
+function GMGenie.Tickets.markAsUnread(ticketId)
+ GMGenie.Tickets.ReadTickets[ticketId] = false;
+end
+
+function GMGenie.Tickets.isOpen()
+ local frame = GMGenie_Tickets_Main;
+ if (frame) then
+ return frame:IsVisible();
+ end
+end
+
+-- hide or show ticket window
+function GMGenie.Tickets.toggle(showOffline)
+ if GMGenie.Tickets.isOpen() then
+ -- hide window
+ GMGenie_Tickets_Main:Hide();
+ else
+ if showOffline and not GMGenie_SavedVars.showOfflineTickets then
+ GMGenie.Tickets.toggleOfflineTickets();
+ end
+ -- refresh ticket list and initiate auto-refresh
+ GMGenie.Tickets.onLoad();
+ -- show window
+ GMGenie_Tickets_Main:Show();
+ end
+end
+
+-- load ticket
+function GMGenie.Tickets.loadTicket(ticketId, num)
+ if (GMGenie.Tickets.currentTicket["ticketId"] and GMGenie.Tickets.currentTicket["ticketId"] == ticketId) then
+ GMGenie.Tickets.close();
+ return;
+ else
+ if GMGenie.Tickets.idToNum[ticketId] then
+ if GMGenie.Tickets.list[GMGenie.Tickets.idToNum[ticketId]]["name"] then
+ -- update current ticket
+ GMGenie.Tickets.currentTicket = { ["num"] = num, ["ticketId"] = ticketId, ["name"] = GMGenie.Tickets.list[GMGenie.Tickets.idToNum[ticketId]]["name"], ["comment"] = "", ["message"] = "Loading..." };
+ -- set title and loading text
+ GMGenie_Tickets_View_Title_Text:SetText(GMGenie.Tickets.currentTicket["name"] .. "'s Ticket");
+ GMGenie.Tickets.showMessage();
+ -- hide reading frame UNUSED ATM
+ --GMGenie_Tickets_View_Ticket_Reading:Hide();
+ -- get ticket
+ SendChatMessage(".ticket viewid " .. ticketId, "GUILD");
+ -- open spy
+ if GMGenie_SavedVars.useSpy then
+ GMGenie.Spy.spy(GMGenie.Tickets.currentTicket["name"]);
+ end
+ -- mark as read
+ GMGenie.Tickets.markAsRead(ticketId);
+ -- toggle frame
+ GMGenie_Tickets_View:Show();
+ if GMGenie_SavedVars.swapTicketWindows then
+ GMGenie.Tickets.toggle();
+ end
+ -- chronos schedule and send message
+ Chronos.scheduleRepeating('ticketSync', 30, GMGenie.Tickets.sync);
+ GMGenie.Tickets.sync();
+ GMGenie.Tickets.displaySync()
+ return;
+ end
+ end
+ end
+ Chronos.schedule(0.2, GMGenie.Tickets.loadTicket, ticketId, num);
+end
+
+function GMGenie.Tickets.displaySync()
+ local names = {};
+ local num = 0;
+ for name, ticketId in pairs(GMGenie.Tickets.syncList) do
+ if tonumber(ticketId) == tonumber(GMGenie.Tickets.currentTicket["ticketId"]) then
+ table.insert(names, name);
+ num = num + 1;
+ end
+ end
+
+ if num > 0 then
+ local text = "";
+ for index, name in ipairs(names) do
+ text = text .. name;
+ if index == (num - 1) then
+ text = text .. " and ";
+ elseif index < (num - 1) then
+ text = text .. ", ";
+ end
+ end
+ GMGenie_Tickets_View_Sync_Names:SetText(text);
+ GMGenie_Tickets_View_Ticket:SetHeight(150);
+ GMGenie_Tickets_View_Ticket_Frame:SetHeight(150);
+ GMGenie_Tickets_View_Ticket_Frame_Text:SetHeight(150);
+ GMGenie_Tickets_View_Sync:Show();
+ else
+ GMGenie_Tickets_View_Ticket:SetHeight(173);
+ GMGenie_Tickets_View_Ticket_Frame:SetHeight(173);
+ GMGenie_Tickets_View_Ticket_Frame_Text:SetHeight(173);
+ GMGenie_Tickets_View_Sync:Hide();
+ end
+end
+
+function GMGenie.Tickets.sync()
+ SendAddonMessage("GMGenie_Sync", GMGenie.Tickets.currentTicket["ticketId"], "GUILD");
+end
+
+function GMGenie.Tickets.syncMessage(name, ticketId)
+ if UnitName("player") ~= name then
+ if not (GMGenie.Tickets.syncList[name] and GMGenie.Tickets.syncList[name] == ticketId) then
+ GMGenie.Tickets.syncList[name] = ticketId;
+ if ticketId == 0 then
+ Chronos.unscheduleByName('ticketSync' .. name);
+ else
+ Chronos.scheduleByName('ticketSync' .. name, 35, GMGenie.Tickets.syncMessage, name, 0);
+ end
+ GMGenie.Tickets.displaySync();
+ else
+ Chronos.scheduleByName('ticketSync' .. name, 35, GMGenie.Tickets.syncMessage, name, 0);
+ end
+ end
+end
+
+function GMGenie.Tickets.loadComment(comment)
+ GMGenie.Tickets.currentTicket["comment"] = comment;
+ GMGenie.Tickets.showMessage();
+end
+
+function GMGenie.Tickets.showMessage()
+ GMGenie_Tickets_View_Ticket_Frame_Text:SetText(GMGenie.Tickets.currentTicket["message"]);
+ GMGenie_Tickets_View_Comment:SetText(GMGenie.Tickets.currentTicket["comment"]);
+end
+
+function GMGenie.Tickets.close()
+ if GMGenie.Spy.currentRequest["name"] == GMGenie.Tickets.currentTicket["name"] then
+ GMGenie_Spy_InfoWindow:Hide();
+ end
+ SendAddonMessage("GMGenie_Sync", "0", "GUILD");
+ Chronos.unscheduleRepeating('ticketSync');
+ GMGenie_Tickets_View:Hide();
+ GMGenie.Tickets.currentTicket = { ["num"] = 0, ["ticketId"] = 0, ['name'] = "" };
+ if GMGenie_SavedVars.swapTicketWindows then
+ GMGenie.Tickets.toggle();
+ end
+ GMGenie.Tickets.updateView();
+end
+
+-- read ticket
+function GMGenie.Tickets.readTicket(ticketId, message)
+ if GMGenie.Tickets.currentTicket["ticketId"] == ticketId then
+ GMGenie.Tickets.currentTicket["message"] = message;
+ GMGenie.Tickets.showMessage();
+ return true;
+ end
+ return false;
+end
+
+-- set comment
+function GMGenie.Tickets.comment(ticketId, comment)
+ if GMGenie.Tickets.currentTicket["ticketId"] == ticketId then
+ GMGenie.Tickets.currentTicket["comment"] = comment;
+ GMGenie.Tickets.showMessage();
+ return true;
+ end
+ return false;
+end
+
+--add line to ticket
+function GMGenie.Tickets.addLine(message)
+ GMGenie.Tickets.currentTicket["message"] = GMGenie.Tickets.currentTicket["message"] .. "\n" .. message;
+ GMGenie.Tickets.showMessage();
+end
+
+function GMGenie.Tickets.delete()
+ SendChatMessage(".ticket close " .. GMGenie.Tickets.currentTicket["ticketId"], "GUILD");
+ SendChatMessage(".ticket del " .. GMGenie.Tickets.currentTicket["ticketId"], "GUILD");
+ GMGenie.Tickets.done = GMGenie.Tickets.done + 1;
+ GMGenie_SavedVars.ticketsDone = GMGenie.Tickets.done;
+ local offlineCount = GMGenie.Tickets.tickets - GMGenie.Tickets.onlineTickets;
+ GMGenie.Tickets.close();
+ GMGenie.Tickets.refresh();
+end
+
+function GMGenie.Tickets.assignToSelf()
+ SendChatMessage(".ticket assign " .. GMGenie.Tickets.currentTicket["ticketId"] .. " " .. UnitName("player"), "GUILD");
+end
+
+function GMGenie.Tickets.assign()
+ GMGenie_Tickets_AssignPopup:Show();
+ GMGenie_Tickets_AssignPopup_GMName:SetText("");
+end
+
+function GMGenie.Tickets.assignTo()
+ GMGenie_Tickets_AssignPopup:Hide();
+ SendChatMessage(".ticket assign " .. GMGenie.Tickets.currentTicket["ticketId"] .. " " .. GMGenie_Tickets_AssignPopup_GMName:GetText(), "GUILD");
+end
+
+function GMGenie.Tickets.unassign()
+ SendChatMessage(".ticket unassign " .. GMGenie.Tickets.currentTicket["ticketId"], "GUILD");
+end
+
+function GMGenie.Tickets.setComment()
+ SendChatMessage(".ticket comment " .. GMGenie.Tickets.currentTicket["ticketId"] .. " " .. GMGenie_Tickets_View_Comment:GetText(), "GUILD");
+end
+
+function GMGenie.Tickets.toggleSpy()
+ if GMGenie_Spy_InfoWindow:IsVisible() and GMGenie.Tickets.currentTicket["name"] == GMGenie.Spy.currentRequest["name"] then
+ GMGenie_Spy_InfoWindow:Hide();
+ else
+ GMGenie.Spy.spy(GMGenie.Tickets.currentTicket["name"]);
+ end
+end
+
+-- add slash command to open.close ticket widnow
+SLASH_TICKETS1 = "/tickets";
+SlashCmdList["TICKETS"] = GMGenie.Tickets.toggle;
+
+local frame = CreateFrame("FRAME");
+frame:RegisterEvent("CHAT_MSG_ADDON");
+
+function frame:OnEvent(event, arg1)
+ if event == "CHAT_MSG_ADDON" and (arg1 == "GMGenie_TicketSync" or arg1 == "GMGenie_Sync") then
+ GMGenie.Tickets.syncMessage(arg4, arg2);
+ end
+end
+
+frame:SetScript("OnEvent", frame.OnEvent);
\ No newline at end of file
diff --git a/Tickets.xml b/Tickets.xml
new file mode 100644
index 0000000..97c2f8c
--- /dev/null
+++ b/Tickets.xml
@@ -0,0 +1,537 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.ticketId = 0;
+
+
+ GMGenie.Tickets.loadTicket(self.ticketId, tonumber(string.sub(self:GetName(), 19)));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadWindow(self, 'Tickets', true, function() GMGenie.Tickets.refresh(); end);
+
+
+ self:ClearAllPoints();
+ self:SetPoint("TOPLEFT");
+
+
+ if arg1 == 1 then
+ GMGenie.Tickets.goToPrevious();
+ else
+ GMGenie.Tickets.goToNext();
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.changeOrder("ticketId");
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.changeOrder("name");
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.changeOrder("createStamp");
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.changeOrder("lastModifiedStamp");
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.changeOrder("assignedTo");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.goToNext();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.goToPrevious();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.toggleOfflineTickets();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:ClearAllPoints();
+ self:SetPoint("LEFT", GMGenie_Tickets_Main, "RIGHT");
+
+
+ GMGenie.Tickets.close();
+
+
+ GMGenie.loadWindow(self, 'Loading...', false, nil);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadEditBox(self);
+ getglobal(self:GetName().."_Frame_Text"):SetAutoFocus(false);
+ getglobal(self:GetName().."_Frame_Text"):SetScript("OnChar", GMGenie.Tickets.showMessage);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.setComment();
+ self:ClearFocus();
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.setComment();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.delete();
+
+
+
+
+
+
+
+
+
+ self:RegisterForClicks("LeftButtonUp","RightButtonUp");
+
+
+ if (button == "RightButton") then
+ GMGenie.Tickets.assign();
+ else
+ GMGenie.Tickets.assignToSelf();
+ end
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_NONE");
+ GameTooltip:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -CONTAINER_OFFSET_X - 13,
+ CONTAINER_OFFSET_Y);
+ GameTooltip:AddLine("Assign ticket");
+ GameTooltip:AddLine("Left click to assign to self.");
+ GameTooltip:AddLine("Right click to assign to someone else.");
+ GameTooltip:Show();
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.unassign();
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.toggleSpy();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.loadWindow(self, 'Assign To', false, nil);
+ getglobal(self:GetName().."_Title_Text"):SetText("Assign To");
+
+
+ self:ClearAllPoints();
+ self:SetPoint("TOP", GMGenie_Tickets_View, "BOTTOM");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.assignTo();
+
+
+
+
+
+
+
+
+
+ GMGenie.Tickets.assignTo();
+
+
+
+
+
+
\ No newline at end of file