view Degaine.lua @ 47:f861e1c0535b v1.0beta11

Take into account that sheathing while drawing doesn't actually sheath
author contrebasse
date Sun, 27 Feb 2011 21:24:10 +0100
parents 1967c9a3c5c2
children 94566cb4534f
line wrap: on
line source
local AddonName, T = ...
-- Draw your weapons automagically


---------------------------------------------------------------
-- Known bugs
---------------------------------------------------------------
-- If you stand up by jumping or walking it won't draw your weapon
--     (it's not possible to know if you were sitting or standing before)

--@debug@
local debug = false
--@end-debug@


---------------------------------------------------------------
-- Globals to local
---------------------------------------------------------------
-- These need to be globals :
-- GLOBALS: Degaine_ToggleAuto, Degaine_isAuto, BINDING_HEADER_DEGAINE

-- It doesn't matter if they are globals, rarely unsed :
-- GLOBALS: DEFAULT_CHAT_FRAME

-- Lua functions
local pairs = pairs;
local type = type;
local select = select

-- Wow functions
local GetTime = GetTime
local InCombatLockdown = InCombatLockdown
local ToggleSheath = ToggleSheath
local UnitName = UnitName
local IsMounted = IsMounted
local UnitCastingInfo = UnitCastingInfo
local GetUnitSpeed = GetUnitSpeed


---------------------------------------------------------------
-- Local vars
---------------------------------------------------------------
-- const
local DegaineFrame = CreateFrame("Frame")
local playername = UnitName("player")
local delay = 2.5 -- seconds
local delay_short = 0.5 -- seconds

-- vars
local t_left = -1
local isGossipClosed = true
local wasGossipOpened = false
local t_lastGossipClosed = 0
--local wasMounted = IsMounted() -- handle mounts with UNIT_AURA
local isTradeSkill = false
local t_lastDegaine = 0 -- Time of the last draw


---------------------------------------------------------------
-- Some stuff...
---------------------------------------------------------------
-- Bindings
BINDING_HEADER_DEGAINE = "Dégainer automatiquement"

-- Print status
local printState = function()
	DEFAULT_CHAT_FRAME:AddMessage(Degaine_isAuto and "Dégainage automatique |cFF00FF00activé|r" or "Dégainage automatique |cFFFF0000désactivé|r")
end


---------------------------------------------------------------
-- Launch drawing weapons
---------------------------------------------------------------
-- Wait a few seconds before drawing, to be able to see the curren animation (and avoid bugs)
local Degaine_OnUpdate = function(self,t_elapsed)
	t_left = t_left - t_elapsed;
	if t_left<=0 then
		ToggleSheath()
		DegaineFrame:SetScript("OnUpdate", nil)
		t_lastDegaine = GetTime()
	end
end
local start = function(arg_delay)

	--@debug@
	--DEFAULT_CHAT_FRAME:AddMessage("Go !")
	--@end-debug@

	if Degaine_isAuto and (GetTime()-t_lastDegaine)>1 and not InCombatLockdown() then
		t_left = arg_delay or delay
		DegaineFrame:SetScript("OnUpdate", Degaine_OnUpdate)
	end
end


---------------------------------------------------------------
-- Events config
---------------------------------------------------------------
-- Events to watch
local events = { -- no args to watch
	GOSSIP_SHOW = function()
		-- isGossipClosed :
		-- if the gossip is already opened, no need to draw weapon
		-- UnitName("npc")==UnitName("target") :
		-- hack gossips again because there's no emote with non npc
		-- you have to target the npc to interact with it
		-- things such as boards can't be targeted and start no emote
		local returnvalue = isGossipClosed and UnitName("npc")==UnitName("target")
		isGossipClosed = false
		return returnvalue
	end,
	MERCHANT_SHOW = function()
		-- hack for the cases where the merchant's frame is opened from a gossip frame :
		--  the gossip is closed and the merchant opened but the weapon is not stealthed
		if (GetTime() - t_lastGossipClosed) < 0.5 then
			return not wasGossipOpened
		else
			return isGossipClosed
		end
	end,
	QUEST_PROGRESS = true,
	BANKFRAME_OPENED = true, --function() return GossipFrame:IsShown() end,
	AUCTION_HOUSE_SHOW = true,
}
local events1player = { -- the first arg is "player"
	UNIT_SPELLCAST_FAILED = true,
	UNIT_SPELLCAST_INTERRUPTED = true,
	UNIT_SPELLCAST_SUCCEEDED = true,
	UNIT_SPELLCAST_START = true, -- to ckeck tradeskill
}

--[[
-- Was used when moving prevented to play the emote when talking
-- Was needed for CHAT_MSG_SAY and CHAT_MSG_YELL
local function playerIsNotMoving()
	return GetUnitSpeed("player") == 0
end
--]]
local events2playername = { -- the 2nd arg is playername
	CHAT_MSG_SAY = true,
	CHAT_MSG_YELL = true,
	CHAT_MSG_TEXT_EMOTE = true, -- the emote is not shown, but the weapon is stealthed
}


---------------------------------------------------------------
-- Handle mounts with OnUpdate
---------------------------------------------------------------
-- works with GupPet but not with the default interface...
-- I guess that's because a specific /cancelaura or alike is done
-- hooksecurefunc("Dismount",start);

-- With OnUpdate
local handleMountsFrame = CreateFrame("frame")
local handleMountsOnUpdate
do
	local IsMounted = IsMounted
	local wasMounted = IsMounted()
	function handleMountsOnUpdate(self,t_elapsed)
		if IsMounted() then
			wasMounted = true
		else
			if wasMounted then
				start(delay_short) -- no animation for unmounting
				wasMounted = false
			end
		end
	end
end


---------------------------------------------------------------
-- Activation functions
---------------------------------------------------------------
local activate = function()
	if (not Degaine_isAuto) or InCombatLockdown() then return end

	--DegaineFrame:SetScript("OnUpdate", Degaine_OnUpdate);
	--@debug@
	if debug then
		DegaineFrame:RegisterAllEvents()
	else
	--@end-debug@
		for k,_ in pairs(events) do DegaineFrame:RegisterEvent(k) end
		for k,_ in pairs(events1player) do DegaineFrame:RegisterEvent(k) end
		for k,_ in pairs(events2playername) do DegaineFrame:RegisterEvent(k) end
		--DegaineFrame:RegisterEvent("UNIT_AURA")
		handleMountsFrame:SetScript("OnUpdate",handleMountsOnUpdate)
	--@debug@
	end
	--@end-debug@
end
local desactivate = function()
	DegaineFrame:SetScript("OnUpdate", nil)
	t_left = -1
	isTradeSkill = false
	for k,_ in pairs(events) do DegaineFrame:UnregisterEvent(k) end
	for k,_ in pairs(events1player) do DegaineFrame:UnregisterEvent(k) end
	for k,_ in pairs(events2playername) do DegaineFrame:UnregisterEvent(k) end
	--DegaineFrame:UnregisterEvent("UNIT_AURA")
	handleMountsFrame:SetScript("OnUpdate",nil)
end
Degaine_ToggleAuto = function()
	if Degaine_isAuto then
		Degaine_isAuto = false
		desactivate()
	else
		Degaine_isAuto = true
		activate()
	end
	printState()
end



---------------------------------------------------------------
-- Event/hooks functions
---------------------------------------------------------------
local Degaine_OnEvent = function(self,event, arg1, arg2, _, _, arg5, ...)
	--@debug@
	if debug then
		DEFAULT_CHAT_FRAME:AddMessage(event)
		if arg1 then DEFAULT_CHAT_FRAME:AddMessage("arg1 = "..arg1) end
		if arg2 then DEFAULT_CHAT_FRAME:AddMessage("arg2 = "..arg2) end
	end
	--@end-debug@

	--[[ IsMounted() renvoie toujours false ici, on doit passer par OnUpdate
	if event=="UNIT_AURA" then
		if arg1=="player" then
			DEFAULT_CHAT_FRAME:AddMessage("player")
			if IsMounted() then
				DEFAULT_CHAT_FRAME:AddMessage("ismounted")
				wasMounted = true
			else
				DEFAULT_CHAT_FRAME:AddMessage("notmounted")
				if wasMounted then
					DEFAULT_CHAT_FRAME:AddMessage("wasmounted : start")
					wasMounted = false
					start()
				end
			end
		end
	else
	--]]
	if events[event] then
		if type(events[event])~="function" or events[event]() then
			start()
		end
	elseif events1player[event] then
		if arg1=="player" then
			if event == "UNIT_SPELLCAST_START" then
				--name, nameSubtext, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo("unit")
				isTradeSkill = select(7,UnitCastingInfo("player"))
				--DEFAULT_CHAT_FRAME:AddMessage(name)
				--DEFAULT_CHAT_FRAME:AddMessage(isTradeSkill and "True" or "False")
				--if isTradeSkill then

				--end
			--elseif arg5 and not T.SpellBlackList[arg5] then -- arg5 is SpellID
			elseif (arg5 and T.SpellWhiteList[arg5]) or isTradeSkill then -- arg5 is SpellID
				isTradeSkill = false -- for next time
				start(type(T.SpellWhiteList[arg5])=="number" and T.SpellWhiteList[arg5] or delay_short)
			end
		end
	elseif events2playername[event] then
		if arg2==playername and (type(events2playername[event])~="function" or events2playername[event]()) then
			start()
		end
	elseif event == "GOSSIP_CLOSED" then
		wasGossipOpened = not isGossipClosed
		isGossipClosed = true
		t_lastGossipClosed = GetTime()

	elseif event == "PLAYER_REGEN_ENABLED" then
		for k,_ in pairs(events1player) do DegaineFrame:UnregisterEvent(k) end
		--desactivate()
	elseif event == "PLAYER_REGEN_DISABLED" then
		for k,_ in pairs(events1player) do DegaineFrame:RegisterEvent(k) end
		--activate()

	elseif event == "ADDON_LOADED" and arg1==AddonName then
		if Degaine_isAuto==nil then
			Degaine_isAuto = true
		end
		if Degaine_isAuto then activate() else desactivate() end
		printState()

		-- Not needed anymore
		DegaineFrame:UnregisterEvent("ADDON_LOADED")

	elseif event == "PLAYER_LOGIN" then
		-- BLacklis alomst all Companions and mounts
		T.DoBlackListCrittersAndMount()
	end
end

-- Hook when standing up
-- (Didn't work, see http://forums.wowace.com/showthread.php?p=310547#post310547)
hooksecurefunc("SitStandOrDescendStart",start);


---------------------------------------------------------------
-- Commands
---------------------------------------------------------------
-- Bindings
BINDING_HEADER_DEGAINE = "Dégainer automatiquement"

-- Slash command
-- GLOBALS: SLASH_DEGAINE1
SLASH_DEGAINE1 = "/degaine"
SlashCmdList["DEGAINE"] = Degaine_ToggleAuto


---------------------------------------------------------------
-- Initialization
---------------------------------------------------------------
DegaineFrame:SetScript("OnEvent",Degaine_OnEvent)

-- Global events
DegaineFrame:RegisterEvent("GOSSIP_CLOSED")
DegaineFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
DegaineFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
DegaineFrame:RegisterEvent("ADDON_LOADED")
DegaineFrame:RegisterEvent("PLAYER_LOGIN")
activate()