static qboolean G_VoteSpeedcaps( gentity_t *ent, int numArgs, const char *arg1, const char *arg2 ) { int n = Q_clampi( 0, atoi( arg2 ), 1 ); Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %i", arg1, n ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); Q_strncpyz( level.voteStringClean, level.voteString, sizeof( level.voteStringClean ) ); return qtrue; }
static void CG_ParseTeamInfo( void ) { int i = 0, client = 0; //Raz: avoid crash if server sends invalid range numSortedTeamPlayers = Q_clampi( 0, atoi( CG_Argv( 1 ) ), TEAM_MAXOVERLAY ); for ( i = 0; i < numSortedTeamPlayers; i++ ) { client = Q_clampi( 0, atoi( CG_Argv( i * 6 + 2 ) ), MAX_CLIENTS ); sortedTeamPlayers[i] = client; cgs.clientinfo[client].location = atoi( CG_Argv( i * 6 + 3 ) ); cgs.clientinfo[client].health = atoi( CG_Argv( i * 6 + 4 ) ); cgs.clientinfo[client].armor = atoi( CG_Argv( i * 6 + 5 ) ); cgs.clientinfo[client].curWeapon = atoi( CG_Argv( i * 6 + 6 ) ); cgs.clientinfo[client].powerups = atoi( CG_Argv( i * 6 + 7 ) ); } }
static void CG_ParseScores( void ) { int i = 0, scoreIndex = 0, powerups = 0, readScores = 0; int scoreOffset = GetScoreOffset(); if ( Server_Supports( SSF_SCOREBOARD_LARGE ) ) readScores = Q_clampi( 0, atoi( CG_Argv( 1 ) ), MAX_CLIENTS ); else readScores = Q_clampi( 0, atoi( CG_Argv( 1 ) ), MAX_CLIENT_SCORE_SEND ); cg.numScores = readScores; cg.teamScores[0] = atoi( CG_Argv( 2 ) ); cg.teamScores[1] = atoi( CG_Argv( 3 ) ); memset( cg.scores, 0, sizeof(cg.scores) ); for ( i = 0, scoreIndex = 0; i < readScores; i++ ) { cg.scores[scoreIndex].client = atoi( CG_Argv( i * scoreOffset + 4 ) ); if ( cg.scores[scoreIndex].client < 0 || cg.scores[scoreIndex].client >= MAX_CLIENTS ) continue; cg.scores[scoreIndex].score = atoi( CG_Argv( i * scoreOffset + 5 ) ); cg.scores[scoreIndex].ping = atoi( CG_Argv( i * scoreOffset + 6 ) ); cg.scores[scoreIndex].time = atoi( CG_Argv( i * scoreOffset + 7 ) ); cg.scores[scoreIndex].scoreFlags = atoi( CG_Argv( i * scoreOffset + 8 ) ); powerups = atoi( CG_Argv( i * scoreOffset + 9 ) ); cg.scores[scoreIndex].accuracy = atoi( CG_Argv( i * scoreOffset + 10 ) ); cg.scores[scoreIndex].impressiveCount = atoi( CG_Argv( i * scoreOffset + 11 ) ); cg.scores[scoreIndex].excellentCount = atoi( CG_Argv( i * scoreOffset + 12 ) ); cg.scores[scoreIndex].gauntletCount = atoi( CG_Argv( i * scoreOffset + 13 ) ); cg.scores[scoreIndex].defendCount = atoi( CG_Argv( i * scoreOffset + 14 ) ); cg.scores[scoreIndex].assistCount = atoi( CG_Argv( i * scoreOffset + 15 ) ); cg.scores[scoreIndex].perfect = atoi( CG_Argv( i * scoreOffset + 16 ) ); cg.scores[scoreIndex].captures = atoi( CG_Argv( i * scoreOffset + 17 ) ); if ( Server_Supports( SSF_SCOREBOARD_KD ) ) cg.scores[scoreIndex].deaths = atoi( CG_Argv( i * scoreOffset + 18 ) ); cgs.clientinfo[cg.scores[scoreIndex].client].score = cg.scores[scoreIndex].score; cgs.clientinfo[cg.scores[scoreIndex].client].powerups = powerups; cg.scores[scoreIndex].team = cgs.clientinfo[cg.scores[scoreIndex].client].team; scoreIndex++; } CG_SetScoreSelection( NULL ); }
// This is called explicitly when the gamestate is first received, and whenever the server updates any serverinfo flagged cvars void CG_ParseServerinfo( void ) { const char *info = NULL, *tinfo = NULL, *mapname; int i, fraglimit, timelimit; info = CG_ConfigString( CS_SERVERINFO ); cgs.debugMelee = atoi( Info_ValueForKey( info, "g_debugMelee" ) ); cgs.stepSlideFix = atoi( Info_ValueForKey( info, "g_stepSlideFix" ) ); cgs.noSpecMove = atoi( Info_ValueForKey( info, "g_noSpecMove" ) ); cgs.siegeTeamSwitch = atoi( Info_ValueForKey( info, "g_siegeTeamSwitch" ) ); cgs.showDuelHealths = atoi( Info_ValueForKey( info, "g_showDuelHealths" ) ); cgs.needpass = atoi( Info_ValueForKey( info, "needpass" ) ); cgs.jediVmerc = atoi( Info_ValueForKey( info, "g_jediVmerc" ) ); cgs.wDisable = atoi( Info_ValueForKey( info, "wdisable" ) ); cgs.fDisable = atoi( Info_ValueForKey( info, "fdisable" ) ); cgs.dmflags = atoi( Info_ValueForKey( info, "dmflags" ) ); cgs.duel_fraglimit = atoi( Info_ValueForKey( info, "duel_fraglimit" ) ); cgs.capturelimit = atoi( Info_ValueForKey( info, "capturelimit" ) ); cgs.gametype = (gametype_t)atoi( Info_ValueForKey( info, "g_gametype" ) ); cgs.japp.jp_cinfo = atoi( Info_ValueForKey( info, "jp_cinfo" ) ); cgs.japp.overbounce = atoi( Info_ValueForKey( info, "pmove_overbounce" ) ); fraglimit = atoi( Info_ValueForKey( info, "fraglimit" ) ); timelimit = atoi( Info_ValueForKey( info, "timelimit" ) ); trap->Cvar_Set( "g_gametype", va( "%i", cgs.gametype ) ); trap->Cvar_Set( "bg_fighterAltControl", Info_ValueForKey( info, "bg_fighterAltControl" ) ); // reset fraglimit warnings if ( cgs.fraglimit < fraglimit ) cg.fraglimitWarnings &= ~(1 | 2 | 4); cgs.fraglimit = fraglimit; // reset timelimit warnings if ( cgs.timelimit != timelimit ) cg.timelimitWarnings &= ~(1 | 2); cgs.timelimit = timelimit; cgs.maxclients = Q_clampi( 0, atoi( Info_ValueForKey( info, "sv_maxclients" ) ), MAX_CLIENTS ); //Raz: Server support flags tinfo = Info_ValueForKey( info, "ssf" ); if ( !Q_stricmpn( Info_ValueForKey( info, "gamename" ), "JA+ Mod", 7 ) ) cg.japp.SSF = JAPLUS_SERVER_FLAGS; if ( tinfo[0] && sscanf( tinfo, "%X", &cg.japp.SSF ) != 1 ) CG_LogPrintf( cg.log.security, "CG_ParseServerinfo: serverinfo 'ssf' was found, but invalid.\n" ); Com_Printf( "Server support hints: 0x%X\n", cg.japp.SSF ); tinfo = Info_ValueForKey( info, "jp_gripSpeedScale" ); if ( tinfo[0] ) { cgs.japp.gripSpeed.scale = atof( tinfo ); cgs.japp.gripSpeed.set = qtrue; } else { cgs.japp.gripSpeed.set = qfalse; } mapname = Info_ValueForKey( info, "mapname" ); Q_strncpyz( cgs.mapnameClean, mapname, sizeof(cgs.mapnameClean) ); //rww - You must do this one here, Info_ValueForKey always uses the same memory pointer. trap->Cvar_Set( "ui_about_mapname", mapname ); Com_sprintf( cgs.mapname, sizeof(cgs.mapname), "maps/%s.bsp", mapname ); trap->Cvar_Set( "ui_about_gametype", va( "%i", cgs.gametype ) ); trap->Cvar_Set( "ui_about_fraglimit", va( "%i", cgs.fraglimit ) ); trap->Cvar_Set( "ui_about_duellimit", va( "%i", cgs.duel_fraglimit ) ); trap->Cvar_Set( "ui_about_capturelimit", va( "%i", cgs.capturelimit ) ); trap->Cvar_Set( "ui_about_timelimit", va( "%i", cgs.timelimit ) ); trap->Cvar_Set( "ui_about_maxclients", va( "%i", cgs.maxclients ) ); trap->Cvar_Set( "ui_about_dmflags", va( "%i", cgs.dmflags ) ); trap->Cvar_Set( "ui_about_hostname", Info_ValueForKey( info, "sv_hostname" ) ); trap->Cvar_Set( "ui_about_needpass", Info_ValueForKey( info, "g_needpass" ) ); trap->Cvar_Set( "ui_about_botminplayers", Info_ValueForKey( info, "bot_minplayers" ) ); //Set the siege teams based on what the server has for overrides. trap->Cvar_Set( "cg_siegeTeam1", Info_ValueForKey( info, "g_siegeTeam1" ) ); trap->Cvar_Set( "cg_siegeTeam2", Info_ValueForKey( info, "g_siegeTeam2" ) ); tinfo = CG_ConfigString( CS_TERRAINS + 1 ); if ( !tinfo || !*tinfo ) cg.mInRMG = qfalse; else { int weather = 0; cg.mInRMG = qtrue; trap->Cvar_Set( "RMG", "1" ); weather = atoi( Info_ValueForKey( info, "RMG_weather" ) ); trap->Cvar_Set( "RMG_weather", va( "%i", weather ) ); if ( weather == 1 || weather == 2 ) cg.mRMGWeather = qtrue; else cg.mRMGWeather = qfalse; } Q_strncpyz( cgs.japp.serverName, Info_ValueForKey( info, "sv_hostname" ), sizeof(cgs.japp.serverName) ); CPM_UpdateSettings( !!(cgs.japp.jp_cinfo & CINFO_CPMPHYSICS) ); //Fix f****d up vote strings Q_strncpyz( cgs.voteString, CG_ConfigString( CS_VOTE_STRING ), sizeof(cgs.voteString) ); //Raz: Synchronise our expected snaps/sec with the server's framerate // OpenJK servers will try to match us to the sv_fps too (sv_client.cpp -> SV_UserinfoChanged) i = atoi( Info_ValueForKey( info, "sv_fps" ) ); if ( i ) trap->Cvar_Set( "snaps", va( "%i", i ) ); }
// Add the weapon, and flash for the player's view void CG_AddViewWeapon( playerState_t *ps ) { // no gun if in third person view or a camera is active if ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR || ps->pm_type == PM_INTERMISSION || cg.renderingThirdPerson ) { return; } const int weap = cg_fakeGun.integer ? cg_fakeGun.integer : ps->weapon; float desiredFov = 0.0f; if ( !cg.renderingThirdPerson && (cg_trueGuns.integer || weap == WP_SABER || weap == WP_MELEE) && cg_trueFOV.value && cg.predictedPlayerState.pm_type != PM_SPECTATOR && cg.predictedPlayerState.pm_type != PM_INTERMISSION ) { desiredFov = cg_fovViewmodel.integer ? cg_fovViewmodel.value : cg_trueFOV.value; } else { desiredFov = cg_fovViewmodel.integer ? cg_fovViewmodel.value : cg_fov.value; } desiredFov = Q_clampi( 1, desiredFov, 180 ); // allow the gun to be completely removed if ( !cg_fakeGun.integer && (!cg_drawGun.integer || cg.predictedPlayerState.zoomMode || cg_trueGuns.integer || weap == WP_SABER || weap == WP_MELEE) ) { return; } // don't draw if testing a gun model if ( cg.testGun ) { return; } centity_t *cent = &cg_entities[cg.predictedPlayerState.clientNum]; CG_RegisterWeapon( weap ); refEntity_t hand; memset( &hand, 0, sizeof(hand) ); // set up gun position vector3 angles; CG_CalculateWeaponPosition( &hand.origin, &angles ); refdef_t *refdef = CG_GetRefdef(); VectorMA( &hand.origin, cg.gunAlign.x, &refdef->viewaxis[0], &hand.origin ); VectorMA( &hand.origin, cg.gunAlign.y, &refdef->viewaxis[1], &hand.origin ); VectorMA( &hand.origin, cg.gunAlign.z, &refdef->viewaxis[2], &hand.origin ); AnglesToAxis( &angles, hand.axis ); if ( cg_fovViewmodel.integer ) { float fracDistFOV, fracWeapFOV; float fov = desiredFov; if ( cg_fovAspectAdjust.integer ) { // Based on LordHavoc's code for Darkplaces // http://www.quakeworld.nu/forum/topic/53/what-does-your-qw-look-like/page/30 const float baseAspect = 0.75f; // 3/4 const float aspect = (float)cgs.glconfig.vidWidth / (float)cgs.glconfig.vidHeight; fov = atanf( tanf( desiredFov*M_PI / 360.0f ) * baseAspect*aspect )*360.0f / M_PI; } fracDistFOV = tanf( refdef->fov_x * M_PI / 360.0f ); fracWeapFOV = (1.0f / fracDistFOV) * tanf( fov * M_PI / 360.0f ); VectorScale( &hand.axis[0], fracWeapFOV, &hand.axis[0] ); } // map torso animations to weapon animations if ( cg_debugGunFrame.integer ) { // development tool hand.frame = hand.oldframe = cg_debugGunFrame.integer; hand.backlerp = 0; } else { float currentFrame; // get clientinfo for animation map clientInfo_t *ci = nullptr; if ( cent->currentState.eType == ET_NPC ) { if ( !cent->npcClient ) { return; } ci = cent->npcClient; } else { ci = &cgs.clientinfo[cent->currentState.clientNum]; } // smoother first-person anims by eezstreet http://jkhub.org/topic/1499-/ // actually ported from SP #if 1 // Sil's fix trap->G2API_GetBoneFrame( cent->ghoul2, "lower_lumbar", cg.time, ¤tFrame, cgs.gameModels, 0 ); hand.frame = CG_MapTorsoToWeaponFrame( ci, ceilf( currentFrame ), cent->currentState.torsoAnim ); hand.oldframe = CG_MapTorsoToWeaponFrame( ci, floorf( currentFrame ), cent->currentState.torsoAnim ); hand.backlerp = 1.0f - (currentFrame - floorf( currentFrame )); #else // basejka style hand.frame = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.frame, cent->currentState.torsoAnim ); hand.oldframe = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.oldFrame, cent->currentState.torsoAnim ); hand.backlerp = cent->pe.torso.backlerp; #endif // Handle the fringe situation where oldframe is invalid if ( hand.frame == -1 ) { hand.frame = 0; hand.oldframe = 0; hand.backlerp = 0; } else if ( hand.oldframe == -1 ) { hand.oldframe = hand.frame; hand.backlerp = 0; } } weaponInfo_t *wi = &cg_weapons[weap]; hand.hModel = wi->handsModel; hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON; // add everything onto the hand CG_AddPlayerWeapon( &hand, ps, &cg_entities[cg.predictedPlayerState.clientNum], ps->persistant[PERS_TEAM], &angles, qfalse ); }
static int JP_GetScoreboardFont( void ) { return Q_clampi( FONT_SMALL, cg_newScoreboardFont.integer, FONT_NUM_FONTS ); }
static void G_Give( gentity_t *ent, const char *name, const char *args, int argc ) { const gitem_t *it; int i; qboolean give_all = qfalse; gentity_t *it_ent; trace_t trace; if ( !Q_stricmp( name, "all" ) ) give_all = qtrue; if ( give_all || !Q_stricmp( name, "health") ) { if ( argc == 3 ) ent->health = Q_clampi( 1, atoi( args ), MAX_HEALTH ); else ent->health = MAX_HEALTH; if ( !give_all ) return; } if ( give_all || !Q_stricmp( name, "armor" ) || !Q_stricmp( name, "shield" ) ) { if ( argc == 3 ) ent->client->ps.stats[STAT_ARMOR] = Q_clampi( 0, atoi( args ), MAX_ARMOR ); else ent->client->ps.stats[STAT_ARMOR] = MAX_ARMOR; if ( !give_all ) return; } if ( give_all || !Q_stricmp( name, "weapons" ) ) { ent->client->ps.stats[STAT_WEAPONS] = (1 << (WP_NUM_WEAPONS)) - (1 << WP_NONE); if ( !give_all ) return; } if ( !give_all && !Q_stricmp( name, "weaponnum" ) ) { ent->client->ps.stats[STAT_WEAPONS] |= (1 << atoi( args )); return; } if ( give_all || !Q_stricmp( name, "ammo" ) ) { int num = 999; if ( argc == 3 ) num = atoi( args ); for ( i=0; i<MAX_WEAPONS; i++ ) ent->client->ps.ammo[i] = num; if ( !give_all ) return; } // spawn a specific item right on the player if ( !give_all ) { it = BG_FindItem( name ); if ( !it ) return; it_ent = G_Spawn(); VectorCopy( &ent->r.currentOrigin, &it_ent->s.origin ); it_ent->classname = it->classname; G_SpawnItem( it_ent, it ); FinishSpawningItem( it_ent ); memset( &trace, 0, sizeof( trace ) ); Touch_Item( it_ent, ent, &trace ); if ( it_ent->inuse ) G_FreeEntity( it_ent ); } }
static qboolean G_VoteWarmup( gentity_t *ent, int numArgs, const char *arg1, const char *arg2 ) { int n = Q_clampi( 0, atoi( arg2 ), 1 ); Com_sprintf( level.voteString, sizeof( level.voteString ), "g_doWarmup %i", n ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); return qtrue; }