Pinkstack/roblox-luau-corpus-text huggingface dataset:
-- Gets the storage location for packages used by each Dev Modules. The packages
-- that get put in this folder are deduplicated so every distinct version of a
-- package has only one copy.


local function getPackageStorage(): Folder
	local packageStorage = constants.PACKAGE_STORAGE_LOCATION:FindFirstChild(constants.PACKAGE_STORAGE_NAME) :: Folder

	if not packageStorage then
		packageStorage = Instance.new("Folder")
		packageStorage.Name = constants.PACKAGE_STORAGE_NAME
		packageStorage.Parent = constants.PACKAGE_STORAGE_LOCATION
	end

	return packageStorage
end
--[[
    Creates a touched event listener on specified part, that kills any humanoids that touch it
]]


return function(part)
	return part.Touched:Connect(
		function(hit)
			if hit and hit.Parent then
				local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
				if humanoid then
					humanoid.Health = 0
				end
			end
		end
	)
end
-------- OMG HAX



r = game:service("RunService")


local damage = 5


local slash_damage = 12
local lunge_damage = 16

sword = script.Parent.Handle
Tool = script.Parent


local SlashSound = Instance.new("Sound")
SlashSound.SoundId = "rbxasset://sounds\\swordslash.wav"
SlashSound.Parent = sword
SlashSound.Volume = .7

local LungeSound = Instance.new("Sound")
LungeSound.SoundId = "rbxasset://sounds\\swordlunge.wav"
LungeSound.Parent = sword
LungeSound.Volume = .6

local UnsheathSound = Instance.new("Sound")
UnsheathSound.SoundId = "rbxasset://sounds\\unsheath.wav"
UnsheathSound.Parent = sword
UnsheathSound.Volume = 1


function blow(hit)
	local humanoid = hit.Parent:findFirstChild("Humanoid")
	local vCharacter = Tool.Parent
	local vPlayer = game.Players:playerFromCharacter(vCharacter)
	local hum = vCharacter:findFirstChild("Humanoid") -- non-nil if tool held by a character
	if humanoid~=nil and humanoid ~= hum and hum ~= nil then
		-- final check, make sure sword is in-hand

		local right_arm = vCharacter:FindFirstChild("Right Arm")
		if (right_arm ~= nil) then
			local joint = right_arm:FindFirstChild("RightGrip")
			if (joint ~= nil and (joint.Part0 == sword or joint.Part1 == sword)) then
				tagHumanoid(humanoid, vPlayer)
				humanoid:TakeDamage(damage)
				wait(1)
				untagHumanoid(humanoid)
			end
		end


	end
end


function tagHumanoid(humanoid, player)
	local creator_tag = Instance.new("ObjectValue")
	creator_tag.Value = player
	creator_tag.Name = "creator"
	creator_tag.Parent = humanoid
end

function untagHumanoid(humanoid)
	if humanoid ~= nil then
		local tag = humanoid:findFirstChild("creator")
		if tag ~= nil then
			tag.Parent = nil
		end
	end
end


function attack()
	damage = slash_damage
	SlashSound:play()
	local anim = Instance.new("StringValue")
	anim.Name = "toolanim"
	anim.Value = "Slash"
	anim.Parent = Tool
end

function lunge()
	damage = lunge_damage

	LungeSound:play()

	local anim = Instance.new("StringValue")
	anim.Name = "toolanim"
	anim.Value = "Lunge"
	anim.Parent = Tool
	
	
	force = Instance.new("BodyVelocity")
	force.velocity = Vector3.new(0,10,0) --Tool.Parent.Torso.CFrame.lookVector * 80
	force.Parent = Tool.Parent.Torso
	wait(.2)
	swordOut()
	wait(.2)
	force.Parent = nil
	wait(.4)
	swordUp()

	damage = slash_damage
end

function swordUp()
	Tool.GripForward = Vector3.new(-1,0,0)
	Tool.GripRight = Vector3.new(0,1,0)
	Tool.GripUp = Vector3.new(0,0,1)
end

function swordOut()
	Tool.GripForward = Vector3.new(0,0,1)
	Tool.GripRight = Vector3.new(0,1,0)
	Tool.GripUp = Vector3.new(1,0,0)
end

function swordAcross()
	-- parry
end


Tool.Enabled = true
local last_attack = 0
function onActivated()

	if not Tool.Enabled then
		return
	end

	Tool.Enabled = false

	local character = Tool.Parent;
	local humanoid = character.Humanoid
	if humanoid == nil then
		print("Humanoid not found")
		return 
	end

	t = r.Stepped:wait()

	if (t - last_attack < .2) then
		lunge()
	else
		attack()
	end

	last_attack = t

	--wait(.5)

	Tool.Enabled = true
end


function onEquipped()
	UnsheathSound:play()
end


script.Parent.Activated:connect(onActivated)
script.Parent.Equipped:connect(onEquipped)


connection = sword.Touched:connect(blow)
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


elseif guntype == 2 then--BullPup
local torso = model.Parent:FindFirstChild("Torso")
if torso ~= nil then
if weldmode == 1 then--barrel pointing upper-right
local w = Instance.new("Weld")
w.Part0 = torso
w.Parent = w.Part0
w.Part1 = handle
w.C1 = CFrame.new(distance *-1, 0.25+y, -0.5 +x *-1) * CFrame.fromEulerAnglesXYZ(math.rad(rotation *-1), math.pi / 2, 0)
elseif weldmode == 2 then--barrel pointing upper-left
local w = Instance.new("Weld")
w.Part0 = torso
w.Parent = w.Part0
w.Part1 = handle
w.C1 = CFrame.new(distance, 0.25 +y, -0.5 +x *-1) * CFrame.fromEulerAnglesXYZ(math.rad(rotation *-1), math.pi / 2 *-1, 0)
elseif weldmode == 3 then--barrel pointing upside-right
local w = Instance.new("Weld")
w.Part0 = torso
w.Parent = w.Part0
w.Part1 = handle
w.C1 = CFrame.new(distance *-1, 0.25 +y, -0.5 +x *-1) * CFrame.fromEulerAnglesXYZ(math.rad(rotation), math.pi / 2, 0)
elseif weldmode == 4 then--barrel pointing upside-left
local w = Instance.new("Weld")
w.Part0 = torso
w.Parent = w.Part0
w.Part1 = handle
w.C1 = CFrame.new(distance, 0.25 +y, -0.5 +x *-1) * CFrame.fromEulerAnglesXYZ(math.rad(rotation), math.pi / 2 *-1, 0)
end
end
-- wait for the first of the passed signals to fire


local function waitForFirst(...)
	local shunt = Instance.new("BindableEvent")
	local slots = {...}

	local function fire(...)
		for i = 1, #slots do
			slots[i]:Disconnect()
		end

		return shunt:Fire(...)
	end

	for i = 1, #slots do
		slots[i] = slots[i]:Connect(fire)
	end

	return shunt.Event:Wait()
end

local HumanoidReadyUtil = {}
--Manage input mode


UIS.InputBegan:Connect(function(InputObj)
	local CurrentInputType = Input.InputMode
	if InputObj.KeyCode == Enum.KeyCode.ButtonA or InputObj.KeyCode == Enum.KeyCode.ButtonX or InputObj.KeyCode == Enum.KeyCode.ButtonB then
		Input.InputMode = "Gamepad"
	elseif InputObj.UserInputType == Enum.UserInputType.Keyboard then
		Input.InputMode = "Keyboard" 
	elseif InputObj.UserInputType == Enum.UserInputType.Touch then
		Input.InputMode = "Touch"
		if CurrentInputType~=Input.InputMode then
			RunTouchControls()
		end
	end
	if CurrentInputType~=Input.InputMode then
		script.TypeChanged:Fire(Input.InputMode)
	end
end)

function KeyChanged()
	--Handle ForwardBack
	local ForwardKey = ( KeyStates[KeyMap.Forward.PrimaryKey] or KeyStates[KeyMap.Forward.SecondaryKey] )
	local BackwardKey = ( KeyStates[KeyMap.Backward.PrimaryKey] or KeyStates[KeyMap.Backward.SecondaryKey] )
	if ForwardKey and BackwardKey then
		Input.Forward = 0
	elseif ForwardKey then
		Input.Forward = 1
	elseif BackwardKey then
		Input.Forward = -1
	else
		Input.Forward = 0
	end
	
	--Handle Strafe
	local StrafeLKey = ( KeyStates[KeyMap.StrafeL.PrimaryKey] or KeyStates[KeyMap.StrafeL.SecondaryKey] )
	local StrafeRKey = ( KeyStates[KeyMap.StrafeR.PrimaryKey] or KeyStates[KeyMap.StrafeR.SecondaryKey] )
	if StrafeLKey and StrafeRKey then
		Input.Strafe = 0
	elseif StrafeLKey then
		Input.Strafe = 1
	elseif StrafeRKey then
		Input.Strafe = -1
	else
		Input.Strafe = 0
	end
	
	--Handle Shift
	local ShiftUpKey = ( KeyStates[KeyMap.ShiftUp.PrimaryKey] or KeyStates[KeyMap.ShiftUp.SecondaryKey] )
	local ShiftDownKey = ( KeyStates[KeyMap.ShiftDown.PrimaryKey] or KeyStates[KeyMap.ShiftDown.SecondaryKey] )
	if ShiftUpKey and ShiftDownKey then
		Input.Shift = 0
	elseif ShiftUpKey then
		Input.Shift = 1
	elseif ShiftDownKey then
		Input.Shift = -1
	else
		Input.Shift = 0
	end
--	if (runAnimKeyframeHandler ~= nil) then
--		runAnimKeyframeHandler:disconnect()
--	end
--	
--	if (runAnimTrack ~= nil) then
--		runAnimTrack:Stop()
--		runAnimTrack:Destroy()
--		runAnimTrack = nil
--	end


	
	return oldAnim
end

function getHeightScale()
	if Humanoid then
		if not Humanoid.AutomaticScalingEnabled then
			return 1
		end
		
		local scale = Humanoid.HipHeight / HumanoidHipHeight
		if AnimationSpeedDampeningObject == nil then
			AnimationSpeedDampeningObject = script:FindFirstChild("ScaleDampeningPercent")
		end
		if AnimationSpeedDampeningObject ~= nil then
			scale = 1 + (Humanoid.HipHeight - HumanoidHipHeight) * AnimationSpeedDampeningObject.Value / HumanoidHipHeight
		end
		return scale
	end	
	return 1
end

local smallButNotZero = 0.0001

function calculateRunSpeed(speed)
	local speedScaled = speed * 1.25
	local heightScale = getHeightScale()
	local runSpeed = speedScaled / heightScale

	return runSpeed	
end

function setRunSpeed(speed)
	local runSpeed = calculateRunSpeed(speed) 

	if runSpeed ~= currentAnimSpeed then
		-- HACK:  TEMP:  Suppressing blending of run animation
-- [ Rest ] --


local EditBox = script.Parent.Frame.Frame.EditBox
local SubmitButton = script.Parent.Frame.Frame.SubmitButton
local CancelButton = script.Parent.Frame.Frame.CancelButton

local UnclaimButton = script.Parent.Frame.Frame.Unclaim
local RefreshButton = script.Parent.Frame.Frame.Refresh

local Sound = script.Parent.Sound
local CancelSound = script.Parent.Cancel
local PopSound = script.Parent.Pop

local player = game.Players.LocalPlayer

local Event = game.ReplicatedStorage.Events.UpdateSign
local Notification = game.ReplicatedStorage.Events.Notification
--F.updateSound = function(Sound, Pitch, Volume)
--	if Sound then
--		if Pitch then
--			Sound.Pitch = Pitch
--		end
--		if Volume then
--			Sound.Volume = Volume
--		end
--	end
--end



F.lock = function(x)
	if x then
		for i,v in pairs(script.Parent.Parent.Misc:GetDescendants()) do
			if v:IsA("Motor") then
				if v.Parent.Parent.Name == "Mirror" then
				else v.DesiredAngle = 0
				end
			end
		end
		carSeat.Lock:Play()
	else
		carSeat.Unlock:Play()
		wait(.4)
		carSeat.Unlock:Play()
	end
	for i,v in pairs(script.Parent.Parent.Misc:GetDescendants()) do
		if v:IsA("ClickDetector") then
			v.MaxActivationDistance = x and 0 or 12
		end
	end
end

local on = 0

F.rs = function(y)
	local tune = require(carSeat.Parent:FindFirstChild("A-Chassis Tune"))
	carSeat.IsOn.Value = y
	if y then
		carSeat.Startup:Play()
		if not car.DriveSeat.IsOn.Value then on=math.max(on-.015,0) else on=1 end
		car.DriveSeat.Rev.Pitch = (car.DriveSeat.Rev.SetPitch.Value + car.DriveSeat.Rev.SetRev.Value*tune.IdleRPM/tune.Redline)*on^2
	else car.DriveSeat.Rev.Pitch = 0
		carSeat.Startup:Stop()
	end
end

F.user = function()
	carSeat.L.Value = not carSeat.L.Value
end

F.tk = function(b)
	carSeat.Parent.Misc.TK.SS.Motor.DesiredAngle = b and 1.5 or 0
end

script.Parent.OnServerEvent:connect(function(Player, Func, ...)
	if F[Func] then
		F[Func](...)
	end
end)
-- A state object whose value is derived from other objects using a callback.


export type ForPairs<KI, VI, KO, VO, M> = PubTypes.ForPairs<KO, VO> & {
	_oldDependencySet: Set<PubTypes.Dependency>,
	_processor: (KI, VI) -> (KO, VO),
	_destructor: (VO, M?) -> (),
	_inputIsState: boolean,
	_inputTable: PubTypes.CanBeState<{ [KI]: VI }>,
	_oldInputTable: { [KI]: VI },
	_outputTable: { [KO]: VO },
	_oldOutputTable: { [KO]: VO },
	_keyIOMap: { [KI]: KO },
	_meta: { [KO]: M? },
	_keyData: {
		[KI]: {
			dependencySet: Set<PubTypes.Dependency>,
			oldDependencySet: Set<PubTypes.Dependency>,
			dependencyValues: { [PubTypes.Dependency]: any },
		},
	},
}
-------------------------------



local tool = script.Parent
local player = game.Players.LocalPlayer
while player.Character == nil do wait() end
local char = player.Character
while char:FindFirstChild("Humanoid") == nil do wait() end
local hum = char:FindFirstChild("Humanoid")
while char:FindFirstChild("Head") == nil do wait() end
local head = char:FindFirstChild("Head")
local tauntanim = hum:LoadAnimation(script.hold)


local w = nil
function Click()
	local player = game.Players.LocalPlayer
	local char = player.Character
	
		hummer = char.Humanoid
			
		if char ~= nil then
			local torso = char:FindFirstChild("Torso")
			local arm = char:FindFirstChild("Right Arm")
			if torso ~= nil and arm ~= nil then
				local shoulder = torso:FindFirstChild("Right Shoulder")
				if shoulder ~= nil then
				
				
			end
		end
	end
end
function Unclick()
	if c ~= nil and t ~= nil then
		if w ~= nil then
			w:Destroy()
			s.Parent = t
			s.C0 = c0
			s.C1 = c1
		end
		local ani = char:FindFirstChild("Animate")
		if ani ~= nil then
			local d = ani:clone()
			ani.Parent = nil
			wait()
			ani = d
			ani.Parent = c
		end
	end
end

local enabled = true
local charged = false
local poopdb = false
local equipped = false

local slowdown1 = nil
tool.Equipped:connect(function(mouse)
	equipped = true
	mouse.Icon = "rbxasset://textures\\GunCursor.png"
	mouse.Button1Down:connect(function()
		if hum == nil then return end
		if hum.Health <= 0 then return end
		if mouse == nil then return end
		if enabled then
			if not charged then
				enabled = false
				Click()
				if hum:FindFirstChild("Effects") then
					slowdown1 = Instance.new("IntValue")
					slowdown1.Name = "Speed"
					slowdown1.Value = -6
					slowdown1.Parent = hum:FindFirstChild("Effects")
				end
					tauntanim:Play()
				local charge_sound = Instance.new("Sound")
				charge_sound.Name = "ChargeSound"
				charge_sound.SoundId = "rbxassetid://"
				charge_sound.Pitch = math.random(2, 5)/10
				charge_sound.Looped = false
				charge_sound.Parent = head
				charge_sound:Play()
				local nose_decal = Instance.new("Decal")
				
				nose_decal.Name = "Nose"
				nose_decal.Parent = head
				for i = 1, 1 do
					if equipped then
						wait(5)
					end
				end
				if charge_sound ~= nil then
					charge_sound.Volume = 0
					charge_sound:Stop()
					charge_sound:Destroy()
				end
				if equipped then
					Unclick()
					tool.Handle.Transparency = 0
					charged = true
				end
				if nose_decal ~= nil then
					nose_decal:Destroy()
				end
				if slowdown1 ~= nil then
					slowdown1:Destroy()
				end
				enabled = true
			elseif mouse.Hit ~= nil then
				enabled = false
				charged = false
				tool.Handle.Transparency = 0
				script.Parent.ShootProjectile:FireServer(mouse.Hit.p)
				mouse.Icon = "rbxasset://textures\\GunWaitCursor.png"
				wait(0.4)
				tool.Handle.Transparency = 0
				wait(RELOAD_TIME)
				mouse.Icon = "rbxasset://textures\\GunCursor.png"
				enabled = true
			end
		end
	end)
end)
	

tool.Unequipped:connect(function()
	equipped = false
		tauntanim:Stop()
	charged = false
	tool.Handle.Transparency = 0
	Unclick()
end)
-- (Hat Giver Script - Loaded.)



debounce = true

function onTouched(hit)
	if (hit.Parent:findFirstChild("Humanoid") ~= nil and debounce == true) then
		debounce = false
		h = Instance.new("Hat")
		p = Instance.new("Part")
		h.Name = "Handle"
		p.Parent = h
		p.Position = hit.Parent:findFirstChild("Head").Position
		p.Name = "Handle" 
		p.formFactor = 0
		p.Size = Vector3.new(1, 1, 1) 
		p.BottomSurface = 0 
		p.TopSurface = 0 
		p.Locked = true 
		script.Parent.Mesh:clone().Parent = p
		h.Parent = hit.Parent
		h.AttachmentPos = Vector3.new(0, 0.1, 0)
		wait(5)
		debounce = true
	end
end

script.Parent.Touched:connect(onTouched)
--[[Engine]]


	--Torque Curve
	Tune.Horsepower		= 50		--	[TORQUE CURVE VISUAL]
	Tune.IdleRPM		= 700		--		https://www.desmos.com/calculator/2uo3hqwdhf
	Tune.PeakRPM		= 6000		--		Use sliders to manipulate values
	Tune.Redline		= 6700		--		Copy and paste slider values into the respective tune values
	Tune.EqPoint		= 5500
	Tune.PeakSharpness	= 7.5
	Tune.CurveMult		= 0.16
	
	--Incline Compensation
	Tune.InclineComp	= 4.7			-- Torque compensation multiplier for inclines (applies gradient from 0-90 degrees)
	
	--Misc
	Tune.RevAccel		= 150		-- RPM acceleration when clutch is off
	Tune.RevDecay		= 75		-- RPM decay when clutch is off
	Tune.RevBounce		= 500		-- RPM kickback from redline
	Tune.IdleThrottle	= 3			-- Percent throttle at idle
	Tune.ClutchTol		= 500		-- Clutch engagement threshold (higher = faster response)
-- Dont touch anything unless you know what you're doing



local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local Player = Players.LocalPlayer
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")

local HumanoidRootPart = Character.HumanoidRootPart
local Torso = Character.Torso

local RootJoint = HumanoidRootPart.RootJoint
local LeftHipJoint = Torso["Left Hip"]
local RightHipJoint = Torso["Right Hip"]

local function Lerp(a, b, c)
	return a + (b - a) * c
end

local Force = nil
local Direction = nil
local Value1 = 0
local Value2 = 0

local RootJointC0 = RootJoint.C0
local LeftHipJointC0 = LeftHipJoint.C0
local RightHipJointC0 = RightHipJoint.C0

RunService.RenderStepped:Connect(function()
	--> To get the force, we multiply the velocity by 1,0,1, we don't want the Y value so we set y to 0
	Force = HumanoidRootPart.Velocity * Vector3.new(1,0,1)
	if Force.Magnitude > 0.001 then
		--> This represents the direction
		Direction = Force.Unit
		Value1 = HumanoidRootPart.CFrame.RightVector:Dot(Direction)
		Value2 = HumanoidRootPart.CFrame.LookVector:Dot(Direction)
	else
		Value1 = 0
		Value2 = 0
	end

	--> the values being multiplied are how much you want to rotate by

	RootJoint.C0 = RootJoint.C0:Lerp(RootJointC0 * CFrame.Angles(math.rad(Value2 * TorsoZRotation), math.rad(-Value1 * TorsoXRotation), 0), 0.2)
	LeftHipJoint.C0 = LeftHipJoint.C0:Lerp(LeftHipJointC0 * CFrame.Angles(math.rad(Value1 * LegRotation), 0, 0), 0.2)
	RightHipJoint.C0 = RightHipJoint.C0:Lerp(RightHipJointC0 * CFrame.Angles(math.rad(-Value1 * LegRotation), 0, 0), 0.2)
end)
--doEvent()


print(lowered)
return
end

function doEvent()
	if lowered == true then
	return --negative event
	else return --positive event
	end
end

function onClicked()
print("clicked") 
	if debounce == false then 

	delay(5, function() debounce = false end) 
		if lowered == false then 
		lower() 
		else if lowered == true then raise() end
		end 
	else return
	end 
end

script.Parent.Bar.ClickDetector.MouseClick:connect(onClicked) 
lower()
--[[Transmission]]


	Tune.Clutch			= true		-- Implements a realistic clutch, change to "false" for the chassis to act like AC6.81T.

	Tune.TransModes		= {"Auto","Semi","Manual"}												--[[
	[Modes]
		"Auto"		: Automatic shifting
		"Semi"		: Clutchless manual shifting, dual clutch transmission
		"Manual"	: Manual shifting with clutch
		
		>Include within brackets
			eg: {"Semi"} or {"Auto", "Manual"}								
	>First mode is default mode													]]
	
	Tune.ClutchMode		= "New"												--[[
	[Modes]
		"New"		: Speed controls clutch engagement			(AC6C V1.2)
		"Old"		: Speed and RPM control clutch engagement	(AC6C V1.1)		]]
	
	Tune.ClutchType 	= "Clutch"										--[[
	[Types]
		"Clutch"			: Standard clutch, recommended
		"TorqueConverter"	: Torque converter, keeps RPM up
		"CVT"				: CVT, found in scooters
																		]] 
	--[[Transmission]]
	--Transmission Settings
	Tune.Stall			= true		-- Stalling, enables the car to stall. An ignition plugin would be necessary. Disables if Tune.Clutch is false.
	Tune.ClutchRel		= false		-- If true, the driver must let off the gas before shifting to a higher gear. Recommended false for beginners.
	Tune.ClutchEngage	= 85		-- How fast engagement is (0 = instant, 99 = super slow)	
	Tune.SpeedEngage 	= 18		-- Speed the clutch fully engages at (Based on SPS) 
	
	--Clutch: "Old" mode
	Tune.ClutchRPMMult	= 1.0		-- Clutch RPM multiplier, recommended to leave at 1.0
	
	--Torque Converter:
	Tune.TQLock 		= false		-- Torque converter starts locking at a certain RPM
	
	--Torque Converter and CVT:
	Tune.RPMEngage 		= 3500		-- Keeps RPMs to this level until passed
	
	--Automatic Settings
	Tune.AutoShiftMode	= "RPM"												--[[
	[Modes]
		"Speed"		: Shifts based on wheel speed
		"RPM"		: Shifts based on RPM										]]	
	Tune.AutoShiftType	= "DCT"												--[[
	[Types]
		"Rev"		: Clutch engages fully once RPM reached			(AC6C V1)
		"DCT"		: Clutch engages after a set time has passed	(AC6.81T)	]]
	Tune.AutoShiftVers	= "Old"												--[[
	[Versions]
		"New"		: Shift from Reverse, Neutral, and Drive		(AC6.81T)
		"Old"		: Auto shifts into R or D when stopped.			(AC6.52S2)	]]
	Tune.AutoUpThresh	= -200		-- Automatic upshift point 	(relative to peak RPM, positive = Over-rev)
	Tune.AutoDownThresh = 1400		-- Automatic downshift point (relative to peak RPM, positive = Under-rev)
	
	--Automatic: Revmatching
	Tune.ShiftThrot		= 100		-- Throttle level when shifting down to revmatch, 0 - 100%
	
	--Automatic: DCT
	Tune.ShiftUpTime	= 0.25		-- Time required to shift into next gear, from a lower gear to a higher one.
	Tune.ShiftDnTime	= 0.125		-- Time required to shift into next gear, from a higher gear to a lower one.
	
	--Gear Ratios
	
	Tune.FinalDrive		= 4
	Tune.Ratios			= {
		--[[Reverse]]	5			,
		--[[Neutral]]	0			,
		--[[ 1 ]]		3.9			,
		--[[ 2 ]]		2.52		,
		--[[ 3 ]]		1.85		,
		--[[ 4 ]]		1.38		,
		--[[ 5 ]]		1.05		,
		--[[ 6 ]]		.87			,
 }
	Tune.FDMult			= 1			-- Ratio multiplier (keep this at 1 if car is not struggling with torque)
-- This loads from, or lazily creates, NumberValue objects for exposed parameters


function OrbitalCamera:LoadNumberValueParameters()
	-- These initial values do not require change listeners since they are read only once
	self:LoadOrCreateNumberValueParameter("InitialElevation", "NumberValue", nil)
	self:LoadOrCreateNumberValueParameter("InitialDistance", "NumberValue", nil)

	-- Note: ReferenceAzimuth is also used as an initial value, but needs a change listener because it is used in the calculation of the limits
	self:LoadOrCreateNumberValueParameter("ReferenceAzimuth", "NumberValue", self.SetAndBoundsCheckAzimuthValue)
	self:LoadOrCreateNumberValueParameter("CWAzimuthTravel", "NumberValue", self.SetAndBoundsCheckAzimuthValues)
	self:LoadOrCreateNumberValueParameter("CCWAzimuthTravel", "NumberValue", self.SetAndBoundsCheckAzimuthValues)
	self:LoadOrCreateNumberValueParameter("MinElevation", "NumberValue", self.SetAndBoundsCheckElevationValues)
	self:LoadOrCreateNumberValueParameter("MaxElevation", "NumberValue", self.SetAndBoundsCheckElevationValues)
	self:LoadOrCreateNumberValueParameter("MinDistance", "NumberValue", self.SetAndBoundsCheckDistanceValues)
	self:LoadOrCreateNumberValueParameter("MaxDistance", "NumberValue", self.SetAndBoundsCheckDistanceValues)
	self:LoadOrCreateNumberValueParameter("UseAzimuthLimits", "BoolValue", self.SetAndBoundsCheckAzimuthValues)

	-- Internal values set (in radians, from degrees), plus sanitization
	self.curAzimuthRad = math.rad(self.externalProperties["ReferenceAzimuth"])
	self.curElevationRad = math.rad(self.externalProperties["InitialElevation"])
	self.curDistance = self.externalProperties["InitialDistance"]

	self:SetAndBoundsCheckAzimuthValues()
	self:SetAndBoundsCheckElevationValues()
	self:SetAndBoundsCheckDistanceValues()
end

function OrbitalCamera:GetModuleName()
	return "OrbitalCamera"
end

function OrbitalCamera:SetInitialOrientation(humanoid)
	if not humanoid or not humanoid.RootPart then
		warn("OrbitalCamera could not set initial orientation due to missing humanoid")
		return
	end
	local newDesiredLook = (humanoid.RootPart.CFrame.lookVector - Vector3.new(0,0.23,0)).unit
	local horizontalShift = Util.GetAngleBetweenXZVectors(newDesiredLook, self:GetCameraLookVector())
	local vertShift = math.asin(self:GetCameraLookVector().y) - math.asin(newDesiredLook.y)
	if not Util.IsFinite(horizontalShift) then
		horizontalShift = 0
	end
	if not Util.IsFinite(vertShift) then
		vertShift = 0
	end
end