local meta = FindMetaTable("Player")

if CLIENT then
	function MG_CarDealer.Switch2CarSpawner(id, model, skin, npc)
		local ply = LocalPlayer()
		if !ply:Alive() then return end
		MG_CarDealer.EnableThirdPerson(true, npc)
		MG_CarDealer.CarSpawnMode(npc, model, skin, id)
	end

	function MG_CarDealer.Switch2CarStorer(npc)
		local ply = LocalPlayer()
		if !ply:Alive() then return end
		MG_CarDealer.EnableThirdPerson(true, npc)
		MG_CarDealer.CarStoreMode(npc)
	end

	function MG_CarDealer.ReturnMousePos()
		local ply = LocalPlayer()
		if !ply:Alive() then return end
		local tr = {}
		tr.start = ply.MG_CarDealerThirdPos
		tr.endpos = ply.MG_CarDealerThirdPos + gui.ScreenToVector(gui.MousePos()) * 20000
		return util.TraceLine(tr)
	end

	function MG_CarDealer.GetRoofPosition(ent)
		local pos = ent:GetPos()
		local tr = {}
		tr.start = pos + Vector(0, 0, 120)
		tr.endpos = pos + Vector(0, 0, 400)
		local trace = util.TraceLine(tr)
		if trace.HitSky then
			pos.z = trace.HitPos.z
			return pos
		else
			return pos + Vector(0, 0, 400)
		end
	end
end

if SERVER then
	util.AddNetworkString("MG_CarDealer_ThirdPerson_C2S")

	net.Receive("MG_CarDealer_ThirdPerson_C2S", function(len, ply)
		local bool = net.ReadBool()
		local npc = net.ReadEntity()
		if bool then
			if !IsValid(npc) or npc:GetClass() != "car_dealer" then return end
			ply:Freeze(true)
		else
			ply:Freeze(false)
		end
	end)
else
	function MG_CarDealer.EnableThirdPerson(bool, npc)
		net.Start("MG_CarDealer_ThirdPerson_C2S")
			net.WriteBool(bool)
			net.WriteEntity(npc)
		net.SendToServer()
	end
end

if SERVER then
	local function SetupVehicle(ent)
		ent.MG_CarDealer_SetupComplete = true
		if VC and !ent.CData.UnlimitedHealth then
			if ent.MG_CarDealer_MaxHealth and ent.VC_setHealthMax then
				ent:VC_setHealthMax(ent.MG_CarDealer_MaxHealth)
			end
			if ent.MG_CarDealer_Health and ent.VC_setHealth then
				ent:VC_setHealth(ent.MG_CarDealer_Health)
			end
			if ent.MG_CarDealer_DamagedParts and ent.VC_SetDamagedParts then
				ent:VC_SetDamagedParts(ent.MG_CarDealer_DamagedParts)
			end
			if !ent.MG_CarDealer_Health and !ent.MG_CarDealer_MaxHealth and ent.MG_CarDealer_Armored and ent.VC_setHealthMax and ent.VC_setHealth then
				ent:VC_setHealthMax(ent:VC_getHealthMax() * MG_CarDealerConfig.ArmorUpgradePercentage)
				ent:VC_setHealth(ent:VC_getHealth() * MG_CarDealerConfig.ArmorUpgradePercentage)
			end
		end
		if ent.GetVehicleFuel and !ent.CData.UnlimitedFuel then
			if ent.MG_CarDealer_MaxFuel then
				ent:SetMaxVehicleFuel(ent.MG_CarDealer_MaxFuel)
			end
			if ent.MG_CarDealer_Fuel then
				ent:SetVehicleFuel(ent.MG_CarDealer_Fuel)
			end
			if !ent.MG_CarDealer_Fuel and !ent.MG_CarDealer_MaxFuel and ent.MG_CarDealer_ExtraFuel then
				ent:SetMaxVehicleFuel(ent:GetMaxVehicleFuel() * MG_CarDealerConfig.FuelUpgradePercentage)
				ent:SetVehicleFuel(ent:GetVehicleFuel() * MG_CarDealerConfig.FuelUpgradePercentage)
			end
			ent:NetworkVehicleFuel()
		end
		if ent.MG_CarDealer_VehicleAlarm then
			ent.AlarmActive = true
		end
	end

	hook.Add("VC_postVehicleInit", "MG_CarDealer_SetHealth", function(ent)
		if ent.IsPlayerCar and !ent.MG_CarDealer_SetupComplete then
			SetupVehicle(ent)
		end
	end)

	hook.Add("VC_CanDamagePart", "MG_CarDealer_BulletProof", function(ent, class)
		if ent.IsPlayerCar and ent.MG_CarDealer_BulletProof and class == "wheel" then
			return false
		end
	end)

	hook.Add("VC_healthChanged", "MG_CarDealer_Insurance", function(ent, ohealth, nhealth)
		if ent.IsPlayerCar and ent.MG_CarDealer_Insurance then
			local max = ent:VC_getHealthMax()
			if ent.MG_CarDealer_Insurance == 0 then
				if nhealth >= max then
					ent.MG_CarDealer_Insurance = true
				end
			elseif (nhealth / max) < MG_CarDealerConfig.InsurancePercentage then
				ent.MG_CarDealer_Insurance = 0
			end
		end
	end)

	util.AddNetworkString("MG_CarDealer_DoSpawn_C2S")
	local spawnrange = MG_CarDealerConfig.CarSpawnRange * MG_CarDealerConfig.CarSpawnRange
	net.Receive("MG_CarDealer_DoSpawn_C2S", function(len, ply)
		if hook.Run("MG_CarDealer_DoSpawn", ply) == false then return end
		if !ply:Alive() then return end
		local pos = net.ReadVector()
		if !util.IsInWorld(pos) then return end
		local npc = net.ReadEntity()
		if !IsValid(npc) or npc:GetClass() != "car_dealer" then return end
		if !ply.LastUsedEntity or ply.LastUsedEntity[1] != npc then return end
		if ply:GetPos():DistToSqr(npc:GetPos()) > 1000000 then DarkRP.notify(ply, 1, 4, "Du bist zu weit vom Autohändler entfernt!") return end
		if pos:DistToSqr(npc:GetPos() + Vector(0, 0, 30) + npc:GetForward() * MG_CarDealerConfig.CarSpawnRange / 2) > spawnrange then DarkRP.notify(ply, 1, 5, "Du kannst Autos nicht außerhalb der Reichweite des Autohändlers spawnen!") return end
		if MG_CarDealerConfig.DrivePrice > 0 and !ply:canAfford(MG_CarDealerConfig.DrivePrice) then ply:MG_CarDealer_SendNotice("Du benötigst $"..string.Comma(MG_CarDealerConfig.DrivePrice)..", um dein Auto aus der Garage zu holen!") return end
		local allowed, reason = ply:MG_CarDealer_CheckCarLimit()
		if !allowed then ply:MG_CarDealer_SendNotice(reason) return end
		local sid = ply:SteamID()
		local id = net.ReadUInt(32)
		MG_CarDealer_Provider.GetVehicle(sid, id, function(data)
			if !IsValid(ply) then return end
			if !data then ply:MG_CarDealer_SendNotice("Fehler! Bitte versuche es später erneut.") return end
			local invdata = data
			local carclass = invdata.carclass
			local tunedata = invdata.tunedata and util.JSONToTable(invdata.tunedata)
			local vehdata = MG_CarDealer.Util_GetVehicleData(carclass)
			if !vehdata then ply:MG_CarDealer_SendNotice("Fehler! Bitte versuche es später erneut.") return end
			local cardata = MG_CarDealer.Util_GetCarData(carclass)
			if !cardata then ply:MG_CarDealer_SendNotice("Fehler! Bitte versuche es später erneut.") return end
			if invdata.towed and invdata.towed != "NULL" and tonumber(invdata.towed) == 1 then ply:MG_CarDealer_SendNotice("Dein Auto wurde abgeschleppt, kaufe es vorerst wieder frei!") return end
			if invdata.towed and invdata.towed != "NULL" and tonumber(invdata.towed) == 2 then ply:MG_CarDealer_SendNotice("Dein Auto wurde gestohlen, kaufe es vorerst wieder frei!") return end
			local allowed, reason = ply:MG_CarDealer_CanSpawnCar(carclass)
			if !allowed then
				ply:MG_CarDealer_SendNotice(reason)
				return
			end
			local health = invdata.health
			if (health and health != "NULL" and tonumber(health) <= 0) then
				ply:MG_CarDealer_SendNotice("Dieses Auto ist zerstört!")
				return
			end
			local fuel = invdata.fuel
			if (fuel and fuel != "NULL" and tonumber(fuel) <= 0) then
				ply:MG_CarDealer_SendNotice("Dieses Auto ist leer!")
				return
			end
			local car = ents.Create(vehdata.Class)
			if !IsValid(car) then return end
			car:SetModel(vehdata.Model)
			for k, v in pairs(vehdata.KeyValues) do
				car:SetKeyValue(k, v)
			end
			local mins = car:OBBMins()
			car:SetPos(pos - Vector(0, 0, mins.z))
			if MG_CarDealerConfig.EnableVCMod then
				car.MG_CarDealer_Health = health and health != "NULL" and tonumber(health)
				car.MG_CarDealer_MaxHealth = invdata.maxhealth and invdata.maxhealth != "NULL" and tonumber(invdata.maxhealth)
				local damagedparts = invdata.damagedparts and invdata.damagedparts != "NULL" and util.JSONToTable(invdata.damagedparts)
				car.MG_CarDealer_DamagedParts = damagedparts
			end
			if MG_CarDealerConfig.EnableMG_VMod then
				car.MG_CarDealer_Fuel = fuel and fuel != "NULL" and tonumber(fuel)
				car.MG_CarDealer_MaxFuel = invdata.maxfuel and invdata.maxfuel != "NULL" and tonumber(invdata.maxfuel)
			end
			car.MG_CarDealer_Armored = tonumber(invdata.armored) == 1
			car.MG_CarDealer_ExtraFuel = tonumber(invdata.extrafuel) == 1
			car.MG_CarDealer_BulletProof = tonumber(invdata.bulletproof) == 1
			car.MG_CarDealer_VehicleAlarm = tonumber(invdata.vehiclealarm) == 1
			car.MG_CarDealer_Insurance = tonumber(invdata.insurance) == 1 and (MG_CarDealerConfig.EnableVCMod and ((car.MG_CarDealer_Health or 1) / (car.MG_CarDealer_MaxHealth or 1)) >= 1 and true or 0)
			car:SetNW2Bool("MG_CarDealer_LockUpgrade", tonumber(invdata.lock) == 1)
			car.IsPlayerCar = true
			car.SID = ply.SID
			car.Owner = ply
			car.OwnerID = sid
			car:SetNWString("OwnerSID", sid)
			car.INVData = invdata
			car.CData = cardata
			car.VehicleName = carclass
			car.VehicleTable = vehdata
			car:SetVehicleClass(carclass)
			car:Spawn()
			car:Activate()
			car:keysOwn(ply)
			if tunedata then
				tunedata = MG_CarDealer.ValidateTuning(tunedata)
				car.TuneData = tunedata
				if !cardata.NoSkin then
					car:SetSkin(tunedata.SkinNumber or 0)
				end
				if !cardata.NoBodygroup then
					for k,v in pairs(tunedata.BodyGroups or {}) do
						car:SetBodygroup(k, v)
					end
				end
			end
			DoPropSpawnedEffect(car)
			if tunedata then
				local tunesys = ents.Create("car_tune_sys")
				if IsValid(tunesys) then
					tunesys:SetPos(car:GetPos())
					tunesys:SetAngles(car:GetAngles())
					tunesys.Mother = car
					tunesys:Spawn()
					tunesys:SetParent(car)
					tunesys:SetTuneData(tunedata)
					car.TuneSys = tunesys
				end
			end
			MG_CarDealer.AddCar(car)
			hook.Call("playerBoughtVehicle", GAMEMODE, car, car)
			hook.Call("PlayerSpawnedVehicle", GAMEMODE, ply, car)
			if car.CPPISetOwner then
				car:CPPISetOwner()
			end
			if MG_CarDealerConfig.EnterCarAfterSpawn and !ply:isArrested() then
				ply:ExitVehicle()
				ply:EnterVehicle(car)
			elseif MG_CarDealerConfig.LockCarAfterSpawn then
				car:keysLock()
			end
			if MG_CarDealerConfig.DrivePrice > 0 then
				ply:addMoney(-MG_CarDealerConfig.DrivePrice)
			end
			DarkRP.notify(ply, 0, 5, "Du hast dein Auto"..(MG_CarDealerConfig.DrivePrice > 0 and " für $"..string.Comma(MG_CarDealerConfig.DrivePrice) or "").." aus der Garage geholt.")
			MG_CarDealer.DrivingCars[id] = car
			hook.Run("MG_CarDealer_SpawnedCar", ply, car)
		end)
	end)
else
	function MG_CarDealer.SpawnCar(pos, id, npc)
		net.Start("MG_CarDealer_DoSpawn_C2S")
			net.WriteVector(pos)
			net.WriteEntity(npc)
			net.WriteUInt(id, 32)
		net.SendToServer()
	end
end

if SERVER then
	util.AddNetworkString("MG_CarDealer_DoStore_C2S")

	net.Receive("MG_CarDealer_DoStore_C2S", function(len, ply)
		local car = net.ReadEntity()
		if IsValid(car) and car.IsPlayerCar and car.OwnerID == ply:SteamID() then
			
			ply:MG_CarDealer_SaveCar(car)
			ply:MG_CarDealer_SendNotice("Dein Auto wurde gespeichert.")
		end
	end)
else
	function MG_CarDealer.StoreCar(car)
		net.Start("MG_CarDealer_DoStore_C2S")
			net.WriteEntity(car)
		net.SendToServer()
	end
end

local function RemoveSpawnHooks()
	hook.Remove("CalcView", "MG_CarDealer_ThirdView")
	hook.Add("ShouldDrawLocalPlayer", "MG_CarDealer_DrawPlayer", function()
		hook.Remove("ShouldDrawLocalPlayer", "MG_CarDealer_DrawPlayer")
		return true
	end)
	hook.Remove("CalcView", "MG_CarDealer_DrawPlayer")
	hook.Remove("HUDPaint", "MG_CarDealer_Guide")
	hook.Remove("PlayerButtonDown", "MG_CarDealer_SpawnClick")
	hook.Remove("PostDrawOpaqueRenderables", "MG_CarDealer_Render")
	gui.EnableScreenClicker(false)
	MG_CarDealer.EnableThirdPerson(false)
end

local function MG_CarDealer_DoSpawnCar(pos, id, npc)
	RemoveSpawnHooks()
	MG_CarDealer.SpawnCar(pos, id, npc)
end

local function RemoveStoreHooks()
	hook.Remove("CalcView", "MG_CarDealer_ThirdView")
	hook.Add("ShouldDrawLocalPlayer", "MG_CarDealer_DrawPlayer", function()
		hook.Remove("ShouldDrawLocalPlayer", "MG_CarDealer_DrawPlayer")
		return true
	end)
	hook.Remove("CalcView", "MG_CarDealer_DrawPlayer")
	hook.Remove("HUDPaint", "MG_CarDealer_Guide")
	hook.Remove("PlayerButtonDown", "MG_CarDealer_SpawnClick")
	hook.Remove("PreDrawHalos", "MG_CarDealer_DrawHalos")
	gui.EnableScreenClicker(false)
	MG_CarDealer.EnableThirdPerson(false)
end

local function MG_CarDealer_DoStoreCar(car)
	RemoveStoreHooks()
	MG_CarDealer.StoreCar(car)
end

local spawnrange = MG_CarDealerConfig.CarSpawnRange * MG_CarDealerConfig.CarSpawnRange
local function CanSpawnCar(npcpos, carpos)
	if npcpos:DistToSqr(carpos) > spawnrange then
		return false, nil, "Du bist zu weit vom Autohändler entfernt!"
	end
	if npcpos.z + 100 < carpos.z then
		return false, nil, "Dieser Ort ist zu hoch!"
	end
	local ent = CDEALER_CMODEL_CAR
	local mins = ent:OBBMins()
	local maxs = ent:OBBMaxs()
	local pos = ent:GetPos()
	local tr = util.TraceHull({start = pos, endpos = pos, mins = mins, maxs = maxs, filter = ent})
	if tr.Hit then
		return false, tr.HitPos, "Dieser Ort ist blockiert!"
	end
	local mouse_tr = MG_CarDealer.ReturnMousePos()
	if !mouse_tr then return true end
	if IsValid(mouse_tr.Entity) then
		return false, mouse_tr.HitPos, "Dieser Ort ist blockiert!"
	end
	return true
end

function MG_CarDealer.CarStoreMode(npc)
	if !IsValid(npc) then return end
	local ply = LocalPlayer()
	if !ply:Alive() then return end
	local poslock = npc:GetPos() + Vector(0, 0, 30) + npc:GetForward() * MG_CarDealerConfig.CarSpawnRange/2
	local roofpos = MG_CarDealer.GetRoofPosition(npc)

	ply.MG_CarDealerThirdPos = npc:GetPos() + Vector(0, 0, 400) + npc:GetForward() * MG_CarDealerConfig.CarSpawnRange/2

	gui.EnableScreenClicker(true)

	hook.Add("CalcView", "MG_CarDealer_ThirdView", function(ply, origin, angles, fov)
		return GAMEMODE:CalcView(ply, ply.MG_CarDealerThirdPos, Angle(90, 0, 0), fov)
	end)

	hook.Add("ShouldDrawLocalPlayer", "MG_CarDealer_DrawPlayer", function()
		return true
	end)

	hook.Add("HUDPaint", "MG_CarDealer_Guide", function()
		if !IsValid(ply) or !ply:Alive() then RemoveStoreHooks() return end
		draw.SimpleText("Linksklick auf ein Auto, um es in deiner Garage zu sichern.", "MG_CarDealer_TrebLWOut_S45", ScrW() / 2, ScrH() - 200, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		draw.SimpleText("Rechtsklick zum Abbrechen.", "MG_CarDealer_TrebLWOut_S30", ScrW() / 2, ScrH() - 170, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		draw.SimpleText("Du kannst die Kamera mit WASD verschieben.", "MG_CarDealer_TrebLWOut_S20", ScrW() / 2, ScrH() - 140, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		draw.SimpleText("Du kannst das Sichtfeld mit den Pfeiltasten verändern.", "MG_CarDealer_TrebLWOut_S20", ScrW() / 2, ScrH() - 120, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		local speed = RealFrameTime() * 500
		if input.IsKeyDown(KEY_A) then
			ply.MG_CarDealerThirdPos.y = ply.MG_CarDealerThirdPos.y + speed
		end
		if input.IsKeyDown(KEY_D) then
			ply.MG_CarDealerThirdPos.y = ply.MG_CarDealerThirdPos.y - speed
		end
		if input.IsKeyDown(KEY_W) then
			ply.MG_CarDealerThirdPos.x = ply.MG_CarDealerThirdPos.x + speed
		end
		if input.IsKeyDown(KEY_S) then
			ply.MG_CarDealerThirdPos.x = ply.MG_CarDealerThirdPos.x - speed
		end
		ply.MG_CarDealerThirdPos.x = math.max(ply.MG_CarDealerThirdPos.x, poslock.x - MG_CarDealerConfig.CarSpawnRange / 2)
		ply.MG_CarDealerThirdPos.x = math.min(ply.MG_CarDealerThirdPos.x, poslock.x + MG_CarDealerConfig.CarSpawnRange / 2)
		ply.MG_CarDealerThirdPos.y = math.max(ply.MG_CarDealerThirdPos.y, poslock.y - MG_CarDealerConfig.CarSpawnRange / 2)
		ply.MG_CarDealerThirdPos.y = math.min(ply.MG_CarDealerThirdPos.y, poslock.y + MG_CarDealerConfig.CarSpawnRange / 2)
		if input.IsKeyDown(KEY_UP) then
			ply.MG_CarDealerThirdPos.z = ply.MG_CarDealerThirdPos.z - speed
		end
		if input.IsKeyDown(KEY_DOWN) then
			ply.MG_CarDealerThirdPos.z = ply.MG_CarDealerThirdPos.z + speed
		end
		ply.MG_CarDealerThirdPos.z = math.max(ply.MG_CarDealerThirdPos.z, poslock.z + 50)
		ply.MG_CarDealerThirdPos.z = math.min(ply.MG_CarDealerThirdPos.z, roofpos.z - 10)
	end)

	hook.Add("PlayerButtonDown", "MG_CarDealer_SpawnClick", function(ply, mc)
		if mc == MOUSE_RIGHT then
			RemoveStoreHooks()
		end
		if mc == MOUSE_LEFT then
			local mouse_tr = MG_CarDealer.ReturnMousePos()
			if !mouse_tr then return end
			if IsValid(mouse_tr.Entity) and mouse_tr.Entity:IsVehicle() and mouse_tr.Entity:GetNWString("OwnerSID") == LocalPlayer():SteamID() then
				MG_CarDealer_DoStoreCar(mouse_tr.Entity)
			end
		end
	end)

	hook.Add("PreDrawHalos", "MG_CarDealer_DrawHalos", function()
		if !IsValid(ply) or !ply:Alive() then RemoveStoreHooks() return end
		local mouse_tr = MG_CarDealer.ReturnMousePos()
		if !mouse_tr then return end
		local allowed = {}
		local ply = LocalPlayer()
		for _,v in ipairs(ents.FindInSphere(poslock, MG_CarDealerConfig.CarStoreRange + 250)) do
			if v:IsVehicle() and v:GetNWString("OwnerSID") == ply:SteamID() then
				allowed[v] = true
				halo.Add({v}, Color(0, 255, 0), 5, 5, 1)
			end
		end
		if IsValid(mouse_tr.Entity) and !allowed[mouse_tr.Entity] and !mouse_tr.Entity:IsPlayer() then
			halo.Add({mouse_tr.Entity}, Color(255, 0, 0), 5, 5, 1)
		end
	end)
end

local beam = Material("sprites/physgbeamb")
function MG_CarDealer.CarSpawnMode(npc, carmodel, carskin, id)
	if !IsValid(npc) then return end
	local ply = LocalPlayer()
	if !ply:Alive() then return end
	local poslock = npc:GetPos() + Vector(0, 0, 30) + npc:GetForward() * MG_CarDealerConfig.CarSpawnRange / 2
	local roofpos = MG_CarDealer.GetRoofPosition(npc)

	ply.MG_CarDealerThirdPos = npc:GetPos() + Vector(0, 0, 400) + npc:GetForward() * MG_CarDealerConfig.CarSpawnRange / 2

	gui.EnableScreenClicker(true)

	hook.Add("CalcView", "MG_CarDealer_ThirdView", function(ply, origin, angles, fov)
		return GAMEMODE:CalcView(ply, ply.MG_CarDealerThirdPos, Angle(90, 0, 0), fov)
	end)

	hook.Add("ShouldDrawLocalPlayer", "MG_CarDealer_DrawPlayer", function()
		return true
	end)

	hook.Add("HUDPaint", "MG_CarDealer_Guide", function()
		if !IsValid(ply) or !ply:Alive() or !IsValid(npc) then RemoveSpawnHooks() return end
		local mouse_tr = MG_CarDealer.ReturnMousePos()
		if !mouse_tr then return end
		local _, _, reason = CanSpawnCar(poslock, mouse_tr.HitPos, npc)
		draw.SimpleText("Linksklick auf eine Position, um dort ein Auto zu platzieren.", "MG_CarDealer_TrebLWOut_S45", ScrW() / 2,ScrH() - 240, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		draw.SimpleText("Rechtsklick zum Abbrechen.", "MG_CarDealer_TrebLWOut_S30", ScrW() / 2, ScrH() - 210, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		draw.SimpleText("Du kannst die Kamera mit WASD verschieben.", "MG_CarDealer_TrebLWOut_S20", ScrW() / 2, ScrH() - 180, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		draw.SimpleText("Du kannst das Sichtfeld mit den Pfeiltasten verändern.", "MG_CarDealer_TrebLWOut_S20", ScrW() / 2, ScrH() - 160, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		if reason then
			draw.SimpleText(reason, "MG_CarDealer_TrebLWOut_S40", ScrW() / 2, ScrH() - 125, Color(255, 0, 0, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		else
			draw.SimpleText("Spawn ist möglich.", "MG_CarDealer_TrebLWOut_S40", ScrW() / 2, ScrH() - 125, Color(0, 255, 0, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
		end
		local speed = RealFrameTime() * 500
		if input.IsKeyDown(KEY_A) then
			ply.MG_CarDealerThirdPos.y = ply.MG_CarDealerThirdPos.y + speed
		end
		if input.IsKeyDown(KEY_D) then
			ply.MG_CarDealerThirdPos.y = ply.MG_CarDealerThirdPos.y - speed
		end
		if input.IsKeyDown(KEY_W) then
			ply.MG_CarDealerThirdPos.x = ply.MG_CarDealerThirdPos.x + speed
		end
		if input.IsKeyDown(KEY_S) then
			ply.MG_CarDealerThirdPos.x = ply.MG_CarDealerThirdPos.x - speed
		end
		ply.MG_CarDealerThirdPos.x = math.max(ply.MG_CarDealerThirdPos.x, poslock.x - MG_CarDealerConfig.CarSpawnRange / 2)
		ply.MG_CarDealerThirdPos.x = math.min(ply.MG_CarDealerThirdPos.x, poslock.x + MG_CarDealerConfig.CarSpawnRange / 2)
		ply.MG_CarDealerThirdPos.y = math.max(ply.MG_CarDealerThirdPos.y, poslock.y - MG_CarDealerConfig.CarSpawnRange / 2)
		ply.MG_CarDealerThirdPos.y = math.min(ply.MG_CarDealerThirdPos.y, poslock.y + MG_CarDealerConfig.CarSpawnRange / 2)
		if input.IsKeyDown(KEY_UP) then
			ply.MG_CarDealerThirdPos.z = ply.MG_CarDealerThirdPos.z - speed
		end
		if input.IsKeyDown(KEY_DOWN) then
			ply.MG_CarDealerThirdPos.z = ply.MG_CarDealerThirdPos.z + speed
		end
		ply.MG_CarDealerThirdPos.z = math.max(ply.MG_CarDealerThirdPos.z, poslock.z + 50)
		ply.MG_CarDealerThirdPos.z = math.min(ply.MG_CarDealerThirdPos.z, roofpos.z - 10)
	end)

	hook.Add("PlayerButtonDown", "MG_CarDealer_SpawnClick", function(ply, mc)
		if mc == MOUSE_RIGHT then
			RemoveSpawnHooks()
		end
		if mc == MOUSE_LEFT then
			local mouse_tr = MG_CarDealer.ReturnMousePos()
			if !mouse_tr then return end
			local cs = CanSpawnCar(poslock, mouse_tr.HitPos, npc)
			if cs == false then return end
			MG_CarDealer_DoSpawnCar(mouse_tr.HitPos, id, npc)
		end
	end)

	hook.Add("PostDrawOpaqueRenderables", "MG_CarDealer_Render", function()
		if !IsValid(ply) or !ply:Alive() or !IsValid(npc) then RemoveSpawnHooks() return end
		local mouse_tr = MG_CarDealer.ReturnMousePos()
		if !mouse_tr then return end
		local carpos = mouse_tr.HitPos
		CDEALER_CMODEL_CAR:SetModel(carmodel)
		CDEALER_CMODEL_CAR:SetSkin(carskin)
		local hgt = 30
		if carmodel == "models/airboat.mdl" then
			hgt = hgt + 12
		elseif MG_CarDealerConfig.PositionModifier[carmodel] then
			hgt = hgt + MG_CarDealerConfig.PositionModifier[carmodel]
		end
		CDEALER_CMODEL_CAR:SetRenderOrigin(carpos + Vector(0, 0, hgt))
		CDEALER_CMODEL_CAR:SetRenderAngles(angle_zero)
		render.SetMaterial(beam)
		local cs, tracehit = CanSpawnCar(poslock, carpos, npc)
		local npcpos = npc:GetPos()
		if !cs then
			render.DrawBeam(npcpos, carpos, 5, 1, 1, Color(255, 0, 0, 255)) 
			if tracehit then
				render.DrawBeam(npcpos, tracehit, 7, 1, 1, Color(255, 255, 0, 255)) 
			end
		else
			render.DrawBeam(npcpos, carpos, 5, 1, 1, Color(0, 255, 255, 255)) 
		end
		render.SetBlend(0.5)
		if !cs then
			render.SetColorModulation(1, 0, 0)
		else
			render.SetColorModulation(1, 1, 1)
		end
		CDEALER_CMODEL_CAR:DrawModel()
		render.SetColorModulation(1, 1, 1)
		render.SetBlend(1)
	end)
end