[SNIPPET] Precache Model Sequences
#1

Vengo a aportar esta pequeña utilidad (ni tan pequeña jajaja), para poder precachear sonidos que se encuentren escritos en los modelos.

Código PHP:
// Eventos mayores o iguales que este son manejados por el cliente *tecnicamente*
const CI_EventClient 5000;

// La cadena a precachear (sonido), debe tener un minimo de caracteres como indica esta cadena
new const CSZ_MinLenExample[] = "a.wav";

// Versión completa de 'SequencePrecache' (HLSDK/CS-SDK)
// Precachea sonidos utilizados por modelos (para usarse por ejemplo, con 'eventos' que son manejados por el servidor)
// (Creditos a Arkshine por esto: https://forums.alliedmods.net/showpost.php?p=2270332&postcount=8 & esto https://forums.alliedmods.net/showpost.php?p=1817050&postcount=11)
UIL_PrecacheModelSequences(const SZ_ModelName[])
{
    
// Verificar si es valido el modelo
    
if (!SZ_ModelName[0] || !strlen(SZ_ModelName))
        return;
    
    
// Busca el archivo y lo abre
    // AVISO: Solo toma desde la carpeta root del MOD (E.X: CS 1.6 -> cstrike)
    
new I_File fopen(SZ_ModelName"rb");
    
    
// Si puede abrirse (y por ende existe)
    
if (I_File)
    {
        
// Offset de "studiohdr_t->numseq" (mayor información leer "engine/studio.h" en el HLSDK)
        
static const CI_NumSeqOFST 164;

        
// Offset de "mstudioseqdesc_t->numevents" (mayor información leer "engine/studio.h" en el HLSDK)
        
static const CI_NumEventsOFST 48;

        
// Offset de "mstudioevent_t->event" (mayor información leer "common/studio_event.h" en el HLSDK)
        
static const CI_EventIDOFST 4;

        
// Tamaño de "mstudioevent_t->type" (es un "int" = 4 bytes en x86 SO(s))
        // Mayor información leer "common/studio_event.h" en el HLSDK
        
static const CI_EventTypeOFSTSize 4;

        
// Tamaño de la estructura "mstudioseqdesc_t "
        // Mayor información leer "engine/studio.h" en el HLSDK
        
static const CI_StudioSeqDescStructSize 176;

        
// Tamaño de la estructura "mstudioevent_t"
        // Mayor información leer "common/studio_event.h" en el HLSDK
        
static const CI_StudioEventStructSize 76;
        
        static const 
CSZ_LogFile[] = "PMS_Info.LOG";

        new 
I_TotalSequencesI_SequenceIndex;
        new 
I_TotalEventsI_EventIndex;
        new 
I_EventID;
        new 
I_CurrentEvent;
        
        static 
SZ_SequenceName[32];
        static 
SZ_EventOptions[64];
        
        
// Guarda la información del modelo
        
log_to_file(CSZ_LogFile"PRECACHEANDO SONIDOS USADOS POR EL MODELO: ^"%s^"^n"SZ_ModelName);
        
        
// Direcciona el cursor del archivo (modelo) a la ubicación del número de secuencias en el modelo
        // El direccionamiento es desde el inicio del archivo hasta la ubicación antes mencionada
        
fseek(I_FileCI_NumSeqOFSTSEEK_SET);
    
        
// Lee el total de secuencias usadas por el modelo
        
fread(I_FileI_TotalSequencesBLOCK_INT);
        
        
// Lee el index de la primera secuencia
        
fread(I_FileI_SequenceIndexBLOCK_INT);
        
        
// Guarda la información del modelo
        
log_to_file(CSZ_LogFile"^tTOTAL DE SECUENCIAS: %d^n"I_TotalSequences);
        
        
// Recorre todas las secuencias del modelo
        
for (new I_CurrentSequenceI_CurrentSequence I_TotalSequencesI_CurrentSequence++)
        {
            
// Direcciona el cursor a la estructura "mstudioseqdesc_t" de la secuencia actual
            // Para mayor información lean "engine/studio.h" en el HLSDK
            // El direccionamiento es desde el inicio del archivo hasta la ubicación antes mencionada
            
fseek(I_File, (I_SequenceIndex + (I_CurrentSequence CI_StudioSeqDescStructSize)), SEEK_SET);
            
            
// Lee el nombre de la secuencia actual
            
fread_blocks(I_FileSZ_SequenceNamesizeof SZ_SequenceNameBLOCK_CHAR);
            
            
// Direcciona el cursor a la ubicación del número de eventos de la secuencia actual
            // El direccionamiento es desde la ubicación actual hasta la ubicación antes mencionada
            
fseek(I_File, (CI_NumEventsOFST sizeof SZ_SequenceName), SEEK_CUR);
            
            
// Lee el número de eventos de la secuencia actual
            
fread(I_FileI_TotalEventsBLOCK_INT);
            
            
// Guarda la información del modelo
            
log_to_file(CSZ_LogFile"^t^tTOTAL DE EVENTOS DE LA SECUENCIA ^"%s^": %d"SZ_SequenceNameI_TotalEvents);
            
            
// Si la secuencia actual no tiene eventos, ignorarla
            
if (!I_TotalEvents)
            {
                if (
I_TotalSequences 1)
                    
log_to_file(CSZ_LogFile"^n");
                
                continue;
            }
            
            
// Lee el index del primer evento de la secuencia actual
            
fread(I_FileI_EventIndexBLOCK_INT);
            
            
// Recorre todos los eventos de la secuencia actual
            
for (I_CurrentEvent 0I_CurrentEvent I_TotalEventsI_CurrentEvent++)
            {
                
// Direcciona el cursor a la estructura "mstudioevent_t" del evento actual
                // Para mayor información lean "common/studio_event.h" en el HLSDK
                // El direccionamiento es desde el inicio del archivo hasta la ubicación antes mencionada
                
fseek(I_File, (I_EventIndex + (I_CurrentEvent CI_StudioEventStructSize) + CI_EventIDOFST), SEEK_SET);
                
                
// Lee el número de evento del evento actual
                
fread(I_FileI_EventIDBLOCK_INT);
                
                
// Direcciona el cursor hacia el sonido del evento actual (no necesariamente, puede ser cualquier cadena que se desee)
                // El direccionamiento es desde la ubicación actual hasta la ubicación antes mencionada
                
fseek(I_FileCI_EventTypeOFSTSizeSEEK_CUR);
                
                
// Lee el sonido del evento actual para intentar precachearlo luego
                
fread_blocks(I_FileSZ_EventOptionssizeof SZ_EventOptionsBLOCK_CHAR);
                
                
// Guarda la información del modelo
                
log_to_file(CSZ_LogFile"^t^t^tEVENTO #%d: ^"%s^""I_EventIDSZ_EventOptions);
                
                
// Si no es un sonido valido no se precacheara
                // Para esto: el número de evento debe estar entre los del servidor...Y...No estar vacia la cadena del sonido...Y...No ser una cadena de sentencia
                
if (!IsSoundEvent(I_EventIDSZ_EventOptions) || IsEmptyString(SZ_EventOptions) || IsSentenceString(SZ_EventOptions[0]))
                    continue;
                
                
// Si el sonido no existe, ignorar
                
if (!SoundExists(SZ_EventOptions))
                    continue;
                
                
// Guarda la información del modelo
                
log_to_file(CSZ_LogFile"^t^t^tPRECACHEANDO SONIDO: ^"%s^""SZ_EventOptions);
                
                
// Precachea el sonido (llegado a este punto el sonido debe ser valido)
                
precache_sound(SZ_EventOptions);
            }
            
            
log_to_file(CSZ_LogFile"^n");
        }
    }
    
    
// Cierra el archivo luego de leerlo
    
fclose (I_File)
}

// Similar a 'IsSoundEvent' (HLSDK/CS-SDK)
// Devueve VERDADERO si el sonido/evento son apropiados (o FALSO en caso contrario)
bool:IsSoundEvent(const I_EventID, const SZ_EventOptions[])
{
    
// Si el número de evento pasado es de los manejados por el cliente, ignorar
    
if (I_EventID >= CI_EventClient)
        return 
false;
    
    new 
I_Len strlen(SZ_EventOptions);
    
    static 
I_MinLen;
    
    
I_MinLen strlen(CSZ_MinLenExample);
    
    
// Si la cadena del sonido esta vacia...O...El número de caracteres es menor del minimo requerido, ignorar
    
if (!SZ_EventOptions[0] || I_Len I_MinLen)
        return 
false;
    
    static 
SZ_Sentence[5];
    
    
copy(SZ_Sentencecharsmax(SZ_Sentence), SZ_EventOptions[I_Len 4])
    
    
// Si la cadena del sonido no tiene la sentencia ".wav" al final (es decir, como extensión), ignorar
    
if (!equal(SZ_Sentence".wav"))
        return 
false;
    
    
// El sonido es valido, entonces debe precachearse
    
return true;
}

// Equivalente a 'PR_IsEmptyString' (GoldSrc/Engine)
// Devuelve VERDADERO si la cadena que se paso tiene caracteres invalidos (incluido espacio)
bool:IsEmptyString(const SZ_String[])
    return 
SZ_String[0] <= ' ';

// Devuelve VERDADERO si la cadena que se paso es de sentencia (inicia con el caracter "!")    
bool:IsSentenceString(const SZ_String[])
    return 
SZ_String[0] == '!';

// Devuelve VERDADERO si el sonido que se pasa existe en la carpeta del MOD
bool:SoundExists(const SZ_Sound[])
{
    static 
SZ_FullSound[64];
        
    
formatex(SZ_FullSoundcharsmax(SZ_FullSound), "sound/%s"SZ_Sound);
    
    return 
bool:file_exists(SZ_FullSound);


La forma de uso es:
Código:
UIL_PrecacheModelSequences("ubicacion_+_modelo.mdl")

OBSERVACION: Al parecer solo puede usarse en modelos que se encuentre en la carpeta raíz del MOD (por ejemplo, CS 1.6/CZero -> cstrike). Asumo que esto ya viene indicado en el AMXX.

Un uso seria precachear sonidos de un NPC (su modelo). Y luego, por ejemplo, usando las funciones que trae el MOD por defecto podemos ejecutar dichos sonidos cuando se ejecutan ciertos eventos del modelo (tal cual como sucede con los modelos View de las armas al ejecutarse en el cliente). Con lo anterior, es más fácil modificar y ejecutar los sonidos en el momento más oportuno para nosotros.

Estas funciones son: StudioFrameAdvance, DispatchAnimEvents, y HandleAnimEvent (también opcionalmente ResetSequenceInfo).

En el HLSDK pueden encontrar más información.

Si gustan puedo postear las firmas de las funciones anteriores (para usarse con Orpheu).
Responder
#2
gracias por el aporte
Ingeniero agrónomo y desarrollador de Software.

tutoriales-allied
buscas un zp?

"La imitación es la forma más sincera de admiración con la que puede pagar la mediocridad a la grandeza"

Merci Alliedmodders pour m'introduire dans la programmation.
Responder
#3
Bueno aporte Approved
Responder
#4

Muchas gracias.

He aquí las firmas y archivos de las funciones mencionadas al principio.

Saludos.


Archivos adjuntos
.rar   orpheu.rar (Tamaño: 1.6 KB / Descargas: 11)
Responder
#5
Buen aporte, parece interesante
Plata o Plomo Usted decide


- Pablo Emilio Escobar Gaviria -
Responder


Salto de foro:


Usuarios navegando en este tema: 1 invitado(s)