示例#1
0
/*
=================
G_Spawn

Either finds a free edict, or allocates a new one.
Try to avoid reusing an entity that was recently freed, because it
can cause the client to think the entity morphed into something else
instead of being removed and recreated, which can cause interpolated
angles and bad trails.
=================
*/
edict_t *G_Spawn (void)
{
	int			i;
	edict_t		*e;

	e = &g_edicts[(int)maxclients->value+1];
	for ( i=maxclients->value+1 ; i<globals.num_edicts ; i++, e++)
	{
		// the first couple seconds of server time can involve a lot of
		// freeing and allocating, so relax the replacement policy
		if (!e->inuse && ( e->freetime < 2 || level.time - e->freetime > 0.5 ) )
		{
			G_InitEdict (e);
			return e;
		}
	}

	if (i == game.maxentities)
		gi.error ("ED_Alloc: no free edicts");

	globals.num_edicts++;

	if(developer->value && readout->value)
		gi.dprintf("num_edicts = %d\n",globals.num_edicts);

	G_InitEdict (e);
	return e;
}
示例#2
0
文件: g_utils.c 项目: phine4s/xatrix
/*
 * Either finds a free edict, or allocates a new one.
 * Try to avoid reusing an entity that was recently freed, because it
 * can cause the client to think the entity morphed into something else
 * instead of being removed and recreated, which can cause interpolated
 * angles and bad trails.
 */
edict_t *
G_Spawn(void)
{
	int i;
	edict_t *e;

	e = &g_edicts[(int)maxclients->value + 1];

	for (i = maxclients->value + 1; i < globals.num_edicts; i++, e++)
	{
		/* the first couple seconds of server time can involve a lot of
		   freeing and allocating, so relax the replacement policy */
		if (!e->inuse && ((e->freetime < 2) || (level.time - e->freetime > 0.5)))
		{
			G_InitEdict(e);
			return e;
		}
	}

	if (i == game.maxentities)
	{
		gi.error("ED_Alloc: no free edicts");
	}

	globals.num_edicts++;
	G_InitEdict(e);
	return e;
}
示例#3
0
文件: p_client.c 项目: ZwS/qudos
/*
===========
ClientBegin

called when a client has finished connecting, and is ready
to be placed into the game.  This will happen every level load.
============
*/
void ClientBegin (edict_t *ent)
{
	int		i;

	ent->client = game.clients + (ent - g_edicts - 1);

	if (deathmatch->value)
	{
		ClientBeginDeathmatch (ent);
		return;
	}

	// if there is already a body waiting for us (a loadgame), just
	// take it, otherwise spawn one from scratch
	if (ent->inuse == true)
	{
		// the client has cleared the client side viewangles upon
		// connecting to the server, which is different than the
		// state when the game is saved, so we need to compensate
		// with deltaangles
		for (i=0 ; i<3 ; i++)
			ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(ent->client->ps.viewangles[i]);
	}
	else
	{
		// a spawn point will completely reinitialize the entity
		// except for the persistant data that was initialized at
		// ClientConnect() time
		G_InitEdict (ent);
		ent->classname = "player";
		InitClientResp (ent->client);
		PutClientInServer (ent);
	}

	if (level.intermissiontime)
	{
		MoveClientToIntermission (ent);
	}
	else
	{
		// send effect if in a multiplayer game
		if (game.maxclients > 1)
		{
			gi.WriteByte (svc_muzzleflash);
			gi.WriteShort (ent-g_edicts);
			gi.WriteByte (MZ_LOGIN);
			gi.multicast (ent->s.origin, MULTICAST_PVS);

#ifdef WITH_ACEBOT
			safe_bprintf
#else
			gi.bprintf 
#endif
			(PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
		}
	}

	// make sure all view stuff is valid
	ClientEndServerFrame (ent);
}
示例#4
0
/*
=====================
ClientBeginDeathmatch

A client has just connected to the server in 
deathmatch mode, so clear everything out before starting them.
=====================
*/
void ClientBeginDeathmatch (edict_t *ent)
{
	G_InitEdict (ent);

	InitClientResp (ent->client);

	// locate ent at a spawn point
	PutClientInServer (ent);

	if (level.intermissiontime)
	{
		MoveClientToIntermission (ent);
	}
	else
	{
		// send effect
		gi.WriteByte (svc_muzzleflash);
		gi.WriteShort (ent-g_edicts);
		gi.WriteByte (MZ_LOGIN);
		gi.multicast (ent->s.origin, MULTICAST_PVS);
	}

	gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);

	// make sure all view stuff is valid
	ClientEndServerFrame (ent);
}
示例#5
0
文件: bot_spawn.c 项目: ZwS/qudos
///////////////////////////////////////////////////////////////////////
// Spawn the bot
///////////////////////////////////////////////////////////////////////
void BOT_SpawnBot (char *team, char *name, char *skin, char *userinfo)
{
	edict_t	*bot;

	if( !nav.loaded ) {
		Com_Printf("Can't spawn bots without a valid navigation file\n");
		return;
	}
	
	bot = BOT_FindFreeClient ();
	
	if (!bot)
	{
		safe_bprintf (PRINT_MEDIUM, "Server is full, increase Maxclients.\n");
		return;
	}

	//init the bot
	bot->inuse = true;
	bot->yaw_speed = 100;

	// To allow bots to respawn
	if(userinfo == NULL)
		BOT_SetName(bot, name, skin, team);
	else
		ClientConnect (bot, userinfo);
	
	G_InitEdict (bot);
	G_SpawnAI(bot); //jabot092(2)
	bot->ai->is_bot = true;
	InitClientResp (bot->client);

	PutClientInServer(bot);
	BOT_StartAsSpectator (bot);

	//skill
	bot->ai->pers.skillLevel = (int)(random()*MAX_BOT_SKILL);
	if (bot->ai->pers.skillLevel > MAX_BOT_SKILL)	//fix if off-limits
		bot->ai->pers.skillLevel =  MAX_BOT_SKILL;
	else if (bot->ai->pers.skillLevel < 0)
		bot->ai->pers.skillLevel =  0;

	BOT_DMclass_InitPersistant(bot);
	AI_ResetWeights(bot);
	AI_ResetNavigation(bot);

	bot->think = BOT_JoinGame;
	bot->nextthink = level.time + (int)(random()*6.0);
	if( ctf->value && team != NULL )
	{
		if( !Q_stricmp( team, "blue" ) )
			bot->think = BOT_JoinBlue;
		else if( !Q_stricmp( team, "red" ) )
			bot->think = BOT_JoinRed;
	}
	
	AI_EnemyAdded (bot); // let the ai know we added another
}
示例#6
0
/**
 * @brief Either finds a free edict, or allocates a new one.
 * @note Try to avoid reusing an entity that was recently freed, because it
 * can cause the player to think the entity morphed into something else
 * instead of being removed and recreated, which can cause interpolated
 * angles and bad trails.
 * @sa G_InitEdict
 * @sa G_FreeEdict
 */
edict_t *G_Spawn (void)
{
	edict_t *ent = G_EdictsGetNewEdict();

	if (!ent)
		gi.Error("G_Spawn: no free edicts");

	G_InitEdict(ent);
	return ent;
}
示例#7
0
/*
 * G_ClientBegin
 *
 * Called when a client has finished connecting, and is ready
 * to be placed into the game.  This will happen every level load.
 */
void G_ClientBegin(g_edict_t *ent) {
	char welcome[256];

	int player_num = ent - g_game.edicts - 1;

	ent->client = g_game.clients + player_num;

	G_InitEdict(ent);

	G_InitClientLocals(ent->client);

	VectorClear(ent->client->cmd_angles);
	ent->client->persistent.first_frame = g_level.frame_num;

	// force spectator if match or rounds
	if (g_level.match || g_level.rounds)
		ent->client->persistent.spectator = true;
	else if (g_level.teams || g_level.ctf) {
		if (g_auto_join->value)
			G_AddClientToTeam(ent, G_SmallestTeam()->name);
		else
			ent->client->persistent.spectator = true;
	}

	// spawn them in
	G_ClientRespawn(ent, true);

	if (g_level.intermission_time) {
		G_ClientToIntermission(ent);
	} else {
		memset(welcome, 0, sizeof(welcome));

		snprintf(welcome, sizeof(welcome),
				"^2Welcome to ^7http://quake2world.net\n"
				"^2Gameplay is ^1%s\n", G_GameplayName(g_level.gameplay));

		if (g_level.teams)
			strncat(welcome, "^2Teams are enabled\n", sizeof(welcome));

		if (g_level.ctf)
			strncat(welcome, "^2CTF is enabled\n", sizeof(welcome));

		if (g_voting->value)
			strncat(welcome, "^2Voting is allowed\n", sizeof(welcome));

		gi.ClientCenterPrint(ent, "%s", welcome);
	}

	// make sure all view stuff is valid
	G_ClientEndFrame(ent);

	srand(time(NULL)); // set random seed
}
示例#8
0
文件: p_client.c 项目: ZwS/qudos
/*
=====================
ClientBeginDeathmatch

A client has just connected to the server in 
deathmatch mode, so clear everything out before starting them.
=====================
*/
void ClientBeginDeathmatch (edict_t *ent)
{
#ifdef WITH_ACEBOT
// ACEBOT_ADD
	static char current_map[55];
// ACEBOT_END
#endif
	G_InitEdict (ent);
#ifdef WITH_ACEBOT
// ACEBOT_ADD
	ACEIT_PlayerAdded(ent);
// ACEBOT_END
#endif
	InitClientResp (ent->client);

	// locate ent at a spawn point
	PutClientInServer (ent);

	// send effect
	gi.WriteByte (svc_muzzleflash);
	gi.WriteShort (ent-g_edicts);
	gi.WriteByte (MZ_LOGIN);
	gi.multicast (ent->s.origin, MULTICAST_PVS);
#ifdef WITH_ACEBOT
	safe_bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
	safe_centerprintf(ent,"\nQ2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2\n\nZaero Bots\n\n\n'sv addbot' to add a new bot.\n\n'sv removebot <name>' to remove bot.\n\n\nhttp://qudos.quakedev.com\n\n\nQ2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q2\n\n");
	// If the map changes on us, init and reload the nodes
	if(strcmp(level.mapname,current_map))
	{
		
		ACEND_InitNodes();
		ACEND_LoadNodes();
		if (botauto_respawn->value) {
			ACESP_LoadBots();
		}
		strcpy(current_map,level.mapname);
	}

	safe_bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
// ACEBOT_END
#else
	gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
#endif	

	// make sure all view stuff is valid
	ClientEndServerFrame (ent);
}
void ClientBeginDeathmatch (edict_t *ent)
{
	// STEVE added these 3 local variables
	FILE *motd_file;
	char motd[500];
	char line[80];

	G_InitEdict (ent);

	InitClientResp (ent->client);

	// locate ent at a spawn point
	PutClientInServer (ent);

	// send effect
	gi.WriteByte (svc_muzzleflash);
	gi.WriteShort (ent-g_edicts);
	gi.WriteByte (MZ_LOGIN);
	gi.multicast (ent->s.origin, MULTICAST_PVS);

	gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);

	// STEVE changed this bit : read the motd from a file
	if (motd_file = fopen("motd.txt", "r"))
	{
		// we successfully opened the file "motd.txt"
		if ( fgets(motd, 500, motd_file) )
		{
			// we successfully read a line from "motd.txt" into motd
			// ... read the remaining lines now
			while ( fgets(line, 80, motd_file) )
			{
				// add each new line to motd, to create a BIG message string.
				// we are using strcat: STRing conCATenation function here.
				strcat(motd, line);
			}

			// print our message.
			gi.centerprintf (ent, motd);
		}
		// be good now ! ... close the file
		fclose(motd_file);
	}

	// make sure all view stuff is valid
	ClientEndServerFrame (ent);
}
示例#10
0
文件: acebot_spawn.c 项目: ZwS/qudos
///////////////////////////////////////////////////////////////////////
// Spawn the bot
///////////////////////////////////////////////////////////////////////
void ACESP_SpawnBot (char *team, char *name, char *skin, char *userinfo)
{
	edict_t	*bot;
	
	bot = ACESP_FindFreeClient ();
	
	if (!bot)
	{
		safe_bprintf (PRINT_MEDIUM, "Server is full, increase Maxclients.\n");
		return;
	}

	bot->yaw_speed = 100; // yaw speed
	bot->inuse = true;
	bot->is_bot = true;

	// To allow bots to respawn
	if(userinfo == NULL)
		ACESP_SetName(bot, name, skin, team);
	else
		ClientConnect (bot, userinfo);
	
	G_InitEdict (bot);

	InitClientResp (bot->client);
	
	// locate ent at a spawn point
    /*if(ctf->value)
	{
		if (team != NULL && strcmp(team,"red")==0)
			ACESP_PutClientInServer (bot,false, CTF_TEAM1);
		else
			ACESP_PutClientInServer (bot,false, CTF_TEAM2);
	}
	else*/
 		ACESP_PutClientInServer (bot,false,0);

	// make sure all view stuff is valid
	ClientEndServerFrame (bot);
	
	ACEIT_PlayerAdded (bot); // let the world know we added another

	ACEAI_PickLongRangeGoal(bot); // pick a new goal

}
示例#11
0
///////////////////////////////////////////////////////////////////////
// Spawn the bot
///////////////////////////////////////////////////////////////////////
void ACESP_SpawnBot(char *team, char *name, char *skin, char *userinfo)
{
	edict_t *bot = ACESP_FindFreeClient();
	
	if (!bot)
	{
		safe_bprintf(PRINT_MEDIUM, "Server is full, increase Maxclients.\n");
		return;
	}

	bot->yaw_speed = 100; // yaw speed
	bot->inuse = true;
	bot->is_bot = true;

	// To allow bots to respawn
	if (userinfo == NULL)
		ACESP_SetName(bot, name, skin, team);
	else
		ClientConnect (bot, userinfo);
	
	G_InitEdict (bot);

	InitClientResp (bot->client);
	
	// locate ent at a spawn point
	if (ctf->value)
	{
		// Knightmare- rewrote this
		int team1count = 0, team2count = 0, team3count = 0;
		int jointeam;
		const float r = random();

		for (int i = 1; i <= maxclients->value; i++)
		{
			edict_t *player = &g_edicts[i];
			if (!player->inuse || !player->client || player == bot)
				continue;

			switch (player->client->resp.ctf_team)
			{
			case CTF_TEAM1:
				team1count++;
				break;
			case CTF_TEAM2:
				team2count++;
				break;
			case CTF_TEAM3: 
				team3count++;
				break;
			}
		}

		if (ttctf->value)
		{
			if (team != NULL && strcmp(team,"red")==0)
				jointeam = CTF_TEAM1;
			else if (team != NULL && strcmp(team,"blue")==0)
				jointeam = CTF_TEAM2;
			else if (team != NULL && strcmp(team,"green")==0)
				jointeam = CTF_TEAM3;
			// join either of the outnumbered teams
			else if (team1count == team2count && team1count < team3count)
				jointeam = (r < 0.5) ? CTF_TEAM1 : CTF_TEAM2;
			else if (team1count == team3count && team1count < team2count)
				jointeam = (r < 0.5) ? CTF_TEAM1 : CTF_TEAM3;
			else if (team2count == team3count && team2count < team1count)
				jointeam = (r < 0.5) ? CTF_TEAM2 : CTF_TEAM3;
			// join outnumbered team
			else if (team1count < team2count && team1count < team3count)
				jointeam = CTF_TEAM1;
			else if (team2count < team1count &&  team2count < team3count) 
				jointeam = CTF_TEAM2;
			else if (team3count < team1count &&  team3count < team2count) 
				jointeam = CTF_TEAM3;
			// pick random team
			else if (r < 0.33)
				jointeam = CTF_TEAM1;
			else if (r < 0.66)
				jointeam = CTF_TEAM2;
			else
				jointeam = CTF_TEAM3;
		}
		else
		{
			if (team != NULL && strcmp(team,"red")==0)
				jointeam = CTF_TEAM1;
			else if (team != NULL && strcmp(team,"blue")==0)
				jointeam = CTF_TEAM2;
			// join outnumbered team
			else if (team1count < team2count)
				jointeam = CTF_TEAM1;
			else if (team2count < team1count)
				jointeam = CTF_TEAM2;
			// pick random team
			else if (r < 0.5)
				jointeam = CTF_TEAM1;
			else
				jointeam = CTF_TEAM2;
		}
		ACESP_PutClientInServer (bot,false, jointeam);
	}
	else
 		ACESP_PutClientInServer (bot,false,0);

	// make sure all view stuff is valid
	ClientEndServerFrame(bot);
	ACEIT_PlayerAdded(bot); // let the world know we added another
	ACEAI_PickLongRangeGoal(bot); // pick a new goal
}
示例#12
0
/*
* 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();
}
示例#13
0
/*
* CopyToBodyQue
*/
static edict_t *CopyToBodyQue( edict_t *ent, edict_t *attacker, int damage )
{
	edict_t	*body;
	int contents;

	if( GS_RaceGametype() )
		return NULL;

	contents = G_PointContents( ent->s.origin );
	if( contents & CONTENTS_NODROP )
		return NULL;

	G_Client_UnlinkBodies( ent );

	// grab a body que and cycle to the next one
	body = &game.edicts[gs.maxclients + level.body_que + 1];
	level.body_que = ( level.body_que + 1 ) % BODY_QUEUE_SIZE;

	// send an effect on the removed body
	if( body->s.modelindex && body->s.type == ET_CORPSE )
		ThrowSmallPileOfGibs( body, 10 );

	GClip_UnlinkEntity( body );

	memset( body, 0, sizeof( edict_t ) ); //clean up garbage

	//init body edict
	G_InitEdict( body );
	body->classname = "body";
	body->health = ent->health;
	body->mass = ent->mass;
	body->r.owner = ent->r.owner;
	body->s.type = ent->s.type;
	body->s.team = ent->s.team;
	body->s.effects = 0;
	body->r.svflags = SVF_CORPSE;
	body->r.svflags &= ~SVF_NOCLIENT;
	body->activator = ent;
	if( g_deadbody_followkiller->integer )
		body->enemy = attacker;

	//use flat yaw
	body->s.angles[PITCH] = 0;
	body->s.angles[ROLL] = 0;
	body->s.angles[YAW] = ent->s.angles[YAW];
	body->s.modelindex2 = 0; // <-  is bodyOwner when in ET_CORPSE, but not in ET_GENERIC or ET_PLAYER
	body->s.weapon = 0;

	//copy player position and box size
	VectorCopy( ent->s.old_origin, body->s.old_origin );
	VectorCopy( ent->s.origin, body->s.origin );
	VectorCopy( ent->s.origin, body->olds.origin );
	VectorCopy( ent->r.mins, body->r.mins );
	VectorCopy( ent->r.maxs, body->r.maxs );
	VectorCopy( ent->r.absmin, body->r.absmin );
	VectorCopy( ent->r.absmax, body->r.absmax );
	VectorCopy( ent->r.size, body->r.size );
	VectorCopy( ent->velocity, body->velocity );
	body->r.maxs[2] = body->r.mins[2] + 8;

	body->r.solid = SOLID_YES;
	body->takedamage = DAMAGE_YES;
	body->r.clipmask = CONTENTS_SOLID | CONTENTS_PLAYERCLIP;
	body->movetype = MOVETYPE_TOSS;
	body->die = body_die;
	body->think = body_think; // body self destruction countdown

	if( ent->health < GIB_HEALTH
		|| meansOfDeath == MOD_ELECTROBOLT_S /* electrobolt always gibs */ )
	{
		ThrowSmallPileOfGibs( body, damage );

		// reset gib impulse
		VectorClear( body->velocity );
		ThrowClientHead( body, damage ); // sets ET_GIB

		body->s.frame = 0;
		body->nextThink = level.time + 3000 + random() * 3000;
		body->deadflag = DEAD_DEAD;
	}
	else if( ent->s.type == ET_PLAYER )
	{
		// copy the model
		body->s.type = ET_CORPSE;
		body->s.modelindex = ent->s.modelindex;
		body->s.bodyOwner = ent->s.number; // bodyOwner is the same as modelindex2
		body->s.skinnum = ent->s.skinnum;
		body->s.teleported = true;

		// launch the death animation on the body
		{
			static int i;
			i = ( i+1 )%3;
			G_AddEvent( body, EV_DIE, i, true );
			switch( i )
			{
			default:
			case 0:
				body->s.frame = ( ( BOTH_DEAD1&0x3F )|( BOTH_DEAD1&0x3F )<<6|( 0 &0xF )<<12 );
				break;
			case 1:
				body->s.frame = ( ( BOTH_DEAD2&0x3F )|( BOTH_DEAD2&0x3F )<<6|( 0 &0xF )<<12 );
				break;
			case 2:
				body->s.frame = ( ( BOTH_DEAD3&0x3F )|( BOTH_DEAD3&0x3F )<<6|( 0 &0xF )<<12 );
				break;
			}
		}

		body->think = body_ready;
		body->takedamage = DAMAGE_NO;
		body->r.solid = SOLID_NOT;
		body->nextThink = level.time + 500; // make damageable in 0.5 seconds
	}
	else // wasn't a player, just copy it's model
	{
		VectorClear( body->velocity );
		body->s.modelindex = ent->s.modelindex;
		body->s.frame = ent->s.frame;
		body->nextThink = level.time + 5000 + random()*10000;
	}

	GClip_LinkEntity( body );
	return body;
}
示例#14
0
/*
* ClientConnect
* Called when a player begins connecting to the server.
* The game can refuse entrance to a client by returning false.
* If the client is allowed, the connection process will continue
* and eventually get to ClientBegin()
* Changing levels will NOT cause this to be called again, but
* loadgames will.
*/
bool ClientConnect( edict_t *ent, char *userinfo, bool fakeClient, bool tvClient )
{
	char *value;

	assert( ent );
	assert( userinfo && Info_Validate( userinfo ) );
	assert( Info_ValueForKey( userinfo, "ip" ) && Info_ValueForKey( userinfo, "socket" ) );

	// verify that server gave us valid data
	if( !Info_Validate( userinfo ) )
	{
		Info_SetValueForKey( userinfo, "rejtype", va( "%i", DROP_TYPE_GENERAL ) );
		Info_SetValueForKey( userinfo, "rejflag", va( "%i", 0 ) );
		Info_SetValueForKey( userinfo, "rejmsg", "Invalid userinfo" );
		return false;
	}

	if( !Info_ValueForKey( userinfo, "ip" ) )
	{
		Info_SetValueForKey( userinfo, "rejtype", va( "%i", DROP_TYPE_GENERAL ) );
		Info_SetValueForKey( userinfo, "rejflag", va( "%i", 0 ) );
		Info_SetValueForKey( userinfo, "rejmsg", "Error: Server didn't provide client IP" );
		return false;
	}

	if( !Info_ValueForKey( userinfo, "ip" ) )
	{
		Info_SetValueForKey( userinfo, "rejtype", va( "%i", DROP_TYPE_GENERAL ) );
		Info_SetValueForKey( userinfo, "rejflag", va( "%i", 0 ) );
		Info_SetValueForKey( userinfo, "rejmsg", "Error: Server didn't provide client socket" );
		return false;
	}

	// check to see if they are on the banned IP list
	value = Info_ValueForKey( userinfo, "ip" );
	if( SV_FilterPacket( value ) )
	{
		Info_SetValueForKey( userinfo, "rejtype", va( "%i", DROP_TYPE_GENERAL ) );
		Info_SetValueForKey( userinfo, "rejflag", va( "%i", 0 ) );
		Info_SetValueForKey( userinfo, "rejmsg", "You're banned from this server" );
		return false;
	}

	// check for a password
	value = Info_ValueForKey( userinfo, "password" );
	if( !fakeClient && ( *password->string && ( !value || strcmp( password->string, value ) ) ) )
	{
		Info_SetValueForKey( userinfo, "rejtype", va( "%i", DROP_TYPE_PASSWORD ) );
		Info_SetValueForKey( userinfo, "rejflag", va( "%i", 0 ) );
		if( value && value[0] )
		{
			Info_SetValueForKey( userinfo, "rejmsg", "Incorrect password" );
		}
		else
		{
			Info_SetValueForKey( userinfo, "rejmsg", "Password required" );
		}
		return false;
	}

	// they can connect

	G_InitEdict( ent );
	ent->s.modelindex = 0;
	ent->r.solid = SOLID_NOT;
	ent->r.client = game.clients + PLAYERNUM( ent );
	ent->r.svflags = ( SVF_NOCLIENT | ( fakeClient ? SVF_FAKECLIENT : 0 ) );
	memset( ent->r.client, 0, sizeof( gclient_t ) );
	ent->r.client->ps.playerNum = PLAYERNUM( ent );
	ent->r.client->connecting = true;
	ent->r.client->isTV = tvClient == true;
	ent->r.client->team = TEAM_SPECTATOR;
	G_Client_UpdateActivity( ent->r.client ); // activity detected

	ClientUserinfoChanged( ent, userinfo );

	if( !fakeClient ) {
		char message[MAX_STRING_CHARS];

		Q_snprintfz( message, sizeof( message ), "%s%s connected", ent->r.client->netname, S_COLOR_WHITE );

		G_PrintMsg( NULL, "%s\n", message );

		G_Printf( "%s%s connected from %s\n", ent->r.client->netname, S_COLOR_WHITE, ent->r.client->ip );
	}

	// let the gametype scripts know this client just connected
	G_Gametype_ScoreEvent( ent->r.client, "connect", NULL );

	G_CallVotes_ResetClient( PLAYERNUM( ent ) );

	return true;
}
示例#15
0
文件: g_spawn.c 项目: 5himmy/opentdm
void ParseEntityString (qboolean respawn)
{
	edict_t		*ent;
	int			inhibit;
	const char	*com_token;
	const char	*entities;
	int			i;

	entities = level.entity_string;

	ent = NULL;
	inhibit = 0;
	i = 0;

	//mark all the spawned_entities as inuse so G_Spawn doesn't try to pick them during
	//trigger spawning etc
	for (i = 0; i < num_spawned_entities; i++)
		spawned_entities[i]->inuse = true;

	i = 0;

// parse ents
	while (1)
	{
		// parse the opening brace	
		com_token = COM_Parse (&entities);
		if (!entities)
			break;
		if (com_token[0] != '{')
			gi.error ("ED_LoadFromFile: found %s when expecting {",com_token);

		if (respawn)
		{
			ent = spawned_entities[i];
			if (ent != world)
			{
				//double check we aren't overwriting stuff that we shouldn't be
				if (ent->enttype == ENT_DOOR_TRIGGER || ent->enttype == ENT_PLAT_TRIGGER)
					TDM_Error ("ParseEntityString: Trying to reuse an already spawned ent!");
				G_FreeEdict (ent);
				G_InitEdict (ent);
			}
			i++;
		}
		else
		{
			if (!ent)
				ent = g_edicts;
			else
				ent = G_Spawn ();
		}
		entities = ED_ParseEdict (entities, ent);

		// yet another map hack
		if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27"))
			ent->spawnflags &= ~SPAWNFLAG_NOT_HARD;

		// remove things (except the world) from different skill levels or deathmatch
		if (ent != g_edicts)
		{
			if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH )
			{
				G_FreeEdict (ent);	
				inhibit++;

				//have to keep num_spawned in sync for respawn
				if (!respawn)
					spawned_entities[num_spawned_entities++] = ent;
				continue;
			}

			ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH);
		}
		else if (respawn)
			continue;

		ED_CallSpawn (ent);

		if (!respawn)
		{
			if (num_spawned_entities == MAX_EDICTS * 4)
				TDM_Error ("Exceeded MAX_EDICTS * 4 entities during entity string parse");
			spawned_entities[num_spawned_entities++] = ent;
		}
		else
		{
			//an elevator or something respawned on top of a player? don't do it for match start, since
			//players will be respawning anyway.
			if (tdm_match_status < MM_PLAYING && (ent->solid == SOLID_BBOX || ent->solid == SOLID_BSP))
			{
				edict_t	*touch[MAX_EDICTS];
				int		count;
				int		j;

				//r1: fix 00000196, can't killbox during map spawn due to risk of killing half-spawned
				//map entities. do a pseudo-killbox that only whacks players instead.

				count = gi.BoxEdicts (ent->absmin, ent->absmax, touch, MAX_EDICTS, AREA_SOLID);
				for (j = 0; j < count; j++)
				{
					if (touch[j] == ent)
						continue;

					//no point killing anything that won't clip (eg corpses)
					if (touch[j]->solid == SOLID_NOT || touch[j]->enttype == ENT_BODYQUE)
						continue;

					if (!touch[j]->client)
						continue;

					if (touch[j]->inuse)
						T_Damage (touch[j], ent, ent, vec3_origin, ent->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
				}
			}
		}
	}

	//gi.dprintf ("%i entities inhibited\n", inhibit);

#ifdef DEBUG
	i = 1;
	ent = EDICT_NUM(i);
	while (i < globals.num_edicts) {
		if (ent->inuse != 0 || ent->inuse != 1)
			Com_DPrintf("Invalid entity %d\n", i);
		i++, ent++;
	}
#endif

	G_FindTeams ();
}