Пример #1
0
// FIXME: use nav handle instead of classes
void G_BotNavInit()
{
	int i;

	Log::Notice( "==== Bot Navigation Initialization ==== \n" );

	for ( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ )
	{
		classModelConfig_t *model;
		botClass_t bot;
		bot.polyFlagsInclude = POLYFLAGS_WALK;
		bot.polyFlagsExclude = POLYFLAGS_DISABLED;

		model = BG_ClassModelConfig( i );
		if ( model->navMeshClass )
		{
			if ( BG_ClassModelConfig( model->navMeshClass )->navMeshClass )
			{
				Log::Warn( "class '%s': navmesh reference target class '%s' must have its own navmesh",
				            BG_Class( i )->name, BG_Class( model->navMeshClass )->name );
				return;
			}

			continue;
		}

		Q_strncpyz( bot.name, BG_Class( i )->name, sizeof( bot.name ) );

		if ( !trap_BotSetupNav( &bot, &model->navHandle ) )
		{
			return;
		}
	}
	navMeshLoaded = true;
}
Пример #2
0
void BotSetNavmesh( gentity_t  *self, class_t newClass )
{
	int navHandle;
	const classModelConfig_t *model;

	if ( newClass == PCL_NONE )
	{
		return;
	}

	model = BG_ClassModelConfig( newClass );
	navHandle = model->navMeshClass
	          ? BG_ClassModelConfig( model->navMeshClass )->navHandle
	          : model->navHandle;

	trap_BotSetNavMesh( self->s.number, navHandle );
}
Пример #3
0
static const char *UnlockableHumanName( unlockable_t *unlockable )
{
	switch ( unlockable->type )
	{
		case UNLT_WEAPON:    return BG_Weapon( unlockable->num )->humanName;
		case UNLT_UPGRADE:   return BG_Upgrade( unlockable->num )->humanName;
		case UNLT_BUILDABLE: return BG_Buildable( unlockable->num )->humanName;
		case UNLT_CLASS:     return BG_ClassModelConfig( unlockable->num )->humanName;
	}

	Com_Error( ERR_FATAL, "UnlockableHumanName: Unlockable has unknown type" );
	return nullptr;
}
Пример #4
0
void G_InitDamageLocations( void )
{
	const char   *modelName;
	char         filename[ MAX_QPATH ];
	int          i;
	int          len;
	fileHandle_t fileHandle;
	char         buffer[ MAX_DAMAGE_REGION_TEXT ];

	for ( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ )
	{
		modelName = BG_ClassModelConfig( i )->modelName;
		Com_sprintf( filename, sizeof( filename ), "configs/classes/%s.locdamage.cfg", modelName );

		len = trap_FS_FOpenFile( filename, &fileHandle, FS_READ );

		if ( !fileHandle )
		{
			G_Printf( S_COLOR_RED "file not found: %s\n", filename );
			continue;
		}

		if ( len >= MAX_DAMAGE_REGION_TEXT )
		{
			G_Printf( S_COLOR_RED "file too large: %s is %i, max allowed is %i\n",
			          filename, len, MAX_DAMAGE_REGION_TEXT );
			trap_FS_FCloseFile( fileHandle );
			continue;
		}

		COM_BeginParseSession( filename );

		trap_FS_Read( buffer, len, fileHandle );
		buffer[ len ] = 0;
		trap_FS_FCloseFile( fileHandle );

		g_numDamageRegions[ i ] = ParseDmgScript( g_damageRegions[ i ], buffer );
	}
}
Пример #5
0
/*
=============
CG_Obituary
=============
*/
static void CG_Obituary( entityState_t *ent )
{
    int          mod;
    int          target, attacker;
    int          attackerClass = -1;
    const char   *message;
    const char   *targetInfo;
    const char   *attackerInfo;
    char         targetName[ MAX_NAME_LENGTH ];
    char         attackerName[ MAX_NAME_LENGTH ];
    gender_t     gender;
    clientInfo_t *ci;
    qboolean     teamKill = qfalse;
    qboolean     attackerFirst = qfalse;

    target = ent->otherEntityNum;
    attacker = ent->otherEntityNum2;
    mod = ent->eventParm;

    if ( target < 0 || target >= MAX_CLIENTS )
    {
        CG_Error( "CG_Obituary: target out of range" );
    }

    ci = &cgs.clientinfo[ target ];
    gender = ci->gender;

    if ( attacker < 0 || attacker >= MAX_CLIENTS )
    {
        attacker = ENTITYNUM_WORLD;
        attackerInfo = NULL;
    }
    else
    {
        attackerInfo = CG_ConfigString( CS_PLAYERS + attacker );

        if ( cgs.clientinfo[ attacker ].team == ci->team )
        {
            teamKill = qtrue;
        }
    }

    targetInfo = CG_ConfigString( CS_PLAYERS + target );

    if ( !targetInfo )
    {
        return;
    }

    Q_strncpyz( targetName, Info_ValueForKey( targetInfo, "n" ), sizeof( targetName ) );

    // check for single client messages

    switch ( mod )
    {
    case MOD_FALLING:
        message = G_( "%s ^7fell foul to gravity\n" );
        break;

    case MOD_CRUSH:
        message = G_( "%s ^7was squished\n" );
        break;

    case MOD_WATER:
        message = G_( "%s ^7forgot to pack a snorkel\n" );
        break;

    case MOD_SLIME:
        message = G_( "%s ^7melted\n" );
        break;

    case MOD_LAVA:
        message = G_( "%s ^7did a back flip into the lava\n" );
        break;

    case MOD_TARGET_LASER:
        message = G_( "%s ^7saw the light\n" );
        break;

    case MOD_TRIGGER_HURT:
        message = G_( "%s ^7was in the wrong place\n" );
        break;

    case MOD_HSPAWN:
        message = G_( "%s ^7should have run further\n" );
        break;

    case MOD_ASPAWN:
        message = G_( "%s ^7shouldn't have trod in the acid\n" );
        break;

    case MOD_MGTURRET:
        if ( cg_emoticonsInMessages.integer )
        {
            message = "[turret] %s\n";
        }
        else
        {
            message = G_( "%s ^7was gunned down by a turret\n" );
        }
        break;

    case MOD_TESLAGEN:
        if ( cg_emoticonsInMessages.integer )
        {
            message = "[tesla] %s\n";
        }
        else
        {
            message = G_( "%s ^7was zapped by a tesla generator\n" );
        }
        break;

    case MOD_ATUBE:
        if ( cg_emoticonsInMessages.integer )
        {
            message = "[acidtube] %s\n";
        }
        else
        {
            message = G_( "%s ^7was melted by an acid tube\n" );
        }
        break;

    case MOD_OVERMIND:
        if ( cg_emoticonsInMessages.integer )
        {
            message = "[overmind] %s\n";
        }
        else
        {
            message = G_( "%s ^7got too close to the overmind\n" );
        }
        break;

    case MOD_REACTOR:
        if ( cg_emoticonsInMessages.integer )
        {
            message = "[reactor] %s\n";
        }
        else
        {
            message = G_( "%s ^7got too close to the reactor\n" );
        }
        break;

    case MOD_SLOWBLOB:
        message = G_( "%s ^7should have visited a medical station\n" );
        break;

    case MOD_SWARM:
        if ( cg_emoticonsInMessages.integer )
        {
            message = "[hive] %s\n";
        }
        else
        {
            message = G_( "%s ^7was hunted down by the swarm\n" );
        }
        break;

    default:
        message = NULL;
        break;
    }

    if ( !message && attacker == target )
    {
        switch ( mod )
        {
        case MOD_FLAMER_SPLASH:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "[flamer] %s\n";
            }
            else
            {
                message = G_( "%s ^7toasted self\n" );
            }
            break;

        case MOD_BURN:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "[fire] %s\n";
            }
            else
            {
                message = G_( "%s ^7burned self\n" );
            }
            break;

        case MOD_LCANNON_SPLASH:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "[lcannon] %s\n";
            }
            else
            {
                message = G_( "%s ^7irradiated self\n" );
            }
            break;

        case MOD_GRENADE:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "[grenade] %s\n";
            }
            else
            // fall-through
            case MOD_FIREBOMB:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "[firebomb] %s\n";
            }
            else
            {
                message = G_( "%s ^7blew self up\n" );
            }
            break;

        case MOD_LEVEL3_BOUNCEBALL:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "[advdragoon] %s\n";
            }
            else
            {
                message = G_( "%s ^7sniped self\n" );
            }
            break;

        case MOD_PRIFLE:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "[prifle] %s\n";
            }
            else
            {
                message = G_( "%s ^7pulse rifled self\n" );
            }
            break;

        default:
            message = G_( "%s ^7killed self\n" );
            break;
        }
    }

    if ( message )
    {
        CG_Printf( message, targetName );
        return;
    }

    // check for double client messages
    if ( !attackerInfo )
    {
        attacker = ENTITYNUM_WORLD;
        strcpy( attackerName, "noname" );
    }
    else
    {
        Q_strncpyz( attackerName, Info_ValueForKey( attackerInfo, "n" ), sizeof( attackerName ) );

        // check for kill messages about the current clientNum
        if ( target == cg.snap->ps.clientNum )
        {
            Q_strncpyz( cg.killerName, attackerName, sizeof( cg.killerName ) );
        }
    }

    if ( attacker != ENTITYNUM_WORLD )
    {
        switch ( mod )
        {
        case MOD_PAINSAW:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [painsaw] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was sawn by %s%s\n" );
            }
            break;

        case MOD_BLASTER:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [blaster] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was blasted by %s%s\n" );
            }
            break;

        case MOD_MACHINEGUN:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [rifle] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was machinegunned by %s%s\n" );
            }
            break;

        case MOD_CHAINGUN:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [chaingun] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was chaingunned by %s%s\n" );
            }
            break;

        case MOD_SHOTGUN:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [shotgun] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was gunned down by %s%s\n" );
            }
            break;

        case MOD_PRIFLE:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [prifle] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was pulse rifled by %s%s\n" );
            }
            break;

        case MOD_MDRIVER:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [mdriver] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was mass driven by %s%s\n" );
            }
            break;

        case MOD_LASGUN:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [lasgun] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was lasgunned by %s%s\n" );
            }
            break;

        case MOD_FLAMER:
        case MOD_FLAMER_SPLASH:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [flamer] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was grilled by %s%s^7's flamer\n" );
            }
            break;

        case MOD_BURN:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [flamer] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was burned by %s%s^7's fire\n" );
            }
            break;

        case MOD_LCANNON:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [lcannon] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7felt the full force of %s%s^7's lucifer cannon\n" );
            }
            break;

        case MOD_LCANNON_SPLASH:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [lcannon] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was caught in the fallout of %s%s^7's lucifer cannon\n" );
            }
            break;

        case MOD_GRENADE:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [grenade] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7couldn't escape %s%s^7's grenade\n" );
            }
            break;

        case MOD_FIREBOMB:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [firebomb] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7couldn't escape %s%s^7's firebomb\n" );
            }
            break;

        case MOD_ABUILDER_CLAW:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [granger] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7should leave %s%s^7's buildings alone\n" );
            }
            break;

        case MOD_LEVEL0_BITE:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [dretch] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was bitten by %s%s\n" );
            }
            break;

        case MOD_LEVEL1_CLAW:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [basilisk] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was swiped by %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL1;
            }
            break;

        case MOD_LEVEL2_CLAW:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [marauder] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was clawed by %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL2;
            }
            break;

        case MOD_LEVEL2_ZAP:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [advmarauder] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was zapped by %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL2;
            }
            break;

        case MOD_LEVEL3_CLAW:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [dragoon] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was chomped by %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL3;
            }
            break;

        case MOD_LEVEL3_POUNCE:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [dragoon] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was pounced upon by %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL3;
            }
            break;

        case MOD_LEVEL3_BOUNCEBALL:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [advdragoon] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was sniped by %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL3;
            }
            break;

        case MOD_LEVEL4_CLAW:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [tyrant] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was mauled by %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL4;
            }
            break;

        case MOD_LEVEL4_TRAMPLE:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [tyrant] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7should have gotten out of the way of %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL4;
            }
            break;

        case MOD_WEIGHT_H:
        case MOD_WEIGHT_A:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 crushed %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was crushed under %s%s^7's weight\n" );
            }
            break;

        case MOD_POISON:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [booster] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7should have used a medkit against %s%s^7's poison\n" );
            }
            break;

        case MOD_LEVEL1_PCLOUD:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [advbasilisk] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7was gassed by %s%s^7's %s\n" );
                attackerClass = PCL_ALIEN_LEVEL1;
            }
            break;

        case MOD_TELEFRAG:
            if ( cg_emoticonsInMessages.integer )
            {
                message = "%s%s^7 [telenode] %s\n";
                attackerFirst = qtrue;
            }
            else
            {
                message = G_( "%s ^7tried to invade %s%s^7's personal space\n" );
            }
            break;

        default:
            message = G_( "%s ^7was killed by %s%s\n" );
            break;
        }

        if ( message )
        {
            if ( attackerFirst )
            {
                // Argument order: "TEAMMATE"/"", attacker, victim
                CG_Printf( message, ( teamKill ) ? _("^1TEAMMATE^7 ") : "", attackerName, targetName );
            }
            else
            {
                // Argument order: victim, ["TEAMMATE"/"", attacker [, alien class]]
                CG_Printf( message, targetName, ( teamKill ) ? _("^1TEAMMATE^7 ") : "", attackerName,
                           ( attackerClass != -1 ) ? _( BG_ClassModelConfig( attackerClass )->humanName ) : NULL );
            }

            if ( teamKill && attacker == cg.clientNum )
            {
                CG_CenterPrint( va( _("You killed ^1TEAMMATE^7 %s"), targetName ),
                                SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
            }

            return;
        }
    }

    // we don't know what it was
    CG_Printf( G_( "%s^7 died\n" ), targetName );
}
Пример #6
0
/*
===============
CG_OffsetShoulderView

===============
*/
void CG_OffsetShoulderView( void )
{
	int          i;
	int          cmdNum;
	usercmd_t    cmd, oldCmd;
	vec3_t       rotationAngles;
	vec3_t       axis[ 3 ], rotaxis[ 3 ];
	float        deltaMousePitch;
	static float mousePitch;
	vec3_t       forward, right, up;
	classModelConfig_t *classModelConfig;

	// Ignore following pitch; it's too jerky otherwise.
	if ( !cg_thirdPersonPitchFollow.integer )
	{
		cg.refdefViewAngles[ PITCH ] = 0.0f;
	}

	AngleVectors( cg.refdefViewAngles, forward, right, up );

	classModelConfig = BG_ClassModelConfig( cg.snap->ps.stats[ STAT_CLASS ] );
	VectorMA( cg.refdef.vieworg, classModelConfig->shoulderOffsets[ 0 ], forward, cg.refdef.vieworg );
	VectorMA( cg.refdef.vieworg, classModelConfig->shoulderOffsets[ 1 ], right, cg.refdef.vieworg );
	VectorMA( cg.refdef.vieworg, classModelConfig->shoulderOffsets[ 2 ], up, cg.refdef.vieworg );

	// If someone is playing like this, the rest is already taken care of
	// so just get the firstperson effects and leave.
	if ( !cg.demoPlayback && !( cg.snap->ps.pm_flags & PMF_FOLLOW ) )
	{
		CG_OffsetFirstPersonView();
		return;
	}

	// Get mouse input for camera rotation.
	cmdNum = trap_GetCurrentCmdNumber();
	trap_GetUserCmd( cmdNum, &cmd );
	trap_GetUserCmd( cmdNum - 1, &oldCmd );

	// Prevent pitch from wrapping and clamp it within a [30, -50] range.
	// Cgame has no access to ps.delta_angles[] here, so we need to reproduce
	// it ourselves here.
	deltaMousePitch = SHORT2ANGLE( cmd.angles[ PITCH ] - oldCmd.angles[ PITCH ] );

	if ( fabs( deltaMousePitch ) < 200.0f )
	{
		mousePitch += deltaMousePitch;
	}

	// Handle pitch.
	rotationAngles[ PITCH ] = mousePitch;

	rotationAngles[ PITCH ] = AngleNormalize180( rotationAngles[ PITCH ] + AngleNormalize180( cg.refdefViewAngles[ PITCH ] ) );

	if ( rotationAngles [ PITCH ] < -90.0f ) { rotationAngles [ PITCH ] = -90.0f; }

	if ( rotationAngles [ PITCH ] > 90.0f ) { rotationAngles [ PITCH ] = 90.0f; }

	// Yaw and Roll are much easier.
	rotationAngles[ YAW ] = SHORT2ANGLE( cmd.angles[ YAW ] ) + cg.refdefViewAngles[ YAW ];
	rotationAngles[ ROLL ] = 0.0f;

	// Perform the rotations.
	AnglesToAxis( rotationAngles, axis );

	if ( !( cg.snap->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING ) ||
	     !BG_RotateAxis( cg.snap->ps.grapplePoint, axis, rotaxis, qfalse,
	                     cg.snap->ps.eFlags & EF_WALLCLIMBCEILING ) )
	{
		AxisCopy( axis, rotaxis );
	}

	AxisToAngles( rotaxis, rotationAngles );

	// Actually set the viewangles.
	for ( i = 0; i < 3; i++ )
	{
		cg.refdefViewAngles[ i ] = rotationAngles[ i ];
	}

	// Now run the first person stuff so we get various effects added.
	CG_OffsetFirstPersonView();
}
Пример #7
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.
============
*/
const char *ClientUserinfoChanged( int clientNum, bool forceName )
{
	gentity_t *ent;
	const char      *s;
	char      model[ MAX_QPATH ];
	char      buffer[ MAX_QPATH ];
	char      oldname[ MAX_NAME_LENGTH ];
	char      newname[ MAX_NAME_LENGTH ];
	char      err[ MAX_STRING_CHARS ];
	bool  revertName = false;
	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\"" );
		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 ), client );

	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_tr %s %d", QQ( N_("Name change spam protection (g_minNameChangePeriod = $1$)") ),
			                          g_minNameChangePeriod.integer ) );
			revertName = true;
		}
		else if ( !forceName && g_maxNameChanges.integer > 0 &&
		          client->pers.namelog->nameChanges >= g_maxNameChanges.integer )
		{
			trap_SendServerCommand( ent - g_entities, va(
			                          "print_tr %s %d", QQ( N_("Maximum name changes reached (g_maxNameChanges = $1$)") ),
			                          g_maxNameChanges.integer ) );
			revertName = true;
		}
		else if ( !forceName && client->pers.namelog->muted )
		{
			trap_SendServerCommand( ent - g_entities,
			                        va( "print_tr %s", QQ( N_("You cannot change your name while you are muted") ) ) );
			revertName = true;
		}
		else if ( !G_admin_name_check( ent, newname, err, sizeof( err ) ) )
		{
			trap_SendServerCommand( ent - g_entities, va( "print_tr %s %s %s", QQ( "$1t$ $2$" ), Quote( err ), Quote( newname ) ) );
			revertName = true;
		}
		else if ( Q_UTF8_Strlen( newname ) > MAX_NAME_CHARACTERS )
		{
			trap_SendServerCommand( ent - g_entities,
			                        va( "print_tr %s %d", QQ( N_("Name is too long! Must be less than $1$ characters.") ), MAX_NAME_CHARACTERS ) );
			revertName = true;

		}

		if ( revertName )
		{
			Q_strncpyz( client->pers.netname, *oldname ? oldname : G_UnnamedClientName( client ),
			            sizeof( client->pers.netname ) );
		}
		else
		{
			if( G_IsUnnamed( newname ) )
			{
				Q_strncpyz( client->pers.netname, G_UnnamedClientName( client ), sizeof( client->pers.netname ) );
			}
			else
			{
				Q_strncpyz( client->pers.netname, newname, sizeof( client->pers.netname ) );
			}

			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\" \"%s^7\"",
				             clientNum, client->pers.ip.str, client->pers.guid,
				             oldname, client->pers.netname,
				             client->pers.netname );
			}
		}

		G_namelog_update_name( client );

		Info_SetValueForKey(userinfo, "name", client->pers.netname, false);
		trap_SetUserinfo(clientNum, userinfo);
	}

	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_ClassModelConfig( PCL_HUMAN_BSUIT )->modelName,
		             BG_ClassModelConfig( PCL_HUMAN_BSUIT )->skinName );
	}
	else
	{
		Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassModelConfig( client->pers.classSelection )->modelName,
		             BG_ClassModelConfig( client->pers.classSelection )->skinName );

		if ( BG_ClassModelConfig( client->pers.classSelection )->segmented )
		{
			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 = true;
	}
	else
	{
		client->pers.disableBlueprintErrors = false;
	}

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

	if ( atoi( s ) != 0 )
	{
		// teamoverlay was enabled so we need an update
		if ( client->pers.teamInfo == 0 )
		{
			client->pers.teamInfo = 1;
		}
	}
	else
	{
		client->pers.teamInfo = 0;
	}

	s = Info_ValueForKey( userinfo, "cg_unlagged" );

	if ( !s[ 0 ] || atoi( s ) != 0 )
	{
		client->pers.useUnlagged = true;
	}
	else
	{
		client->pers.useUnlagged = false;
	}

	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.team, model,
	             Com_ClientListString( &client->sess.ignoreList ),
	             client->pers.voice );

	trap_SetConfigstring( CS_PLAYERS + clientNum, userinfo );

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

	return nullptr;
}
Пример #8
0
static void CG_Obituary( entityState_t *ent )
{
	int          mod;
	int          target, attacker, assistant;
	int          attackerClass = -1;
	const char   *message;
	const char   *messageAssisted = nullptr;
	const char   *messageSuicide = nullptr;
	const char   *targetInfo;
	const char   *attackerInfo;
	const char   *assistantInfo;
	char         targetName[ MAX_NAME_LENGTH ];
	char         attackerName[ MAX_NAME_LENGTH ];
	char         assistantName[ MAX_NAME_LENGTH ];
	gender_t     gender;
	clientInfo_t *ci;
	team_t       attackerTeam, assistantTeam = TEAM_NONE;

	target = ent->otherEntityNum;
	attacker = ent->otherEntityNum2;
	assistant = ent->otherEntityNum3;
	assistantTeam = (team_t) ( ent->generic1 & 0xFF ); // ugly hack allowing for future expansion(!)
	mod = ent->eventParm;

	if ( target < 0 || target >= MAX_CLIENTS )
	{
		CG_Error( "CG_Obituary: target out of range" );
	}

	ci = &cgs.clientinfo[ target ];
	gender = ci->gender;

	if ( attacker < 0 || attacker >= MAX_CLIENTS )
	{
		attacker = ENTITYNUM_WORLD;
		attackerInfo = nullptr;
		attackerTeam = TEAM_NONE;
		strcpy( attackerName, "noname" );
	}
	else
	{
		attackerInfo = CG_ConfigString( CS_PLAYERS + attacker );
		attackerTeam = cgs.clientinfo[ attacker ].team;
		Q_strncpyz( attackerName, Info_ValueForKey( attackerInfo, "n" ), sizeof( attackerName ) );

		// check for kill messages about the current clientNum
		if ( target == cg.snap->ps.clientNum )
		{
			Q_strncpyz( cg.killerName, attackerName, sizeof( cg.killerName ) );
		}
	}

	if ( assistant < 0 || assistant >= MAX_CLIENTS )
	{
		assistantInfo = nullptr;
	}
	else
	{
		assistantInfo = CG_ConfigString( CS_PLAYERS + assistant );
	}

	if ( assistantTeam < TEAM_NONE || assistantTeam >= NUM_TEAMS )
	{
		assistantTeam = TEAM_NONE;
	}

	if ( !assistantInfo )
	{
		strcpy( assistantName, "noname" );
	}
	else
	{
		Q_strncpyz( assistantName, Info_ValueForKey( assistantInfo, "n" ), sizeof( assistantName ) );
	}

	targetInfo = CG_ConfigString( CS_PLAYERS + target );

	if ( !targetInfo )
	{
		return;
	}

	Q_strncpyz( targetName, Info_ValueForKey( targetInfo, "n" ), sizeof( targetName ) );

	// check for single client messages

	if ( cg_emoticonsInMessages.integer )
	{
		if ( mod < MOD_UNKNOWN || mod >= ARRAY_LEN( meansOfDeath ) )
		{
			mod = MOD_UNKNOWN;
		}

		if ( meansOfDeath[ mod ].team )
		{
			attackerTeam = meansOfDeath[ mod ].team;
		}

		// if the long form is needed, show it; but we need a kill icon for this kill type
		if ( *meansOfDeath[ mod ].icon == '>' )
		{
				goto is_long_kill_message;
		}

		// if there's text for the kill type, print a kill message
		if ( *meansOfDeath[ mod ].icon )
		{
			if ( meansOfDeath[ mod ].envKill )
			{
				if ( meansOfDeath[ mod ].showAssist && assistantInfo )
				{
					CG_Printf( "%s (+ %s%s^7) %s %s%s\n", teamTag[ attackerTeam ], teamTag[ assistantTeam ], assistantName, meansOfDeath[ mod ].icon, teamTag[ ci->team ], targetName );
				}
				else
				{
					CG_Printf( "%s %s %s%s\n", teamTag[ attackerTeam ], meansOfDeath[ mod ].icon, teamTag[ ci->team ], targetName );
				}
			}
			else if ( attacker == target )
			{
				CG_Printf( "%s %s%s\n", meansOfDeath[ mod ].icon, teamTag[ ci->team ], targetName );
			}
			else
			{
				if ( meansOfDeath[ mod ].showAssist && assistantInfo )
				{
					CG_Printf( "%s%s^7 (+ %s%s^7) %s %s%s\n", teamTag[ attackerTeam ], attackerName, teamTag[ assistantTeam ], assistantName, meansOfDeath[ mod ].icon, teamTag[ ci->team ], targetName );
				}
				else
				{
					CG_Printf( "%s%s^7 %s %s%s\n", teamTag[ attackerTeam ], attackerName, meansOfDeath[ mod ].icon, teamTag[ ci->team ], targetName );
				}

				// nice big message for teamkills
				if ( attackerTeam == ci->team && attacker == cg.clientNum )
				{
					CG_CenterPrint( va( _("You killed ^1TEAMMATE^7 %s"), targetName ),
							SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
				}
			}
		}
	}
	else // Long form
	{
		is_long_kill_message: // <- use of this label == needs a kill icon

		// Messages which contain no killer name
		switch ( mod )
		{
			// Environmental kills

			case MOD_FALLING:
				message = G_( "%s%s ^7fell to death\n" );
				break;

			case MOD_CRUSH:
				message = G_( "%s%s ^7was crushed to death\n" );
				break;

			case MOD_WATER:
				message = G_( "%s%s ^7drowned\n" );
				break;

			case MOD_SLIME:
				message = G_( "%s%s ^7melted\n" );
				break;

			case MOD_LAVA:
				message = G_( "%s%s ^7took a dip in some lava\n" );
				break;

			case MOD_TRIGGER_HURT:
				message = G_( "%s%s ^7was in the wrong place\n" );
				break;

			// Building explosions

			case MOD_HSPAWN:
				message = G_( "%s%s ^7was caught in the explosion\n" );
				break;

			case MOD_ASPAWN:
				message = G_( "%s%s ^7was caught in the acid\n" );
				break;

			// Attacked by a building

			case MOD_MGTURRET:
				message = G_( "%s%s ^7was gunned down by a turret\n" );
				messageAssisted = G_( "%s%s ^7was gunned down by a turret; %s%s^7 assisted\n" );
				break;

			case MOD_ROCKETPOD:
				message = G_( "%s%s ^7caught a rocket\n" );
				messageAssisted = G_( "%s%s ^7caught a rocket; %s%s^7 assisted\n" );
				break;

			case MOD_ATUBE:
				message = G_( "%s%s ^7was melted by an acid tube\n" );
				messageAssisted = G_( "%s%s ^7was melted by an acid tube; %s%s^7 assisted\n" );
				break;

			case MOD_SPIKER:
				message = G_( "%s%s ^7was flechetted by a spiker\n" );
				messageAssisted = G_( "%s%s ^7was flechetted by a spiker; %s%s^7 assisted\n" );
				break;

			case MOD_OVERMIND:
				message = G_( "%s%s ^7was whipped by the overmind\n" );
				messageAssisted = G_( "%s%s ^7was whipped by the overmind; %s%s^7 assisted\n" );
				break;

			case MOD_REACTOR:
				message = G_( "%s%s ^7was fried by the reactor\n" );
				messageAssisted = G_( "%s%s ^7was fried by the reactor; %s%s^7 assisted\n" );
				break;

			case MOD_SLOWBLOB:
				message = G_( "%s%s ^7couldn't avoid the granger\n" );
				messageAssisted = G_( "%s%s ^7couldn't avoid the granger; %s%s^7 assisted\n" );
				break;

			case MOD_SWARM:
				message = G_( "%s%s ^7was consumed by the swarm\n" );
				messageAssisted = G_( "%s%s ^7was consumed by the swarm; %s%s^7 assisted\n" );
				break;

			// Shouldn't happen

			case MOD_TARGET_LASER:
				message = G_( "%s%s ^7saw the light\n" );
				messageAssisted = G_( "%s%s ^7saw the light; %s%s^7 assisted\n" );
				break;

			default:
				message = nullptr;
				break;
		}

		if ( message )
		{
			if ( messageAssisted && assistantInfo )
			{
				CG_Printf( messageAssisted, teamTag[ ci->team ], targetName , teamTag[ assistantTeam ], assistantName);
			}
			else
			{
				CG_Printf( message, teamTag[ ci->team ], targetName );
			}

			return;
		}

		// Messages which contain the killer's name
		switch ( mod )
		{
			case MOD_PAINSAW:
				message = G_( "%s%s ^7was sawn by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was sawn by %s%s^7; %s%s^7 assisted\n" );
				break;

			case MOD_BLASTER:
				message = G_( "%s%s ^7was blasted by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was blasted by %s%s^7; %s%s^7 assisted\n" );
				break;

			case MOD_MACHINEGUN:
				message = G_( "%s%s ^7was machinegunned by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was machinegunned by %s%s^7; %s%s^7 assisted\n" );
				break;

			case MOD_CHAINGUN:
				message = G_( "%s%s ^7was mowed down by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was mowed down by %s%s^7; %s%s^7 assisted\n" );
				break;

			case MOD_SHOTGUN:
				message = G_( "%s%s ^7was gunned down by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was gunned down by %s%s^7; %s%s^7 assisted\n" );
				break;

			case MOD_PRIFLE:
				message = G_( "%s%s ^7was seared by %s%s^7's pulse blast\n" );
				messageAssisted = G_( "%s%s ^7was seared by %s%s^7's pulse blast; %s%s^7 assisted\n" );
				break;

			case MOD_MDRIVER:
				message = G_( "%s%s ^7was sniped by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was sniped by %s%s^7; %s%s^7 assisted\n" );
				break;

			case MOD_LASGUN:
				message = G_( "%s%s ^7was lasered by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was lasered by %s%s^7; %s%s^7 assisted\n" );
				break;

			case MOD_FLAMER:
			case MOD_FLAMER_SPLASH:
				message = G_( "%s%s ^7was grilled by %s%s^7's flame\n" );
				messageAssisted = G_( "%s%s ^7was grilled by %s%s^7's flame; %s%s^7 assisted\n" );
				messageSuicide = G_( "%s%s ^7was charred to a crisp" );
				break;

			case MOD_BURN:
				message = G_( "%s%s ^7was burned by %s%s^7's fire\n" );
				messageAssisted = G_( "%s%s ^7was burned by %s%s^7's fire; %s%s^7 assisted\n" );
				messageSuicide = G_( "%s%s ^7was burned to death" );
				break;

			case MOD_LCANNON:
				message = G_( "%s%s ^7was annihilated by %s%s^7's plasma blast\n" );
				messageAssisted = G_( "%s%s ^7was annihilated by %s%s^7's plasma blast; %s%s^7 assisted\n" );
				break;

			case MOD_LCANNON_SPLASH:
				message = G_( "%s%s ^7was irradiated by %s%s^7's plasma blast\n" );
				messageAssisted = G_( "%s%s ^7was irradiated by %s%s^7's plasma blast; %s%s^7 assisted\n" );
				messageSuicide = G_( "%s%s ^7was irradiated" );
				break;

			case MOD_GRENADE:
				message = G_( "%s%s ^7was blown up by %s%s^7's grenade\n" );
				messageAssisted = G_( "%s%s ^7was blown up by %s%s^7's grenade; %s%s^7 assisted\n" );
				messageSuicide = G_( "%s%s ^7was blown up" );
				break;

			case MOD_FIREBOMB:
				message = G_( "%s%s ^7was incinerated by %s%s^7's firebomb\n" );
				messageAssisted = G_( "%s%s ^7was incinerated by %s%s^7's firebomb; %s%s^7 assisted\n" );
				messageSuicide = G_( "%s%s ^7was incinerated" );
				break;

			case MOD_ABUILDER_CLAW:
				message = G_( "%s%s ^7was gently nibbled by %s%s^7's granger\n" );
				messageAssisted = G_( "%s%s ^7was gently nibbled by %s%s^7's granger; %s%s^7 assisted\n" );
				break;

			case MOD_LEVEL0_BITE:
				message = G_( "%s%s ^7was bitten by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was bitten by %s%s^7; %s%s^7 assisted\n" );
				break;

			case MOD_LEVEL1_CLAW:
				message = G_( "%s%s ^7was sliced by %s%s^7's %s\n" );
				messageAssisted = G_( "%s%s ^7was sliced by %s%s^7's %s^7; %s%s^7 assisted\n" );
				attackerClass = PCL_ALIEN_LEVEL1;
				break;

			case MOD_LEVEL2_CLAW:
				message = G_( "%s%s ^7was shredded by %s%s^7's %s\n" );
				messageAssisted = G_( "%s%s ^7was shredded by %s%s^7's %s^7; %s%s^7 assisted\n" );
				attackerClass = PCL_ALIEN_LEVEL2;
				break;

			case MOD_LEVEL2_ZAP:
				message = G_( "%s%s ^7was electrocuted by %s%s^7's %s\n" );
				messageAssisted = G_( "%s%s ^7was electrocuted by %s%s^7's %s^7; %s%s^7 assisted\n" );
				attackerClass = PCL_ALIEN_LEVEL2;
				break;

			case MOD_LEVEL3_CLAW:
				message = G_( "%s%s ^7was chomped by %s%s^7's %s\n" );
				messageAssisted = G_( "%s%s ^7was chomped by %s%s^7's %s^7; %s%s^7 assisted\n" );
				attackerClass = PCL_ALIEN_LEVEL3;
				break;

			case MOD_LEVEL3_POUNCE:
				message = G_( "%s%s ^7was pounced upon by %s%s^7's %s\n" );
				messageAssisted = G_( "%s%s ^7was pounced upon by %s%s^7's %s^7; %s%s^7 assisted\n" );
				attackerClass = PCL_ALIEN_LEVEL3;
				break;

			case MOD_LEVEL3_BOUNCEBALL:
				message = G_( "%s%s ^7was barbed by %s%s^7's %s\n" );
				messageAssisted = G_( "%s%s ^7was barbed by %s%s^7's %s^7; %s%s^7 assisted\n" );
				messageSuicide = G_( "%s%s ^7was barbed" );
				attackerClass = PCL_ALIEN_LEVEL3;
				break;

			case MOD_LEVEL4_CLAW:
				message = G_( "%s%s ^7was mauled by %s%s^7's %s\n" );
				messageAssisted = G_( "%s%s ^7was mauled by %s%s^7's %s^7; %s%s^7 assisted\n" );
				attackerClass = PCL_ALIEN_LEVEL4;
				break;

			case MOD_LEVEL4_TRAMPLE:
				message = G_( "%s%s ^7should have gotten out of the way of %s%s^7's %s\n" );
				messageAssisted = G_( "%s%s ^7should have gotten out of the way of %s%s^7's %s^7; %s%s^7 assisted\n" );
				attackerClass = PCL_ALIEN_LEVEL4;
				break;

			case MOD_WEIGHT_H:
			case MOD_WEIGHT_A:
				message = G_( "%s%s ^7was crushed under %s%s^7's weight\n" );
				messageAssisted = G_( "%s%s ^7was crushed under %s%s^7's weight; %s%s^7 assisted\n" );
				break;

			case MOD_POISON:
				message = G_( "%s%s ^7should have used a medkit against %s%s^7's poison\n" );
				messageAssisted = G_( "%s%s ^7should have used a medkit against %s%s^7's poison; %s%s^7 assisted\n" );
				break;

			case MOD_TELEFRAG:
				message = G_( "%s%s ^7tried to invade %s%s^7's personal space\n" );
				break;

			default:
				message = G_( "%s%s ^7was killed by %s%s\n" );
				messageAssisted = G_( "%s%s ^7was killed by %s%s^7 and %s%s\n" );
				messageSuicide = G_( "%s%s ^7committed suicide\n" );
				break;
		}

		if ( message )
		{
			// shouldn't need to do this here, but it avoids
			char attackerClassName[ 64 ];

			if ( attackerClass == -1 )
			{
				*attackerClassName = 0;
			}
			else
			{
				Q_strncpyz( attackerClassName, _( BG_ClassModelConfig( attackerClass )->humanName ), sizeof( attackerClassName ) );
			}

			// Argument order: victim, attacker, [class,] [assistant]. Each has team tag first.
			if ( messageSuicide && attacker == target )
			{
				CG_Printf( messageSuicide, teamTag[ ci->team ], targetName );
			}
			else if ( messageAssisted && assistantInfo )
			{
				if ( attackerClass != -1 )
				{
					CG_Printf( messageAssisted, teamTag[ ci->team ], targetName, teamTag[ attackerTeam ], attackerName, attackerClassName, teamTag[ assistantTeam ], assistantName );
				}
				else
				{
					CG_Printf( messageAssisted, teamTag[ ci->team ], targetName, teamTag[ attackerTeam ], attackerName, teamTag[ assistantTeam ], assistantName );
				}
			}
			else
			{
				CG_Printf( message, teamTag[ ci->team ], targetName, teamTag[ attackerTeam ], attackerName, attackerClassName );
			}

			if ( attackerTeam == ci->team && attacker == cg.clientNum && attacker != target )
			{
				CG_CenterPrint( va( _("You killed ^1TEAMMATE^7 %s"), targetName ),
						SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
			}

			return;
		}

		// we don't know what it was
		CG_Printf( G_( "%s%s^7 died\n" ), teamTag[ ci->team ], targetName );
	}
}
Пример #9
0
/*
==============
CG_Menu
==============
*/
void CG_Menu( int menuType, int arg )
{
    int          menu = -1; // Menu to open
    const char   *longMsg = nullptr; // command parameter
    const char   *shortMsg = nullptr; // non-modal version of message

    switch ( menuType )
    {
    case MN_WELCOME:
        break;

    case MN_TEAM:
        menu = ROCKETMENU_TEAMSELECT;
        break;

    case MN_A_CLASS:
        menu = ROCKETMENU_ALIENSPAWN;
        break;

    case MN_H_SPAWN:
        menu = ROCKETMENU_HUMANSPAWN;
        break;

    case MN_A_BUILD:
        menu = ROCKETMENU_ALIENBUILD;
        break;

    case MN_H_BUILD:
        menu = ROCKETMENU_HUMANBUILD;
        break;

    case MN_H_ARMOURY:
        menu = ROCKETMENU_ARMOURYBUY;
        break;

    case MN_H_UNKNOWNITEM:
        shortMsg = "Unknown item";
        break;

    case MN_A_TEAMFULL:
        longMsg = _("The alien team has too many players. Please wait until slots "
                    "become available or join the human team.");
        shortMsg = _("The alien team has too many players");
        break;

    case MN_H_TEAMFULL:
        longMsg = _("The human team has too many players. Please wait until slots "
                    "become available or join the alien team.");
        shortMsg = _("The human team has too many players");
        break;

    case MN_A_TEAMLOCKED:
        longMsg = _("The alien team is locked. You cannot join the aliens "
                    "at this time.");
        shortMsg = _("The alien team is locked");
        break;

    case MN_H_TEAMLOCKED:
        longMsg = _("The human team is locked. You cannot join the humans "
                    "at this time.");
        shortMsg = _("The human team is locked");
        break;

    case MN_PLAYERLIMIT:
        longMsg = _("The maximum number of playing clients has been reached. "
                    "Please wait until slots become available.");
        shortMsg = _("No free player slots");
        break;

    case MN_WARMUP:
        longMsg = _("You must wait until the warmup time is finished "
                    "before joining a team. ");
        shortMsg = _("You cannot join a team during warmup.");
        break;

    //===============================

    case MN_CMD_CHEAT:
        //longMsg   = "This action is considered cheating. It can only be used "
        //            "in cheat mode, which is not enabled on this server.";
        shortMsg = _("Cheats are not enabled on this server");
        break;

    case MN_CMD_CHEAT_TEAM:
        shortMsg = _("Cheats are not enabled on this server, so "
                     "you may not use this command while on a team");
        break;

    case MN_CMD_TEAM:
        //longMsg   = "You must be on a team to perform this action. Join the alien"
        //            "or human team and try again.";
        shortMsg = _("Join a team first");
        break;

    case MN_CMD_SPEC:
        //longMsg   = "You may not perform this action while on a team. Become a "
        //            "spectator before trying again.";
        shortMsg = _("You can only use this command when spectating");
        break;

    case MN_CMD_ALIEN:
        //longMsg   = "You must be on the alien team to perform this action.";
        shortMsg = _("Must be alien to use this command");
        break;

    case MN_CMD_HUMAN:
        //longMsg   = "You must be on the human team to perform this action.";
        shortMsg = _("Must be human to use this command");
        break;

    case MN_CMD_ALIVE:
        //longMsg   = "You must be alive to perform this action.";
        shortMsg = _("Must be alive to use this command");
        break;

    //===============================

    case MN_B_NOROOM:
        longMsg = _("There is no room to build here. Move until the structure turns "
                    "translucent green, indicating a valid build location.");
        shortMsg = _("There is no room to build here");
        break;

    case MN_B_NORMAL:
        longMsg = _("Cannot build on this surface. The surface is too steep or "
                    "unsuitable for building. Please choose another site for this "
                    "structure.");
        shortMsg = _("Cannot build on this surface");
        break;

    case MN_B_CANNOT:
        longMsg = nullptr;
        shortMsg = _("You cannot build that structure");
        break;

    case MN_B_LASTSPAWN:
        longMsg = _("This action would remove your team's last spawn point, "
                    "which often quickly results in a loss. Try building more "
                    "spawns.");
        shortMsg = _("You may not deconstruct the last spawn");
        break;

    case MN_B_MAINSTRUCTURE:
        longMsg = _("The main structure is protected against instant removal. "
                    "When it is marked, you can move it to another place by "
                    "building it there.");
        shortMsg = _("You may not deconstruct this structure");
        break;

    case MN_B_DISABLED:
        longMsg = _("Building has been disabled on the server for your team.");
        shortMsg = _("Building has been disabled for your team");
        break;

    case MN_B_REVOKED:
        longMsg = _("Your teammates have lost faith in your ability to build "
                    "for the team. You will not be allowed to build until your "
                    "team votes to reinstate your building rights.");
        shortMsg = _("Your building rights have been revoked");
        break;

    case MN_B_SURRENDER:
        longMsg = _("Your team has decided to admit defeat and concede the game: "
                    "There's no point in building anything anymore.");
        shortMsg = _("Cannot build after admitting defeat");
        break;

    case MN_H_NOBP:
        longMsg = _("There are no resources remaining. Free up resources by "
                    "marking existing buildables for deconstruction.");
        shortMsg = _("There are no resources remaining");
        break;

    case MN_H_NOTPOWERED:
        longMsg = _("This buildable is not powered. Build a Reactor and/or Repeater "
                    "in order to power it.");
        shortMsg = _("This buildable is not powered");
        break;

    case MN_H_NOPOWERHERE:
        longMsg = _("There is not enough power in this area. Keep a distance to other "
                    "buildables or build a repeater to increase the local capacity.");
        shortMsg = _("There is not enough power here");
        break;

    case MN_H_NOREACTOR:
        longMsg = _("There is no reactor and the local power supply is insufficient. "
                    "Build the reactor or a repeater to increase the local capacity.");
        shortMsg = _("There is no reactor and the local power supply is insufficient");
        break;

    case MN_H_ONEREACTOR:
        longMsg = _("There can only be one Reactor. Mark the existing one if you "
                    "wish to move it.");
        shortMsg = _("There can only be one Reactor");
        break;

    case MN_H_NOSLOTS:
        longMsg = _("You have no room to carry this. Please sell any conflicting "
                    "upgrades before purchasing this item.");
        shortMsg = _("You have no room to carry this");
        break;

    case MN_H_NOFUNDS:
        longMsg = _("Insufficient funds. You do not have enough credits to perform "
                    "this action.");
        shortMsg = _("Insufficient funds");
        break;

    case MN_H_ITEMHELD:
        longMsg = _("You already hold this item. It is not possible to carry multiple "
                    "items of the same type.");
        shortMsg = _("You already hold this item");
        break;

    case MN_H_NOARMOURYHERE:
        longMsg = _("You must be near a powered Armoury in order to purchase "
                    "weapons, upgrades or ammunition.");
        shortMsg = _("You must be near a powered Armoury");
        break;

    case MN_H_NOENERGYAMMOHERE:
        longMsg = _("You must be near a Reactor or a powered Armoury or Repeater "
                    "in order to purchase energy ammunition.");
        shortMsg = _("You must be near a Reactor or a powered Armoury or Repeater");
        break;

    case MN_H_NOROOMARMOURCHANGE:
        longMsg = _("There is not enough room here to change armour.");
        shortMsg = _("Not enough room here to change armour.");
        break;

    case MN_H_ARMOURYBUILDTIMER:
        longMsg = _("You are not allowed to buy or sell weapons until your "
                    "build timer has expired.");
        shortMsg = _("You can not buy or sell weapons until your build timer "
                     "expires");
        break;

    case MN_H_DEADTOCLASS:
        shortMsg = _("You must be dead to use the class command");
        break;

    case MN_H_UNKNOWNSPAWNITEM:
        shortMsg = _("Unknown starting item");
        break;

    //===============================

    case MN_A_NOCREEP:
        longMsg = _("There is no creep here. You must build near existing Eggs or "
                    "the Overmind. Alien structures will not support themselves.");
        shortMsg = _("There is no creep here");
        break;

    case MN_A_NOOVMND:
        longMsg = _("There is no Overmind. An Overmind must be built to control "
                    "the structure you tried to place.");
        shortMsg = _("There is no Overmind");
        break;

    case MN_A_ONEOVERMIND:
        longMsg = _("There can only be one Overmind. Deconstruct the existing one if you "
                    "wish to move it.");
        shortMsg = _("There can only be one Overmind");
        break;

    case MN_A_NOBP:
        longMsg = _("The Overmind cannot control any more structures. Deconstruct existing "
                    "structures to build more.");
        shortMsg = _("The Overmind cannot control any more structures");
        break;

    case MN_A_NOEROOM:
        longMsg = _("There is no room to evolve here. Move away from walls or other "
                    "nearby objects and try again.");
        shortMsg = _("There is no room to evolve here");
        break;

    case MN_A_TOOCLOSE:
        longMsg = _("This location is too close to the enemy to evolve. Move away "
                    "from the enemy's presence and try again.");
        shortMsg = _("This location is too close to the enemy to evolve");
        break;

    case MN_A_NOOVMND_EVOLVE:
        longMsg = _("There is no Overmind. An Overmind must be built to allow "
                    "you to upgrade.");
        shortMsg = _("There is no Overmind");
        break;

    case MN_A_EVOLVEBUILDTIMER:
        longMsg = _("You cannot evolve until your build timer has expired.");
        shortMsg = _("You cannot evolve until your build timer expires");
        break;

    case MN_A_INFEST:
        trap_Cvar_Set( "ui_currentClass",
                       va( "%d %d", cg.snap->ps.stats[ STAT_CLASS ],
                           cg.snap->ps.persistant[ PERS_CREDIT ] ) );

        menu = ROCKETMENU_ALIENEVOLVE;
        break;

    case MN_A_CANTEVOLVE:
        shortMsg = va( _("You cannot evolve into a %s"),
                       _( BG_ClassModelConfig( arg )->humanName ) );
        break;

    case MN_A_EVOLVEWALLWALK:
        shortMsg = _("You cannot evolve while wallwalking");
        break;

    case MN_A_UNKNOWNCLASS:
        shortMsg = _("Unknown class");
        break;

    case MN_A_CLASSNOTSPAWN:
        shortMsg = va( _("You cannot spawn as a %s"),
                       _( BG_ClassModelConfig( arg )->humanName ) );
        break;

    case MN_A_CLASSNOTALLOWED:
        shortMsg = va( _("The %s is not allowed"),
                       _( BG_ClassModelConfig( arg )->humanName ) );
        break;

    case MN_A_CLASSLOCKED:
        shortMsg = va( _("The %s has not been unlocked yet"),
                       _( BG_ClassModelConfig( arg )->humanName ) );
        break;

    default:
        Com_Printf(_( "cgame: debug: no such menu %d\n"), menu );
    }

    if ( menu > 0 )
    {
        Rocket_DocumentAction( rocketInfo.menu[ menu ].id, "show" );
    }
    else if ( longMsg && cg_disableWarningDialogs.integer == 0 )
    {
        CG_CenterPrint( longMsg, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );

        if ( shortMsg && cg_disableWarningDialogs.integer < 2 )
        {
            CG_Printf( "%s\n", shortMsg );
        }
    }
    else if ( shortMsg && cg_disableWarningDialogs.integer < 2 )
    {
        CG_Printf( "%s\n", shortMsg );
    }
}
Пример #10
0
/*
==============
CG_Menu
==============
*/
void CG_Menu( int menu, int arg )
{
    const char   *cmd; // command to send
    const char   *longMsg = NULL; // command parameter
    const char   *shortMsg = NULL; // non-modal version of message
    const char   *dialog;
    dialogType_t type = 0; // controls which cg_disable var will switch it off

    switch ( cg.snap->ps.stats[ STAT_TEAM ] )
    {
    case TEAM_ALIENS:
        dialog = "menu tremulous_alien_dialog\n";
        break;

    case TEAM_HUMANS:
        dialog = "menu tremulous_human_dialog\n";
        break;

    default:
        dialog = "menu tremulous_default_dialog\n";
    }

    cmd = dialog;

    switch ( menu )
    {
    case MN_TEAM:
        cmd = "menu tremulous_teamselect\n";
        type = DT_INTERACTIVE;
        break;

    case MN_A_CLASS:
        cmd = "menu tremulous_alienclass\n";
        type = DT_INTERACTIVE;
        break;

    case MN_H_SPAWN:
        cmd = "menu tremulous_humanitem\n";
        type = DT_INTERACTIVE;
        break;

    case MN_A_BUILD:
        cmd = "menu tremulous_alienbuild\n";
        type = DT_INTERACTIVE;
        break;

    case MN_H_BUILD:
        cmd = "menu tremulous_humanbuild\n";
        type = DT_INTERACTIVE;
        break;

    case MN_H_ARMOURY:
        cmd = "menu tremulous_humanarmoury\n";
        type = DT_INTERACTIVE;
        break;

    case MN_H_UNKNOWNITEM:
        shortMsg = "Unknown item";
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_TEAMFULL:
        longMsg = _("The alien team has too many players. Please wait until slots "
                    "become available or join the human team.");
        shortMsg = _("The alien team has too many players");
        type = DT_COMMAND;
        break;

    case MN_H_TEAMFULL:
        longMsg = _("The human team has too many players. Please wait until slots "
                    "become available or join the alien team.");
        shortMsg = _("The human team has too many players");
        type = DT_COMMAND;
        break;

    case MN_A_TEAMLOCKED:
        longMsg = _("The alien team is locked. You cannot join the aliens "
                    "at this time.");
        shortMsg = _("The alien team is locked");
        type = DT_COMMAND;
        break;

    case MN_H_TEAMLOCKED:
        longMsg = _("The human team is locked. You cannot join the humans "
                    "at this time.");
        shortMsg = _("The human team is locked");
        type = DT_COMMAND;
        break;

    case MN_PLAYERLIMIT:
        longMsg = _("The maximum number of playing clients has been reached. "
                    "Please wait until slots become available.");
        shortMsg = _("No free player slots");
        type = DT_COMMAND;
        break;

    case MN_WARMUP:
        longMsg = _("You must wait until the warmup time is finished "
                    "before joining a team. ");
        shortMsg = _("You cannot join a team during warmup.");
        type = DT_COMMAND;
        break;

    //===============================

    // Since cheating commands have no default binds, they will often be done
    // via console. In light of this, perhaps opening a menu is
    // counterintuitive
    case MN_CMD_CHEAT:
        //longMsg   = "This action is considered cheating. It can only be used "
        //            "in cheat mode, which is not enabled on this server.";
        shortMsg = _("Cheats are not enabled on this server");
        type = DT_COMMAND;
        break;

    case MN_CMD_CHEAT_TEAM:
        shortMsg = _("Cheats are not enabled on this server, so "
                     "you may not use this command while on a team");
        type = DT_COMMAND;
        break;

    case MN_CMD_TEAM:
        //longMsg   = "You must be on a team to perform this action. Join the alien"
        //            "or human team and try again.";
        shortMsg = _("Join a team first");
        type = DT_COMMAND;
        break;

    case MN_CMD_SPEC:
        //longMsg   = "You may not perform this action while on a team. Become a "
        //            "spectator before trying again.";
        shortMsg = _("You can only use this command when spectating");
        type = DT_COMMAND;
        break;

    case MN_CMD_ALIEN:
        //longMsg   = "You must be on the alien team to perform this action.";
        shortMsg = _("Must be alien to use this command");
        type = DT_COMMAND;
        break;

    case MN_CMD_HUMAN:
        //longMsg   = "You must be on the human team to perform this action.";
        shortMsg = _("Must be human to use this command");
        type = DT_COMMAND;
        break;

    case MN_CMD_ALIVE:
        //longMsg   = "You must be alive to perform this action.";
        shortMsg = _("Must be alive to use this command");
        type = DT_COMMAND;
        break;

    //===============================

    case MN_B_NOROOM:
        longMsg = _("There is no room to build here. Move until the structure turns "
                    "translucent green, indicating a valid build location.");
        shortMsg = _("There is no room to build here");
        type = DT_BUILD;
        break;

    case MN_B_NORMAL:
        longMsg = _("Cannot build on this surface. The surface is too steep or "
                    "unsuitable for building. Please choose another site for this "
                    "structure.");
        shortMsg = _("Cannot build on this surface");
        type = DT_BUILD;
        break;

    case MN_B_CANNOT:
        longMsg = NULL;
        shortMsg = _("You cannot build that structure");
        type = DT_BUILD;
        break;

    // FIXME: MN_H_ and MN_A_?
    case MN_B_LASTSPAWN:
        longMsg = _("This action would remove your team's last spawn point, "
                    "which often quickly results in a loss. Try building more "
                    "spawns.");
        shortMsg = _("You may not deconstruct the last spawn");
        type = DT_MISC_CP;
        break;

    case MN_B_SUDDENDEATH:
        longMsg = _("Neither team has prevailed after a certain time and the "
                    "game has entered Sudden Death. During Sudden Death "
                    "building is not allowed.");
        shortMsg = _("Cannot build during Sudden Death");
        type = DT_BUILD;
        break;

    case MN_B_REVOKED:
        longMsg = _("Your teammates have lost faith in your ability to build "
                    "for the team. You will not be allowed to build until your "
                    "team votes to reinstate your building rights.");
        shortMsg = _("Your building rights have been revoked");
        type = DT_BUILD;
        break;

    case MN_B_SURRENDER:
        longMsg = _("Your team has decided to admit defeat and concede the game:"
                    "traitors and cowards are not allowed to build.");
        // too harsh?
        shortMsg = _("Building is denied to traitorous cowards");
        type = DT_MISC_CP;
        break;

    //===============================

    case MN_H_NOBP:
        if ( cgs.markDeconstruct )
        {
            longMsg = _("There is no power remaining. Free up power by marking "
                        "existing buildable objects.");
        }
        else
        {
            longMsg = _("There is no power remaining. Free up power by deconstructing "
                        "existing buildable objects.");
        }

        shortMsg = _("There is no power remaining");
        type = DT_BUILD;
        break;

    case MN_H_NOTPOWERED:
        longMsg = _("This buildable is not powered. Build a Reactor and/or Repeater "
                    "in order to power it.");
        shortMsg = _("This buildable is not powered");
        type = DT_BUILD;
        break;

    case MN_H_ONEREACTOR:
        longMsg = _("There can only be one Reactor. Deconstruct the existing one if you "
                    "wish to move it.");
        shortMsg = _("There can only be one Reactor");
        type = DT_BUILD;
        break;

    case MN_H_NOPOWERHERE:
        longMsg = _("There is no power here. If available, a Repeater may be used to "
                    "transmit power to this location.");
        shortMsg = _("There is no power here");
        type = DT_BUILD;
        break;

    case MN_H_NODCC:
        longMsg = _("There is no Defense Computer. A Defense Computer is needed to "
                    "build this.");
        shortMsg = _("There is no Defense Computer");
        type = DT_BUILD;
        break;

    case MN_H_RPTPOWERHERE:
        longMsg = _("This area already has power. A Repeater is not required here.");
        shortMsg = _("This area already has power");
        type = DT_BUILD;
        break;

    case MN_H_NOSLOTS:
        longMsg = _("You have no room to carry this. Please sell any conflicting "
                    "upgrades before purchasing this item.");
        shortMsg = _("You have no room to carry this");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_H_NOFUNDS:
        longMsg = _("Insufficient funds. You do not have enough credits to perform "
                    "this action.");
        shortMsg = _("Insufficient funds");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_H_ITEMHELD:
        longMsg = _("You already hold this item. It is not possible to carry multiple "
                    "items of the same type.");
        shortMsg = _("You already hold this item");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_H_NOARMOURYHERE:
        longMsg = _("You must be near a powered Armoury in order to purchase "
                    "weapons, upgrades or ammunition.");
        shortMsg = _("You must be near a powered Armoury");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_H_NOENERGYAMMOHERE:
        longMsg = _("You must be near a Reactor or a powered Armoury or Repeater "
                    "in order to purchase energy ammunition.");
        shortMsg = _("You must be near a Reactor or a powered Armoury or Repeater");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_H_NOROOMBSUITON:
        longMsg = _("There is not enough room here to put on a Battle Suit. "
                    "Make sure you have enough head room to climb in.");
        shortMsg = _("Not enough room here to put on a Battle Suit");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_H_NOROOMBSUITOFF:
        longMsg = _("There is not enough room here to take off your Battle Suit. "
                    "Make sure you have enough head room to climb out.");
        shortMsg = _("Not enough room here to take off your Battle Suit");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_H_ARMOURYBUILDTIMER:
        longMsg = _("You are not allowed to buy or sell weapons until your "
                    "build timer has expired.");
        shortMsg = _("You can not buy or sell weapons until your build timer "
                     "expires");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_H_DEADTOCLASS:
        shortMsg = _("You must be dead to use the class command");
        type = DT_COMMAND;
        break;

    case MN_H_UNKNOWNSPAWNITEM:
        shortMsg = _("Unknown starting item");
        type = DT_COMMAND;
        break;

    //===============================

    case MN_A_NOCREEP:
        longMsg = _("There is no creep here. You must build near existing Eggs or "
                    "the Overmind. Alien structures will not support themselves.");
        shortMsg = _("There is no creep here");
        type = DT_BUILD;
        break;

    case MN_A_NOOVMND:
        longMsg = _("There is no Overmind. An Overmind must be built to control "
                    "the structure you tried to place.");
        shortMsg = _("There is no Overmind");
        type = DT_BUILD;
        break;

    case MN_A_ONEOVERMIND:
        longMsg = _("There can only be one Overmind. Deconstruct the existing one if you "
                    "wish to move it.");
        shortMsg = _("There can only be one Overmind");
        type = DT_BUILD;
        break;

    case MN_A_NOBP:
        longMsg = _("The Overmind cannot control any more structures. Deconstruct existing "
                    "structures to build more.");
        shortMsg = _("The Overmind cannot control any more structures");
        type = DT_BUILD;
        break;

    case MN_A_NOEROOM:
        longMsg = _("There is no room to evolve here. Move away from walls or other "
                    "nearby objects and try again.");
        shortMsg = _("There is no room to evolve here");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_TOOCLOSE:
        longMsg = _("This location is too close to the enemy to evolve. Move away "
                    "from the enemy's presence and try again.");
        shortMsg = _("This location is too close to the enemy to evolve");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_NOOVMND_EVOLVE:
        longMsg = _("There is no Overmind. An Overmind must be built to allow "
                    "you to upgrade.");
        shortMsg = _("There is no Overmind");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_EVOLVEBUILDTIMER:
        longMsg = _("You cannot evolve until your build timer has expired.");
        shortMsg = _("You cannot evolve until your build timer expires");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_INFEST:
        trap_Cvar_Set( "ui_currentClass",
                       va( "%d %d", cg.snap->ps.stats[ STAT_CLASS ],
                           cg.snap->ps.persistant[ PERS_CREDIT ] ) );

        cmd = "menu tremulous_alienupgrade\n";
        type = DT_INTERACTIVE;
        break;

    case MN_A_CANTEVOLVE:
        shortMsg = va( _("You cannot evolve into a %s"),
                       _( BG_ClassModelConfig( arg )->humanName ) );
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_EVOLVEWALLWALK:
        shortMsg = _("You cannot evolve while wallwalking");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_UNKNOWNCLASS:
        shortMsg = _("Unknown class");
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_CLASSNOTSPAWN:
        shortMsg = va( _("You cannot spawn as a %s"),
                       _( BG_ClassModelConfig( arg )->humanName ) );
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_CLASSNOTALLOWED:
        shortMsg = va( _("The %s is not allowed"),
                       _( BG_ClassModelConfig( arg )->humanName ) );
        type = DT_ARMOURYEVOLVE;
        break;

    case MN_A_CLASSNOTATSTAGE:
        shortMsg = va( _("The %s is not allowed at Stage %d"),
                       _( BG_ClassModelConfig( arg )->humanName ),
                       cgs.alienStage + 1 );
        type = DT_ARMOURYEVOLVE;
        break;

    default:
        Com_Printf(_( "cgame: debug: no such menu %d\n"), menu );
    }

    switch ( type )
    {
    case DT_BUILD:
    case DT_ARMOURYEVOLVE:
    case DT_MISC_CP:
        // menu open? we need to use the modal dbox
        // menu closed? we want to centre print
        if ( !trap_Cvar_VariableIntegerValue( "ui_menuIsOpen" ) )
        {
            cmd = NULL;
            // only a short message? make the long message the same
            longMsg = longMsg ? longMsg : shortMsg;
        }
    default:
        break;
    }

    if ( type == DT_ARMOURYEVOLVE && cg_disableUpgradeDialogs.integer )
    {
        return;
    }

    if ( type == DT_BUILD && cg_disableBuildDialogs.integer )
    {
        return;
    }

    if ( type == DT_COMMAND && cg_disableCommandDialogs.integer )
    {
        return;
    }

    if ( cmd && cmd != dialog )
    {
        trap_SendConsoleCommand( cmd );
    }
    else if ( longMsg && cg_disableWarningDialogs.integer == 0 )
    {
        if ( cmd )
        {
            trap_Cvar_Set( "ui_dialog", longMsg );
            trap_SendConsoleCommand( cmd );
        }
        else
        {
            CG_CenterPrint( longMsg, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );

            if ( shortMsg && cg_disableWarningDialogs.integer < 2 )
            {
                CG_Printf( "%s\n", shortMsg );
            }
        }
    }
    else if ( shortMsg && cg_disableWarningDialogs.integer < 2 )
    {
        CG_Printf( "%s\n", shortMsg );
    }
}
Пример #11
0
/*
============
BG_VoiceParseTrack
============
*/
static qboolean BG_VoiceParseTrack( int handle, voiceTrack_t *voiceTrack )
{
	pc_token_t token;
	qboolean   found = qfalse;
	qboolean   foundText = qfalse;
	qboolean   foundToken = qfalse;

	foundToken = trap_Parse_ReadToken( handle, &token );

	while ( foundToken )
	{
		if ( token.string[ 0 ] == '}' )
		{
			if ( foundText )
			{
				return qtrue;
			}
			else
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): "
				                    "missing text attribute for track" );
			}
		}
		else if ( !Q_stricmp( token.string, "team" ) )
		{
			foundToken = trap_Parse_ReadToken( handle, &token );
			found = qfalse;

			while ( foundToken )
			{
				if ( voiceTrack->team < 0 )
				{
					voiceTrack->team = 0;
				}

				if ( !Q_stricmp( token.string, "humans" ) )
				{
					voiceTrack->team |= 1 << TEAM_HUMANS;
				}
				else if ( !Q_stricmp( token.string, "aliens" ) )
				{
					voiceTrack->team |= 1 << TEAM_ALIENS;
				}
				else
				{
					break;
				}

				found = qtrue;
				foundToken = trap_Parse_ReadToken( handle, &token );
			}

			if ( !found )
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): missing \"team\" name" );
			}

			continue;
		}
		else if ( !Q_stricmp( token.string, "class" ) )
		{
			qboolean negate = qfalse;

			foundToken = trap_Parse_ReadToken( handle, &token );
			found = qfalse;

			while ( foundToken )
			{
				classModelConfig_t *model;
				int                modelno = -1;

				if ( voiceTrack->pClass < 0 )
				{
					voiceTrack->pClass = 0;
				}

				if ( !Q_stricmp( token.string, "all" ) )
				{
					modelno = PCL_ALL_CLASSES;
				}
				else if ( !Q_stricmp( token.string, "humans" ) )
				{
					modelno = PCL_HUMAN_CLASSES;
				}
				else if ( !Q_stricmp( token.string, "aliens" ) )
				{
					modelno = PCL_ALIEN_CLASSES;
				}
				else if ( !Q_stricmp( token.string, "-" ) ) // this must be outside quotation marks
				{
					negate = qtrue;
					modelno = 0;
				}
				else
				{
					model = BG_ClassModelConfigByName( token.string );

					if ( model != BG_ClassModelConfigByName( NULL ) )
					{
						modelno = 1 << ( model - BG_ClassModelConfig( 0 ) );

						if ( modelno <= 1)
						{
							modelno = -1; // match failure
						}
					}

				}

				if ( modelno > 0 )
				{
					if ( negate )
					{
						negate = qfalse;
						voiceTrack->pClass &= ~modelno;
					}
					else
					{
						voiceTrack->pClass |= modelno;
					}
				}
				else if ( modelno < 0 )
				{
				        break; // possibly the next keyword
				}

				found = qtrue;
				foundToken = trap_Parse_ReadToken( handle, &token );
			}

			if ( !found )
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): missing \"class\" name" );
			}

			continue;
		}
		else if ( !Q_stricmp( token.string, "text" ) )
		{
			if ( foundText )
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): "
				                    "duplicate \"text\" definition for track" );
			}

			foundToken = trap_Parse_ReadToken( handle, &token );

			if ( !foundToken )
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): "
				                    "missing \"text\" value" );
			}

			foundText = qtrue;

			if ( strlen( token.string ) >= MAX_SAY_TEXT )
			{
				BG_VoiceParseError( handle, va( "BG_VoiceParseTrack(): "
				                                "\"text\" value " "\"%s\" exceeds MAX_SAY_TEXT length",
				                                token.string ) );
			}

			voiceTrack->text = ( char * ) BG_Alloc( strlen( token.string ) + 1 );
			Q_strncpyz( voiceTrack->text, token.string, strlen( token.string ) + 1 );
			foundToken = trap_Parse_ReadToken( handle, &token );
			continue;
		}
		else if ( !Q_stricmp( token.string, "enthusiasm" ) )
		{
			foundToken = trap_Parse_ReadToken( handle, &token );

			if ( token.type == TT_NUMBER )
			{
				voiceTrack->enthusiasm = token.intvalue;
			}
			else
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): "
				                    "missing \"enthusiasm\" value" );
			}

			foundToken = trap_Parse_ReadToken( handle, &token );
			continue;
		}
		else
		{
			BG_VoiceParseError( handle, va( "BG_VoiceParseTrack():"
			                                " unknown token \"%s\"", token.string ) );
		}
	}

	return qfalse;
}