Jump to content

Synchronize setVehicleComponentPosition


mariogallardo

Recommended Posts

The spoiler is moving perfectly but just for me because this is client-sided. How can I make to server-side so everyone see when the spoiler moves?
 

function spoiler()
local vehicle = getPedOccupiedVehicle(localPlayer)
if vehicle then
                local sX, sY, sZ = getVehicleComponentPosition(vehicle, "movspoiler_23.5_1800")
                if spoiler == 1 then
                    if sZ < 1.2 then
                        setVehicleComponentPosition(vehicle, "movspoiler_23.5_1800", sX, sY-0.006, sZ+0.005)
                    end
                elseif spoiler == 0 then
                    if sZ > 1 then
                        setVehicleComponentPosition(vehicle, "movspoiler_23.5_1800", sX, sY+0.012, sZ-0.01)
                    end
                end
        end
end
addEventHandler("onClientRender", root, spoiler)

I know I need to trigger server event, but the setVehicleComponentPosition & getVehicleComponentPosition is client-side functions only.

Link to comment
function spoiler()
    local vehicles = getElementsByType("vehicle");
    for _,vehicle in ipairs(vehicles) do
        local sX, sY, sZ = getVehicleComponentPosition(vehicle, "movspoiler_23.5_1800")
        if (sX) then
            if spoiler == 1 then -- warning: variable overlaps with function name
                if sZ < 1.2 then
                    setVehicleComponentPosition(vehicle, "movspoiler_23.5_1800", sX, sY-0.006, sZ+0.005)
                end
            elseif spoiler == 0 then
                if sZ > 1 then
                    setVehicleComponentPosition(vehicle, "movspoiler_23.5_1800", sX, sY+0.012, sZ-0.01)
                end
            end
        end
    end
end
addEventHandler("onClientRender", root, spoiler)

This clientside approach works as long as you do not want special synchronized modifications to the spoiler placement.

Edited by The_GTA
Link to comment
16 minutes ago, The_GTA said:
function spoiler()
    local vehicles = getElementsByType("vehicle");
    for _,vehicle in ipairs(vehicles) do
        local sX, sY, sZ = getVehicleComponentPosition(vehicle, "movspoiler_23.5_1800")
        if (sX) then
            if spoiler == 1 then -- warning: variable overlaps with function name
                if sZ < 1.2 then
                    setVehicleComponentPosition(vehicle, "movspoiler_23.5_1800", sX, sY-0.006, sZ+0.005)
                end
            elseif spoiler == 0 then
                if sZ > 1 then
                    setVehicleComponentPosition(vehicle, "movspoiler_23.5_1800", sX, sY+0.012, sZ-0.01)
                end
            end
        end
    end
end
addEventHandler("onClientRender", root, spoiler)

This clientside approach works as long as you do not want special synchronized modifications to the spoiler placement.

What? This is moves the spoiler on all vehicles... not just the one which I sit in

Link to comment
1 hour ago, mariogallardo said:

What? This is moves the spoiler on all vehicles... not just the one which I sit in

Oh, excuse me for misunderstanding. You did not give accurate enough specification of which spoiler should move and whether there was only one vehicle on the server with the spoiler. Here is a better version. I cannot test it because you missed out on giving us your vehicle model. Please tell me if it works for you. ?

clientside.lua

local spoiler_status = {};

local function getVehicleSpoilerStatus(veh)
    local status = spoiler_status[veh];
    
    if (status) then return status; end;
    
    status = {};
    status.move_dir = false;
    
    spoiler_status[veh] = status;
    return status;
end

addEventHandler("onClientElementDestroy", root,
    function()
        if (getElementType(source) == "vehicle") then
            spoiler_status[source] = nil;
        end
    end
);

addEvent("onClientSpoilerInformation", true);
addEventHandler("onClientSpoilerInformation", root,
    function(desc)
        local info = getVehicleSpoilerStatus(source);
        
        --outputDebugString("received spoiler information");
        
        info.move_dir = desc.move_dir;
        info.sX = desc.sX;
        info.sY = desc.sY;
        info.sZ = desc.sZ;
    end
);

function spoiler_move()
    local vehicles = getElementsByType("vehicle");
    for _,vehicle in ipairs(vehicles) do
        local status = getVehicleSpoilerStatus(vehicle)
        if status.move_dir == 1 then
            if status.sZ and status.sZ < 1.2 then
                status.sX = status.sX + 0;
                status.sY = status.sY - 0.006;
                status.sZ = status.sZ + 0.005;
            end
            --dxDrawRectangle(300, 300, 100, 100, tocolor(255, 0, 0, 255));
        elseif status.move_dir == 0 then
            if status.sZ and status.sZ > 1 then
                status.sX = status.sX + 0;
                status.sY = status.sY + 0.012;
                status.sZ = status.sZ - 0.01;
            end
            --dxDrawRectangle(300, 300, 100, 100, tocolor(0, 255, 0, 255));
        end
        if (status.sX) then
            -- Only works if vehicle is streamed in, but we keep a copy of the component position just in case.
            setVehicleComponentPosition(vehicle, "movspoiler_23.5_1800", status.sX, status.sY, status.sZ)
        end
    end
end
addEventHandler("onClientRender", root, spoiler_move)

-- Cached network table.
local net_desc = {};

local function synchronizeSpoilerStatus(veh, info)
    -- Transmit over the network.
    net_desc.move_dir = info.move_dir;
    net_desc.sX = info.sX;
    net_desc.sY = info.sY;
    net_desc.sZ = info.sZ;
    
    triggerServerEvent("onSpoilerInformation", veh, net_desc);
end

local function spoiler_control(key, state)
    local veh = getPedOccupiedVehicle(localPlayer);
    
    if (veh) and (getVehicleOccupant(veh, 0) == localPlayer) then
        local info = getVehicleSpoilerStatus(veh);

        if not (info.sX) then
            local sX, sY, sZ = getVehicleComponentPosition(veh, "movspoiler_23.5_1800");
            
            if (sX) then
                info.sX, info.sY, info.sZ = sX, sY, sZ;
            end
        end
        
        if (key == "u") and not (info.move_dir == 0) then
            if (state == "down") then
                info.move_dir = 1;
            else
                info.move_dir = false;
            end
        elseif (key == "z") and not (info.move_dir == 1) then
            if (state == "down") then
                info.move_dir = 0;
            else
                info.move_dir = false;
            end
        end
        
        synchronizeSpoilerStatus(veh, info);
    end
end
bindKey("u", "both", spoiler_control);
bindKey("z", "both", spoiler_control);

addEventHandler("onClientVehicleExit", root,
    function(ped, seat)
        if not (seat == 0) then return; end;
    
        local info = getVehicleSpoilerStatus(source);
        
        info.move_dir = false;
        
        if (ped == localPlayer) then
            synchronizeSpoilerStatus(source, info);
        end
    end
);

addEventHandler("onClientResourceStart", resourceRoot,
    function()
        triggerServerEvent("onPlayerReady_Spoiler", root);
    end
);

serverside.lua

-- TODO: add proper security to this script.

local spoiler_status = {};
local ready_players = {};

local function sendSpoilerInformation(player, veh, desc)
    triggerClientEvent("onClientSpoilerInformation", veh, desc);
end

addEvent("onSpoilerInformation", true);
addEventHandler("onSpoilerInformation", root,
    function(desc)
        spoiler_status[source] = desc;
        
        for m,n in pairs(ready_players) do
            if not (n == client) then
                sendSpoilerInformation(n, source, desc);
            end
        end
    end
);

addEvent("onPlayerReady_Spoiler", true);
addEventHandler("onPlayerReady_Spoiler", root,
    function()
        for veh,desc in pairs(spoiler_status) do
            sendSpoilerInformation(client, veh, desc);
        end
        ready_players[client] = true;
    end
);

addEventHandler("onPlayerQuit", root,
    function()
        ready_players[source] = nil;
    end
);

addEventHandler("onElementDestroy", root,
    function()
        if (getElementType(source) == "vehicle") then
            spoiler_status[source] = nil;
        end
    end
);

Use the "u" and "z" keys to control spoiler movement.

Edited by The_GTA
  • Thanks 1
Link to comment
1 hour ago, The_GTA said:

Oh, excuse me for misunderstanding. You did not give accurate enough specification of which spoiler should move and whether there was only one vehicle on the server with the spoiler. Here is a better version. I cannot test it because you missed out on giving us your vehicle model. Please tell me if it works for you. ?

clientside.lua

local spoiler_status = {};

local function getVehicleSpoilerStatus(veh)
    local status = spoiler_status[veh];
    
    if (status) then return status; end;
    
    status = {};
    status.move_dir = false;
    
    spoiler_status[veh] = status;
    return status;
end

addEventHandler("onClientElementDestroy", root,
    function()
        if (getElementType(source) == "vehicle") then
            spoiler_status[source] = nil;
        end
    end
);

addEvent("onClientSpoilerInformation", true);
addEventHandler("onClientSpoilerInformation", root,
    function(desc)
        local info = getVehicleSpoilerStatus(source);
        
        --outputDebugString("received spoiler information");
        
        info.move_dir = desc.move_dir;
        info.sX = desc.sX;
        info.sY = desc.sY;
        info.sZ = desc.sZ;
    end
);

function spoiler_move()
    local vehicles = getElementsByType("vehicle");
    for _,vehicle in ipairs(vehicles) do
        local status = getVehicleSpoilerStatus(vehicle)
        if status.move_dir == 1 then
            if status.sZ and status.sZ < 1.2 then
                status.sX = status.sX + 0;
                status.sY = status.sY - 0.006;
                status.sZ = status.sZ + 0.005;
            end
            --dxDrawRectangle(300, 300, 100, 100, tocolor(255, 0, 0, 255));
        elseif status.move_dir == 0 then
            if status.sZ and status.sZ > 1 then
                status.sX = status.sX + 0;
                status.sY = status.sY + 0.012;
                status.sZ = status.sZ - 0.01;
            end
            --dxDrawRectangle(300, 300, 100, 100, tocolor(0, 255, 0, 255));
        end
        if (status.sX) then
            -- Only works if vehicle is streamed in, but we keep a copy of the component position just in case.
            setVehicleComponentPosition(vehicle, "movspoiler_23.5_1800", status.sX, status.sY, status.sZ)
        end
    end
end
addEventHandler("onClientRender", root, spoiler_move)

-- Cached network table.
local net_desc = {};

local function synchronizeSpoilerStatus(veh, info)
    -- Transmit over the network.
    net_desc.move_dir = info.move_dir;
    net_desc.sX = info.sX;
    net_desc.sY = info.sY;
    net_desc.sZ = info.sZ;
    
    triggerServerEvent("onSpoilerInformation", veh, net_desc);
end

local function spoiler_control(key, state)
    local veh = getPedOccupiedVehicle(localPlayer);
    
    if (veh) and (getVehicleOccupant(veh, 0) == localPlayer) then
        local info = getVehicleSpoilerStatus(veh);

        if not (info.sX) then
            local sX, sY, sZ = getVehicleComponentPosition(veh, "movspoiler_23.5_1800");
            
            if (sX) then
                info.sX, info.sY, info.sZ = sX, sY, sZ;
            end
        end
        
        if (key == "u") and not (info.move_dir == 0) then
            if (state == "down") then
                info.move_dir = 1;
            else
                info.move_dir = false;
            end
        elseif (key == "z") and not (info.move_dir == 1) then
            if (state == "down") then
                info.move_dir = 0;
            else
                info.move_dir = false;
            end
        end
        
        synchronizeSpoilerStatus(veh, info);
    end
end
bindKey("u", "both", spoiler_control);
bindKey("z", "both", spoiler_control);

addEventHandler("onClientVehicleExit", root,
    function(ped, seat)
        if not (seat == 0) then return; end;
    
        local info = getVehicleSpoilerStatus(source);
        
        info.move_dir = false;
        
        if (ped == localPlayer) then
            synchronizeSpoilerStatus(source, info);
        end
    end
);

addEventHandler("onClientResourceStart", resourceRoot,
    function()
        triggerServerEvent("onPlayerReady_Spoiler", root);
    end
);

serverside.lua

-- TODO: add proper security to this script.

local spoiler_status = {};
local ready_players = {};

local function sendSpoilerInformation(player, veh, desc)
    triggerClientEvent("onClientSpoilerInformation", veh, desc);
end

addEvent("onSpoilerInformation", true);
addEventHandler("onSpoilerInformation", root,
    function(desc)
        spoiler_status[source] = desc;
        
        for m,n in pairs(ready_players) do
            if not (n == client) then
                sendSpoilerInformation(n, source, desc);
            end
        end
    end
);

addEvent("onPlayerReady_Spoiler", true);
addEventHandler("onPlayerReady_Spoiler", root,
    function()
        for veh,desc in pairs(spoiler_status) do
            sendSpoilerInformation(client, veh, desc);
        end
        ready_players[client] = true;
    end
);

addEventHandler("onPlayerQuit", root,
    function()
        ready_players[source] = nil;
    end
);

addEventHandler("onElementDestroy", root,
    function()
        if (getElementType(source) == "vehicle") then
            spoiler_status[source] = nil;
        end
    end
);

Use the "u" and "z" keys to control spoiler movement.

Thank you, yes this is working but it's have a little problem, I need to press the u,z buttons 12 times until the spoiler is opens up fully / close fully.

I think I need to put a timer somewhere?!

Link to comment
8 minutes ago, mariogallardo said:

Thank you, yes this is working but it's have a little problem, I need to press the u,z buttons 12 times until the spoiler is opens up fully / close fully.

I think I need to put a timer somewhere?!

You're welcome. A big problem in your model is that you link the movement-speed of the spoiler to game FPS. This results in different speeds depending on computer performance. I recommend you to use getTickCount to get elapsed time in milliseconds and then divide it by 1000 to get the elapsed seconds. Then multiply it by a base-velocity to get the distance it should travel per second. Then change the mathematics accordingly inside spoiler_move clientside.lua .

Edited by The_GTA
  • 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...