Jump to content

novo

Members
  • Posts

    325
  • Joined

  • Last visited

Posts posted by novo

  1. First error is caused by the function getCursorMoveOn, as it does not return any value in case isCursorShowing() returns false at line 2. Second error is because outputChatBox only accepts a player as second argument server-side (visibleTo), whilst client does not and thus expects a number (r).

  2. You get that error because number is an undefined variable, and thus equals to nil. Now, you can do table.test with alphabetical keys only - you have to do table[123] for numbers.

      
    local table = { 
        test = 'a', 
        ['something'] = 'b', 
        [1] = 'c', 
        ['test2'] = 'd', 
    } 
    print(table.test) -- a 
    print(table.something) -- b 
    print(table[1]) -- c 
    print(table['test2']) -- d 
    ---------------------------- 
    local players = {} 
    local player = getRandomPlayer() 
    players[player] = { 
        name = getPlayerName(player), 
    } 
    print(players[player].name) 
    

  3. It indeed does not check if given projectile has a target, but still does work with static elements. Now, you might instead do a per-frame check and find out whether an element interferes with the projectile, or through loop as in your code. I would do some sort of sight check around the projectile and check if there is any nearby approaching element that might end up colliding given its velocity within a certain distance.

    Also, I had a few issues calculating what the final position is going to be and dividing by 10 worked just fine there for testing, though you might want to replace this with proper calculations.

  4. function collision (projectile) 
        local time = projectile.counter / 10 
        local velocity = projectile.velocity 
        velocity = velocity * time 
        -- 
        local position = projectile.position + velocity 
        local sight, x, y, z = processLineOfSight( 
            projectile.position, 
            position, 
            true, 
            true, 
            true, 
            true, 
            true, 
            true, 
            true, 
            false, 
            nil, 
            true     
        ) 
        position = (sight and Vector3(x, y, z)) or position 
        -- 
        Marker( 
            position, 
            'corona', 
            3 
        ) 
    end 
      
    addEventHandler( 
        'onClientProjectileCreation', 
        root, 
        function() 
            collision(source) 
        end 
    ) 
      
    

  5. toptimes = { 
    {32423,"nickname"}, 
    {12313,"nickname"}, 
    }; 
      
    table.sort(toptimes, 
        function(a, b) 
            return a[1] < b[1] 
        end 
    ) 
    

    table.sort basically needs minimum two values inside the input table, toptimes in this case, and then does compare these values and thus determines their order. We have got two sub-tables inside toptimes, and those tables are the ones being compared through table.sort. This is why [1] is used, we retrieve those table's index 1 value and then check which one is smaller/bigger. However, here is a similar thing I found you may have a look at.

  6.   
    addEventHandler("onClientVehicleDamage", root, 
        function(attacker) 
            if getElementModel(source) ~= 432 then return end -- avoid this function from executing in case the vehicle that is being damaged is not a tank(?) 
            if getElementModel(getPedOccupiedVehicle(attacker)) == 432 then -- in case attacker's model is equal to 432 
                if attacker == localPlayer then -- in case the attacker tank's driver is the localPlayer 
                    outputChatBox("Don't attack friendly tanks!", 255, 0, 0) -- a warning message is output 
                end 
                cancelEvent() 
            end 
        end 
    ) 
      
    

    What about this? You could've either way tried to modify the code on your own, lol.

  7. It is not working because you are using onClientVehicleDamage's arguments in a wrong way. Either way, you are using attacter at isPedInVehicle - a non-defined variable.

      
    addEventHandler("onClientVehicleDamage", root, 
        function(attacker) 
            if getElementModel(source) ~= 432 then return end -- avoid this function from executing in case the vehicle that is being damaged is not a tank(?) 
            if getElementModel(attacker) == 432 then -- in case attacker's model is equal to 432 
                if getVehicleController(attacker) == localPlayer then -- in case the attacker tank's driver is the localPlayer 
                    outputChatBox("Don't attack friendly tanks!", 255, 0, 0) -- a warning message is output 
                end 
                cancelEvent() 
            end 
        end 
    ) 
      
    

  8. You can either go through events and trigger a client-sided event from server-side or, create a client-sided command and execute it from server-side. Both examples:

      
    -- #1 
    -- Server 
    addCommandHandler("kazandik", 
        function(player, command, ...) 
            triggerClientEvent(root, "kazandik_music", root) -- trigger this event for every player belonging to the root element, which should trigger for everyone in case you did not change any player's parent element 
        end 
    ) 
    -- Client / Add the snippet bellow into your code 
    addEvent("kazandik_music", true) 
    addEventHandler("kazandik_music", root, 
        function() 
            startMusic() -- calling and executing startMusic 
        end 
    ) 
    ----------------- 
    -- #2 
    -- Server 
    addCommandHandler("kazandik_all", -- As both, server and client sided commands, can not be named the same - we are using a different one 
        function(player, command, ...) 
            executeCommandHandler("kazandik", root) -- not sure if root can be used here instead of a player element directly / executing 'kazandik', your client-sided command that does the thing 
            -- and in case that does not work 
            for _, v in ipairs(getElementsByType("player")) do -- we iterate over a table returned by 'getElementsByType' that contains all players and 
                executeCommandHandler("kazandik", v) -- execute the command for each one of them 
            end 
         
        end 
    ) 
      
    

  9. Yeah that's it though I'd do the following:

      
    local loader = {environment = {}} 
    function loader:generate_environment () 
        self.environment = _G -- make so that it contains all mta functions, would be a mess to add them all on your own 
        self.environment.outputChatBox = function() end 
        self.environment.addEventHandler = 
            function(name, element, func) 
                -- (...) 
            end 
        -- or either / will not work 
        self.environment = { 
            outputChatBox = function() end, 
            addEventHandler = 
                function() 
                end, 
            triggerServerEvent = function() end, -- avoid server events triggering 
            -- or either 
            triggerServerEvent = function(name, element, ...) return triggerEvent(localPlayer, name, localPlayer, ...) end, -- redirect it towards the client itself 
        } 
        for k, v in pairs(_G) do 
            if k ~= "loader" then -- our loader's 'global'-'environment' 
                self.environment[k] = v 
            end 
        end 
    end 
      
    

    Just realized that doing it the second way is not really possible as the for loop would be overwriting your functions. You can instead, would be foolish though, place your functions into another table and then set your environment equal to _G and use a for loop with your functions' table this time instead. However, go through the first way.

    You can then simply execute generate_environment each time you want to reset/restart it after, of course, removing and destroying all unnecessary stuff.

  10. I guess that your issue might be caused by the fact that you are using addEventHandler when adding your custom events - onScriptLoadRequest, onScriptUnloadRequest. Another reason to use an environment instead. So yeah, either use the wrapper instead (_addEventHandler) or start with the environment thingy.

  11. I suggest also to store all functions and variables into own environment using setfenv.

    That basically is what you should do in order to avoid most security issues and in case you want to run all the functions attached to onClientResourceStart, simply set another event name for the handler that you can afterwards manually-trigger in order to execute all those functions simultaneously (without actually triggering onClientResourceStart).

  12. Though there are many security-issues related to loading code that way, the one-issue you're going through on your last post is you are not triggering onClientResourceStart, event responsible of executing startMusic function (as, this way, you are not running a resource on its own and thus such event is not being run).

  13. Actually, under onClientDownloadFinish you are, for some reason, using 'player' as if there was any argument expected to arrive - whilst you do not send/specify any when triggering (line 5, uniquely specifying gMe as the event's source). So I guess you instead wanted to use 'client', respective element reference to the player that triggered the event.

    Also note that there may be a short timespan between which the 'transferring box' is hidden and then shown up again, same span that might cause your timer to trigger the event that hides your custom messages. So basically, I would recommend you to increase your timer's interval up to 2000ms as specified in the example here.

    function onClientDownloadFinish() 
        if textDisplayIsObserver(DownloadDisplay, client) then 
            textDisplayRemoveObserver(DownloadDisplay, client) 
        end 
    end 
    

×
×
  • Create New...