Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Posts posted by IIYAMA

  1. 18 minutes ago, 31cmTrueDamage said:

    Thank you, sorry to bother, but what recommendations do you have to work better in multiplayer,

    For multiplayer you have to store data for each player. And one of the ways to do that is using tables.


    Here some basic functions you could use.

    • Init the storage first: initPlayerData (onPlayerJoin)
    • And after that you can set and get data from the table, for each player: getPlayerData, setPlayerData
    • When a player disconnects: deletePlayerData (onPlayerQuit)


    ---@type {[userdata]: {[string]: unknown}|nil}
    local playerDataCollection = {}
    ---@param player userdata
    ---@param key string
    ---@return unknown|nil
    function getPlayerData(player, key)
        local playerData = playerDataCollection[player]
        if not playerData then return end
        return playerData[key]
    ---@param player userdata
    ---@param key string
    ---@param value any
    function setPlayerData(player, key, value)
        local playerData = playerDataCollection[player]
        if not playerData then return end
        playerData[key] = value
    --- Create a storage table for data of a specific player
    ---@param player userdata
    function initPlayerData(player)
        if playerDataCollection[player] then return end
        playerDataCollection[player] = {}
    --- Remove all player data and remove it's storage table
    ---@param player userdata
    function deletePlayerData(player)
        if not playerDataCollection[player] then return end
        playerDataCollection[player] = nil





  2. 17 hours ago, 31cmTrueDamage said:

    so i guess i am not getting the player position correctly maybe? not sure.

    Your initial code looked fine except for a duplicated message when you are in the marker:

    Stage time:
    Stage finished! Time:


    Here you have an alternative version + debug lines so that you can validate what is wrong.

    View in debug console: /debugscript 3


    Also keep in mind that this code will not work very good in multiplayer, as startTime, startMarker and finishMarker are shared between all players.


    You can ignore the ---@ annotations, those are helping me to automatic validate your code. (and perhaps help you to improve readability)


    -- Add to top of script (local's making sure other scripts can't modify these values by accident)
    ---@type integer
    local startTime = 0
    ---@type userdata|nil
    local startMarker
    ---@type userdata|nil
    local finishMarker
    -- ... --
    ---@param player userdata
    function checkStageProgress(player)
        iprint("Validate player", player, isElement(player) and getElementType(player))
        if not isElement(startMarker) or not isElement(finishMarker) then
            iprint("Not startMarker:", isElement(startMarker) and "It exist" or "does not exist", "or not finishMarker:", isElement(finishMarker) and "It exist" or "does not exist")
        if not raceInProgress then
            iprint("Race is not in progress")
            local startX, startY, startZ = getElementPosition(startMarker)
            local playerX, playerY, playerZ = getElementPosition(player)
            local distanceToStart = getDistanceBetweenPoints2D(startX, startY, playerX, playerY)
            if distanceToStart <= 3 then
                raceInProgress = true
                startTime = getTickCount() -- Start counting time
                outputChatBox("Stage started!", player)
        -- Race is in progress --
        local elapsedTime = math.floor((getTickCount() - startTime) / 1000) 
        if isElementWithinMarker(player, finishMarker) then
            outputChatBox("Stage finished! Time: " .. elapsedTime .. " seconds.", player)
            raceInProgress = false
        -- Player is not in marker --
        outputChatBox("Stage time: " .. elapsedTime .. " seconds.", player)



  3. On 11/03/2024 at 01:14, Snakegold said:

    ERROR: Client "playername" triggered serverside event onPlayerDamage, but event is not marked as remotely triggerable

    • Double check if the serverside file is running and init as serverside.
    • Do not enable remote for native events. This is a security risk.
    • Use the predefined client variable for remote triggers, else cheaters can kill a whole server instantly.


    iprint(triggerClientEvent and "serverside" or "clientside") -- inspect if the file is running serverside
    addEvent("onPlayerDamage", false) -- disable remote
    function handlePlayerDamage(attacker, weapon, bodypart, loss)
        if client ~= source then return end
        local victim = client
        triggerEvent("onPlayerDamage", victim, attacker, weapon, bodypart, loss) -- emulate the (client) cancelled onPlayerDamage event
        if getElementHealth(victim) > 0 then
            setElementHealth(victim, getElementHealth(victim) - loss)
            if getElementHealth(victim) <= 0 then
                setElementData(victim, "isDead", true)
    addEvent("onCustomPlayerDamage", true)
    addEventHandler("onCustomPlayerDamage", root, handlePlayerDamage)
    function isPlayerDead(player)
        return getElementData(player, "isDead") or false


    function onClientPlayerDamage(attacker, weapon, bodypart, loss)
        if attacker and getElementType(attacker) == "player" then
            triggerServerEvent("onCustomPlayerDamage", localPlayer, attacker, weapon, bodypart, loss)
    addEventHandler("onClientPlayerDamage", root, onClientPlayerDamage)


  4. 7 hours ago, Snakegold said:

    I want to ensure that only one player dies in such situations.

    Technically it is possible, but it will only work as intended when the latency is very low (< 60 ping) and stable internet (no packet loss).

    How it technically works is that the server is used as mediator for all the damage. When a player it's health is 0, all future damage done by this player is ignored.

    But keep in mind that this will look very weird when the latency is too high. (unplayable)


    Some basics:














  5. 2 hours ago, Ryan167 said:

    how could I make the marker only trigger on dimension 11?

    If the parameter matchingDimension contains the value true, the marker is hit in the same dimension.

    2 hours ago, Ryan167 said:

    What I'm trying to do is have a marker in dimension 11 and when the player joins the marker the player can't use a jetpack (it works but it stays working even outside the marker) and the weapons disabled, which works fine.

    Instead of setting a timer. Which currently is being created infinity > crashing the server at a given point.

    Do the following:

    When giving a jetpack, check if the player is inside of the marker. Based on that, give the Jetpack yes / no.

    -- Making the marker find able inside of another resource
    local antiJetpack = createElement ( "antiJetpackType", "antiJetpackID" )
    local marker = createMarker ( 0, 0, 0, "cylinder", 1.5, 255, 255, 0, 170 )
    setElementParent(marker, antiJetpack)

    (Other resource)

    local parent = getElementByID ("antiJetpackID")
    if not parent then return end  
    local marker = getElementChildren ( parent )[1]
    local status =  isElementWithinMarker ( thePlayer, marker )




  6. 23 hours ago, RandomRambo said:

    and one more thing...where I can download mta 1.6n?Cus it says I need it to join the server on mta-1.6.0-unstable-7976-net41DA build on which it works...

    Can't you just copy your Program Files (x86)\MTA San Andreas 1.6\server to the server? (maybe I am missing something, but a windows server should be able to start up windows stuff)

  7. 3 hours ago, pixel77 said:

    data[1] and data[2] are numbers. 

    For example: inUseData[12][5] = true

    The client is clicking on a dxDraw button, that is rendered on the 3D World. 

    Then the code looks fine. Unless the numbers are a mixture of numbers and strings. 123 vs "123"


    16 hours ago, pixel77 said:

    So they can run the "--some more code here to do things" in the same time, and I don't want to allow this.

    In theory it shouldn't be possible because this function is ran single threaded. There will always be one that is first. The whole function chain-call should have been ended before a new call can be made.

    The following should be finished before the root function can be called again.

    16 hours ago, pixel77 said:
    --some more code here to do things



    • Thanks 1
  8. 3 hours ago, RandomRambo said:

    Config changed after I installed latest build so config isn't the real problem.

    It can be an issue if you used the config of an older build.


    3 hours ago, RandomRambo said:

    It works perfectly on 1.5.9 builds,but on 1.6 it just restarts all time and no errors in console -_-

    You checked the logs as well? (sometimes not all errors are visible in the console)

    And what kind of server are you running? Windows or linux?

    If it is Windows, you should be able to copy over your local server and try that one.

    If Linux, you might consider starting it up with sudo, so that it does not run in to any permission issues while creating/moving the initial files.



  9. On 17/02/2024 at 21:20, RandomRambo said:

    So,what is the problem that my server doesn't start on stable 1.6 build?:(

    Is this server installed with MTA or did you download the stable version separately?

    Things to check/do:

  10. 5 hours ago, pixel77 said:

    Any other methods?

    A hard function skip maybe, just to figure out if it is actually the models. 🤔

    addDebugHook( "preFunction", function ( ) return "skip" end, {"engineLoadCOL", "engineReplaceCOL", "engineLoadTXD", "engineImportTXD", "engineLoadDFF", "engineReplaceModel"})

    (if possible run the hook on a resource with higher download priority)


    If that is the issue, then rewrite the resources so that the models are loaded slower. For example load a model every X frame(s).

  11. 1 hour ago, aRRRtem said:

    So my question is how can I track other client`s software to block players with rippers?

    I believe you should first understand the underlying problem.


    1 hour ago, aRRRtem said:

    steal my game client files

    They are not stealing your files. You are sending those files to them. When they host your files, this is where they are using your files without permission.



    where they use your files without permission

    This is where I recommend to solve your problem. They are using your files because they are appealing to be used. If you make them less appealing, for example by adding branding to them, this will become advertisement for your server (in their server).

  12. On 07/02/2024 at 21:24, Hiding said:

    so I want my arrow marker to be visible even if there's an object front of it that obscures it.

    You could try to use the dxDrawPrimitive3D function to mimic the marker and set postGUI to true, just keep in mind the downsides of postGUI.


    © MTA wiki


    • Like 1
  13. 4 hours ago, FreezyMTA said:

    I gave HTTP authorization from ACL and meta.xml, but it still does not work.

    You probably already did the following, but just checking.
    What happens if you visit those URL's manually? (maybe it is asking for a login authorisation)

  14. 5 hours ago, Turbe$Z said:

    what wrong with the loop?


    You have to index the variable veh one time less. Since the pairs loop did the first index already for you.


    dxDrawText(veh[k][1].." | "..veh[k][2], sx/2-370,sy/2-297,sx/2,sy/2, tocolor(255, 255, 255, 220), 3, "default-bold", "left", "top", false, false, false, true )

    dxDrawText(veh[1].." | "..veh[2], sx/2-370,sy/2-297,sx/2,sy/2, tocolor(255, 255, 255, 220), 3, "default-bold", "left", "top", false, false, false, true )
    • Thanks 1
  15. 6 hours ago, Snow-Man said:

    what confuses me that when i get table into another tables inside and when i try to get a return from what?


    Sometimes it really helps when you use the iprint function to print the current table. It shows you the current depth and helps you to decide how to index the next table.


    When I for example I am working with a secret table.



    	["test"] = {
    				[133]="found me!"


    The first step is to peel it down.


    Layer 1



    			[133]="found me!"


    Layer 2



    		[133]="found me!"


    Layer 3



    	[133]="found me!"


    Layer 4



    "found me!"




  16. 21 hours ago, Snow-Man said:

    im lost through a lot of tables 

    It helps if you write every table modification inside of a new function. This way you keep your code more readable.

    The following examples are re-written code. You could use this as a start, but make sure to test it, because I didn't test it for you.


    local farm = createFarm(123, 1, 1, 1)


    local horse = createHorse(player, horseId)
    local farm = getFarmFromID (123)
    -- If the farm does exist
    if farm then
        addHorseToFarm(horse, farm)



    local horseCollection = {} -- all horses
    local farmCollection = {} -- all farms
    ---@param player userdata
    ---@param horseId integer
    ---@return table
    function createHorse(player, horseId)
        local horse = { id = horseId }
        horseCollection[horseId] = horse
        return horse
    ---@param farmId integer
    ---@param x number
    ---@param y number
    ---@param z number
    ---@return table
    function createFarm (farmId, x, y, z)
        local marker = createMarker(x, y, z)
        local farm =  {
            marker = marker, 
            id = farmId, 
            location = { x, y, z }, 
            owner = nil, 
            creator = nil, 
            creationTime = getTickCount(), 
            price = 0, 
            horses = {}
        farmCollection[farmId] = farm
        return farm
    ---@param farmId integer
    ---@return table|false
    function getFarmFromID (farmId)
        return farmCollection[farmId] or false
    ---@param farm table
    ---@param player userdata
    ---@return table
    function setFarmCreator (farm, player)
        farm.creator = player
        return farm
    ---@param horse table
    ---@param farm table
    function addHorseToFarm (horse, farm)
        table.insert(farm, horse)
    ---@param horse table
    ---@param farm table
    ---@return boolean
    function isHorseInFarm(horse, farm)
        for i=1, #farm do
            if farm[i] == horse then return true end
        return false
    ---@param farmId integer
    ---@return boolean
    function doesFarmExist(farmId)
        return farmCollection[farmId] and true or false


    • Like 2
  • Create New...