--SỬ DỤNG:
-- 1. quest id: 3 	--Q3

require "questui/vl_quest_introwindow_ui"
require "questui/vl_quest_popup_ui"

local GetPlayerGlobalModDataQ3 = VLGMD.GetPlayerGlobalModDataQ3
local GetPlayerGlobalModData = VLGMD.GetPlayerGlobalModData
local ActiveQuestIntro_Free = VLF.ActiveQuestIntro_Free
local SetNPCStateInQueueSpawnList = VLZB.SetNPCStateInQueueSpawnList
local IsPlayerInArea = VLPL.IsPlayerInArea
local QuestUpdatedPopIn = VLF.QuestUpdatedPopIn
local GetQuestGlobalModData = VLGMD.GetQuestGlobalModData
local SpawnNPCOnClient = VLZB.SpawnNPCOnClient
local SetPlayerGMD_Q3 = VLGMD.SetPlayerGMD_Q3
local SetPlayerGMD_Data = VLGMD.SetPlayerGMD_Data
local RemoveZombie = VLZB.RemoveZombie
local GetDoorOrWindowOfRoom = VLF.GetDoorOrWindowOfRoom
local BarricadeOnObject = VLF.BarricadeOnObject
local GetZombieByOnlineIDOrUID = VLZB.GetZombieByOnlineIDOrUID
local ResetData_EndQ3 = VLF.ResetData_EndQ3
local SetNPCDead = VLF.SetNPCDead
local RemoveNPCQuest = VLZB.RemoveNPCQuest
local IsQuest3Completing = VLF.IsQuest3Completing
local UpdateQuestStepAndNext = VLF.UpdateQuestStepAndNext
local AddObjectToSquare = VLF.AddObjectToSquare
local RemoveItemFromContainer = VLIT.RemoveItemFromContainer

local thisSession = {}

local pTick = 1
local pTick2 = 1
local delay = 20


local function GetCorpsesOnSquare(square)
	local list = {}
    local objs = square:getStaticMovingObjects()
    for i = 0, objs:size()-1 do
        local obj = objs:get(i)
        if obj and instanceof(obj, "IsoDeadBody") then
			table.insert(list, obj)
        end
    end
    return list
end

local function RemoveCorpsesInArea(x, y, x2, y2, z)
	for i = x, x2 do
		for j = y, y2 do
			local square = getCell():getGridSquare(i, j, z)
			if square then
				local corpses = GetCorpsesOnSquare(square)
				if #corpses > 0 then
					for k = 1, #corpses do
						VLZB.RemoveZombie(corpses[k])
					end
				end
			end
		end
	end
end

local function BarricadeRoom_q3s001(x, y, z)	--tọa độ để lấy room
	local square = getCell():getGridSquare(x, y, z)
	if square then
		local room = square:getRoom()
		if room then
			--Nếu có door thì đóng lại và barricade
			local doorTab, sideTab = GetDoorOrWindowOfRoom(room, "door")
			for i, door in ipairs(doorTab) do	
				BarricadeOnObject({x = door:getSquare():getX(), y = door:getSquare():getY(), z = door:getSquare():getZ(), objFlag = "door", side = sideTab[i], barItem = "Base.Plank"})
			end
			--Nếu có window thì đóng lại và barricade
			local windowTab, sideTab = GetDoorOrWindowOfRoom(room, "window")
			for i, window in ipairs(windowTab) do
				--barricade
				BarricadeOnObject({x = window:getSquare():getX(), y = window:getSquare():getY(), z = window:getSquare():getZ(), objFlag = "window", side = sideTab[i], barItem = "Base.Plank"})
			end
		end
	end
end

local function RemoveAllNPCsSpawningQ3()
	local questMD = GetQuestGlobalModData(nil)
	for _qStep, _ in pairs(questMD.NPCsQueueToSpawn) do
		if string.find(_qStep, "q3s") then
			if questMD.NPC[_qStep] and questMD.NPC[_qStep]["spawned"] == true then
				local zID = questMD.NPC[_qStep]["zID"]
				local zNPC = GetZombieByOnlineIDOrUID(zID)
				if zNPC then
					RemoveNPCQuest(zNPC)
				end
			end
			
			--Xóa queue bất kể đang spawn hay không
			SetNPCStateInQueueSpawnList({qStep = _qStep, active = nil})
		end
	end
end

local function CloseDoor(x, y, z)
	local square = getCell():getGridSquare(x, y, z)
	if square then
		local door = square:getIsoDoor()
		if door and door:IsOpen() then
			door:ToggleDoorSilent()
		end
	end
end

local function AddDoor(x, y, z, isNorth)
	isNorth = isNorth or false
	local square = getCell():getGridSquare(x, y, z)
	if square then
		local door = square:getIsoDoor()
		if not door then
			local doorSprite
			if isNorth == true then
				doorSprite = "fixtures_doors_fences_01_13"
			else
				doorSprite = "fixtures_doors_fences_01_12"
			end
			AddObjectToSquare(square, doorSprite, {isTransmit = false, x = -1, y = -1, z = 0, objType = "IsoDoor", isNorth = isNorth})
		end
	end
end

local function AddObj(x, y, z, sprite)

	local square = getCell():getGridSquare(x, y, z)
	if square then
		local obj = square:getIsoDoor()
		if not door then
			local doorSprite
			if isNorth == true then
				doorSprite = "fixtures_doors_fences_01_13"
			else
				doorSprite = "fixtures_doors_fences_01_12"
			end
			AddObjectToSquare(square, doorSprite, {isTransmit = false, x = -1, y = -1, z = 0, objType = "IsoDoor", isNorth = isNorth})
		end
	end
end

local function RemoveAllFoodOnSquare(x, y, z)
	local square = getCell():getGridSquare(x, y, z)
	if square then
		local objs = square:getObjects()
		if objs:size() > 0  then
			for i = 0, objs:size() - 1 do
				local obj = objs:get(i)
				if obj then
					local container = obj:getContainer()
					if container then						
						local foodList = {}
						VLIT.GetFoodInContainer(container, foodList)
						if #foodList > 0 then
							for i = #foodList, 1, -1 do
								VLIT.RemoveItemFromContainer(container, foodList[i], nil, 1)
								--print("-----------Remove foodList: ", foodList[i])
							end
						end
					end
				end
			end
		end
	end
end

--MAIN FUNC --Chạy các qStep đang active
local function OnPlayerUpdate_Q3(player)
    if not player or player:isDead() then return end
	if pTick % delay == 0 then
	
		--Kích hoạt quest khi đến gần nhà Bob and Kate
		local playerGMD = GetPlayerGlobalModData(player)

		if not playerGMD.Data["QuestActive_BobAndKate"] then
			--Kích hoạt quest sau 3 ngày ingame
			if getGameTime():getWorldAgeHours() >= 72 then --FIXME: 72
				if IsPlayerInArea(player, 10737, 9402, 10761, 9424) then
					SetPlayerGMD_Data(player, "QuestActive_BobAndKate", true)
					SetPlayerGMD_Q3(player, "q3s001", "active", true)
					SetPlayerGMD_Q3(player, "q3s001", "startHour_KateZombified", getGameTime():getWorldAgeHours())
					SetPlayerGMD_Q3(player, "q3s001", "countHour_KateZombified", 168)	--FIXME: 168
					ActiveQuestIntro_Free(getText("IGUI_VLQ_3_Desc_q3s001"), (getCore():getScreenWidth() - 800) / 2, (getCore():getScreenHeight() - 200) / 6, 800, 250, false, "")
					QuestUpdatedPopIn()
					
					--Xóa zombie trong nhà Bob and Kate
					sendClientCommand(player, "NPCQuestCM", "RemoveZombiesInAreaExceptNPC", {x1 = 10744, y1 = 9409, x2 = 10753, y2 = 9416, z = 0})
					sendClientCommand(player, "NPCQuestCM", "RemoveZombiesInAreaExceptNPC", {x1 = 10744, y1 = 9409, x2 = 10753, y2 = 9416, z = 1})
					
					--Spawn NPC Bob + Kate
					SetNPCStateInQueueSpawnList({qStep = "q3s001", active = true})
					SpawnNPCOnClient("q3s001", 0)
					SetNPCStateInQueueSpawnList({qStep = "q3s001_2", active = true})
					SpawnNPCOnClient("q3s001_2", 0)  
					
					--Xóa xác chết
					RemoveCorpsesInArea(10744, 9409, 10753, 9416, 0)
					RemoveCorpsesInArea(10744, 9409, 10753, 9416, 1)
					
					--Thêm cửa nếu thiếu
					AddDoor(10744, 9413, 0, false)
					AddDoor(10750, 9415, 0, true)
					AddDoor(10747, 9411, 1, true)
					
					--Thêm giường nếu thiếu
					AddObjectToSquare(nil, "furniture_bedding_01_8", {isTransmit = true, x = 10745, y = 9412, z = 1, objType = "IsoObject"})
					AddObjectToSquare(nil, "furniture_bedding_01_9", {isTransmit = true, x = 10745, y = 9411, z = 1, objType = "IsoObject"})
					
					--Xóa đồ ăn trong nhà tầng 1
					for x = 10744, 10753 do
						for y = 9409, 9416 do
							RemoveAllFoodOnSquare(x, y, 0)
						end
					end
					
					--Barricade
					BarricadeRoom_q3s001(10750, 9413, 0)
					BarricadeRoom_q3s001(10747, 9415, 0)
					BarricadeRoom_q3s001(10744, 9414, 0)
					BarricadeRoom_q3s001(10745, 9412, 0)
					BarricadeRoom_q3s001(10745, 9411, 0)
					BarricadeRoom_q3s001(10749, 9409, 0)
				end
			end
		end

		--Chạy các qStep đang active
		if not VLQS or not VLQS.Q3Steps then return end
		
		local playerGMD_Quest_Q3 = GetPlayerGlobalModDataQ3(player, "q3s001")
		local activeQStepTab = {}
		for qStep, data in pairs(playerGMD_Quest_Q3) do
			if data.active == true then
				table.insert(activeQStepTab, qStep)
			end
		end
		
		for i = 1, #activeQStepTab do
			local func = VLQS.Q3Steps[activeQStepTab[i]]
			if func then
				func(player)
			end
		end
		
		pTick = 1
	end

	pTick = pTick + 1
end
Events.OnPlayerUpdate.Remove(OnPlayerUpdate_Q3)
Events.OnPlayerUpdate.Add(OnPlayerUpdate_Q3)

local function OnPlayerUpdate_EventQ3(player)
    if not player then return end
	if pTick2 % delay == 0 then
		--Nếu quest 3 kích hoạt mới update
		local playerGMD = GetPlayerGlobalModData(player)
		if playerGMD.Data["QuestActive_BobAndKate"] == true then
	
			local playerGMD_Quest_Q3 = GetPlayerGlobalModDataQ3(player, "q3s001")
						 
			--Player ở trong khu vực nhà của Bob và Kate
			if IsPlayerInArea(player, 10709, 9373, 10789, 9453, nil) then
				if not (playerGMD_Quest_Q3["q3s100"] and playerGMD_Quest_Q3["q3s100"]["quest3Ended"] == true) then	--kết thúc quest thì không update phần này
					if not thisSession["removeZombie"] then
						--Xóa zombie trong nhà Bob and Kate
						sendClientCommand(player, "NPCQuestCM", "RemoveZombiesInAreaExceptNPC", {x1 = 10744, y1 = 9409, x2 = 10753, y2 = 9416, z = 0})
						sendClientCommand(player, "NPCQuestCM", "RemoveZombiesInAreaExceptNPC", {x1 = 10744, y1 = 9409, x2 = 10753, y2 = 9416, z = 1})
						
						--Đóng cửa phòng tầng 2
						CloseDoor(10747, 9411, 1)
						--[[
						if not playerGMD_Quest_Q3["q3s001"]["setupBnKHouse"] then
							--Xóa xác chết
							RemoveCorpsesInArea(10744, 9409, 10753, 9416, 0)
							RemoveCorpsesInArea(10744, 9409, 10753, 9416, 1)
							
							--Thêm cửa nếu thiếu
							AddDoor(10744, 9413, 0, false)
							AddDoor(10750, 9415, 0, true)
							AddDoor(10747, 9411, 1, true)
							
							--Thêm giường nếu thiếu
							AddObjectToSquare(nil, "furniture_bedding_01_8", {isTransmit = true, x = 10745, y = 9412, z = 1, objType = "IsoObject"})
							AddObjectToSquare(nil, "furniture_bedding_01_9", {isTransmit = true, x = 10745, y = 9411, z = 1, objType = "IsoObject"})
							
							--Xóa đồ ăn trong nhà tầng 1
							for x = 10744, 10753 do
								for y = 9409, 9416 do
									RemoveAllFoodOnSquare(x, y, 0)
								end
							end
							
							--Barricade
							BarricadeRoom_q3s001(10750, 9413, 0)
							BarricadeRoom_q3s001(10747, 9415, 0)
							BarricadeRoom_q3s001(10744, 9414, 0)
							BarricadeRoom_q3s001(10745, 9412, 0)
							BarricadeRoom_q3s001(10745, 9411, 0)
							BarricadeRoom_q3s001(10749, 9409, 0)
							
							SetPlayerGMD_Q3(player, "q3s001", "setupBnKHouse", true)
						end
						]]
						
						thisSession["removeZombie"] = true
					end
				end
			else 
				if thisSession["removeZombie"] ~= nil then thisSession["removeZombie"] = nil end
			end
			
			--Kết cục 5 --Hết thời gian giới hạn cho Q3, Kate biến thành zombie
			if playerGMD_Quest_Q3["q3s001"] and playerGMD_Quest_Q3["q3s001"]["startHour_KateZombified"] and playerGMD_Quest_Q3["q3s001"]["countHour_KateZombified"] then
				local qStep = "q3s001"
				if (getGameTime():getWorldAgeHours() - playerGMD_Quest_Q3[qStep]["startHour_KateZombified"]) >= playerGMD_Quest_Q3[qStep]["countHour_KateZombified"] then
					--Không xác định npc Bob Kate đang ở qStep nào.
					--Xóa NPC. --check npc nào đang spawned trong Q3. Có thì xóa NPC
					RemoveAllNPCsSpawningQ3()

					--clear data
					ResetData_EndQ3(player)
					
					if not IsQuest3Completing() then
						--set ModData
						SetPlayerGMD_Q3(player, "q3s100", "quest3End5", true)
						
						--update qStep kết thúc 5
						UpdateQuestStepAndNext(player, 3, false, false, true, qStep, "done", "q3s100", true)
					end
					
					SetPlayerGMD_Q3(player, qStep, "startHour_KateZombified", nil)
					SetPlayerGMD_Q3(player, qStep, "countHour_KateZombified", nil)
				end	
			end

			--Kết cục 6 --Nếu không đưa thức ăn cho Bob, và đã kết thúc qStep q3s006
			if playerGMD_Quest_Q3["q3s006"] and playerGMD_Quest_Q3["q3s006"]["active"] == "done" and not playerGMD_Quest_Q3["q3s006"]["given500RHungerForBob"] then
				local qStep = "q3s006"
				if playerGMD_Quest_Q3[qStep]["startHour_BobZombified"] and playerGMD_Quest_Q3[qStep]["countHour_BobZombified"] then
					if (getGameTime():getWorldAgeHours() - playerGMD_Quest_Q3[qStep]["startHour_BobZombified"]) >= playerGMD_Quest_Q3[qStep]["countHour_BobZombified"] then
						--Không xác định npc Bob Kate đang ở qStep nào.
						--Xóa NPC. --check npc nào đang spawned trong Q3. Có thì xóa NPC
						RemoveAllNPCsSpawningQ3()
						
						--clear data
						ResetData_EndQ3(player)
						
						if not IsQuest3Completing() then
							SetPlayerGMD_Q3(player, "q3s100", "quest3End6", true)
							
							--update qStep kết thúc 6
							UpdateQuestStepAndNext(player, 3, false, false, true, qStep, "done", "q3s100", true)
						end
					end
				end
			end
					
			--Kết cục 2 --Tính thời gian 12 tiếng sau khi nói với Kate cô ấy là nguy hiểm của Bob --VLF.TalkToNPC["q3s012"]
			if playerGMD_Quest_Q3["q3s012"] and playerGMD_Quest_Q3["q3s012"]["sayKateIsDangerousToBob2"] == true then
				local qStep = "q3s012"
				local now = getGameTime():getWorldAgeHours()
				if (now - playerGMD_Quest_Q3[qStep]["startTime_KateSuicide"]) >= 12 then
				
					--Kate tự sát		
					local npcData = VLF.npcData["q3s012"]
					local isKateDead = SetNPCDead("npcQuestSleepOnBed", "q3s012", "pistol", npcData.startX + 1.5, npcData.startY + 2.5, npcData.startZ)
					if isKateDead == true then
						SetPlayerGMD_Q3(player, qStep, "corpseAdded_Kate", true)
					end
					--Bob tự sát	
					local isBobDead = SetNPCDead("npcQuestIdle", "q3s013", "pistol", nil, nil, nil)
					if isBobDead == true then
						SetPlayerGMD_Q3(player, qStep, "corpseAdded_Bob", true)
					end
					
					--set ModData
					SetPlayerGMD_Q3(player, "q3s012", "sayKateIsDangerousToBob2", nil)
					SetPlayerGMD_Q3(player, "q3s100", "quest3End2", true)
					
					if not IsQuest3Completing() then
						--clear data
						ResetData_EndQ3(player)
						
						--update qStep kết thúc 2
						UpdateQuestStepAndNext(player, 3, false, false, true, qStep, "done", "q3s100", true)
					end
				end
			end
			
			--Quest 3 kết thúc thì xóa event này
			if playerGMD_Quest_Q3["q3s100"] and playerGMD_Quest_Q3["q3s100"]["quest3Ended"] == true then
				Events.OnPlayerUpdate.Remove(OnPlayerUpdate_EventQ3)
			end
		end
		pTick2 = 1
	end	
	pTick2 = pTick2 + 1
end
Events.OnPlayerUpdate.Remove(OnPlayerUpdate_EventQ3)
Events.OnPlayerUpdate.Add(OnPlayerUpdate_EventQ3)
 





