Jump to content

RottenFlesh

Members
  • Posts

    189
  • Joined

  • Last visited

Posts posted by RottenFlesh

  1. Wow this is awesome! Having to upload and download a compiled file from the webpage is really annoying. So thanks! This is very useful! :)

    Just a question: With this method the files are extra-obfuscated? Or just normal compiled?

    BTW: I get this warning in the console of Sublime:

    WARN Without -s or -e, compiled files contains debug information and can be more easily decompiled (script.lua) 
    

  2. Gracias por tu recomendación!

    Como has podido observar, los tutoriales son bastante sencillos, están orientados mas que nada hacia las personas que apenas comienzan, por eso es que me centro en temas bastante específicos, así no esta muy saturada la información.

    Ahorita apenas me voy adentrando en explicar las estructuras de control, los siguientes serán sobre loops y luego empezare a hablar sobre las librerías que trae lua.

  3.   
    playerData = {} 
      
    function set_data(player_element, data_key, data_value) -- export this function 
        if type(player_element) == "nil" or type(data_key) == "nil" or type(data_value) == "nil" then return false end 
      
        if not playerData[player_element] then 
            playerData[player_element] = {} 
        end 
      
        playerData[player_element][data_key] = data_value 
        return true 
    end 
      
    function get_data(player_element, data_key) -- export this function 
        if type(player_element) == "nil" or type(data_key) == "nil" then return false end 
      
        return playerData[player_element] and playerData[player_element][data_key] or false 
    end 
      
    function delete_data() -- you have to delete the data when the player quits 
        playerData[source] = nil 
    end 
    addEventHandler('onClientPlayerQuit', root, delete_data) 
      
    

    That will not work, as onClientPlayerQuit is only triggered on remote clients. You have to make this system server side, and the use triggerServerEvent and triggerClientEvent to get the data client-side.

  4. Una reacción rápida promedio de un humano dura un poco mas de 200 milisegundos. Acá estamos hablando de apenas decenas de milisegundos, esos son tiempos sumamente rápidos. Entiendo que por ejemplo en un gamemode race es realmente necesaria mucha rapidez de procesamiento (que el mapa vaya cargando mas lento de lo que conduces es fatal!). Pero en otros tipos de gamemode no veo donde esta la importancia de ahorrarse una cantidad tan mínima.

    http://www.humanbenchmark.com/tests/reactiontime/stats.php

  5. Bueno, yo también hice mis pruebas. Aquí están los resultados:

    Procedimental:

    Metodo:

    -- Crear 1000 objetos, obtener la matris de uno y crear el siguiente adelante y a la derecha del anterior. 
      
    ------------------- 
    -- PROCEDIMENTAL -- 
    ------------------- 
      
    local inicio = getTickCount() 
      
    function getPositionFromElementOffset(element,offX,offY,offZ) 
        local m = getElementMatrix ( element ) 
        local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1] 
        local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2] 
        local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3] 
        return x, y, z 
    end 
      
    local rotZ = 0 
    local cuenta = 1 
    local x, y, z = -1238, -180, 15 -- posiciones iniciales en el aero de SF 
      
    for i=1, 1000 do 
        local v = createVehicle(411, x, y, z, 0, 0, rotZ) 
        setElementFrozen(v, true) 
        x, y, z = getPositionFromElementOffset(v,5,5,0) 
        rotZ = rotZ + 90 
        cuenta = cuenta + 1 
        if cuenta > 4 then 
            z = z + 1.5 
            cuenta = 1 
        end 
    end 
      
    local fin = getTickCount() 
    outputDebugString("resultado: "..fin - inicio, 3) 
    

    Resultados en 10 pruebas:

    20 + 18 + 19 + 20 + 20 + 20 + 21 + 19 + 19 + 21 = 197

    197 / 10 = 19.7 milisegundos.

    OOP: por cierto, oop tampoco existe en español, tendrías que decir POO.

    Metodo:

    -- Crear 1000 objetos, obtener la matris de uno y crear el siguiente adelante y a la derecha del anterior. 
      
    ------------------------------------ 
    -- VECTORES Y ORIENTADO A OBJETOS -- 
    ------------------------------------ 
      
    local inicio = getTickCount() 
      
    local rotZ = 0 
    local cuenta = 1 
    local pos = Vector3(-1238, -180, 15) -- posiciones iniciales en el aero de SF 
      
    for i=1, 1000 do 
        local v = Vehicle(411, pos, 0, 0, rotZ) 
        v.frozen = true 
        pos = pos + v.matrix.forward * 5 
        pos = pos + v.matrix.right * 5 
        rotZ = rotZ + 90 
        cuenta = cuenta + 1 
        if cuenta > 4 then 
            pos.z = pos.z + 1.5 
            cuenta = 1 
        end 
    end 
      
    local fin = getTickCount() 
    outputDebugString("resultado: "..fin - inicio, 3) 
    

    Resultados en 10 pruebas:

    37 + 37 + 38 + 37 + 37 + 38 + 37 + 38 + 36 + 35 = 370

    370 / 10 = 37 milisegundos

    Conclusión:

    Efectivamente, tras hacer las pruebas, se puede concluir que la implementación OOP es mas lenta que la procedimental, en este caso la diferencia son 17.3 milisegundos. Pero debemos tomar en consideración también los siguientes aspectos:

    Primero: En este contexto estamos hablando de crear mil autos, no es una situación común y el tiempo al final dependerá del script que estés creando.

    Segundo: Se logró reducir de 34 a 27 lineas un script pequeño como este. Se imaginan cuanto código es posible ahorrar en scripts de miles de lineas?

    Tercero: Los problemas de fluctuación del tiempo de ejecución también me pasaron, pero eran debido a laag generado por estar muy cerca del área donde se crearon los autos. Al alejarme los resultados cambiaron dramáticamente e incluso la implementación oop fue mas estable que la procedimental.

    Lo dejo a decisión de cada quien, por mi parte yo voy a seguir usando OOP. :lol:

  6. En términos de eficiencia OOP es una aberración, sobretodo en un juego en línea donde cada milesima de segundo importa. A mi parecer la comodidad que OOP significa se ve completamente opacada por su poca o nula eficiencia, evitarla tanto como sea posible debe ser una prioridad.

    Y la fuente de esta información la sacaste de donde?

    *De lo siguiente no estoy seguro, así que no te lo tomes enserio:

    Mira, yo he leído los archivos del código fuente donde esta programado el OOP, y esos archivos simplemente hacen referencia a las funciones normales.

    Ademas, que no es C mas rápido que lua? Si es asi, entonces es mas rápido hacer todos esos cálculos en C, que llamar la función getElementMatrix y hacer los cálculos tu mismo, ademas que de igual forma tiene que hacer varios cálculos internamente en MTA, no es mejor que directamente se encargue de todo?

    Claro, en este contexto especifico de las matrices...

    Acá esta el código fuente del que te hablaba:

    OOP client-side: https://code.google.com/p/mtasa-blue/source/browse/trunk/MTA10/mods/shared_logic/lua/CLuaMain.cpp

    OOP server-side: https://code.google.com/p/mtasa-blue/source/browse/trunk/MTA10_Server/mods/deathmatch/logic/lua/CLuaMain.cpp

    Nomas dale al Ctrl+F y busca la función que quieras. Ahí están programadas las referencias a las funciones de las matrices y los vectores también.

    Si quieres ponemos esto a prueba, de OOP vs el tradicional procedural. Hacemos múltiples pruebas, les sacamos promedio y vemos quien tiene la razón. Nos ponemos de acuerdo en que métodos vamos a usar para hacer la prueba y lo dejamos todo claro desde el principio sin entrar a discusiones sin sentido y sin fundamento. Que te parece?

  7. Aaaah bueno, esta bien entonces.

    Solo como un dato interesante, a quien le interese saber... Para obtener la posición enfrente del player en MTA 1.4, puedes hacer esto:

    local pos_enfrente = player.position + player.matrix.forward * 2 
    

    Con eso obtienes la posición a dos metros de distancia, enfrente del jugador, no importa hacia adonde este viendo.

    Luego para usarlo nomas haces esto:

    createVehicle(modelo, pos_enfrente) -- Sí, las funciones como estas ya aceptan vectores, ya no es necesario escribir las tres coordenadas. 
    

    O si prefieres hacerlo en OOP, lo haces así:

    Vehicle.create(modelo, pos_enfrente) -- Incluso se puede hacer sin el ".create", solo con Vehicle(cosas), pero no estoy seguro por que no lo he probado aún. 
    

  8. Is it possible to create a bean?

    - Like a class having some attributes; Example:

    class Player{ 
        private nick; 
        private kills; 
        private cash; 
    } 
    

    and then being able to do something like aPlayer.setNick(hisNick);

    :mrgreen:

    If you have a player variable, you can do something like this:

    function command(player) 
        player.name = "something" 
        outputChatBox(player.name) 
         
        player.money = 100 
    end 
    addCommandHandler("blah", command) 
    

    But they are predefined by MTA, you can not create your own, unless you make your own implementation of OOP in lua using tables and metatables.

    We are slowly documenting the OOP syntax in wiki. i've already documented almost every server-side player functions by myself.

    https://wiki.multitheftauto.com/wiki/Server_Scripting_Functions#Player_functions

    There, you will see something like this:

    [b]OOP Syntax[/b] 
    [b]Method[/b]: player:getName() 
    [b]Variable:[/b] .name 
    [b]Pair:[/b] setPlayerName 
    

    It means you can do things like this:

    function some_random_function(player) 
        local name = player:getName() -- element -> "player"; method -> ":getName()" 
        local name = player.name -- ".name" is just short for getPlayerName() 
        -- And the pair function is used when you have a variable like the one above and you set a value to it. 
        player.name = "something" -- in this case you are not calling getPlayerName(), but setPlayerName() is used instead.  
    end 
    

    There is also methods and variables that are declared under some object Class.

    Like this:

    function some_other_random_function() 
        Player.getRandom() -- "Player", is a class that contains all player methods and variables, and ".getRandom()" is one of those methods. 
        Player.random -- This is just a short form of the above. Both valid. 
    end 
    

    I hope you understand what i said, English is not my native language :)

  9. addEvent("mostrarLog", true) 
    function showGangLog( theGangName ) 
    local theGangLogTable = {} 
    local theLog = executeSQLQuery("SELECT Log FROM theGangLog WHERE NameGroup=?", theGangName) 
    -------------------------------"SELECT * FROM punishments WHERE serial=? 
    if (not theLog) then return end 
    for i, log in ipairs(theLog) do 
        theGangLogTable[i] = log["Log"] 
    end 
    triggerClientEvent(source, "setGangLog", source, theGangLogTable ) 
    theGangLogTable = {} 
    end 
    addEventHandler("mostrarLog", root, showGangLog ) 
    

    Dime si te funciona esto.

  10. Yeah, but you need to set the player element as the key for the sub-tables. like this:

    playerData = {} 
      
    function set_data(player_element, data_key, data_value) -- export this function 
        if type(player_element) == "nil" or type(data_key) == "nil" or type(data_value) == "nil" then return false end 
      
        if not playerData[player_element] then 
            playerData[player_element] = {} 
        end 
      
        playerData[player_element][data_key] = data_value 
        return true 
    end 
      
    function get_data(player_element, data_key) -- export this function 
        if type(player_element) == "nil" or type(data_key) == "nil" then return false end 
      
        return playerData[player_element] and playerData[player_element][data_key] or false 
    end 
      
    function delete_data() -- you have to delete the data when the player quits 
        playerData[source] = nil 
    end 
    addEventHandler('onPlayerQuit', root, delete_data) 
    

    Then, if you export those functions, you can call them from any resource this way:

    exports.resourceName:set_data(player, "SQLID", 1231231) 
    exports.resourceName:set_data(player, "Username", "Booth") 
    exports.resourceName:set_data(player, "Password", "12345") 
      
    exports.resourceName:get_data(player, "SQLID") 
    exports.resourceName:get_data(player, "Username") 
    exports.resourceName:get_data(player, "Password") 
    

    And this is how you would do a basic good-enough data system. :)

  11. do this after line 16:

    outputDebugString("s.weap data: "..tostring(weap), 3) 
    outputDebugString("s.ammo data: "..tostring(ammo), 3) 
    

    What does it output?

    And are you shure you are logged in when you test this script?

  12. You have defined the "target" variable until line 8, and as it is local it will only work inside the scope of that function. You have to declare the "target" variable outside the function or move everything inside the function.

  13. Primero. Para que usas tonumber? si estas sumando dos números, el resultado siempre va ser un numero. Incluso, si tu sumas un numero con un string, el resultado va a ser un numero también. Si quieres comprobarlo puedes hacer esto:

    outputChatBox(type( 5 + 5 )) -- > esto te da numero 
    outputChatBox(type( 5 + "10" )) -- > esto te da numero tambien 
    

    okey, y para agregar los ceros puedes hacer algo así:

    local ntest = "0000" -- aca pon los ceros que quieras 
    local id = 32 
    local ntest_digitos = string.len(ntest) -- con esto obtenemos el numero de ceros 
    local id_digitos = string.len(id) -- y con esto el numero de digitos de la id 
      
    if id_digitos < ntest_digitos then 
        id = string.sub(ntest, 1, ntest_digitos - id_digitos) .. id 
    end 
      
    outputChatBox(id) 
    

    de esta forma puedes poner la cantidad de ceros que quieras, pero recuerda que al final te resultará un string, si lo conviertes de nuevo a numero se le borrarán esos ceros.

×
×
  • Create New...