Vice City: Multiplayer

VC:MP Discussion => Support => Topic started by: LamFloGaming on Aug 09, 2026, 08:35 AM

Title: Showing Speedometer
Post by: LamFloGaming on Aug 09, 2026, 08:35 AM
Hello! It me again.
Today, I found this store on 1 public server Store folder of Rockstar Experience Sprite (https://prnt.sc/1exC8jaVrc-i) and this script in script folder:
local g_LocalVehicle = null;
local g_SpeedTableLerpTime = 0.2;
local g_ZeroVector = VectorScreen(0, 0);
local g_FullColour = Colour(255, 255, 255, 255);

local g_StatsLabel = null;
local g_StatsLabelShadow = null; 
local g_StatsBg = null;
local g_DefaultColour = Colour(255, 255, 255, 255);
local g_SpeedHint = null;
sX <- GUI.GetScreenSize().X;
sY <- GUI.GetScreenSize().Y;

local sprite_logo, label_name;

function CenterStatsLabels() {
    if (g_StatsLabel) {
        local pos = VectorScreen(10, sY - 30);
        g_StatsLabel.Pos = pos;
        if (g_StatsLabelShadow) {
            g_StatsLabelShadow.Pos = VectorScreen(10 + 1, sY - 30 + 1);
        }
    }
}

function Script::ScriptLoad() {
    g_StatsLabelShadow = GUILabel(VectorScreen(11, 11), Colour(0, 0, 0, 255), "Loading stats...");
    g_StatsLabelShadow.FontSize = 14;
    g_StatsLabelShadow.FontFlags = GUI_FFLAG_BOLD;
    g_StatsLabel = GUILabel(VectorScreen(10, 10), g_DefaultColour, "Loading stats...");
    g_StatsLabel.FontSize = 14;                       
    g_StatsLabel.FontFlags = GUI_FFLAG_BOLD;         
    g_StatsLabel.TextColour = Colour(224,255,255);

    CenterStatsLabels();
}

function Script::ScriptProcess() { 
    CheckAndUpdateVehicleTableProc();
}

function GUI::GameResize(width, height) {
    sX = width;
    sY = height;
    CheckAndUpdateVehicleTableUI();
    CenterStatsLabels();
}

function Server::ServerData(stream) {
    local cmd = stream.ReadString();

    switch (cmd) {
        case "stats":
            local kills = stream.ReadInt();
            local deaths = stream.ReadInt();
            local gwWins = stream.ReadInt();
            local headshots = stream.ReadInt();
            local duelWins = stream.ReadInt();
            if (g_StatsLabel) {
                local newText = format(
                    "Kills: %d   Deaths: %d   Gangwar Wins: %d   Headshots: %d   Duel Wins: %d",
                    kills, deaths, gwWins, headshots, duelWins
                );
                g_StatsLabel.Text = newText;
                if (g_StatsLabelShadow) g_StatsLabelShadow.Text = newText;
                CenterStatsLabels();
            }
            break;

        case "onPlayerEnterVehicle":
            g_LocalVehicle = World.FindVehicle(stream.ReadInt());
            CreateSpeedTableElements();
            break;

        case "onPlayerExitVehicle":
            g_LocalVehicle = null;
            RemoveSpeedTableElements();
            break;
    }
}

SpeedTableElement <- {
    Ring = null
    Needle = null
}

function CreateSpeedTableElements(posX = 25, posY = 25) {
    SpeedTableElement.Ring = GUISprite("Ring.png", g_ZeroVector, g_FullColour);
    SpeedTableElement.Needle = GUISprite("Needle.png", VectorScreen(posX, posY), g_FullColour);
    SpeedTableElement.Ring.AddChild(SpeedTableElement.Needle);
    SpeedTableElement.Needle.Pos = g_ZeroVector;
    local tempScale = SpeedTableElement.Ring.Size;
    SpeedTableElement.Needle.RotationCentre = VectorScreen(tempScale.X / 2, tempScale.Y / 2);
    g_SpeedHint = GUILabel(VectorScreen(0,0), Colour(255,255,255,255), "Booster: G \n Stop: H");
    g_SpeedHint.FontSize = 13.5;
    g_SpeedHint.TextAlignment = GUI_ALIGN_CENTER;
    CheckAndUpdateVehicleTableUI();
}

function RemoveSpeedTableElements() {
    SpeedTableElement.Ring = null;
    SpeedTableElement.Needle = null;
    if (g_SpeedHint) g_SpeedHint = null;
}

function CheckAndUpdateVehicleTableProc() {
    if (g_LocalVehicle) {
        local speedMagnitude = sqrt(
            g_LocalVehicle.Speed.X * g_LocalVehicle.Speed.X +
            g_LocalVehicle.Speed.Y * g_LocalVehicle.Speed.Y +
            g_LocalVehicle.Speed.Z * g_LocalVehicle.Speed.Z
        );
        if (SpeedTableElement.Ring) {
            SpeedTableElement.Needle.Rotation = Lerp(SpeedTableElement.Needle.Rotation,
                                                     speedMagnitude * 100,
                                                     g_SpeedTableLerpTime);
        }
    }
}

function CheckAndUpdateVehicleTableUI() {
    if (!SpeedTableElement.Ring) return;

    local tempScale = SpeedTableElement.Ring.Size;
    local width = GUI.GetScreenSize().X;
    local height = GUI.GetScreenSize().Y;
    SpeedTableElement.Ring.Pos = VectorScreen((width - tempScale.X) - 25, (height - tempScale.Y) - 25);

    if (g_SpeedHint) {
        local ringPos = SpeedTableElement.Ring.Pos;
        local hintWidth = g_SpeedHint.Size.X;
        local hintHeight = g_SpeedHint.Size.Y;
        local hintX = ringPos.X + (tempScale.X / 2) - (hintWidth / 2);
        local hintY = ringPos.Y - hintHeight - 5;
        g_SpeedHint.Pos = VectorScreen(hintX, hintY);
    }
}

function Lerp(a, b, t) {
    return a + (b - a) * t;
}
And I want to bring the speedometer from this to my server (no need speed hint and stat text). But, I try copy and paste, editing the code but not bring me a answer (doesnt work).
I wish everyone help me!!!
My code:
main.nut in server side:
function onPlayerEnterVehicle( player, vehicle, door )
{
local stream = Stream();
    stream.WriteInt(1);
    stream.WriteString(vehicle.ID.tostring());
    stream.SendStream(player);

local vehID = vehicle.ID;
local vehName = GetVehicleNameFromModel( vehicle.Model );
local vehHealth = vehicle.Health;
ClientMessage("Phuong tien dang lai co ten: " + vehName + " [ID: " + vehID + "] Hien tai xe nay dang co: " + vehHealth + " mau", player, 255, 255, 255);
}

function onPlayerExitVehicle( player, vehicle )
{
local stream = Stream();
    stream.WriteInt(2);
    stream.SendStream(player);

}
and the begin the file:
function SendDataToClient( player, ... )
{
    if( vargv.len() > 0 && vargv[0] )
    {
        local byte = vargv[0],
              len  = vargv.len();

        if( 1 > len ) Message( "ToClient <" + byte + "> No params specified." );
        else
        {
            Stream.StartWrite();
            Stream.WriteByte( byte );

            for( local i = 1; i < len; i++ )
            {
                switch( typeof( vargv[i] ) )
                {
                    case "integer": Stream.WriteInt( vargv[i] ); break;
                    case "string":  Stream.WriteString( vargv[i] ); break;
                    case "float":   Stream.WriteFloat( vargv[i] ); break;
                    case "bool":    Stream.WriteBool( vargv[i] ); break;
                }
            }

            if( player == null ) Stream.SendStream( null );
            else if( typeof( player ) == "instance" ) Stream.SendStream( player );
            else Message( "ToClient <" + byte + "> Player is not online." );
        }
    }
}

// B?ng Byte đ?nh danh
enum StreamType {
    Speedo = 0x01
}

main.nut in client side:
local g_LocalVehicle = null;
local g_SpeedTableLerpTime = 0.2;
local g_ZeroVector = VectorScreen(0, 0);
local g_FullColour = Colour(255, 255, 255, 255);
local g_SpeedHint = null;

sX <- GUI.GetScreenSize().X;
sY <- GUI.GetScreenSize().Y;

function Script::ScriptLoad() {
    Console.Print("[CLIENT] Loaded ClientSide Successfully!!!");
}

function Script::ScriptProcess() { 
    CheckAndUpdateVehicleTableProc();
}

function GUI::GameResize(width, height) {
    sX = width;
    sY = height;
    CheckAndUpdateVehicleTableUI(); // Đã xóa CenterStatsLabels() bị lỗi!
}

function Server::ServerData(stream) {
    local packetID = stream.ReadInt();

    switch (packetID) {
        case 1: // Lên xe
            local vehID_str = stream.ReadString();
            local vehID = vehID_str.tointeger();
           
            g_LocalVehicle <- World.FindVehicle(vehID);
            CreateSpeedTableElements();
            break;

        case 2: // Xuống xe
            g_LocalVehicle = null;
            RemoveSpeedTableElements();
            break;
    }
}

SpeedTableElement <- {
    Ring = null,
    Needle = null
}

function CreateSpeedTableElements(posX = 25, posY = 25) {
    try {
        SpeedTableElement.Ring = GUISprite("sprites/Ring.png", g_ZeroVector, g_FullColour);
        SpeedTableElement.Needle = GUISprite("sprites/Needle.png", VectorScreen(posX, posY), g_FullColour);
       
        SpeedTableElement.Ring.AddChild(SpeedTableElement.Needle);
        SpeedTableElement.Needle.Pos = g_ZeroVector;
       
        local tempScale = SpeedTableElement.Ring.Size;
        SpeedTableElement.Needle.RotationCentre = VectorScreen(tempScale.X / 2, tempScale.Y / 2);
       
        g_SpeedHint = GUILabel(VectorScreen(0,0), Colour(255,255,255,255), "Booster: G \n Stop: H");
        g_SpeedHint.FontSize = 13.5;
        g_SpeedHint.TextAlignment = GUI_ALIGN_CENTER;
       
        CheckAndUpdateVehicleTableUI();
        Console.Print("[SPEEDO] Dong ho Speedometer da load thanh cong!");
    }
    catch(err) {
        Console.Print("[SPEEDO ERROR] -> " + err);
    }
}

function RemoveSpeedTableElements() {
    SpeedTableElement.Ring = null;
    SpeedTableElement.Needle = null;
    if (g_SpeedHint) g_SpeedHint = null;
}

function CheckAndUpdateVehicleTableProc() {
    if (g_LocalVehicle) {
        local speedMagnitude = sqrt(
            g_LocalVehicle.Speed.X * g_LocalVehicle.Speed.X +
            g_LocalVehicle.Speed.Y * g_LocalVehicle.Speed.Y +
            g_LocalVehicle.Speed.Z * g_LocalVehicle.Speed.Z
        );
        if (SpeedTableElement.Ring && SpeedTableElement.Needle) {
            SpeedTableElement.Needle.Rotation = Lerp(SpeedTableElement.Needle.Rotation,
                                                     speedMagnitude * 100,
                                                     g_SpeedTableLerpTime);
        }
    }
}

function CheckAndUpdateVehicleTableUI() {
    if (!SpeedTableElement.Ring) return;

    local tempScale = SpeedTableElement.Ring.Size;
    local width = GUI.GetScreenSize().X;
    local height = GUI.GetScreenSize().Y;
    SpeedTableElement.Ring.Pos = VectorScreen((width - tempScale.X) - 25, (height - tempScale.Y) - 25);

    if (g_SpeedHint) {
        local ringPos = SpeedTableElement.Ring.Pos;
        local hintWidth = g_SpeedHint.Size.X;
        local hintHeight = g_SpeedHint.Size.Y;
        local hintX = ringPos.X + (tempScale.X / 2) - (hintWidth / 2);
        local hintY = ringPos.Y - hintHeight - 5;
        g_SpeedHint.Pos = VectorScreen(hintX, hintY);
    }
}

function Lerp(a, b, t) {
    return a + (b - a) * t;
}

my sprites folder have: Needle.png and Ring.png