Jump to content

kill timer table?


Recommended Posts

Hello, i just want to know if my code is correct,

this is serverside, I created a timer table so if a player leaves the zone the others timer and explosions wont stop, only his, is my code correct or im doing things really wrong?

local areaex = createColRectangle ( 2076.61499, 971.57928, 50, 50)
local arearadar = createRadarArea ( 2076.61499, 971.57928, 50, 50, 0, 255, 0, 100)
local timers = { }; 

function enterZone(hitPlayer) 
if isElement(hitPlayer) and getElementType(hitPlayer) == "player" then 
    outputChatBox("Entering zone",hitPlayer, 255, 0, 0)
    local pX, pY, pZ = getElementPosition ( hitPlayer )
    timers[ hitPlayer ] =  setTimer ( function()
createExplosion ( pX+math.random(-30,30), pY, pZ, 6, source )
	end, 3000, 0 )
end
end
addEventHandler( "onColShapeHit", areaex, enterZone ) 
  
function leaveZone(hitPlayer) 
if isElement(hitPlayer) and getElementType(hitPlayer) == "player" then 
    outputChatBox("leaving",hitPlayer)
    killTimer( timers[ hitPlayer ] );
end
end 
addEventHandler( "onColShapeLeave", areaex, leaveZone ) 
Link to post

It seems fine to me. As long as it works fine you should not worry about it.
You could only add a check if the timer exists and then kill it.

if isTimer(timers[hitPlayer]) then
	killTimer(timers[hitPlayer]);
end


IF IT AIN'T BROKE, DON'T FIX IT

Link to post

it works but i haven't tested it with players yet, im just not sure if it would kill other player's timers anyway can u help me with this code,

i put locations in the table that there would be a random nearby explosion around the player so i made these the problem is I dont know how to make it work as i want to since i made a loop that a certain explosion would happen but it only happens on 1 place, and i'm aware of that, the real problem is idk how to make all locations in the table be in the createExplosion randomly, it just picks one location in the table and it repeats, how to solve that?

function enterZone(hitPlayer) 
if isElement(hitPlayer) and getElementType(hitPlayer) == "player" then 
local pX, pY, pZ = getElementPosition ( hitPlayer )
local locations = { 
      { pX, pY, pZ },
      { pX+30, pY+60, pZ}, 
      { pX+60, pY, pZ }
} 
    loc = math.random(#locations) 
    timers[ hitPlayer ] =  setTimer ( function()
createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, hitPlayer )
	end, 5000, 0 )
end
end
addEventHandler( "onColShapeHit", areaex, enterZone ) 

 

Edited by Shaman123
Link to post

You have to put the math.random line inside the timer function. This way everytime the timer executes the function it will generate random number and then the explosions will be at random locations.

timers[ hitPlayer ] =  setTimer ( function()
	loc = math.random(#locations) 
	createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, hitPlayer )
end, 5000, 0 )


About the kill timers it will kill only the specified player's timer. The other timers (for the other players) will stay untouched.

Edited by SpecT
Link to post
51 minutes ago, SpecT said:

You have to put the math.random line inside the timer function. This way everytime the timer executes the function it will generate random number and then the explosions will be at random locations.




timers[ hitPlayer ] =  setTimer ( function()
	loc = math.random(#locations) 
	createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, hitPlayer )
end, 5000, 0 )


About the kill timers it will kill only the specified player's timer. The other timers (for the other players) will stay untouched.

and last, how do i create a timer within a timer?

I tried but its hard i created another table for the timer 2, and it kinda works, but idk if thats well optimized, the problem is i want to kill the timer2 after 5 seconds its been going on, how do I do that?

timers[ hitPlayer ] =  setTimer ( function()
timer2[ hitPlayer ] = setTimer(function()
	loc = math.random(#locations) 
	createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, hitPlayer )
end, 1500, 0)
end, 10000, 0 )
end
end
addEventHandler( "onColShapeHit", areaex, enterZone ) 

EDIT: i did this, is this fine? it works kinda fine but i want u to take a look if its really okay, edit again: nvm this is buggy, im having a hard time killing timer2, i executed it , but timer 3 is looping as well.

local timers = { }; 
local timer2 = { }; 
local timer3= { }; 

function enterZone(hitPlayer) 
if isElement(hitPlayer) and getElementType(hitPlayer) == "player" then 
    outputChatBox("enter",hitPlayer, 255, 0, 0)
timers[ hitPlayer ] =  setTimer ( function()
outputChatBox("started", hitPlayer, 255, 0, 0)
timer2[ hitPlayer ] = setTimer ( function()
local pX, pY, pZ = getElementPosition ( hitPlayer )
local locations = { 
      { pX+20, pY, pZ },
      { pX+30, pY, pZ}, 
      { pX+30, pY+20, pZ}, 
      { pX, pY+35, pZ}, 
      { pX, pY+40, pZ}, 
      { pX+60, pY, pZ }
} 
	loc = math.random(#locations) 
	createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, hitPlayer )
timer3[hitPlayer] = setTimer(function()
if isTimer(timer2[hitPlayer]) then
killTimer(timer2[hitPlayer])
outputChatBox("ended", hitElement, 0, 255, 0)
end
end, 5000, 1)
end, 2000, 0 )
end, 12000, 0 )
end
end
addEventHandler( "onColShapeHit", areaex, enterZone ) 

 

Edited by Shaman123
Link to post
37 minutes ago, Shaman123 said:

and last, how do i create a timer within a timer?

I tried but its hard i created another table for the timer 2, and it kinda works, but idk if thats well optimized, the problem is i want to kill the timer2 after 5 seconds its been going on, how do I do that?



timers[ hitPlayer ] =  setTimer ( function()
timer2[ hitPlayer ] = setTimer(function()
	loc = math.random(#locations) 
	createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, hitPlayer )
end, 1500, 0)
end, 10000, 0 )
end
end
addEventHandler( "onColShapeHit", areaex, enterZone ) 

EDIT: i did this, is this fine? it works kinda fine but i want u to take a look if its really okay, edit again: nvm this is buggy, im having a hard time killing timer2, i executed it , but timer 3 is looping as well.



local timers = { }; 
local timer2 = { }; 
local timer3= { }; 

function enterZone(hitPlayer) 
if isElement(hitPlayer) and getElementType(hitPlayer) == "player" then 
    outputChatBox("enter",hitPlayer, 255, 0, 0)
timers[ hitPlayer ] =  setTimer ( function()
outputChatBox("started", hitPlayer, 255, 0, 0)
timer2[ hitPlayer ] = setTimer ( function()
local pX, pY, pZ = getElementPosition ( hitPlayer )
local locations = { 
      { pX+20, pY, pZ },
      { pX+30, pY, pZ}, 
      { pX+30, pY+20, pZ}, 
      { pX, pY+35, pZ}, 
      { pX, pY+40, pZ}, 
      { pX+60, pY, pZ }
} 
	loc = math.random(#locations) 
	createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, hitPlayer )
timer3[hitPlayer] = setTimer(function()
if isTimer(timer2[hitPlayer]) then
killTimer(timer2[hitPlayer])
outputChatBox("ended", hitElement, 0, 255, 0)
end
end, 5000, 1)
end, 2000, 0 )
end, 12000, 0 )
end
end
addEventHandler( "onColShapeHit", areaex, enterZone ) 

 

update: here first loop is fine, works fine, but when the second loop comes,  timer1 starts, timer2 starts, then is ended instantly by timer 3. no delays how is that?, nvm i get it now, because i had put the timer3 on loop as well, on the timer2, so it gives multiple timer3s, how can i fix this? or how can i put the timer3 out of timer2 then if timer2 starts, it starts too. 

Edited by Shaman123
Link to post
  • Moderators
2 hours ago, Shaman123 said:

how can i fix this? or how can i put the timer3 out of timer2 then if timer2 starts, it starts too. 

 

Recommendation: It is best do not nest timer functions.

Just create new named functions outside:

local timers = {}

--[[
if not timers[hitPlayer] then
	timers[hitPlayer] = setTimer(stage1, 3000, 1, hitPlayer)
end
]]

function stage1 (hitPlayer)
	timers[hitPlayer] = setTimer(stage2, 3000, 1, hitPlayer)
end

function stage2 (hitPlayer)
	timers[hitPlayer] = setTimer(stage3, 3000, 1, hitPlayer)
end

function stage3 (hitPlayer)
	timers[hitPlayer] = nil
end

function stopStageTimer (player)
	if timers[ player ] then
		if isTimer(timers[ player ] ) then
			killTimer(timers[ player ] )
		end
		timers[ player ] = nil
	end
end
addCommandHandler("stopTimer", stopStageTimer)

 

If your code works in stages, adding more timer tables will create more complexity. It is best to use 1 single timer table for all stages.

 


 

Especially when you do this:

end, 2000, 0 ) end, 12000, 0 )

This combo can kill your server at a given moment.

Never create an infinity timer inside of another infinity timer. It will just multiply.

Even if you create something that will prevent this inside of the function. > If there is an error inside the most inner function, the function will stop and it is not prevented any more.

 


 

The following code can be used for:

  • Stopping a timer
  • Prevent double timers
if timer2[ hitPlayer ] then
	if isTimer(timer2[ hitPlayer ] ) then
		killTimer(timer2[ hitPlayer ] )
	end
	timer2[ hitPlayer ] = nil
end

 

 

 

 

 

 

 

 

 

Link to post
2 hours ago, IIYAMA said:

 

Recommendation: It is best do not nest timer functions.

Just create new named functions outside:



local timers = {}

--[[
if not timers[hitPlayer] then
	timers[hitPlayer] = setTimer(stage1, 3000, 1, hitPlayer)
end
]]

function stage1 (hitPlayer)
	timers[hitPlayer] = setTimer(stage2, 3000, 1, hitPlayer)
end

function stage2 (hitPlayer)
	timers[hitPlayer] = setTimer(stage3, 3000, 1, hitPlayer)
end

function stage3 (hitPlayer)
	timers[hitPlayer] = nil
end

function stopStageTimer (player)
	if timers[ player ] then
		if isTimer(timers[ player ] ) then
			killTimer(timers[ player ] )
		end
		timers[ player ] = nil
	end
end
addCommandHandler("stopTimer", stopStageTimer)

 

If your code works in stages, adding more timer tables will create more complexity. It is best to use 1 single timer table for all stages.

 


 

Especially when you do this:

end, 2000, 0 ) end, 12000, 0 )

This combo can kill your server at a given moment.

Never create an infinity timer inside of another infinity timer. It will just multiply.

Even if you create something that will prevent this inside of the function. > If there is an error inside the most inner function, the function will stop and it is not prevented any more.

 


 

The following code can be used for:

  • Stopping a timer
  • Prevent double timers


if timer2[ hitPlayer ] then
	if isTimer(timer2[ hitPlayer ] ) then
		killTimer(timer2[ hitPlayer ] )
	end
	timer2[ hitPlayer ] = nil
end

 

 

 

 

 

 

 

function stage3 (hitPlayer)
	timers[hitPlayer] = nil
end

Thanks for these, i got an idea now, and btw

the stage3 is where it stops the timer right? and as i'm aware it'll only stop for the player right? not all of them. 

Edited by Shaman123
  • Like 1
Link to post
  • Moderators
5 minutes ago, Shaman123 said:

the stage3 is where it stops the timer right? and as i'm aware it'll only stop for the player right? not all of them. 

That is correct.

But it stops by itself, since it only runs 1x. (0= infinity)

setTimer(stage3, 3000, 1, hitPlayer)

In stage3 there is only a clean up for the value in the table.

Edited by IIYAMA
Link to post
18 minutes ago, IIYAMA said:

That is correct.

But it stops by itself, since it only runs 1x. (0= infinity)

setTimer(stage3, 3000, 1, hitPlayer)

In stage3 there is only a clean up for the value in the table.

function leaveZone(hitPlayer) 
if isElement(hitPlayer) and getElementType(hitPlayer) == "player" then 
if timers[ hitPlayer ] then
   if isTimer(timers[ hitPlayer ] ) then
	   killTimer(timers[ hitPlayer ] )
         outputChatBox("leaving",hitPlayer)
      end
    end 
  end
end
addEventHandler( "onColShapeLeave", areaex, leaveZone ) 

Player leaves Colshape, all timers in the timertable will be killed. is this correct? (only his timers, not others)

Edited by Shaman123
Link to post
  • Moderators
10 minutes ago, Shaman123 said:

Player leaves Colshape, all timers in the timertable will be killed. is this correct? (only his timers, not others)

That is correct.

But don't forget to clean up:

if timers[ hitPlayer ] then
	if isTimer(timers[ hitPlayer ] ) then
		killTimer(timers[ hitPlayer ] )
		outputChatBox("leaving",hitPlayer)
	end
	timers[ hitPlayer ] = nil -- clean up
end 
  

 

 

Link to post
3 minutes ago, IIYAMA said:

That is correct.

But don't forget to clean up:


if timers[ hitPlayer ] then
	if isTimer(timers[ hitPlayer ] ) then
		killTimer(timers[ hitPlayer ] )
		outputChatBox("leaving",hitPlayer)
	end
	timers[ hitPlayer ] = nil -- clean up
end 
  

 

 

may I ask why u put the timer [ hitPlayer ] = nil after the end? what is the explanation.

Link to post
  • Moderators
9 minutes ago, Shaman123 said:

may I ask why u put the timer [ hitPlayer ] = nil after the end? what is the explanation.

Even if you destroy the timer, both the value of the player(as table key) and timer (as table value) are still inside of the table.

Link to post
15 minutes ago, IIYAMA said:

Even if you destroy the timer, both the value of the player(as table key) and timer (as table value) are still inside of the table.

function leaveZone(hitPlayer) 
if timers[ hitPlayer ] then
	if isTimer(timers[ hitPlayer ] ) then
		killTimer(timers[ hitPlayer ] )
		outputChatBox("leaving",hitPlayer)
	end
end
end
	timers[ hitPlayer ] = nil 
addEventHandler( "onColShapeLeave", areaex, leaveZone ) 

table index is nil line 51,

51 is timers [hitPlayer] = nil

whats the problem?

EDIT: nvm i just put the line 51 above the ends, idk if thats fine but it fixed the error. anyways i want a time loop, but as u said its safer to just make the timer to "1", not "0", how is it possible to make an endless loop without the "0"?, like example i want the same cycle to repeat every 5 minutes.

i tried making a loop by making the start stage a "0" but ended up getting messy. its sad

Edited by Shaman123
Link to post
  • Moderators
28 minutes ago, Shaman123 said:

how is it possible to make an endless loop without the "0"?

When you are on stage3, you could start stage1 again. That is one way of doing.

Also, have 1 infinity timer is not the end of the world. As long as it does not start another infinity timer within.

Link to post
13 minutes ago, IIYAMA said:

When you are on stage3, you could start stage1 again. That is one way of doing.

Also, have 1 infinity timer is not the end of the world. As long as it does not start another infinity timer within.

function stage1 (hitPlayer)
outputChatBox("bomb", hitPlayer, 255, 0, 0)
local pX, pY, pZ = getElementPosition ( hitPlayer )
local locations = { 
      { pX+20, pY, pZ },
      { pX+30, pY, pZ}, 
      { pX+30, pY+20, pZ}, 
      { pX, pY+35, pZ}, 
      { pX, pY+40, pZ}, 
      { pX+60, pY, pZ }
} 
	loc = math.random(#locations) 
	createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, hitPlayer )
	timers[hitPlayer] = setTimer(stage2, 5*1000, 1, hitPlayer)
end

function stage2 (hitPlayer)
outputChatBox("repeat", hitPlayer, 0, 255, 0)
	timers[hitPlayer] = nil
timers[hitPlayer] = setTimer(stage1, 3000, 1, hitPlayer)
end

ohhh i got it, so basically like this right? anyways thanks man, u helped me so much today. 

Edited by Shaman123
Link to post
  • Moderators
37 minutes ago, Shaman123 said:

ohhh i got it, so basically like this right?

yes

 

Small note:  when you set another value, then you do not have to set it first to nil. Your code will overwrite the previous value with a new value:

timers[hitPlayer] = nil
timers[hitPlayer] = setTimer(stage1, 3000, 1, hitPlayer) -- < overwrite

But feel free to leave it as it is, in case you are going expand the code.

 

 

Link to post
15 minutes ago, IIYAMA said:

yes

 

Small note:  when you set another value, then you do not have to set it first to nil. Your code will overwrite the previous value with a new value:



timers[hitPlayer] = nil
timers[hitPlayer] = setTimer(stage1, 3000, 1, hitPlayer) -- < overwrite

But feel free to leave it as it is, in case you are going expand the code.

 

 

btw i tried the opposite version of them sharing timers, no individual timers anymore, that's easy, but im having a problem, how do you define a player in serverside? no matter how i put thePlayer, or try to define it it always says nil such as this, i want to happen that this function only happens if the player is in the areaex colshape

function stage2 (thePlayer, matchingDimension)
local detection = isElementWithinColShape ( thePlayer, areaex )
detection = detection and getElementDimension( thePlayer ) == getElementDimension( areaex )
if detection then
local pX, pY, pZ = getElementPosition ( thePlayer )
local locations = { 
      { pX+20, pY, pZ },
      { pX+30, pY, pZ}, 
      { pX+30, pY+20, pZ}, 
      { pX, pY+35, pZ}, 
      { pX, pY+40, pZ}, 
      { pX+60, pY, pZ }
} 
	loc = math.random(#locations) 
	createExplosion ( locations[loc][1], locations[loc][2], locations[loc][3], 6, source )
timers = setTimer(stage3, 1500, 1, source)
end
end

isElementWithinColShape, expected element at argument 1, got nil. how do you define a player in serverside?

Edited by Shaman123
Link to post
  • Moderators
27 minutes ago, Shaman123 said:

how do you define a player in serverside?

The player is a value that is in most cases defined based on the action that made the code run in the first place.

If it is an event, it differs from the pre-defined variable or parameter:

  • Predefined variable:  'source'(responsible element for an event: onPlayerWasted),
  • Predefined variable: 'client'(triggerServerEvent)
  • Parameter: onVehicleEnter > first argument is the ped that enters, check wiki. For this event `source` is the vehicle because: onVehicleEnter > the event is about the vehicle and not a player.

All this information is available on wiki.

 


 

When dealing with functions that take input through different ways. It is best to normalize the information first, which you want to pass through your function.

An example for addCommandHandler and an event:

-- Information normalized from 2 - input(s)

function showText (player, text)
	outputChatBox(text, player)
end


-- input 1

addCommandHandler("hi", 
function (player) 
	showText(player, "Hi!")
end)

-- input 2

addEventHandler("onPlayerWasted", root, 
function () 
	showText(source, "I died, sorry my bad.")
end)

 

 

 

 

 

 

 

 

 

Edited by IIYAMA
Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...