Jump to content

[QUESTION] How to record distance travelled by vehicle?


koragg

Recommended Posts

Hello people. Few days ago I started creating a new PlayerStats panel mainly focused on racing. I added the following things so far and they all work perfectly:

-Cars destroyed

-Bikes destroyed

-Boats destroyed

-Planes & Helicopters destroyed

-Race starts

-Race finishes

-Race wins

-Toptimes set

-Checkpoints collected

-Total earnings

-Money spent

-Current balance

But I also wanted to add these things:

*Distance travelled by car

*Distance travelled by motorbike

*Distance travelled by boat

*Distance travelled by aircraft

*Distance travelled by bicycle

 

So my question is, how can I record the distance travelled and save it as account data like all other stats above? I saw this and although I found the code responsible for recording the distance it's done in a pretty hard way (at least for me). Is there an easy way to record distance travelled by each of the above vehicles (in KMh)? 

Link to comment
local totalDis
local lastX, lastY, lastZ

function startJourney()
	if not lastX then -- if there is no previous position save the current
    	lastX, lastY, lastZ = getElementPosition(vehElement)
   	end
  	setTimer(function()
      local currX, currY, currZ = getElementPosition(vehElement) -- get the current position of the vehicle
      totalDis = getDistanceBetweenPoints3D(currX, currY, currZ, lastX, lastY, lastZ ) -- calculate the distance between the current and the last and add it to the totalDistance
      lastX, lastY, lastZ = currX, currY, currZ -- update the last position with the current
    end, 2000, 0) -- 2 sec infinite timer, could be increased/decreased, the smaller it is the more accurate results you get
end

I used something like that in one of my projects, not saying it's the best solution, but it was working fine for me.

Edited by pa3ck
  • Like 1
Link to comment

I guess that's server-side right? And I'll be able to check if it's a car, bike, etc by doing an "if getElementModel(vehElement) == 411 then". Timer set to 50 sounds the most accurate.

Edited by koragg
Or it would be better if I add an "onClientRender" and make it client-side?
Link to comment

Doesn't have to be server side, it's fine on client side with something like getTickCount() so you only update the element data every couple of seconds, like 5-8-10 secs or so, depending if you need to display it on HUD, that would be a bit choppy. Regarding the timer tick, 50 would be the most accurate, yea, but I don't think it's that important to get as accurate result as you can. See when you drive 150m forward, then 50m backward between 2 ticks, it will only update 100, not 200 (as a real car would), but you can't really change much on the outcome under 1-2 second time span.

Edited by pa3ck
Link to comment

You could use this.

local total_km, partial_km, tick_km = 0, 0, 0

function handleSpeed()
  if ( getPedOccupiedVehicle( localPlayer ) and getVehicleOccupant( getPedOccupiedVehicle( localPlayer ), 0 ) == localPlayer ) then
    local theVehicle = getPedOccupiedVehicle( localPlayer )
    
    if ( tick_km <= 0 ) and ( getVehicleEngineState( vehicle ) ) then
      tick_km = getTickCount()
    end

    if ( getTickCount() - tick_km >= 1000 ) then
      local sx, sy, sz = getElementVelocity ( theVehicle )
      local kms = ( ( ( sx * sx ) + ( sy * sy ) + ( sz * sz ) ) ^ ( 0.5 ) ) * 1000 / 3600 -- This would be the most realistic way but it add's up very fastly so better up the number that is dividing.

      if ( partial_km + kms >= 1 ) then
        partial_km = ( partial_km + kms ) - 1

        total_km = total_km + 1
      else
        partial_km = partial_km + kms
      end
      
	  tick_km = getTickCount()
    end
  end
end
addEventHandler( "onClientRender", root, handleSpeed )

 

Edited by Simple01
  • Like 1
Link to comment

Thanks to both of you, I used @Simple01's code as I did something similar when recording total drift score some time ago and was more familiar with it being client side.

1. Recorded the distance client-side

2. Sent it to server-side with events (those things are priceless)

Client:

-- Used to record distance passed with the specific vehicle category.
local totalAircraft_km = 0
local partialAircraft_km = 0
local tickAircraft_km = 0

local totalBoat_km = 0
local partialBoat_km = 0
local tickBoat_km = 0

local totalBike_km = 0
local partialBike_km = 0
local tickBike_km = 0

local totalCar_km = 0
local partialCar_km = 0
local tickCar_km = 0

local totalBicycle_km = 0
local partialBicycle_km = 0
local tickBicycle_km = 0

function handleSpeed()
	local car = getPedOccupiedVehicle(localPlayer)
	local id
	if car then
		id = getElementModel(car)
	end
	
	-- distanceByAircraft
	if id == 592 or id == 577 or id == 511 or id == 512 or id == 593 or id == 520 or id == 553 or id == 476 or id == 519
	or id == 460 or id == 513 or id == 548 or id == 425 or id == 417 or id == 487 or id == 488 or id == 497 or id == 563 
	or id == 447 or id == 469 then	
		if car and getVehicleOccupant(car, 0) == localPlayer then
			if tickAircraft_km <= 0 and getVehicleEngineState(car) then
				tickAircraft_km = getTickCount()
			end
			if getTickCount() - tickAircraft_km >= 1000 then
				local sx, sy, sz = getElementVelocity(car)
				local kms = ((sx * sx + sy * sy + sz * sz)^(0.5) * 1000) / 20650
				if partialAircraft_km + kms >= 1 then
					partialAircraft_km = partialAircraft_km + kms - 1
					totalAircraft_km = totalAircraft_km + 1
					triggerServerEvent("distanceByAircraft", localPlayer, totalAircraft_km)
				else
					partialAircraft_km = partialAircraft_km + kms
				end
				tickAircraft_km = getTickCount()
			end
		end
		
	-- distanceByBoat
	elseif id == 472 or id == 473 or id == 493 or id == 595 or id == 484 or id == 430 or id == 453 or id == 452 or 
	id == 446 or id == 454 then
		if car and getVehicleOccupant(car, 0) == localPlayer then
			if tickBoat_km <= 0 and getVehicleEngineState(car) then
				tickBoat_km = getTickCount()
			end
			if getTickCount() - tickBoat_km >= 1000 then
				local sx, sy, sz = getElementVelocity(car)
				local kms = ((sx * sx + sy * sy + sz * sz)^(0.5) * 1000) / 20650
				if partialBoat_km + kms >= 1 then
					partialBoat_km = partialBoat_km + kms - 1
					totalBoat_km = totalBoat_km + 1
					triggerServerEvent("distanceByBoat", localPlayer, totalBoat_km)
				else
					partialBoat_km = partialBoat_km + kms
				end
				tickBoat_km = getTickCount()
			end
		end
		
	-- distanceByBike
	elseif id == 581 or id == 509 or id == 481 or id == 462 or id == 521 or id == 463 or id == 510 or id == 522 or 
	id == 461 or id == 448 or id == 468 or id == 586 then
		if car and getVehicleOccupant(car, 0) == localPlayer then
			if tickBike_km <= 0 and getVehicleEngineState(car) then
				tickBike_km = getTickCount()
			end
			if getTickCount() - tickBike_km >= 1000 then
				local sx, sy, sz = getElementVelocity(car)
				local kms = ((sx * sx + sy * sy + sz * sz)^(0.5) * 1000) / 20650
				if partialBike_km + kms >= 1 then
					partialBike_km = partialBike_km + kms - 1
					totalBike_km = totalBike_km + 1
					triggerServerEvent("distanceByBike", localPlayer, totalBike_km)
				else
					partialBike_km = partialBike_km + kms
				end
				tickBike_km = getTickCount()
			end
		end
	
	-- distanceByCar
	elseif id == 602 or id == 496 or id == 401 or id == 518 or id == 527 or id == 589 or id == 419 or id == 587 or 
	id == 533 or id == 526 or id == 474 or id == 545 or id == 517 or id == 410 or id == 600 or id == 436 or id == 439 or 
	id == 549 or id == 491 or id == 485 or id == 431 or id == 438 or id == 437 or id == 574 or id == 420 or id == 525 or 
	id == 408 or id == 552 or id == 416 or id == 433 or id == 427 or id == 490 or id == 528 or id == 407 or id == 544 or 
	id == 523 or id == 470 or id == 596 or id == 598 or id == 599 or id == 597 or id == 432 or id == 601 or id == 428 or 
	id == 499 or id == 609 or id == 498 or id == 524 or id == 532 or id == 578 or id == 486 or id == 406 or id == 573 or 
	id == 455 or id == 588 or id == 403 or id == 423 or id == 414 or id == 443 or id == 515 or id == 514 or id == 531 or 
	id == 456 or id == 459 or id == 422 or id == 482 or id == 605 or id == 530 or id == 418 or id == 572 or id == 582 or 
	id == 413 or id == 440 or id == 543 or id == 583 or id == 478 or id == 554 or id == 579 or id == 400 or id == 404 or 
	id == 489 or id == 505 or id == 479 or id == 442 or id == 458 or id == 536 or id == 575 or id == 534 or id == 567 or 
	id == 535 or id == 576 or id == 412 or id == 402 or id == 542 or id == 603 or id == 475 or id == 429 or id == 541 or 
	id == 415 or id == 480 or id == 562 or id == 565 or id == 434 or id == 494 or id == 502 or id == 503 or id == 411 or 
	id == 559 or id == 561 or id == 560 or id == 506 or id == 451 or id == 558 or id == 555 or id == 477 or id == 441 or 
	id == 464 or id == 594 or id == 501 or id == 465 or id == 564 or id == 606 or id == 607 or id == 610 or id == 584 or 
	id == 611 or id == 608 or id == 435 or id == 450 or id == 591 or id == 590 or id == 538 or id == 570 or id == 569 or 
	id == 537 or id == 449 or id == 568 or id == 424 or id == 504 or id == 457 or id == 483 or id == 508 or id == 571 or
	id == 500 or id == 444 or id == 556 or id == 557 or id == 471 or id == 495 or id == 539 then
		if car and getVehicleOccupant(car, 0) == localPlayer then
			if tickCar_km <= 0 and getVehicleEngineState(car) then
				tickCar_km = getTickCount()
			end
			if getTickCount() - tickCar_km >= 1000 then
				local sx, sy, sz = getElementVelocity(car)
				local kms = ((sx * sx + sy * sy + sz * sz)^(0.5) * 1000) / 20650
				if partialCar_km + kms >= 1 then
					partialCar_km = partialCar_km + kms - 1
					totalCar_km = totalCar_km + 1
					triggerServerEvent("distanceByCar", localPlayer, totalCar_km)
				else
					partialCar_km = partialCar_km + kms
				end
				tickCar_km = getTickCount()
			end
		end
		
	-- distanceByBicycle
	elseif id == 509 or id == 481 or id == 510 then
		if car and getVehicleOccupant(car, 0) == localPlayer then
			if tickBicycle_km <= 0 and getVehicleEngineState(car) then
				tickBicycle_km = getTickCount()
			end
			if getTickCount() - tickBicycle_km >= 1000 then
				local sx, sy, sz = getElementVelocity(car)
				local kms = ((sx * sx + sy * sy + sz * sz)^(0.5) * 1000) / 20650
				if partialBicycle_km + kms >= 1 then
					partialBicycle_km = partialBicycle_km + kms - 1
					totalBicycle_km = totalBicycle_km + 1
					triggerServerEvent("distanceByBicycle", localPlayer, totalBicycle_km)
				else
					partialBicycle_km = partialBicycle_km + kms
				end
				tickBicycle_km = getTickCount()
			end
		end
	end
end
addEventHandler("onClientRender", root, handleSpeed)

Server:

-- distanceByAircraft
addEvent("distanceByAircraft", true)
function distanceByAircraft(currentDistance)
	local playeraccount = getPlayerAccount(source)
	if isGuestAccount(playeraccount) then
		return
	end
	
	local prevDistance = tonumber(getAccountData(playeraccount, "distanceByAircraft") or 0)
	local newDistance = prevDistance + tonumber(currentDistance)
	setAccountData(playeraccount, "distanceByAircraft", newDistance)
	setElementData(source, "distanceByAircraft", newDistance)
end
addEventHandler("distanceByAircraft", root, distanceByAircraft)

-- distanceByBoat
addEvent("distanceByBoat", true)
function distanceByBoat(currentDistance)
	local playeraccount = getPlayerAccount(source)
	if isGuestAccount(playeraccount) then
		return
	end
	
	local prevDistance = tonumber(getAccountData(playeraccount, "distanceByBoat") or 0)
	local newDistance = prevDistance + tonumber(currentDistance)
	setAccountData(playeraccount, "distanceByBoat", newDistance)
	setElementData(source, "distanceByBoat", newDistance)
end
addEventHandler("distanceByBoat", root, distanceByBoat)

-- distanceByBike
addEvent("distanceByBike", true)
function distanceByBike(currentDistance)
	local playeraccount = getPlayerAccount(source)
	if isGuestAccount(playeraccount) then
		return
	end
	
	local prevDistance = tonumber(getAccountData(playeraccount, "distanceByBike") or 0)
	local newDistance = prevDistance + tonumber(currentDistance)
	setAccountData(playeraccount, "distanceByBike", newDistance)
	setElementData(source, "distanceByBike", newDistance)
end
addEventHandler("distanceByBike", root, distanceByBike)

-- distanceByCar
addEvent("distanceByCar", true)
function distanceByCar(currentDistance)
	local playeraccount = getPlayerAccount(source)
	if isGuestAccount(playeraccount) then
		return
	end
	
	local prevDistance = tonumber(getAccountData(playeraccount, "distanceByCar") or 0)
	local newDistance = prevDistance + tonumber(currentDistance)
	setAccountData(playeraccount, "distanceByCar", newDistance)
	setElementData(source, "distanceByCar", newDistance)
end
addEventHandler("distanceByCar", root, distanceByCar)

-- distanceByBicycle
addEvent("distanceByBicycle", true)
function distanceByBicycle(currentDistance)
	local playeraccount = getPlayerAccount(source)
	if isGuestAccount(playeraccount) then
		return
	end
	
	local prevDistance = tonumber(getAccountData(playeraccount, "distanceByBicycle") or 0)
	local newDistance = prevDistance + tonumber(currentDistance)
	setAccountData(playeraccount, "distanceByBicycle", newDistance)
	setElementData(source, "distanceByBicycle", newDistance)
end
addEventHandler("distanceByBicycle", root, distanceByCar)

And then used the element data to show the correct info on the GUI. :)

 

PS: I'm pretty sure I could have avoided like 70% of the code as it's the same but I prefer to play it safe :D

Edited by koragg
  • Like 1
Link to comment

Ops, made a small typo and can't edit my previous post :\

The total distance needs to be set to 0 after the event gets triggered so:

totalAircraft_km = totalAircraft_km + 1
triggerServerEvent("distanceByAircraft", localPlayer, totalAircraft_km)
totalAircraft_km = 0

And like that^ for each vehicle category (totalCar_km = 0, totalBike_km = 0, etc.)

Otherwise it recorded huge numbers as passed KMh :P

Link to comment
  • Moderators
	elseif id == 602 or id == 496 or id == 401 or id == 518 or id == 527 or id == 589 or id == 419 or id == 587 or 
	id == 533 or id == 526 or id == 474 or id == 545 or id == 517 or id == 410 or id == 600 or id == 436 or id == 439 or 
	id == 549 or id == 491 or id == 485 or id == 431 or id == 438 or id == 437 or id == 574 or id == 420 or id == 525 or 
	id == 408 or id == 552 or id == 416 or id == 433 or id == 427 or id == 490 or id == 528 or id == 407 or id == 544 or 
	id == 523 or id == 470 or id == 596 or id == 598 or id == 599 or id == 597 or id == 432 or id == 601 or id == 428 or 
	id == 499 or id == 609 or id == 498 or id == 524 or id == 532 or id == 578 or id == 486 or id == 406 or id == 573 or 
	id == 455 or id == 588 or id == 403 or id == 423 or id == 414 or id == 443 or id == 515 or id == 514 or id == 531 or 
	id == 456 or id == 459 or id == 422 or id == 482 or id == 605 or id == 530 or id == 418 or id == 572 or id == 582 or 
	id == 413 or id == 440 or id == 543 or id == 583 or id == 478 or id == 554 or id == 579 or id == 400 or id == 404 or 
	id == 489 or id == 505 or id == 479 or id == 442 or id == 458 or id == 536 or id == 575 or id == 534 or id == 567 or 
	id == 535 or id == 576 or id == 412 or id == 402 or id == 542 or id == 603 or id == 475 or id == 429 or id == 541 or 
	id == 415 or id == 480 or id == 562 or id == 565 or id == 434 or id == 494 or id == 502 or id == 503 or id == 411 or 
	id == 559 or id == 561 or id == 560 or id == 506 or id == 451 or id == 558 or id == 555 or id == 477 or id == 441 or 
	id == 464 or id == 594 or id == 501 or id == 465 or id == 564 or id == 606 or id == 607 or id == 610 or id == 584 or 
	id == 611 or id == 608 or id == 435 or id == 450 or id == 591 or id == 590 or id == 538 or id == 570 or id == 569 or 
	id == 537 or id == 449 or id == 568 or id == 424 or id == 504 or id == 457 or id == 483 or id == 508 or id == 571 or
	id == 500 or id == 444 or id == 556 or id == 557 or id == 471 or id == 495 or id == 539 then

Woow, this very very very inefficient. O_o

+ > onClientRender <
 

I suggest to follow a table tutorial.

local vehicleIDs = {
	car = {
		[501] = true,
    	[465] = true,
    	[607] = true,
    	[571] = true
	}
	boat = {
     -- etc.
	}
}

 

 

elseif vehicleIDs.car[id] then
-- do your stuff

elseif vehicleIDs.boat[id] then
-- do your stuff

 


and you might want to consider using: https://wiki.multitheftauto.com/wiki/TriggerLatentServerEvent

Since you trigger it every second, you have to take in account that not everybody has great internet. I would strongly recommend to send it every 10 or even 20 seconds. What does 10 seconds matter when they are an hour in the server?

  • Like 1
Link to comment
  • Moderators

onClientRender is fine, just the id check and communication between the server can be optimised.

 

Update time to check the distance

You also increase (~50ms) the update time with getTickCount as you did before. (that gives you somehow less lagg than a 50 ms timer)

Edited by IIYAMA
  • Like 1
Link to comment

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...