Beispiel #1
0
void ThrowSaberToAttacker(gentity_t *self, gentity_t *attacker)
{
	gentity_t *ent = &g_entities[self->client->ps.saberIndex];
	vec3_t a;
	int altVelocity = 0;

	if (!ent || ent->enemy != self)
	{ //something has gone very wrong (this should never happen)
		//but in case it does.. find the saber manually
#ifdef _DEBUG
		Com_Printf("Lost the saber! Attempting to use global pointer..\n");
#endif
		ent = gJMSaberEnt;

		if (!ent)
		{
#ifdef _DEBUG
			Com_Printf("The global pointer was NULL. This is a bad thing.\n");
#endif
			return;
		}

#ifdef _DEBUG
		Com_Printf("Got it (%i). Setting enemy to client %i.\n", ent->s.number, self->s.number);
#endif

		ent->enemy = self;
		self->client->ps.saberIndex = ent->s.number;
	}

	trap_SetConfigstring ( CS_CLIENT_JEDIMASTER, "-1" );

	if (attacker && attacker->client && self->client->ps.saberInFlight)
	{ //someone killed us and we had the saber thrown, so actually move this saber to the saber location
	  //if we killed ourselves with saber thrown, however, same suicide rules of respawning at spawn spot still
	  //apply.
		gentity_t *flyingsaber = &g_entities[self->client->ps.saberEntityNum];

		if (flyingsaber && flyingsaber->inuse)
		{
			VectorCopy(flyingsaber->s.pos.trBase, ent->s.pos.trBase);
			VectorCopy(flyingsaber->s.pos.trDelta, ent->s.pos.trDelta);
			VectorCopy(flyingsaber->s.apos.trBase, ent->s.apos.trBase);
			VectorCopy(flyingsaber->s.apos.trDelta, ent->s.apos.trDelta);

			VectorCopy(flyingsaber->r.currentOrigin, ent->r.currentOrigin);
			VectorCopy(flyingsaber->r.currentAngles, ent->r.currentAngles);
			altVelocity = 1;
		}
	}

	self->client->ps.saberInFlight = qtrue; //say he threw it anyway in order to properly remove from dead body

	ent->s.modelindex = G_ModelIndex("models/weapons2/saber/saber_w.glm");
	ent->s.eFlags &= ~(EF_NODRAW);
	ent->s.modelGhoul2 = 1;
	ent->s.eType = ET_MISSILE;
	ent->enemy = NULL;

	if (!attacker || !attacker->client)
	{
		VectorCopy(ent->s.origin2, ent->s.pos.trBase);
		VectorCopy(ent->s.origin2, ent->s.origin);
		VectorCopy(ent->s.origin2, ent->r.currentOrigin);
		ent->pos2[0] = 0;
		trap_LinkEntity(ent);
		return;
	}

	if (!altVelocity)
	{
		VectorCopy(self->s.pos.trBase, ent->s.pos.trBase);
		VectorCopy(self->s.pos.trBase, ent->s.origin);
		VectorCopy(self->s.pos.trBase, ent->r.currentOrigin);

		VectorSubtract(attacker->client->ps.origin, ent->s.pos.trBase, a);

		VectorNormalize(a);

		ent->s.pos.trDelta[0] = a[0]*256;
		ent->s.pos.trDelta[1] = a[1]*256;
		ent->s.pos.trDelta[2] = 256;
	}

	trap_LinkEntity(ent);
}
Beispiel #2
0
void SP_worldspawn( void ) 
{
	char		*text, temp[32];
	int			i;
	int			lengthRed, lengthBlue, lengthGreen;

	//I want to "cull" entities out of net sends to clients to reduce
	//net traffic on our larger open maps -rww
	G_SpawnFloat("distanceCull", "6000.0", &g_cullDistance);
	trap_SetServerCull(g_cullDistance);

	G_SpawnString( "classname", "", &text );
	if ( Q_stricmp( text, "worldspawn" ) ) {
		G_Error( "SP_worldspawn: The first entity isn't 'worldspawn'" );
	}

	for ( i = 0 ; i < level.numSpawnVars ; i++ ) 
	{
		if ( Q_stricmp( "spawnscript", level.spawnVars[i][0] ) == 0 )
		{//ONly let them set spawnscript, we don't want them setting an angle or something on the world.
			BG_ParseField( fields, level.spawnVars[i][0], level.spawnVars[i][1], (byte *)&g_entities[ENTITYNUM_WORLD] );
		}
	}
	//The server will precache the standard model and animations, so that there is no hit
	//when the first client connnects.
	if (!BGPAFtextLoaded)
	{
		BG_ParseAnimationFile("models/players/_humanoid/animation.cfg", bgHumanoidAnimations, qtrue);
	}

	if (!precachedKyle)
	{
		int defSkin;

		trap_G2API_InitGhoul2Model(&precachedKyle, "models/players/kyle/model.glm", 0, 0, -20, 0, 0);

		if (precachedKyle)
		{
			defSkin = trap_R_RegisterSkin("models/players/kyle/model_default.skin");
			trap_G2API_SetSkin(precachedKyle, 0, defSkin, defSkin);
		}
	}

	if (!g2SaberInstance)
	{
		trap_G2API_InitGhoul2Model(&g2SaberInstance, "models/weapons2/saber/saber_w.glm", 0, 0, -20, 0, 0);

		if (g2SaberInstance)
		{
			// indicate we will be bolted to model 0 (ie the player) on bolt 0 (always the right hand) when we get copied
			trap_G2API_SetBoltInfo(g2SaberInstance, 0, 0);
			// now set up the gun bolt on it
			trap_G2API_AddBolt(g2SaberInstance, 0, "*blade1");
		}
	}

	if (g_gametype.integer == GT_SIEGE)
	{ //a tad bit of a hack, but..
		EWebPrecache();
	}

	// 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", "", &text );
	trap_SetConfigstring( CS_MUSIC, text );

	G_SpawnString( "message", "", &text );
	trap_SetConfigstring( CS_MESSAGE, text );				// map specific message

	trap_SetConfigstring( CS_MOTD, g_motd.string );		// message of the day

	G_SpawnString( "gravity", "800", &text );
	trap_Cvar_Set( "g_gravity", text );

	G_SpawnString( "enableBreath", "0", &text );
	trap_Cvar_Set( "g_enableBreath", text );

	G_SpawnString( "soundSet", "default", &text );
	trap_SetConfigstring( CS_GLOBAL_AMBIENT_SET, text );

	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, "" );
	if ( g_restarted.integer ) {
		trap_Cvar_Set( "g_restarted", "0" );
		level.warmupTime = 0;
	} 
	/*
	else if ( g_doWarmup.integer && g_gametype.integer != GT_DUEL && g_gametype.integer != GT_POWERDUEL ) { // Turn it on
		level.warmupTime = -1;
		trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) );
		G_LogPrintf( "Warmup:\n" );
	}
	*/

	trap_SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+0, defaultStyles[0][0]);
	trap_SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+1, defaultStyles[0][1]);
	trap_SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+2, defaultStyles[0][2]);
	
	for(i=1;i<LS_NUM_STYLES;i++)
	{
		Com_sprintf(temp, sizeof(temp), "ls_%dr", i);
		G_SpawnString(temp, defaultStyles[i][0], &text);
		lengthRed = strlen(text);
		trap_SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+0, text);

		Com_sprintf(temp, sizeof(temp), "ls_%dg", i);
		G_SpawnString(temp, defaultStyles[i][1], &text);
		lengthGreen = strlen(text);
		trap_SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+1, text);

		Com_sprintf(temp, sizeof(temp), "ls_%db", i);
		G_SpawnString(temp, defaultStyles[i][2], &text);
		lengthBlue = strlen(text);
		trap_SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+2, text);

		if (lengthRed != lengthGreen || lengthGreen != lengthBlue)
		{
			Com_Error(ERR_DROP, "Style %d has inconsistent lengths: R %d, G %d, B %d", 
				i, lengthRed, lengthGreen, lengthBlue);
		}
	}		
}
Beispiel #3
0
void ThinkBalloonzone( gentity_t *self ) {
	//"(team == 0) ? TEAM_RED : TEAM_BLUE" => ! in this code red=0, blue=1 ! (unlike TEAM_RED(1), TEAM_BLUE(2) from team_t)
	// FIXME: Remove that offset team uglyness or at least make it readable!!1!
	int team, opponent;
	int numPlayers;
	team_t tteam;
	char *msg;

	if ( !self->message ) {
		msg = "Balloon";
	}
	else {
		msg = self->message;
	}

	if ( self->target_ent->s.frame ) {
		// get teams
		team = ( self->target_ent->s.generic1 - 1 );
		opponent = ( team ^ 1 );
		tteam = ( team + 1 );

		// capturing
		if ( ( self->target_ent->s.frame < 11 ) &&
		     ( self->teamMask & ( 1 << team ) ) &&
		     !( self->teamMask & (1 << opponent ) ) ) {

			numPlayers = NumPlayersAtBalloon( self, tteam );
			if ( numPlayers <= 0 ) {
				numPlayers = 1; //... so, we must not check this later
			}

			self->teamTime[team] += ( BALLOON_THINKTIME * numPlayers );
			self->target_ent->s.frame = ( 1 + self->teamTime[team] / ( 100 * self->speed ) );

			if ( self->target_ent->s.frame >= 11 ) {
				// captured
				self->last_move_time = 0;
				self->teamTime[team] = 0;
				level.balloonState[self->count] = ( '1' + team );
				trap_SetConfigstring( CS_BALLOONS, level.balloonState );

				// TODO: Give more points for capturing than for owning?
				//       Need to test balance!
				AddTeamScore( self->s.pos.trBase, tteam, ( BalloonScore() * 2 ), SCORE_BONUS_CAPTURE_S );
				AddBalloonScores( self, tteam, 1 );

				trap_SendServerCommand( -1, va( "mp \"%s captured by %s Team\"", msg, TeamName( tteam ) ) );
			}
		}

		// balloon is fully raised
		if ( self->target_ent->s.frame >= 11 ) {
			// animate
			self->last_move_time += BALLOON_THINKTIME;
			if ( self->last_move_time >= ( 700 * self->speed ) ) {
				self->last_move_time -= ( 700 * self->speed );
			}
			self->target_ent->s.frame = ( 11 + self->last_move_time / ( 100 * self->speed ) );

			// give points
			if ( !level.intermissiontime ) {
				self->teamTime[team] += BALLOON_THINKTIME;
				while ( self->teamTime[team] >= BALLOON_POINTTIME ) {
					self->teamTime[team] -= BALLOON_POINTTIME;

					AddTeamScore( self->s.pos.trBase, tteam, ( BalloonScore() * 2 ), SCORE_BONUS_CAPTURE_TEAM_S );
				}
			}
		}

		// countering capture
		if ( self->teamMask & (1 << opponent ) ) {
			numPlayers = NumPlayersAtBalloon( self, tteam );
			if ( numPlayers <= 0 ) {
				numPlayers = 1; //... so, we must not check this later
			}

			if ( !self->teamTime[opponent] ) {
				self->teamTime[opponent] = level.time;
			}
			// FIXME: If some players come "later", they will also be calculated for the full time.
			else if ( level.time > ( self->teamTime[opponent] + ( self->wait * 1000 / numPlayers ) ) ) {
				// countered
				self->teamTime[0] = 0;
				self->teamTime[1] = 0;
				self->target_ent->s.frame = 0;
				level.balloonState[self->count] = '0';
				trap_SetConfigstring( CS_BALLOONS, level.balloonState );

				// TODO: Also give players//&team points for destroying a balloon?

				trap_SendServerCommand( -1, va( "mp \"%s destroyed by %s Team\"", msg, TeamName( OtherTeam( tteam ) ) ) );
			}
		}
		else {
			self->teamTime[opponent] = 0;
		}
	}
	else {
		if ( ( self->teamMask & BT_RED ) && ( self->teamMask & BT_BLUE ) ) {
			// reset timer if both teams are trying to capture
			self->teamTime[0] = 0;
			self->teamTime[1] = 0;
		}
		else {
			for ( team = 0; team < 2; team++ ) {
				if ( self->teamMask & ( 1 << team ) ) {
					// start capture timer or test for capture
					if ( !self->teamTime[team] ) {
						self->teamTime[team] = level.time;
					}
					else if ( level.time > ( self->teamTime[team] + 1000 ) ) {
						self->teamTime[team] = 0;
						self->teamTime[team^1] = level.time;
						self->target_ent->s.generic1 = ( team + 1 );
						self->target_ent->s.frame = 1;
						level.balloonState[self->count] = ( 'a' + team );
						trap_SetConfigstring( CS_BALLOONS, level.balloonState );

						trap_SendServerCommand( -1, va( "mp \"%s under attack by %s Team\"", msg, TeamName( team + 1 ) ) );
					}
				} 
				else {
					self->teamTime[team] = 0;
				}
			}
		}
	}

	// prepare next think

	//#@070329: some delay ... i think there isn't always a touch-call (with laging clients)
	// "TEAM_RED ? 0 : 1" @ teamTime[...]
	if ( ( self->target_ent->teamTime[0] + BALLOON_TOUCHDELAY ) < level.time ) {
		self->teamMask &= ~BT_RED;
	}
	if ( ( self->target_ent->teamTime[1] + BALLOON_TOUCHDELAY ) < level.time ) {
		self->teamMask &= ~BT_BLUE;
	}

	self->nextthink = ( level.time + BALLOON_THINKTIME );
}
Beispiel #4
0
/*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( "humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, &s );
  trap_Cvar_Set( "g_humanBuildPoints", s );

  G_SpawnString( "humanMaxStage", DEFAULT_HUMAN_MAX_STAGE, &s );
  trap_Cvar_Set( "g_humanMaxStage", s );

  G_SpawnString( "humanStage2Threshold", DEFAULT_HUMAN_STAGE2_THRESH, &s );
  trap_Cvar_Set( "g_humanStage2Threshold", s );

  G_SpawnString( "humanStage3Threshold", DEFAULT_HUMAN_STAGE3_THRESH, &s );
  trap_Cvar_Set( "g_humanStage3Threshold", s );

  G_SpawnString( "alienBuildPoints", DEFAULT_ALIEN_BUILDPOINTS, &s );
  trap_Cvar_Set( "g_alienBuildPoints", s );

  G_SpawnString( "alienMaxStage", DEFAULT_ALIEN_MAX_STAGE, &s );
  trap_Cvar_Set( "g_alienMaxStage", s );

  G_SpawnString( "alienStage2Threshold", DEFAULT_ALIEN_STAGE2_THRESH, &s );
  trap_Cvar_Set( "g_alienStage2Threshold", s );

  G_SpawnString( "alienStage3Threshold", DEFAULT_ALIEN_STAGE3_THRESH, &s );
  trap_Cvar_Set( "g_alienStage3Threshold", s );

  G_SpawnString( "enableDust", "0", &s );
  trap_Cvar_Set( "g_enableDust", s );

  G_SpawnString( "enableBreath", "0", &s );
  trap_Cvar_Set( "g_enableBreath", s );

  G_SpawnString( "disabledEquipment", "", &s );
  trap_Cvar_Set( "g_disabledEquipment", s );

  G_SpawnString( "disabledClasses", "", &s );
  trap_Cvar_Set( "g_disabledClasses", s );

  G_SpawnString( "disabledBuildables", "", &s );
  trap_Cvar_Set( "g_disabledBuildables", s );

  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, "" );
  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" );
  }

}
Beispiel #5
0
void SP_trigger_objective_info( gentity_t *ent ) {
	char *scorestring;

	if ( !ent->track ) {
		G_Error( "'trigger_objective_info' does not have a 'track' \n" );
	}

	if ( level.numOidTriggers >= MAX_OID_TRIGGERS ) {
		G_Error( "Exceeded maximum number of 'trigger_objective_info' entities\n" );
	}

	// JPW NERVE -- if this trigger has a "score" field set, then blowing up an objective
	//  inside of this field will add "score" to the right player team.  storing this
	//  in ent->accuracy since that's unused.
	G_SpawnString( "score", "0", &scorestring );
	ent->accuracy = atof( scorestring );
	// jpw

	// Arnout: HACK HACK - someone at nerve forgot to add the score field to sub - have to
	// hardcode it cause we don't want people to download the map again
	{
		char mapName[MAX_QPATH];
		trap_Cvar_VariableStringBuffer( "mapname", mapName, sizeof( mapName ) );
		if ( !Q_stricmp( mapName, "mp_sub" ) && !Q_stricmp( ent->track, "the Axis Submarine" ) ) {
			ent->accuracy = 15;
		}
	}

	trap_SetConfigstring( CS_OID_TRIGGERS + level.numOidTriggers, ent->track );
	ent->s.teamNum = level.numOidTriggers;

	level.numOidTriggers++;
	InitTrigger( ent );

	// unlike other triggers, we need to send this one to the client
	ent->r.svFlags &= ~SVF_NOCLIENT;
	ent->s.eType = ET_OID_TRIGGER;

	trap_LinkEntity( ent );

	// NERVE - SMF - spawn an explosive indicator
	if ( ( ent->spawnflags & AXIS_OBJECTIVE ) || ( ent->spawnflags & ALLIED_OBJECTIVE ) ) {
		gentity_t *e;
		e = G_Spawn();

		e->r.svFlags = SVF_BROADCAST;
		e->classname = "explosive_indicator";
		e->s.eType = ET_EXPLOSIVE_INDICATOR;
		e->s.pos.trType = TR_STATIONARY;

		if ( ent->spawnflags & AXIS_OBJECTIVE ) {
			e->s.teamNum = 1;
		} else if ( ent->spawnflags & ALLIED_OBJECTIVE ) {
			e->s.teamNum = 2;
		}

		e->r.ownerNum = ent->s.number;
		e->think = explosive_indicator_think;
		e->nextthink = level.time + FRAMETIME;

		VectorCopy( ent->r.mins, e->s.pos.trBase );
		VectorAdd( ent->r.maxs, e->s.pos.trBase, e->s.pos.trBase );
		VectorScale( e->s.pos.trBase, 0.5, e->s.pos.trBase );

		SnapVector( e->s.pos.trBase );

		trap_LinkEntity( e );
	}
	// -NERVE - SMF
}
Beispiel #6
0
/*
==================
AICast_CheckLoadGame

  at the start of a level, the game is either saved, or loaded

  we must wait for all AI to spawn themselves, and a real client to connect
==================
*/
void AICast_CheckLoadGame( void ) {
    char loading[4];
    gentity_t *ent = NULL; // TTimo: VC6 'may be used without having been init'
    qboolean ready;
    cast_state_t *pcs;

    // have we already done the save or load?
    if ( !saveGamePending ) {
        return;
    }

    // tell the cgame NOT to render the scene while we are waiting for things to settle
    trap_Cvar_Set( "cg_norender", "1" );

    trap_Cvar_VariableStringBuffer( "savegame_loading", loading, sizeof( loading ) );

//	reloading = qtrue;
    trap_Cvar_Set( "g_reloading", "1" );

    if ( strlen( loading ) > 0 && atoi( loading ) != 0 ) {
        // screen should be black if we are at this stage
        trap_SetConfigstring( CS_SCREENFADE, va( "1 %i 1", level.time - 10 ) );

//		if (!reloading && atoi(loading) == 2) {
        if ( !( g_reloading.integer ) && atoi( loading ) == 2 ) {
            // (SA) hmm, this seems redundant when it sets it above...
//			reloading = qtrue;	// this gets reset at the Map_Restart() since the server unloads the game dll
            trap_Cvar_Set( "g_reloading", "1" );
        }

        ready = qtrue;
        if ( numSpawningCast != numcast ) {
            ready = qfalse;
        } else if ( !( ent = AICast_FindEntityForName( "player" ) ) ) {
            ready = qfalse;
        } else if ( !ent->client || ent->client->pers.connected != CON_CONNECTED ) {
            ready = qfalse;
        }

        if ( ready ) {
            trap_Cvar_Set( "savegame_loading", "0" ); // in-case it aborts
            saveGamePending = qfalse;
            G_LoadGame( NULL );     // always load the "current" savegame

            // RF, spawn a thinker that will enable rendering after the client has had time to process the entities and setup the display
            //trap_Cvar_Set( "cg_norender", "0" );
            ent = G_Spawn();
            ent->nextthink = level.time + 200;
            ent->think = AICast_EnableRenderingThink;

            // wait for the clients to return from faded screen
            //trap_SetConfigstring( CS_SCREENFADE, va("0 %i 1500", level.time + 500) );
            trap_SetConfigstring( CS_SCREENFADE, va( "0 %i 750", level.time + 500 ) );
            level.reloadPauseTime = level.time + 1100;

            // make sure sound fades up
            trap_SendServerCommand( -1, va( "snd_fade 1 %d", 2000 ) );  //----(SA)	added

            AICast_CastScriptThink();
        }
    } else {

        ready = qtrue;
        if ( numSpawningCast != numcast ) {
            ready = qfalse;
        } else if ( !( ent = AICast_FindEntityForName( "player" ) ) ) {
            ready = qfalse;
        } else if ( !ent->client || ent->client->pers.connected != CON_CONNECTED ) {
            ready = qfalse;
        }

        // not loading a game, we must be in a new level, so look for some persistant data to read in, then save the game
        if ( ready ) {
            G_LoadPersistant();     // make sure we save the game after we have brought across the items

            trap_Cvar_Set( "g_totalPlayTime", "0" );  // reset play time
            trap_Cvar_Set( "g_attempts", "0" );
            pcs = AICast_GetCastState( ent->s.number );
            pcs->totalPlayTime = 0;
            pcs->lastLoadTime = 0;
            pcs->attempts = 0;

            // RF, disabled, since the pregame menu turns this off after the button is pressed, this isn't
            // required here
            // RF, spawn a thinker that will enable rendering after the client has had time to process the entities and setup the display
            //trap_Cvar_Set( "cg_norender", "0" );
            //ent = G_Spawn();
            //ent->nextthink = level.time + 200;
            //ent->think = AICast_EnableRenderingThink;

            saveGamePending = qfalse;

            // wait for the clients to return from faded screen
//			trap_SetConfigstring( CS_SCREENFADE, va("0 %i 1500", level.time + 500) );
//			trap_SetConfigstring( CS_SCREENFADE, va("0 %i 750", level.time + 500) );
            // (SA) send a command that will be interpreted for both the screenfade and any other effects (music cues, pregame menu, etc)

// briefing menu will handle transition, just set a cvar for it to check for drawing the 'continue' button
            trap_SendServerCommand( -1, "rockandroll\n" );

            level.reloadPauseTime = level.time + 1100;

            AICast_CastScriptThink();
        }
    }
}
Beispiel #7
0
/*
===========
ClientDisconnect

Called when a player drops from the server.
Will not be called between levels.

This should NOT be called directly by any game logic,
call trap_DropClient(), which will call this and do
server system housekeeping.
============
*/
void ClientDisconnect( int clientNum ) {
	gentity_t	*ent;
	gentity_t	*tent;
	int			i;

	// cleanup if we are kicking a bot that
	// hasn't spawned yet
	G_RemoveQueuedBotBegin( clientNum );

	ent = g_entities + clientNum;
	if ( !ent->client ) {
		return;
	}

	// stop any following clients
	for ( i = 0 ; i < level.maxclients ; i++ ) {
		if ( level.clients[i].sess.sessionTeam == TEAM_SPECTATOR
			&& level.clients[i].sess.spectatorState == SPECTATOR_FOLLOW
			&& level.clients[i].sess.spectatorClient == clientNum ) {
			StopFollowing( &g_entities[i] );
		}
	}

	// send effect if they were completely connected
	if ( ent->client->pers.connected == CON_CONNECTED 
		&& ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
		tent->s.clientNum = ent->s.clientNum;

		// They don't get to take powerups with them!
		// Especially important for stuff like CTF flags
		TossClientItems( ent );
#ifdef MISSIONPACK
		TossClientPersistantPowerups( ent );
		if( g_gametype.integer == GT_HARVESTER ) {
			TossClientCubes( ent );
		}
#endif

	}

	G_LogPrintf( "ClientDisconnect: %i\n", clientNum );

	// if we are playing in tourney mode and losing, give a win to the other player
	if ( (g_gametype.integer == GT_TOURNAMENT )
		&& !level.intermissiontime
		&& !level.warmupTime && level.sortedClients[1] == clientNum ) {
		level.clients[ level.sortedClients[0] ].sess.wins++;
		ClientUserinfoChanged( level.sortedClients[0] );
	}

	trap_UnlinkEntity (ent);
	ent->s.modelindex = 0;
	ent->inuse = qfalse;
	ent->classname = "disconnected";
	ent->client->pers.connected = CON_DISCONNECTED;
	ent->client->ps.persistant[PERS_TEAM] = TEAM_FREE;
	ent->client->sess.sessionTeam = TEAM_FREE;

	trap_SetConfigstring( CS_PLAYERS + clientNum, "");

	CalculateRanks();

	if ( ent->r.svFlags & SVF_BOT ) {
		BotAIShutdownClient( clientNum, qfalse );
	}
}
Beispiel #8
0
/*
===========
PlayerUserinfoChanged

Called from PlayerConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
void PlayerUserinfoChanged( int playerNum ) {
	gentity_t *ent;
	int		teamTask, teamLeader;
	char	*s;
	char	model[MAX_QPATH];
	char	headModel[MAX_QPATH];
	char	oldname[MAX_STRING_CHARS];
	gplayer_t	*player;
	char	c1[MAX_INFO_STRING];
	char	c2[MAX_INFO_STRING];
	char	userinfo[MAX_INFO_STRING];

	ent = g_entities + playerNum;
	player = ent->player;

	trap_GetUserinfo( playerNum, userinfo, sizeof( userinfo ) );

	// check for malformed or illegal info strings
	if ( !Info_Validate(userinfo) ) {
		strcpy (userinfo, "\\name\\badinfo");
		// don't keep those players and userinfo
		trap_DropPlayer(playerNum, "Invalid userinfo");
	}

	// check the item prediction
	s = Info_ValueForKey( userinfo, "cg_predictItems" );
	if ( !atoi( s ) ) {
		player->pers.predictItemPickup = qfalse;
	} else {
		player->pers.predictItemPickup = qtrue;
	}

	// check the anti lag
	s = Info_ValueForKey( userinfo, "cg_antiLag" );
	player->pers.antiLag = atoi( s );

	// set name
	Q_strncpyz ( oldname, player->pers.netname, sizeof( oldname ) );
	s = Info_ValueForKey (userinfo, "name");
	PlayerCleanName( s, player->pers.netname, sizeof(player->pers.netname) );

	if ( player->sess.sessionTeam == TEAM_SPECTATOR ) {
		if ( player->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
			Q_strncpyz( player->pers.netname, "scoreboard", sizeof(player->pers.netname) );
		}
	}

	if ( player->pers.connected == CON_CONNECTED ) {
		if ( strcmp( oldname, player->pers.netname ) ) {
			trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " renamed to %s\n\"", oldname, 
				player->pers.netname) );
		}
	}

	// set max health
#ifdef MISSIONPACK
	if (player->ps.powerups[PW_GUARD]) {
		player->pers.maxHealth = 200;
	} else {
		player->pers.maxHealth = PlayerHandicap( player );
	}
#else
	player->pers.maxHealth = PlayerHandicap( player );
#endif
	player->ps.stats[STAT_MAX_HEALTH] = player->pers.maxHealth;

	// set model
	if( g_gametype.integer >= GT_TEAM ) {
		Q_strncpyz( model, Info_ValueForKey (userinfo, "team_model"), sizeof( model ) );
		Q_strncpyz( headModel, Info_ValueForKey (userinfo, "team_headmodel"), sizeof( headModel ) );
	} else {
		Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) );
		Q_strncpyz( headModel, Info_ValueForKey (userinfo, "headmodel"), sizeof( headModel ) );
	}

#ifdef MISSIONPACK
	if (g_gametype.integer >= GT_TEAM) {
		player->pers.teamInfo = qtrue;
	} else {
		s = Info_ValueForKey( userinfo, "teamoverlay" );
		if ( ! *s || atoi( s ) != 0 ) {
			player->pers.teamInfo = qtrue;
		} else {
			player->pers.teamInfo = qfalse;
		}
	}
#else
	// teamInfo
	s = Info_ValueForKey( userinfo, "teamoverlay" );
	if ( ! *s || atoi( s ) != 0 ) {
		player->pers.teamInfo = qtrue;
	} else {
		player->pers.teamInfo = qfalse;
	}
#endif
	/*
	s = Info_ValueForKey( userinfo, "cg_pmove_fixed" );
	if ( !*s || atoi( s ) == 0 ) {
		player->pers.pmoveFixed = qfalse;
	}
	else {
		player->pers.pmoveFixed = qtrue;
	}
	*/

	// team task (0 = none, 1 = offence, 2 = defence)
	teamTask = atoi(Info_ValueForKey(userinfo, "teamtask"));
	// team Leader (1 = leader, 0 is normal player)
	teamLeader = player->sess.teamLeader;

	// colors
	strcpy(c1, Info_ValueForKey( userinfo, "color1" ));
	strcpy(c2, Info_ValueForKey( userinfo, "color2" ));

	// send over a subset of the userinfo keys so other clients can
	// print scoreboards, display models, and play custom sounds
	if (ent->r.svFlags & SVF_BOT)
	{
		s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d",
			player->pers.netname, player->sess.sessionTeam, model, headModel, c1, c2, 
			player->pers.maxHealth, player->sess.wins, player->sess.losses,
			Info_ValueForKey( userinfo, "skill" ), teamTask, teamLeader );
	}
	else
	{
		s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d",
			player->pers.netname, player->sess.sessionTeam, model, headModel, c1, c2, 
			player->pers.maxHealth, player->sess.wins, player->sess.losses, teamTask, teamLeader);
	}

	trap_SetConfigstring( CS_PLAYERS+playerNum, s );

	// this is not the userinfo, more like the configstring actually
	G_LogPrintf( "PlayerUserinfoChanged: %i %s\n", playerNum, s );
}
Beispiel #9
0
/*QUAKED worldspawn (0 0 0) ? NO_GT_WOLF NO_GT_STOPWATCH NO_GT_CHECKPOINT NO_LMS

Every map should have exactly one worldspawn.
"music"     Music wav file
"gravity"   800 is default gravity
"message" Text to print during connection process
"ambient"  Ambient light value (must use '_color')
"_color"    Ambient light color (must be used with 'ambient')
"sun"        Shader to use for 'sun' image
*/
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'\n");
	}

	// 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

	G_SpawnString("cclayers", "0", &s);
	if (atoi(s))
	{
		level.ccLayers = qtrue;
	}

	level.mapcoordsValid = qfalse;
	if (G_SpawnVector2D("mapcoordsmins", "-128 128", level.mapcoordsMins) &&     // top left
	    G_SpawnVector2D("mapcoordsmaxs", "128 -128", level.mapcoordsMaxs))       // bottom right
	{
		level.mapcoordsValid = qtrue;
	}

	BG_InitLocations(level.mapcoordsMins, level.mapcoordsMaxs);

	trap_SetConfigstring(CS_MOTD, g_motd.string);       // message of the day

	G_SpawnString("gravity", "800", &s);
	trap_Cvar_Set("g_gravity", s);

	G_SpawnString("spawnflags", "0", &s);
	g_entities[ENTITYNUM_WORLD].spawnflags   = atoi(s);
	g_entities[ENTITYNUM_WORLD].r.worldflags = g_entities[ENTITYNUM_WORLD].spawnflags;

	g_entities[ENTITYNUM_WORLD].s.number   = ENTITYNUM_WORLD;
	g_entities[ENTITYNUM_WORLD].r.ownerNum = ENTITYNUM_NONE;
	g_entities[ENTITYNUM_WORLD].classname  = "worldspawn";

	g_entities[ENTITYNUM_NONE].s.number   = ENTITYNUM_NONE;
	g_entities[ENTITYNUM_NONE].r.ownerNum = ENTITYNUM_NONE;
	g_entities[ENTITYNUM_NONE].classname  = "nothing";

	// see if we want a warmup time
	trap_SetConfigstring(CS_WARMUP, "");
	if (g_restarted.integer)
	{
		trap_Cvar_Set("g_restarted", "0");
		level.warmupTime = 0;
	}

	if (g_gamestate.integer == GS_PLAYING)
	{
		G_initMatch();
	}
}
Beispiel #10
0
/*
============
CalculateRanks

Recalculates the score ranks of all players
This will be called on every client connect, begin, disconnect, death,
and team change.
============
*/
void CalculateRanks( void ) {
	int		i;
	int		rank;
	int		score;
	int		newScore;
	gclient_t	*cl;

	level.follow1 = -1;
	level.follow2 = -1;
	level.numConnectedClients = 0;
	level.numNonSpectatorClients = 0;
	level.numPlayingClients = 0;
	level.numVotingClients = 0;		// don't count bots
	for ( i = 0; i < TEAM_NUM_TEAMS; i++ ) {
		level.numteamVotingClients[i] = 0;
	}
	for ( i = 0 ; i < level.maxclients ; i++ ) {
		if ( level.clients[i].pers.connected != CON_DISCONNECTED ) {
			level.sortedClients[level.numConnectedClients] = i;
			level.numConnectedClients++;

			if ( level.clients[i].sess.sessionTeam != TEAM_SPECTATOR ) {
				level.numNonSpectatorClients++;
			
				// decide if this should be auto-followed
				if ( level.clients[i].pers.connected == CON_CONNECTED ) {
					level.numPlayingClients++;
					if ( !(g_entities[i].r.svFlags & SVF_BOT) ) {
						level.numVotingClients++;
						if ( level.clients[i].sess.sessionTeam == TEAM_RED )
							level.numteamVotingClients[0]++;
						else if ( level.clients[i].sess.sessionTeam == TEAM_BLUE )
							level.numteamVotingClients[1]++;
					}
					if ( level.follow1 == -1 ) {
						level.follow1 = i;
					} else if ( level.follow2 == -1 ) {
						level.follow2 = i;
					}
				}
			}
		}
	}

	qsort( level.sortedClients, level.numConnectedClients, 
		sizeof(level.sortedClients[0]), SortRanks );

	// set the rank value for all clients that are connected and not spectators
	if ( g_gametype.integer >= GT_TEAM ) {
		// in team games, rank is just the order of the teams, 0=red, 1=blue, 2=tied
		for ( i = 0;  i < level.numConnectedClients; i++ ) {
			cl = &level.clients[ level.sortedClients[i] ];
			if ( level.teamScores[TEAM_RED] == level.teamScores[TEAM_BLUE] ) {
				cl->ps.persistant[PERS_RANK] = 2;
			} else if ( level.teamScores[TEAM_RED] > level.teamScores[TEAM_BLUE] ) {
				cl->ps.persistant[PERS_RANK] = 0;
			} else {
				cl->ps.persistant[PERS_RANK] = 1;
			}
		}
	} else {	
		rank = -1;
		score = 0;
		for ( i = 0;  i < level.numPlayingClients; i++ ) {
			cl = &level.clients[ level.sortedClients[i] ];
			newScore = cl->ps.persistant[PERS_SCORE];
			if ( i == 0 || newScore != score ) {
				rank = i;
				// assume we aren't tied until the next client is checked
				level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank;
			} else {
				// we are tied with the previous client
				level.clients[ level.sortedClients[i-1] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
				level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
			}
			score = newScore;
			if ( g_gametype.integer == GT_SINGLE_PLAYER && level.numPlayingClients == 1 ) {
				level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
			}
		}
	}

	// set the CS_SCORES1/2 configstrings, which will be visible to everyone
	if ( g_gametype.integer >= GT_TEAM ) {
		trap_SetConfigstring( CS_SCORES1, va("%i", level.teamScores[TEAM_RED] ) );
		trap_SetConfigstring( CS_SCORES2, va("%i", level.teamScores[TEAM_BLUE] ) );
	} else {
		if ( level.numConnectedClients == 0 ) {
			trap_SetConfigstring( CS_SCORES1, va("%i", SCORE_NOT_PRESENT) );
			trap_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
		} else if ( level.numConnectedClients == 1 ) {
			trap_SetConfigstring( CS_SCORES1, va("%i", level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE] ) );
			trap_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
		} else {
			trap_SetConfigstring( CS_SCORES1, va("%i", level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE] ) );
			trap_SetConfigstring( CS_SCORES2, va("%i", level.clients[ level.sortedClients[1] ].ps.persistant[PERS_SCORE] ) );
		}
	}

	// see if it is time to end the level
	CheckExitRules();

	// if we are at the intermission, send the new info to everyone
	if ( level.intermissiontime ) {
		SendScoreboardMessageToAllClients();
	}
}
Beispiel #11
0
/*
===========
PlayerDisconnect

Called when a player drops from the server.
Will not be called between levels.

This should NOT be called directly by any game logic,
call trap_DropPlayer(), which will call this and do
server system housekeeping.
============
*/
void PlayerDisconnect( int playerNum ) {
	gentity_t	*ent;
	gentity_t	*tent;
	int			i;

	// cleanup if we are kicking a bot that
	// hasn't spawned yet
	G_RemoveQueuedBotBegin( playerNum );

	ent = g_entities + playerNum;
	if (!ent->player || ent->player->pers.connected == CON_DISCONNECTED) {
		return;
	}

	// stop any following players
	for ( i = 0 ; i < level.maxplayers ; i++ ) {
		if ( level.players[i].sess.sessionTeam == TEAM_SPECTATOR
			&& level.players[i].sess.spectatorState == SPECTATOR_FOLLOW
			&& level.players[i].sess.spectatorPlayer == playerNum ) {
			StopFollowing( &g_entities[i] );
		}
	}

	// send effect if they were completely connected
	if ( ent->player->pers.connected == CON_CONNECTED 
		&& ent->player->sess.sessionTeam != TEAM_SPECTATOR ) {
		tent = G_TempEntity( ent->player->ps.origin, EV_PLAYER_TELEPORT_OUT );
		tent->s.playerNum = ent->s.playerNum;

		// They don't get to take powerups with them!
		// Especially important for stuff like CTF flags
		TossPlayerItems( ent );
#ifdef MISSIONPACK
		TossPlayerPersistantPowerups( ent );
		if( g_gametype.integer == GT_HARVESTER ) {
			TossPlayerCubes( ent );
		}
#endif

	}

	G_LogPrintf( "PlayerDisconnect: %i\n", playerNum );

	// if we are playing in tourney mode and losing, give a win to the other player
	if ( (g_gametype.integer == GT_TOURNAMENT )
		&& !level.intermissiontime
		&& !level.warmupTime && level.sortedPlayers[1] == playerNum ) {
		level.players[ level.sortedPlayers[0] ].sess.wins++;
		PlayerUserinfoChanged( level.sortedPlayers[0] );
	}

	if( g_gametype.integer == GT_TOURNAMENT &&
		ent->player->sess.sessionTeam == TEAM_FREE &&
		level.intermissiontime ) {

		trap_Cmd_ExecuteText( EXEC_APPEND, "map_restart 0\n" );
		level.restarted = qtrue;
		level.changemap = NULL;
		level.intermissiontime = 0;
	}

	trap_UnlinkEntity (ent);
	ent->s.modelindex = 0;
	ent->inuse = qfalse;
	ent->classname = "disconnected";
	ent->player->pers.connected = CON_DISCONNECTED;
	ent->player->ps.persistant[PERS_TEAM] = TEAM_FREE;
	ent->player->sess.sessionTeam = TEAM_FREE;

	trap_SetConfigstring( CS_PLAYERS + playerNum, "");

	CalculateRanks();

	if ( ent->r.svFlags & SVF_BOT ) {
		BotAIShutdownPlayer( playerNum, qfalse );
	}

	// clear player connection info
	level.connections[ent->player->pers.connectionNum].numLocalPlayers--;
	level.connections[ent->player->pers.connectionNum].localPlayerNums[ent->player->pers.localPlayerNum] = -1;
	ent->player->pers.localPlayerNum = ent->player->pers.connectionNum = -1;
}
Beispiel #12
0
/*
=============
CheckTournament

Once a frame, check for changes in tournement player state
=============
*/
void CheckTournament( void ) {
	// check because we run 3 game frames before calling Connect and/or ClientBegin
	// for clients on a map_restart
	if ( level.numPlayingClients == 0 ) {
		return;
	}

	if ( g_gametype.integer == GT_TOURNAMENT ) {

		// pull in a spectator if needed
		if ( level.numPlayingClients < 2 ) {
			AddTournamentPlayer();
		}

		// if we don't have two players, go back to "waiting for players"
		if ( level.numPlayingClients != 2 ) {
			if ( level.warmupTime != -1 ) {
				level.warmupTime = -1;
				trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) );
				G_LogPrintf( "Warmup:\n" );
			}
			return;
		}

		if ( level.warmupTime == 0 ) {
			return;
		}

		// if the warmup is changed at the console, restart it
		if ( g_warmup.modificationCount != level.warmupModificationCount ) {
			level.warmupModificationCount = g_warmup.modificationCount;
			level.warmupTime = -1;
		}

		// if all players have arrived, start the countdown
		if ( level.warmupTime < 0 ) {
			if ( level.numPlayingClients == 2 ) {
				// fudge by -1 to account for extra delays
				if ( g_warmup.integer > 1 ) {
					level.warmupTime = level.time + ( g_warmup.integer - 1 ) * 1000;
				} else {
					level.warmupTime = 0;
				}

				trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) );
			}
			return;
		}

		// if the warmup time has counted down, restart
		if ( level.time > level.warmupTime ) {
			level.warmupTime += 10000;
			trap_Cvar_Set( "g_restarted", "1" );
			trap_SendConsoleCommand( EXEC_APPEND, "map_restart 0\n" );
			level.restarted = qtrue;
			return;
		}
	} else if ( g_gametype.integer != GT_SINGLE_PLAYER && level.warmupTime != 0 ) {
		int		counts[TEAM_NUM_TEAMS];
		qboolean	notEnough = qfalse;

		if ( g_gametype.integer > GT_TEAM ) {
			counts[TEAM_BLUE] = TeamCount( -1, TEAM_BLUE );
			counts[TEAM_RED] = TeamCount( -1, TEAM_RED );

			if (counts[TEAM_RED] < 1 || counts[TEAM_BLUE] < 1) {
				notEnough = qtrue;
			}
		} else if ( level.numPlayingClients < 2 ) {
			notEnough = qtrue;
		}

		if ( notEnough ) {
			if ( level.warmupTime != -1 ) {
				level.warmupTime = -1;
				trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) );
				G_LogPrintf( "Warmup:\n" );
			}
			return; // still waiting for team members
		}

		if ( level.warmupTime == 0 ) {
			return;
		}

		// if the warmup is changed at the console, restart it
		if ( g_warmup.modificationCount != level.warmupModificationCount ) {
			level.warmupModificationCount = g_warmup.modificationCount;
			level.warmupTime = -1;
		}

		// if all players have arrived, start the countdown
		if ( level.warmupTime < 0 ) {
			// fudge by -1 to account for extra delays
			level.warmupTime = level.time + ( g_warmup.integer - 1 ) * 1000;
			trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) );
			return;
		}

		// if the warmup time has counted down, restart
		if ( level.time > level.warmupTime ) {
			level.warmupTime += 10000;
			trap_Cvar_Set( "g_restarted", "1" );
			trap_SendConsoleCommand( EXEC_APPEND, "map_restart 0\n" );
			level.restarted = qtrue;
			return;
		}
	}
}
Beispiel #13
0
/*
================
LogExit

Append information about this game to the log file
================
*/
void LogExit( const char *string ) {
	int				i, numSorted;
	gclient_t		*cl;
#ifdef MISSIONPACK
	qboolean won = qtrue;
#endif
	G_LogPrintf( "Exit: %s\n", string );

	level.intermissionQueued = level.time;

	// this will keep the clients from playing any voice sounds
	// that will get cut off when the queued intermission starts
	trap_SetConfigstring( CS_INTERMISSION, "1" );

	// don't send more than 32 scores (FIXME?)
	numSorted = level.numConnectedClients;
	if ( numSorted > 32 ) {
		numSorted = 32;
	}

	if ( g_gametype.integer >= GT_TEAM ) {
		G_LogPrintf( "red:%i  blue:%i\n",
			level.teamScores[TEAM_RED], level.teamScores[TEAM_BLUE] );
	}

	for (i=0 ; i < numSorted ; i++) {
		int		ping;

		cl = &level.clients[level.sortedClients[i]];

		if ( cl->sess.sessionTeam == TEAM_SPECTATOR ) {
			continue;
		}
		if ( cl->pers.connected == CON_CONNECTING ) {
			continue;
		}

		ping = cl->ps.ping < 999 ? cl->ps.ping : 999;

		G_LogPrintf( "score: %i  ping: %i  client: %i %s\n", cl->ps.persistant[PERS_SCORE], ping, level.sortedClients[i],	cl->pers.netname );
#ifdef MISSIONPACK
		if (g_singlePlayer.integer && g_gametype.integer == GT_TOURNAMENT) {
			if (g_entities[cl - level.clients].r.svFlags & SVF_BOT && cl->ps.persistant[PERS_RANK] == 0) {
				won = qfalse;
			}
		}
#endif

	}

#ifdef MISSIONPACK
	if (g_singlePlayer.integer) {
		if (g_gametype.integer >= GT_CTF) {
			won = level.teamScores[TEAM_RED] > level.teamScores[TEAM_BLUE];
		}
		trap_SendConsoleCommand( EXEC_APPEND, (won) ? "spWin\n" : "spLose\n" );
	}
#endif


}
Beispiel #14
0
void target_play_music_use(gentity_t *self, gentity_t *other, gentity_t *activator)
{
	G_ActivateBehavior(self,BSET_USE);
	trap_SetConfigstring( CS_MUSIC, self->message );
}
Beispiel #15
0
// ************** PAUSE / UNPAUSE
//
// Pause/unpause a match.
void G_pause_cmd(gentity_t * ent, unsigned int dwCommand, qboolean fPause)
{
	char           *status[2] = { "^5UN", "^1" };

	if(team_nocontrols.integer)
	{
		G_noTeamControls(ent);
		return;
	}

	if((PAUSE_UNPAUSING >= level.match_pause && !fPause) || (PAUSE_NONE != level.match_pause && fPause))
	{
		CP(va("print \"The match is already %sPAUSED^7!\n\"", status[fPause]));
		return;
	}

	// Alias for referees
	if(ent->client->sess.referee)
	{
		G_refPause_cmd(ent, fPause);
	}
	else
	{
		int             tteam = G_teamID(ent);

		if(!G_cmdDebounce(ent, aCommandInfo[dwCommand].pszCommandName))
		{
			return;
		}

		// Trigger the auto-handling of pauses
		if(fPause)
		{
			if(0 == teamInfo[tteam].timeouts)
			{
				CP("cpm \"^3Your team has no more timeouts remaining!\n\"");
				return;
			}
			else
			{
				teamInfo[tteam].timeouts--;
				level.match_pause = tteam + 128;
				G_globalSound("sound/misc/referee.wav");
				G_spawnPrintf(DP_PAUSEINFO, level.time + 15000, NULL);
				AP(va
				   ("print \"^3Match is ^1PAUSED^3!\n^7[%s^7: - %d Timeouts Remaining]\n\"", aTeams[tteam],
					teamInfo[tteam].timeouts));
				AP(va("cp \"^3Match is ^1PAUSED^3! (%s^3)\n\"", aTeams[tteam]));	// CHRUKER: b040 - Was only sending this to the client sending the command
				level.server_settings |= CV_SVS_PAUSE;
				trap_SetConfigstring(CS_SERVERTOGGLES, va("%d", level.server_settings));
			}
		}
		else if(tteam + 128 != level.match_pause)
		{
			CP("cpm \"^3Your team didn't call the timeout!\n\"");
			return;
		}
		else
		{
			AP("print \"^3Match is ^5UNPAUSED^3 ... resuming in 10 seconds!\n\"");	// CHRUKER: b068 - Had extra linebreaks, before and after.
			level.match_pause = PAUSE_UNPAUSING;
			G_globalSound("sound/osp/prepare.wav");
			G_spawnPrintf(DP_UNPAUSING, level.time + 10, NULL);
		}
	}
}
Beispiel #16
0
/*
==================
Cmd_CallVote_f
==================
*/
void Cmd_CallVote_f( gentity_t *ent ) {
	char*	c;
	int		i;
	char	arg1[MAX_STRING_TOKENS];
	char	arg2[MAX_STRING_TOKENS];

	if ( !g_allowVote.integer ) {
		trap_SendServerCommand( ent-g_entities, "print \"Voting not allowed here.\n\"" );
		return;
	}

	if ( level.voteTime ) {
		trap_SendServerCommand( ent-g_entities, "print \"A vote is already in progress.\n\"" );
		return;
	}
	if ( ent->client->pers.voteCount >= MAX_VOTE_COUNT ) {
		trap_SendServerCommand( ent-g_entities, "print \"You have called the maximum number of votes.\n\"" );
		return;
	}
	if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
		trap_SendServerCommand( ent-g_entities, "print \"Not allowed to call a vote as spectator.\n\"" );
		return;
	}

	// make sure it is a valid command to vote on
	trap_Argv( 1, arg1, sizeof( arg1 ) );
	trap_Argv( 2, arg2, sizeof( arg2 ) );

	// check for command separators in arg2
	for( c = arg2; *c; ++c) {
		switch(*c) {
			case '\n':
			case '\r':
			case ';':
				trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" );
				return;
			break;
		}
	}

	if ( !Q_stricmp( arg1, "map_restart" ) ) {
	} else if ( !Q_stricmp( arg1, "nextmap" ) ) {
	} else if ( !Q_stricmp( arg1, "map" ) ) {
	} else if ( !Q_stricmp( arg1, "g_gametype" ) ) {
	} else if ( !Q_stricmp( arg1, "kick" ) ) {
	} else if ( !Q_stricmp( arg1, "clientkick" ) ) {
	} else if ( !Q_stricmp( arg1, "g_doWarmup" ) ) {
	} else if ( !Q_stricmp( arg1, "timelimit" ) ) {
	} else if ( !Q_stricmp( arg1, "fraglimit" ) ) {
	} else {
		trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" );
		trap_SendServerCommand( ent-g_entities, "print \"Vote commands are: map_restart, nextmap, map <mapname>, g_gametype <n>, kick <player>, clientkick <clientnum>, g_doWarmup, timelimit <time>, fraglimit <frags>.\n\"" );
		return;
	}

	// if there is still a vote to be executed
	if ( level.voteExecuteTime ) {
		level.voteExecuteTime = 0;
		trap_SendConsoleCommand( EXEC_APPEND, va("%s\n", level.voteString ) );
	}

	// special case for g_gametype, check for bad values
	if ( !Q_stricmp( arg1, "g_gametype" ) ) {
		i = atoi( arg2 );
		if( i == GT_SINGLE_PLAYER || i < GT_FFA || i >= GT_MAX_GAME_TYPE) {
			trap_SendServerCommand( ent-g_entities, "print \"Invalid gametype.\n\"" );
			return;
		}

		Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %d", arg1, i );
		Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s %s", arg1, gameNames[i] );
	} else if ( !Q_stricmp( arg1, "map" ) ) {
		// special case for map changes, we want to reset the nextmap setting
		// this allows a player to change maps, but not upset the map rotation
		char	s[MAX_STRING_CHARS];

		trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) );
		if (*s) {
			Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s; set nextmap \"%s\"", arg1, arg2, s );
		} else {
			Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 );
		}
		Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
	} else if ( !Q_stricmp( arg1, "nextmap" ) ) {
		char	s[MAX_STRING_CHARS];

		trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) );
		if (!*s) {
			trap_SendServerCommand( ent-g_entities, "print \"nextmap not set.\n\"" );
			return;
		}
		Com_sprintf( level.voteString, sizeof( level.voteString ), "vstr nextmap");
		Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
	} else {
		Com_sprintf( level.voteString, sizeof( level.voteString ), "%s \"%s\"", arg1, arg2 );
		Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
	}

	trap_SendServerCommand( -1, va("print \"%s called a vote.\n\"", ent->client->pers.netname ) );

	// start the voting, the caller autoamtically votes yes
	level.voteTime = level.time;
	level.voteYes = 1;
	level.voteNo = 0;

	for ( i = 0 ; i < level.maxclients ; i++ ) {
		level.clients[i].ps.eFlags &= ~EF_VOTED;
	}
	ent->client->ps.eFlags |= EF_VOTED;

	trap_SetConfigstring( CS_VOTE_TIME, va("%i", level.voteTime ) );
	trap_SetConfigstring( CS_VOTE_STRING, level.voteDisplayString );	
	trap_SetConfigstring( CS_VOTE_YES, va("%i", level.voteYes ) );
	trap_SetConfigstring( CS_VOTE_NO, va("%i", level.voteNo ) );	
}
Beispiel #17
0
void G_configLoadAndSet(const char *name)
{
	pc_token_t token;
	int        handle;
	config_t   *config;
	qboolean   parseOK = qtrue;

	handle = trap_PC_LoadSource(va("configs/%s.config", name));

	if (!handle)
	{
		Com_Printf(S_COLOR_RED "ERROR: File not found: %s\n", name);
		return;
	}

	memset(&level.config, 0, sizeof(config_t));

	G_wipeCvars();

	config = &level.config;

	config->publicConfig = qfalse;

	while (1)
	{
		if (!trap_PC_ReadToken(handle, &token))
		{
			break;
		}

		if (!Q_stricmp(token.string, "configname"))
		{
			if (!PC_String_ParseNoAlloc(handle, config->name, sizeof(config->name)))
			{
				G_Printf("expected config name\n");
				parseOK = qfalse;
				break;
			}
			G_Printf("Config name is: %s\n", config->name);
		}
		else if (!Q_stricmp(token.string, "version"))
		{
			if (!PC_String_ParseNoAlloc(handle, config->version, sizeof(config->name)))
			{
				G_Printf("expected config version\n");
				parseOK = qfalse;
				break;
			}
		}
		else if (!Q_stricmp(token.string, "init"))
		{
			if (!G_ParseSettings(handle, qtrue, config))
			{
				G_Printf("Reading settings failed\n");
				parseOK = qfalse;
				break;
			}
		}
		else if (!Q_stricmp(token.string, "map"))
		{
			if (!G_ParseMapSettings(handle, config))
			{
				G_Printf("Reading map settings failed\n");
				parseOK = qfalse;
				break;
			}
		}
		else if (!Q_stricmp(token.string, "signature"))
		{
			if (!PC_String_ParseNoAlloc(handle, config->signature, sizeof(config->signature)))
			{
				G_Printf("expected config signature\n");
				parseOK = qfalse;
				break;
			}
		}
		else if (!Q_stricmp(token.string, "public"))
		{
			config->publicConfig = qtrue;
		}
		else
		{
			G_Printf("unknown token %s\n", token.string);
			parseOK = qfalse;
			break;
		}
	}
	trap_PC_FreeSource(handle);

	if (parseOK)
	{
		trap_SetConfigstring(CS_CONFIGNAME, config->name);

		if (level.config.version[0] && level.config.name[0])
		{
			trap_SendServerCommand(-1, va("cp \"^7Config '%s^7' version '%s'^7 loaded\"", level.config.name, level.config.version));
		}
		else if (level.config.name[0])
		{
			trap_SendServerCommand(-1, va("cp \"^7Config '%s^7' loaded\"", level.config.name));
		}
	}
	else
	{
		trap_SetConfigstring(CS_CONFIGNAME, "");
		trap_SendServerCommand(-1, va("cp \"^7Config '%s^7' ^1FAILED ^7to load\"", name));
	}

	G_UpdateCvars();
}
Beispiel #18
0
/*
==================
Cmd_CallTeamVote_f
==================
*/
void Cmd_CallTeamVote_f( gentity_t *ent ) {
	int		i, team, cs_offset;
	char	arg1[MAX_STRING_TOKENS];
	char	arg2[MAX_STRING_TOKENS];

	team = ent->client->sess.sessionTeam;
	if ( team == TEAM_RED )
		cs_offset = 0;
	else if ( team == TEAM_BLUE )
		cs_offset = 1;
	else
		return;

	if ( !g_allowVote.integer ) {
		trap_SendServerCommand( ent-g_entities, "print \"Voting not allowed here.\n\"" );
		return;
	}

	if ( level.teamVoteTime[cs_offset] ) {
		trap_SendServerCommand( ent-g_entities, "print \"A team vote is already in progress.\n\"" );
		return;
	}
	if ( ent->client->pers.teamVoteCount >= MAX_VOTE_COUNT ) {
		trap_SendServerCommand( ent-g_entities, "print \"You have called the maximum number of team votes.\n\"" );
		return;
	}
	if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
		trap_SendServerCommand( ent-g_entities, "print \"Not allowed to call a vote as spectator.\n\"" );
		return;
	}

	// make sure it is a valid command to vote on
	trap_Argv( 1, arg1, sizeof( arg1 ) );
	arg2[0] = '\0';
	for ( i = 2; i < trap_Argc(); i++ ) {
		if (i > 2)
			strcat(arg2, " ");
		trap_Argv( i, &arg2[strlen(arg2)], sizeof( arg2 ) - strlen(arg2) );
	}

	if( strchr( arg1, ';' ) || strchr( arg2, ';' ) ) {
		trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" );
		return;
	}

	if ( !Q_stricmp( arg1, "leader" ) ) {
		char netname[MAX_NETNAME], leader[MAX_NETNAME];

		if ( !arg2[0] ) {
			i = ent->client->ps.clientNum;
		}
		else {
			// numeric values are just slot numbers
			for (i = 0; i < 3; i++) {
				if ( !arg2[i] || arg2[i] < '0' || arg2[i] > '9' )
					break;
			}
			if ( i >= 3 || !arg2[i]) {
				i = atoi( arg2 );
				if ( i < 0 || i >= level.maxclients ) {
					trap_SendServerCommand( ent-g_entities, va("print \"Bad client slot: %i\n\"", i) );
					return;
				}

				if ( !g_entities[i].inuse ) {
					trap_SendServerCommand( ent-g_entities, va("print \"Client %i is not active\n\"", i) );
					return;
				}
			}
			else {
				Q_strncpyz(leader, arg2, sizeof(leader));
				Q_CleanStr(leader);
				for ( i = 0 ; i < level.maxclients ; i++ ) {
					if ( level.clients[i].pers.connected == CON_DISCONNECTED )
						continue;
					if (level.clients[i].sess.sessionTeam != team)
						continue;
					Q_strncpyz(netname, level.clients[i].pers.netname, sizeof(netname));
					Q_CleanStr(netname);
					if ( !Q_stricmp(netname, leader) ) {
						break;
					}
				}
				if ( i >= level.maxclients ) {
					trap_SendServerCommand( ent-g_entities, va("print \"%s is not a valid player on your team.\n\"", arg2) );
					return;
				}
			}
		}
		Com_sprintf(arg2, sizeof(arg2), "%d", i);
	} else {
		trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" );
		trap_SendServerCommand( ent-g_entities, "print \"Team vote commands are: leader <player>.\n\"" );
		return;
	}

	Com_sprintf( level.teamVoteString[cs_offset], sizeof( level.teamVoteString[cs_offset] ), "%s %s", arg1, arg2 );

	for ( i = 0 ; i < level.maxclients ; i++ ) {
		if ( level.clients[i].pers.connected == CON_DISCONNECTED )
			continue;
		if (level.clients[i].sess.sessionTeam == team)
			trap_SendServerCommand( i, va("print \"%s called a team vote.\n\"", ent->client->pers.netname ) );
	}

	// start the voting, the caller autoamtically votes yes
	level.teamVoteTime[cs_offset] = level.time;
	level.teamVoteYes[cs_offset] = 1;
	level.teamVoteNo[cs_offset] = 0;

	for ( i = 0 ; i < level.maxclients ; i++ ) {
		if (level.clients[i].sess.sessionTeam == team)
			level.clients[i].ps.eFlags &= ~EF_TEAMVOTED;
	}
	ent->client->ps.eFlags |= EF_TEAMVOTED;

	trap_SetConfigstring( CS_TEAMVOTE_TIME + cs_offset, va("%i", level.teamVoteTime[cs_offset] ) );
	trap_SetConfigstring( CS_TEAMVOTE_STRING + cs_offset, level.teamVoteString[cs_offset] );
	trap_SetConfigstring( CS_TEAMVOTE_YES + cs_offset, va("%i", level.teamVoteYes[cs_offset] ) );
	trap_SetConfigstring( CS_TEAMVOTE_NO + cs_offset, va("%i", level.teamVoteNo[cs_offset] ) );
}
Beispiel #19
0
/*QUAKED script_mover (0.5 0.25 1.0) ? TRIGGERSPAWN SOLID EXPLOSIVEDAMAGEONLY RESURECTABLE COMPASS ALLIED AXIS MOUNTED_GUN
Scripted brush entity. A simplified means of moving brushes around based on events.

"modelscale" - Scale multiplier (defaults to 1, and scales uniformly)
"modelscale_vec" - Set scale per-axis.  Overrides "modelscale", so if you have both the "modelscale" is ignored
"model2" optional md3 to draw over the solid clip brush
"scriptname" name used for scripting purposes (like aiName in AI scripting)
"health" optionally make this entity damagable
"description" used with health, if the entity is damagable, it draws a healthbar with this description above it.
*/
void SP_script_mover(gentity_t *ent) {

	float	scale[3] = {1,1,1};
	vec3_t	scalevec;
	char	tagname[MAX_QPATH];
	char*	modelname;
	char*	tagent;
	char	cs[MAX_INFO_STRING];
	char*	s;
	
	if (!ent->model)
		G_Error("script_mover must have a \"model\"\n" );
	if (!ent->scriptName)
		G_Error("script_mover must have a \"scriptname\"\n" );

	ent->blocked = script_mover_blocked;

	// first position at start
	VectorCopy( ent->s.origin, ent->pos1 );

//	VectorCopy( ent->r.currentOrigin, ent->pos1 );
	VectorCopy( ent->pos1, ent->pos2 );	// don't go anywhere just yet

	trap_SetBrushModel( ent, ent->model );

	InitMover( ent );
	ent->reached = NULL;
	ent->s.animMovetype = 0;

	ent->s.density = 0;

	if (ent->spawnflags & 256) {
		ent->s.density |= 2;
	}

	if (ent->spawnflags & 8) {
		ent->use = script_mover_use;
	}

	if (ent->spawnflags & 16) {
		ent->s.time2 = 1;
	} else {
		ent->s.time2 = 0;
	}

	if (ent->spawnflags & 32) {
		ent->s.teamNum = TEAM_ALLIES;
	} else if (ent->spawnflags & 64) {
		ent->s.teamNum = TEAM_AXIS;
	} else {
		ent->s.teamNum = TEAM_FREE;
	}

	if (ent->spawnflags & 1) {
		ent->use = script_mover_use;
		trap_UnlinkEntity(ent);	// make sure it's not visible
		return;
	}

 	G_SetAngle (ent, ent->s.angles);

	G_SpawnInt( "health", "0", &ent->health );
	if(ent->health) {
		ent->takedamage = qtrue;
		ent->count = ent->health;

		// client needs to know about it as well
		ent->s.effect1Time = ent->count;
		ent->s.dl_intensity = 255;

		if( G_SpawnString( "description", "", &s ) ) {
			trap_GetConfigstring( CS_SCRIPT_MOVER_NAMES, cs, sizeof(cs) );
			Info_SetValueForKey( cs, va("%i",ent-g_entities), s );
			trap_SetConfigstring( CS_SCRIPT_MOVER_NAMES, cs );
		}
	} else {
		ent->count = 0;
	}

	ent->die = script_mover_die;

	// look for general scaling
	if(G_SpawnFloat( "modelscale", "1", &scale[0])) {
		scale[2] = scale[1] = scale[0];
	}

	if(G_SpawnString( "model2", "", &modelname ) ) {
		COM_StripExtension( modelname, tagname );
		Q_strcat( tagname, MAX_QPATH, ".tag" );

		ent->tagNumber = trap_LoadTag( tagname );

/*		if( !(ent->tagNumber = trap_LoadTag( tagname )) ) {
			Com_Error( ERR_DROP, "Failed to load Tag File (%s)\n", tagname );
		}*/
	}

	// look for axis specific scaling
	if(G_SpawnVector("modelscale_vec", "1 1 1", &scalevec[0])) {
		VectorCopy(scalevec, scale);
	}

	if(scale[0] != 1 || scale[1] != 1 || scale[2] != 1) {
		ent->s.density |= 1;
		// scale is stored in 'angles2'
		VectorCopy(scale, ent->s.angles2);
	}

	if (ent->spawnflags & 128) {
		ent->s.density |= 4;
		ent->waterlevel = 0;
		
		if( G_SpawnString( "gun", "", &modelname ) ) {
			if( !Q_stricmp( modelname, "browning" ) ) {
				ent->s.density |= 8;
			}
		}

		G_SpawnString("tagent", "", &tagent);
		Q_strncpyz( ent->tagBuffer, tagent, 16 );
		ent->s.powerups = -1;
	}

	ent->think = script_mover_spawn;
	ent->nextthink = level.time + FRAMETIME;
}
Beispiel #20
0
/*QUAKED worldspawn (0 0 0) ?
Used for game-world global options.
Every map should have exactly one.

=== KEYS ===
; message: Text to print during connection process. Used for the name of level.
; music: path/name of looping .wav file used for level's music (eg. music/sonic5.wav).
; gravity: level gravity [g_gravity (800)]

; humanBuildPoints: maximum amount of power the humans can use. [g_humanBuildPoints]
; humanRepeaterBuildPoints: maximum amount of power the humans can use around each repeater. [g_humanRepeaterBuildPoints]
; alienBuildPoints: maximum amount of sentience available to the overmind. [g_alienBuildPoints]

; disabledEquipment: A comma delimited list of human weapons or upgrades to disable for this map. [g_disabledEquipment ()]
; disabledClasses: A comma delimited list of alien classes to disable for this map. [g_disabledClasses ()]
; disabledBuildables: A comma delimited list of buildables to disable for this map. [g_disabledBuildables ()]
*/
void SP_worldspawn()
{
	char *s;
	float reverbIntensity = 1.0f;

	G_SpawnString( "classname", "", &s );

	if ( Q_stricmp( s, S_WORLDSPAWN ) )
	{
		Com_Error(errorParm_t::ERR_DROP,  "SP_worldspawn: The first entry in the spawn string isn't of expected type '" S_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

	if(G_SpawnString( "gradingTexture", "", &s ))
		trap_SetConfigstring( CS_GRADING_TEXTURES, va( "%i %f %s", -1, 0.0f, s ) );

	if(G_SpawnString( "colorGrade", "", &s )) {
		Log::Warn("\"colorGrade\" deprecated. Please use \"gradingTexture\"");
		trap_SetConfigstring( CS_GRADING_TEXTURES, va( "%i %f %s", -1, 0.0f, s ) );
	}

	if(G_SpawnString( "reverbIntensity", "", &s ))
		sscanf( s, "%f", &reverbIntensity );
	if(G_SpawnString( "reverbEffect", "", &s ))
		trap_SetConfigstring( CS_REVERB_EFFECTS, va( "%i %f %s %f", 0, 0.0f, s, Com_Clamp( 0.0f, 2.0f, reverbIntensity ) ) );

	trap_SetConfigstring( CS_MOTD, g_motd.string );  // message of the day

	G_SpawnStringIntoCVarIfSet( "gravity", "g_gravity" );

	G_SpawnStringIntoCVarIfSet( "humanBuildPoints", "g_humanBuildPoints" );
	G_SpawnStringIntoCVarIfSet( "humanRepeaterBuildPoints", "g_humanRepeaterBuildPoints" );
	G_SpawnStringIntoCVarIfSet( "alienBuildPoints", "g_alienBuildPoints" );

	G_SpawnStringIntoCVar( "disabledEquipment", "g_disabledEquipment" );
	G_SpawnStringIntoCVar( "disabledClasses", "g_disabledClasses" );
	G_SpawnStringIntoCVar( "disabledBuildables", "g_disabledBuildables" );

	g_entities[ ENTITYNUM_WORLD ].s.number = ENTITYNUM_WORLD;
	g_entities[ ENTITYNUM_WORLD ].r.ownerNum = ENTITYNUM_NONE;
	g_entities[ ENTITYNUM_WORLD ].classname = S_WORLDSPAWN;

	g_entities[ ENTITYNUM_NONE ].s.number = ENTITYNUM_NONE;
	g_entities[ ENTITYNUM_NONE ].r.ownerNum = ENTITYNUM_NONE;
	g_entities[ ENTITYNUM_NONE ].classname = "nothing";

	// see if we want a warmup time
	trap_SetConfigstring( CS_WARMUP, "-1" );

	if ( g_doWarmup.integer )
	{
		level.warmupTime = level.matchTime + ( g_warmup.integer * 1000 );
		trap_SetConfigstring( CS_WARMUP, va( "%i", level.warmupTime ) );
		G_LogPrintf( "Warmup: %i\n", g_warmup.integer );
	}

	level.timelimit = g_timelimit.integer;
}
Beispiel #21
0
/*
===========
ClientUserInfoChanged

Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
void ClientUserinfoChanged( int clientNum ) {
	gentity_t *ent;
	int		teamTask, teamLeader, team, health;
	char	*s;
	char	model[MAX_QPATH];
	char	headModel[MAX_QPATH];
	char	oldname[MAX_STRING_CHARS];
	gclient_t	*client;
	char	c1[MAX_INFO_STRING];
	char	c2[MAX_INFO_STRING];
	char	redTeam[MAX_INFO_STRING];
	char	blueTeam[MAX_INFO_STRING];
	char	userinfo[MAX_INFO_STRING];

	ent = g_entities + clientNum;
	client = ent->client;

	trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );

	// check for malformed or illegal info strings
	if ( !Info_Validate(userinfo) ) {
		strcpy (userinfo, "\\name\\badinfo");
	}

	// check for local client
	s = Info_ValueForKey( userinfo, "ip" );
	if ( !strcmp( s, "localhost" ) ) {
		client->pers.localClient = qtrue;
	}

	// check the item prediction
	s = Info_ValueForKey( userinfo, "cg_predictItems" );
	if ( !atoi( s ) ) {
		client->pers.predictItemPickup = qfalse;
	} else {
		client->pers.predictItemPickup = qtrue;
	}

	// set name
	Q_strncpyz ( oldname, client->pers.netname, sizeof( oldname ) );
	s = Info_ValueForKey (userinfo, "name");
	ClientCleanName( s, client->pers.netname, sizeof(client->pers.netname) );

	if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
		if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
			Q_strncpyz( client->pers.netname, "scoreboard", sizeof(client->pers.netname) );
		}
	}

	if ( client->pers.connected == CON_CONNECTED ) {
		if ( strcmp( oldname, client->pers.netname ) ) {
			trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " renamed to %s\n\"", oldname, 
				client->pers.netname) );
		}
	}

	// set max health
#ifdef MISSIONPACK
	if (client->ps.powerups[PW_GUARD]) {
		client->pers.maxHealth = 200;
	} else {
		health = atoi( Info_ValueForKey( userinfo, "handicap" ) );
		client->pers.maxHealth = health;
		if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
			client->pers.maxHealth = 100;
		}
	}
#else
	health = atoi( Info_ValueForKey( userinfo, "handicap" ) );
	client->pers.maxHealth = health;
	if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
		client->pers.maxHealth = 100;
	}
#endif
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;

	// set model
	if( g_gametype.integer >= GT_TEAM ) {
		Q_strncpyz( model, Info_ValueForKey (userinfo, "team_model"), sizeof( model ) );
		Q_strncpyz( headModel, Info_ValueForKey (userinfo, "team_headmodel"), sizeof( headModel ) );
	} else {
		Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) );
		Q_strncpyz( headModel, Info_ValueForKey (userinfo, "headmodel"), sizeof( headModel ) );
	}

	// bots set their team a few frames later
	if (g_gametype.integer >= GT_TEAM && g_entities[clientNum].r.svFlags & SVF_BOT) {
		s = Info_ValueForKey( userinfo, "team" );
		if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) {
			team = TEAM_RED;
		} else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) {
			team = TEAM_BLUE;
		} else {
			// pick the team with the least number of players
			team = PickTeam( clientNum );
		}
	}
	else {
		team = client->sess.sessionTeam;
	}

/*	NOTE: all client side now

	// team
	switch( team ) {
	case TEAM_RED:
		ForceClientSkin(client, model, "red");
//		ForceClientSkin(client, headModel, "red");
		break;
	case TEAM_BLUE:
		ForceClientSkin(client, model, "blue");
//		ForceClientSkin(client, headModel, "blue");
		break;
	}
	// don't ever use a default skin in teamplay, it would just waste memory
	// however bots will always join a team but they spawn in as spectator
	if ( g_gametype.integer >= GT_TEAM && team == TEAM_SPECTATOR) {
		ForceClientSkin(client, model, "red");
//		ForceClientSkin(client, headModel, "red");
	}
*/

#ifdef MISSIONPACK
	if (g_gametype.integer >= GT_TEAM) {
		client->pers.teamInfo = qtrue;
	} else {
		s = Info_ValueForKey( userinfo, "teamoverlay" );
		if ( ! *s || atoi( s ) != 0 ) {
			client->pers.teamInfo = qtrue;
		} else {
			client->pers.teamInfo = qfalse;
		}
	}
#else
	// teamInfo
	s = Info_ValueForKey( userinfo, "teamoverlay" );
	if ( ! *s || atoi( s ) != 0 ) {
		client->pers.teamInfo = qtrue;
	} else {
		client->pers.teamInfo = qfalse;
	}
#endif
	/*
	s = Info_ValueForKey( userinfo, "cg_pmove_fixed" );
	if ( !*s || atoi( s ) == 0 ) {
		client->pers.pmoveFixed = qfalse;
	}
	else {
		client->pers.pmoveFixed = qtrue;
	}
	*/

	// team task (0 = none, 1 = offence, 2 = defence)
	teamTask = atoi(Info_ValueForKey(userinfo, "teamtask"));
	// team Leader (1 = leader, 0 is normal player)
	teamLeader = client->sess.teamLeader;

	// colors
	strcpy(c1, Info_ValueForKey( userinfo, "color1" ));
	strcpy(c2, Info_ValueForKey( userinfo, "color2" ));

	strcpy(redTeam, Info_ValueForKey( userinfo, "g_redteam" ));
	strcpy(blueTeam, Info_ValueForKey( userinfo, "g_blueteam" ));

	// send over a subset of the userinfo keys so other clients can
	// print scoreboards, display models, and play custom sounds
	if ( ent->r.svFlags & SVF_BOT ) {
		s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d",
			client->pers.netname, team, model, headModel, c1, c2, 
			client->pers.maxHealth, client->sess.wins, client->sess.losses,
			Info_ValueForKey( userinfo, "skill" ), teamTask, teamLeader );
	} else {
		s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\g_redteam\\%s\\g_blueteam\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d",
			client->pers.netname, client->sess.sessionTeam, model, headModel, redTeam, blueTeam, c1, c2, 
			client->pers.maxHealth, client->sess.wins, client->sess.losses, teamTask, teamLeader);
	}

	trap_SetConfigstring( CS_PLAYERS+clientNum, s );

	// this is not the userinfo, more like the configstring actually
	G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, s );
}
Beispiel #22
0
/**
 * @brief - send name, team and value when there is a winner - else empty string
 * and TEAM_FREE = 0 (client structure is only used for awards!)
 * - connectedClients have a team but keep the check for TEAM_FREE
 * ... we'll never know for sure, connectedClients are determined in CalculateRanks
 */
void G_BuildEndgameStats(void)
{
	char      buffer[1024];
	int       i, j;
	gclient_t *best         = NULL;
	int       bestClientNum = -1;
	float     mapXP, bestMapXP = 0.f;

	G_CalcClientAccuracies();

	for (i = 0; i < level.numConnectedClients; i++)
	{
		level.clients[i].hasaward = qfalse;
	}

	*buffer = '\0';

	// highest ranking officer - check rank, then medals and XP
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (!best || cl->sess.rank > best->sess.rank)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
		else if (cl->sess.rank == best->sess.rank && cl->medals > best->medals)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
		else if (cl->sess.rank == best->sess.rank && cl->medals == best->medals && cl->ps.persistant[PERS_SCORE] > best->ps.persistant[PERS_SCORE])
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i 0 %i ", bestClientNum, best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

#ifdef FEATURE_RATING
	// highest rated player - check skill rating
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->sess.mu - 3 * cl->sess.sigma <= 0)
		{
			continue;
		}

		if (!best || (cl->sess.mu - 3 * cl->sess.sigma) > (best->sess.mu - 3 * best->sess.sigma))
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %.2f %i ", bestClientNum, MIN(best->sess.mu - 3 * best->sess.sigma, 50.f), best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;
#endif

	// highest experience points - check XP (total in campaign, otherwise this map only then total XP)
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->ps.persistant[PERS_SCORE] <= 0)
		{
			continue;
		}

		if (g_gametype.integer == GT_WOLF_CAMPAIGN)
		{
			if (!best || cl->ps.persistant[PERS_SCORE] > best->ps.persistant[PERS_SCORE])
			{
				best          = cl;
				bestClientNum = level.sortedClients[i];
			}
		}
		else
		{
			mapXP = 0.f;

			for (j = 0; j < SK_NUM_SKILLS; j++)
			{
				mapXP += (cl->sess.skillpoints[j] - cl->sess.startskillpoints[j]);
			}

			if (!best || mapXP > bestMapXP)
			{
				best          = cl;
				bestMapXP     = mapXP;
				bestClientNum = level.sortedClients[i];
			}
			else if (mapXP == bestMapXP && cl->ps.persistant[PERS_SCORE] > best->ps.persistant[PERS_SCORE])
			{
				best          = cl;
				bestMapXP     = mapXP;
				bestClientNum = level.sortedClients[i];
			}
		}
	}

	if (best)
	{
		best->hasaward = qtrue;

		if (g_gametype.integer == GT_WOLF_CAMPAIGN)
		{
			Q_strcat(buffer, 1024, va("%i %i %i ", bestClientNum, best->ps.persistant[PERS_SCORE], best->sess.sessionTeam));
		}
		else
		{
			Q_strcat(buffer, 1024, va("%i %i %i ", bestClientNum, (int)bestMapXP, best->sess.sessionTeam));
		}
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

	// most highly decorated - check medals then XP
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->medals <= 0)
		{
			continue;
		}

		if (!best || cl->medals > best->medals)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
		else if (cl->medals == best->medals && cl->ps.persistant[PERS_SCORE] > best->ps.persistant[PERS_SCORE])
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %i %i ", bestClientNum, best->medals, best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	// highest fragger - check kills, then damage given
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->sess.kills <= 0)
		{
			continue;
		}

		if (!best || cl->sess.kills > best->sess.kills)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
		else if (cl->sess.kills == best->sess.kills && cl->sess.damage_given > best->sess.damage_given)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %i %i ", bestClientNum, best->sess.kills, best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

	// highest skills - check skills points (this map only, min lvl 1)
	for (i = 0; i < SK_NUM_SKILLS; i++)
	{
		best = NULL;

		for (j = 0; j < level.numConnectedClients; j++)
		{
			gclient_t *cl = &level.clients[level.sortedClients[j]];

			if (cl->sess.sessionTeam == TEAM_FREE)
			{
				continue;
			}

			if ((cl->sess.skillpoints[i] - cl->sess.startskillpoints[i]) <= 0)
			{
				continue;
			}

			if (cl->sess.skill[i] < 1)
			{
				continue;
			}

			if (!best || (cl->sess.skillpoints[i] - cl->sess.startskillpoints[i]) > (best->sess.skillpoints[i] - best->sess.startskillpoints[i]))
			{
				best          = cl;
				bestClientNum = level.sortedClients[j];
			}
		}

		if (best)
		{
			best->hasaward = qtrue;
			Q_strcat(buffer, 1024, va("%i %i %i ", bestClientNum, (int)(best->sess.skillpoints[i] - best->sess.startskillpoints[i]), best->sess.sessionTeam));
		}
		else
		{
			Q_strcat(buffer, 1024, "-1 0 0 ");
		}
	}

	best = NULL;

	// highest accuracy
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->acc <= 0)
		{
			continue;
		}

		if (!best || cl->acc > best->acc)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %.2f %i ", bestClientNum, best->acc < 100.f ? (double)best->acc : 100., best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

	// highest HS percentage
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->hspct <= 0)
		{
			continue;
		}

		if (!best || cl->hspct > best->hspct)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %.2f %i ", bestClientNum, best->hspct < 100.f ? (double)best->hspct : 100., best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

	// best survivor - check time played percentage (min 50% of map duration)
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if ((level.time - cl->pers.enterTime) / (float)(level.time - level.intermissiontime) < 0.5f)
		{
			continue;
		}

		if (!best || (cl->sess.time_played / (float)(level.time - cl->pers.enterTime)) > (best->sess.time_played / (float)(level.time - best->pers.enterTime)))
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %.2f %i ", bestClientNum, MIN(100. * best->sess.time_played / (double)(level.time - best->pers.enterTime), 100.), best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

	// most gibs - check gibs, then damage given
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->sess.gibs <= 0)
		{
			continue;
		}

		if (!best || cl->sess.gibs > best->sess.gibs)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
		else if (cl->sess.gibs == best->sess.gibs && cl->sess.damage_given > best->sess.damage_given)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %i %i ", bestClientNum, best->sess.gibs, best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

	// most selfkill - check selfkills, then deaths
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->sess.self_kills <= 0)
		{
			continue;
		}

		if (!best || cl->sess.self_kills > best->sess.self_kills)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
		else if (cl->sess.self_kills == best->sess.self_kills && cl->sess.deaths > best->sess.deaths)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %i %i ", bestClientNum, best->sess.self_kills, best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

	// most deaths - check deaths, then damage received
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (cl->sess.deaths <= 0)
		{
			continue;
		}

		if (!best || cl->sess.deaths > best->sess.deaths)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
		else if (cl->sess.deaths == best->sess.deaths && cl->sess.damage_received > best->sess.damage_received)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
		Q_strcat(buffer, 1024, va("%i %i %i ", bestClientNum, best->sess.deaths, best->sess.sessionTeam));
	}
	else
	{
		Q_strcat(buffer, 1024, "-1 0 0 ");
	}

	best = NULL;

	// I ain't got no friends award - check team kills, then team damage given (min 5 tks)
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (!best || cl->sess.team_kills > best->sess.team_kills)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
		else if (cl->sess.team_kills == best->sess.team_kills && cl->sess.team_damage_given > best->sess.team_damage_given)
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		best->hasaward = qtrue;
	}
	Q_strcat(buffer, 1024, va("%i %i %i ", best && best->sess.team_kills >= 5 ? bestClientNum : -1, best ? best->sess.team_kills : 0, best && best->sess.team_kills >= 5 ? best->sess.sessionTeam : TEAM_FREE));

	best = NULL;

	// welcome newbie! award - dont get this if any other award given or > 100 xp (this map)
	for (i = 0; i < level.numConnectedClients; i++)
	{
		gclient_t *cl = &level.clients[level.sortedClients[i]];

		if (cl->sess.sessionTeam == TEAM_FREE)
		{
			continue;
		}

		if (!best || (cl->ps.persistant[PERS_SCORE] / (float)(level.time - cl->pers.enterTime)) > (best->ps.persistant[PERS_SCORE] / (float)(level.time - best->pers.enterTime)))
		{
			best          = cl;
			bestClientNum = level.sortedClients[i];
		}
	}

	if (best)
	{
		if ((best->sess.startxptotal - best->ps.persistant[PERS_SCORE]) >= 100 || best->medals || best->hasaward)
		{
			best = NULL;
		}
	}
	Q_strcat(buffer, 1024, va("%i %i %i ", best ? bestClientNum : -1, best ? best->ps.persistant[PERS_SCORE] : 0, best ? best->sess.sessionTeam : TEAM_FREE));

	trap_SetConfigstring(CS_ENDGAME_STATS, buffer);
}
Beispiel #23
0
void SP_trigger_objective_info(gentity_t *ent)
{
	char *scorestring;
	char *customimage;
	int  cix, cia, objflags;

	if (!ent->track)
	{
		G_Error("'trigger_objective_info' does not have a 'track' \n");
	}

	if (ent->spawnflags & MESSAGE_OVERRIDE)
	{
		if (!ent->spawnitem)
		{
			G_Error("'trigger_objective_info' has override flag set but no override text\n");
		}
	}

	// for specifying which commandmap objectives this entity "belongs" to
	G_SpawnInt("objflags", "0", &objflags);

	if (G_SpawnString("customimage", "", &customimage))
	{
		cix = cia = G_ShaderIndex(customimage);
	}
	else
	{
		if (G_SpawnString("customaxisimage", "", &customimage))
		{
			cix = G_ShaderIndex(customimage);
		}
		else
		{
			cix = 0;
		}

		if (G_SpawnString("customalliesimage", "", &customimage))
		{
			cia = G_ShaderIndex(customimage);
		}
		else if (G_SpawnString("customalliedimage", "", &customimage))
		{
			cia = G_ShaderIndex(customimage);
		}
		else
		{
			cia = 0;
		}
	}

	G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "e", va("%i", (int)(ent - g_entities)));
	G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "o", va("%i", objflags));
	if (cix)
	{
		G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "cix", va("%i", cix));
	}
	if (cia)
	{
		G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "cia", va("%i", cia));
	}
	G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "s", va("%i", ent->spawnflags));
	G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "n", ent->message ? ent->message : "");

	if (level.numOidTriggers >= MAX_OID_TRIGGERS)
	{
		G_Error("Exceeded maximum number of 'trigger_objective_info' entities\n");
	}

	// if this trigger has a "score" field set, then blowing up an objective
	// inside of this field will add "score" to the right player team.  storing this
	// in ent->accuracy since that's unused.
	G_SpawnString("score", "0", &scorestring);
	ent->accuracy = atof(scorestring);

	trap_SetConfigstring(CS_OID_TRIGGERS + level.numOidTriggers, ent->track);

	InitTrigger(ent);

	if (ent->s.origin[0] || ent->s.origin[1] || ent->s.origin[2])
	{
		G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "x", va("%i", (int)ent->s.origin[0]));
		G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "y", va("%i", (int)ent->s.origin[1]));
		G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "z", va("%i", (int)ent->s.origin[2]));
	}
	else
	{
		vec3_t mid;

		VectorAdd(ent->r.absmin, ent->r.absmax, mid);
		VectorScale(mid, 0.5f, mid);

		G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "x", va("%i", (int)mid[0]));
		G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "y", va("%i", (int)mid[1]));
		G_SetConfigStringValue(CS_OID_DATA + level.numOidTriggers, "z", va("%i", (int)mid[2]));
	}

	ent->s.teamNum = level.numOidTriggers++;

	// unlike other triggers, we need to send this one to the client
	ent->r.svFlags &= ~SVF_NOCLIENT;
	ent->s.eType    = ET_OID_TRIGGER;

	if (!ent->target)
	{
		// no target - just link and go
		trap_LinkEntity(ent);
	}
	else
	{
		// finalize spawing on fourth frame to allow for proper linking with targets
		ent->nextthink = level.time + (3 * FRAMETIME);
		ent->think     = Think_SetupObjectiveInfo;
	}
}
/*
==================
BotSetInfoConfigString
==================
*/
void BotSetInfoConfigString(bot_state_t *bs) {
	char goalname[MAX_MESSAGE_SIZE];
	char netname[MAX_MESSAGE_SIZE];
	char action[MAX_MESSAGE_SIZE];
	char *leader, carrying[32], *cs;
	bot_goal_t goal;
	//
	ClientName(bs->client, netname, sizeof(netname));
	if (Q_stricmp(netname, bs->teamleader) == 0) leader = "L";
	else leader = " ";

	strcpy(carrying, "  ");
	if (gametype == GT_CTF) {
		if (BotCTFCarryingFlag(bs)) {
			strcpy(carrying, "F ");
		}
	}
#ifdef MISSIONPACK
	else if (gametype == GT_1FCTF) {
		if (Bot1FCTFCarryingFlag(bs)) {
			strcpy(carrying, "F ");
		}
	}
	else if (gametype == GT_HARVESTER) {
		if (BotHarvesterCarryingCubes(bs)) {
			if (BotTeam(bs) == TEAM_RED) Com_sprintf(carrying, sizeof(carrying), "%2d", bs->inventory[INVENTORY_REDCUBE]);
			else Com_sprintf(carrying, sizeof(carrying), "%2d", bs->inventory[INVENTORY_BLUECUBE]);
		}
	}
#endif

	switch(bs->ltgtype) {
		case LTG_TEAMHELP:
		{
			EasyClientName(bs->teammate, goalname, sizeof(goalname));
			Com_sprintf(action, sizeof(action), "helping %s", goalname);
			break;
		}
		case LTG_TEAMACCOMPANY:
		{
			EasyClientName(bs->teammate, goalname, sizeof(goalname));
			Com_sprintf(action, sizeof(action), "accompanying %s", goalname);
			break;
		}
		case LTG_DEFENDKEYAREA:
		{
			trap_BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname));
			Com_sprintf(action, sizeof(action), "defending %s", goalname);
			break;
		}
		case LTG_GETITEM:
		{
			trap_BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname));
			Com_sprintf(action, sizeof(action), "getting item %s", goalname);
			break;
		}
		case LTG_KILL:
		{
			ClientName(bs->teamgoal.entitynum, goalname, sizeof(goalname));
			Com_sprintf(action, sizeof(action), "killing %s", goalname);
			break;
		}
		case LTG_CAMP:
		case LTG_CAMPORDER:
		{
			Com_sprintf(action, sizeof(action), "camping");
			break;
		}
		case LTG_PATROL:
		{
			Com_sprintf(action, sizeof(action), "patrolling");
			break;
		}
		case LTG_GETFLAG:
		{
			Com_sprintf(action, sizeof(action), "capturing flag");
			break;
		}
		case LTG_RUSHBASE:
		{
			Com_sprintf(action, sizeof(action), "rushing base");
			break;
		}
		case LTG_RETURNFLAG:
		{
			Com_sprintf(action, sizeof(action), "returning flag");
			break;
		}
		case LTG_ATTACKENEMYBASE:
		{
			Com_sprintf(action, sizeof(action), "attacking the enemy base");
			break;
		}
		case LTG_HARVEST:
		{
			Com_sprintf(action, sizeof(action), "harvesting");
			break;
		}
		default:
		{
			trap_BotGetTopGoal(bs->gs, &goal);
			trap_BotGoalName(goal.number, goalname, sizeof(goalname));
			Com_sprintf(action, sizeof(action), "roaming %s", goalname);
			break;
		}
	}
  	cs = va("l\\%s\\c\\%s\\a\\%s",
				leader,
				carrying,
				action);
  	trap_SetConfigstring (CS_BOTINFO + bs->client, cs);
}
Beispiel #25
0
/*
================
G_SetEntState

  sets the entstate of an entity.
================
*/
void G_SetEntState(gentity_t *ent, entState_t state)
{
	if (ent->entstate == state)
	{
		G_DPrintf("G_SetEntState: entity %i [%s] already in desired state [%i]\n", ent->s.number, ent->classname, state);
		return;
	}

	switch (state)
	{
	case STATE_DEFAULT:
		if (ent->entstate == STATE_UNDERCONSTRUCTION)
		{
			ent->clipmask   = ent->realClipmask;
			ent->r.contents = ent->realContents;
			if (!ent->realNonSolidBModel)
			{
				ent->s.eFlags &= ~EF_NONSOLID_BMODEL;
			}
		}

		ent->entstate   = STATE_DEFAULT;
		ent->s.powerups = STATE_DEFAULT;

		if (ent->s.eType == ET_WOLF_OBJECTIVE)
		{
			char cs[MAX_STRING_CHARS];

			trap_GetConfigstring(ent->count, cs, sizeof(cs));
			ent->count2 &= ~256;
			Info_SetValueForKey(cs, "t", va("%i", ent->count2));
			trap_SetConfigstring(ent->count, cs);
		}

		if (ent->s.eType != ET_COMMANDMAP_MARKER)
		{
			trap_LinkEntity(ent);
		}

		// deal with any entities in the solid
		{
			int       listedEntities, e;
			int       entityList[MAX_GENTITIES];
			gentity_t *check, *block;

			listedEntities = trap_EntitiesInBox(ent->r.absmin, ent->r.absmax, entityList, MAX_GENTITIES);

			for (e = 0; e < listedEntities; e++)
			{
				check = &g_entities[entityList[e]];

				// ignore everything but items, players and missiles (grenades too)
				if (check->s.eType != ET_MISSILE && check->s.eType != ET_ITEM && check->s.eType != ET_PLAYER && !check->physicsObject)
				{
					continue;
				}

				if ((block = G_TestEntityPosition(check)) == NULL)
				{
					continue;
				}

				if (block != ent)
				{
					// the entity is blocked by another entity - that block this should take care of this itself
					continue;
				}

				if (check->client || check->s.eType == ET_CORPSE)
				{
					// gibs anything player like
					G_Damage(check, ent, ent, NULL, NULL, 9999, DAMAGE_NO_PROTECTION, MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER);
				}
				else if (check->s.eType == ET_ITEM && check->item->giType == IT_TEAM)
				{
					// see if it's a critical entity, one that we can't just simply kill (basically flags)
					Team_DroppedFlagThink(check);
				}
				else
				{
					// remove the landmine from both teamlists
					if (check->s.eType == ET_MISSILE && check->methodOfDeath == MOD_LANDMINE)
					{
						mapEntityData_t *mEnt;

						if ((mEnt = G_FindMapEntityData(&mapEntityData[0], check - g_entities)) != NULL)
						{
							G_FreeMapEntityData(&mapEntityData[0], mEnt);
						}

						if ((mEnt = G_FindMapEntityData(&mapEntityData[1], check - g_entities)) != NULL)
						{
							G_FreeMapEntityData(&mapEntityData[1], mEnt);
						}
					}

					// just get rid of it
					G_FreeEntity(check);
				}
			}
		}

		break;
	case STATE_UNDERCONSTRUCTION:
		ent->entstate     = STATE_UNDERCONSTRUCTION;
		ent->s.powerups   = STATE_UNDERCONSTRUCTION;
		ent->realClipmask = ent->clipmask;
		if (ent->s.eType != ET_CONSTRUCTIBLE)                               // don't make nonsolid as we want to make them partially solid for staged construction
		{
			ent->clipmask = 0;
		}
		ent->realContents = ent->r.contents;
		if (ent->s.eType != ET_CONSTRUCTIBLE)
		{
			ent->r.contents = 0;
		}
		if (ent->s.eFlags & EF_NONSOLID_BMODEL)
		{
			ent->realNonSolidBModel = qtrue;
		}
		else if (ent->s.eType != ET_CONSTRUCTIBLE)
		{
			ent->s.eFlags |= EF_NONSOLID_BMODEL;
		}

		if (!Q_stricmp(ent->classname, "misc_mg42"))
		{
			// stop using the mg42
			mg42_stopusing(ent);
		}
		else if (!Q_stricmp(ent->classname, "misc_aagun"))
		{
			aagun_stopusing(ent);
		}

		if (ent->s.eType == ET_COMMANDMAP_MARKER)
		{
			mapEntityData_t *mEnt;

			if ((mEnt = G_FindMapEntityData(&mapEntityData[0], ent - g_entities)) != NULL)
			{
				G_FreeMapEntityData(&mapEntityData[0], mEnt);
			}
			if ((mEnt = G_FindMapEntityData(&mapEntityData[1], ent - g_entities)) != NULL)
			{
				G_FreeMapEntityData(&mapEntityData[1], mEnt);
			}
		}

		trap_LinkEntity(ent);
		break;
	case STATE_INVISIBLE:
		if (ent->entstate == STATE_UNDERCONSTRUCTION)
		{
			ent->clipmask   = ent->realClipmask;
			ent->r.contents = ent->realContents;
			if (!ent->realNonSolidBModel)
			{
				ent->s.eFlags &= ~EF_NONSOLID_BMODEL;
			}
		}

		ent->entstate   = STATE_INVISIBLE;
		ent->s.powerups = STATE_INVISIBLE;

		if (!Q_stricmp(ent->classname, "misc_mg42"))
		{
			mg42_stopusing(ent);
		}
		else if (!Q_stricmp(ent->classname, "misc_aagun"))
		{
			aagun_stopusing(ent);
		}
		else if (ent->s.eType == ET_WOLF_OBJECTIVE)
		{
			char cs[MAX_STRING_CHARS];

			trap_GetConfigstring(ent->count, cs, sizeof(cs));
			ent->count2 |= 256;
			Info_SetValueForKey(cs, "t", va("%i", ent->count2));
			trap_SetConfigstring(ent->count, cs);
		}

		if (ent->s.eType == ET_COMMANDMAP_MARKER)
		{
			mapEntityData_t *mEnt;

			if ((mEnt = G_FindMapEntityData(&mapEntityData[0], ent - g_entities)) != NULL)
			{
				G_FreeMapEntityData(&mapEntityData[0], mEnt);
			}
			if ((mEnt = G_FindMapEntityData(&mapEntityData[1], ent - g_entities)) != NULL)
			{
				G_FreeMapEntityData(&mapEntityData[1], mEnt);
			}
		}

		trap_UnlinkEntity(ent);
		break;
	}
}
Beispiel #26
0
/*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

    G_SpawnString( "author", "", &s );
    trap_SetConfigstring( CS_AUTHOR1, s );				// map specific author

    G_SpawnString( "author2", "", &s );
    trap_SetConfigstring( CS_AUTHOR2, s );				// map specific author

    trap_SetConfigstring( CS_MOTD, g_motd.string );		// message of the day

    if ( G_SpawnString("gravity", "", &s) ) trap_Cvar_LSet( "g_gravity", s );
    else trap_Cvar_Set( "g_gravity", "800" );	//todo: revert to original gravity value

    G_SpawnString( "enableDust", "0", &s );
    trap_Cvar_Set( "g_enableDust", s );

    G_SpawnString( "enableBreath", "0", &s );
    trap_Cvar_Set( "g_enableBreath", gt[g_gametype.integer].freeze ? "1" : s );

    G_SpawnString( "enableSpawnPads", "0", &s );
    level.enableSpawnPads = atoi( s );
//fnq3: ra3
    G_SpawnString( "arena", "0", &s );
    if ( s[0] ) {
        level.arenas_total = atoi( s );
        if ( level.arenas_total > MAX_MAP_ARENAS ) level.arenas_total = MAX_MAP_ARENAS;

        level.arenas_active = 0;
        trap_SetConfigstring( CS_ARENA, va("%i", level.arenas_active) );
    }
//-fnq3

    g_entities[ENTITYNUM_WORLD].s.number = ENTITYNUM_WORLD;
    g_entities[ENTITYNUM_WORLD].r.ownerNum = ENTITYNUM_NONE;
    g_entities[ENTITYNUM_WORLD].classname = "worldspawn";

    g_entities[ENTITYNUM_NONE].s.number = ENTITYNUM_NONE;
    g_entities[ENTITYNUM_NONE].r.ownerNum = ENTITYNUM_NONE;
    g_entities[ENTITYNUM_NONE].classname = "nothing";

    // see if we want a warmup time
    trap_SetConfigstring( CS_WARMUP, "" );
    if ( g_restarted.integer ) {
        trap_Cvar_Set( "g_restarted", "0" );
        level.warmupTime = 0;
        level.warmupState = WARMUP_ENDED;
        trap_SetConfigstring( CS_WARMUP_STATE, va("%i", level.warmupState) );

        if ( gt[g_gametype.integer].rounds ) {
            Round_Queue( FRAMETIME, qtrue );
        }
    } else if ( g_doWarmup.integer ) { // Turn it on
        level.warmupTime = -1;
        level.warmupState = WARMUP_DEFAULT;
        trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) );
        trap_SetConfigstring( CS_WARMUP_STATE, va("%i", level.warmupState) );
        G_LogPrintf( "Warmup:\n" );
    }

}
Beispiel #27
0
/*
===========
ClientUserInfoChanged

Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
char *ClientUserinfoChanged( int clientNum, qboolean forceName )
{
  gentity_t *ent;
  char      *s;
  char      model[ MAX_QPATH ];
  char      buffer[ MAX_QPATH ];
  char      filename[ MAX_QPATH ];
  char      oldname[ MAX_NAME_LENGTH ];
  char      newname[ MAX_NAME_LENGTH ];
  char      err[ MAX_STRING_CHARS ];
  qboolean  revertName = qfalse;
  gclient_t *client;
  char      userinfo[ MAX_INFO_STRING ];

  ent = g_entities + clientNum;
  client = ent->client;

  trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );

  // check for malformed or illegal info strings
  if( !Info_Validate(userinfo) )
  {
    trap_SendServerCommand( ent - g_entities,
        "disconnect \"illegal or malformed userinfo\n\"" );
    trap_DropClient( ent - g_entities, 
        "dropped: illegal or malformed userinfo");
    return "Illegal or malformed userinfo";
  }
  // If their userinfo overflowed, tremded is in the process of disconnecting them.
  // If we send our own disconnect, it won't work, so just return to prevent crashes later
  //  in this function. This check must come after the Info_Validate call.
  else if( !userinfo[ 0 ] )
    return "Empty (overflowed) userinfo";

  // stickyspec toggle
  s = Info_ValueForKey( userinfo, "cg_stickySpec" );  
  client->pers.stickySpec = atoi( s ) != 0;

  // set name
  Q_strncpyz( oldname, client->pers.netname, sizeof( oldname ) );
  s = Info_ValueForKey( userinfo, "name" );
  G_ClientCleanName( s, newname, sizeof( newname ) );

  if( strcmp( oldname, newname ) )
  {
    if( !forceName && client->pers.namelog->nameChangeTime &&
      level.time - client->pers.namelog->nameChangeTime <=
      g_minNameChangePeriod.value * 1000 )
    {
      trap_SendServerCommand( ent - g_entities, va(
        "print \"Name change spam protection (g_minNameChangePeriod = %d)\n\"",
         g_minNameChangePeriod.integer ) );
      revertName = qtrue;
    }
    else if( !forceName && g_maxNameChanges.integer > 0 &&
      client->pers.namelog->nameChanges >= g_maxNameChanges.integer  )
    {
      trap_SendServerCommand( ent - g_entities, va(
        "print \"Maximum name changes reached (g_maxNameChanges = %d)\n\"",
         g_maxNameChanges.integer ) );
      revertName = qtrue;
    }
    else if( !forceName && client->pers.namelog->muted )
    {
      trap_SendServerCommand( ent - g_entities,
        "print \"You cannot change your name while you are muted\n\"" );
      revertName = qtrue;
    }
    else if( !G_admin_name_check( ent, newname, err, sizeof( err ) ) )
    {
      trap_SendServerCommand( ent - g_entities, va( "print \"%s\n\"", err ) );
      revertName = qtrue;
    }

    if( revertName )
    {
      Q_strncpyz( client->pers.netname, *oldname ? oldname : "UnnamedPlayer",
        sizeof( client->pers.netname ) );
      Info_SetValueForKey( userinfo, "name", oldname );
      trap_SetUserinfo( clientNum, userinfo );
    }
    else
    {
      G_CensorString( client->pers.netname, newname,
        sizeof( client->pers.netname ), ent );
      if( !forceName && client->pers.connected == CON_CONNECTED )
      {
        client->pers.namelog->nameChangeTime = level.time;
        client->pers.namelog->nameChanges++;
      }
      if( *oldname )
      {
        G_LogPrintf( "ClientRename: %i [%s] (%s) \"%s^7\" -> \"%s^7\" \"%c%s%c^7\"\n",
                   clientNum, client->pers.ip.str, client->pers.guid,
                   oldname, client->pers.netname,
                   DECOLOR_OFF, client->pers.netname, DECOLOR_ON );
      }
    }
    G_namelog_update_name( client );
  }

  if( client->pers.classSelection == PCL_NONE )
  {
    //This looks hacky and frankly it is. The clientInfo string needs to hold different
    //model details to that of the spawning class or the info change will not be
    //registered and an axis appears instead of the player model. There is zero chance
    //the player can spawn with the battlesuit, hence this choice.
    Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassConfig( PCL_HUMAN_BSUIT )->modelName,
                                              BG_ClassConfig( PCL_HUMAN_BSUIT )->skinName );
  }
  else
  {
    Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassConfig( client->pers.classSelection )->modelName,
                                              BG_ClassConfig( client->pers.classSelection )->skinName );

    //model segmentation
    Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg",
                 BG_ClassConfig( client->pers.classSelection )->modelName );

    if( G_NonSegModel( filename ) )
      client->ps.persistant[ PERS_STATE ] |= PS_NONSEGMODEL;
    else
      client->ps.persistant[ PERS_STATE ] &= ~PS_NONSEGMODEL;
  }
  Q_strncpyz( model, buffer, sizeof( model ) );

  // wallwalk follow
  s = Info_ValueForKey( userinfo, "cg_wwFollow" );

  if( atoi( s ) )
    client->ps.persistant[ PERS_STATE ] |= PS_WALLCLIMBINGFOLLOW;
  else
    client->ps.persistant[ PERS_STATE ] &= ~PS_WALLCLIMBINGFOLLOW;

  // wallwalk toggle
  s = Info_ValueForKey( userinfo, "cg_wwToggle" );

  if( atoi( s ) )
    client->ps.persistant[ PERS_STATE ] |= PS_WALLCLIMBINGTOGGLE;
  else
    client->ps.persistant[ PERS_STATE ] &= ~PS_WALLCLIMBINGTOGGLE;

  // always sprint
  s = Info_ValueForKey( userinfo, "cg_sprintToggle" );

  if( atoi( s ) )
    client->ps.persistant[ PERS_STATE ] |= PS_SPRINTTOGGLE;
  else
    client->ps.persistant[ PERS_STATE ] &= ~PS_SPRINTTOGGLE;

  // fly speed
  s = Info_ValueForKey( userinfo, "cg_flySpeed" );

  if( *s )
    client->pers.flySpeed = atoi( s );
  else
    client->pers.flySpeed = BG_Class( PCL_NONE )->speed;

  // disable blueprint errors
  s = Info_ValueForKey( userinfo, "cg_disableBlueprintErrors" );

  if( atoi( s ) )
    client->pers.disableBlueprintErrors = qtrue;
  else
    client->pers.disableBlueprintErrors = qfalse;

  // teamInfo
  s = Info_ValueForKey( userinfo, "teamoverlay" );

  if( atoi( s ) != 0 )
    client->pers.teamInfo = qtrue;
  else
    client->pers.teamInfo = qfalse;

  s = Info_ValueForKey( userinfo, "cg_unlagged" );
  if( !s[0] || atoi( s ) != 0 )
    client->pers.useUnlagged = qtrue;
  else
    client->pers.useUnlagged = qfalse;

  Q_strncpyz( client->pers.voice, Info_ValueForKey( userinfo, "voice" ),
    sizeof( client->pers.voice ) );

  // send over a subset of the userinfo keys so other clients can
  // print scoreboards, display models, and play custom sounds

  Com_sprintf( userinfo, sizeof( userinfo ),
    "n\\%s\\t\\%i\\model\\%s\\ig\\%16s\\v\\%s",
    client->pers.netname, client->pers.teamSelection, model,
    Com_ClientListString( &client->sess.ignoreList ),
    client->pers.voice );

  trap_SetConfigstring( CS_PLAYERS + clientNum, userinfo );

  /*G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, userinfo );*/

  return NULL;
}
/*
===========
ClientUserInfoChanged

Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
void ClientUserinfoChanged( int clientNum )
{
  gentity_t *ent;
  int       health;
  char      *s;
  char      model[ MAX_QPATH ];
  char      buffer[ MAX_QPATH ];
  char      filename[ MAX_QPATH ];
  char      oldname[ MAX_NAME_LENGTH ];
  char      newname[ MAX_NAME_LENGTH ];
  char      err[ MAX_STRING_CHARS ];
  qboolean  revertName = qfalse;
  gclient_t *client;
  char      c1[ MAX_INFO_STRING ];
  char      c2[ MAX_INFO_STRING ];
  char      userinfo[ MAX_INFO_STRING ];

  ent = g_entities + clientNum;
  client = ent->client;

  trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );

  // check for malformed or illegal info strings
  if( !Info_Validate(userinfo) )
    strcpy( userinfo, "\\name\\badinfo" );

  // set name
  Q_strncpyz( oldname, client->pers.netname, sizeof( oldname ) );
  s = Info_ValueForKey( userinfo, "name" );
  G_ClientCleanName( s, newname, sizeof( newname ) );

  if( strcmp( oldname, newname ) )
  {
    // in case we need to revert and there's no oldname
    if( client->pers.connected != CON_CONNECTED )
        Q_strncpyz( oldname, "UnnamedPlayer", sizeof( oldname ) );

    if( client->pers.nameChangeTime &&
      ( level.time - client->pers.nameChangeTime )
      <= ( g_minNameChangePeriod.value * 1000 ) )
    {
      trap_SendServerCommand( ent - g_entities, va(
        "print \"Name change spam protection (g_minNameChangePeriod = %d)\n\"",
         g_minNameChangePeriod.integer ) );
      revertName = qtrue;
    }
    else if( g_maxNameChanges.integer > 0
      && client->pers.nameChanges >= g_maxNameChanges.integer  )
    {
      trap_SendServerCommand( ent - g_entities, va(
        "print \"Maximum name changes reached (g_maxNameChanges = %d)\n\"",
         g_maxNameChanges.integer ) );
      revertName = qtrue;
    }
    else if( !G_admin_name_check( ent, newname, err, sizeof( err ) ) )
    {
      trap_SendServerCommand( ent - g_entities, va( "print \"%s\n\"", err ) );
      revertName = qtrue;
    }

    if( revertName )
    {
      Q_strncpyz( client->pers.netname, oldname,
        sizeof( client->pers.netname ) );
      Info_SetValueForKey( userinfo, "name", oldname );
      trap_SetUserinfo( clientNum, userinfo );
    }
    else
    {
      Q_strncpyz( client->pers.netname, newname,
        sizeof( client->pers.netname ) );
      if( client->pers.connected == CON_CONNECTED )
      {
        client->pers.nameChangeTime = level.time;
        client->pers.nameChanges++;
      }
    }
  }

  if( client->sess.spectatorState == SPECTATOR_SCOREBOARD )
    Q_strncpyz( client->pers.netname, "scoreboard", sizeof( client->pers.netname ) );

  if( client->pers.connected == CON_CONNECTED )
  {
    if( strcmp( oldname, client->pers.netname ) )
    {
      trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE
        " renamed to %s\n\"", oldname, client->pers.netname ) );
      G_LogPrintf( "ClientRename: %i [%s] (%s) \"%s\" -> \"%s\"\n", clientNum,
         client->pers.ip, client->pers.guid, oldname, client->pers.netname );
      G_admin_namelog_update( client, qfalse );
    }
  }

  // set max health
  health = atoi( Info_ValueForKey( userinfo, "handicap" ) );
  client->pers.maxHealth = health;

  if( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 )
    client->pers.maxHealth = 100;

  if( client->pers.classSelection == PCL_NONE )
  {
    //This looks hacky and frankly it is. The clientInfo string needs to hold different
    //model details to that of the spawning class or the info change will not be
    //registered and an axis appears instead of the player model. There is zero chance
    //the player can spawn with the battlesuit, hence this choice.
    Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassConfig( PCL_HUMAN_BSUIT )->modelName,
                                              BG_ClassConfig( PCL_HUMAN_BSUIT )->skinName );
  }
  else
  {
    Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassConfig( client->pers.classSelection )->modelName,
                                              BG_ClassConfig( client->pers.classSelection )->skinName );

    //model segmentation
    Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg",
                 BG_ClassConfig( client->pers.classSelection )->modelName );

    if( G_NonSegModel( filename ) )
      client->ps.persistant[ PERS_STATE ] |= PS_NONSEGMODEL;
    else
      client->ps.persistant[ PERS_STATE ] &= ~PS_NONSEGMODEL;
  }
  Q_strncpyz( model, buffer, sizeof( model ) );

  // wallwalk follow
  s = Info_ValueForKey( userinfo, "cg_wwFollow" );

  if( atoi( s ) )
    client->ps.persistant[ PERS_STATE ] |= PS_WALLCLIMBINGFOLLOW;
  else
    client->ps.persistant[ PERS_STATE ] &= ~PS_WALLCLIMBINGFOLLOW;

  // wallwalk toggle
  s = Info_ValueForKey( userinfo, "cg_wwToggle" );

  if( atoi( s ) )
    client->ps.persistant[ PERS_STATE ] |= PS_WALLCLIMBINGTOGGLE;
  else
    client->ps.persistant[ PERS_STATE ] &= ~PS_WALLCLIMBINGTOGGLE;

  // teamInfo
  s = Info_ValueForKey( userinfo, "teamoverlay" );

  if( !*s || atoi( s ) != 0 )
    client->pers.teamInfo = qtrue;
  else
    client->pers.teamInfo = qfalse;

  // colors
  strcpy( c1, Info_ValueForKey( userinfo, "color1" ) );
  strcpy( c2, Info_ValueForKey( userinfo, "color2" ) );

  Q_strncpyz( client->pers.voice, Info_ValueForKey( userinfo, "voice" ),
    sizeof( client->pers.voice ) );

  // send over a subset of the userinfo keys so other clients can
  // print scoreboards, display models, and play custom sounds

  Com_sprintf( userinfo, sizeof( userinfo ),
    "n\\%s\\t\\%i\\model\\%s\\c1\\%s\\c2\\%s\\"
    "hc\\%i\\ig\\%16s\\v\\%s",
    client->pers.netname, client->pers.teamSelection, model, c1, c2,
    client->pers.maxHealth, BG_ClientListString( &client->sess.ignoreList ),
    client->pers.voice );

  trap_SetConfigstring( CS_PLAYERS + clientNum, userinfo );

  /*G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, userinfo );*/
}
Beispiel #29
0
void G_delayPrint(gentity_t *dpent)
{
	int      think_next = 0;
	qboolean fFree      = qtrue;

	switch (dpent->spawnflags)
	{
	case DP_PAUSEINFO:
	{
		if (level.match_pause > PAUSE_UNPAUSING)
		{
			int cSeconds = match_timeoutlength.integer * 1000 - (level.time - dpent->timestamp);

			if (cSeconds > 1000)
			{
				AP(va("cp \"^3Match resuming in ^1%d^3 seconds!\n\"", cSeconds / 1000));
				think_next = level.time + 15000;
				fFree      = qfalse;
			}
			else
			{
				level.match_pause = PAUSE_UNPAUSING;
				AP("print \"^3Match resuming in 10 seconds!\n\"");
				G_globalSound("sound/osp/prepare.wav");
				G_spawnPrintf(DP_UNPAUSING, level.time + 10, NULL);
			}
		}
		break;
	}

	case DP_UNPAUSING:
	{
		if (level.match_pause == PAUSE_UNPAUSING)
		{
			int cSeconds = 11 * 1000 - (level.time - dpent->timestamp);

			if (cSeconds > 1000)
			{
				AP(va("cp \"^3Match resuming in ^1%d^3 seconds!\n\"", cSeconds / 1000));
				think_next = level.time + 1000;
				fFree      = qfalse;
			}
			else
			{
				level.match_pause = PAUSE_NONE;
				G_globalSound("sound/osp/fight.wav");
				G_printFull("^1FIGHT!", NULL);
				trap_SetConfigstring(CS_LEVEL_START_TIME, va("%i", level.startTime + level.timeDelta));
				level.server_settings &= ~CV_SVS_PAUSE;
				trap_SetConfigstring(CS_SERVERTOGGLES, va("%d", level.server_settings));
			}
		}
		break;
	}

#ifdef FEATURE_MULTIVIEW
	case DP_MVSPAWN:
	{
		int       i;
		gentity_t *ent;

		for (i = 0; i < level.numConnectedClients; i++)
		{
			ent = g_entities + level.sortedClients[i];

			if (ent->client->pers.mvReferenceList == 0)
			{
				continue;
			}
			if (ent->client->sess.sessionTeam != TEAM_SPECTATOR)
			{
				continue;
			}
			G_smvRegenerateClients(ent, ent->client->pers.mvReferenceList);
		}

		break;
	}
#endif

	default:
		break;
	}

	dpent->nextthink = think_next;
	if (fFree)
	{
		dpent->think = 0;
		G_FreeEntity(dpent);
	}
}
Beispiel #30
0
void JMSaberTouch(gentity_t *self, gentity_t *other, trace_t *trace)
{
	int i = 0;
//	gentity_t *te;

	if (!other || !other->client || other->health < 1)
	{
		return;
	}

	if (self->enemy)
	{
		return;
	}

	if (!self->s.modelindex)
	{
		return;
	}

	if (other->client->ps.stats[STAT_WEAPONS] & (1 << WP_SABER))
	{
		return;
	}

	if (other->client->ps.isJediMaster)
	{
		return;
	}

	self->enemy = other;
	other->client->ps.stats[STAT_WEAPONS] = (1 << WP_SABER);
	other->client->ps.weapon = WP_SABER;
	other->s.weapon = WP_SABER;
	G_AddEvent(other, EV_BECOME_JEDIMASTER, 0);

	// Track the jedi master 
	trap_SetConfigstring ( CS_CLIENT_JEDIMASTER, va("%i", other->s.number ) );

	if (g_spawnInvulnerability.integer)
	{
		other->client->ps.eFlags |= EF_INVULNERABLE;
		other->client->invulnerableTimer = level.time + g_spawnInvulnerability.integer;
	}

	trap_SendServerCommand( -1, va("cp \"%s %s\n\"", other->client->pers.netname, G_GetStripEdString("SVINGAME", "BECOMEJM")) );

	other->client->ps.isJediMaster = qtrue;
	other->client->ps.saberIndex = self->s.number;

	if (other->health < 200 && other->health > 0)
	{ //full health when you become the Jedi Master
		other->client->ps.stats[STAT_HEALTH] = other->health = 200;
	}

	if (other->client->ps.fd.forcePower < 100)
	{
		other->client->ps.fd.forcePower = 100;
	}

	while (i < NUM_FORCE_POWERS)
	{
		other->client->ps.fd.forcePowersKnown |= (1 << i);
		other->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_3;

		i++;
	}

	self->pos2[0] = 1;
	self->pos2[1] = level.time + JMSABER_RESPAWN_TIME;

	self->s.modelindex = 0;
	self->s.eFlags |= EF_NODRAW;
	self->s.modelGhoul2 = 0;
	self->s.eType = ET_GENERAL;

	/*
	te = G_TempEntity( vec3_origin, EV_DESTROY_GHOUL2_INSTANCE );
	te->r.svFlags |= SVF_BROADCAST;
	te->s.eventParm = self->s.number;
	*/
	G_KillG2Queue(self->s.number);

	return;
}