[Standalone] Crutches

Hm… Been trying to figure this out for a while now, which server artifacts are you on? And do you have any hospital MLO’s on your server?

@MadsL I am trying to add this as a command within fv-menu would you be able to help me out to what I have to put here in this line of code
image

I presume that functionName is the name of the event that will get trigger. If that’s the case then you’ll have to add an event to the client.lua file in the crutches script.

In your case it would look something like this:

AddEventHandler('crutches:crutch', function()
    ToggleCrutch()
end)

Sorry didn’t see this - am on server artifact 5539 and build 2545 (The Contract DLC)

Has anyone managed to get this working as an item for QB so far?

I followed the steps and get the item but nothing happens when used, command works fine but I’d much rather include this as an item for Paramedics to give to patients with no need of using the command.

is there anyway i could make it so that when a player is sent to the hospital and is “revived” the automatically have the crutch on for say… 10 minutes?

Hm… I’m unsure, I’ve been thinking that maybe it has something to do with some people not having any hospitals loaded making the crutch model not loading as it should. But again I think it should’ve worked regardless, I’m just kinda confused at this point.

You could make them auto-equip the crutch after they are revived at the hospital. If you want to force it on them for 10 minutes, you could just add a variable that prohibits the player from removing the crutch. And then make that variable be set to true when they get revived at the hospital and that has a 10-minute wait before it is set to false again.

could you give me an example?

how do i make it to where ems can put the crutch on players for a set amount of time

1 Like

yeah how would we do that for qbcore?

Okey, so for everybody who wants to force this on players for x amount of time, here is one way to do it:

Add these variables at the top of the script under “-- Variables --”

local forceEquipped = false
local endForceTime = 0

Change the ToggleCrutch function to look like this:

local function ToggleCrutch()
	if isUsingCrutch then
		if forceEquipped then
			DisplayNotification("You need to use the Crutch for a little longer!")
			return
		end
		UnequipCrutch()
	else
		EquipCrutch()
	end
end

Then add this timer function under the ToggleCrutch function.

local function StartForcedTimer(time)
	Citizen.CreateThread(function()
		endForceTime = GetGameTimer() + time * 1000

		while true do
			Citizen.Wait(1000)
			if endForceTime < GetGameTimer() then
				break
			end
		end

		forceEquipped = false
	end)
end

And then last but not least add a way for the crutch to be added from external scripts like so:

-- Events --
-- Time is in seconds
AddEventHandler('crutches:forceEquip', function(state, time)
	forceEquipped = state
	if forceEquipped then
		if not isUsingCrutch then
			EquipCrutch()
		end
		StartForcedTimer(time)
	end
end)

In the end, your file should look something like this:

client.lua
-- Config --
local crutchModel = -1035084591 -- v_med_crutch01
local clipSet = "move_lester_CaneUp"
local pickupAnim = {
	dict = "pickup_object",
	name = "pickup_low"
}

local localization = {
	['ragdoll'] = "You can't use a crutch while you are in ragdoll!",
	['falling'] = "You can't use a crutch while you are falling!",
	['combat'] = "You can't use a crutch while you are in combat!",
	['dead'] = "You can't use a crutch while you are dead!",
	['vehicle'] = "You can't use a crutch while you are in a vehicle!",
	['weapon'] = "You can't use a crutch while having a weapon out!",
	['pickup'] = "Press ~INPUT_PICKUP~ to pick up your crutch!"
}

-- Variables --
local isUsingCrutch = false
local crutchObject = nil
local walkStyle = nil
local forceEquipped = false
local endForceTime = 0

-- Functions --
local function LoadClipSet(set)
	RequestClipSet(set)
	while not HasClipSetLoaded(set) do
		Citizen.Wait(10)
	end
end

local function LoadAnimDict(dict)
	RequestAnimDict(dict)
	while not HasAnimDictLoaded(dict) do
		Citizen.Wait(10)
	end
end

local function DisplayNotification(msg)
	BeginTextCommandThefeedPost("STRING")
	AddTextComponentSubstringPlayerName(msg)
	EndTextCommandThefeedPostTicker(false, false)
end

local function DisplayHelpText(msg)
	BeginTextCommandDisplayHelp("STRING")
	AddTextComponentSubstringPlayerName(msg)
	EndTextCommandDisplayHelp(0, false, true, 50)
end

local function CreateCrutch()
	if not HasModelLoaded(crutchModel) then
		RequestModel(crutchModel)
		while not HasModelLoaded(crutchModel) do
			Citizen.Wait(10)
		end
	end
	local playerPed = PlayerPedId()
	crutchObject = CreateObject(crutchModel, GetEntityCoords(playerPed), true, false, false)
	AttachEntityToEntity(crutchObject, playerPed, 70, 1.18, -0.36, -0.20, -20.0, -87.0, -20.0, true, true, false, true, 1, true)
end

local function CanPlayerEquipCrutch()
	local playerPed = PlayerPedId()
	local hasWeapon, weaponHash = GetCurrentPedWeapon(playerPed, true)

	if hasWeapon then
		return false, localization['weapon']
	elseif IsPedInAnyVehicle(playerPed, false) then
		return false, localization['vehicle']
	elseif IsEntityDead(playerPed) then
		return false, localization['dead']
	elseif IsPedInMeleeCombat(playerPed) then
		return false, localization['combat']
	elseif IsPedFalling(playerPed) then
		return false, localization['falling']
	elseif IsPedRagdoll(playerPed) then
		return false, localization['ragdoll']
	end
	return true
end

local function UnequipCrutch()
	if DoesEntityExist(crutchObject) then
		DeleteEntity(crutchObject)
	end

	isUsingCrutch = false
	local playerPed = PlayerPedId()
	
	if walkStyle then
		LoadClipSet(walkStyle)
		SetPedMovementClipset(playerPed, walkStyle, 1.0)
		RemoveClipSet(walkStyle)
	else
		ResetPedMovementClipset(playerPed, 1.0)
	end
end

local function EquipCrutch()
	local playerPed = PlayerPedId()
	local canEquip, msg = CanPlayerEquipCrutch()
	if not canEquip then
		DisplayNotification(msg)
		return
	end

	LoadClipSet(clipSet)
	SetPedMovementClipset(playerPed, clipSet, 1.0)
	RemoveClipSet(clipSet)

	CreateCrutch()
	isUsingCrutch = true

	Citizen.CreateThread(function()
		local fallCount = 0

		while true do
			Citizen.Wait(250)
			if not isUsingCrutch then
				break
			end

			local playerPed = PlayerPedId()
			local isCrutchHidden = false
			local hasWeapon, weaponHash = GetCurrentPedWeapon(playerPed, true)

			if IsPedInAnyVehicle(playerPed, true) or hasWeapon then
				if not isCrutchHidden then
					isCrutchHidden = true
					if DoesEntityExist(crutchObject) then
						DeleteEntity(crutchObject)
					end
				end
			elseif not DoesEntityExist(crutchObject) then
				Citizen.Wait(750)
				CreateCrutch()
				isCrutchHidden = false
			elseif not IsEntityAttachedToEntity(crutchObject, playerPed) then
				local traceObject = true
				while traceObject do
					local wait = 0
					if DoesEntityExist(crutchObject) then
						playerPed = PlayerPedId()
						if not IsPedFalling(playerPed) and not IsPedRagdoll(playerPed) then
							local dist = #(GetEntityCoords(playerPed)-GetEntityCoords(crutchObject))
							if dist < 2.0 then
								DisplayHelpText(localization['pickup'])
								if IsControlJustReleased(0, 38) then
									LoadAnimDict(pickupAnim.dict)
									TaskPlayAnim(playerPed, pickupAnim.dict, pickupAnim.name, 2.0, 2.0, -1, 0, 0, false, false, false)

									local failCount = 0
									while not IsEntityPlayingAnim(playerPed, pickupAnim.dict, pickupAnim.name, 3) and failCount < 25 do
										failCount = failCount + 1
										Citizen.Wait(50)
									end
									if failCount >= 25 then
										ClearPedTasks(playerPed)
									else
										Citizen.Wait(800)
									end

									RemoveAnimDict(pickupAnim.dict)
									DeleteEntity(crutchObject)
									Citizen.Wait(900)
									CreateCrutch()
									traceObject = false
								end
							elseif dist < 200.0 then
								wait = dist * 10
							else
								traceObject = false
							end
						else
							wait = 250
						end
					else
						traceObject = false
					end
					Citizen.Wait(wait)
				end
			elseif IsPedRagdoll(playerPed) or IsEntityDead(playerPed) then
				DetachEntity(crutchObject, true, true)
			elseif IsPedInMeleeCombat(playerPed) then
				Citizen.Wait(400)
				DetachEntity(crutchObject, true, true)
			elseif IsPedFalling(playerPed) then
				fallCount = fallCount + 1
				if fallCount > 3 then
					DetachEntity(crutchObject, true, true)
					fallCount = 0
				end
			elseif fallCount > 0 then
				fallCount = fallCount - 1
			end
		end
	end)
end

local function ToggleCrutch()
	if isUsingCrutch then
		if forceEquipped then
			DisplayNotification("You need to use the Crutch for a little longer!")
			return
		end
		UnequipCrutch()
	else
		EquipCrutch()
	end
end

local function StartForcedTimer(time)
	Citizen.CreateThread(function()
		endForceTime = GetGameTimer() + time * 1000

		while true do
			Citizen.Wait(1000)
			if endForceTime < GetGameTimer() then
				break
			end
		end

		forceEquipped = false
	end)
end

-- Exports --
exports('SetWalkStyle', function(walk)
	walkStyle = walk
end)

-- Commands --
RegisterCommand("crutch", function(source, args, rawCommand)
	ToggleCrutch()
end, false)

-- Events --
-- Time is in seconds
AddEventHandler('crutches:forceEquip', function(state, time)
	forceEquipped = state
	if forceEquipped then
		if not isUsingCrutch then
			EquipCrutch()
		end
		StartForcedTimer(time)
	end
end)

Then, all you would have to do is to add this to your revive script if you want to force them to have it for 10 minutes:

TriggerEvent('crutches:forceEquip', true, 600)

600 seconds = 10 minutes.

I hope that helps for everyone who was wondering.

2 Likes

how would u make this a command like /crutches playerid time

One way could be to do it like this in a server file:

RegisterCommand("crutches", function(source, args, rawCommand)
	local playerId = args[1]
	local time = args[2]

	if playerId == nil then
		TriggerClientEvent('chat:addMessage', source, { args = { 'PlayerId was invalid' } })
		return
	else
		playerId = tonumber(playerId)
	end

	if time == nil then
		TriggerClientEvent('chat:addMessage', source, { args = { 'Time was invalid' } })
		return
	else
		time = tonumber(time)
	end

	TriggerClientEvent('crutches:forceEquip', playerId, true, time)
end, true)

The command above is supposedly restricted, make sure that is true before your roll that out on a live server.

You would have to add a server-side file for the script since the script doesn’t have any server files by default. Alternatively, you could put it in an admin resource or similar.

For chat suggestions you could do it like this (client side):

TriggerEvent('chat:addSuggestion', '/crutches', 'force crutches on somebody', {
    { name="id", help="the player id" },
    { name="time", help="the amount of time in seconds" }
})

I forgot to include one more thing how would u make the command work for a certain job?

1 Like

How do i make it where only players with the ambulance job can put the crutch on players

hell yeah definetly for qbcore

Would you ever offer a paid version that makes ems revive people with the crutches? would definitely be willing to pay for that

How would i fix this?
image

at the end of a command there is either an “end, true)” or an “end, false)”. true means it’s restricted and you’ll have to give ace permissions to people/groups to use it. false means anyone can use it.

So if you want to allow anyone to use it just change it to false, else you’ll have to add ace permissions.