Quantcast
Channel: SA-MP Forums
Viewing all articles
Browse latest Browse all 18226

[Tutorial] YSI - y_iterate

$
0
0
y_iterate

Introducción
¿Han escuchado alguna vez de foreach? Espero que sí porque todo parte de ahí, Y_Less en su momento creó un include independiente llamado así. En pocas palabras, este include permite iterar arrays fácilmente, sin tener que recorrer celdas inválidas. Menciono que un iterador, en nuestro caso, es como una lista a la que le podemos aplicar foreach. Podemos crear nuestros propios iteradores para añadir los elementos que deseemos.

y_iterate es una especie de foreach, pero está mucho más integrado dentro de YSI y conecta con otros elementos como y_groups, y_commands, y_bit, etc. Iremos por partes porque este include es muy grande.

Por ejemplo, a día de hoy lo más normal es encontrarnos con algo como esto:
PHP Code:

for(new 0GetPlayerPoolSize(); <= ti++)
{
    if(!
IsPlayerConnected(i)) continue;
    
// Nuestro código.


Ese es el método más común de iterar arrays o crear un bucle. Con y_iterate podemos reducir lo anterior a algo muy sencillo:
PHP Code:

foreach(new Player)
{
    
/*
    Itera a través de la lista de jugadores reales válidos. No hace falta comprobar si están
    conectados porque la lista que se itera contiene solamente a los jugadores conectados.
    */


Una de las características más llamativas es que los iteradores predefinidos solamente recorren elementos válidos, es decir, no se paran a comprobar si una ID es válida o si un cierto jugador está conectado. Existen ciertos eventos en los que los elementos se añaden/eliminan de las listas, una vez están dentro es muy fácil acceder a ellos. En resumen, estos iteradores son mucho más rápidos que los bucles estándar del ejemplo superior.

Obsolescencia
Si van a utilizar el antiguo formato de foreach con y_iterate obtendrán un warning, el formato correcto es el que vimos en el ejemplo de la introducción. Lo siguiente todavía funciona pero lo ideal es actualizar.
PHP Code:

foreach(Playeri/* Warning: using_deprecated_foreach_syntax */ 

Iteradores predefinidos
El include trae ciertos iteradores ya definidos para simplificarnos un poco las cosas, podemos desactivarlos si lo deseamos y el include deja de rastrear dichos elementos. Primero veamos todos los iteradores que tenemos disponibles:
  • Player
    Este iterador nos sirve para iterar a través de los jugadores conectados.
    PHP Code:

    foreach(new Player)
    {
        
    SendClientMessage(i0xFF0000FF"Bienvenido, estás conectado y eres un jugador real.");


  • Character
    Aquí iteraremos a través de los jugadores reales y los NPC conectados.
    PHP Code:

    foreach(new Character)
    {
        if(
    IsPlayerNPC(i)) SendClientMessage(i0xFFFFFFFF"Eres un NPC y estás conectado.");
        else 
    SendClientMessage(i0xFFFFFFFF"Eres un jugador real y estás conectado.");


  • Bot
    Con esto solamente iteraremos a través de los NPC conectados.
    PHP Code:

    foreach(new Bot)
    {
        
    SendClientMessage(i0xFFFFFFFF"Eres un NPC y estás conectado.");


  • Actor
    Con esto podemos recorrer las IDs de todos los actors que se han creado en el servidor.
    PHP Code:

    foreach(new Actor)
    {
        
    printf("La ID del actor es: %d."i);
    }

    /*
    Pueden usar LocalActor en lugar de Actor para iterar solamente a través de los actors
    que se han creado exclusivamente desde el mismo script en el que se ha incluido y_iterate.
    */ 

  • Vehicle
    Aquí iteramos a través de todos los vehículos que se han creado en el servidor.
    PHP Code:

    foreach(new Vehicle)
    {
        
    printf("La ID del vehículo es: %d."i);
    }

    /*
    Pueden usar LocalVehicle en lugar de Vehicle para iterar solamente a través de los vehículos
    que se han creado exclusivamente desde el mismo script en el que se ha incluido y_iterate.
    */ 

Como dije, estos iteradores se pueden desactivar. Si no vamos a utilizar alguno de ellos nos viene bien hacerlo porque así no están funcionando en segundo plano para nada. Para ello debemos definir alguna de las siguientes opciones antes de incluir y_iterate.
  • FOREACH_NO_PLAYERS - Desactiva todos los iteradores relacionados a los jugadores, NPC y actors.
  • FOREACH_NO_BOTS - Desactiva los iteradores Character y Bot.
  • FOREACH_NO_VEHICLES - Desactiva los iteradores Vehicle y LocalVehicle.
  • FOREACH_NO_ACTORS - Desactiva los iteradores Actor y LocalActor.
  • FOREACH_NO_LOCALS - Desactiva los iteradores LocalVehicle y LocalActor.
Un pequeño ejemplo:
PHP Code:

#include <a_samp>

#define FOREACH_NO_BOTS

#include <YSI-Includes\YSI\y_iterate> 

Declarar un iterador
Todo lo anterior representa solamente una pequeña parte de y_iterate, todavía quedan muchas cosas por ver. Si crees que lo único que vas a utilizar son los iteradores predefinidos puedes ignorar todo lo que sigue. Bueno, podemos crear nuestros propios iteradores, podemos añadir los elementos que deseemos y recorrerlos de diversas formas.
  • Iterador unidimensional
    A continuación vamos a crear un iterador, como veréis vamos a especificar el número máximo de elementos que puede albergar, que pueda albergar 500 elementos no significa que se repita 500 veces. Un iterador se repite tantas veces como elementos contenga, es decir, los que nosotros añadamos.
    PHP Code:

    new Iterator:Ejemplo<10>; /* Este iterador puede albergar 10 elementos */

    /* Añadimos elementos, atentos a los valores que añadimos */
    Iter_Add(Ejemplo5);
    Iter_Add(Ejemplo0);
    Iter_Add(Ejemplo9);

    /* Iteramos */
    foreach(new Ejemplo)
    {
        
    printf("%d"x);
    }

    /*
    Resultado:
    0
    5
    9
    */ 

    IMPORTANTE: en un iterador no podemos añadir valores superiores al número de elementos que puede albergar. En el ejemplo anterior no podemos añadir el número 15 porque de 0 a 9 ya hay 10 valores. Es como si "activáramos" uno de los números que hay por debajo del número de elementos máximos. De hecho, si se fijan en el resultado del código anterior, los números salen en orden ascendente. Esto tiene sentido, piensen en el caso de los jugadores, no tiene sentido añadir IDs superiores en el iterador a las que realmente pueden existir.

  • Iterador multidimensional
    Un iterador multidimensional es un iterador en el que existen múltiples listas sobre el mismo conjunto de elementos.
    PHP Code:

    /* Creamos cinco iteradores, cada uno puede albergar un máximo de 10 elementos (0 - 9) */
    new Iterator:Ejemplo[5]<10>;

    /* Este tipo de iterador debe inicializarse, por ejemplo, en OnGameModeInit */
    Iter_Init(Ejemplo);

    /* En algún lugar */
    Iter_Add(Ejemplo[2], 9);
    Iter_Add(Ejemplo[2], 2);

    foreach(new 
    Ejemplo[2])
    {
        
    printf("%d"x); /* Resultado: 2 9 */
    }

    Iter_Add(Ejemplo[0], 5);
    Iter_Add(Ejemplo[0], 0);

    foreach(new 
    Ejemplo[0])
    {
        
    printf("%d"x); /* Resultado: 0 5 */


    Veamos otro caso, imaginemos una lista de vehículos adquiridos. El conjunto de elementos son los vehículos, cada jugador puede tener una lista de los vehículos que posee y cada vehículo puede tener como máximo un propietario. Podríamos hacer algo como esto:
    PHP Code:

    new Iterator:MisCoches[MAX_PLAYERS]<MAX_VEHICLES>;

    /* OnGameModeInit */
    Iter_Init(MisCoches);

    /* En algún sitio. */
    Iter_Add(MisCoches[2], 50); // Añadimos el coche con la ID 50 al iterador del jugador con la ID 2.
    Iter_Add(MisCoches[5], 50); // Añadimos el coche con la ID 50 al iterador del jugador con la ID 5.

    /*
    Lo anterior no cumple la condición "cada vehículo puede tener como máximo un propietario", además
    tener 500 iteradores con 2000 slots cada uno no es nada óptimo (MAX_PLAYERS * MAX_VEHICLES).
    */ 

    Una solución alternativa al problema anterior es la siguiente:
    PHP Code:

    new Iterator:MisCoches<MAX_PLAYERSMAX_VEHICLES>

    /*
    Lo anterior reduce el número de slots, dado que equivale a MAX_PLAYERS + MAX_VEHICLES.
    Por otro lado, un vehículo solo puede aparecer en un iterador, no se puede repetir una misma
    ID en un iterador diferente. Por ende, esto cumple la condición impuesta, un vehículo solo puede
    ser comprado por un jugador. No hace falta inicializar este tipo de iterador.
    */

    Iter_Add(MisCoches<2>, 50); // Asignamos el vehículo con la ID 50 al jugador con la ID 2.
    Iter_Add(MisCoches<5>, 50); // Esto fallaría, dado que la ID 50 ya está en uso.

    /* Iteramos a través de los vehículos adquiridos por un jugador. */
    foreach(new vid MisCoches<playerid>)
    {
        
    printf("vehicleid: %d"vid);


    En este último ejemplo hemos visto cómo crear varios iteradores y "compartir" el conjunto de elementos entre todos ellos, es decir, un elemento solo puede estar en uno de los iteradores (nunca en más de uno). El formato que hemos seguido es: <ITERADORES, ELEMENTOS>. También tenemos funciones como:
    PHP Code:

    new Iterator:Coches<MAX_PLAYERSMAX_VEHICLES>;

    /* Comprobar si un valor está en un iterador en concreto */
    if(Iter_Contains(Coches<playerid>, 10))
    {
        print(
    "El coche con la ID 10 lo tiene playerid.");
    }

    /* Comprobar si un valor está en alguno de los iteradores */
    if(Iter_Contains(Coches<>, 10))
    {
        print(
    "El coche con la ID 10 ha sido comprado.");


  • Iteradores YSI
    Si están utilizando otros elementos de YSI, seguramente esto os vendrá bien en alguna ocasión.
    PHP Code:

    /* y_bit */
    new BitArray:Ejemplo<100>;

    /* Obtener las celdas que son "true". */
    foreach(new Bits(Ejemplo))
    {
        
    printf("La celda %d está en true."i);
    }

    /* Obtener las celdas que son "false". */
    foreach(new Blanks(Ejemplo))
    {
        
    printf("La celda %d está en false."i);


    PHP Code:

    /* y_commands */

    /* Iteramos a través de todos los comandos creados. */
    foreach (new Command())
    {
    }

    /* Iteramos a través de todos los comandos que puede utilizar un jugador. */
    foreach (new PlayerCommand(playerid))
    {


    PHP Code:

    /* y_groups */

    /* Iteramos a través de todos los grupos creados. */
    foreach (new Group:CreatedGroup())
    {
    }

    /* Iteramos a través de todos los sub-grupos de un grupo. */
    foreach (new Group:GroupChild(g))
    {
    }

    /* Iteramos a través de todos los miembros que posee un grupo. */
    foreach (new GroupMemeber(g))
    {
    }

    /* Iteramos a través de todos los grupos en los que se encuentra un jugador. */
    foreach (new Group:PlayerGroups(playerid))
    {


Funciones
Tenemos una cantidad de funciones que nos permiten interactuar con los iteradores que declaramos, vamos a ver cómo funciona cada una de ellas:
  • Iter_Init(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador que vamos a inicializar.

    Esta función debe utilizarse para inicializar iteradores multidimensionales de este tipo:
    PHP Code:

    new Iterator:Casas[MAX_PLAYERS]<50>;

    /* OnGameModeInit */
    Iter_Init(Casas);

    /* En algún lugar */
    Iter_Add(Casas[playerid], 5); 

  • Iter_Add(iter, value)
    Code:

    PARÁMETROS
    iter  -> nombre del iterador.
    value -> valor que vamos a añadir en el iterador.

    VALORES DEVUELTOS
    value  -> se devuelve el valor que se ha añadido si se ha ejecutado correctamente.
    cellmin -> si el valor que intentamos añadir es inválido o si ya existe dentro del iterador.

    Con esta función añadimos un valor a un iterador, recuerden que dicho valor nunca puede superar el valor del número máximo de elementos que puede contener. Si el valor que vamos a añadir es inválido o ya existe la acción simplemente se ignora.
    PHP Code:

    new Iterator:Lista<5>;

    /* En algún lugar */
    Iter_Add(Lista0);

    /* En otro lugar */
    if(Iter_Add(Lista2) == 2)
    {
        print(
    "El valor 2 se ha añadido correctamente.");


  • Iter_Remove(iter, value)
    Code:

    PARÁMETROS
    iter  -> nombre del iterador.
    value -> valor que vamos a eliminar del iterador.

    VALORES DEVUELTOS
    value  -> se devuelve el valor que se ha eliminado si se ha ejecutado correctamente.
    cellmin -> si el valor que intentamos eliminar es inválido o si no existe dentro del iterador.

    Como su propio nombre indica, nos sirve para eliminar un valor de un iterador. Si el valor que vamos a eliminar es inválido o no existe la acción simplemente se ignora.
    PHP Code:

    new Iterator:Lista<5>;

    /* En algún lugar */
    Iter_Add(Lista0);

    /* En otro lugar */
    if(Iter_Remove(Lista0) == 0)
    {
        print(
    "El valor 0 se ha eliminado correctamente.");


  • Iter_SafeRemove(iter, value, &prev)
    Code:

    PARÁMETROS
    iter  -> nombre del iterador.
    value -> valor que vamos a eliminar del iterador.
    &prev -> valor que usaremos como base para seguir iterando.

    VALORES DEVUELTOS
    value  -> se devuelve el valor que se ha eliminado si se ha ejecutado correctamente.
    cellmin -> si la función ha fallado.

    Es una mala idea eliminar uno de los valores que contiene un iterador mientras lo recorremos, no podemos utilizar Iter_Remove bajo ningún concepto. Si se diera el caso alguna vez, para eliminar uno de los valores que contiene el iterador debemos utilizar esta función.
    PHP Code:

    new Iterator:Lista<5>;

    Iter_Add(Lista0);
    Iter_Add(Lista1);
    Iter_Add(Lista2);
    Iter_Add(Lista3);

    /* En algún lugar */
    foreach(new Lista)
    {
        
    /* Supongamos una condición. */
        
    if(== 2)
        {
            new 
    base;

            
    Iter_SafeRemove(Listaxbase);

            
    base;
        }
    }

    /*
    Mucho cuidado, el valor que eliminamos debería ser el valor que contenga "x" en el momento que
    llamamos a Iter_SafeRemove. La variable "base" toma el primer valor disponible que se encuentra
    antes de "x", así se tiene una referencia para poder seguir iterando. Si usáramos Iter_Remove,
    al eliminar el valor, el script no sabrá por donde iba y se perderá, ¡puede resultar en un bucle infinito!
    */ 

  • Iter_Clear(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador que vamos a vaciar.

    Con esta función eliminamos todos los datos de un iterador, por ejemplo:
    PHP Code:

    new Iterator:Lista<5>;

    Iter_Add(Lista0);
    Iter_Add(Lista1);
    Iter_Add(Lista4);

    /* Vaciamos el iterador "Lista". */
    Iter_Clear(Lista); 

  • Iter_Free(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.

    VALORES DEVUELTOS
    valor  -> el primer valor libre que se encuentre en el iterador.
    cellmin -> si no se encuentra ningún valor libre en el iterador.

    Esta función devuelve el primer slot, o valor, que se encuentre libre en el iterador.
    PHP Code:

    new Iterator:Lista<5>;

    /* En algún lugar */
    Iter_Add(Lista0);
    Iter_Add(Lista1);

    /* En otro lugar */
    printf("Primer valor libre - %d"Iter_Free(Lista)); // Resultado: Primer valor libre - 2

    /*
    Cuidado, esta función no añade dicho valor al iterador, solo
    nos informa. Si queremos podemos hacer algo como esto:
    */

    Iter_Add(ListaIter_Free(Lista)); 

  • Iter_Alloc(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.

    VALORES DEVUELTOS
    valor  -> el primer valor libre que se ha añadido al iterador.
    cellmin -> si no se encuentra ningún valor libre en el iterador.

    Está función es como Iter_Free y Iter_Add juntas, se busca el primer valor libre del iterador y se añade al mismo. En caso de éxito la función devuelve el valor añadido.
    PHP Code:

    new Iterator:Lista<2>;

    Iter_Add(Lista0);

    printf("Se ha añadido - %d"Iter_Alloc(Lista)); // Resultado: Se ha añadido - 1. 

  • Iter_Count(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.

    VALORES DEVUELTOS
    valor -> la cantidad de elementos que hay dentro de un iterador.

    Esta función nos devuelve la cantidad de elementos que contiene un iterador.
    PHP Code:

    new Iterator:Lista<5>;

    Iter_Add(Lista0);
    Iter_Add(Lista1);

    printf("%d"Iter_Count(Lista)); // Resultado: 2 

  • Iter_Random(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.

    VALORES DEVUELTOS
    valor  -> un valor aleatorio del iterador.
    cellmin -> en caso de que el iterador esté vacío.

    Esta función nos devuelve aleatoriamente uno de los valores que contiene un iterador.
    PHP Code:

    new Iterator:Lista<5>;

    Iter_Add(Lista0);
    Iter_Add(Lista1);

    printf("%d"Iter_Random(Lista)); // Resultado: 0 o 1 

  • Iter_Contains(iter, value)
    Code:

    PARÁMETROS
    iter  -> nombre del iterador.
    value -> valor que buscamos.

    VALORES DEVUELTOS
    0 -> el iterador no contiene dicho valor.
    1 -> el iterado contiene dicho valor.

    Con esta función podemos comprobar un iterador para ver si contiene un valor.
    PHP Code:

    new Iterator:Lista<5>;

    Iter_Add(Lista3);

    if(
    Iter_Contains(Lista3) == 1)
    {
        print(
    "Existe.");


Funciones avanzadas
Existen unas cuantas funciones más que te pueden dar más control sobre los bucles creados con este include, por ejemplo:
  • Iter_First(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.

    VALORES DEVUELTOS
    valor -> devuelve el primer valor válido de un iterador.

  • Iter_Last(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.

    VALORES DEVUELTOS
    valor -> devuelve el último valor válido de un iterador.

  • Iter_Next(iter, cur)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.
    cur  -> valor actual.

    VALORES DEVUELTOS
    valor -> el primer valor válido que se encuentra después del valor actual "cur".

  • Iter_Prev(iter, cur)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.
    cur  -> valor actual.

    VALORES DEVUELTOS
    valor -> el primer valor válido que se encuentra antes del valor actual "cur".

  • Iter_Begin(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.

    VALORES DEVUELTOS
    valor -> un valor inválido que se encuentra antes del comienzo del iterador.

  • Iter_End(iter)
    Code:

    PARÁMETROS
    iter -> nombre del iterador.

    VALORES DEVUELTOS
    valor -> un valor inválido que se encuentra después del último valor válido del iterador.

Estas funciones pueden ser usadas para hacer bucles más personalizados, por ejemplo:
PHP Code:

new Iterator:Ejemplo<5>;

Iter_Add(Ejemplo2);
Iter_Add(Ejemplo0);

for(new 
Iter_First(Ejemplo); != Iter_End(Ejemplo); Iter_Next(Ejemploi))
{
    
printf("%d"i); //Resultado: 0 2


Otras funciones
Podemos aplicar algunas funciones directamente al iterar, veamos algunas de ellas.
  • Reverse
    En un iterador inverso iteramos desde el valor más alto hacia el más pequeño.
    PHP Code:

    new Iterator:Ejemplo<10>;

    Iter_Add(Ejemplo5);
    Iter_Add(Ejemplo0);
    Iter_Add(Ejemplo10);

    foreach(new 
    Reverse(Ejemplo)) /* Aplicamos Reverse */
    {
        
    printf("%d"x); // Resultado: 10 5 0


  • Range
    En este iterador establecemos un intervalo y lo podemos recorrer de diferentes formas.
    PHP Code:

    /* Iterar en un intervalo. */
    foreach(new Range(48))
    {
        
    printf("%d"x); // Resultado: 4 5 6 7
    }

    /* Iterar en un intervalo aplicando un salto. */
    foreach(new Range(062))
    {
        
    printf("%d"x); // Resultado: 0 2 4
    }

    /* Iterar en un intervalo al revés. */
    foreach(new Range(105, -1))
    {
        
    printf("%d"x); // Resultado: 10 9 8 7 6


  • Random
    Esta función podemos usarla de diferentes modos, veamos:
    PHP Code:

    /* Itera una cantidad de veces devolviendo valores aleatorios. */
    foreach(new Random(5))
    {
        
    // Se repite 5 veces, "x" puede valer cualquier cosa entre [-2147483648, 2147483647]. 
    }

    /* Itera una cantidad de veces devolviendo valores aleatorios comprendidos en un rango. */
    foreach(new Random(5, -26))
    {
        
    // Se repite 5 veces, "x" puede valer cualquier cosa entre [-2, 6).


Errores típicos
Mucha gente no entiende cómo funciona realmente y_iterate, hay diferencias importantes entre una array y un iterador. Este include no está pensado para almacenar IDs que devuelven las funciones que nosotros hagamos por ahí, más bien está hecho para llevar un rastreo de los índices válidos de una array.

Imaginen que creamos un sistema de casas dinámico, digamos que cada casa tiene una ID única que nos sirve para identificarla en una base de datos MySQL. Por ejemplo:
PHP Code:

#define MAX_HOUSES 1000

enum e_house_info
{
    
SQL_ID,
    
Precio
}
new 
HouseInfo[MAX_HOUSES][e_house_info];

/* Declaramos nuestro iterador para llevar la cuenta de las casas. */
new Iterator:Houses<MAX_HOUSES>;

/* Cargamos las casas */
CargarCasas()
{
    
// ... 
    
    
HouseInfo[x][SQL_ID] = cache_get_value_index_int(...);
    
HouseInfo[x][Precio] = cache_get_value_index_int(...);

    
Iter_Add(Housesx); // ¡OJO! Añadimos al iterador el índice de la array HouseInfo, ¡no SQL_ID!

    // ...

    
printf("Se han cargado %d casas."Iter_Count(Houses));
    return 
1;
}

/* Alguien usa un comando y quiere que todas las casas tengan un checkpoint en el mapa. */
foreach(new id Houses)
{
    
SetPlayerCheckpoint(playeridHouseInfo[id][X], HouseInfo[id][Y], HouseInfo[id][Z], 1.0);
}

/*
Si se dan cuenta, al utilizar foreach solamente recorremos las celdas válidas de HouseInfo.
Si hay tres casas cargadas, el bucle se repite tres veces, no mil. Esto es mucho más rápido
que utilizar un bucle for y comprobar si cada celda de HouseInfo es una casa válida.
*/ 

Tengan muy presente el ejemplo anterior a la hora de crear vuestros sistemas, y_iterate no está hecho para almacenar cadenas de texto, ni floats, ni el dinero del jugador, ni nada por el estilo. Está hecho para iterar de forma rápida, no intenten hacer con el cosas para las que no ha sido diseñado.

Ya que estamos con esto, vamos a explicar uno de los ejemplos de más arriba para que entiendan bien por qué lo hemos hecho así:
PHP Code:

new Iterator:Coches<MAX_PLAYERSMAX_VEHICLES>;

/*
¿Por qué MAX_PLAYERS y MAX_VEHICLES?
Si lo piensan bien MAX_PLAYERS viene definido como 500 y MAX_VEHICLES como 2000. Las IDs de
los jugadores están comprendidas en el intervalo [0, 499] y las de los vehículos entre [1, 1999].

¿Qué significa <MAX_PLAYERS, MAX_VEHICLES>?
Significa que se van a crear 500 iteradores, pero los 2000 elementos se repartirán entre todos ellos.
Un iterador puede tener varios elementos en su interior, pero todos son únicos, ninguno se repite.
Por su parte, los elementos pueden existir solamente una vez, es decir, no pueden estar en varios
iteradores a la vez. Un elemento puede estar en el iterador, o bien, libre.

Sabiendo esto, tiene sentido asignar la ID in-game de un vehículo a un jugador porque cada
jugador tiene su iterador "Coches<playerid>" y cada coche puede estar solamente en un iterador.
De esta forma conseguimos que un vehículo solo pueda ser "comprado" una vez por un único jugador.
*/

if(Iter_Contains(Coches<playerid>, 50))
{
    
printf("El jugador con la ID %d posee el vehículo con la ID 50."playerid);


Este forma de "comprar" vehículos que se ve en el ejemplo anterior no tiene sentido en un servidor RolePlay con un sistema de vehículos dinámico, básicamente porque la ID de un jugador cambia y la de los vehículos también. En un servidor free roam está bien para "comprar" el vehículo temporalmente, por ejemplo, hasta que te desconectes.

Créditos
Si tienen alguna duda respecto a la autoría de alguno de los tutoriales que he escrito en relación a YSI os invito a leer el tema principal. Esto es todo, espero que os sirva. Por favor, comenten cualquier duda o error de tipografía (o conceptual) que encuentren.

Viewing all articles
Browse latest Browse all 18226

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>