Just went to Gurubashi Arena and ZONE_CHANGED triggers when you enter or leave the circular center area (the arena). In some points if you are very close to the edge you can cross the zone without going to the ground level but I don't think that is relevant.
UNIT_FACTION also triggers but when you leave the center area you still keep the FFA status for a while. Maybe you can use UnitIsPVPFreeForAll("player") when UNIT_FACTION triggers (arg1 being "player"), to check if you are or not in a FFA combat. That would avoid you to use ZONE_CHANGED.
I still prefer my solution (for world pvp) because BATTLEFIELD_MGR_* triggers only rarely and most of times will be relevant for your problem. For battlegrounds and arenas all you need to do is call IsInInstance() when PLAYER_ENTERING_WORLD triggers (I know you are already doing that). So apparently is totally possible to avoid using ZONE_CHANGED and ZONE_CHANGED_NEW_AREA.
Here my complete solution attempt:
Lua Code:
local Ashran_instance_id = 1191
local Ashran_battle_id = 24
local f = CreateFrame("Frame")
f:SetScript("OnEvent",function(self,event,...)
local pvp_old = f.pvp
if event=="PLAYER_ENTERING_WORLD" then
local _,instance_type = IsInInstance()
if instance_type=="pvp" or instance_type=="arena" then
f.instance = true
else
f.instance = false
local _,_,_,_,_,_,_,instance_id = GetInstanceInfo()
if instance_id==Ashran_instance_id or IsInActiveWorldPVP() then
f.world = true
else
f.world = false
end
end
elseif event=="BATTLEFIELD_MGR_ENTERED" then
f.world = true
elseif event=="BATTLEFIELD_MGR_EJECTED" then
f.world = false
elseif event=="BATTLEFIELD_MGR_STATE_CHANGE" then
if ...~=Ashran_battle_id and IsInActiveWorldPVP()==false then
f.world = false
end
elseif event=="UNIT_FACTION" and ...=="player" then
if UnitIsPVPFreeForAll("player")==true then
f.ffa = true
else
f.ffa = false
end
end
f.pvp = f.instance or f.world or f.ffa or false
if f.pvp~=pvp_old then
print("pvp area:",f.pvp)
end
end)
f:RegisterEvent("PLAYER_ENTERING_WORLD")
f:RegisterEvent("BATTLEFIELD_MGR_ENTERED")
f:RegisterEvent("BATTLEFIELD_MGR_EJECTED")
f:RegisterEvent("BATTLEFIELD_MGR_STATE_CHANGE")
f:RegisterEvent("UNIT_FACTION")