local DEFAULT_OPTIONS = {}; DEFAULT_OPTIONS[ACESWIFTSHIFT_SPAMDELAY] = 5; DEFAULT_OPTIONS[ACESWIFTSHIFT_BAGDELAY] = 2; DEFAULT_OPTIONS[ACESWIFTSHIFT_AUTOMOUNT] = TRUE; --[[-------------------------------------------------------------------------------- Class Setup -----------------------------------------------------------------------------------]] AceSwiftShift = AceAddon:new({ name = AceSwiftShiftLocals.Title, description = AceSwiftShiftLocals.Desc, -- Optional; Ace will use the .toc Notes text version = AceSwiftShiftLocals.Version, releaseDate = "", aceCompatible = "102", -- Check ACE_COMP_VERSION in Ace.lua for current. author = "Thirsterhall/facboy", email = "", website = "http://", category = "Class", --optionsFrame = "AddonNameOptionsFrame", db = AceDatabase:new("AceSwiftShiftDB"), defaults = DEFAULT_OPTIONS, cmd = AceChatCmd:new(AceSwiftShiftLocals.ChatCmd, AceSwiftShiftLocals.ChatOptions) }) function AceSwiftShift:Initialize() -- Helpful closures for accessing the addon's currently loaded profile. self.Msg = function(...) self.cmd:result(format(unpack(arg))) end self.Get = function(var) return self.db:get(self.profilePath, var) end self.Set = function(var, val) return self.db:set(self.profilePath, var, val) end self.Tog = function(var) return self.db:toggle(self.profilePath,var) end end --[[-------------------------------------------------------------------------------- Addon Enabling/Disabling -----------------------------------------------------------------------------------]] function AceSwiftShift:Enable() if not self.Get(ACESWIFTSHIFT_BAGDELAY) then self.Set(ACESWIFTSHIFT_BAGDELAY, 2) end self.Forms = {}; self.FormCount = 0; self:LoadForms(); self.lastShift = GetTime(); self.setTimer = FALSE; self.lastForm = ""; self:RegisterEvent("BAG_UPDATE", "UpdateBag"); self:RegisterEvent("TAXIMAP_OPENED", "Shift"); self:RegisterEvent("UI_ERROR_MESSAGE", "AutoShift"); self:RegisterEvent("LEARNED_SPELL_IN_TAB", "LoadForms"); end -- Disable() is not needed if all you are doing in Enable() is registering events -- and hooking functions. Ace will automatically unregister and unhook these. function AceSwiftShift:Disable() end -- use to find shift successful --CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS --use to determin if shift didn't work --SPELL_CAST_FAILED --[[-------------------------------------------------------------------------------- Main Processing -----------------------------------------------------------------------------------]] function AceSwiftShift:LoadForms() local i; local n = GetNumShapeshiftForms(); if (self.Forms[AceSwiftShiftLocals.BearForm] or n ~= self.FormCount) then local bear = false; local moonkin = false; for i=1,n do local _, name = GetShapeshiftFormInfo(i); if (name == AceSwiftShiftLocals.BearForm) then bear = true; end if (name == AceSwiftShiftLocals.MoonkinForm) then moonkin = true; end self.Forms[name] = i; end self.FormCount = n; if (not bear) then self.Forms[AceSwiftShiftLocals.BearForm] = nil; end if (not moonkin) then self.Forms[AceSwiftShiftLocals.MoonkinForm] = nil; end -- this is an initial load if (not arg1) then if self.Forms[AceSwiftShiftLocals.DireBearForm] then AceSwiftShiftLocals.BearForm = AceSwiftShiftLocals.DireBearForm; self.Msg("AceShapeshift forms loaded: %s (Dire Bear detected)", n); else self.Msg("AceShapeshift forms loaded: %s", n); end end end end function AceSwiftShift:FindMountBuff() local i = 0 local currBuffTex; while (1) do local bi, _ = GetPlayerBuff(i, "HELPFUL") if bi < 0 then break end currBuffTex = GetPlayerBuffTexture(bi) for j = 1, table.getn(AceSwiftShiftLocals.MountTexturs) do if (string.find(currBuffTex,AceSwiftShiftLocals.MountTexturs[j])) then return bi end end i = i+1 end return FALSE end function AceSwiftShift:SetMountItem() for b = 0, 4, 1 do for s = 1, GetContainerNumSlots(b), 1 do local txture = GetContainerItemInfo(b, s) if txture then for i = 1, table.getn(AceSwiftShiftLocals.MountTexturs) do if (string.find(txture,AceSwiftShiftLocals.MountTexturs[i])) then self.Forms['Mount'] = { bag = b, slot=s} return end end end end end end function AceSwiftShift:CurrentForm() local cf = AceSwiftShiftLocals.HumanoidForm; for i=1,GetNumShapeshiftForms() do local _, name, isActive = GetShapeshiftFormInfo(i); if isActive == 1 then cf = name; end end if cf == AceSwiftShiftLocals.HumanoidForm and self.Get(ACESWIFTSHIFT_AUTOMOUNT) then if self:FindMountBuff() then cf = AceSwiftShiftLocals.Mount; end end return cf; end function AceSwiftShift:Shift(f) if not f then f = AceSwiftShiftLocals.HumanoidForm; end local cf = self:CurrentForm(); -- if we want human form and already human then end if f == AceSwiftShiftLocals.HumanoidForm and f == cf then return; end if not self.Forms[f] then if f == AceSwiftShiftLocals.TravelForm and not (self.Forms[AceSwiftShiftLocals.TravelForm] or self.Forms[AceSwiftShiftLocals.AquaticForm] or self.Forms[AceSwiftShiftLocals.Mount]) then self.Msg("You don't have any %ss, looks like you are going to be running.", f); return; end end -- argument massaging if f == AceSwiftShiftLocals.TravelForm then if self.Forms[AceSwiftShiftLocals.Mount] and self.Get(ACESWIFTSHIFT_AUTOMOUNT) and not UnitAffectingCombat("player") then f = AceSwiftShiftLocals.Mount; elseif self.Forms[AceSwiftShiftLocals.AquaticForm] then f = AceSwiftShiftLocals.AquaticForm; end end -- self.Msg("F is: %s", f); -- self.Msg("CF is: %s", cf); -- self.Msg("LastForm is: %s", self.lastForm); if cf == self.lastForm then local timePassed = GetTime() - self.lastShift; if timePassed < self.Get(ACESWIFTSHIFT_SPAMDELAY) then self.Msg("Spam Delay %.1f sec left", self.Get(ACESWIFTSHIFT_SPAMDELAY) - timePassed); return false; end end self.lastForm = f; --self.Msg("Escaped spam delay, how?"); self:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS", "ShiftSuccess"); -- want a form and in human form now if self.Forms[f] and not self.Forms[cf] then if f == AceSwiftShiftLocals.Mount then self:RegisterEvent("UI_ERROR_MESSAGE", "ShiftError"); UseContainerItem(self.Forms[f].bag, self.Forms[f].slot); else if f == AceSwiftShiftLocals.AquaticForm then self:RegisterEvent("UI_ERROR_MESSAGE", "ShiftError"); end CastShapeshiftForm(self.Forms[f]); end self.setTimer = TRUE else -- either I'm not in human form or a want to go to a form I don't have -- I'm in an animal form so switch back to humanoid form if self.Forms[cf] then if f == cf then self.setTimer = TRUE; else self.setTimer = FALSE; end if cf == AceSwiftShiftLocals.Mount then CancelPlayerBuff(self:FindMountBuff()); else CastShapeshiftForm(self.Forms[cf]); end else if f ~= AceSwiftShiftLocals.HumanoidForm then --I asked for a form I don't have self.Msg("You don't have %s", f); end end end end function AceSwiftShift:ShiftSuccess() local form = strfind(arg1, "You gain ([^.]+) Form."); if (form) then self:UnregisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"); self:RegisterEvent("UI_ERROR_MESSAGE", "AutoShift"); if self.setTimer then self.lastShift = GetTime(); else self.lastShift = self.lastShift - self.Get(ACESWIFTSHIFT_SPAMDELAY); end self.setTimer = FALSE; end end function AceSwiftShift:AutoShift() if self:CurrentForm() ~= AceSwiftShiftLocals.HumanoidForm then -- tried to talk in animal form if arg1 == ERR_CANT_INTERACT_SHAPESHIFTED or arg1 == ERR_MOUNT_SHAPESHIFTED or arg1 == ERR_NOT_WHILE_SHAPESHIFTED or arg1 == ERR_NO_ITEMS_WHILE_SHAPESHIFTED or arg1 == SPELL_NOT_SHAPESHIFTED or arg1 == SPELL_NOT_SHAPESHIFTED_NOSPACE or arg1 == SPELL_FAILED_NOT_SHAPESHIFT or arg1 == ERR_EMBLEMERROR_NOTABARDGEOSET or ((arg1 == ERR_OUT_OF_RAGE or arg1 == 'Must be in Bear Form, Dire Bear Form') and self:CurrentForm() ~= AceSwiftShiftLocals.BearForm) or ((arg1 == ERR_OUT_OF_ENERGY or arg1 == 'Must be in Cat Form') and self:CurrentForm() ~= AceSwiftShiftLocals.CatForm) then self:Shift(AceSwiftShiftLocals.HumanoidForm); end elseif self:CurrentForm() ~= AceSwiftShiftLocals.BearForm or self:CurrentForm() ~= AceSwiftShiftLocals.CatForm then --tried to use a bear skill if arg1 == ERR_OUT_OF_RAGE or arg1 == 'Must be in Bear Form, Dire Bear Form' then self:Shift(AceSwiftShiftLocals.BearForm); elseif arg1 == ERR_OUT_OF_ENERGY or arg1 == 'Must be in Cat Form' then self:Shift(AceSwiftShiftLocals.CatForm); end end end function AceSwiftShift:ShiftError() self:RegisterEvent("UI_ERROR_MESSAGE", "AutoShift") -- tried to mount while moving if arg1 == SPELL_FAILED_MOVING or arg1 == ERR_NOT_IN_COMBAT or arg1 == ERR_CLIENT_LOCKED_OUT then if self.Forms[AceSwiftShiftLocals.TravelForm] then self.setTimer = TRUE; CastShapeshiftForm(self.Forms[AceSwiftShiftLocals.TravelForm]); return; end -- tried to mount while swimming elseif arg1 == SPELL_FAILED_ONLY_ABOVEWATER then if self.Forms[AceSwiftShiftLocals.AquaticForm] then self.setTimer = TRUE; CastShapeshiftForm(self.Forms[AceSwiftShiftLocals.AquaticForm]); return; end -- tried goto aquatic form while on dry land elseif arg1 == SPELL_FAILED_ONLY_UNDERWATER then if self.Forms[AceSwiftShiftLocals.TravelForm] then self.setTimer = TRUE; CastShapeshiftForm(self.Forms[AceSwiftShiftLocals.TravelForm]); return; end end self:UnregisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"); end function AceSwiftShift:UpdateBag() if Timex:NamedScheduleCheck("AceSwiftShiftBagUpdate") then return end Timex:AddNamedSchedule("AceSwiftShiftBagUpdate", self.Get(ACESWIFTSHIFT_BAGDELAY), nil, nil,AceSwiftShift["SetMountItem"], AceSwiftShift); end --[[-------------------------------------------------------------------------------- Command Handlers -----------------------------------------------------------------------------------]] function AceSwiftShift:SetSpamDelay(i) i = tonumber(i) self.Set(ACESWIFTSHIFT_SPAMDELAY, i) self.Msg("Spam cutoff set to %s sec", i) end function AceSwiftShift:SetAutoMount() if (self.Get(ACESWIFTSHIFT_AUTOMOUNT)) then self.Set(ACESWIFTSHIFT_AUTOMOUNT, FALSE); self.Msg("Auto-mount off."); else self.Set(ACESWIFTSHIFT_AUTOMOUNT, TRUE); self.Msg("Auto-mount on."); end end --[[-------------------------------------------------------------------------------- Register the Addon -----------------------------------------------------------------------------------]] AceSwiftShift:RegisterForLoad()