/* ================= SV_UserinfoChanged Pull specific info from a newly changed userinfo string into a more C friendly form. ================= */ void SV_UserinfoChanged( client_t *cl ) { char *val=NULL, *ip=NULL; int i=0, len=0; // name for C code Q_strncpyz( cl->name, Info_ValueForKey (cl->userinfo, "name"), sizeof(cl->name) ); // rate command // if the client is on the same subnet as the server and we aren't running an // internet public server, assume they don't need a rate choke if ( Sys_IsLANAddress( cl->netchan.remoteAddress ) && com_dedicated->integer != 2 && sv_lanForceRate->integer == 1 ) { cl->rate = 99999; // lans should not rate limit } else { val = Info_ValueForKey (cl->userinfo, "rate"); if (strlen(val)) { i = atoi(val); cl->rate = i; if (cl->rate < 1000) { cl->rate = 1000; } else if (cl->rate > 90000) { cl->rate = 90000; } } else { cl->rate = 3000; } } // snaps command //Note: cl->snapshotMsec is also validated in sv_main.cpp -> SV_CheckCvars if sv_fps, sv_snapsMin or sv_snapsMax is changed int minSnaps = Com_Clampi( 1, sv_snapsMax->integer, sv_snapsMin->integer ); // between 1 and sv_snapsMax ( 1 <-> 40 ) int maxSnaps = min( sv_fps->integer, sv_snapsMax->integer ); // can't produce more than sv_fps snapshots/sec, but can send less than sv_fps snapshots/sec val = Info_ValueForKey( cl->userinfo, "snaps" ); cl->wishSnaps = atoi( val ); i = Com_Clampi( minSnaps, maxSnaps, cl->wishSnaps ); cl->snapshotMsec = 1000/i; // TTimo // maintain the IP information // the banning code relies on this being consistently present if( NET_IsLocalAddress(cl->netchan.remoteAddress) ) ip = "localhost"; else ip = (char*)NET_AdrToString( cl->netchan.remoteAddress ); val = Info_ValueForKey( cl->userinfo, "ip" ); if( val[0] ) len = strlen( ip ) - strlen( val ) + strlen( cl->userinfo ); else len = strlen( ip ) + 4 + strlen( cl->userinfo ); if( len >= MAX_INFO_STRING ) SV_DropClient( cl, "userinfo string length exceeded" ); else Info_SetValueForKey( cl->userinfo, "ip", ip ); }
/*QUAKED target_location (0 0.5 0) (-8 -8 -8) (8 8 8) Set "message" to the name of this location. Set "count" to 0-7 for color. 0:white 1:red 2:green 3:yellow 4:blue 5:cyan 6:magenta 7:white Closest target_location in sight used for the location, if none in site, closest in distance */ void SP_target_location( gentity_t *self ) { if ( self->targetname && self->targetname[0] ) { SP_target_position( self ); return; } else { static qboolean didwarn = qfalse; if ( !VALIDSTRING( self->message ) ) { G_Printf( "target_location with no message at %s\n", vtos( self->s.origin ) ); G_FreeEntity( self ); return; } if ( level.locations.legacy.num >= MAX_LOCATIONS ) { if ( !didwarn ) { G_Printf( "Maximum target_locations hit (%d)! Remaining locations will be removed.\n", MAX_LOCATIONS ); didwarn = qtrue; } G_FreeEntity( self ); return; } VectorCopy( self->s.origin, level.locations.legacy.data[level.locations.legacy.num].origin ); Q_strncpyz( level.locations.legacy.data[level.locations.legacy.num].message, self->message, sizeof( level.locations.legacy.data[level.locations.legacy.num].message ) ); level.locations.legacy.data[level.locations.legacy.num].count = Com_Clampi( 0, 9, self->count ); level.locations.legacy.num++; G_FreeEntity( self ); } }
void CG_Decrease(byte *work, float lerp, int *info) { int val; val = *work - origin_land->irand(2, 5); *work = (byte)Com_Clampi(1, 255, val); }
/*QUAKED target_location (0 0.5 0) (-8 -8 -8) (8 8 8) Set "message" to the name of this location. Set "count" to 0-7 for color. 0:white 1:red 2:green 3:yellow 4:blue 5:cyan 6:magenta 7:white Closest target_location in sight used for the location, if none in site, closest in distance */ void SP_target_location( gentity_t *self ) { if ( self->targetname && self->targetname[0] ) { SP_target_position( self ); return; } else { static qboolean didwarn = qfalse; if ( !self->message ) { trap->Print( "target_location with no message at %s\n", vtos( self->s.origin ) ); G_FreeEntity( self ); return; } if ( level.locations.num >= MAX_LOCATIONS ) { if ( !didwarn ) { trap->Print( "Maximum target_locations hit (%d)\n", MAX_LOCATIONS ); didwarn = qtrue; } G_FreeEntity( self ); return; } VectorCopy( self->s.origin, level.locations.data[level.locations.num].origin ); Q_strncpyz( level.locations.data[level.locations.num].message, self->message, sizeof( level.locations.data[level.locations.num].message ) ); level.locations.data[level.locations.num].count = Com_Clampi( 0, 7, self->count ); level.locations.num++; G_FreeEntity( self ); } }
static void CG_ParseScores( void ) { int i=0, scoreIndex=0, powerups=0, readScores=0; int scoreOffset = GetScoreOffset(); if ( Server_Supports( SSF_SCOREBOARD_LARGE ) ) readScores = Com_Clampi( 0, MAX_CLIENTS, atoi( CG_Argv( 1 ) ) ); else readScores = Com_Clampi( 0, MAX_CLIENT_SCORE_SEND, atoi( CG_Argv( 1 ) ) ); 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].guantletCount = 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 ); }
/* ================= CG_ParseTeamInfo ================= */ static void CG_ParseTeamInfo( void ) { int i=0, client=0; //Raz: avoid crash if server sends invalid range numSortedTeamPlayers = Com_Clampi( 0, TEAM_MAXOVERLAY, atoi( CG_Argv( 1 ) ) ); for ( i=0; i<numSortedTeamPlayers; i++ ) { client = Com_Clampi( 0, MAX_CLIENTS, atoi( CG_Argv( i * 6 + 2 ) ) ); 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 ) ); } }
void R_RMGInit(void) { char newSky[MAX_QPATH]; char newFog[MAX_QPATH]; shader_t *fog; fog_t *gfog; mgrid_t *grid; char temp[MAX_QPATH]; int i; unsigned short *pos; ri.Cvar_VariableStringBuffer("RMG_sky", newSky, MAX_QPATH); // Get sunlight - this should set up all the sunlight data R_FindShader( newSky, lightmapsNone, stylesDefault, qfalse ); // Remap sky R_RemapShader("textures/tools/_sky", newSky, NULL); // Fill in the lightgrid with sunlight if(tr.world->lightGridData) { grid = tr.world->lightGridData; grid->ambientLight[0][0] = (byte)Com_Clampi(0, 255, tr.sunAmbient[0] * 255.0f); grid->ambientLight[0][1] = (byte)Com_Clampi(0, 255, tr.sunAmbient[1] * 255.0f); grid->ambientLight[0][2] = (byte)Com_Clampi(0, 255, tr.sunAmbient[2] * 255.0f); R_ColorShiftLightingBytes(grid->ambientLight[0], grid->ambientLight[0]); grid->directLight[0][0] = (byte)Com_Clampi(0, 255, tr.sunLight[0]); grid->directLight[0][1] = (byte)Com_Clampi(0, 255, tr.sunLight[1]); grid->directLight[0][2] = (byte)Com_Clampi(0, 255, tr.sunLight[2]); R_ColorShiftLightingBytes(grid->directLight[0], grid->directLight[0]); NormalToLatLong(tr.sunDirection, grid->latLong); pos = tr.world->lightGridArray; for(i=0;i<tr.world->numGridArrayElements;i++) { *pos = 0; pos++; } } // Override the global fog with the defined one if(tr.world->globalFog != -1) { ri.Cvar_VariableStringBuffer("RMG_fog", newFog, MAX_QPATH); fog = R_FindShader( newFog, lightmapsNone, stylesDefault, qfalse); if (fog != tr.defaultShader) { gfog = tr.world->fogs + tr.world->globalFog; gfog->parms = *fog->fogParms; if (gfog->parms.depthForOpaque) { gfog->tcScale = 1.0f / ( gfog->parms.depthForOpaque * 8.0f ); tr.distanceCull = gfog->parms.depthForOpaque; tr.distanceCullSquared = tr.distanceCull * tr.distanceCull; ri.Cvar_Set("RMG_distancecull", va("%f", tr.distanceCull)); } else { gfog->tcScale = 1.0f; } gfog->colorInt = ColorBytes4 ( gfog->parms.color[0], gfog->parms.color[1], gfog->parms.color[2], 1.0f ); } } ri.Cvar_VariableStringBuffer("RMG_weather", temp, MAX_QPATH); // Set up any weather effects switch(atol(temp)) { case 0: break; case 1: RE_WorldEffectCommand("rain init 1000"); RE_WorldEffectCommand("rain outside"); break; case 2: RE_WorldEffectCommand("snow init 1000 outside"); RE_WorldEffectCommand("snow outside"); break; } }
/* ================ CG_ParseServerinfo 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; char *mapname; int i, value; info = CG_ConfigString( CS_SERVERINFO ); cgs.debugMelee = atoi( Info_ValueForKey( info, "g_debugMelee" ) ); //trap->Cvar_GetHiddenVarValue("g_iknowkungfu"); 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.gametype = atoi( Info_ValueForKey( info, "g_gametype" ) ); trap->Cvar_Set("g_gametype", va("%i", cgs.gametype)); cgs.needpass = atoi( Info_ValueForKey( info, "g_needpass" ) ); cgs.jediVmerc = atoi( Info_ValueForKey( info, "g_jediVmerc" ) ); // this changes on map_restart, attempt to precache weapons value = atoi( Info_ValueForKey( info, "g_weaponDisable" ) ); if ( cgs.wDisable != value ) { gitem_t *item = NULL; itemInfo_t *itemInfo = NULL; cgs.wDisable = value; for ( i=1, item=bg_itemlist, itemInfo = cg_items; i<bg_numItems; i++, item++, itemInfo++ ) {// register all weapons that aren't disabled if ( item->giType == IT_WEAPON ) CG_RegisterWeapon( item->giTag ); } } cgs.fDisable = atoi( Info_ValueForKey( info, "g_forcePowerDisable" ) ); cgs.dmflags = atoi( Info_ValueForKey( info, "dmflags" ) ); cgs.duel_fraglimit = atoi( Info_ValueForKey( info, "duel_fraglimit" ) ); cgs.capturelimit = atoi( Info_ValueForKey( info, "capturelimit" ) ); // reset fraglimit warnings i = atoi( Info_ValueForKey( info, "fraglimit" ) ); if ( cgs.fraglimit < i ) cg.fraglimitWarnings &= ~(1|2|4); cgs.fraglimit = i; // reset timelimit warnings i = atoi( Info_ValueForKey( info, "timelimit" ) ); if ( cgs.timelimit != i ) cg.timelimitWarnings &= ~(1|2); cgs.timelimit = i; cgs.maxclients = Com_Clampi( 0, MAX_CLIENTS, atoi( Info_ValueForKey( info, "sv_maxclients" ) ) ); mapname = Info_ValueForKey( info, "mapname" ); //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 ); // Q_strncpyz( cgs.redTeam, Info_ValueForKey( info, "g_redTeam" ), sizeof(cgs.redTeam) ); // trap->Cvar_Set("g_redTeam", cgs.redTeam); // Q_strncpyz( cgs.blueTeam, Info_ValueForKey( info, "g_blueTeam" ), sizeof(cgs.blueTeam) ); // trap->Cvar_Set("g_blueTeam", cgs.blueTeam); 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.voteString, CG_ConfigString( CS_VOTE_STRING ), sizeof( cgs.voteString ) ); // synchronise our expected snaps/sec with the server's framerate i = atoi( Info_ValueForKey( info, "sv_fps" ) ); if ( i ) trap->Cvar_Set( "snaps", va( "%i", i ) ); }
static QINLINE int JP_GetChatboxFont( void ) { return Com_Clampi( FONT_SMALL, FONT_NUM_FONTS, cg_chatboxFont.integer ); }
void G_Give( gentity_t *ent, const char *name, const char *args, int argc ) { gitem_t *it; int i; qboolean give_all = qfalse; if ( !Q_stricmp( name, "all" ) ) give_all = qtrue; if ( give_all || !Q_stricmp( name, "health") ) { if ( argc == 3 ) ent->health = Com_Clampi( 1, ent->client->ps.stats[STAT_MAX_HEALTH], atoi( args ) ); else ent->health = ent->client->ps.stats[STAT_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] = Com_Clampi( 0, ent->client->ps.stats[STAT_MAX_HEALTH], atoi( args ) ); else ent->client->ps.stats[STAT_ARMOR] = ent->client->ps.stats[STAT_MAX_HEALTH]; if ( !give_all ) return; } if ( give_all || !Q_stricmp( name, "force" ) ) { if ( argc == 3 ) ent->client->ps.forcePower = Com_Clampi( 0, FORCE_POWER_MAX, atoi( args ) ); else ent->client->ps.forcePower = FORCE_POWER_MAX; if ( !give_all ) return; } if ( give_all || !Q_stricmp( name, "weapons" ) ) { ent->client->ps.stats[STAT_WEAPONS] = (1 << (WP_MELEE)) - ( 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, "eweaps" ) ) //for developing, gives you all the weapons, including enemy { ent->client->ps.stats[STAT_WEAPONS] = (unsigned)(1 << WP_NUM_WEAPONS) - ( 1 << WP_NONE ); // NOTE: this wasn't giving the last weapon in the list return; } if ( give_all || !Q_stricmp( name, "ammo" ) ) { int num = 999; if ( argc == 3 ) num = Com_Clampi( 0, 999, atoi( args ) ); for ( i=AMMO_FORCE; i<MAX_AMMO; i++ ) ent->client->ps.ammo[i] = num != -1 ? num : ammoData[i].max; if ( !give_all ) return; } if ( give_all || !Q_stricmp( name, "batteries" ) ) { if ( argc == 3 ) ent->client->ps.batteryCharge = Com_Clampi( 0, MAX_BATTERIES, atoi( args ) ); else ent->client->ps.batteryCharge = MAX_BATTERIES; if (!give_all) return; } // spawn a specific item right on the player if ( !give_all ) { gentity_t *it_ent; trace_t trace; it = FindItem (args); if (!it) { it = FindItem (name); if (!it) { gi.SendServerCommand( ent-g_entities, "print \"unknown item\n\""); return; } } it_ent = G_Spawn(); VectorCopy( ent->currentOrigin, it_ent->s.origin ); it_ent->classname = G_NewString(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 ); } } }
void CG_ParseServerinfo( void ) { const char *info = NULL, *tinfo = NULL; char *mapname; int i; info = CG_ConfigString( CS_SERVERINFO ); cgs.debugMelee = atoi( Info_ValueForKey( info, "g_debugMelee" ) ); //trap->Cvar_GetHiddenVarValue("g_iknowkungfu"); cgs.stepSlideFix = atoi( Info_ValueForKey( info, "g_stepSlideFix" ) ); cgs.noSpecMove = atoi( Info_ValueForKey( info, "g_noSpecMove" ) ); trap->Cvar_Set("bg_fighterAltControl", Info_ValueForKey( info, "bg_fighterAltControl" )); cgs.siegeTeamSwitch = atoi( Info_ValueForKey( info, "g_siegeTeamSwitch" ) ); cgs.showDuelHealths = atoi( Info_ValueForKey( info, "g_showDuelHealths" ) ); cgs.gametype = atoi( Info_ValueForKey( info, "g_gametype" ) ); trap->Cvar_Set("g_gametype", va("%i", cgs.gametype)); 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" ) ); // reset fraglimit warnings i = atoi( Info_ValueForKey( info, "fraglimit" ) ); if ( cgs.fraglimit < i ) cg.fraglimitWarnings &= ~(1|2|4); cgs.fraglimit = i; // reset timelimit warnings i = atoi( Info_ValueForKey( info, "timelimit" ) ); if ( cgs.timelimit != i ) cg.timelimitWarnings &= ~(1|2); cgs.timelimit = i; cgs.maxclients = Com_Clampi( 0, MAX_CLIENTS, atoi( Info_ValueForKey( info, "sv_maxclients" ) ) ); cgs.japp.jp_cinfo = atoi( Info_ValueForKey( info, "jp_cinfo" ) ); cgs.japp.overbounce = atoi( Info_ValueForKey( info, "pmove_overbounce" ) ); //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 MAC_PORT if ( tinfo[0] && sscanf( tinfo, "%X", &cg.japp.SSF ) != 1 ) #else if ( tinfo[0] && sscanf_s( tinfo, "%X", &cg.japp.SSF ) != 1 ) #endif CG_SecurityLogPrintf( "CG_ParseServerinfo: serverinfo 'ssf' was found, but invalid.\n" ); Com_Printf( "Server support hints: 0x%X\n", cg.japp.SSF ); mapname = Info_ValueForKey( info, "mapname" ); //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 ); // Q_strncpyz( cgs.redTeam, Info_ValueForKey( info, "g_redTeam" ), sizeof(cgs.redTeam) ); // trap->Cvar_Set("g_redTeam", cgs.redTeam); // Q_strncpyz( cgs.blueTeam, Info_ValueForKey( info, "g_blueTeam" ), sizeof(cgs.blueTeam) ); // trap->Cvar_Set("g_blueTeam", cgs.blueTeam); 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; } } // cg.japp.mod = GetMod( info ); 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 =o 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 ) ); }
void G_ReflectMissile( gentity_t *ent, gentity_t *missile, vec3_t forward, qboolean coneBased ) { vec3_t bounce_dir; int i; float speed; qboolean isOwner, breakRng; #if 0 vec3_t eyePoint; vec3_t viewTestLine; VectorCopy( ent->client->ps.origin, eyePoint ); eyePoint[2] += ent->client->ps.viewheight; VectorCopy( forward, viewTestLine ); VectorNormalize( viewTestLine ); VectorScale( viewTestLine, 500, viewTestLine ); VectorAdd( viewTestLine, eyePoint, viewTestLine ); G_TestLine( eyePoint, viewTestLine, 0x00ff00, 10000 ); #endif breakRng = g_breakRNG.integer & BROKEN_RNG_REFLECT; //save the original speed speed = VectorNormalize( missile->s.pos.trDelta ); if ( missile->r.ownerNum == ent->s.number ) { // since we're giving boost to our own missile by pushing it, up the velocity speed *= 1.5; isOwner = qtrue; } if ( coneBased ) { // new behavior: the direction is randomized in a cone centered around the player view, so you can roughly aim const float coneAngle = DEG2RAD( Com_Clampi( 0, 360, g_coneReflectAngle.integer ) ); vec3_t coneDir; VectorCopy( forward, coneDir ); VectorNormalize( coneDir ); // generate a point on the angled spherical cap centered on the Z axis const float phi = RandFloat( 0, 1, breakRng ) * 2 * M_PI; bounce_dir[2] = RandFloat( 0, 1, breakRng ) * ( 1 - cos( coneAngle ) ) + cos( coneAngle ); bounce_dir[0] = sqrt( 1 - bounce_dir[2] * bounce_dir[2] ) * cos( phi ); bounce_dir[1] = sqrt( 1 - bounce_dir[2] * bounce_dir[2] ) * sin( phi ); // find the rotation axis and rotation angle for the cone direction const vec3_t zAxis = { 0.0f, 0.0f, 1.0f }; vec3_t rotationAxis; CrossProduct( zAxis, coneDir, rotationAxis ); const float rotationAngle = acos( DotProduct( coneDir, zAxis ) ); if ( rotationAngle ) { // rotate that shit const float cr = cos( rotationAngle ); const float sr = sin( rotationAngle ); vec3_t zCenteredDirection; VectorCopy( bounce_dir, zCenteredDirection ); // my head bounce_dir[0] = ( ( cr + ( rotationAxis[0] * rotationAxis[0] * ( 1 - cr ) ) ) * zCenteredDirection[0] ) + ( ( ( rotationAxis[0] * rotationAxis[1] * ( 1 - cr ) ) - ( rotationAxis[2] * sr ) ) * zCenteredDirection[1] ) + ( ( ( rotationAxis[0] * rotationAxis[2] * ( 1 - cr ) ) + ( rotationAxis[1] * sr ) ) * zCenteredDirection[2] ); bounce_dir[1] = ( ( ( rotationAxis[1] * rotationAxis[0] * ( 1 - cr ) ) + ( rotationAxis[2] * sr ) ) * zCenteredDirection[0] ) + ( ( cr + ( rotationAxis[1] * rotationAxis[1] * ( 1 - cr ) ) ) * zCenteredDirection[1] ) + ( ( ( rotationAxis[1] * rotationAxis[2] * ( 1 - cr ) ) - ( rotationAxis[0] * sr ) ) * zCenteredDirection[2] ); bounce_dir[2] = ( ( ( rotationAxis[2] * rotationAxis[0] * ( 1 - cr ) ) - ( rotationAxis[1] * sr ) ) * zCenteredDirection[0] ) + ( ( ( rotationAxis[2] * rotationAxis[1] * ( 1 - cr ) ) + ( rotationAxis[0] * sr ) ) * zCenteredDirection[1] ) + ( ( cr + ( rotationAxis[2] * rotationAxis[2] * ( 1 - cr ) ) ) * zCenteredDirection[2] ); } } else { // basejka behavior: if owner is present, it's roughly sent back at him if ( &g_entities[missile->r.ownerNum] && missile->s.weapon != WP_SABER && missile->s.weapon != G2_MODEL_PART && !isOwner ) { // bounce back at them if you can VectorSubtract( g_entities[missile->r.ownerNum].r.currentOrigin, missile->r.currentOrigin, bounce_dir ); VectorNormalize( bounce_dir ); } else { vec3_t missile_dir; VectorSubtract( ent->r.currentOrigin, missile->r.currentOrigin, missile_dir ); VectorCopy( missile->s.pos.trDelta, bounce_dir ); VectorScale( bounce_dir, DotProduct( forward, missile_dir ), bounce_dir ); VectorNormalize( bounce_dir ); } for ( i = 0; i < 3; i++ ) { bounce_dir[i] += RandFloat( -0.2f, 0.2f, breakRng ); // *CHANGE 10a* bigger deflect angles } } VectorNormalize( bounce_dir ); VectorScale( bounce_dir, speed, missile->s.pos.trDelta ); missile->s.pos.trTime = level.time; // move a bit on the very first frame VectorCopy( missile->r.currentOrigin, missile->s.pos.trBase ); #if 0 vec3_t reflectionTestLine; VectorCopy( missile->s.pos.trDelta, reflectionTestLine ); VectorNormalize( reflectionTestLine ); VectorScale( reflectionTestLine, 500, reflectionTestLine ); VectorAdd( reflectionTestLine, missile->s.pos.trBase, reflectionTestLine ); G_TestLine( missile->s.pos.trBase, reflectionTestLine, 0x0000ff, 10000 ); #endif if ( missile->s.weapon != WP_SABER && missile->s.weapon != G2_MODEL_PART ) { // you are mine, now! missile->r.ownerNum = ent->s.number; missile->isReflected = qtrue; } if ( missile->s.weapon == WP_ROCKET_LAUNCHER ) { // stop homing missile->think = 0; missile->nextthink = 0; } }