Entities File for Quake3

22 replies [Last post]
Z3nnY
Offline
Joined: May 2013
Posts:
Re: Entities File for Quake3

On ne peux "normalement" pas modifier les fichiers .qvm.. Mais tu peux quand même faire ton propre mod grace au source de quake 3. Après c'est a toi d'apprendre, c'est du C simplement

V1979
V1979's picture
Offline
Joined: Nov 2011
Posts:
RU Russian Federation
Re: Entities File for Quake3

Je le sais, mais je ne connais pas le code: ni C, ni C+, ni C++, ni C#, ni d'autres. Je sais qu'on peut compiler de nouveaux fichiers *.qvm d'après les sources à l'aide des fichiers *.bat, mais je ne sais pas quels fichiers j'ai à modifier.
Tout ce que je veux, c'est d'avoir un mode qui se base sur le "baseq3", mais avec les armes et les bonus (power-ups) de Team Arena, et avec les armures verte (25 points - cela existe au mode ExcessvePlus) et bleue (200 points - cela existe, si je ne me trompe pas, à Quake Live).

Z3nnY
Offline
Joined: May 2013
Posts:
Re: Entities File for Quake3

Je peux pas vraiment t'aider la dessus j'utilise rarement les qvm de q3.. Je suis plus dans l'engine Happy

Z3nnY
Offline
Joined: May 2013
Posts:
Re: Entities File for Quake3

So, I have tried to do a new function named CM_LoadMapEntities who are launched exactly in the same time than CM_LoadMap but with .ent at the end (no .bsp). In this function "buf" is the text in my file .ent but when i do cm.entityString = (char *)buf he don't take all the text so i have the error "G_ParseSpawnVars: found &c when expecting {".. Anybody know how can i take all the text in my buf ?

void CM_LoadMapEntities( const char *name ) {
    int                *buf;
    lump_t                *lump;
    int                length;
 
    length = FS_ReadFile( name, (void **)&buf );
 
    if ( !buf ) {
        Com_Printf( "Couldn't load %s", name);
    }
 
    cm.entityString = (char *)buf;
 
    FS_FreeFile (buf);
}

0MS
Offline
Joined: Apr 2010
Posts:
Re: Entities File for Quake3

Excessiveplus v2.1, fragment of g_spawn.c
( xp_noCustomEnts and g_mapname must be defined as cvars, g_mapname depends on currently loaded map )

/*QUAKED worldspawn (0 0 0) ?
 
Every map should have exactly one worldspawn.
"music"        music wav file
"gravity"    800 is default gravity
"message"    Text to print during connection process
*/
void SP_worldspawn( void ) {
    char    *s;
 
    G_SpawnString( "classname", "", &s );
    if ( Q_stricmp( s, "worldspawn" ) ) {
        G_Error( "SP_worldspawn: The first entity isn't 'worldspawn'" );
    }
 
    // make some data visible to connecting client
    trap_SetConfigstring( CS_GAME_VERSION, GAME_VERSION );
 
    trap_SetConfigstring( CS_LEVEL_START_TIME, va("%i", level.startTime ) );
 
    G_SpawnString( "music", "", &s );
    trap_SetConfigstring( CS_MUSIC, s );
 
    G_SpawnString( "message", "", &s );
    trap_SetConfigstring( CS_MESSAGE, s );                // map specific message
 
    trap_SetConfigstring( CS_MOTD, g_motd.string );        // message of the day
 
    G_SpawnString( "gravity", "800", &s );
    trap_Cvar_Set( "g_gravity", s );
 
    G_SpawnString( "enableDust", "0", &s );
    trap_Cvar_Set( "g_enableDust", s );
 
    G_SpawnString( "enableBreath", "0", &s );
    trap_Cvar_Set( "g_enableBreath", s );
#ifdef EXCESSIVEPLUS
    G_SpawnString( "atmosphere", "", &s );
    if ( g_gametype.integer == GT_FTAG )
    {
        trap_Cvar_Set( "g_enableBreath", "1" );
        s = "T=SNOW";
    }
    trap_SetConfigstring( 31, s );
#endif
 
    g_entities[ENTITYNUM_WORLD].s.number = ENTITYNUM_WORLD;
    g_entities[ENTITYNUM_WORLD].classname = "worldspawn";
 
    // see if we want a warmup time
    trap_SetConfigstring( CS_WARMUP, "" );
#ifdef EXCESSIVEPLUS
    if ( trap_Cvar_VariableIntegerValue( "g_restarted" ) )
    {
        trap_Cvar_Set( "g_restarted", "0" );
        level.warmupTime = 0;
    }
    else
    {
        if ( g_gametype.integer != GT_SINGLE_PLAYER )
        {
            trap_SetConfigstring( CS_WARMUP, "-1" );
            level.warmupTime = -1;
            G_LogPrintf( "Warmup:\n" );
        }
    }
#else
    if ( g_restarted.integer ) {
        trap_Cvar_Set( "g_restarted", "0" );
        level.warmupTime = 0;
    } else if ( g_doWarmup.integer ) { // Turn it on
        level.warmupTime = -1;
        trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) );
        G_LogPrintf( "Warmup:\n" );
    }
#endif
}
 
#ifdef EXCESSIVEPLUS
qboolean G_ParseSpawnVarsFromFile( char **data )
{
    char        keyname[MAX_TOKEN_CHARS];
    char        com_token[MAX_TOKEN_CHARS];
 
    level.numSpawnVars = 0;
    level.numSpawnVarChars = 0;
    Com_sprintf( com_token, sizeof( com_token ), "%s", COM_Parse( data ) );
    if ( com_token[0] )
    {
        if ( com_token[0] != '{' )
            COM_ParseError( "found '%s' when expecting {", com_token );
        while ( 1 )
        {    
            Com_sprintf( keyname, sizeof( keyname ), "%s", COM_Parse( data ) );
            if ( !keyname[0] )
                COM_ParseError( "EOF without closing brace" );
            if ( keyname[0] == '}' )
                break;
            Com_sprintf( com_token, sizeof( com_token ), "%s", COM_Parse( data ) );
            if ( !com_token[0] )
                COM_ParseError( "EOF without closing brace" );
            if ( com_token[0] == '}' )
                COM_ParseError( "closing brace without data" );
            if ( level.numSpawnVars == MAX_SPAWN_VARS ) 
                COM_ParseError( "MAX_SPAWN_VARS" );
            level.spawnVars[ level.numSpawnVars ][0] = G_AddSpawnVarToken( keyname );
            level.spawnVars[ level.numSpawnVars ][1] = G_AddSpawnVarToken( com_token );
            level.numSpawnVars++;
        }
        return qtrue;
    }
    else
        return qfalse;
}
 
qboolean G_SpawnEntitiesFromFile( const char *filename, qboolean isents )
{
    fileHandle_t f;
    int len;
    char *buf;
 
    len = trap_FS_FOpenFile( filename, &f, FS_READ );
    if ( !f )
        return qfalse;
    if ( len <= 0 )
    {
        trap_FS_FCloseFile( f );
        return qfalse;
    }
    COM_BeginParseSession( filename );
    buf = ( char * )malloc( len + 1 );
    if ( buf )
    {
        trap_FS_Read( buf, len, f );
        buf[len] = 0;
        if ( isents )
        {
            if ( !G_ParseSpawnVarsFromFile( &buf ) ) 
                COM_ParseError( "SpawnEntities: no entities" );
            SP_worldspawn();
        }
        while ( G_ParseSpawnVarsFromFile( &buf ) )
            G_SpawnGEntityFromSpawnVars();
        trap_FS_FCloseFile( f );
        free( buf );
        return qtrue;
    }
    else
    {
        trap_FS_FCloseFile( f );
        COM_ParseError( "Not enough memory to load file" );
        return qfalse;
    }
}
#endif
 
/*
==============
G_SpawnEntitiesFromString
 
Parses textual entity definitions out of an entstring and spawns gentities.
==============
*/
void G_SpawnEntitiesFromString( void ) {
#ifdef EXCESSIVEPLUS
    /*char string[MAX_CVAR_VALUE_STRING];
    char *ptr;*/
#endif
    // allow calls to G_Spawn*()
    level.spawning = qtrue;
    level.numSpawnVars = 0;
#ifdef EXCESSIVEPLUS
    if ( xp_noCustomEnts.integer || !G_SpawnEntitiesFromFile( va( "maps/%s.ents", g_mapname.string ), qtrue ) )
    {
#endif
    // the worldspawn is not an actual entity, but it still
    // has a "spawn" function to perform any global setup
    // needed by a level (setting configstrings or cvars, etc)
    if ( !G_ParseSpawnVars() ) {
        G_Error( "SpawnEntities: no entities" );
    }
    SP_worldspawn();
 
    // parse ents
    while( G_ParseSpawnVars() ) {
        G_SpawnGEntityFromSpawnVars();
    }
#ifdef EXCESSIVEPLUS
    }
    if ( !xp_noCustomEnts.integer )
    {
        G_SpawnEntitiesFromFile( va( "maps/%s.add", g_mapname.string ), qfalse );
    }
    /*trap_Cvar_VariableStringBuffer( "xp_config", string, sizeof( string ) );
    if ( !string )
        ptr = "default";
    else
        ptr = string;
    if ( !ParseConfig( ptr, 3 ) )
        ParseConfig( "default", 2 );*/
#endif
    level.spawning = qfalse;            // any future calls to G_Spawn*() will be errors
}

Z3nnY
Offline
Joined: May 2013
Posts:
Re: Entities File for Quake3

Ok, Thank's a lot Big grin
EDIT : We can found the source of E+ somewhere ?

0MS
Offline
Joined: Apr 2010
Posts:
Re: Entities File for Quake3

This code fragment is small part of reverse-engineered qagamex86.dll(xp2.1).
P.S. I think excessiveplus source code is here.

Z3nnY
Offline
Joined: May 2013
Posts:
Re: Entities File for Quake3

Ok so my code is finish and he is located into the server engine (like that that work for the big part of the q3 mod).. For what you call the "reverse-engine " it's manual (you think it's like that) or a program do that for you ?

0MS
Offline
Joined: Apr 2010
Posts:
Re: Entities File for Quake3

From program(IDA Pro with Hex-Rays) I can get only this files.

Z3nnY
Offline
Joined: May 2013
Posts:
Re: Entities File for Quake3

That really clean for a decompiler code, do you know if you can do that with qvm file ? And if you can after the decompiling remade a dll or qvm file ?