Jump to content

Work as a bus driver.


Recommended Posts

Good time of day. I am developing a bus system and have run into several problems:
1) I can't make a bus stop informant: I can't make the informant be heard by other players on the server and, in addition, I can't make the reminder trigger timer reset when exiting the bus.

The code for triggering the memo every 2 minutes:

Spoiler

client: 

setTimer(function()
                if isPedInVehicle (localPlayer) then
                    randomin={"pamgaz.wav","pam_nez_vesj.wav","pammesta.wav","pamoplaty.wav","pampok.wav","pamporuch.wav","pampriobr.wav","pampriv.wav","pamprovod.wav","pirotehpam.wav"}
                    randInSound = playSound3D("randominform/"..randomin[math.random(1,10)],0.0,0.0,0.0, false)
                    setSoundMaxDistance( randInSound,150 )
                    attachElements ( randInSound, thevehiclei, 0, 0, 0 )
                else
                    stopSound(randInSound)
                end
            end, 120000, 0)


2) I can't fully make the texture on the bus route board change (for some reason there are no changes on old devices, but they are applied on the server), that is, the texture changes on the server, but the texture does not change for those players who have just connected to the server.
 Plate Texture replacement code:

Spoiler

client:

function changeRouteTexture(theVehicle, id)
            if (theVehicle and id) then
                local textureName = tostring(id) .. ".png"
                triggerServerEvent("onClientRouteTextureChanged", resourceRoot, theVehicle,  id, textureName)
            end
        end
        addEvent("onServerRouteTextureChanged", true)
        addEventHandler("onServerRouteTextureChanged", resourceRoot, function(theVehicle,  id, textureName)
            applyTextureShader(theVehicle, id, textureName)
        end)

        function applyTextureShader(theVehicle, id, textureName)
            local texture = dxCreateTexture(textureName)
            local shader = dxCreateShader("texture_replace.fx")
            local trailer = getVehicleTowedByVehicle (theVehicle)
            engineApplyShaderToWorldTexture(shader, "tablavtobus", theVehicle, true)
            engineApplyShaderToWorldTexture(shader, "tablavtobus", trailer, true)
            dxSetShaderValue(shader, "gTexture", texture)
        end

        changeRouteTexture(thevehiclei, id)

server:

function changeRouteTexture (pl)
triggerClientEvent ("changeRouteTexture", pl)
end

local shaders = {}

addEvent("onClientRouteTextureChanged", true)
addEventHandler("onClientRouteTextureChanged", resourceRoot, function(theVehicle, id, textureName)
    -- Сохраняем информацию об изменении текстуры и применяем изменения на всех клиентах
    if not shaders[theVehicle] then
        shaders[theVehicle] = {}
    end

    shaders[theVehicle].id = id
    shaders[theVehicle].textureName = textureName

    triggerClientEvent("onServerRouteTextureChanged", resourceRoot, theVehicle, id, textureName)
    outputChatBox("Транспортное средство с ID: " .. tostring(getElementID(theVehicle)) .. " изменило текстуру маршрута на: " .. tostring(id))
end)
function sendTexturesToPlayer(player)
    for theVehicle, shaderTable in pairs(shaders) do
        triggerClientEvent(player, "onServerRouteTextureChanged", resourceRoot, theVehicle, shaderTable.id, shaderTable.textureName)
    end
end
addEventHandler("onPlayerJoin", root, sendTexturesToPlayer)

In addition to the classic 1-section buses, I will also use two-section articulated vehicles (tractor + trailer in the original game)

Link to comment
  • 2 weeks later...

1) To make the sound play for other players, you should make all the controlling code server-side, and use triggerClientEvent on nearby players to trigger a client-side event which would call playSound3D.

To reset the timer when the player exits the bus: instead of having a timer run all the time, call setTimer in onPlayerVehicleEnter to start the timer and killTimer in onPlayerVehicleExit to stop the timer.

2) You have a variable player for the first parameter in sendTexturesToPlayer, but onPlayerJoin has no parameters and uses source for the player who joined - so you need to pass source instead of player to triggerClientEvent.

But even then, there's another problem: when the player joins, the resource hasn't loaded on the client side yet so it hasn't had time to call addEvent yet, which will cause triggerClientEvent to fail. Instead, you need to use onPlayerResourceStart for this. Because this event will be triggered on each resource start, you also need to check if its first parameter (loadedResource in the wiki) equals the return value of getThisResource.

Link to comment
2 hours ago, DiSaMe said:

1) To make the sound play for other players, you should make all the controlling code server-side, and use triggerClientEvent on nearby players to trigger a client-side event which would call playSound3D.

To reset the timer when the player exits the bus: instead of having a timer run all the time, call setTimer in onPlayerVehicleEnter to start the timer and killTimer in onPlayerVehicleExit to stop the timer.

2) You have a variable player for the first parameter in sendTexturesToPlayer, but onPlayerJoin has no parameters and uses source for the player who joined - so you need to pass source instead of player to triggerClientEvent.

But even then, there's another problem: when the player joins, the resource hasn't loaded on the client side yet so it hasn't had time to call addEvent yet, which will cause triggerClientEvent to fail. Instead, you need to use onPlayerResourceStart for this. Because this event will be triggered on each resource start, you also need to check if its first parameter (loadedResource in the wiki) equals the return value of getThisResource.

I had to wait a long time for help, but thanks for the answer :)
I managed to make the sound audible on the server, can you help with the implementation of the so-called reset timer? That is, when boarding a car, a memo is triggered every 2 minutes, and when exiting the car, the timer needs to be reset and stop counting, and when re-boarding in the car, it only works after 2 minutes. Here is my code:
Client:

Spoiler

function createRoute (id, name)    -- A function that creates a route, and is triggered accordingly when I sit in the driver's seat on the bus
            thevehiclei = getPedOccupiedVehicle(localPlayer)
            randomPamtimer=setTimer(ranfominform,120000, 0)
            routeSet = getRouteFromName (name)
            replaceTexture(id)
            if routeSet[markerIndex][4] then....... 

function ranfominform()
    local vehicle = getPedOccupiedVehicle(localPlayer)
    if (getVehicleController(vehicle) == localPlayer) then
        spam = getTickCount()
        randomin={"pamgaz.wav","pam_nez_vesj.wav","pammesta.wav","pamoplaty.wav","pampok.wav","pamporuch.wav","pampriobr.wav","pampriv.wav","pamprovod.wav","pirotehpam.wav"}
        randinInd=randomin[math.random(1,10)]
        local x, y, z = getElementPosition(vehicle)
        triggerServerEvent("onSyncRandi", localPlayer,randinInd)
    end
end

function syncedranfominform(vehicle, x, y, z,randinSoundInd)
    if randInSound then
        stopSound(randInSound)
    end
        randInSound = playSound3D(randinSoundInd,x,y,z, false)
        setSoundMaxDistance( randInSound,150 )
        attachElements ( randInSound, vehicle, 0, 0, 0 )
end
addEvent("onPlaySyncedRandInform", true)
addEventHandler("onPlaySyncedRandInform", root, syncedranfominform)

Server:

Spoiler

function syncRandi(randinInd)
    local vehicle = getPedOccupiedVehicle(client)
    if getVehicleController(vehicle) == client then
        if spam[client] and getTickCount() - spam[client] < 5000 then return end
        local x, y, z = getElementPosition(client)
        local nearbyPlayers = getElementsWithinRange(x, y, z, 150, "player")
        spam[client] = getTickCount()
        randinSoundInd="randominform/"..randinInd
        triggerClientEvent(nearbyPlayers, "onPlaySyncedRandInform", client, vehicle, x, y, z,randinSoundInd)
    end
end
addEvent("onSyncRandi", true)
addEventHandler("onSyncRandi", root, syncRandi)

I'm a beginner and just getting to know Lua :)

 

Edited by Lance_Delmago
Link to comment

My point was that you shouldn't do that much work on the client. The client-side code should only be used for playing the sound. Which in this case is the part with syncedranfominform function and onPlaySyncedRandInform event. Everything else should be done on the server.

You should call setTimer from onPlayerVehicleEnter event to start the timer and call killTimer from onPlayerVehicleExit event to stop it - so every time you enter a vehicle, a timer will be created to execute every 2 minutes, with first execution occurring 2 minutes after entering. And when you exit the vehicle, that timer will be destroyed so it will no longer execute. An example:

local timers = {}

function startTimerOnEnter(vehicle, seat, jacked)
	if seat == 0 then -- only call it if entered the driver seat
		local timer = setTimer(whateverFunctionYouNeedToCall, 120000, 0) -- create a timer
		timers[source] = timer -- store the timer in the table under source, which is the player
	end
end

function stopTimerOnExit(vehicle, seat, jacker, forcedByScript)
	local timer = timers[source] -- retrieve the timer from the table

	if timer then -- if, for whatever reason, the timer wasn't previously created, we need to check it
		killTimer(timer) -- destroy the timer
		timers[source] = nil -- clear the field from the table since the timer no longer exists
	end
end

addEventHandler("onPlayerVehicleEnter", root, startTimerOnEnter)
addEventHandler("onPlayerVehicleExit", root, stopTimerOnExit)

There are going to be some additional cases where you need to clean up, like destroying the timer if the player quits while in the vehicle, as onPlayerVehicleExit won't be triggered. This is just the main part to show what it should look like.

Link to comment
2 hours ago, DiSaMe said:

 

local timers = {}

function startTimerOnEnter(vehicle, seat, jacked)
	if seat == 0 then -- only call it if entered the driver seat
		local timer = setTimer(whateverFunctionYouNeedToCall, 120000, 0) -- create a timer
		timers[source] = timer -- store the timer in the table under source, which is the player
	end
end

function stopTimerOnExit(vehicle, seat, jacker, forcedByScript)
	local timer = timers[source] -- retrieve the timer from the table

	if timer then -- if, for whatever reason, the timer wasn't previously created, we need to check it
		killTimer(timer) -- destroy the timer
		timers[source] = nil -- clear the field from the table since the timer no longer exists
	end
end

addEventHandler("onPlayerVehicleEnter", root, startTimerOnEnter)
addEventHandler("onPlayerVehicleExit", root, stopTimerOnExit)

 

Thanks, everything works :). Only I decided to do it on the client side because most of the script (sound, gui and route markers) are tied to the client. Everything is related to this topic, but I will need help with things like .dat files (the topic is in the scripting section), adding seats, spawn cars in the interior, "gluing" the trailer to the truck tightly (for articulated buses), etc., but the most basic ".dat" files and turning the rear wheels of the trailer relative to truck (as on ikarus 280)

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