Skip to content

Instantly share code, notes, and snippets.

Created July 22, 2017 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/b1f2a5572ad1c7d9175eecf8af65808f to your computer and use it in GitHub Desktop.
Save anonymous/b1f2a5572ad1c7d9175eecf8af65808f to your computer and use it in GitHub Desktop.
GC5 fixes
----------------------------------------
-- Group Calendar 5 Copyright 2005 - 2016 John Stephen, wobbleworks.com
-- All rights reserved, unauthorized redistribution is prohibited
----------------------------------------
local _
GroupCalendar.cBlizzardCalendarFunctionNames =
{
"CalendarAddEvent",
"CalendarCanAddEvent",
"CalendarCanSendInvite",
"CalendarCloseEvent",
"CalendarContextEventCanComplain",
"CalendarContextEventCanEdit",
"CalendarContextEventClipboard",
"CalendarContextEventComplain",
"CalendarContextEventCopy",
"CalendarContextEventIsGuildWide",
"CalendarContextInviteAvailable",
"CalendarContextInviteDecline",
"CalendarContextInviteRemove",
"CalendarContextInviteTentative",
"CalendarContextEventPaste",
"CalendarContextEventRemove",
"CalendarContextEventSignUp",
"CalendarContextInviteIsPending",
"CalendarContextInviteStatus",
"CalendarContextSelectEvent",
"CalendarDefaultGuildFilter",
"CalendarEventAvailable",
"CalendarEventCanEdit",
"CalendarEventClearAutoApprove",
"CalendarEventClearLocked",
"CalendarEventClearModerator",
"CalendarEventDecline",
"CalendarEventGetInvite",
"CalendarEventGetInviteResponseTime",
"CalendarEventGetInviteSortCriterion",
"CalendarEventGetNumInvites",
"CalendarEventGetRepeatOptions",
"CalendarEventGetSelectedInvite",
"CalendarEventGetStatusOptions",
"CalendarEventGetTextures",
"CalendarEventGetTypes",
"CalendarEventHasPendingInvite",
"CalendarEventHaveSettingsChanged",
"CalendarEventInvite",
"CalendarEventIsGuildWide",
"CalendarEventRemoveInvite",
"CalendarEventSelectInvite",
"CalendarEventSetAutoApprove",
"CalendarEventSetDate",
"CalendarEventSetDescription",
"CalendarEventSetLocked",
"CalendarEventSetLockoutDate",
"CalendarEventSetLockoutTime",
"CalendarEventSetModerator",
"CalendarEventSetRepeatOption",
"CalendarEventSetSize",
"CalendarEventSetStatus",
"CalendarEventSetTextureID",
"CalendarEventSetTime",
"CalendarEventSetTitle",
"CalendarEventSetType",
"CalendarEventSortInvites",
"CalendarEventSignUp",
"CalendarEventTentative",
"CanSendInvite",
"CalendarGetAbsMonth",
"CalendarGetDate",
"CalendarGetDay",
"CalendarGetDayEvent",
"CalendarGetEventIndex",
"CalendarGetEventInfo",
"CalendarGetFirstPendingInvite",
"CalendarGetHolidayInfo",
"CalendarGetMaxCreateDate",
"CalendarGetMinDate",
"CalendarGetMonth",
"CalendarGetNumDayEvents",
"CalendarGetNumPendingInvites",
"CalendarGetRaidInfo",
"CalendarIsActionPending",
"CalendarMassInviteGuild",
"CalendarNewArenaTeamEvent",
"CalendarNewEvent",
"CalendarNewGuildEvent",
"CalendarNewGuildAnnouncement",
"CalendarOpenEvent",
"CalendarRemoveEvent",
"CalendarSetAbsMonth",
"CalendarSetMonth",
"CalendarUpdateEvent",
}
-- Invite Statuses
GroupCalendar.CALENDAR_EVENTCOLOR_MODERATOR = {r = 0.54, g = 0.75, b = 1.0}
GroupCalendar.CALENDAR_INVITESTATUS_COLORS =
{
[CALENDAR_INVITESTATUS_CONFIRMED] = GREEN_FONT_COLOR,
[CALENDAR_INVITESTATUS_ACCEPTED] = {r = 0.6, g = 1, b = 1},
[CALENDAR_INVITESTATUS_TENTATIVE] = ORANGE_FONT_COLOR,
[CALENDAR_INVITESTATUS_DECLINED] = GRAY_FONT_COLOR,
[CALENDAR_INVITESTATUS_OUT] = RED_FONT_COLOR,
[CALENDAR_INVITESTATUS_STANDBY] = YELLOW_FONT_COLOR,
[CALENDAR_INVITESTATUS_INVITED] = NORMAL_FONT_COLOR,
[CALENDAR_INVITESTATUS_SIGNEDUP] = {r = 0.6, g = 1, b = 1},
[CALENDAR_INVITESTATUS_NOT_SIGNEDUP] = NORMAL_FONT_COLOR,
}
GroupCalendar.CALENDAR_INVITESTATUS_COLOR_CODES = {}
for vKey, vColor in pairs(GroupCalendar.CALENDAR_INVITESTATUS_COLORS) do
GroupCalendar.CALENDAR_INVITESTATUS_COLOR_CODES[vKey] = string.format("|cff%02x%02x%02x", vColor.r * 255 + 0.5, vColor.g * 255 + 0.5, vColor.b * 255 + 0.5)
end
GroupCalendar.CALENDAR_INVITESTATUS_NAMES =
{
[CALENDAR_INVITESTATUS_CONFIRMED] = CALENDAR_STATUS_CONFIRMED,
[CALENDAR_INVITESTATUS_ACCEPTED] = CALENDAR_STATUS_ACCEPTED,
[CALENDAR_INVITESTATUS_TENTATIVE] = CALENDAR_STATUS_TENTATIVE,
[CALENDAR_INVITESTATUS_DECLINED] = CALENDAR_STATUS_DECLINED,
[CALENDAR_INVITESTATUS_OUT] = CALENDAR_STATUS_OUT,
[CALENDAR_INVITESTATUS_STANDBY] = CALENDAR_STATUS_STANDBY,
[CALENDAR_INVITESTATUS_INVITED] = CALENDAR_STATUS_INVITED,
[CALENDAR_INVITESTATUS_SIGNEDUP] = CALENDAR_STATUS_SIGNEDUP,
[CALENDAR_INVITESTATUS_NOT_SIGNEDUP] = nil,
}
GroupCalendar.CALENDAR_CALENDARTYPE_COLORS =
{
-- ["PLAYER"] = ,
-- ["GUILD_ANNOUNCEMENT"] = ,
-- ["GUILD_EVENT"] = ,
["SYSTEM"] = {r=1.0, g=1.0, b=0.6},
["HOLIDAY"] = HIGHLIGHT_FONT_COLOR,
["RAID_LOCKOUT"] = NORMAL_FONT_COLOR,
["RAID_RESET"] = HIGHLIGHT_FONT_COLOR,
}
GroupCalendar.EVENT_MAX_TITLE_LENGTH = 31
GroupCalendar.EVENT_MAX_DESCRIPTION_LENGTH = 255
----------------------------------------
GroupCalendar._Calendar = {}
----------------------------------------
GroupCalendar._Calendar.cMaxHistory = 14
function GroupCalendar._Calendar:Construct(pOwnersName, pCalendarID, pCalendarData, pReadOnly)
self.OwnersName = pOwnersName
self.CalendarID = pCalendarID
self.CalendarData = pCalendarData
self.ReadOnly = pReadOnly
self.Schedules = {}
-- Add the method table to all of the events in the calendar
local vMetaTable = (pReadOnly and GroupCalendar._CachedEventMetaTable) or GroupCalendar._APIEventMetaTable
if self.CalendarData then
for vDate, vEvents in pairs(self.CalendarData) do
for _, vEvent in ipairs(vEvents) do
setmetatable(vEvent, vMetaTable)
end
end
end
--
if not self.ReadOnly then
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_EVENT_LIST", self.CalendarUpdateEventList, self)
GroupCalendar.EventLib:RegisterEvent("CVAR_UPDATE", self.CVarUpdate, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_PENDING_INVITES", self.Synchronize, self)
end
-- Install event monitoring to aid in debugging
--[[
if pCalendarID == "PLAYER" then
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_EVENT_LIST", self.DebugEvents, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_OPEN_EVENT", self.DebugEvents, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_CLOSE_EVENT", self.DebugEvents, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_EVENT", self.DebugEvents, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_INVITE_LIST", self.DebugEvents, self)
GroupCalendar.EventLib:RegisterEvent("GC5_EVENT_CHANGED", self.DebugEvents, self)
GroupCalendar.EventLib:RegisterEvent("GC5_CALENDAR_CHANGED", self.DebugEvents, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_ACTION_PENDING", self.DebugEvents, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_NEW_EVENT", self.DebugEvents, self)
end
]]
end
function GroupCalendar._Calendar:DebugEvents(pEventID, ...)
if GroupCalendar.Debug.events then
local vParam = select(1, ...) or ""
GroupCalendar:DebugMessage("Calendar:DebugEvents: %s%s: %s", GREEN_FONT_COLOR_CODE, pEventID, tostring(vParam))
end
end
function GroupCalendar._Calendar:CalendarUpdateEventList()
GroupCalendar.BlizzardCalendarReady = true
self:FlushCaches()
end
function GroupCalendar._Calendar:GetSelectedEvent()
if GroupCalendar.WoWCalendar.OpenedEvent then
return GroupCalendar.WoWCalendar.OpenedEvent
end
if not self.CalendarData then
return
end
local vDate = GroupCalendar.DateLib:ConvertMDYToDate(
GroupCalendar.WoWCalendar.SelectedEventMonth,
GroupCalendar.WoWCalendar.SelectedEventDay,
GroupCalendar.WoWCalendar.SelectedEventYear)
local vEvents = self.CalendarData[vDate]
if not vEvents then
return
end
for _, vEvent in ipairs(vEvents) do
if vEvent.Index == GroupCalendar.WoWCalendar.SelectedEventIndex then
return vEvent
end
end
end
function GroupCalendar._Calendar:FlushCaches()
if self.ReadOnly then
return
end
if self.CalendarID ~= "PLAYER" then
for vDate, vSchedule in pairs(self.Schedules) do
self.Schedules[vDate] = nil
end
else
self:Synchronize()
end
GroupCalendar.EventLib:DispatchEvent("GC5_CALENDAR_CHANGED")
end
function GroupCalendar._Calendar:CVarUpdate(pName, pValue)
if pName == "calendarShowDarkmoon"
or pName == "calendarShowWeeklyHolidays"
or pName == "calendarShowBattlegrounds" then
self:FlushCaches()
end
end
function GroupCalendar._Calendar:GetSchedule(pMonth, pDay, pYear)
if not pMonth or not pDay or not pYear then
error("GetSchedule: month, day and year expected")
end
local vDate = GroupCalendar.DateLib:ConvertMDYToDate(pMonth, pDay, pYear)
local vSchedule = self.Schedules[vDate]
if not vSchedule then
vSchedule = GroupCalendar:New(GroupCalendar._CalendarDay, self.OwnersName, self.CalendarID, self.CalendarData, self.ReadOnly)
vSchedule:SetDate(pMonth, pDay, pYear)
self.Schedules[vDate] = vSchedule
end
return vSchedule
end
function GroupCalendar._Calendar:GetLocalSchedule(pMonth, pDay, pYear)
end
function GroupCalendar._Calendar:Synchronize()
_, self.CurrentMonth, self.CurrentDay, self.CurrentYear = GroupCalendar.WoWCalendar:CalendarGetDate()
self.CurrentDate = GroupCalendar.DateLib:ConvertMDYToDate(self.CurrentMonth, self.CurrentDay, self.CurrentYear)
local vCutoffDate = self.CurrentDate - self.cMaxHistory
-- Mark the schedules so we can tell which ones don't get used
for vDate, vSchedule in pairs(self.Schedules) do
vSchedule.Unused = true
end
for vDate = vCutoffDate, self.CurrentDate + 365 do
local vMonth, vDay, vYear = GroupCalendar.DateLib:ConvertDateToMDY(vDate)
if self:HasDayEvents(vMonth, vDay, vYear) then
local vSchedule = self.Schedules[vDate]
if not vSchedule then
vSchedule = GroupCalendar:New(GroupCalendar._CalendarDay, self.OwnersName, self.CalendarID, self.CalendarData, self.ReadOnly)
self.Schedules[vDate] = vSchedule
else
vSchedule.Unused = nil
end
vSchedule:SetDate(vMonth, vDay, vYear)
end
end
-- Remove unused schedules
for vDate, vSchedule in pairs(self.Schedules) do
if vSchedule.Unused then
self.Schedules[vDate] = nil
end
end
end
function GroupCalendar._Calendar:HasDayEvents(pMonth, pDay, pYear)
local vMonthOffset = GroupCalendar.WoWCalendar:CalendarGetMonthOffset(pMonth, pYear)
local vNumEvents = GroupCalendar.WoWCalendar:CalendarGetNumDayEvents(vMonthOffset, pDay)
SetCVar("calendarShowLockouts", 1)
for vEventIndex = 1, vNumEvents do
local vTitle, vHour, vMinute,
vCalendarType, vSequenceType, vEventType,
vTextureID, vModStatus, vInviteStatus, vInvitedBy,
vDifficulty, vInviteType, vSequenceIndex, vNumSequenceDays, vDifficultyName = GroupCalendar.WoWCalendar:CalendarGetDayEvent(vMonthOffset, pDay, vEventIndex)
if (self.CalendarID == GroupCalendar._CalendarDay.cBlizzardCalendarIDs[vCalendarType])
or (self.CalendarID ~= "BLIZZARD" and not GroupCalendar._CalendarDay.cBlizzardCalendarIDs[vCalendarType]) then
return true
end
end
return false
end
function GroupCalendar._Calendar:NewEvent(pMonth, pDay, pYear, pCalendarType)
if self.ReadOnly then
error("Can't create new events in a read-only calendar")
end
if self:IsAfterMaxCreateDate(pMonth, pDay, pYear) then
error("Can't create events that far in the future")
end
local vEvent = {}
setmetatable(vEvent, GroupCalendar._APIEventMetaTable)
vEvent:NewEvent(self.OwnersName, pMonth, pDay, pYear, pCalendarType)
return vEvent
end
function GroupCalendar._Calendar:IsAfterMaxCreateDate(pMonth, pDay, pYear)
if not pMonth or not pDay or not pYear then
error("Expected month, day, year")
end
local _, vMaxMonth, vMaxDay, vMaxYear = GroupCalendar.WoWCalendar:CalendarGetMaxCreateDate()
if pYear > vMaxYear then
return true
elseif pYear < vMaxYear then
return false
elseif pMonth > vMaxMonth then
return true
elseif pMonth < vMaxMonth then
return false
else
return pDay > vMaxDay
end
end
----------------------------------------
GroupCalendar._CalendarDay = {}
----------------------------------------
function GroupCalendar._CalendarDay:Construct(pOwnersName, pCalendarID, pCalendarData, pReadOnly)
self.OwnersName = pOwnersName
self.CalendarID = pCalendarID
self.CalendarData = pCalendarData
self.ReadOnly = pReadOnly
self.Events = nil
end
GroupCalendar._CalendarDay.cBlizzardCalendarIDs =
{
SYSTEM = "BLIZZARD",
HOLIDAY = "BLIZZARD",
RAID_RESET = "BLIZZARD"
}
function GroupCalendar._CalendarDay:SetDate(pMonth, pDay, pYear)
local vDate = GroupCalendar.DateLib:ConvertMDYToDate(pMonth, pDay, pYear)
if not self.Events then
if self.CalendarData then
self.Events = self.CalendarData[vDate]
end
if not self.Events then
self.Events = {}
end
end
-- Synchronize to the Blizzard database if we're not read-only
if not self.ReadOnly then
self:SynchronizeEvents(pMonth, pDay, pYear)
if self.CalendarData then
if #self.Events > 0 then
self.CalendarData[vDate] = self.Events
else
self.CalendarData[vDate] = nil
end
end
end
end
function GroupCalendar._CalendarDay:SynchronizeEvents(pMonth, pDay, pYear)
if self.CalendarID == "PLAYER"
and not GroupCalendar.BlizzardCalendarReady then
return -- Can't do anything until the WoW calendar's have loaded
end
-- Mark existing event records so we can determine if
-- they're still active once we're done
if self.Events then
for _, vEvent in ipairs(self.Events) do
vEvent.Orphaned = true
end
else
self.Events = {}
end
-- Collect the events from the WoW calendar
local vMonthOffset = GroupCalendar.WoWCalendar:CalendarGetMonthOffset(pMonth, pYear)
local vNumEvents = GroupCalendar.WoWCalendar:CalendarGetNumDayEvents(vMonthOffset, pDay)
SetCVar("calendarShowLockouts", 1)
local vAPIEvent = {}
setmetatable(vAPIEvent, GroupCalendar._APIEventMetaTable)
local vCurrentDateTimeStamp = GroupCalendar.DateLib:GetServerDateTimeStamp()
local vCalendarChanged
for vEventIndex = 1, vNumEvents do
vAPIEvent:SetEvent(self.OwnersName, pMonth, pDay, pYear, vEventIndex)
if (self.CalendarID == self.cBlizzardCalendarIDs[vAPIEvent.CalendarType])
or (self.CalendarID ~= "BLIZZARD" and not self.cBlizzardCalendarIDs[vAPIEvent.CalendarType]) then
local vEvent = self:FindExistingEvent(vAPIEvent)
if vEvent then
local vChanged
for vKey, vValue in pairs(vAPIEvent) do
if vEvent[vKey] ~= vValue then
vEvent[vKey] = vValue
vChanged = true
end
end
vEvent.CacheUpdateDate, vEvent.CacheUpdateTime = GroupCalendar.DateLib:GetServerDateTime()
vEvent.Orphaned = nil
if vChanged then
vCalendarChanged = true
GroupCalendar.BroadcastLib:Broadcast(vEvent, "CHANGED")
end
else
vEvent = GroupCalendar:DuplicateTable(vAPIEvent, true)
setmetatable(vEvent, GroupCalendar._APIEventMetaTable)
vEvent.CreationDate, vEvent.CreationTime = GroupCalendar.DateLib:GetServerDateTime()
vEvent.CacheUpdateDate, vEvent.CacheUpdateTime = GroupCalendar.DateLib:GetServerDateTime()
if self.CalendarID == "PLAYER"
and not vEvent:IsCooldownEvent()
and not vEvent:HasPassed(vCurrentDateTimeStamp)
and vEvent.InvitedBy ~= GroupCalendar.PlayerName then
vEvent.Unseen = true
end
if not self.Events then
self.Events = {}
end
table.insert(self.Events, vEvent)
vCalendarChanged = true
GroupCalendar.EventLib:DispatchEvent("GC5_EVENT_ADDED", vEvent)
end
end
end
for vIndex = #self.Events, 1, -1 do
local vEvent = self.Events[vIndex]
if vEvent.Orphaned then
vCalendarChanged = true
table.remove(self.Events, vIndex)
GroupCalendar.BroadcastLib:Broadcast(vEvent, "DELETED")
end
end
if vCalendarChanged then
GroupCalendar.EventLib:DispatchEvent("GC5_CALENDAR_CHANGED", vEvent)
end
end
function GroupCalendar._CalendarDay:FindExistingEvent(pEvent)
local vBestScore, vBestEvent
for _, vEvent in ipairs(self.Events) do
if vEvent.Orphaned then
if pEvent.CalendarType == vEvent.CalendarType
and pEvent.SequenceType == vEvent.SequenceType then
local vScore = 0
if pEvent.Title == vEvent.Title then vScore = vScore + 1 end
if pEvent.TitleTag == vEvent.TitleTag then vScore = vScore + 1 end
if pEvent.Hour == vEvent.Hour
and pEvent.Minute == vEvent.Minute then vScore = vScore + 1 end
if pEvent.Month == vEvent.Month
and pEvent.Day == vEvent.Day
and pEvent.Year == vEvent.Year then vScore = vScore + 1 end
if pEvent.EventType == vEvent.EventType
and pEvent.TextureID == vEvent.TextureID
and pEvent.Difficulty == vEvent.Difficulty then vScore = vScore + 1 end
if pEvent.ModStatus == vEvent.ModStatus then vScore = vScore + 0.25 end
if pEvent.InviteStatus == vEvent.InviteStatus then vScore = vScore + 0.25 end
if pEvent.InviteType == vEvent.InviteType then vScore = vScore + 0.25 end
if pEvent.InvitedBy == vEvent.InvitedBy then vScore = vScore + 0.5 end
if vScore and vScore >= 3 and (not vBestScore or vScore > vBestScore) then
vBestScore = vScore
vBestEvent = vEvent
end
end -- if pCalendarTYpe
end -- if Orphaned
end -- for
return vBestEvent
end
function GroupCalendar:AddTooltipEvents(pTooltip, pEvents, pUseLocalTime)
if not pEvents then
return
end
for vIndex, vEvent in ipairs(pEvents) do
local vColor = vEvent:GetEventColor()
local vOwner = tern((vEvent.RealmName ~= GroupCalendar.RealmName) and vEvent.OwnersName,
string.format(GroupCalendar.cForeignRealmFormat, vEvent.OwnersName, vEvent.RealmName),
vEvent.OwnersName)
local vEventFormat = vEvent.InvitedBy and vEvent.InvitedBy ~= "" and GroupCalendar.cTooltipScheduleItemFormat or "%s"
local vTitle = vEventFormat:format(vEvent.Title, vOwner)
if vEvent:IsAllDayEvent() then
pTooltip:AddDoubleLine(
GroupCalendar.cAllDay,
vTitle,
vColor.r, vColor.g, vColor.b, vColor.r, vColor.g, vColor.b)
else
local vTime = GroupCalendar.DateLib:ConvertHMToTime(vEvent.Hour, vEvent.Minute)
if pUseLocalTime then
vTime = GroupCalendar.DateLib:GetLocalTimeFromServerTime(vTime)
end
pTooltip:AddDoubleLine(
GroupCalendar.DateLib:GetShortTimeString(vTime),
vTitle,
vColor.r, vColor.g, vColor.b, vColor.r, vColor.g, vColor.b)
end
end
end
function GroupCalendar:GetEventTypeTextures(pEventType)
if not self.EventTypeTextures then
self.EventTypeTextures = {}
end
local vEventTypeTextures = self.EventTypeTextures[pEventType]
if not vEventTypeTextures then
vEventTypeTextures = {}
local vTextures = {GroupCalendar.WoWCalendar:CalendarEventGetTextures(pEventType)}
local vTextureIndex = 1
for vIndex = 1, #vTextures, 6 do
vEventTypeTextures[vTextureIndex] = {
Name = vTextures[vIndex],
TextureName = vTextures[vIndex + 1],
ExpLevel = vTextures[vIndex + 2],
DifficultyName = vTextures[vIndex + 3]
}
vTextureIndex = vTextureIndex + 1
end
self.EventTypeTextures[pEventType] = vEventTypeTextures
end
return vEventTypeTextures
end
function GroupCalendar:InitializeEventDefaults()
GroupCalendar.DefaultEventLimits = {}
GroupCalendar.DefaultEventLevel = {}
local vEventTypeNames = {GroupCalendar.WoWCalendar:CalendarEventGetTypes()}
for vEventType, vEventTypeName in ipairs(vEventTypeNames) do
GroupCalendar.DefaultEventLimits[vEventType] = {}
GroupCalendar.DefaultEventLevel[vEventType] = {}
if vEventType == CALENDAR_EVENTTYPE_RAID or vEventType == CALENDAR_EVENTTYPE_DUNGEON or vEventType == CALENDAR_EVENTTYPE_HEROIC_DUNGEON then
local vEventTypeTextures = GroupCalendar:GetEventTypeTextures(vEventType)
for vTextureIndex, vTextureInfo in ipairs(vEventTypeTextures) do
local vLimit, vMinLevel
-- Dungeons are always 5-man
if vEventType == CALENDAR_EVENTTYPE_DUNGEON or vEventType == CALENDAR_EVENTTYPE_HEROIC_DUNGEON then
vLimit = 5
if vTextureInfo.ExpLevel == 1 then
vMinLevel = 60
elseif vTextureInfo.ExpLevel == 2 then
vMinLevel = 70
else
vMinLevel = 10
end
-- Classic raids are 20 for ZG and AQR and 40 for everything else
elseif vTextureInfo.ExpLevel == 0 then
if vTextureInfo.TextureName == "LFGIcon-ZulGurub"
or vTextureInfo.TextureName == "LFGIcon-AQRuins" then
vLimit = 20
vMinLevel = 58
else
vLimit = 40
vMinLevel = 58
end
-- TBC raids are 10-man for Karazhan and Zul'Aman, 25 for everything else
elseif vTextureInfo.ExpLevel == 0 then
if vTextureInfo.TextureName == "LFGIcon-Karazhan"
or vTextureInfo.TextureName == "LFGIcon-ZulAman" then
vLimit = 10
vMinLevel = 68
else
vLimit = 25
vMinLevel = 70
end
-- WotLK raids are 10-man for non-heroic, 25 for
-- heroic (I'm assuming this is the default for the future too)
else
if vTextureInfo.Name and vTextureInfo.Name:sub(-1) == ")" then -- Cheesy, but what else is there?
vLimit = 25
vMinLevel = 80
else
vLimit = 10
vMinLevel = 78
end
end
GroupCalendar.DefaultEventLimits[vEventType][vTextureIndex] = vLimit
GroupCalendar.DefaultEventLevel[vEventType][vTextureIndex] = vMinLevel
end -- for vTextureIndex
end -- if vEventType
end -- for vEventType
end
----------------------------------------
GroupCalendar._BaseEventMethods = {}
----------------------------------------
----------------------------------------
-- Get
function GroupCalendar._BaseEventMethods:GetTexture()
if not GroupCalendar.EventTypeTextures then
GroupCalendar.EventTypeTextures = {}
end
local vEventTypeTextures = GroupCalendar:GetEventTypeTextures(self.EventType)
return GroupCalendar:GetTextureFile(
self.TextureIndex and vEventTypeTextures[self.TextureIndex] and vEventTypeTextures[self.TextureIndex].TextureName,
self.CalendarType, self.NumSequenceDays ~= 2 and self.SequenceType or "", self.EventType, self.TitleTag)
end
function GroupCalendar._BaseEventMethods:GetLocation()
local vEventTypeTextures = GroupCalendar:GetEventTypeTextures(self.EventType)
if not vEventTypeTextures
or not vEventTypeTextures[self.TextureIndex] then
return ""
end
return vEventTypeTextures[self.TextureIndex].Name
end
function GroupCalendar._BaseEventMethods:GetEventColor()
if self:IsPlayerCreated() then
if GroupCalendar.CALENDAR_INVITESTATUS_COLORS[self.InviteStatus] then
return GroupCalendar.CALENDAR_INVITESTATUS_COLORS[self.InviteStatus]
end
elseif GroupCalendar.CALENDAR_CALENDARTYPE_COLORS[self.CalendarType] then
return GroupCalendar.CALENDAR_CALENDARTYPE_COLORS[self.CalendarType]
end
-- Default to normal color
return NORMAL_FONT_COLOR
end
function GroupCalendar._BaseEventMethods:GetLevelRange()
return self.MinLevel, self.MaxLevel
end
function GroupCalendar._BaseEventMethods:GetLimits()
return self.Limits
end
function GroupCalendar._BaseEventMethods:GetDefaultPartySize()
if not GroupCalendar.DefaultEventLimits then
GroupCalendar:InitializeEventDefaults()
end
if not GroupCalendar.DefaultEventLimits[self.EventType] then
return
else
return GroupCalendar.DefaultEventLimits[self.EventType][self.TextureIndex],
GroupCalendar.DefaultEventLevel[self.EventType][self.TextureIndex]
end
end
function GroupCalendar._BaseEventMethods:GetUID()
if self.CalendarType == "HOLIDAY"
or self.CalendarType == "SYSTEM"
or self.CalendarType == "RAID_RESET" then
return string.format("%s//%04d%02d%02d//%d", self.CalendarType, self.Year, self.Month, self.Day, self.Index)
end
if not self.UID then
self.UID = math.random(1000000)
end
return self.RealmName.."//"..self.OwnersName.."//"..self.UID
end
function GroupCalendar._BaseEventMethods:GetCreationDateTime()
if not self.CreationDate then
self.CreationDate, self.CreationTime = GroupCalendar.DateLib:GetServerDateTime()
end
return self.CreationDate, self.CreationTime
end
function GroupCalendar._BaseEventMethods:GetModifiedDateTime()
if not self.CreationDate then
self.CacheUpdateDate, self.CacheUpdateTime = GroupCalendar.DateLib:GetServerDateTime()
end
return self.CacheUpdateDate, self.CacheUpdateTime
end
function GroupCalendar._BaseEventMethods:GetSecondsToStart(pCurrentDateTimeStamp)
local vDate = GroupCalendar.DateLib:ConvertMDYToDate(self.Month, self.Day, self.Year)
local vTime60 = GroupCalendar.DateLib:ConvertHMSToTime60(self.Hour, self.Minute, 0) or 0
local vDateTimeStamp = vDate * GroupCalendar.DateLib.cSecondsPerDay + vTime60
return vDateTimeStamp - pCurrentDateTimeStamp
end
function GroupCalendar._BaseEventMethods:HasPassed(pCurrentDateTimeStamp)
local vDuration = (self.Duration or (4 * 60)) * 60
return self:GetSecondsToStart(pCurrentDateTimeStamp) + vDuration < 0
end
----------------------------------------
-- Status
function GroupCalendar._BaseEventMethods:IsAllDayEvent()
if self.SequenceType == "ONGOING" then
return true
end
if self.TitleTag
and GroupCalendar.TitleTagInfo[self.TitleTag] then
return GroupCalendar.TitleTagInfo[self.TitleTag].AllDay
end
return false
end
function GroupCalendar._BaseEventMethods:IsCooldownEvent()
if self.CalendarType == "RAID_LOCKOUT" then
return true
end
if self.TitleTag
and GroupCalendar.TitleTagInfo[self.TitleTag] then
return GroupCalendar.TitleTagInfo[self.TitleTag].IsCooldown
end
return self.TitleTag ~= nil
end
function GroupCalendar._BaseEventMethods:IsBirthdayEvent()
return self.TitleTag == "BRTH"
end
function GroupCalendar._BaseEventMethods:IsPersonalEvent()
if self.TitleTag
and GroupCalendar.TitleTagInfo[self.TitleTag] then
return GroupCalendar.TitleTagInfo[self.TitleTag].IsPersonal
end
return (self.CalendarType == "PLAYER" or self.CalendarType == "GUILD_EVENT" or self.CalendarType == "GUILD" or self.CalendarType == "GUILD_ANNOUNCEMENT")
and self.TitleTag ~= nil
end
function GroupCalendar._BaseEventMethods:IsDungeonEvent()
return (self.CalendarType == "PLAYER" or self.CalendarType == "GUILD_EVENT" or self.CalendarType == "GUILD" or self.CalendarType == "GUILD_ANNOUNCEMENT")
and self.TitleTag == nil
end
function GroupCalendar._BaseEventMethods:IsSignupEvent()
return self.InviteType == CALENDAR_INVITETYPE_SIGNUP
end
function GroupCalendar._BaseEventMethods:IsAnnouncementEvent()
return self.CalendarType == "GUILD_ANNOUNCEMENT" or self.CalendarType == "GUILD"
end
function GroupCalendar._BaseEventMethods:IsPlayerCreated()
return self.CalendarType == "PLAYER"
or self.CalendarType == "GUILD"
or self.CalendarType == "GUILD_ANNOUNCEMENT"
or self.CalendarType == "GUILD_EVENT"
or self.CalendarType == "ARENA"
end
function GroupCalendar._BaseEventMethods:UsesLevelLimits()
if self.TitleTag
and GroupCalendar.TitleTagInfo[self.TitleTag] then
return GroupCalendar.TitleTagInfo[self.TitleTag].UsesLevelLimits
end
return (self.CalendarType == "PLAYER"
or self.CalendarType == "GUILD"
or self.CalendarType == "GUILD_EVENT"
or self.CalendarType == "GUILD_ANNOUNCEMENT")
and self.TitleTag == nil
end
function GroupCalendar._BaseEventMethods:UsesAttendance()
if self.TitleTag
and GroupCalendar.TitleTagInfo[self.TitleTag] then
return GroupCalendar.TitleTagInfo[self.TitleTag].UsesAttendance
end
return (self.CalendarType == "PLAYER"
or self.CalendarType == "GUILD_EVENT")
and (self.TitleTag == nil or self.TitleTag == "")
end
function GroupCalendar._BaseEventMethods:PlayerIsQualified()
return true
end
function GroupCalendar._BaseEventMethods:IsExpired()
local vServerDate, vServerTime = GroupCalendar.DateLib:GetServerDateTime()
local vEventDate, vEventTime = GroupCalendar.DateLib:ConvertMDYToDate(self.Month, self.Day, self.Year), GroupCalendar.DateLib:ConvertHMToTime(self.Hour, self.Minute)
return vEventDate < vServerDate or (vEventDate == vServerDate and vEventTime and vEventTime < vServerTime)
end
function GroupCalendar._BaseEventMethods:EventIsVisible(pIsPlayerEvent)
if not self:IsPlayerCreated() then
return true
end
if pIsPlayerEvent then
return true
end
return self.ModStatus == "CREATOR" or self:IsAttending()
end
function GroupCalendar._BaseEventMethods:IsAttending()
return not self.TitleTag
and (self.InviteStatus == CALENDAR_INVITESTATUS_ACCEPTED
or self.InviteStatus == CALENDAR_INVITESTATUS_TENTATIVE
or self.InviteStatus == CALENDAR_INVITESTATUS_SIGNEDUP
or self.InviteStatus == CALENDAR_INVITESTATUS_CONFIRMED
or self.InviteStatus == CALENDAR_INVITESTATUS_STANDBY)
end
function GroupCalendar._BaseEventMethods:GetAttendance()
return self.Attendance
end
function GroupCalendar._BaseEventMethods:GetInviteStatus(pPlayerName)
local vAttendance = self:GetAttendance()
if not vAttendance then
if pPlayerName == self.OwnersName then
return self.InviteStatus
elseif self.CalendarType == "GUILD_EVENT" then
return CALENDAR_INVITESTATUS_NOT_SIGNEDUP
else
return
end
end
if not vAttendance[pPlayerName] then
if self.CalendarType == "GUILD_EVENT" then
return CALENDAR_INVITESTATUS_NOT_SIGNEDUP
else
return
end
end
return vAttendance[pPlayerName].InviteStatus
end
----------------------------------------
GroupCalendar._APIEventMethods = {}
----------------------------------------
for vKey, vValue in pairs(GroupCalendar._BaseEventMethods) do
GroupCalendar._APIEventMethods[vKey] = vValue
end
function GroupCalendar._APIEventMethods:NewEvent(pOwnersName, pMonth, pDay, pYear, pCalendarType)
self.Month = pMonth
self.Day = pDay
self.Year = pYear
self.Index = nil
self.OwnersName = pOwnersName
self.RealmName = GroupCalendar.RealmName
self.Title = ""
self.TitleTag = nil
self.Hour = 20
self.Minute = 0
self.Duration = 180
self.MinLevel = nil
self.MaxLevel = nil
if pCalendarType then
self.CalendarType = pCalendarType
elseif CanEditGuildEvent() then
self.CalendarType = "GUILD_EVENT"
else
self.CalendarType = "PLAYER"
end
self.SequenceType = nil
self.EventType = CALENDAR_EVENTTYPE_OTHER
self.TextureID = nil
self.ModStatus = "CREATOR"
self.InviteStatus = CALENDAR_INVITESTATUS_CONFIRMED
self.InvitedBy = GroupCalendar.PlayerName
self.InviteType = CALENDAR_INVITETYPE_NORMAL
self.Difficulty = nil
self.Description = ""
self.DescriptionTag = nil
end
function GroupCalendar._APIEventMethods:SetEvent(pOwnersName, pMonth, pDay, pYear, pIndex)
if not pIndex then
return self:NewEvent(pOwnersName, pMonth, pDay, pYear)
end
local vMonthOffset = GroupCalendar.WoWCalendar:CalendarGetMonthOffset(pMonth, pYear)
self.Month = pMonth
self.Day = pDay
self.Year = pYear
self.Index = pIndex
self.OwnersName = pOwnersName
self.RealmName = GroupCalendar.RealmName
local event = GroupCalendar.WoWCalendar:CalendarGetDayEvent(vMonthOffset, self.Day, self.Index)
self.Title = event.title
if (event.sequenceType == "END") then
self.Hour = event.endTime.hour;
self.Minute = event.endTime.minute;
else
self.Hour = event.startTime.hour;
self.Minute = event.startTime.minute;
end
self.CalendarType = event.calendarType
self.SequenceType = event.sequenceType
self.EventType = event.eventType
self.TextureID = event.iconTexture
self.ModStatus = event.modStatus
self.InviteStatus = event.inviteStatus
self.InvitedBy = event.invitedBy
self.Difficulty = event.difficulty
self.InviteType = event.inviteType
self.SequenceIndex = event.sequenceType
self.NumSequenceDays = event.numSequenceDays
self.DifficultyName = event.difficultyName
self.TitleTag = GroupCalendar.WoWCalendar:CalendarEventGetTitleTag()
self.EventCanComplain = GroupCalendar.WoWCalendar:CalendarContextEventCanComplain(vMonthOffset, self.Day, self.Index)
if self.CalendarType == "GUILD"
and CalendarContextEventIsGuildWide
and not GroupCalendar.WoWCalendar:CalendarContextEventIsGuildWide(vMonthOffset, self.Day, self.Index) then
self.CalendarType = "PLAYER"
end
if self.Difficulty == ""
or self.Difficulty == 0 then
self.Difficulty = nil
end
if self.Difficulty then
self.Title = string.format(DUNGEON_NAME_WITH_DIFFICULTY, self.Title or "nil", self.DifficultyName or "nil")
end
self.Title = GroupCalendar.WoWCalendar:CalendarGetDisplayTitle(self.CalendarType, self.SequenceType, self.Title)
if self.CalendarType == "HOLIDAY" then
_, self.Description, _ = GroupCalendar.WoWCalendar:CalendarGetHolidayInfo(vMonthOffset, self.Day, self.Index)
elseif self.CalendarType == "RAID_LOCKOUT"
or self.CalendarType == "RAID_RESET" then
self.Description = ""
end
if self.SequenceType == "ONGOING" then
self.Hour = nil
self.Minute = nil
end
if not self.InvitedBy or self.InvitedBy == "" then
self.InvitedBy = (self.CalendarType == "RAID_LOCKOUT" and GroupCalendar.PlayerData.Name)
or (self.CalendarType == "HOLIDAY" and "Holiday")
or (self.CalendarType == "SYSTEM" and GroupCalendar.cBlizzardOwner)
or (self.CalendarType == "RAID_RESET" and GroupCalendar.cBlizzardOwner)
end
end
function GroupCalendar._APIEventMethods:Open()
if GroupCalendar.WoWCalendar.OpenedEvent then
GroupCalendar.WoWCalendar.OpenedEvent:Close()
end
SetCVar("calendarShowLockouts", 1) -- Make sure this is on so indices are correct
if self.Index then
GroupCalendar.WoWCalendar:CalendarOpenEvent(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
GroupCalendar.WoWCalendar.OpenedEvent = self
else
if self.CalendarType == "GUILD_EVENT" then
GroupCalendar.WoWCalendar:CalendarNewGuildEvent()
elseif self.CalendarType == "GUILD_ANNOUNCEMENT" then
GroupCalendar.WoWCalendar:CalendarNewGuildAnnouncement()
else
GroupCalendar.WoWCalendar:CalendarNewEvent()
end
GroupCalendar.WoWCalendar.OpenedEvent = self
self:InitializeNewEvent()
end
GroupCalendar.EventLib:RegisterEvent("CALENDAR_OPEN_EVENT", self.CalendarOpenEvent, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_CLOSE_EVENT", self.EventClosed, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_EVENT", self.CalendarUpdateEvent, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_INVITE_LIST", self.CalendarUpdateEventInvites, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_ERROR", self.CalendarUpdateError, self)
if self.OriginalEvent then
GroupCalendar.BroadcastLib:Listen(self.OriginalEvent, self.ShadowEventMessage, self)
end
end
function GroupCalendar._APIEventMethods:InitializeNewEvent()
GroupCalendar.WoWCalendar:CalendarEventSetDate(self.Month, self.Day, self.Year)
GroupCalendar.WoWCalendar:CalendarEventSetTime(self.Hour or 0, self.Minute or 0)
GroupCalendar.WoWCalendar:CalendarEventSetTitle(self.Title)
GroupCalendar.WoWCalendar:CalendarEventSetTitleTag(self.TitleTag)
GroupCalendar.WoWCalendar:CalendarEventSetDescription(self.Description)
GroupCalendar.WoWCalendar:CalendarEventSetDescriptionTag(self.DescriptionTag)
GroupCalendar.WoWCalendar:CalendarEventSetType(self.EventType)
if self.TextureIndex then
GroupCalendar.WoWCalendar:CalendarEventSetTextureID(self.TextureIndex)
end
GroupCalendar.WoWCalendar:CalendarEventSetRepeatOption(self.RepeatOption)
self:GetEventInfo()
end
function GroupCalendar._APIEventMethods:SetEventMode(pMode)
if self.Index then
return -- Can't change mode on an existing event
end
if pMode == "SIGNUP"
and CanEditGuildEvent() then
if self.CalendarType == "GUILD_EVENT" then
return
end
self.ChangingMode = true
GroupCalendar.WoWCalendar:CalendarCloseEvent()
GroupCalendar.WoWCalendar:CalendarNewGuildEvent()
self.ChangingMode = nil
self.CalendarType = "GUILD_EVENT"
self.InviteType = CALENDAR_INVITETYPE_NORMAL
elseif pMode == "ANNOUNCE"
and CanEditGuildEvent() then
if self.CalendarType == "GUILD_ANNOUNCEMENT" then
return
end
self.ChangingMode = true
GroupCalendar.WoWCalendar:CalendarCloseEvent()
GroupCalendar.WoWCalendar:CalendarNewGuildAnnouncement()
self.ChangingMode = nil
self.CalendarType = "GUILD_ANNOUNCEMENT"
self.InviteType = CALENDAR_INVITETYPE_NORMAL
else
if self.CalendarType == "PLAYER" then
return
end
self.ChangingMode = true
GroupCalendar.WoWCalendar:CalendarCloseEvent()
GroupCalendar.WoWCalendar:CalendarNewEvent()
self.ChangingMode = nil
self.CalendarType = "PLAYER"
self.InviteType = CALENDAR_INVITETYPE_NORMAL
end
GroupCalendar.WoWCalendar.OpenedEvent = self
self:InitializeNewEvent()
GroupCalendar.BroadcastLib:Broadcast(self, "CHANGED")
end
function GroupCalendar._APIEventMethods:Close()
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
GroupCalendar.WoWCalendar:CalendarCloseEvent()
end
function GroupCalendar._APIEventMethods:GetShadowCopy()
local vEvent = GroupCalendar:DuplicateTable(self, true)
vEvent.OriginalEvent = self
vEvent.Group = self.Group -- Don't clone the group
setmetatable(vEvent, getmetatable(self))
return vEvent
end
function GroupCalendar._APIEventMethods:ShadowEventMessage(pEvent, pMessageID, ...)
if pMessageID == "CHANGED" then
for vField, vValue in pairs(self.OriginalEvent) do
if type(vValue) ~= "table" then
self[vField] = vValue
else
-- Attendance needs to be merged?
end
end
end
GroupCalendar.BroadcastLib:Broadcast(self, pMessageID, ...)
end
function GroupCalendar._APIEventMethods:IsOpened()
return GroupCalendar.WoWCalendar.OpenedEvent == self
end
function GroupCalendar._APIEventMethods:Save()
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self:UpdateDescriptionTag()
if self.Index then
GroupCalendar.WoWCalendar:CalendarUpdateEvent()
else
GroupCalendar.WoWCalendar:CalendarAddEvent()
end
end
function GroupCalendar._APIEventMethods:Copy()
GroupCalendar.WoWCalendar:CalendarContextEventCopy(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
end
function GroupCalendar._APIEventMethods:Delete()
if self.Index then
if self.ModStatus == "CREATOR" then
GroupCalendar.WoWCalendar:CalendarContextEventRemove(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
else
GroupCalendar.WoWCalendar:CalendarContextInviteRemove(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
end
else
-- Nothing to do for new events
end
end
function GroupCalendar._APIEventMethods:LoadDefaults()
local vPartySize, vMinLevel = self:GetDefaultPartySize()
--[[ Don't bother setting default limits since they're not supported yet
if vPartySize then
self.Limits = GroupCalendar:DuplicateTable(GroupCalendar.DefaultLimits[vPartySize], true)
end
]]
self:SetLevelRange(vMinLevel, nil)
local vEventTypeTextures = GroupCalendar:GetEventTypeTextures(self.EventType)
if vEventTypeTextures and vEventTypeTextures[self.TextureIndex] then
self:SetTitle(vEventTypeTextures[self.TextureIndex].Name)
end
local vDefaults = self.TitleTag
and GroupCalendar.TitleTagInfo[self.TitleTag]
and GroupCalendar.TitleTagInfo[self.TitleTag].Defaults
if vDefaults then
-- Change the mode
if vDefaults.CalendarType == "GUILD_ANNOUNCEMENT" then
self:SetEventMode("ANNOUNCE")
elseif vDefaults.CalendarType == "GUILD_EVENT" then
self:SetEventMode("SIGNUP")
elseif vDefaults.CalendarType == "PLAYER" then
self:SetEventMode("NORMAL")
end
-- Set the title
if vDefaults.Title then
self:SetTitle(vDefaults.Title:format(GroupCalendar.PlayerName))
end
end
-- Clear out fields which aren't used
if self:IsAllDayEvent() then
self.Hour = 0 -- Midnight
self.Minute = 0
self.Duration = 1440 -- 24 hours
end
if not self:UsesLevelLimits() then
self.MinLevel = nil
self.MaxLevel = nil
end
end
----------------------------------------
-- Get
function GroupCalendar._APIEventMethods:CanSendInvite(pIgnoreOpenedEvent)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self or pIgnoreOpenedEvent)
return GroupCalendar.WoWCalendar:CalendarCanSendInvite()
end
function GroupCalendar._APIEventMethods:GetEventInfo(pIgnoreOpenedEvent)
local vChanged
if not pIgnoreOpenedEvent then
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
end
if self.ChangingMode then
return
end
local vTitle,
vDescription,
vCreator,
vEventType,
vRepeatOption,
vMaxSize,
vTextureIndex,
vWeekday,
vMonth,
vDay,
vYear,
vHour,
vMinute,
vLockoutWeekday,
vLockoutMonth,
vLockoutDay,
vLockoutYear,
vLockoutHour,
vLockoutMinute,
vLocked,
vAutoApprove,
vPendingInvite,
vInviteStatus,
vInviteType,
vCalendarType = GroupCalendar.WoWCalendar:CalendarGetEventInfo()
if vTextureIndex == 0 then vTextureIndex = nil end
if self.TextureIndex ~= vTextureIndex then
self.TextureIndex = vTextureIndex
vChanged = true
end
if self.Description ~= vDescription then
self.Description = vDescription
vChanged = true
end
if self.Creator ~= vCreator then
self.Creator = vCreator
vChanged = true
end
if self.RepeatOption ~= vRepeatOption then
self.RepeatOption = vRepeatOption
vChanged = true
end
if self.MaxSize ~= vMaxSize then
self.MaxSize = vMaxSize
vChanged = true
end
if self.LockoutWeekday ~= vLockoutWeekday then
self.LockoutWeekday = vLockoutWeekday
vChanged = true
end
if self.LockoutMonth ~= vLockoutMonth then
self.LockoutMonth = vLockoutMonth
vChanged = true
end
if self.LockoutDay ~= vLockoutDay then
self.LockoutDay = vLockoutDay
vChanged = true
end
if self.LockoutYear ~= vLockoutYear then
self.LockoutYear = vLockoutYear
vChanged = true
end
if self.LockoutHour ~= vLockoutHour then
self.LockoutHour = vLockoutHour
vChanged = true
end
if self.LockoutMinute ~= vLockoutMinute then
self.LockoutMinute = vLockoutMinute
vChanged = true
end
if self.Locked ~= vLocked then
self.Locked = vLocked
vChanged = true
end
if self.AutoApprove ~= vAutoApprove then
self.AutoApprove = vAutoApprove
vChanged = true
end
if self.PendingInvite ~= vPendingInvite then
self.PendingInvite = vPendingInvite
vChanged = true
end
if self.InviteStatus ~= vInviteStatus then
self.InviteStatus = vInviteStatus
vChanged = true
end
if self.InviteType ~= vInviteType then
self.InviteType = vInviteType
vChanged = true
end
if self.CalendarType ~= vCalendarType then
self.CalendarType = vCalendarType
vChanged = true
end
if self:DecodeDescriptionTag() then
vChanged = true
end
if self:RefreshAttendance(pIgnoreOpenedEvent) then
vChanged = true
end
self.CacheUpdateDate, self.CacheUpdateTime = GroupCalendar.DateLib:GetServerDateTime()
if vChanged then
GroupCalendar.BroadcastLib:Broadcast(self, "CHANGED")
end
if self.OriginalEvent then
self.OriginalEvent:GetEventInfo(true)
end
return vChanged
end
function GroupCalendar._APIEventMethods:GetEventAttendance(pIgnoreOpenedEvent)
if not pIgnoreOpenedEvent then
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
end
if self.ChangingMode then
return
end
local vChanged
if self:RefreshAttendance(pIgnoreOpenedEvent) then
vChanged = true
end
self.CacheUpdateDate, self.CacheUpdateTime = GroupCalendar.DateLib:GetServerDateTime()
if vChanged then
GroupCalendar.BroadcastLib:Broadcast(self, "CHANGED")
end
if self.OriginalEvent then
self.OriginalEvent:GetEventAttendance(true)
end
return vChanged
end
function GroupCalendar._APIEventMethods:DecodeDescriptionTag()
local vDescriptionTag = GroupCalendar.WoWCalendar:CalendarEventGetDescriptionTag()
local vChanged
if not self.DescriptionTags then
self.DescriptionTags = {}
else
for vKey, _ in pairs(self.DescriptionTags) do
self.DescriptionTags[vKey] = nil
end
end
if vDescriptionTag then
for vTag, vParameters in vDescriptionTag:gmatch("(%w+):?([^/]*)") do
self.DescriptionTags[vTag] = vParameters
end
end
if self.DescriptionTags.L then
local _, _, vMin, vMax = self.DescriptionTags.L:find("(.*),(.*)")
vMin = tonumber(vMin)
vMax = tonumber(vMax)
if vMin ~= self.MinLevel then
self.MinLevel = vMin
vChanged = true
end
if vMax ~= self.MaxLevel then
self.MaxLevel = vMax
vChanged = true
end
else
if self.MinLevel then
self.MinLevel = nil
vChanged = true
end
if self.MaxLevel then
self.MaxLevel = nil
vChanged = true
end
end
if self.DescriptionTags.D then
local vDuration = tonumber(self.DescriptionTags.D)
if vDuration ~= self.Duration then
self.Duration = vDuration
vChanged = true
end
elseif self.Duration then
self.Duration = nil
vChanged = true
end
if self.DescriptionTags.C then
self.Limits = {}
for vTagData in self.DescriptionTags.C:gmatch("[^:]+") do
if vTagData == "ROLE" then
self.Limits.Mode = "ROLE"
self.Limits.RoleLimits = {}
else
local _, _, vRoleCode, vMin, vMax, vClassReservations = vTagData:find("(.)(%d*),?(%d*)(.*)")
if vRoleCode == "X" then
self.Limits.MaxAttendance = tonumber(vMin)
elseif vRoleCode == "H"
or vRoleCode == "T"
or vRoleCode == "R"
or vRoleCode == "M" then
local vRoleLimit = {}
vRoleLimit.Min = tonumber(vMin)
vRoleLimit.Max = tonumber(vMax)
if vClassReservations ~= "" then
vRoleLimit.Class = {}
for vClassCode, vClassMin in vClassReservations:gmatch("([A-Z])(%d*)") do
local vClassID = GroupCalendar.ClassInfoByClassCode[vClassCode].ClassID
vRoleLimit.Class[vClassID] = tonumber(vClassMin)
end
end
self.Limits.RoleLimits[vRoleCode] = vRoleLimit
end
end
end
elseif self.Limits then
self.Limits = nil
vChanged = true
end
return vChanged
end
----------------------------------------
-- Set
function GroupCalendar._APIEventMethods:SetDate(pMonth, pDay, pYear)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.Month, self.Day, self.Year = pMonth, pDay, pYear
GroupCalendar.WoWCalendar:CalendarEventSetDate(pMonth, pDay, pYear)
end
function GroupCalendar._APIEventMethods:SetTime(pHour, pMinute)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.Hour, self.Minute = pHour, pMinute
GroupCalendar.WoWCalendar:CalendarEventSetTime(pHour or 0, pMinute or 0)
end
function GroupCalendar._APIEventMethods:SetLockoutDate(pMonth, pDay, pYear)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.LockoutMonth, self.LockoutDay, self.LockoutYear = pMonth, pDay, pYear
GroupCalendar.WoWCalendar:CalendarEventSetLockoutDate(pMonth, pDay, pYear)
end
function GroupCalendar._APIEventMethods:SetLockoutTime(pHour, pMinute)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.LockoutHour, self.LockoutMinute = pHour, pMinute
GroupCalendar.WoWCalendar:CalendarEventSetLockoutTime(pHour, pMinute)
end
function GroupCalendar._APIEventMethods:SetTitle(pTitle)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.Title = pTitle
GroupCalendar.WoWCalendar:CalendarEventSetTitle(pTitle)
end
function GroupCalendar._APIEventMethods:SetTitleTag(pTitleTag)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.TitleTag = pTitleTag
GroupCalendar.WoWCalendar:CalendarEventSetTitleTag(pTitleTag)
end
function GroupCalendar._APIEventMethods:SetDescription(pDescription)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.Description = pDescription
GroupCalendar.WoWCalendar:CalendarEventSetDescription(pDescription)
end
function GroupCalendar._APIEventMethods:SetDescriptionTag(pDescriptionTag)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.DescriptionTag = pDescriptionTag
GroupCalendar.WoWCalendar:CalendarEventSetDescriptionTag(pDescriptionTag)
GroupCalendar.BroadcastLib:Broadcast(self, "CHANGED")
end
function GroupCalendar._APIEventMethods:SetType(pEventType, pTextureIndex)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.EventType = pEventType
self.TextureIndex = pTextureIndex
GroupCalendar.WoWCalendar:CalendarEventSetType(pEventType)
if self.TextureIndex then
GroupCalendar.WoWCalendar:CalendarEventSetTextureID(self.TextureIndex)
end
end
function GroupCalendar._APIEventMethods:SetRepeatOption(pRepeatOption)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.RepeatOption = pRepeatOption
GroupCalendar.WoWCalendar:CalendarEventSetRepeatOption(pRepeatOption)
end
function GroupCalendar._APIEventMethods:SetLocked(pLocked)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
if pLocked then
GroupCalendar.WoWCalendar:CalendarEventSetLocked()
else
GroupCalendar.WoWCalendar:CalendarEventClearLocked()
end
end
function GroupCalendar._APIEventMethods:SetDuration(pMinutes)
self.Duration = pMinutes
self:UpdateDescriptionTag()
end
function GroupCalendar._APIEventMethods:SetLimits(pLimits)
self.Limits = GroupCalendar:DuplicateTable(pLimits, true)
self:UpdateDescriptionTag()
end
function GroupCalendar._APIEventMethods:SetLevelRange(pMinLevel, pMaxLevel)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
self.MinLevel = pMinLevel
self.MaxLevel = pMaxLevel
self:UpdateDescriptionTag()
end
function GroupCalendar._APIEventMethods:UpdateDescriptionTag()
if not self.DescriptionTags then
self.DescriptionTags = {}
end
if self.MinLevel or self.MaxLevel then
self.DescriptionTags.L = (self.MinLevel or "")..","..(self.MaxLevel or "")
else
self.DescriptionTags.L = nil
end
if self.Duration then
self.DescriptionTags.D = tostring(self.Duration)
else
self.DescriptionTags.D = nil
end
if self.Limits then
self.DescriptionTags.C = self:GetAutoConfirmString()
else
self.DescriptionTags.C = nil
end
local vDescriptionTag
for vTag, vValue in pairs(self.DescriptionTags) do
if vDescriptionTag then
vDescriptionTag = vDescriptionTag.."/"..vTag..":"..vValue
else
vDescriptionTag = vTag..":"..vValue
end
end
self:SetDescriptionTag(vDescriptionTag)
end
function GroupCalendar._APIEventMethods:GetAutoConfirmString()
local vString = "ROLE"
if self.Limits then
if self.Limits.MaxAttendance then
vString = vString..":X"..self.Limits.MaxAttendance
end
if self.Limits.RoleLimits then
for vRoleCode, vRoleLimit in pairs(self.Limits.RoleLimits) do
vString = vString..":"..vRoleCode..(vRoleLimit.Min or "")..","..(vRoleLimit.Max or "")
if vRoleLimit.Class then
for vClassID, vClassLimit in pairs(vRoleLimit.Class) do
local vClassCode = GroupCalendar.ClassInfoByClassID[vClassID].ClassCode
vString = vString..vClassCode..vClassLimit
end
end
end
end
end
return vString
end
----------------------------------------
-- Attendance
function GroupCalendar._APIEventMethods:RefreshAttendance(pIgnoreOpenedEvent)
assert(GroupCalendar.WoWCalendar.OpenedEvent == self or pIgnoreOpenedEvent)
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(NORMAL_FONT_COLOR_CODE.."RefreshAttendance, MinLevel=%s", tostring(self.MinLevel))
end
local vChanged
if not self.Attendance then
self.Attendance = {}
else
for vName, vInfo in pairs(self.Attendance) do
vInfo.Unused = true
end
end
self.NumInvites = GroupCalendar.WoWCalendar:CalendarEventGetNumInvites() or 0
for vIndex = 1, self.NumInvites do
local vName, vLevel, vClassName, vClassFileName, vInviteStatus, vModStatus, vInviteIsMine = GroupCalendar.WoWCalendar:CalendarEventGetInvite(vIndex)
local vResponseDate, vResponseTime
if CalendarEventGetInviteResponseTime then
local vWeekday, vMonth, vDay, vYear, vHour, vMinute = GroupCalendar.WoWCalendar:CalendarEventGetInviteResponseTime(vIndex)
if vYear and vYear ~= 0 then
vResponseDate = GroupCalendar.DateLib:ConvertMDYToDate(vMonth, vDay, vYear)
vResponseTime = GroupCalendar.DateLib:ConvertHMToTime(vHour, vMinute)
end
end
local vInfo = self.Attendance[vName or ""]
if not vName then
-- The server didn't respond, probably laggy
elseif not vInfo then
-- Use the current date/time if no stamp is found
if not vResponseDate
and (vInviteStatus == CALENDAR_INVITESTATUS_ACCEPTED
or vInviteStatus == CALENDAR_INVITESTATUS_TENTATIVE
or vInviteStatus == CALENDAR_INVITESTATUS_CONFIRMED
or vInviteStatus == CALENDAR_INVITESTATUS_STANDBY
or vInviteStatus == CALENDAR_INVITESTATUS_SIGNEDUP) then
vResponseDate, vResponseTime = GroupCalendar.DateLib:GetServerDateTime()
end
-- Create the new record
vInfo =
{
Name = vName,
Level = vLevel,
ClassName = vClassName,
ClassID = vClassFileName,
RoleCode = GroupCalendar:GetPlayerDefaultRoleCode(vName, vClassFileName),
InviteStatus = vInviteStatus,
ModStatus = vModStatus,
InviteIsMine = vInviteIsMine,
ResponseDate = vResponseDate,
ResponseTime = vResponseTime,
}
self.Attendance[vName] = vInfo
vChanged = true
else
vInfo.Unused = nil
if vInfo.Name ~= vName then
vInfo.Name = vName
vChanged = true
end
if vInfo.Level ~= vLevel then
vInfo.Level = vLevel
vChanged = true
end
if vInfo.ClassName ~= vClassName then
vInfo.ClassName = vClassName
vChanged = true
end
if vInfo.ClassID ~= vClassFileName then
vInfo.ClassID = vClassFileName
vChanged = true
end
if vInfo.InviteStatus ~= vInviteStatus then
vInfo.InviteStatus = vInviteStatus
vChanged = true
end
if vInfo.ModStatus ~= vModStatus then
vInfo.ModStatus = vModStatus
vChanged = true
end
if vInfo.InviteIsMine ~= vInviteIsMine then
vInfo.InviteIsMine = vInviteIsMine
vChanged = true
end
if not vResponseDate then
if not vInfo.ResponseDate
and (vInviteStatus == CALENDAR_INVITESTATUS_ACCEPTED
or vInviteStatus == CALENDAR_INVITESTATUS_TENTATIVE
or vInviteStatus == CALENDAR_INVITESTATUS_CONFIRMED
or vInviteStatus == CALENDAR_INVITESTATUS_STANDBY
or vInviteStatus == CALENDAR_INVITESTATUS_SIGNEDUP) then
vInfo.ResponseDate, vInfo.ResponseTime = GroupCalendar.DateLib:GetServerDateTime()
vChanged = true
end
elseif vInfo.ResponseDate ~= vResponseDate
or vInfo.ResponseTime ~= vResponseTime then
vInfo.ResponseDate = vResponseDate
vInfo.ResponseTime = vResponseTime
vChanged = true
end
end
end -- for vIndex
for vName, vInfo in pairs(self.Attendance) do
if vInfo.Unused then
self.Attendance[vName] = nil
vChanged = true
end
end
self.CacheUpdateDate, self.CacheUpdateTime = GroupCalendar.DateLib:GetServerDateTime()
if vChanged then
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(NORMAL_FONT_COLOR_CODE.."Sending INVITES_CHANGED, MinLevel=%s", tostring(self.MinLevel))
end
GroupCalendar.BroadcastLib:Broadcast(self, "INVITES_CHANGED")
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(NORMAL_FONT_COLOR_CODE.."Sent INVITES_CHANGED, MinLevel=%s", tostring(self.MinLevel))
end
end
if self.OriginalEvent then
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(NORMAL_FONT_COLOR_CODE.."Refreshing OriginalEvent, MinLevel=%s", tostring(self.MinLevel))
end
self.OriginalEvent:RefreshAttendance(true)
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(NORMAL_FONT_COLOR_CODE.."Refreshed OriginalEvent, MinLevel=%s", tostring(self.MinLevel))
end
end
return vChanged
end
function GroupCalendar._APIEventMethods:MassInvite(pMinLevel, pMaxLevel, pMinRank)
local _, vDefaultMaxLevel = GroupCalendar.WoWCalendar:CalendarDefaultGuildFilter()
GroupCalendar.WoWCalendar:CalendarMassInviteGuild(pMinLevel or 1, pMaxLevel or vDefaultMaxLevel, pMinRank)
end
function GroupCalendar._APIEventMethods:ReadyToContinueInvites()
if not self.DesiredAttendance then
return false
end
if self.WaitingForEventID then
return false
end
if GroupCalendar.WoWCalendar:CalendarIsActionPending() then
-- Listen for action pending events so we can tell when the API is available again
if not GroupCalendar.EventLib:EventIsRegistered("CALENDAR_ACTION_PENDING", self.CalendarActionPending, self) then
GroupCalendar.EventLib:RegisterEvent("CALENDAR_ACTION_PENDING", self.CalendarActionPending, self)
end
return false
end
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_ACTION_PENDING", self.CalendarActionPending, self)
if not GroupCalendar.WoWCalendar:CalendarCanSendInvite() then
-- Start the timer so we can tell when invites are available again
GroupCalendar.SchedulerLib:ScheduleUniqueRepeatingTask(0.1, self.CheckCanSendInvite, self)
return false
end
GroupCalendar.SchedulerLib:UnscheduleTask(self.CheckCanSendInvite, self)
return true
end
function GroupCalendar._APIEventMethods:CalendarActionPending(pEventID, pBusy)
if pBusy then return end
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_ACTION_PENDING", self.CalendarActionPending, self)
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("CalendarActionPending: Free")
end
self:CheckDesiredAttendance()
end
function GroupCalendar._APIEventMethods:WaitForEvent(pEventID)
assert(self.WaitingForEventID == nil)
self.WaitingForEventID = pEventID
GroupCalendar.EventLib:RegisterEvent(self.WaitingForEventID, self.ProcessWaitForEvent, self)
end
function GroupCalendar._APIEventMethods:ProcessWaitForEvent(pEventID, pParam)
assert(self.WaitingForEventID ~= nil)
if self.WaitingForEventID ~= pEventID then
error("Unexpected event "..tostring(pEventID))
end
GroupCalendar.EventLib:UnregisterEvent(self.WaitingForEventID, self.ProcessWaitForEvent, self)
self.WaitingForEventID = nil
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("CalendarActionPending: Found event %s", pEventID)
end
self:CheckDesiredAttendance()
end
function GroupCalendar._APIEventMethods:CheckCanSendInvite()
if not GroupCalendar.WoWCalendar:CalendarCanSendInvite() then
return
end
GroupCalendar.SchedulerLib:UnscheduleTask(self.CheckCanSendInvite, self)
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(GREEN_FONT_COLOR_CODE.."CanSendInvite")
end
self:CheckDesiredAttendance()
end
function GroupCalendar._APIEventMethods:FindInviteByName(pName)
local vNumInvites = GroupCalendar.WoWCalendar:CalendarEventGetNumInvites()
for vIndex = 1, vNumInvites do
local vName, vLevel, vClassName, vClassFileName, vInviteStatus, vModStatus, vInviteIsMine = GroupCalendar.WoWCalendar:CalendarEventGetInvite(vIndex)
if vName == pName then
return vIndex, vName, vLevel, vClassName, vClassFileName, vInviteStatus, vModStatus, vInviteIsMine
end
end
end
function GroupCalendar._APIEventMethods:GetDesiredAttendanceCount()
if not self.DesiredAttendance then
return 0
end
local vTotalChanges = 0
-- Removed players
for vName, vInfo in pairs(self.Attendance) do
if not self.DesiredAttendance[vName] then
vTotalChanges = vTotalChanges + 1
end
end
-- New/updated players
for vName, vInfo in pairs(self.DesiredAttendance) do
local vCurrentInfo = self.Attendance[vName]
if not vCurrentInfo then
vTotalChanges = vTotalChanges + 1
elseif vCurrentInfo.ModStatus ~= "CREATOR"
and (vCurrentInfo.ModStatus ~= vInfo.ModStatus or vCurrentInfo.InviteStatus ~= vInfo.InviteStatus) then
vTotalChanges = vTotalChanges + 1
end
end
return vTotalChanges
end
function GroupCalendar._APIEventMethods:GetDesiredNewAttendanceCount()
if not self.DesiredAttendance then
return 0
end
local vTotalChanges = 0
for vName, vInfo in pairs(self.DesiredAttendance) do
local vCurrentInfo = self.Attendance[vName]
if not vCurrentInfo then
vTotalChanges = vTotalChanges + 1
end
end
return vTotalChanges
end
function GroupCalendar._APIEventMethods:AllDesiredAttendanceIsInGuild()
local vMinLevel, vMaxLevel, vMinRank
for vName, vInfo in pairs(self.DesiredAttendance) do
local vPlayerInfo = GroupCalendar.GuildLib:GetPlayer(vName)
if not vPlayerInfo then
return false
end
if not self.Attendance[vName]
or self.Attendance[vName].ModStatus ~= "CREATOR" then
if not vMinLevel or vPlayerInfo.Level < vMinLevel then
vMinLevel = vPlayerInfo.Level
end
if not vMaxLevel or vPlayerInfo.Level > vMaxLevel then
vMaxLevel = vPlayerInfo.Level
end
if not vMinRank or vPlayerInfo.GuildRank > vMinRank then
vMinRank = vPlayerInfo.GuildRank
end
end
end
return true, vMinLevel, vMaxLevel, vMinRank
end
function GroupCalendar._APIEventMethods:CheckDesiredAttendance()
if self.CheckingDesiredAttendance then
return
end
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("CheckDesiredAttendance")
end
self.CheckingDesiredAttendance = true
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_UPDATE_INVITE_LIST", self.CalendarUpdateEventInvites, self)
self:CheckDesiredAttendance_Body()
self.CheckingDesiredAttendance = nil
GroupCalendar.EventLib:RegisterEvent("CALENDAR_UPDATE_INVITE_LIST", self.CalendarUpdateEventInvites, self)
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("CheckDesiredAttendance: Done")
end
self:RefreshAttendance()
end
function GroupCalendar._APIEventMethods:CheckDesiredAttendance_Body()
local vEventMinLevel = self.MinLevel or 1
local vEventMaxLevel = self.MaxLevel or MAX_PLAYER_LEVEL_TABLE[#MAX_PLAYER_LEVEL_TABLE]
-- If this is a new private event, and everyone on the list is a guild member,
-- and there are invitees missing, use the mass invite feature
if not self.Index -- New event
and self.CalendarType ~= "GUILD_EVENT"
and CanEditGuildEvent() -- Mass invite is available to this player
and self:GetDesiredNewAttendanceCount() > 0 then
local vAllGuild, vMinLevel, vMaxLevel, vMinRank = self:AllDesiredAttendanceIsInGuild()
if vAllGuild then
if not self:ReadyToContinueInvites() then
return
end
if vMinLevel < vEventMinLevel then
vMinLevel = vEventMinLevel
end
if vMaxLevel > vEventMaxLevel then
vMaxLevel = vEventMaxLevel
end
GroupCalendar.BroadcastLib:Broadcast(self, "INVITE_QUEUE_UPDATE", GroupCalendar.cWaitingForServerInvite)
self:WaitForEvent("CALENDAR_UPDATE_INVITE_LIST")
self:MassInvite(1, nil, vMinRank + 1)
end
end
--
while self.DesiredAttendance ~= nil do
-- Remove unwanted players
for vName, vInfo in pairs(self.Attendance) do
if not self:ReadyToContinueInvites() then
return
end
if not self.DesiredAttendance[vName] then
GroupCalendar.BroadcastLib:Broadcast(self, "INVITE_QUEUE_UPDATE", string.format("Removing %s", vName))
local vIndex, vName, vLevel, vClassName, vClassFileName, vInviteStatus, vModStatus, vInviteIsMine = self:FindInviteByName(vName)
assert(vIndex ~= nil)
assert(vModStatus ~= "CREATOR")
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("CalendarEventRemoveInvite(%s)", vName)
end
self:WaitForEvent("CALENDAR_UPDATE_INVITE_LIST")
GroupCalendar.WoWCalendar:CalendarEventRemoveInvite(vIndex)
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("CalendarEventRemoveInvite(%s): Done", vName)
end
end
end
-- Invite missing players
if not self:ReadyToContinueInvites() then
return
end
for vName, vInfo in pairs(self.DesiredAttendance) do
GroupCalendar.BroadcastLib:Broadcast(self, "INVITE_QUEUE_UPDATE", string.format(GroupCalendar.cAddingInviteFormat, vName))
if not self.Attendance[vName] then
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("CalendarEventInvite(%s)", vName)
end
self:WaitForEvent("CALENDAR_UPDATE_INVITE_LIST")
GroupCalendar.WoWCalendar:CalendarEventInvite(vName)
end
if not self:ReadyToContinueInvites() then
return
end
end
-- Update mis-matched player status
if not self:ReadyToContinueInvites() then
return
end
for vName, vInfo in pairs(self.DesiredAttendance) do
local vCurrentInfo = self.Attendance[vName]
if (vCurrentInfo.ModStatus ~= "CREATOR" and vCurrentInfo.ModStatus ~= vInfo.ModStatus)
or vCurrentInfo.InviteStatus ~= vInfo.InviteStatus then
GroupCalendar.BroadcastLib:Broadcast(self, "INVITE_QUEUE_UPDATE", string.format("Updating %s", vName))
local vIndex, vName, vLevel, vClassName, vClassFileName, vInviteStatus, vModStatus, vInviteIsMine = self:FindInviteByName(vName)
assert(vIndex ~= nil)
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("CalendarEventSetStatus/Moderator(%s): Index=%s, Status=%s", vName, tostring(vIndex), tostring(vInfo.InviteStatus))
end
if vCurrentInfo.InviteStatus ~= vInfo.InviteStatus then
GroupCalendar.WoWCalendar:CalendarEventSetStatus(vIndex, vInfo.InviteStatus)
end
if vCurrentInfo.ModStatus ~= "CREATOR" and vCurrentInfo.ModStatus ~= vInfo.ModStatus then
if vInfo.ModStatus == "MODERATOR" then
GroupCalendar.WoWCalendar:CalendarEventSetModerator(vIndex)
else
GroupCalendar.WoWCalendar:CalendarEventClearModerator(vIndex)
end
end
end
if not self:ReadyToContinueInvites() then
return
end
end
-- All clear
self.DesiredAttendance = nil
GroupCalendar.BroadcastLib:Broadcast(self, "INVITE_QUEUE_END")
end -- while
end
function GroupCalendar._APIEventMethods:PlayerInviteIsPending(pPlayerName)
if not self.DesiredAttendance then
return false
end
local vCurrentInfo = self.Attendance and self.Attendance[pPlayerName]
local vDesiredInfo = self.DesiredAttendance[pPlayerName]
if (vCurrentInfo == nil) ~= (vDesiredInfo == nil) then
return true
end
if not vCurrentInfo then
return false
end
return vCurrentInfo.InviteStatus ~= vDesiredInfo.InviteStatus
or vCurrentInfo.ModStatus ~= vDesiredInfo.ModStatus
end
----------------------------------------
-- Invites
function GroupCalendar._APIEventMethods:BeginBatchInvites()
self.DoingBatchInvites = true
end
function GroupCalendar._APIEventMethods:EndBatchInvites()
self.DoingBatchInvites = nil
self:DesiredAttendanceChanged()
end
function GroupCalendar._APIEventMethods:CancelPendingInvites()
if not self.DesiredAttendance then
return
end
self.DesiredAttendance = nil
if self.WaitingForEventID then
GroupCalendar.EventLib:UnregisterEvent(self.WaitingForEventID, self.ProcessWaitForEvent, self)
self.WaitingForEventID = nil
end
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_ACTION_PENDING", self.CalendarActionPending, self)
GroupCalendar.SchedulerLib:UnscheduleTask(self.CheckCanSendInvite, self)
GroupCalendar.BroadcastLib:Broadcast(self, "INVITE_QUEUE_END")
end
function GroupCalendar._APIEventMethods:CalendarUpdateError(pEvent, pMessage)
if not self.DesiredAttendance then
return
end
self:CancelPendingInvites()
GroupCalendar:ErrorMessage(GroupCalendar.cInviteErrorMessage, tostring(pMessage))
end
function GroupCalendar._APIEventMethods:InvitePlayer(pPlayerName)
if self.Attendance and self.Attendance[pPlayerName] then
return
end
local vDesiredAttendance = self:GetDesiredAttendance(true)
if vDesiredAttendance[pPlayerName] then
return
end
vDesiredAttendance[pPlayerName] =
{
Name = pPlayerName,
InviteStatus = CALENDAR_INVITESTATUS_INVITED,
ModStatus = "",
}
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(RED_FONT_COLOR_CODE.."InvitePlayer(%s)", pPlayerName)
end
if not self.DoingBatchInvites then
self:DesiredAttendanceChanged()
end
end
function GroupCalendar._APIEventMethods:UninvitePlayer(pPlayerName)
local vCurrentInfo = self.Attendance[pPlayerName]
if not vCurrentInfo and not self.DesiredAttendance then
return
end
if vCurrentInfo and vCurrentInfo.ModStatus == "CREATOR" then
return -- Can't uninvite the creator
end
local vDesiredAttendance = self:GetDesiredAttendance(true)
vDesiredAttendance[pPlayerName] = nil
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(RED_FONT_COLOR_CODE.."UninvitePlayer(%s)", pPlayerName)
end
if not self.DoingBatchInvites then
self:DesiredAttendanceChanged()
end
end
function GroupCalendar._APIEventMethods:ContextSelectEvent()
GroupCalendar.WoWCalendar:CalendarContextSelectEvent(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
end
function GroupCalendar._APIEventMethods:SetConfirmedStatus()
-- If it's a new event or if the event is open and it's for
-- the creator then set the status manually since the normal
-- APIs won't work
if not self.Index
or (GroupCalendar.WoWCalendar.OpenedEvent == self and self.ModStatus == "CREATOR") then
self:SetInviteStatus(GroupCalendar.PlayerName, CALENDAR_INVITESTATUS_CONFIRMED)
return
end
-- If the event isn't currently open then use the context APIs
-- to set the status. These APIs don't work for the creator
if self.ModStatus == "CREATOR" then
return -- Can't use context APIs for creator
end
if GroupCalendar.WoWCalendar.OpenedEvent ~= self then
self:ContextSelectEvent()
if self:IsSignupEvent() then
GroupCalendar.WoWCalendar:CalendarContextEventSignUp()
else
GroupCalendar.WoWCalendar:CalendarContextInviteAvailable()
end
return
end
-- The event is currently opened and it isn't the creator. Use
-- the normal event response APIs
if self:IsSignupEvent() then
GroupCalendar.WoWCalendar:CalendarEventSignUp()
else
GroupCalendar.WoWCalendar:CalendarEventAvailable()
end
end
function GroupCalendar._APIEventMethods:SetTentativeStatus()
-- If it's a new event or if the event is open and it's for
-- the creator then set the status manually since the normal
-- APIs won't work
if not self.Index
or (GroupCalendar.WoWCalendar.OpenedEvent == self and self.ModStatus == "CREATOR") then
self:SetInviteStatus(GroupCalendar.PlayerName, CALENDAR_INVITESTATUS_TENTATIVE)
return
end
-- If the event isn't currently open then use the context APIs
-- to set the status. These APIs don't work for the creator
if self.ModStatus == "CREATOR" then
return -- Can't use context APIs for creator
end
if GroupCalendar.WoWCalendar.OpenedEvent ~= self then
self:ContextSelectEvent()
GroupCalendar.WoWCalendar:CalendarContextInviteTentative()
return
end
-- The event is currently opened and it isn't the creator. Use
-- the normal event response APIs
GroupCalendar.WoWCalendar:CalendarEventTentative()
end
function GroupCalendar._APIEventMethods:SetDeclinedStatus()
-- If it's a new event or if the event is open and it's for
-- the creator then set the status manually since the normal
-- APIs won't work
if not self.Index
or (GroupCalendar.WoWCalendar.OpenedEvent == self and self.ModStatus == "CREATOR") then
if self.CalendarType == "GUILD_EVENT" then
self:SetInviteStatus(GroupCalendar.PlayerName, CALENDAR_INVITESTATUS_OUT)
else
self:SetInviteStatus(GroupCalendar.PlayerName, CALENDAR_INVITESTATUS_DECLINED)
end
return
end
-- If the event isn't currently open then use the context APIs
-- to set the status. These APIs don't work for the creator
if self.ModStatus == "CREATOR" then
return -- Can't use context APIs for creator
end
if GroupCalendar.WoWCalendar.OpenedEvent ~= self then
self:ContextSelectEvent()
if self:IsSignupEvent() then
GroupCalendar.WoWCalendar:CalendarContextInviteRemove()
else
GroupCalendar.WoWCalendar:CalendarContextInviteDecline()
end
return
end
-- The event is currently opened and it isn't the creator. Use
-- the normal event response APIs
if self:IsSignupEvent() then
GroupCalendar.WoWCalendar:CalendarRemoveEvent()
else
GroupCalendar.WoWCalendar:CalendarEventDecline()
end
end
function GroupCalendar._APIEventMethods:SetInviteStatus(pPlayerName, pInviteStatus)
local vDesiredAttendance = self:GetDesiredAttendance(true)
assert(vDesiredAttendance[pPlayerName] ~= nil)
vDesiredAttendance[pPlayerName].InviteStatus = pInviteStatus
vDesiredAttendance[pPlayerName].Queued = false
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(RED_FONT_COLOR_CODE.."SetInviteStatus(%s, %s)", pPlayerName, tostring(pInviteStatus))
end
if not self.DoingBatchInvites then
self:DesiredAttendanceChanged()
end
end
function GroupCalendar._APIEventMethods:SetModerator(pPlayerName, pModerator)
local vDesiredAttendance = self:GetDesiredAttendance(true)
assert(vDesiredAttendance[pPlayerName] ~= nil)
vDesiredAttendance[pPlayerName].ModStatus = pModerator and "MODERATOR"
vDesiredAttendance[pPlayerName].Queued = false
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(RED_FONT_COLOR_CODE.."SetModerator(%s, %s)", pPlayerName, tostring(pModerator))
end
if not self.DoingBatchInvites then
self:DesiredAttendanceChanged()
end
end
function GroupCalendar._APIEventMethods:SetInviteRoleCode(pPlayerName, pRoleCode)
assert(self.Attendance[pPlayerName] ~= nil)
self.Attendance[pPlayerName].RoleCode = pRoleCode
if self.OriginalEvent then
self.OriginalEvent:SetInviteRoleCode(pPlayerName, pRoleCode)
end
end
function GroupCalendar._APIEventMethods:GetAttendance()
if self.DesiredAttendance then
return self.DesiredAttendance
end
return self.Attendance
end
function GroupCalendar._APIEventMethods:GetDesiredAttendance(pCreate)
if not self.DesiredAttendance and pCreate then
if self.Attendance then
self.DesiredAttendance = GroupCalendar:DuplicateTable(self.Attendance, true)
else
self.DesiredAttendance = {}
end
GroupCalendar.BroadcastLib:Broadcast(self, "INVITE_QUEUE_BEGIN")
GroupCalendar.WoWCalendar:ResetInviteActionCount()
end
return self.DesiredAttendance
end
function GroupCalendar._APIEventMethods:GetPlayerInvite(pPlayerName)
local vAttendance = self:GetAttendance()
return vAttendance and vAttendance[pPlayerName]
end
function GroupCalendar._APIEventMethods:DesiredAttendanceChanged()
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage("DesiredAttendanceChanged")
end
self:CheckDesiredAttendance()
end
----------------------------------------
-- Status
function GroupCalendar._APIEventMethods:CanDelete()
if not self:IsPlayerCreated() then
return false
end
if self.Index then
return GroupCalendar.WoWCalendar:CalendarContextEventCanEdit(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
else
return true
end
end
function GroupCalendar._APIEventMethods:CanEdit()
if self.ModStatus ~= "MODERATOR"
and self.ModStatus ~= "CREATOR" then
return false
end
if not self:IsPlayerCreated() then
return false
end
if self.TitleTag
and (not GroupCalendar.TitleTagInfo[self.TitleTag]
or not GroupCalendar.TitleTagInfo[self.TitleTag].CanEdit) then
return false
end
if self.Index then
return GroupCalendar.WoWCalendar:CalendarContextEventCanEdit(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
else
return true
end
end
function GroupCalendar._APIEventMethods:CanCopy()
return self.Index and self:CanEdit()
end
function GroupCalendar._APIEventMethods:CanComplain()
if not self.Index then
return false
end
return self.EventCanComplain
end
function GroupCalendar._APIEventMethods:Complain()
GroupCalendar.WoWCalendar:CalendarContextSelectEvent(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
GroupCalendar.WoWCalendar:CalendarContextEventComplain()
end
function GroupCalendar._APIEventMethods:CanRemove()
return self.Index
and self.ModStatus ~= "CREATOR"
and (self.CalendarType == "PLAYER"
or (self.CalendarType == "GUILD_EVENT" and self.InviteType == CALENDAR_INVITETYPE_NORMAL))
end
function GroupCalendar._APIEventMethods:Remove()
GroupCalendar.WoWCalendar:CalendarContextSelectEvent(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day, self.Index)
GroupCalendar.WoWCalendar:CalendarContextInviteRemove()
end
function GroupCalendar._APIEventMethods:IsGuildWide()
return self.CalendarType == "GUILD_ANNOUNCEMENT" or self.CalendarType == "GUILD" or self.CalendarType == "GUILD_EVENT"
end
function GroupCalendar._APIEventMethods:CanRSVP()
if not self:UsesAttendance() then
return false
end
return not self:IsExpired()
end
----------------------------------------
-- Events
function GroupCalendar._APIEventMethods:CalendarOpenEvent()
self:GetEventInfo()
end
function GroupCalendar._APIEventMethods:EventClosed()
assert(GroupCalendar.WoWCalendar.OpenedEvent == self)
if self.ChangingMode then
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(RED_FONT_COLOR_CODE.."Ignoring event closed -- event is transitioning")
end
return
end
if GroupCalendar.Debug.invites then
GroupCalendar:DebugMessage(RED_FONT_COLOR_CODE.."Event closed")
end
GroupCalendar.WoWCalendar:ClearQueue()
GroupCalendar.WoWCalendar.OpenedEvent = nil
if self.DesiredAttendance then
self:CancelPendingInvites()
GroupCalendar:NoteMessage(GroupCalendar.cInvitesCanceledMessage)
end
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_OPEN_EVENT", self.CalendarOpenEvent, self)
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_CLOSE_EVENT", self.EventClosed, self)
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_UPDATE_EVENT", self.CalendarUpdateEvent, self)
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_UPDATE_INVITE_LIST", self.CalendarUpdateEventInvites, self)
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_UPDATE_ERROR", self.CalendarUpdateError, self)
GroupCalendar.BroadcastLib:StopListening(nil, self.ShadowEventMessage, self)
GroupCalendar.BroadcastLib:Broadcast(self, "CLOSED")
end
function GroupCalendar._APIEventMethods:CalendarUpdateEvent()
self:GetEventInfo()
end
function GroupCalendar._APIEventMethods:CalendarUpdateEventInvites()
self:GetEventAttendance()
end
----------------------------------------
GroupCalendar._CachedEventMethods = {}
----------------------------------------
for vName, vFunction in pairs(GroupCalendar._BaseEventMethods) do
GroupCalendar._CachedEventMethods[vName] = vFunction
end
function GroupCalendar._CachedEventMethods:Open()
end
function GroupCalendar._CachedEventMethods:Close()
end
function GroupCalendar._CachedEventMethods:Save()
error("Can't save cached events")
end
function GroupCalendar._CachedEventMethods:Delete()
error("Can't delete cached events")
end
function GroupCalendar._CachedEventMethods:CanEdit()
return false
end
function GroupCalendar._CachedEventMethods:CanCopy()
return false
end
function GroupCalendar._CachedEventMethods:CanDelete()
return false
end
function GroupCalendar._CachedEventMethods:CanRSVP()
return false
end
function GroupCalendar._CachedEventMethods:CanComplain()
return false
end
function GroupCalendar._CachedEventMethods:CanRemove()
return false
end
function GroupCalendar._CachedEventMethods:IsGuildWide()
return self.CalendarType == "GUILD_ANNOUNCEMENT"
end
function GroupCalendar._CachedEventMethods:CanSendInvite(pIgnoreOpenedEvent)
return false
end
function GroupCalendar._CachedEventMethods:SetInviteRoleCode(pPlayerName, pRoleCode)
assert(self.Attendance[pPlayerName] ~= nil)
self.Attendance[pPlayerName].RoleCode = pRoleCode
end
function GroupCalendar._CachedEventMethods:GetAttendance()
return self.Attendance
end
function GroupCalendar._CachedEventMethods:GetPlayerInvite(pPlayerName)
local vAttendance = self:GetAttendance()
return vAttendance and vAttendance[pPlayerName]
end
function GroupCalendar._CachedEventMethods:PlayerInviteIsPending(pPlayerName)
return false
end
----------------------------------------
GroupCalendar._APIEventMetaTable = {__index = GroupCalendar._APIEventMethods}
GroupCalendar._CachedEventMetaTable = {__index = GroupCalendar._CachedEventMethods}
----------------------------------------
----------------------------------------
GroupCalendar._WoWCalendar = {}
----------------------------------------
function GroupCalendar._WoWCalendar:Construct()
self.Month = 0
self.Year = 0
self.GetExtendedInfoQueue = {}
self.TitleTag = nil
self.DescriptionTag = nil
-- Hook the original APIs to extend the functionality with tag support
for _, vName in ipairs(GroupCalendar.cBlizzardCalendarFunctionNames) do
if not self[vName] then
self[vName] = function (pWoWCalendar, ...) return _G[vName](...) end
end
end
-- self.WoWAPIOrigs = {}
-- for vName, vFunction in pairs(self.WoWAPIHooks) do
-- hooksecurefunc(vName, function (...) vFunction(self, ...) end
-- self.WoWAPIOrigs[vName] = _G[vName]
-- _G[vName] = function (...) return vFunction(self, ...) end
-- end
GroupCalendar.EventLib:RegisterEvent("CALENDAR_NEW_EVENT", self.NewEventCreated, self)
end
function GroupCalendar._WoWCalendar:ResetInviteActionCount(...)
end
function GroupCalendar._WoWCalendar:QueueInviteAction(...)
end
function GroupCalendar._WoWCalendar:PlayerHasInviteAction(...)
end
function GroupCalendar._WoWCalendar:ClearQueue(...)
end
function GroupCalendar._WoWCalendar:BeginHardwareEvent()
self.HardwareEventAvailable = true
self.InviteQueue:HardwareEvent()
end
function GroupCalendar._WoWCalendar:EndHardwareEvent()
self.HardwareEventAvailable = false
end
function GroupCalendar._WoWCalendar:GetEventExtendedInfo(pEventData)
if true or pEventData.SequenceType == "ONGOING" then
return -- No extended info for ongoing events
end
GroupCalendar:DebugMessage(HIGHLIGHT_FONT_COLOR_CODE.."GetEventExtendedInfo: %s (%s/%s/%s index %s)", tostring(pEventData.Title), tostring(pEventData.Month), tostring(pEventData.Day), tostring(pEventData.Year), tostring(pEventData.Index))
table.insert(self.GetExtendedInfoQueue, pEventData)
if #self.GetExtendedInfoQueue == 1 then
self:GetNextExtendedInfo()
end
end
function GroupCalendar._WoWCalendar:GetNextExtendedInfo()
if #self.GetExtendedInfoQueue == 0 then
return
end
local vEvent = self.GetExtendedInfoQueue[1]
--GroupCalendar:DebugMessage("GetNextExtendedInfo: %s (%s/%s/%s index %s)", tostring(vEvent.Title), tostring(vEvent.Month), tostring(vEvent.Day), tostring(vEvent.Year), tostring(vEvent.Index))
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_OPEN_EVENT", self.UpdateNextQueuedEvent, self)
GroupCalendar.EventLib:RegisterEvent("CALENDAR_OPEN_EVENT", self.UpdateNextQueuedEvent, self)
GroupCalendar.SchedulerLib:ScheduleUniqueTask(2, self.GetNextExtendedInfo, self)
-- GroupCalendar.WoWCalendar:CalendarCloseEvent()
local vMonthOffset = GroupCalendar.WoWCalendar:CalendarGetMonthOffset(vEvent.Month, vEvent.Year)
--GroupCalendar:DebugMessage("GetNextExtendedInfo: CalendarOpenEvent(%s, %s, %s)", tostring(vMonthOffset), tostring(vEvent.Day), tostring(vEvent.Index))
GroupCalendar.WoWCalendar:CalendarOpenEvent(vMonthOffset, vEvent.Day, vEvent.Index)
end
function GroupCalendar._WoWCalendar:UpdateNextQueuedEvent()
GroupCalendar.SchedulerLib:UnscheduleTask(self.GetNextExtendedInfo, self)
GroupCalendar.EventLib:UnregisterEvent("CALENDAR_OPEN_EVENT", self.UpdateNextQueuedEvent, self)
local vEvent = table.remove(self.GetExtendedInfoQueue, 1)
if not vEvent then
return
end
if vEvent:UpdateExtendedInfo() then
GroupCalendar.EventLib:DispatchEvent("GC5_EVENT_CHANGED", vEvent)
end
GroupCalendar.WoWCalendar:CalendarCloseEvent()
self:GetNextExtendedInfo()
end
function GroupCalendar._WoWCalendar:ProcessTitle(pTitle)
local vTagStart, vTagEnd, vTagData
if pTitle then
vTagStart, vTagEnd, vTagData = pTitle:find("%s?%[(.*)%]")
end
if vTagStart then
self.Title = pTitle:sub(1, vTagStart - 1)..pTitle:sub(vTagEnd + 1)
self.TitleTag = vTagData
else
self.Title = pTitle
self.TitleTag = nil
end
-- Process tradeskill cooldowns
if self.TitleTag then
local _, _, vRecipeIDString = self.TitleTag:find("RECIPE_(.*)")
if vRecipeIDString then
local vRecipeID = tonumber(vRecipeIDString)
local vRecipeInfo = C_TradeSkillUI.GetRecipeInfo(vRecipeID)
if vRecipeInfo then
self.Title = GroupCalendar.cCooldownEventName:format(vRecipeInfo.name)
end
end
end
return self.Title
end
function GroupCalendar._WoWCalendar:ProcessDescription(pDescription)
local vTagStart, vTagEnd, vTagData
if pDescription then
vTagStart, vTagEnd, vTagData = pDescription:find("%s?%[(.*)%]")
end
if vTagStart then
self.Description = pDescription:sub(1, vTagStart - 1)..pDescription:sub(vTagEnd + 1)
self.DescriptionTag = vTagData
else
self.Description = pDescription
self.DescriptionTag = nil
end
return self.Description
end
function GroupCalendar._WoWCalendar:NewEventCreated()
if self.OpenedEvent then
self.OpenedEvent:EventClosed()
self.OpenedEvent = nil
end
end
----------------------------------------
-- WoW API hooks and extensions
----------------------------------------
function GroupCalendar._WoWCalendar:CalendarNewEvent(...)
if self.OpenedEvent then
self.OpenedEvent:Close()
end
self.SelectedEventMonth = nil
self.SelectedEventYear = nil
self.SelectedEventDay = nil
self.SelectedEventIndex = nil
self.Description = ""
self.DescriptionTag = ""
self.Title = ""
self.TitleTag = ""
return CalendarNewEvent(...)
end
function GroupCalendar._WoWCalendar:CalendarNewGuildEvent(...)
if self.OpenedEvent then
self.OpenedEvent:Close()
end
self.SelectedEventMonth = nil
self.SelectedEventYear = nil
self.SelectedEventDay = nil
self.SelectedEventIndex = nil
self.Description = ""
self.DescriptionTag = ""
self.Title = ""
self.TitleTag = ""
return CalendarNewGuildEvent(...)
end
function GroupCalendar._WoWCalendar:CalendarNewGuildAnnouncement(...)
if self.OpenedEvent then
self.OpenedEvent:Close()
end
self.SelectedEventMonth = nil
self.SelectedEventYear = nil
self.SelectedEventDay = nil
self.SelectedEventIndex = nil
self.Description = ""
self.DescriptionTag = ""
self.Title = ""
self.TitleTag = ""
return CalendarNewGuildAnnouncement(...)
end
function GroupCalendar._WoWCalendar:CalendarOpenEvent(pMonthOffset, pDay, pIndex, ...)
if self.OpenedEvent then
self.OpenedEvent:Close()
end
self.SelectedEventMonth = self.Month + pMonthOffset
self.SelectedEventYear = self.Year
self.SelectedEventDay = pDay
self.SelectedEventIndex = pIndex
while self.SelectedEventMonth > 12 do
self.SelectedEventMonth = self.SelectedEventMonth - 12
self.SelectedEventYear = self.SelectedEventYear + 1
end
while self.SelectedEventMonth < 1 do
self.SelectedEventMonth = self.SelectedEventMonth + 12
self.SelectedEventYear = self.SelectedEventYear - 1
end
self.Description = nil
self.DescriptionTag = nil
self.Title = nil
self.TitleTag = nil
return CalendarOpenEvent(pMonthOffset, pDay, pIndex, ...)
end
function GroupCalendar._WoWCalendar:CalendarEventSetDate(pMonth, pDay, pYear, ...)
self.SelectedEventMonth = pMonth
self.SelectedEventYear = pDay
self.SelectedEventDay = pYear
return CalendarEventSetDate(pMonth, pDay, pYear, ...)
end
function GroupCalendar._WoWCalendar:CalendarCloseEvent(...)
local vResult = CalendarCloseEvent(...)
if self.OpenedEvent and not self.OpenedEvent.ChangingMode then
self.OpenedEvent:EventClosed()
self.OpenedEvent = nil
end
return vResult
end
function GroupCalendar._WoWCalendar:CalendarNewArenaTeamEvent(...)
if self.OpenedEvent then
self.OpenedEvent:Close()
end
self.SelectedEventMonth = nil
self.SelectedEventYear = nil
self.SelectedEventDay = nil
self.SelectedEventIndex = nil
self.Description = ""
self.DescriptionTag = ""
self.Title = ""
self.TitleTag = ""
return CalendarNewArenaTeamEvent(...)
end
function GroupCalendar._WoWCalendar:CalendarGetDayEvent(...)
local vResult = C_Calendar.GetDayEvent(...)
vResult.title = self:ProcessTitle(vResult.title)
return vResult
end
function GroupCalendar._WoWCalendar:CalendarEventSetTitle(pTitle)
if not self.Title then
CalendarGetEventInfo()
end
self.Title = pTitle or ""
if self.TitleTag and self.TitleTag ~= "" then
local vResult = self.Title.." ["..self.TitleTag.."]"
local vTrunc = self.Title:len()
local vCount = 10
while vResult:len() > GroupCalendar.EVENT_MAX_TITLE_LENGTH do
vCount = vCount - 1
if vCount == 0 then
error("CalendarEventSetTitle locked up while truncating")
end
local vTrunc = vResult:len() - GroupCalendar.EVENT_MAX_TITLE_LENGTH
vResult = self.Title:sub(1, -(vTrunc + 1)).." ["..self.TitleTag.."]"
end
return CalendarEventSetTitle(vResult)
else
return CalendarEventSetTitle(self.Title)
end
end
function GroupCalendar._WoWCalendar:CalendarGetEventInfo()
local vResult = {CalendarGetEventInfo()}
vResult[1] = self:ProcessTitle(vResult[1])
vResult[2] = self:ProcessDescription(vResult[2])
return unpack(vResult)
end
function GroupCalendar._WoWCalendar:CalendarEventSetDescription(pDescription)
if not self.Description then
CalendarGetEventInfo()
end
self.Description = pDescription
if self.DescriptionTag and self.DescriptionTag ~= "" then
local vResult = self.Description.."\r["..self.DescriptionTag.."]"
local vTrunc = self.Description:len()
while vResult:len() > GroupCalendar.EVENT_MAX_DESCRIPTION_LENGTH do
local vTrunc = vResult:len() - GroupCalendar.EVENT_MAX_DESCRIPTION_LENGTH
vResult = self.Description:sub(1, -(vTrunc + 1)).."\r["..self.DescriptionTag.."]"
end
return CalendarEventSetDescription(vResult)
else
return CalendarEventSetDescription(self.Description)
end
end
function GroupCalendar._WoWCalendar:CalendarEventSetTitleTag(pTitleTag)
if not self.Title then
CalendarGetEventInfo()
end
self.TitleTag = pTitleTag
self:CalendarEventSetTitle(self.Title) -- This will update the title tag portion as well
end
function GroupCalendar._WoWCalendar:CalendarEventGetTitleTag()
if not self.Title then
self:CalendarGetEventInfo()
end
return self.TitleTag
end
function GroupCalendar._WoWCalendar:CalendarEventSetDescriptionTag(pDescriptionTag)
if not self.Description then
self:CalendarGetEventInfo()
end
self.DescriptionTag = pDescriptionTag
self:CalendarEventSetDescription(self.Description) -- This will update the description tag portion as well
end
function GroupCalendar._WoWCalendar:CalendarEventGetDescriptionTag()
if not self.Description then
self:CalendarGetEventInfo()
end
return self.DescriptionTag
end
function GroupCalendar._WoWCalendar:CalendarSetAbsMonth(pMonth, pYear, ...)
if self.Month == pMonth and self.Year == pYear then
return
end
self.Month = pMonth
self.Year = pYear
return CalendarSetAbsMonth(pMonth, pYear, ...)
end
function GroupCalendar._WoWCalendar:CalendarGetAbsDayEvent(pMonth, pDay, pYear, pEventIndex)
return self:CalendarGetDayEvent(self:CalendarGetMonthOffset(pMonth, pYear), pDay, pEventIndex)
end
function GroupCalendar._WoWCalendar:CalendarGetDisplayTitle(pCalendarType, pSequenceType, pTitle)
local vTitleFormats = GroupCalendar.CALENDAR_CALENDARTYPE_NAMEFORMAT[pCalendarType]
local vTitleFormat
if vTitleFormats then
vTitleFormat = vTitleFormats[pSequenceType]
end
if not vTitleFormat then
vTitleFormat = "%s"
end
return vTitleFormat:format(pTitle or "")
end
function GroupCalendar._WoWCalendar:CalendarGetMonthOffset(pMonth, pYear)
pMonth = pMonth + 12 * (pYear - self.Year)
return pMonth - self.Month
end
function GroupCalendar._WoWCalendar:CalendarGetNumAbsDayEvents(pMonth, pDay, pYear)
return self:CalendarGetNumDayEvents(self:CalendarGetMonthOffset(pMonth, pYear), pDay)
end
function GroupCalendar._WoWCalendar:CalendarRemoveAbsEvent(pMonth, pDay, pYear, pEventIndex)
return self:CalendarContextEventRemove(self:CalendarGetMonthOffset(pMonth, pYear), pDay, pEventIndex)
end
----------------------------------------
--
----------------------------------------
GroupCalendar.CALENDAR_CALENDARTYPE_TEXTURE_PATHS = {
-- ["PLAYER"] = "",
-- ["GUILD_ANNOUNCEMENT"] = "",
-- ["GUILD_EVENT"] = "",
-- ["SYSTEM"] = "",
["HOLIDAY"] = "Interface\\Calendar\\Holidays\\",
-- ["RAID_LOCKOUT"] = "",
-- ["RAID_RESET"] = "",
}
GroupCalendar.CALENDAR_CALENDARTYPE_TEXTURES =
{
["PLAYER"] = {
-- [""] = "",
},
["GUILD_ANNOUNCEMENT"] = {
-- [""] = "",
},
["GUILD_EVENT"] = {
-- [""] = "",
},
["SYSTEM"] = {
-- [""] = "",
},
["HOLIDAY"] = {
["START"] = "Interface\\Calendar\\Holidays\\Calendar_DefaultHoliday",
-- ["ONGOING"] = "",
["END"] = "Interface\\Calendar\\Holidays\\Calendar_DefaultHoliday",
["INFO"] = "Interface\\Calendar\\Holidays\\Calendar_DefaultHoliday",
-- [""] = "",
},
["RAID_LOCKOUT"] = {
-- [""] = "",
},
["RAID_RESET"] = {
-- [""] = "",
},
}
GroupCalendar.CALENDAR_CALENDARTYPE_TEXTURE_APPEND =
{
-- ["PLAYER"] = {
-- },
-- ["GUILD_ANNOUNCEMENT"] = {
-- },
-- ["GUILD_EVENT"] = {
-- },
-- ["SYSTEM"] = {
-- },
["HOLIDAY"] = {
["START"] = "Start",
["ONGOING"] = "Ongoing",
["END"] = "End",
["INFO"] = "Info",
[""] = "",
},
-- ["RAID_LOCKOUT"] = {
-- },
-- ["RAID_RESET"] = {
-- },
}
GroupCalendar.CALENDAR_CALENDARTYPE_TCOORDS =
{
["PLAYER"] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
["GUILD_ANNOUNCEMENT"] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
["GUILD_EVENT"] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
["SYSTEM"] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
["HOLIDAY"] = {
left = 0.0,
right = 0.7109375,
top = 0.0,
bottom = 0.7109375,
},
["RAID_LOCKOUT"] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
["RAID_RESET"] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
}
GroupCalendar.CALENDAR_MONTH_NAMES =
{
MONTH_JANUARY,
MONTH_FEBRUARY,
MONTH_MARCH,
MONTH_APRIL,
MONTH_MAY,
MONTH_JUNE,
MONTH_JULY,
MONTH_AUGUST,
MONTH_SEPTEMBER,
MONTH_OCTOBER,
MONTH_NOVEMBER,
MONTH_DECEMBER,
}
GroupCalendar.CALENDAR_FULLDATE_MONTH_NAMES =
{
FULLDATE_MONTH_JANUARY,
FULLDATE_MONTH_FEBRUARY,
FULLDATE_MONTH_MARCH,
FULLDATE_MONTH_APRIL,
FULLDATE_MONTH_MAY,
FULLDATE_MONTH_JUNE,
FULLDATE_MONTH_JULY,
FULLDATE_MONTH_AUGUST,
FULLDATE_MONTH_SEPTEMBER,
FULLDATE_MONTH_OCTOBER,
FULLDATE_MONTH_NOVEMBER,
FULLDATE_MONTH_DECEMBER,
}
-- Event Types
GroupCalendar.CALENDAR_EVENTTYPE_TEXTURE_PATHS = {
[CALENDAR_EVENTTYPE_RAID] = "Interface\\LFGFrame\\LFGIcon-",
[CALENDAR_EVENTTYPE_DUNGEON] = "Interface\\LFGFrame\\LFGIcon-",
}
GroupCalendar.CALENDAR_EVENTTYPE_TEXTURES = {
[CALENDAR_EVENTTYPE_RAID] = "Interface\\LFGFrame\\LFGIcon-Raid",
[CALENDAR_EVENTTYPE_DUNGEON] = "Interface\\LFGFrame\\LFGIcon-Dungeon",
[CALENDAR_EVENTTYPE_PVP] = "Interface\\Calendar\\UI-Calendar-Event-PVP",
[CALENDAR_EVENTTYPE_MEETING] = "Interface\\Calendar\\MeetingIcon",
[CALENDAR_EVENTTYPE_OTHER] = "Interface\\Calendar\\UI-Calendar-Event-Other",
}
GroupCalendar.CALENDAR_EVENTTYPE_TCOORDS = {
[CALENDAR_EVENTTYPE_RAID] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
[CALENDAR_EVENTTYPE_DUNGEON] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
[CALENDAR_EVENTTYPE_PVP] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
[CALENDAR_EVENTTYPE_MEETING] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
[CALENDAR_EVENTTYPE_OTHER] = {
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
},
}
GroupCalendar.CALENDAR_CALENDARTYPE_NAMEFORMAT =
{
HOLIDAY =
{
START = CALENDAR_EVENTNAME_FORMAT_START,
END = CALENDAR_EVENTNAME_FORMAT_END,
},
RAID_LOCKOUT =
{
[""] = CALENDAR_EVENTNAME_FORMAT_RAID_LOCKOUT,
},
RAID_RESET =
{
[""] = CALENDAR_EVENTNAME_FORMAT_RAID_RESET,
},
}
GroupCalendar.TitleTagInfo =
{
BRTH =
{
CanEdit = true,
AllDay = true,
Texture = GroupCalendar.AddonPath.."Textures\\Icon-Birth",
IsPersonal = true,
IsCooldown = false,
UsesAttendance = true,
Defaults = {CalendarType = "PLAYER", Title = GroupCalendar.cBirthdayTitleFormat},
},
MD =
{
CanEdit = true,
Texture = "Interface\\Icons\\Spell_Holy_SealOfSacrifice", -- Doctor
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
UsesAttendance = true,
Defaults = {CalendarType = "PLAYER", Title = GroupCalendar.cDoctorEventName},
},
DDS =
{
CanEdit = true,
Texture = "Interface\\Icons\\INV_Misc_Bone_09", -- Dentist
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
UsesAttendance = true,
Defaults = {CalendarType = "PLAYER", Title = GroupCalendar.cDentistEventName},
},
VAC =
{
CanEdit = true,
Texture = GroupCalendar.AddonPath.."Textures\\Icon-Vacation", -- Vacation
IsPersonal = true,
UsesAttendance = true,
Defaults = {CalendarType = "PLAYER", Title = GroupCalendar.cVacationEventName},
},
RP =
{
CanEdit = true,
Texture = GroupCalendar.AddonPath.."Textures\\Icon-RP", -- Roleplaying
IsPersonal = false,
UsesAttendance = true,
Defaults = {Title = GroupCalendar.cRoleplayEventName},
},
-- Cooldowns
XMUT =
{
CanEdit = false,
Texture = "Interface\\Icons\\Trade_Alchemy", -- Transmutes
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
ALCH =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Potion_106", -- Alchemy Research
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
VOID =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Enchant_ShardPrismaticLarge", -- Void Shatter
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
SPHR =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Enchant_VoidSphere", -- Void Sphere
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
MOON =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Fabric_MoonRag_01", -- Mooncloth
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
PMON =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Fabric_Moonshroud", -- Primal Mooncloth
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
SPEL =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Fabric_Spellfire", -- Spellcloth
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
SHAD =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Fabric_Felcloth_Ebon", -- Shadowcloth
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
EBON =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Fabric_Ebonweave", -- Ebonweave
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
SWEV =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Fabric_Spellweave", -- Spellweave
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
SHRD =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Fabric_Moonshroud", -- Moonshroud
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
GLSS =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Misc_Gem_02", -- Brilliant Glass
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
ICYP =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Misc_Gem_Diamond_02", -- Icy Prism
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
FIRP =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Misc_Gem_Ruby_01", -- Fire Prism
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
INSC =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Inscription_Tradeskill01", -- Inscription Research
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
INSN =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Inscription_Tradeskill01", -- Northrend Inscription Research
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
TITN =
{
CanEdit = false,
Texture = "Interface\\Icons\\INV_Ingot_Titansteel_blue", -- Smelt Titansteel
TexCoords = {left = 0.0625, right = 0.9375, top = 0.0625, bottom = 0.9375},
IsPersonal = true,
IsCooldown = true,
UsesAttendance = false,
},
}
GroupCalendar.CALENDAR_TITLETAG_DEFAULT_TCOORDS =
{
left = 0.0,
right = 1.0,
top = 0.0,
bottom = 1.0,
}
GroupCalendar.CALENDAR_TITLETAG_TCOORDS =
{
}
function GroupCalendar:GetTextureFile(pTextureName, pCalendarType, pSequenceType, pEventType, pTitleTag)
local vTexture, vTexCoords
-- GroupCalendar:DebugMessage("GetTextureFile: %s (CalType: %s SeqType: %s EventType: %s)", pTextureName or "nil", pCalendarType or "nil", pSequenceType or "nil", pEventType or "nil")
if pTitleTag and self.TitleTagInfo[pTitleTag] then
vTexture = self.TitleTagInfo[pTitleTag].Texture
vTexCoords = self.TitleTagInfo[pTitleTag].TexCoords or GroupCalendar.CALENDAR_TITLETAG_DEFAULT_TCOORDS
elseif pTextureName and pTextureName ~= "" then
-- pTextureName is actually a texture ID which can be used directly in the call to SetTexture()
vTexture = pTextureName
if self.CALENDAR_CALENDARTYPE_TEXTURE_PATHS[pCalendarType] then
-- vTexture = self.CALENDAR_CALENDARTYPE_TEXTURE_PATHS[pCalendarType]..pTextureName
-- if self.CALENDAR_CALENDARTYPE_TEXTURE_APPEND[pCalendarType] then
-- vTexture = vTexture..self.CALENDAR_CALENDARTYPE_TEXTURE_APPEND[pCalendarType][pSequenceType]
-- end
vTexCoords = self.CALENDAR_CALENDARTYPE_TCOORDS[pCalendarType]
elseif self.CALENDAR_EVENTTYPE_TEXTURE_PATHS[pEventType] then
-- vTexture = self.CALENDAR_EVENTTYPE_TEXTURE_PATHS[pEventType]..pTextureName
vTexCoords = self.CALENDAR_EVENTTYPE_TCOORDS[pEventType]
elseif self.CALENDAR_CALENDARTYPE_TEXTURES[pCalendarType][pSequenceType] then
-- vTexture = self.CALENDAR_CALENDARTYPE_TEXTURES[pCalendarType][pSequenceType]
vTexCoords = self.CALENDAR_CALENDARTYPE_TCOORDS[pCalendarType]
elseif self.CALENDAR_EVENTTYPE_TEXTURES[pEventType] then
-- vTexture = self.CALENDAR_EVENTTYPE_TEXTURES[pEventType]
vTexCoords = self.CALENDAR_EVENTTYPE_TCOORDS[pEventType]
end
elseif self.CALENDAR_CALENDARTYPE_TEXTURES[pCalendarType][pSequenceType] then
vTexture = self.CALENDAR_CALENDARTYPE_TEXTURES[pCalendarType][pSequenceType]
vTexCoords = self.CALENDAR_CALENDARTYPE_TCOORDS[pCalendarType]
elseif self.CALENDAR_EVENTTYPE_TEXTURES[pEventType] then
vTexture = self.CALENDAR_EVENTTYPE_TEXTURES[pEventType]
vTexCoords = self.CALENDAR_EVENTTYPE_TCOORDS[pEventType]
end
return vTexture, vTexCoords
end
function GroupCalendar:GetTextureCache()
if not self.textureCache then
self.textureCache = {}
self.textureCache[CALENDAR_EVENTTYPE_RAID] = self:TextureCacheForEventType(CALENDAR_EVENTTYPE_RAID, CalendarEventGetTextures(CALENDAR_EVENTTYPE_RAID))
self.textureCache[CALENDAR_EVENTTYPE_DUNGEON] = self:TextureCacheForEventType(CALENDAR_EVENTTYPE_DUNGEON, CalendarEventGetTextures(CALENDAR_EVENTTYPE_DUNGEON))
end
return self.textureCache
end
function GroupCalendar:TextureCacheForEventType(eventType, ...)
local eventTypeTextureCache = {}
local STRIDE = 6
local numTextures = select("#", ...) / STRIDE
if numTextures <= 0 then
return false
end
local overlappingMapIDs = (eventType == CALENDAR_EVENTTYPE_RAID or eventType == CALENDAR_EVENTTYPE_DUNGEON) and {}
local cacheIndex = 1
for textureIndex = 1, numTextures do
if not eventTypeTextureCache[cacheIndex] then
eventTypeTextureCache[cacheIndex] = {}
end
local title, texture, expansionLevel, difficultyID, mapID, isLFR = select((textureIndex - 1) * STRIDE + 1, ...)
local difficultyName, instanceType, isHeroic, isChallengeMode, displayHeroic, displayMythic, toggleDifficultyID = GetDifficultyInfo(difficultyID)
if not difficultyName then
difficultyName = ""
end
if overlappingMapIDs and overlappingMapIDs[mapID] then
-- Already exists a map, collapse the difficulty
local firstCacheIndex = overlappingMapIDs[mapID]
local cacheEntry = eventTypeTextureCache[firstCacheIndex]
if cacheEntry.isLFR and not isLFR then
-- Prefer a non-LFR name over a LFR name
cacheEntry.title = title
cacheEntry.isLFR = nil
end
if cacheEntry.displayHeroic or cacheEntry.displayMythic and (not displayHeroic and not displayMythic) then
-- Prefer normal difficulty name over higher difficulty
cacheEntry.title = title
cacheEntry.displayHeroic = nil
cacheEntry.displayMythic = nil
end
table.insert(cacheEntry.difficulties, { textureIndex = textureIndex, difficultyName = difficultyName })
else
eventTypeTextureCache [cacheIndex].textureIndex = textureIndex
eventTypeTextureCache [cacheIndex].title = title
eventTypeTextureCache [cacheIndex].texture = texture
eventTypeTextureCache [cacheIndex].expansionLevel = expansionLevel
eventTypeTextureCache [cacheIndex].difficultyName = difficultyName
eventTypeTextureCache [cacheIndex].isLFR = isLFR
eventTypeTextureCache [cacheIndex].displayHeroic = displayHeroic
eventTypeTextureCache [cacheIndex].displayMythic = displayMythic
if overlappingMapIDs then
if not overlappingMapIDs[mapID] then
overlappingMapIDs[mapID] = cacheIndex
end
eventTypeTextureCache [cacheIndex].difficulties = { { textureIndex = textureIndex, difficultyName = difficultyName } }
end
cacheIndex = cacheIndex + 1
end
end
return eventTypeTextureCache
end
function GroupCalendar:GetEventTexture(index, eventType)
local textureCache = self:GetTextureCache()
local eventTextureCache = textureCache[eventType]
if not eventTextureCache then
return nil
end
for cacheIndex, textureInfo in ipairs(eventTextureCache) do
if textureInfo.difficulties then
for difficultyIndex, difficultyInfo in ipairs(textureInfo.difficulties) do
if difficultyInfo.textureIndex == index then
return textureInfo, difficultyInfo
end
end
end
if textureInfo.textureIndex and index == textureInfo.textureIndex then
return textureInfo
end
end
return nil
end
function GroupCalendar:toluastring(pValue)
if type(pValue) == "string" then
return "\""..pValue.."\""
else
return tostring(pValue)
end
end
function GroupCalendar:ShowFunctionParameters(pFunctionName, pResult, ...)
local vFunctionParams
for vIndex = 1, select("#", ...) do
if not vFunctionParams then
vFunctionParams = self:toluastring(select(vIndex, ...))
else
vFunctionParams = vFunctionParams..", "..self:toluastring(select(vIndex, ...))
end
end
local vResults
for vIndex, vResult in ipairs(pResult) do
if not vResults then
vResults = self:toluastring(vResult)
else
vResults = vResults..", "..self:toluastring(vResult)
end
end
GroupCalendar:DebugMessage("%s(%s) returned %s", pFunctionName, vFunctionParams or "", vResults or "nil")
end
function GroupCalendar:MonitorCalendarAPIRecursion()
if self.PatchedWoWCalendarAPIRecursion then
return
end
self.InWoWAPI = {}
for _, vFunctionName in ipairs(self.cBlizzardCalendarFunctionNames) do
local vOrigFunction = _G[vFunctionName]
if vOrigFunction then
_G[vFunctionName] = function (...)
if self.InWoWAPI[vFunctionName] then
GroupCalendar:DebugMessage("Recursive call to %s", vFunctionName)
GroupCalendar:DebugStack()
return
end
self.InWoWAPI[vFunctionName] = true
local vResult = {vOrigFunction(...)}
self.InWoWAPI[vFunctionName] = nil
return unpack(vResult)
end
end
end
self.PatchedWoWCalendarAPIRecursion = true
end
function GroupCalendar:MonitorCalendarAPI()
if not self.PatchedWoWCalendarAPI then
self.InWoWAPI = {}
for _, vFunctionName in ipairs(self.cBlizzardCalendarFunctionNames) do
local vOrigFunction = _G[vFunctionName]
if vOrigFunction then
if false
and (vFunctionName == "CalendarCloseEvent"
or vFunctionName == "CalendarNewEvent") then
_G[vFunctionName] = function (...)
local vResult = {vOrigFunction(...)}
GroupCalendar:ShowFunctionParameters(vFunctionName, vResult, ...)
GroupCalendar:DebugStack()
return unpack(vResult)
end
else
_G[vFunctionName] = function (...)
local vResult = {vOrigFunction(...)}
GroupCalendar:ShowFunctionParameters(vFunctionName, vResult, ...)
return unpack(vResult)
end
end
end
end
self.PatchedWoWCalendarAPI = true
end
end
----------------------------------------
-- Group Calendar 5 Copyright 2005 - 2016 John Stephen, wobbleworks.com
-- All rights reserved, unauthorized redistribution is prohibited
----------------------------------------
----------------------------------------
GroupCalendar.UI._DaySidebar = {}
----------------------------------------
function GroupCalendar.UI._DaySidebar:New(pParent)
return GroupCalendar:New(GroupCalendar.UIElementsLib._SidebarWindowFrame, pParent)
end
function GroupCalendar.UI._DaySidebar:Construct(pParent)
self:SetWidth(350)
self:SetHeight(500)
self:SetPoint("TOPLEFT", pParent, "TOPRIGHT", -1, -20)
self.DateText = self:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
self.DateText:SetPoint("TOP", self, "TOP", 0, -33)
self.BottomTrim = self:CreateTexture(nil, "ARTWORK")
self.BottomTrim:SetHeight(32)
self.BottomTrim:SetWidth(256)
self.BottomTrim:SetTexture(GroupCalendar.UI.AddonPath.."Textures\\HorizontalTrim")
self.BottomTrim:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", 0, 4)
self.BottomTrim:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -8, 4)
self.NewEventButton = GroupCalendar:New(GroupCalendar.UIElementsLib._PushButton, self, GroupCalendar.cNewEvent, 120)
self.NewEventButton:SetPoint("RIGHT", self.BottomTrim, "RIGHT", 0, -2)
self.NewEventButton:SetScript("OnClick", function (pButton, pMouseButton)
GroupCalendar.UI.Window:OpenNewEvent(self.Month, self.Day, self.Year)
end)
self.PasteEventButton = GroupCalendar:New(GroupCalendar.UIElementsLib._PushButton, self, GroupCalendar.cPasteEvent, 120)
self.PasteEventButton:SetPoint("RIGHT", self.NewEventButton, "LEFT")
self.PasteEventButton:SetScript("OnClick", function (pButton, pMouseButton)
GroupCalendar.WoWCalendar:CalendarContextEventPaste(GroupCalendar.WoWCalendar:CalendarGetMonthOffset(self.Month, self.Year), self.Day)
end)
self.PasteEventButton:SetScript("OnUpdate", function (pButton)
pButton:SetEnabled(GroupCalendar.WoWCalendar:CalendarContextEventClipboard() and not self.ReadOnly)
end)
--
self.ItemHeight = 22
self.ScrollingList = GroupCalendar:New(GroupCalendar.UIElementsLib._ScrollingItemList, self, self._ListItem, self.ItemHeight)
self.ScrollingList.RedrawFunc = function () self:Refresh() end
self.ScrollingList:SetPoint("TOPLEFT", self, "TOPLEFT", 10, -62)
self.ScrollingList:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -9, 32)
self.ItemFrames = {}
self.Events = {}
self:SetScript("OnShow", function (self)
PlaySound("igCharacterInfoOpen")
self:Refresh()
GroupCalendar.EventLib:RegisterEvent("GC5_CALENDAR_CHANGED", self.Rebuild, self)
GroupCalendar.EventLib:RegisterEvent("GC5_PREFS_CHANGED", self.Rebuild, self)
GroupCalendar.UI.Window.MonthView:SelectDate(self.Month, self.Day, self.Year)
end)
self:SetScript("OnHide", function (self)
--
for vEventIndex, vEvent in ipairs(self.Events) do
vEvent.Unseen = nil
end
GroupCalendar.EventLib:DispatchEvent("GC5_CALENDAR_CHANGED")
--
PlaySound("igCharacterInfoClose")
GroupCalendar.EventLib:UnregisterEvent("GC5_CALENDAR_CHANGED", self.Rebuild, self)
GroupCalendar.EventLib:UnregisterEvent("GC5_PREFS_CHANGED", self.Rebuild, self)
GroupCalendar.UI.Window.MonthView:SelectDate(nil)
end)
end
function GroupCalendar.UI._DaySidebar:SetDate(pMonth, pDay, pYear)
if self.Month ~= pMonth
or self.Day ~= pDay
or self.Year ~= pYear then
for vEventIndex, vEvent in ipairs(self.Events) do
vEvent.Unseen = nil
end
GroupCalendar.EventLib:DispatchEvent("GC5_CALENDAR_CHANGED")
end
self.Month = pMonth
self.Day = pDay
self.Year = pYear
self.ReadOnly = not GroupCalendar:CanCreateEventOnDate(pMonth, pDay, pYear)
self.NewEventButton:SetEnabled(not self.ReadOnly)
self:Rebuild()
end
function GroupCalendar.UI._DaySidebar:Rebuild()
if GroupCalendar.Calendars.PLAYER:IsAfterMaxCreateDate(self.Month, self.Day, self.Year) then
self.NewEventButton:Hide()
else
self.NewEventButton:Show()
end
self:Refresh()
end
function GroupCalendar.CompareEventTimes(pEvent1, pEvent2)
if pEvent1.Year < pEvent2.Year then
return true
elseif pEvent1.Year > pEvent2.Year then
return false
end
if pEvent1.Month < pEvent2.Month then
return true
elseif pEvent1.Month > pEvent2.Month then
return false
end
if pEvent1.Day < pEvent2.Day then
return true
elseif pEvent1.Day > pEvent2.Day then
return false
end
if (pEvent1.Hour or -1) < (pEvent2.Hour or -1) then
return true
elseif (pEvent1.Hour or -1) > (pEvent2.Hour or -1) then
return false
end
if (pEvent1.Minute or 0) < (pEvent2.Minute or 0) then
return true
elseif (pEvent1.Minute or 0) > (pEvent2.Minute or 0) then
return false
end
return (pEvent1.Title or "") < (pEvent2.Title or "")
end
function GroupCalendar.UI._DaySidebar:Refresh()
-- Rebuild the event list
self.Events = GroupCalendar:GetDayEvents(self.Month, self.Day, self.Year, self.Events)
-- Update the date text
self.DateText:SetText(GroupCalendar.DateLib:GetLongDateString(GroupCalendar.DateLib:ConvertMDYToDate(self.Month, self.Day, self.Year), true))
-- Update the list
self.ScrollingList:SetNumItems(#self.Events)
for vEventIndex, vEventData in ipairs(self.Events) do
local vItemFrame = self.ScrollingList.ItemFrames[vEventIndex]
if vItemFrame then vItemFrame:SetEvent(vEventData) end
end
end
----------------------------------------
GroupCalendar.UI._DaySidebar._ListItem = {}
----------------------------------------
function GroupCalendar.UI._DaySidebar._ListItem:New(pParent)
return CreateFrame("Button", nil, pParent)
end
function GroupCalendar.UI._DaySidebar._ListItem:Construct(pParent)
local vWidth = 288
self:RegisterForClicks("LeftButtonUp", "RightButtonUp")
self:SetWidth(vWidth)
self:SetHeight(pParent.ItemHeight)
local vIconWidth = pParent.ItemHeight - 2
local vTimeTextWidth = 65
local vOwnerTextWidth = 60
local vRightMargin = 3
local vTitleTextWidth = vWidth - vTimeTextWidth - vOwnerTextWidth
self.IconTexture = self:CreateTexture(nil, "BORDER")
self.IconTexture:SetWidth(vIconWidth)
self.IconTexture:SetHeight(vIconWidth)
self.IconTexture:SetTexture(0, 1, 0)
self.IconTexture:SetPoint("LEFT", self, "LEFT", 0, 0)
self.OwnerText = self:CreateFontString(nil, "BORDER", "SystemFont_Tiny")
self.OwnerText:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
self.OwnerText:SetJustifyH("RIGHT")
self.OwnerText:SetJustifyV("BOTTOM")
-- self.OwnerText:SetWidth(vOwnerTextWidth)
self.OwnerText:SetHeight(pParent.ItemHeight)
self.OwnerText:SetPoint("RIGHT", self, "RIGHT", -vRightMargin, 6)
self.OwnerText:SetText("Gizmodo")
self.OwnerIcon = self:CreateTexture(nil, "BORDER")
self.OwnerIcon:SetTexture("Interface\\GroupFrame\\UI-Group-LeaderIcon")
self.OwnerIcon:SetWidth(16)
self.OwnerIcon:SetHeight(16)
self.OwnerIcon:SetPoint("RIGHT", self.OwnerText, "LEFT", 0, -6)
self.TitleText = self:CreateFontString(nil, "BORDER", "GameFontNormal")
self.TitleText:SetJustifyH("LEFT")
self.TitleText:SetJustifyV("BOTTOM")
self.TitleText:SetHeight(pParent.ItemHeight)
self.TitleText:SetPoint("LEFT", self.IconTexture, "RIGHT", vTimeTextWidth + 6, 5)
self.TitleText:SetPoint("RIGHT", self.OwnerIcon, "LEFT")
self.TitleText:SetText("Uldar")
self.TimeText = self:CreateFontString(nil, "BORDER", "GameFontNormal")
self.TimeText:SetJustifyH("RIGHT")
self.TimeText:SetJustifyV("BOTTOM")
self.TimeText:SetWidth(vTimeTextWidth)
self.TimeText:SetHeight(pParent.ItemHeight)
self.TimeText:SetPoint("LEFT", self.IconTexture, "RIGHT", 0, 5)
self.TimeText:SetText("12:59pm")
self.Circled = self:CreateTexture(nil, "BACKGROUND")
self.Circled:SetTexture(GroupCalendar.UI.AddonPath.."Textures\\CircledDate")
self.Circled:SetPoint("TOPLEFT", self.TimeText, "TOPLEFT", 5, -5)
self.Circled:SetPoint("BOTTOMRIGHT", self.TimeText, "BOTTOMRIGHT", 7, -6)
self:SetHighlightTexture("Interface\\HelpFrame\\HelpFrameButton-Highlight")
local vHighlightTexture = self:GetHighlightTexture()
vHighlightTexture:SetTexCoord(0, 1, 0, 0.578125)
vHighlightTexture:SetBlendMode("ADD")
self:SetScript("OnClick", self.OnClick)
end
function GroupCalendar.UI._DaySidebar._ListItem:SetEvent(pEvent)
self.Event = pEvent
if not self.Event then
return
end
local vColor = self.Event:GetEventColor()
self.TitleText:SetTextColor(vColor.r, vColor.g, vColor.b)
if self.Event:IsAllDayEvent() then
self.TitleText:SetText(self.Event.Title)
self.TimeText:SetText(GroupCalendar.cAllDay)
else
local vTime = GroupCalendar.DateLib:ConvertHMToTime(self.Event.Hour, self.Event.Minute)
if GroupCalendar.Clock.Data.ShowLocalTime then
vTime = GroupCalendar.DateLib:GetLocalTimeFromServerTime(vTime)
end
local vTimeString = GroupCalendar.DateLib:GetShortTimeString(vTime)
self.TitleText:SetText(self.Event.Title)
self.TimeText:SetText(vTimeString)
end
self.OwnerText:SetText(self.Event.OwnersName or "")
if self.Event.ModStatus == "CREATOR" then
self.OwnerIcon:SetTexture("Interface\\GroupFrame\\UI-Group-LeaderIcon")
self.OwnerIcon:Show()
elseif self.Event.ModStatus == "MODERATOR" then
self.OwnerIcon:SetTexture("Interface\\GroupFrame\\UI-Group-AssistantIcon")
self.OwnerIcon:Show()
else
self.OwnerIcon:Hide()
end
local vTexturePath, vTexCoords = GroupCalendar:GetTextureFile(pEvent.TextureID, pEvent.CalendarType, pEvent.NumSequenceDays ~= 2 and pEvent.SequenceType or "", pEvent.EventType, pEvent.TitleTag)
if pEvent.SequenceType == "ONGOING" then
-- start texture is right before ongoing texture. this works, probably not a good idea in the long run though.
vTexturePath = vTexturePath - 1
end
self.IconTexture:SetTexture(vTexturePath)
if vTexCoords then
self.IconTexture:SetTexCoord(vTexCoords.left, vTexCoords.right, vTexCoords.top, vTexCoords.bottom)
else
self.IconTexture:SetTexCoord(0, 1, 0, 1)
end
-- Circle the date if necessary
if pEvent:IsAttending() then
self.Circled:SetVertexColor(vColor.r, vColor.g, vColor.b, 0.7)
self.Circled:Show()
else
self.Circled:Hide()
end
end
function GroupCalendar.UI._DaySidebar._ListItem:OnClick(pButton)
if pButton == "RightButton" then
GroupCalendar.UI.Window.MonthView.EventMenu:Toggle(self.Event.Month, self.Event.Day, self.Event.Year, self.Event)
else
GroupCalendar.UI.Window:ShowEventSidebar(self.Event)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment