--[[ * Copyright (c) 2011-2012 by Adam Hellberg. * * This file is part of Command. * * Command is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Command is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Command. If not, see <http://www.gnu.org/licenses/>. --]] -- Manages player death and resurrection -- Disabled by default to prevent abuse -- Enabled with /command set deathmanager enabled -- Upvalues local type = type -- API Upvalues local RepopMe = RepopMe local CreateFrame = CreateFrame local HasSoulstone = HasSoulstone local UseSoulstone = UseSoulstone local AcceptResurrect = AcceptResurrect local StaticPopup_Hide = StaticPopup_Hide local StaticPopup_Visible = StaticPopup_Visible local ResurrectGetOfferer = ResurrectGetOfferer local C = Command C.DeathManager = {} local L = C.LocaleManager local DM = C.DeathManager local CM local CEN = C.Extensions.Number local DEFAULT_RELEASE_DELAY = 5 local DEFAULT_RESURRECT_DELAY = 5 local MAX_RELEASE_DELAY = 60 local MAX_RESURRECT_DELAY = 55 local DeathAnnouncePending = false local RessAnnouncePending = false local SelfRessType = { None = 0, Soulstone = 1, Reincarnate = 2, Card = 3 -- Darkmoon Card: Twisting Nether } function DM:Init() CM = C.ChatManager self:LoadSavedVars() end function DM:LoadSavedVars() if type(C.Global["DEATH_MANAGER"]) ~= "table" then C.Global["DEATH_MANAGER"] = {} end self.Settings = C.Global["DEATH_MANAGER"] if type(self.Settings.ENABLED) ~= "boolean" then self.Settings.ENABLED = false end if type(self.Settings.RELEASE_ENABLED) ~= "boolean" then self.Settings.RELEASE_ENABLED = true end if type(self.Settings.RELEASE_ANNOUNCE) ~= "boolean" then self.Settings.RELEASE_ANNOUNCE = true end if type(self.Settings.RELEASE_DELAY) ~= "number" then self.Settings.RELEASE_DELAY = DEFAULT_RELEASE_DELAY end if type(self.Settings.RESURRECT_ENABLED) ~= "boolean" then self.Settings.RESURRECT_ENABLED = true end if type(self.Settings.RESURRECT_ANNOUNCE) ~= "boolean" then self.Settings.RESURRECT_ANNOUNCE = true end if type(self.Settings.RESURRECT_DELAY) ~= "number" then self.Settings.RESURRECT_DELAY = DEFAULT_RESURRECT_DELAY end end function DM:OnDeath() if not self.Settings.ENABLED or not self.Settings.RELEASE_ENABLED or not self.Settings.RELEASE_ANNOUNCE or DeathAnnouncePending then return end self.Dead = true if self.Settings.RELEASE_DELAY > 0 then DeathAnnouncePending = true local frame = CreateFrame("Frame") frame.Time = 0 frame.Delay = self.Settings.RELEASE_DELAY frame:SetScript("OnUpdate", function(self, elapsed) self.Time = self.Time + elapsed if self.Time >= self.Delay then self:SetScript("OnUpdate", nil) self.Time = 0 DeathAnnouncePending = false DM:AnnounceDeath() end end) else self:AnnounceDeath() end end function DM:OnResurrect(resser) if not self.Settings.ENABLED or not self.Settings.RESURRECT_ENABLED or not self.Settings.RESURRECT_ANNOUNCE or RessAnnouncePending then return end self.Resurrection = true if self.Settings.RESURRECT_DELAY > 0 then RessAnnouncePending = true local frame = CreateFrame("Frame") frame.Time = 0 frame.Delay = self.Settings.RESURRECT_DELAY frame.Resser = resser frame:SetScript("OnUpdate", function(self, elapsed) self.Time = self.Time + elapsed if self.Time >= self.Delay then self:SetScript("OnUpdate", nil) self.Time = 0 RessAnnouncePending = false DM:AnnounceResurrect(self.Resser) end end) else self:AnnounceResurrect(resser) end end function DM:AnnounceDeath() if not self.Dead then return end local t = self:HasSelfRess() if t == SelfRessType.SoulStone then CM:SendMessage(L("DM_ONDEATH_SOULSTONE"), "SMART") elseif t == SelfRessType.Reincarnate then CM:SendMessage(L("DM_ONDEATH_REINCARNATE"), "SMART") elseif t == SelfRessType.Card then CM:SendMessage(L("DM_ONDEATH_CARD"), "SMART") elseif self.Settings.RELEASE_ENABLED then CM:SendMessage(L("DM_ONDEATH"), "SMART") end end function DM:AnnounceResurrect(resser) if not self.Resurrection then return end CM:SendMessage(L("DM_ONRESS"):format(resser), "SMART") end -- Returns appropriate SelfRessType function DM:HasSelfRess() local t = HasSoulstone() if not t then return SelfRessType.None elseif t:lower() == L("USE_SOULSTONE"):lower() then -- soulstone ("Use Soulstone") return SelfRessType.Soulstone elseif t:lower() == L("REINCARNATION"):lower() then -- Reincarnate return SelfRessType.Reincarnate elseif t:lower() == L("TWISTING_NETHER"):lower() then -- Darkmoon Card: Twisting Nether return SelfRessType.Card end return SelfRessType.None end function DM:Release() if not UnitIsDead("player") then return false, "DM_RELEASE_NOTDEAD" end RepopMe() if StaticPopup_Visible("DEATH") then StaticPopup_Hide("DEATH") end return "DM_RELEASED" end function DM:Resurrect() if not UnitIsDeadOrGhost("player") then return false, "DM_ERR_NOTDEAD" end local result = "DM_RESURRECTED" local selfRess = DM:HasSelfRess() local resser = ResurrectGetOfferer() if selfRess ~= SelfRessType.None then UseSoulstone() if selfRess == SelfRessType.Soulstone then result = "DM_RESURRECTED_SOULSTONE" elseif selfRess == SelfRessType.Reincarnate then result = "DM_RESURRECTED_REINCARNATE" elseif selfRess == SelfRessType.Card then result = "DM_RESURRECTED_CARD" end else if not resser then return false, "DM_RESURRECT_NOTACTIVE" end AcceptResurrect() result = "DM_RESURRECTED_PLAYER" end if StaticPopup_Visible("RESURRECT") then -- Never seems to show, but just in case StaticPopup_Hide("RESURRECT") elseif StaticPopup_Visible("RESURRECT_NO_TIMER") then StaticPopup_Hide("RESURRECT_NO_TIMER") elseif StaticPopup_Visible("RESURRECT_NO_SICKNESS") then StaticPopup_Hide("RESURRECT_NO_SICKNESS") end return result, {resser} end function DM:IsEnabled() return self.Settings.ENABLED end function DM:Enable() self.Settings.ENABLED = true return "DM_ENABLED" end function DM:Disable() self.Settings.ENABLED = false return "DM_DISABLED" end function DM:Toggle() if self:IsEnabled() then return self:Disable() end return self:Enable() end function DM:IsReleaseEnabled() return self.Settings.RELEASE_ENABLED end function DM:EnableRelease() self.Settings.RELEASE_ENABLED = true return "DM_RELEASE_ENABLED" end function DM:DisableRelease() self.Settings.RELEASE_ENABLED = false return "DM_RELEASE_DISABLED" end function DM:ToggleRelease() if self:IsReleaseEnabled() then return self:DisableRelease() end return self:EnableRelease() end function DM:IsReleaseAnnounceEnabled() return self.Settings.RELEASE_ANNOUNCE end function DM:EnableReleaseAnnounce() self.Settings.RELEASE_ANNOUNCE = true return "DM_RELEASE_ANNOUNCE_ENABLED" end function DM:DisableReleaseAnnounce() self.Settings.RELEASE_ANNOUNE = false return "DM_RELEASE_ANNOUNCE_DISABLED" end function DM:ToggleReleaseAnnounce() if self:IsReleaseAnnounceEnabled() then return self:DisableReleaseAnnounce() end return self:EnableReleaseAnnounce() end function DM:GetReleaseDelay() return self.Settings.RELEASE_DELAY end function DM:SetReleaseDelay(amount) if amount < 0 then amount = 0 elseif amount > MAX_RELEASE_DELAY then amount = MAX_RELEASE_DELAY end self.Settings.RELEASE_DELAY = amount if amount > 0 then return "DM_RELEASE_SETDELAY_SUCCESS", {CEN:FormatSeconds(amount)} end return "DM_RELEASE_SETDELAY_INSTANT" end function DM:IsResurrectEnabled() return self.Settings.RESURRECT_ENABLED end function DM:EnableResurrect() self.Settings.RESURRECT_ENABLED = true return "DM_RESURRECT_ENABLED" end function DM:DisableResurrect() self.Settings.RESURRECT_ENABLED = false return "DM_RESURRECT_DISABLED" end function DM:ToggleResurrect() if self:IsResurrectEnabled() then return self:DisableResurrect() end return self:EnableResurrect() end function DM:IsResurrectAnnounceEnabled() return self.Settings.RESURRECT_ANNOUNCE end function DM:EnableResurrectAnnounce() self.Settings.RESURRECT_ANNOUNCE = true return "DM_RESURRECT_ANNOUNCE_ENABLED" end function DM:DisableResurrectAnnounce() self.Settings.RESURRECT_ANNOUNE = false return "DM_RESURRECT_ANNOUNCE_DISABLED" end function DM:ToggleResurrectAnnounce() if self:IsResurrectAnnounceEnabled() then return self:DisableResurrectAnnounce() end return self:EnableResurrectAnnounce() end function DM:GetResurrectDelay() return self.Settings.RESURRECT_DELAY end function DM:SetResurrectDelay(amount) if amount < 0 then amount = 0 elseif amount > MAX_RESURRECT_DELAY then amount = MAX_RESURRECT_DELAY end self.Settings.RESURRECT_DELAY = amount if amount > 0 then return "DM_RESURRECT_SETDELAY_SUCCESS", {CEN:FormatSeconds(amount)} end return "DM_RESURRECT_SETDELAY_INSTANT" end