I can't cancel an animation on key press?

Hi guys!

I having a bit of an issue here. (pretty new to lua)
I’m modifying a cigarette script by KexetV2 - credit

I am trying to:-

  1. Make the Ped smoke for 30 seconds and then throw it away if no buttons are pressed. (This is working)
RegisterNetEvent('esx_cigarette:startSmoke')
AddEventHandler('esx_cigarette:startSmoke', function(source)
	SmokeAnimation()
end)

function SmokeAnimation()
	local playerPed = GetPlayerPed(-1)
	
	Citizen.CreateThread(function()
        TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_SMOKING", 0, true)
		Citizen.Wait(30000)
		ClearPedTasks(playerPed)
	end)
end
  1. Cut the cigarette short and throw it away if the “TIDLE” (`/~) button is pressed.

Here is my attempt with both.

RegisterNetEvent('esx_cigarette:startSmoke')
AddEventHandler('esx_cigarette:startSmoke', function(source)
	SmokeAnimation()
end)

function SmokeAnimation()
	local playerPed = GetPlayerPed(-1)
	
	Citizen.CreateThread(function()
        TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_SMOKING", 0, true)
		Citizen.Wait(30000)
		ClearPedTasks(playerPed)

		if IsControlJustPressed(0, 243) then
			Citizen.Wait(0)
			ClearPedTasks(playerPed)
		end
	end
end

Any help would be greatly appreciated, I have been trying to figure this out for hours :slight_smile: Thanks guys!

Hello,
First of all you’ll need to put your code in a while loop. (btw you forgot a “)” in your thread next to the “end”)

local smoking = false

RegisterNetEvent('esx_cigarette:startSmoke')
AddEventHandler('esx_cigarette:startSmoke', function(source)
	SmokeAnimation()
    smoking = not smoking 
end)

Citizen.CreateThread(function()
    while smoking do
        Citizen.Wait(1)
        -- Do stuff
    end
end)

Quick suggest add a bool to deal with the smoking part. Like I did just up there ↑
The main issue here is that you are using Citizen.Wait wich stop the code there for 30 sec so it won’t do anything. Quick fix, you could use is

Citizen.SetTimeout(30000, function()
 -- Will do stuff here after 30 sec and won't interrupt script
end)

Hope this help

Hey man! Thank you so much!
I’ll give this a try in the morning! I appreciate it.

I was actually trying to use like that smoking variable like you did but i couldnt get it to work (because i dont understand lua well enough)

I’ll let you know how i go!

1 Like

So I still can’t get it to work, Here is my attempt but maybe I’m not understand it properly.
Where am I calling the actions when the animation is happening?

Sorry if i completely misunderstood, and thanks again for your help!

What I tried:

local smoking = false
local playerPed = GetPlayerPed(-1)

RegisterNetEvent('esx_cigarette:startSmoke')
AddEventHandler('esx_cigarette:startSmoke', function(source)
	SmokeAnimation()
    smoking = not smoking 
end)

Citizen.CreateThread(function()
    while smoking do
        Citizen.Wait(1)
        TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_SMOKING", 0, true)
		Citizen.SetTimeout(30000, function()
			if IsControlJustPressed(0, 243) then
				Citizen.Wait(1)
				ClearPedTasks(playerPed)
			end
		end)
		ClearPedTasks(playerPed)
    end
end)```

This is as far as i can get with the animation still working. (smoking for 30 secs, stress is removed at the end and the ped throws the cigarette away.

CLIENT SIDE

ESX = nil

Citizen.CreateThread(function()
	while ESX == nil do
		TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
		Citizen.Wait(0)
	end
end)

RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer)
  PlayerData = xPlayer
end)

-----

RegisterNetEvent('esx_cigarette:startSmoke')
AddEventHandler('esx_cigarette:startSmoke', function(source)
	SmokeAnimation()
end)

function SmokeAnimation()
	local playerPed = GetPlayerPed(-1)
	
	Citizen.CreateThread(function()
        TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_SMOKING", 0, true)
		Citizen.SetTimeout(30000, function()
		ClearPedTasks(playerPed)
		
		end)
	end)
end

SERVER SIDE

ESX  = nil

TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)

ESX.RegisterUsableItem('cigarette', function(source)
    local xPlayer = ESX.GetPlayerFromId(source)
    xPlayer.removeInventoryItem('cigarette', 1)

    TriggerClientEvent('esx_cigarette:startSmoke', source)
    Wait(30000)
    TriggerClientEvent('esx_status:remove', source, 'stress', 250000)
    xPlayer.showNotification(_U('used_cigarette'))
end)

Hello @JamieRedHands
The code you have is working but not optimal. You are doing a wait in the client as well as the server. So decide on either one. I would suggest the client as the server is only needed in removing the item. So just remove the wait(30000) in the server and copy over the event call and the notification. (Note that in client its called TriggerEvent now instead of TriggerClientEvent. You also must not hand over the source, as you are the source then.)

You said you wanted to do something additionally inside the client while smoking?

function SmokeAnimation()
	local playerPed = GetPlayerPed(-1)
        local smoking = true
        while smoking do
        Citizen.Wait(1)
          if IsControlJustPressed(0, 243) then
             ClearPedTasks(playerPed)
             smoking = false
          end
        end
	
	Citizen.CreateThread(function()
        TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_SMOKING", 0, true)
		Citizen.SetTimeout(30000, function()
		ClearPedTasks(playerPed)
		smoking=false
                   -- call TriggerEvent remove status and show notification. Best inside new function, to also use in while loop above
		end)
	end)
end

This will listen for a keypress of 243 while smoking and end the smoking. You can also do what ever you want in this while loop.

Hi @Dvergar,

Thanks for helping me out!

I’ll try explain why I have the Wait in server.lua

What I am trying to do, is only remove the 25% stress if the player waits out the 30secs to finish.

Even better would be like 5% stress removal every 5-10 seconds, I hope I explained that okay.

I’m going to try get it working with your advice now!

Unfortunately this way, the animation doesn’t play at all, not sure what I did wrong. (Sorry if I’ve done something silly, still new to coding)

RegisterNetEvent('esx_cigarette:startSmoke')
AddEventHandler('esx_cigarette:startSmoke', function(source)
	SmokeAnimation()
end)

function SmokeAnimation()
	local playerPed = GetPlayerPed(-1)
		local smoking = true
		while smoking do
			Citizen.Wait(1)
			if IsControlJustPressed(0, 243) then
				ClearPedTasks(playerPed)
             	smoking = false
			end
		end
	
	Citizen.CreateThread(function()
        TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_SMOKING", 0, true)
		Citizen.SetTimeout(30000, function()
		ClearPedTasks(playerPed)
		smoking = false

		end)
	end)
end

Okay, yeah. Kind of my fault :wink:
Since we are using a while loop we have to surround it with a new thread. Otherwise it will be stuck in this while and wait “forever” or until you pressed 243

RegisterNetEvent('esx_cigarette:startSmoke')
AddEventHandler('esx_cigarette:startSmoke', function(source)
	SmokeAnimation()
end)

function SmokeAnimation()
	local playerPed = GetPlayerPed(-1)
		local smoking = true
Citizen.CreateThread(function()
		while smoking do
			Citizen.Wait(1)
			if IsControlJustPressed(0, 243) then
				ClearPedTasks(playerPed)
             	smoking = false
			end
		end
end)
	
	Citizen.CreateThread(function()
        TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_SMOKING", 0, true)
		Citizen.SetTimeout(30000, function()
		ClearPedTasks(playerPed)
		smoking = false
                 -- remove stress here. The user waited the full 30 sec and never canceled animation
		end)
	end)
end

If you want to remove 5% stress every x seconds you will need to create a new Thread and insert a new while with the wait x seconds. Bind the while smoking variable. So while you are smoking remove y% stress per x seconds.
Also remember to not remove 25% on finish as this would be doubled.