//"void GT_ThinkRules( void )" void GT_asCallThinkRules( void ) { int error; asIScriptContext *ctx; if( !level.gametype.thinkRulesFunc ) { return; } ctx = game.asExport->asAcquireContext( GAME_AS_ENGINE() ); error = ctx->Prepare( static_cast<asIScriptFunction *>( level.gametype.thinkRulesFunc ) ); if( error < 0 ) { return; } error = ctx->Execute(); if( G_ExecutionErrorReport( error ) ) { GT_asShutdownScript(); } }
bool GT_asLoadScript( const char *gametypeName ) { const char *moduleName = GAMETYPE_SCRIPTS_MODULE_NAME; asIScriptModule *asModule; GT_ResetScriptData(); // Load the script asModule = G_LoadGameScript( moduleName, GAMETYPE_SCRIPTS_DIRECTORY, gametypeName, GAMETYPE_PROJECT_EXTENSION ); if( asModule == NULL ) { return false; } // Initialize the script if( !G_asInitializeGametypeScript( asModule ) ) { GT_asShutdownScript(); return false; } return true; }
//"void GT_scoreEvent( Client @client, String &score_event, String &args )" void GT_asCallScoreEvent( gclient_t *client, const char *score_event, const char *args ) { int error; asIScriptContext *ctx; asstring_t *s1, *s2; if( !level.gametype.scoreEventFunc ) { return; } if( !score_event || !score_event[0] ) { return; } if( !args ) { args = ""; } ctx = game.asExport->asAcquireContext( GAME_AS_ENGINE() ); error = ctx->Prepare( static_cast<asIScriptFunction *>( level.gametype.scoreEventFunc ) ); if( error < 0 ) { return; } // Now we need to pass the parameters to the script function. s1 = game.asExport->asStringFactoryBuffer( score_event, strlen( score_event ) ); s2 = game.asExport->asStringFactoryBuffer( args, strlen( args ) ); ctx->SetArgObject( 0, client ); ctx->SetArgObject( 1, s1 ); ctx->SetArgObject( 2, s2 ); error = ctx->Execute(); if( G_ExecutionErrorReport( error ) ) { GT_asShutdownScript(); } game.asExport->asStringRelease( s1 ); game.asExport->asStringRelease( s2 ); }
//"bool GT_Command( Client @client, String &cmdString, String &argsString, int argc )" bool GT_asCallGameCommand( gclient_t *client, const char *cmd, const char *args, int argc ) { int error; asIScriptContext *ctx; asstring_t *s1, *s2; if( !level.gametype.clientCommandFunc ) return false; // should have a hardcoded backup // check for having any command to parse if( !cmd || !cmd[0] ) return false; ctx = angelExport->asAcquireContext( GAME_AS_ENGINE() ); error = ctx->Prepare( static_cast<asIScriptFunction *>(level.gametype.clientCommandFunc) ); if( error < 0 ) return false; // Now we need to pass the parameters to the script function. s1 = angelExport->asStringFactoryBuffer( cmd, strlen( cmd ) ); s2 = angelExport->asStringFactoryBuffer( args, strlen( args ) ); ctx->SetArgObject( 0, client ); ctx->SetArgObject( 1, s1 ); ctx->SetArgObject( 2, s2 ); ctx->SetArgDWord( 3, argc ); error = ctx->Execute(); if( G_ExecutionErrorReport( error ) ) GT_asShutdownScript(); angelExport->asStringRelease( s1 ); angelExport->asStringRelease( s2 ); // Retrieve the return from the context return ctx->GetReturnByte() == 0 ? false : true; }
//"void GT_playerRespawn( Entity @ent, int old_team, int new_team )" void GT_asCallPlayerRespawn( edict_t *ent, int old_team, int new_team ) { int error; asIScriptContext *ctx; if( !level.gametype.playerRespawnFunc ) return; ctx = angelExport->asAcquireContext( GAME_AS_ENGINE() ); error = ctx->Prepare( static_cast<asIScriptFunction *>(level.gametype.playerRespawnFunc) ); if( error < 0 ) return; // Now we need to pass the parameters to the script function. ctx->SetArgObject( 0, ent ); ctx->SetArgDWord( 1, old_team ); ctx->SetArgDWord( 2, new_team ); error = ctx->Execute(); if( G_ExecutionErrorReport( error ) ) GT_asShutdownScript(); }
/* * G_Shutdown */ void G_Shutdown( void ) { int i; G_Printf( "==== G_Shutdown ====\n" ); // racesow RS_Shutdown(); GT_asCallShutdown(); G_asCallMapExit(); G_asShutdownMapScript(); GT_asShutdownScript(); G_asShutdownGameModuleEngine(); SV_WriteIPList (); trap_Cvar_ForceSet( "nextmap", va( "map \"%s\"", G_SelectNextMapName() ) ); BOT_RemoveBot( "all" ); G_RemoveCommands(); G_FreeCallvotes(); G_LevelFreePool(); for( i = 0; i < game.numentities; i++ ) { if( game.edicts[i].r.inuse ) G_FreeEdict( &game.edicts[i] ); } G_Free( game.edicts ); G_Free( game.clients ); }
/* * SpawnEntities * * Creates a server's entity / program execution context by * parsing textual entity definitions out of an ent file. */ void G_InitLevel( char *mapname, char *entities, int entstrlen, unsigned int levelTime, unsigned int serverTime, unsigned int realTime ) { char *mapString = NULL; char name[MAX_CONFIGSTRING_CHARS]; int i; edict_t *ent; char *token; const gsitem_t *item; G_asGarbageCollect( true ); GT_asCallShutdown(); G_asCallMapExit(); G_asShutdownMapScript(); GT_asShutdownScript(); G_FreeCallvotes(); game.serverTime = serverTime; game.realtime = realTime; game.levelSpawnCount++; GClip_ClearWorld(); // clear areas links if( !entities ) G_Error( "G_SpawnLevel: NULL entities string\n" ); // make a copy of the raw entities string so it's not freed with the pool mapString = ( char * )G_Malloc( entstrlen + 1 ); memcpy( mapString, entities, entstrlen ); Q_strncpyz( name, mapname, sizeof( name ) ); // clear old data G_LevelInitPool( strlen( mapname ) + 1 + ( entstrlen + 1 ) * 2 + G_LEVELPOOL_BASE_SIZE ); G_StringPoolInit(); memset( &level, 0, sizeof( level_locals_t ) ); memset( &gs.gameState, 0, sizeof( gs.gameState ) ); level.spawnedTimeStamp = game.realtime; level.time = levelTime; level.gravity = g_gravity->value; // get the strings back Q_strncpyz( level.mapname, name, sizeof( level.mapname ) ); level.mapString = ( char * )G_LevelMalloc( entstrlen + 1 ); level.mapStrlen = entstrlen; memcpy( level.mapString, mapString, entstrlen ); G_Free( mapString ); mapString = NULL; // make a copy of the raw entities string for parsing level.map_parsed_ents = ( char * )G_LevelMalloc( entstrlen + 1 ); level.map_parsed_ents[0] = 0; if( !level.time ) memset( game.edicts, 0, game.maxentities * sizeof( game.edicts[0] ) ); else { G_FreeEdict( world ); for( i = gs.maxclients + 1; i < game.maxentities; i++ ) { if( game.edicts[i].r.inuse ) G_FreeEdict( game.edicts + i ); } } game.numentities = gs.maxclients + 1; // link client fields on player ents for( i = 0; i < gs.maxclients; i++ ) { game.edicts[i+1].s.number = i+1; game.edicts[i+1].r.client = &game.clients[i]; game.edicts[i+1].r.inuse = ( trap_GetClientState( i ) >= CS_CONNECTED ) ? true : false; memset( &game.clients[i].level, 0, sizeof( game.clients[0].level ) ); game.clients[i].level.timeStamp = level.time; } // initialize game subsystems trap_ConfigString( CS_MAPNAME, level.mapname ); trap_ConfigString( CS_SKYBOX, "" ); trap_ConfigString( CS_AUDIOTRACK, "" ); trap_ConfigString( CS_STATNUMS, va( "%i %i %i", STAT_SCORE, STAT_HEALTH, STAT_LAST_KILLER ) ); trap_ConfigString( CS_POWERUPEFFECTS, va( "%i %i %i %i", EF_QUAD, EF_SHELL, EF_CARRIER, EF_REGEN ) ); trap_ConfigString( CS_SCB_PLAYERTAB_LAYOUT, "" ); trap_ConfigString( CS_SCB_PLAYERTAB_TITLES, "" ); trap_ConfigString( CS_MATCHNAME, "" ); trap_ConfigString( CS_MATCHSCORE, "" ); // reset map messages for( i = 0; i < MAX_HELPMESSAGES; i++ ) { trap_ConfigString( CS_HELPMESSAGES + i, "" ); } G_InitGameCommands(); G_MapLocations_Init(); G_CallVotes_Init(); G_SpawnQueue_Init(); G_Teams_Init(); // load map script G_asLoadMapScript( level.mapname ); G_Gametype_Init(); // ch : this would be the location to "transfer ratings" G_PrecacheItems(); // set configstrings for items (gametype must be initialized) G_PrecacheMedia(); G_PrecacheGameCommands(); // adding commands after this point won't update them to the client AI_InitLevel(); // load navigation file of the current map // start spawning entities level.canSpawnEntities = true; G_InitBodyQueue(); // reserve some spots for dead player bodies entities = level.mapString; i = 0; ent = NULL; while( 1 ) { level.spawning_entity = NULL; // parse the opening brace token = COM_Parse( &entities ); if( !entities ) break; if( token[0] != '{' ) G_Error( "G_SpawnMapEntities: found %s when expecting {", token ); if( !ent ) { ent = world; G_InitEdict( world ); } else ent = G_Spawn(); ent->spawnString = entities; // keep track of string definition of this entity entities = ED_ParseEdict( entities, ent ); if( !ent->classname ) { i++; // racesow - introducing the freestyle map bug again in // order to make some freestyle maps work if( !level.gametype.freestyleMapFix ) G_FreeEdict( ent ); // !racesow G_FreeEdict( ent ); continue; } if( !G_CanSpawnEntity( ent ) ) { i++; G_FreeEdict( ent ); continue; } if( !G_CallSpawn( ent ) ) { i++; G_FreeEdict( ent ); continue; } // check whether an item is allowed to spawn if( ( item = ent->item ) ) { // not pickable items aren't spawnable if( item->flags & ITFLAG_PICKABLE ) { if( G_Gametype_CanSpawnItem( item ) ) { // override entity's classname with whatever item specifies ent->classname = item->classname; PrecacheItem( item ); continue; } } i++; G_FreeEdict( ent ); continue; } } G_FindTeams(); // is the parsing string sane? assert( (int)level.map_parsed_len < entstrlen ); level.map_parsed_ents[level.map_parsed_len] = 0; // make sure server got the edicts data trap_LocateEntities( game.edicts, sizeof( game.edicts[0] ), game.numentities, game.maxentities ); // items need brush model entities spawned before they are linked G_Items_FinishSpawningItems(); // // initialize game subsystems which require entities initialized // // call gametype specific GT_asCallSpawn(); // call map specific G_asCallMapInit(); AI_InitEntitiesData(); // always start in warmup match state and let the thinking code // revert it to wait state if empty ( so gametype based item masks are setup ) G_Match_LaunchState( MATCH_STATE_WARMUP ); G_asGarbageCollect( true ); // racesow RS_Init(); }