--------------------------------------

-- ϵͳ汾
SCRIPT_VERSION = "ϵͳű汾 $Rev: 212 $"

-- ģʽ
MODE_DEBUG = 1

-- ЧIDֵ
INVALID_ID = -1

-- NPCԻ
MAX_TALK_RANGE = 8

--Я()
PET_MAX_NUMBER = 6+4

-- ıȽϷʽ
CMP_FULL_MATCH = 1	-- ȫƥ
CMP_PART_MATCH = 2	-- ģƥ

-- 
CHAT_TYPE_TEAM = 1		--Ϣ
CHAT_TYPE_SCENE = 2		--Ϣ
CHAT_TYPE_TELL = 3		--˽Ϣ
CHAT_TYPE_SYSTEM = 4		--ϵͳϢ
CHAT_TYPE_CHANNEL = 5		--ԽƵϢ
CHAT_TYPE_GUILD = 6		--Ϣ
CHAT_TYPE_MENPAI = 7		--Ϣ
CHAT_TYPE_SELF = 8		--ͻʹõϢ


-- Զɵʱִв
BPM_ABNEGATE = 1		-- 
BPM_STOP = 2			-- ֹͣű
BPM_TIP	= 3			-- ʾû
BLOCK_PROCESS_MODE = BPM_ABNEGATE

-- ʰȡģʽ
PM_NOPICKUP = 0
PM_PICKUP = 1

-- ɫ
PLAYER_NAME = Player:GetData("NAME")

-- Ʒ
ITEM_OWNER = { 
	IO_MYSELF_EQUIP = 1,	-- Լϵװ
	IO_MYSELF_PACKET = 2	-- Լϵİ
}

-- Ʒ
ITEM_CLASS = {
	ICLASS_EQUIP = 1,
}

-- ѡֲԳ
CHA_RELATION_ENEMY = 0x00000001	-- ж
CHA_RELATION_FRIEND = 0x00000002	-- Ѻ
CHA_TYPE_NPC = 0x00000004	-- NPC
CHA_TYPE_PET = 0x00000008	-- 
CHA_TYPE_MOUNT = 0x00000010	-- 
CHA_TYPE_PLAYEROTHER = 0x00000020	-- 
CHA_OWNER_FREE = 0x00000040	-- ûӵ
CHA_OWNER_MYSELF = 0x00000080	-- ӵԼ
CHA_OWNER_OTHER = 0x00000100	-- ӵΪ
CHA_OWNER_ANY = CHA_OWNER_FREE|CHA_OWNER_MYSELF|CHA_OWNER_OTHER
CHA_OCCUPANT_FREE = 0x00000200	-- ûռ
CHA_OCCUPANT_MYSELF = 0x00000400	-- Լռ
CHA_OCCUPANT_TEAM = 0x00000800	-- Առ
CHA_OCCUPANT_OTHER = 0x00001000	-- ռ
CHA_OCCUPANT_ANY = CHA_OCCUPANT_FREE|CHA_OCCUPANT_MYSELF|CHA_OCCUPANT_TEAM|CHA_OCCUPANT_OTHER
CHA_STATE_DEAD = 0x00002000	-- 
CHA_STATE_ALIVE	= 0x00004000	-- Ϊ
CHA_TYPE_BAG = 0x00010000 --ϰ


LASTERROR_NOPATH = 1
LASTERROR_NOMONEY = 2
--------------------------------------------------------------------------------------------------

ENUM_CHARACTER_LOGIC = 
{
	CHARACTER_LOGIC_INVALID	= -1,	-- Ч

	CHARACTER_LOGIC_MOVE = 2,			-- ƶ
	CHARACTER_LOGIC_FLY = 3,			-- 
}

-- Ϣ
function DbgPrintf(text, ...)
	if MODE_DEBUG then

	 for i=1,arg.n do  
		if arg[i] == nil then
			System:OutputDebugString(string.format("## : %s [%d]", text, i))
			return
		end
	 end  

		System:OutputDebugString(string.format(text,unpack(arg)))
	end
end

function DebugMessage(format, ...)
	PushDebugMessage( string.format(format,unpack(arg)) )
end

function WriteLog(format, ...)
	if MODE_DEBUG then
		System:WriteLogFile(PLAYER_NAME, string.format(format,unpack(arg)))
	end
end

function ShowMessage(format, ...)

	for i=1,arg.n do  
		if arg[i] == nil then
			System:OutputDebugString(string.format("## arg[%d] = nil, %s", i, format))
			return
		end
	end

	local txt = string.format(format,unpack(arg))

	DebugMessage(txt)
	AddTalkMsg(txt, CHAT_TYPE_SELF)
	DbgPrintf(txt)
	WriteLog(txt)
end

function GetDistSq(x1, y1, x2, y2)
	if x1 == nil or x2 == nil or y1 == nil or y2 == nil then
		DbgPrintf("GetDistSq() !")
		return -1
	end
	local dist = (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)
	return dist
end

function GetDist(x1, y1, x2, y2)
	if x1 == nil or x2 == nil or y1 == nil or y2 == nil then
		DbgPrintf("GetDistSq() !")
		return -1
	end
	local dist = math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
	return dist
end

function GetAngle(x1, y1, x2, y2)
	
	if x1<x2 and y1>y2 then
		return math.atan(math.abs((y2-y1)/(x2-x1)))*180/math.pi
	elseif x1<x2 and y1<y2 then
		return 90 + math.atan(math.abs((y2-y1)/(x2-x1)))*180/math.pi
	elseif x1>x2 and y1<y2 then
		return 180 + math.atan(math.abs((y2-y1)/(x2-x1)))*180/math.pi
	elseif x1>x2 and y1>y2 then
		return 270 + math.atan(math.abs((y2-y1)/(x2-x1)))*180/math.pi
	elseif x1==x2 and y1>y2 then
		return 0
	elseif x1==x2 and y1<y2 then
		return 180
	elseif x1<x2 and y1==y2 then
		return 90
	elseif x1>x2 and y1==y2 then
		return 270
	end

	return 0
end

local g_MoveInfo = {nMoveCheckTime = 0, xOld = 0, yOld = 0, sceneOld = -1, nError = 0, bMove = false, nAngle = 0}
local g_MoveFault = {nFormX = 0, nFormY = 0, nFormScene = 0, nToX = 0, nToY = 0, nToScene = 0, nNum = 0}

function IsDestination(fX, fY, nScene, fSpace)

	local xNow, yNow = Player:GetPos()
	local currentSceneID = GetActiveDataSceneID()

	-- жǷ񵽴
	if nScene == currentSceneID or nScene == -1 then
		if fSpace >= GetDist(xNow, yNow, fX, fY) then
			return true
		end
	end

	return false
end


-- ƶĳأ󷵻
function MoveTo(fX, fY, nScene, strNPCName, fSpace, bMount, _callback , bMoneyRoad)
	local nSpace = 2
	if fSpace ~= nil and tonumber(fSpace) > 2 then
		nSpace = fSpace 
	end

	if IsDestination( fX , fY , nScene , nSpace ) == true then
		return
	end

	DbgPrintf("MoveTo %d,%d %d", fX, fY, nScene)

	AI:SetParameter("")

	AI:SetAI("ƶ")
	AI:SetParameter("ʼ")
	AI:SetParameter("ͼ", nScene )
	AI:SetParameter("", "" , fX , fY , nSpace)
	if bMoneyRoad ~= nil then
		AI:SetParameter("շͨ" , bMoneyRoad)
	else
		AI:SetParameter("շͨ" , false)
	end

	local nStartSceneID = GetActiveDataSceneID()
		
	AI:Start(true)
	while true do
		if IsDestination( fX , fY , nScene , nSpace ) == true then
			break
		end

		if GetMyLastError() == LASTERROR_NOPATH then
			break 
		end

		if _callback ~= nil then
			if _callback(fX, fY, nScene) == false then 
				break 
			end
		end

		if nScene == -1 and GetActiveDataSceneID() ~= nStartSceneID then 
			break 
		end

		System:Sleep(200)
	end
	AI:Stop()

	AI:SetParameter("ָ")
end                      

function OnMove(fX , fY , nScene )
	MoveTo( fX , fY , nScene , "" , 0 , 0 , 0 )
end

function MoveToNPC(fX, fY, nScene, strNPCName, bMount)

	local xNow, yNow = Player:GetPos()
	local currentSceneID = GetActiveDataSceneID()

	-- жǷ񵽴
	if nScene == currentSceneID or nScene == -1 then
		local range = GetDistSq(xNow, yNow, fX, fY)

		if range < MAX_TALK_RANGE then
			QuestFrameSpeak(INVALID_ID, strNPCName)
			return
		elseif strNPCName ~= "" then
			local idNpc, xNpc, yNpc = FindCharacterByName(strNPCName)
			if idNpc ~= INVALID_ID then
				if GetDist(xNow, yNow, xNpc, yNpc) < MAX_TALK_RANGE then
					QuestFrameSpeak(INVALID_ID, strNPCName)
					return
				end
			end
		end
	end

	MoveTo(fX, fY, nScene, strNPCName, 4 , bMount)
	QuestFrameSpeak(INVALID_ID, strNPCName)

	local dwTimeOut = System:GetTickCount() + 3000
	while System:GetTickCount() < dwTimeOut do
		if UI:IsWindowShow("Quest") then break end
		System:Sleep(100)
	end
end

-- ƶNPC
function MissionMoveToNPC(NPC)

	local szName, fX, fY, nScene = DataBase:GetMissionNPCInfo(NPC)

	if fX ~= 0 then
		DbgPrintf("Move to %d,%d %d %s", fX, fY, nScene, szName)
		MoveToNPC(fX, fY, nScene, szName)
	else
		if type(NPC) == "string" then
			DbgPrintf("1ûҵ[%s]", NPC)
		elseif type(NPC) == "number" then
			DbgPrintf("2ûҵ[%d]", NPC)
		end
	end
end

-- NPCԻѡƥ
function FindQuestFrameOption(strOpt, nMode)

	if nMode == nil or strOpt == nil then 
		return -1 
	end

	-- ж϶Ի򴰿Ƿ
	if UI:IsWindowShow("Quest") == false then return 0 end

	local nListCount = DataPool:GetNPCEventList_Num()

	if nListCount == 0 then return 0 end
	
	for i=0, nListCount - 1 do

		local strType,_,_,_,szText = DataPool:GetNPCEventList_Item(i)

		if strType == "id" then
			-- ƥģʽȽ
			if nMode == CMP_FULL_MATCH then
				if szText == strOpt then
					return true
				end
			elseif nMode == CMP_PART_MATCH then
				if string.find(szText, strOpt) ~= -1 then
					return true
				end
			end
		end
	end

	return false
end

-- ӳн
function CityToGuild()

	while true do
		if IsGuildCity() then break end

		local sceneNow = GetActiveDataSceneID()

		if sceneNow == 1 then
			MoveToNPC(322, 264, 1, "")
		elseif sceneNow == 2 then
			MoveToNPC(179, 121, 2, "")
		else
			MoveToNPC(237, 236, 0, "")
		end
		

		if FindQuestFrameOption("뱾", CMP_FULL_MATCH) == false then
			return false
		end

		QuestFrameOptionClicked("뱾", CMP_FULL_MATCH)
		System:Sleep(500)

	end

	return true
end

-- Ӱ᷵س
function GuildToCity(nCity)

	while true do
		if IsGuildCity() == false then break end

		MoveToNPC(99, 55, -1, "֣")
		QuestFrameOptionClicked("س", CMP_FULL_MATCH)

		if nCity == 1 then
			QuestFrameOptionClicked("ص", CMP_FULL_MATCH)
		elseif nCity == 2 then
			QuestFrameOptionClicked("ص", CMP_FULL_MATCH)
		else
			QuestFrameOptionClicked("ص", CMP_FULL_MATCH)
		end
		
		System:Sleep(500)
	end
end


-- ȡõڽɫnIndexΪǰеλ
function GetMissionRound(nIndex)

	local nRound = DataPool:GetPlayerMission_Display(nIndex,3)

	if( nRound >= 0 ) then

	    Mission_Variable = DataPool:GetPlayerMission_DataRound(nRound)

	    if(Mission_Variable >= 0) then
		return Mission_Variable
	    end

	end
	return -1
end

-- ָŮĽֵ
function InfantTreatBadStatus(SelInfantIndex)	

--[[
	if Infant:GetInfantHealthyValue(SelInfantIndex) < 10 then
		
		local guid_H, guid_L = Infant:GetInfantGUID(SelInfantIndex)

		if guid_H == -1 and guid_L == -1 then
			return
		end

		local str = ""
		str = str .. "Clear_XSCRIPT()\n"
		str = str .. "Set_XSCRIPT_Function_Name(\"InfantTreatBadStatus\")\n"
		str = str .. "Set_XSCRIPT_ScriptID(890600)\n"
		str = str .. string.format("Set_XSCRIPT_Parameter(0,%d)\n", guid_H)
		str = str .. string.format("Set_XSCRIPT_Parameter(1,%d)\n", guid_L)
		str = str .. "Set_XSCRIPT_ParamCount(2)\n"
		str = str .. "Send_XSCRIPT()"

		DoLuaString("Infant_Env", str)
		System:Sleep(1000)
	end
]]--

end

-- Զɵʱִв
function MissionBlockProcess(idScript)

	if BPM_ABNEGATE == BLOCK_PROCESS_MODE then

		QuestFrameMissionAbnegate(idScript)

	elseif BPM_STOPSCRIPT == BLOCK_PROCESS_MODE then

		

	elseif BPM_TIP == BLOCK_PROCESS_MODE then

		System:FlashWindow(true)

	end

end

-- Ѫ
function LuoYangRestore()
	
	while true do

		local nHP = Player:GetData("HP")
		local nMaxHP = Player:GetData("MAXHP")
		local nMP = Player:GetData("MP")
		local nMaxMP = Player:GetData("MAXMP")
		local nHPPercent = (nHP * 100) / nMaxHP
		local nMPPercent = (nMP * 100) / nMaxMP

		DbgPrintf("LuoYangRestore() %d(%d/%d) %d(%d/%d)", nHPPercent, nHP , nMaxHP , nMPPercent , nMP , nMaxMP)

		if (nHPPercent > 80 and nMPPercent > 80) then return end
		
		MoveToNPC(185, 336, 0, "")
		QuestFrameOptionClicked("ŭ", CMP_FULL_MATCH)
		QuestFrameOptionClicked("", CMP_FULL_MATCH)

		QuestFrameSpeak(0, "")
		QuestFrameOptionClicked("޻ָѪ", CMP_FULL_MATCH)
		QuestFrameOptionClicked("", CMP_FULL_MATCH)

		System:Sleep(200)
	end
end

-- ȡõǰս
function Pet_GetFighting()

	local nFightPet = -1
	local nPetCount = Pet:GetPet_Count()

	if nPetCount > 0 then
		for i=1, PET_MAX_NUMBER do
			if Pet:IsPresent(i-1) then
				if(Pet:GetIsFighting(i-1)) then
					nFightPet = i-1;
				end
			end
		end
	end
	return nFightPet
end


-- ָƵĳ
function Pet_GetPetByName(szName)

	for i=1, PET_MAX_NUMBER do
		if Pet:IsPresent(i-1) then
			if (szName == Pet:GetName(i-1)) then
				return (i-1)
			end
		end
	end

	return -1
end

-- ջصǰս
function Pet_Relax()

	local index = Pet_GetFighting()

	if index ~= -1 then
		Pet:Go_Relax(index)
	end
end

-- ϰť
function Relive_Out_Ghost()
	DoLuaString("Relive_Env", "Relive_Out_Ghost()")
end

-- ť
function Relive_Relive()
	DoLuaString("Relive_Env", "Relive_Relive()")
end

-- Լ״̬
function Player_GetBuff(szBuffName)

	local nBuffCount = Player:GetBuffNumber()

	for i = 1, nBuffCount do
		local szBuffToolTips = Player:GetBuffToolTipsByIndex(i-1)

		if string.find(szBuffToolTips, szBuffName) then
			return (i-1)
		end
	end
	return -1
end

-- indexȡ״̬
function Player_DispelBuffByIndex(nIndex)
	if nIndex == -1 or nIndex > Player:GetBuffNumber() then return end
	DoLuaString("", string.format("Player:DispelBuffByIndex(%d)", nIndex))
end

--ȡҵǰȼЯ(ԺҪϳ,µķ)-add by xindefeng
function GetMyCurMaxPetCount()
	local mylevel = Player:GetData("LEVEL") --ȡҵȼ
	if mylevel == nil or type(mylevel) ~= "number" then
		return 2;
	end
	local MaxCount = 0	--Я

	if mylevel < 21 then
		MaxCount = 2	--һʼЯ޾2
	elseif mylevel < 41 then
		MaxCount = 3
	elseif mylevel < 61 then
		MaxCount = 4
	elseif mylevel < 81 then
		MaxCount = 5
	else
		MaxCount = 6
	end
	MaxCount = MaxCount + Player:GetData("PET_EXTRANUM")

	if MaxCount > PET_MAX_NUMBER then
		MaxCount = PET_MAX_NUMBER
	end

	return MaxCount
end

function GetMapInfomationLink(szText)
	local _,_, szMapName , tX , tY , tMapId = string.find(szText ,"#.(.-)#.+_INFOAIM(%d+),(%d+),(%d+)")
	return szMapName , tonumber(tX) , tonumber(tY) , tonumber(tMapId)
end

-- ȡԼڶеIndex
function GetTeamMemberIndex(strName)
	local count = DataPool:GetTeamMemCount()
	if count > 0 then
		for i = 0, count - 1 do
			local szNick = DataPool:GetTeamMemInfo(i)
			if szNick == strName then
				return i
			end
		end
	end
	return -1
end

function OnPickup()
	AI:SetParameter("")
	AI:SetAI("ɱ")
	AI:SetParameter("ʼ")
	AI:SetParameter("ʰȡ" , 1 )
	AI:SetParameter("ͼ" , -1)
	local xNow, yNow = Player:GetPos()
	AI:SetParameter("" , "" , xNow , yNow , 20 )
	AI:Start(true)
		
	AI:SetParameter("в" , "ɱ" , 0 )
	AI:SetParameter("в" , "ֹͣ" , 1 )

	while true do 

		System:Sleep(1000)

		if LockNearestTarget( "" , CHA_TYPE_BAG ) == -1 then
			break 
		end

	end
	
	AI:Stop()
	AI:SetParameter("ָ")
end


-- ӡϵͳű汾
-- ShowMessage(SCRIPT_VERSION)