// Shows best/worst accuracy for all weapons, or sorted // accuracies for a single weapon. void G_weaponRankings_cmd(gentity_t *ent, unsigned int dwCommand, qboolean state) { gclient_t *cl; // sta acqu-sdk (issue 2): CHRUKER: b068 int c = 0, i, wBestAcc; unsigned shots; //int c = 0, i, shots, wBestAcc; // end acqu-sdk (issue 2): CHRUKER: b068 char z[MAX_STRING_CHARS]; if(trap_Argc() < 2) { G_weaponStatsLeaders_cmd(ent, state, qfalse); return; } wBestAcc = (state) ? 0 : 99999; // Find the weapon trap_Argv(1, z, sizeof(z)); if((iWeap = atoi(z)) == 0 || iWeap < WS_KNIFE || iWeap >= WS_MAX) { for(iWeap=WS_SYRINGE; iWeap>=WS_KNIFE; iWeap--) { if(!Q_stricmp(z, aWeaponInfo[iWeap].pszCode)) break; } } if(iWeap < WS_KNIFE) { G_commandHelp(ent, (state)?"topshots":"bottomshots", dwCommand); Q_strncpyz(z, "^3Available weapon codes:^7\n", sizeof(z)); for(i=WS_KNIFE; i<WS_MAX; i++) { Q_strcat(z, sizeof(z), va(" %s - %s\n", aWeaponInfo[i].pszCode, aWeaponInfo[i].pszName)); } CP(va("print \"%s\"", z)); return; } memcpy(&level.sortedStats, &level.sortedClients, sizeof(level.sortedStats)); qsort(level.sortedStats, level.numConnectedClients, sizeof(level.sortedStats[0]), SortStats); z[0] = 0; for(i=0; i<level.numConnectedClients; i++) { cl = &level.clients[level.sortedStats[i]]; if(cl->sess.sessionTeam == TEAM_SPECTATOR) continue; shots = cl->sess.aWeaponStats[iWeap].atts; if(shots >= cQualifyingShots[iWeap]) { float acc = (float)(cl->sess.aWeaponStats[iWeap].hits * 100.0) / (float)shots; c++; wBestAcc = (((state)?acc:wBestAcc) > ((state)?wBestAcc:acc)) ? (int)acc : wBestAcc; Q_strcat(z, sizeof(z), va(" %d %d %d %d %d", level.sortedStats[i], cl->sess.aWeaponStats[iWeap].hits, shots, cl->sess.aWeaponStats[iWeap].kills, cl->sess.aWeaponStats[iWeap].deaths)); } } CP(va("astats%s %d %d %d%s", ((state)?"":"b"), c, iWeap, wBestAcc, z)); }
/* ================== SV_DirectConnect A "connect" OOB command has been received ================== */ void SV_DirectConnect( netadr_t from ) { char userinfo[MAX_INFO_STRING]; int i; client_t *cl, *newcl; client_t temp; sharedEntity_t *ent; int clientNum; int version; int qport; int challenge; char *password; int startIndex; char *denied; int count; char *ip; Com_DPrintf ("SVC_DirectConnect ()\n"); // Check whether this client is banned. if ( SV_IsBanned( &from, qfalse ) ) { NET_OutOfBandPrint( NS_SERVER, from, "print\nYou are banned from this server.\n" ); Com_DPrintf( " rejected connect from %s (banned)\n", NET_AdrToString(from) ); return; } Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) ); version = atoi( Info_ValueForKey( userinfo, "protocol" ) ); if ( version != PROTOCOL_VERSION ) { NET_OutOfBandPrint( NS_SERVER, from, "print\nServer uses protocol version %i (yours is %i).\n", PROTOCOL_VERSION, version ); Com_DPrintf (" rejected connect from version %i\n", version); return; } challenge = atoi( Info_ValueForKey( userinfo, "challenge" ) ); qport = atoi( Info_ValueForKey( userinfo, "qport" ) ); // quick reject for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) { /* This was preventing sv_reconnectlimit from working. It seems like commenting this out has solved the problem. HOwever, if there is a future problem then it could be this. if ( cl->state == CS_FREE ) { continue; } */ if ( NET_CompareBaseAdr( from, cl->netchan.remoteAddress ) && ( cl->netchan.qport == qport || from.port == cl->netchan.remoteAddress.port ) ) { if (( svs.time - cl->lastConnectTime) < (sv_reconnectlimit->integer * 1000)) { NET_OutOfBandPrint( NS_SERVER, from, "print\nReconnect rejected : too soon\n" ); Com_DPrintf ("%s:reconnect rejected : too soon\n", NET_AdrToString (from)); return; } break; } } // don't let "ip" overflow userinfo string if ( NET_IsLocalAddress (from) ) ip = "localhost"; else ip = (char *)NET_AdrToString( from ); if( ( strlen( ip ) + strlen( userinfo ) + 4 ) >= MAX_INFO_STRING ) { NET_OutOfBandPrint( NS_SERVER, from, "print\nUserinfo string length exceeded. " "Try removing setu cvars from your config.\n" ); return; } Info_SetValueForKey( userinfo, "ip", ip ); // see if the challenge is valid (localhost clients don't need to challenge) if (!NET_IsLocalAddress(from)) { // Verify the received challenge against the expected challenge if (!SV_VerifyChallenge(challenge, from)) { NET_OutOfBandPrint( NS_SERVER, from, "print\nIncorrect challenge for your address.\n" ); return; } } newcl = &temp; Com_Memset (newcl, 0, sizeof(client_t)); // if there is already a slot for this ip, reuse it for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) { if ( cl->state == CS_FREE ) { continue; } if ( NET_CompareBaseAdr( from, cl->netchan.remoteAddress ) && ( cl->netchan.qport == qport || from.port == cl->netchan.remoteAddress.port ) ) { Com_Printf ("%s:reconnect\n", NET_AdrToString (from)); newcl = cl; // VVFIXME - both SOF2 and Wolf remove this call, claiming it blows away the user's info // disconnect the client from the game first so any flags the // player might have are dropped GVM_ClientDisconnect( newcl - svs.clients ); // goto gotnewcl; } } // find a client slot // if "sv_privateClients" is set > 0, then that number // of client slots will be reserved for connections that // have "password" set to the value of "sv_privatePassword" // Info requests will report the maxclients as if the private // slots didn't exist, to prevent people from trying to connect // to a full server. // This is to allow us to reserve a couple slots here on our // servers so we can play without having to kick people. // check for privateClient password password = Info_ValueForKey( userinfo, "password" ); if ( !strcmp( password, sv_privatePassword->string ) ) { startIndex = 0; } else { // skip past the reserved slots startIndex = sv_privateClients->integer; } newcl = NULL; for ( i = startIndex; i < sv_maxclients->integer ; i++ ) { cl = &svs.clients[i]; if (cl->state == CS_FREE) { newcl = cl; break; } } if ( !newcl ) { if ( NET_IsLocalAddress( from ) ) { count = 0; for ( i = startIndex; i < sv_maxclients->integer ; i++ ) { cl = &svs.clients[i]; if (cl->netchan.remoteAddress.type == NA_BOT) { count++; } } // if they're all bots if (count >= sv_maxclients->integer - startIndex) { SV_DropClient(&svs.clients[sv_maxclients->integer - 1], "only bots on server"); newcl = &svs.clients[sv_maxclients->integer - 1]; } else { Com_Error( ERR_FATAL, "server is full on local connect\n" ); return; } } else { const char *SV_GetStringEdString(char *refSection, char *refName); NET_OutOfBandPrint( NS_SERVER, from, va("print\n%s\n", SV_GetStringEdString("MP_SVGAME","SERVER_IS_FULL"))); Com_DPrintf ("Rejected a connection.\n"); return; } } // we got a newcl, so reset the reliableSequence and reliableAcknowledge cl->reliableAcknowledge = 0; cl->reliableSequence = 0; gotnewcl: // build a new connection // accept the new client // this is the only place a client_t is ever initialized *newcl = temp; clientNum = newcl - svs.clients; ent = SV_GentityNum( clientNum ); newcl->gentity = ent; // save the challenge newcl->challenge = challenge; // save the address Netchan_Setup (NS_SERVER, &newcl->netchan , from, qport); // save the userinfo Q_strncpyz( newcl->userinfo, userinfo, sizeof(newcl->userinfo) ); // get the game a chance to reject this connection or modify the userinfo denied = GVM_ClientConnect( clientNum, qtrue, qfalse ); // firstTime = qtrue if ( denied ) { NET_OutOfBandPrint( NS_SERVER, from, "print\n%s\n", denied ); Com_DPrintf ("Game rejected a connection: %s.\n", denied); return; } SV_UserinfoChanged( newcl ); // send the connect packet to the client NET_OutOfBandPrint( NS_SERVER, from, "connectResponse" ); Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name ); newcl->state = CS_CONNECTED; newcl->nextSnapshotTime = svs.time; newcl->lastPacketTime = svs.time; newcl->lastConnectTime = svs.time; // when we receive the first packet from the client, we will // notice that it is from a different serverid and that the // gamestate message was not just sent, forcing a retransmit newcl->gamestateMessageNum = -1; newcl->lastUserInfoChange = 0; //reset the delay newcl->lastUserInfoCount = 0; //reset the count // if this was the first client on the server, or the last client // the server can hold, send a heartbeat to the master. count = 0; for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) { if ( svs.clients[i].state >= CS_CONNECTED ) { count++; } } if ( count == 1 || count == sv_maxclients->integer ) { SV_Heartbeat_f(); } }
bool GEItescriptsDlg_Init ( HWND hwnd ) { idWindow* window; rvGEWindowWrapper* wrapper; HWND script; // Extract the window pointer from the win32 windows user data long window = (idWindow*)GetWindowLong ( hwnd, GWL_USERDATA ); assert ( window ); // Get the window wrapper of the script window wrapper = rvGEWindowWrapper::GetWrapper ( window ); assert ( wrapper ); // Get the edit box used to edit the script script = GetDlgItem ( hwnd, IDC_GUIED_SCRIPT ); UINT tabsize = 16; SendMessage ( script, EM_SETTABSTOPS, 1, (LPARAM)&tabsize ); SetWindowLong ( script, GWL_USERDATA, GetWindowLong ( script, GWL_WNDPROC ) ); SetWindowLong ( script, GWL_WNDPROC, (LONG) GEScriptEdit_WndProc ); TEXTMETRIC tm; HDC dc; dc = GetDC ( script ); GetTextMetrics ( dc, &tm ); ReleaseDC ( script, dc ); LOGFONT lf; ZeroMemory ( &lf, sizeof(lf) ); lf.lfHeight = tm.tmHeight; strcpy ( lf.lfFaceName, "Courier New" ); SendMessage ( script, WM_SETFONT, (WPARAM)CreateFontIndirect ( &lf ), 0 ); SendMessage ( script, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(10,10) ); int i; for ( i = 0; i < wrapper->GetVariableDict().GetNumKeyVals ( ); i ++ ) { const idKeyValue* key = wrapper->GetVariableDict().GetKeyVal ( i ); SendMessage ( script, EM_SETSEL, -1, -1 ); SendMessage ( script, EM_REPLACESEL, FALSE, (LPARAM)key->GetKey().c_str() ); SendMessage ( script, EM_SETSEL, -1, -1 ); SendMessage ( script, EM_REPLACESEL, FALSE, (LPARAM)"\t" ); SendMessage ( script, EM_SETSEL, -1, -1 ); SendMessage ( script, EM_REPLACESEL, FALSE, (LPARAM)key->GetValue().c_str() ); SendMessage ( script, EM_SETSEL, -1, -1 ); SendMessage ( script, EM_REPLACESEL, FALSE, (LPARAM)"\r\n" ); } if ( i ) { SendMessage ( script, EM_SETSEL, -1, -1 ); SendMessage ( script, EM_REPLACESEL, FALSE, (LPARAM)"\r\n" ); } for ( i = 0; i < wrapper->GetScriptDict().GetNumKeyVals ( ); i ++ ) { const idKeyValue* key = wrapper->GetScriptDict().GetKeyVal ( i ); SendMessage ( script, EM_SETSEL, -1, -1 ); SendMessage ( script, EM_REPLACESEL, FALSE, (LPARAM)va("%s\r\n", key->GetKey().c_str() ) ); SendMessage ( script, EM_SETSEL, -1, -1 ); SendMessage ( script, EM_REPLACESEL, FALSE, (LPARAM)key->GetValue().c_str() ); SendMessage ( script, EM_SETSEL, -1, -1 ); SendMessage ( script, EM_REPLACESEL, FALSE, (LPARAM)"\r\n\r\n" ); } SendMessage ( script, EM_SETSEL, 0, 0 ); SendMessage ( script, EM_SCROLLCARET, 0, 0 ); return true; }
static void CG_TaskOwnFlag_f (void ) { trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_IHAVEFLAG)); }
/* =============== GLimp_DetectAvailableModes =============== */ static void GLimp_DetectAvailableModes(void) { int i, j; char buf[ MAX_STRING_CHARS ] = { 0 }; int numSDLModes; SDL_Rect *modes; int numModes = 0; SDL_DisplayMode windowMode; int display = SDL_GetWindowDisplayIndex( SDL_window ); if( display < 0 ) { ri.Printf( PRINT_WARNING, "Couldn't get window display index, no resolutions detected: %s\n", SDL_GetError() ); return; } numSDLModes = SDL_GetNumDisplayModes( display ); if( SDL_GetWindowDisplayMode( SDL_window, &windowMode ) < 0 || numSDLModes <= 0 ) { ri.Printf( PRINT_WARNING, "Couldn't get window display mode, no resolutions detected: %s\n", SDL_GetError() ); return; } modes = SDL_calloc( (size_t)numSDLModes, sizeof( SDL_Rect ) ); if ( !modes ) { ri.Error( ERR_FATAL, "Out of memory" ); } for( i = 0; i < numSDLModes; i++ ) { SDL_DisplayMode mode; if( SDL_GetDisplayMode( display, i, &mode ) < 0 ) continue; if( !mode.w || !mode.h ) { ri.Printf( PRINT_ALL, "Display supports any resolution\n" ); SDL_free( modes ); return; } if( windowMode.format != mode.format ) continue; // SDL can give the same resolution with different refresh rates. // Only list resolution once. for( j = 0; j < numModes; j++ ) { if( mode.w == modes[ j ].w && mode.h == modes[ j ].h ) break; } if( j != numModes ) continue; modes[ numModes ].w = mode.w; modes[ numModes ].h = mode.h; numModes++; } if( numModes > 1 ) qsort( modes, numModes, sizeof( SDL_Rect ), GLimp_CompareModes ); for( i = 0; i < numModes; i++ ) { const char *newModeString = va( "%ux%u ", modes[ i ].w, modes[ i ].h ); if( strlen( newModeString ) < (int)sizeof( buf ) - strlen( buf ) ) Q_strcat( buf, sizeof( buf ), newModeString ); else ri.Printf( PRINT_WARNING, "Skipping mode %ux%u, buffer too small\n", modes[ i ].w, modes[ i ].h ); } if( *buf ) { buf[ strlen( buf ) - 1 ] = 0; ri.Printf( PRINT_ALL, "Available modes: '%s'\n", buf ); ri.Cvar_Set( "r_availableModes", buf ); } SDL_free( modes ); }
static void CG_TaskCamp_f (void ) { trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONCAMPING)); trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_CAMP)); }
static void CG_TaskRetrieve_f (void ) { trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONRETURNFLAG)); trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_RETRIEVE)); }
void CL_Frame ( int msec,float fractionMsec ) { if ( !com_cl_running->integer ) { return; } // load the ref / ui / cgame if needed CL_StartHunkUsers(); if ( cls.state == CA_DISCONNECTED && !( cls.keyCatchers & KEYCATCH_UI ) && !com_sv_running->integer ) { // if disconnected, bring up the menu if (!CL_CheckPendingCinematic()) // this avoid having the menu flash for one frame before pending cinematics { UI_SetActiveMenu( "mainMenu",NULL ); } } // if recording an avi, lock to a fixed fps if ( cl_avidemo->integer ) { // save the current screen if ( cls.state == CA_ACTIVE ) { if (cl_avidemo->integer > 0) { Cbuf_ExecuteText( EXEC_NOW, "screenshot silent\n" ); } else { Cbuf_ExecuteText( EXEC_NOW, "screenshot_tga silent\n" ); } } // fixed time for next frame if (cl_avidemo->integer > 0) { msec = 1000 / cl_avidemo->integer; } else { msec = 1000 / -cl_avidemo->integer; } } // save the msec before checking pause cls.realFrametime = msec; // decide the simulation time cls.frametime = msec; if(cl_framerate->integer) { avgFrametime+=msec; char mess[256]; if(!(frameCount&0x1f)) { sprintf(mess,"Frame rate=%f\n\n",1000.0f*(1.0/(avgFrametime/32.0f))); // OutputDebugString(mess); Com_Printf(mess); avgFrametime=0.0f; } frameCount++; } cls.frametimeFraction=fractionMsec; cls.realtime += msec; cls.realtimeFraction+=fractionMsec; if (cls.realtimeFraction>=1.0f) { if (cl_newClock&&cl_newClock->integer) { cls.realtime++; } cls.realtimeFraction-=1.0f; } if ( cl_timegraph->integer ) { SCR_DebugGraph ( cls.realFrametime * 0.25, 0 ); } // see if we need to update any userinfo CL_CheckUserinfo(); // if we haven't gotten a packet in a long time, // drop the connection CL_CheckTimeout(); // send intentions now CL_SendCmd(); // resend a connection request if necessary CL_CheckForResend(); // decide on the serverTime to render CL_SetCGameTime(); if (cl_pano->integer && cls.state == CA_ACTIVE) { //grab some panoramic shots int i = 1; int pref = cl_pano->integer; int oldnoprint = cl_noprint->integer; Con_Close(); cl_noprint->integer = 1; //hide the screen shot msgs for (; i <= cl_panoNumShots->integer; i++) { Cvar_SetValue( "pano", i ); SCR_UpdateScreen();// update the screen Cbuf_ExecuteText( EXEC_NOW, va("screenshot %dpano%02d\n", pref, i) ); //grab this screen } Cvar_SetValue( "pano", 0 ); //done cl_noprint->integer = oldnoprint; } if (cl_skippingcin->integer && !cl_endcredits->integer) { if (cl_skippingcin->modified){ S_StopSounds(); //kill em all but music cl_skippingcin->modified=qfalse; Com_Printf (S_COLOR_YELLOW "...."); SCR_UpdateScreen(); } } else { // update the screen SCR_UpdateScreen(); } // update audio S_Update(); // advance local effects for next frame SCR_RunCinematic(); Con_RunConsole(); cls.framecount++; }
char *demoAutoFormat(const char* name) { const char *format; qboolean haveTag = qfalse; char outBuf[512]; int outIndex = 0; int outLeft = sizeof(outBuf) - 1; int t = 0; char timeStamps[MAX_QPATH] = ""; qtime_t ct; char playerName[MAX_QPATH], *mapName = COM_SkipPath(Info_ValueForKey((cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO]), "mapname")); Q_strncpyz(playerName, Info_ValueForKey((cl.gameState.stringData + cl.gameState.stringOffsets[CS_PLAYERS+cl.snap.ps.clientNum]), "n"), sizeof(playerName)); if (cls.uag.newColors) Q_StripColorUAG(playerName); else Q_StripColor(playerName); Com_RealTime(&ct); format = cl_autoDemoFormat->string; if (!format || !format[0]) { if (!name || !name[0]) { format = "%t"; } else { format = "%n_%t"; } } while (*format && outLeft > 0) { if (haveTag) { char ch = *format++; haveTag = qfalse; switch (ch) { case 'd': //date Com_sprintf( outBuf + outIndex, outLeft, "%d-%02d-%02d-%02d%02d%02d", 1900+ct.tm_year, ct.tm_mon+1,ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec); outIndex += strlen( outBuf + outIndex ); break; case 'm': //map Com_sprintf( outBuf + outIndex, outLeft, mapName); outIndex += strlen( outBuf + outIndex ); break; case 'n': //custom demo name Com_sprintf( outBuf + outIndex, outLeft, name); outIndex += strlen( outBuf + outIndex ); break; case 'p': //current player name Com_sprintf( outBuf + outIndex, outLeft, playerName); outIndex += strlen( outBuf + outIndex ); break; case 't': //timestamp while (demo.record.timeStamps[t] && t < MAX_TIMESTAMPS) { int min = demo.record.timeStamps[t] / 60000; int sec = (demo.record.timeStamps[t] / 1000) % 60; if (t == 0) { Com_sprintf(timeStamps, sizeof(timeStamps), "%0.2d%0.2d", min, sec); } else { Com_sprintf(timeStamps, sizeof(timeStamps), "%s_%0.2d%0.2d", timeStamps, min, sec); } t++; } Com_sprintf( outBuf + outIndex, outLeft, timeStamps); outIndex += strlen( outBuf + outIndex ); break; case '%': outBuf[outIndex++] = '%'; break; default: continue; } outLeft = sizeof(outBuf) - outIndex - 1; continue; } if (*format == '%') { haveTag = qtrue; format++; continue; } outBuf[outIndex++] = *format++; outLeft = sizeof(outBuf) - outIndex - 1; } outBuf[ outIndex ] = 0; return va("%s", outBuf); }
/* ==================== CL_Record_f record <demoname> <map> [cd track] ==================== */ void CL_Record_f (void) { int c; char name[MAX_OSPATH]; int track; if (cmd_source != src_command) return; c = Cmd_Argc(); if (c != 2 && c != 3 && c != 4) { Con_Printf ("record <demoname> [<map> [cd track]]\n"); return; } if (strstr(Cmd_Argv(1), "..")) { Con_Printf ("Relative pathnames are not allowed.\n"); return; } if (c == 2 && cls.state == ca_connected) { Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n"); return; } // write the forced cd track number, or -1 if (c == 4) { track = atoi(Cmd_Argv(3)); Con_Printf ("Forcing CD track to %i\n", cls.forcetrack); } else track = -1; sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1)); // // start the map up // if (c > 2) Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command); // // open the demo file // COM_DefaultExtension (name, ".dem"); Con_Printf ("recording to %s.\n", name); cls.demofile = Sys_FileOpenStdlib(name, "wb"); if (!cls.demofile) { Con_Printf ("ERROR: couldn't open.\n"); return; } cls.forcetrack = track; fprintf (cls.demofile, "%i\n", cls.forcetrack); cls.demorecording = true; }
/* ================ SVC_Info Responds with a short info message that should be enough to determine if a user is interested in a server to do a full status ================ */ void SVC_Info( netadr_t from ) { int i, count, botCount; char infostring[ MAX_INFO_STRING ]; const char *challenge; challenge = Cmd_Argv( 1 ); /* * Check whether Cmd_Argv(1) has a sane length. This was not done in the original Quake3 version which led * to the Infostring bug discovered by Luigi Auriemma. See http://aluigi.altervista.org/ for the advisory. */ // A maximum challenge length of 128 should be more than plenty. if ( strlen( challenge ) > MAX_CHALLENGE_LEN ) { return; } //bani - bugtraq 12534 if ( !SV_VerifyChallenge( challenge ) ) { return; } SV_ResolveMasterServers(); // don't count privateclients botCount = count = 0; for ( i = sv_privateClients->integer; i < sv_maxclients->integer; i++ ) { if ( svs.clients[ i ].state >= CS_CONNECTED ) { if ( svs.clients[ i ].gentity && ( svs.clients[ i ].gentity->r.svFlags & SVF_BOT ) ) { ++botCount; } else { ++count; } } } infostring[ 0 ] = 0; // echo back the parameter to status. so servers can use it as a challenge // to prevent timed spoofed reply packets that add ghost servers Info_SetValueForKey( infostring, "challenge", challenge, qfalse ); // If the master server listens on IPv4 and IPv6, we want to send the // most recent challenge received from it over the OTHER protocol for ( i = 0; i < MAX_MASTER_SERVERS; i++ ) { // First, see if the challenge was sent by this master server if ( !NET_CompareBaseAdr( from, masterServerAddr[ i ].ipv4 ) && !NET_CompareBaseAdr( from, masterServerAddr[ i ].ipv6 ) ) { continue; } // It was - if the saved challenge is for the other protocol, send it and record the current one if ( challenges[ i ].type == NA_IP || challenges[ i ].type == NA_IP6 ) { if ( challenges[ i ].type != from.type ) { Info_SetValueForKey( infostring, "challenge2", challenges[ i ].text, qfalse ); challenges[ i ].type = from.type; strcpy( challenges[ i ].text, challenge ); break; } } // Otherwise record the current one regardless and check the next server challenges[ i ].type = from.type; strcpy( challenges[ i ].text, challenge ); } Info_SetValueForKey( infostring, "protocol", va( "%i", PROTOCOL_VERSION ), qfalse ); Info_SetValueForKey( infostring, "hostname", sv_hostname->string, qfalse ); Info_SetValueForKey( infostring, "serverload", va( "%i", svs.serverLoad ), qfalse ); Info_SetValueForKey( infostring, "mapname", sv_mapname->string, qfalse ); Info_SetValueForKey( infostring, "clients", va( "%i", count ), qfalse ); Info_SetValueForKey( infostring, "bots", va( "%i", botCount ), qfalse ); Info_SetValueForKey( infostring, "sv_maxclients", va( "%i", sv_maxclients->integer - sv_privateClients->integer ), qfalse ); Info_SetValueForKey( infostring, "pure", va( "%i", sv_pure->integer ), qfalse ); if ( sv_statsURL->string[0] ) { Info_SetValueForKey( infostring, "stats", sv_statsURL->string, qfalse ); } #ifdef USE_VOIP if ( sv_voip->integer ) { Info_SetValueForKey( infostring, "voip", va( "%i", sv_voip->integer ), qfalse ); } #endif if ( sv_minPing->integer ) { Info_SetValueForKey( infostring, "minPing", va( "%i", sv_minPing->integer ), qfalse ); } if ( sv_maxPing->integer ) { Info_SetValueForKey( infostring, "maxPing", va( "%i", sv_maxPing->integer ), qfalse ); } Info_SetValueForKey( infostring, "gamename", GAMENAME_STRING, qfalse ); // Arnout: to be able to filter out Quake servers NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring ); }
void R_RMGInit(void) { char newSky[MAX_QPATH]; char newFog[MAX_QPATH]; shader_t *sky; shader_t *fog; fog_t *gfog; mgrid_t *grid; char temp[MAX_QPATH]; int i; unsigned short *pos; Cvar_VariableStringBuffer("RMG_sky", newSky, MAX_QPATH); // Get sunlight - this should set up all the sunlight data sky = 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) { 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; 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 ); } } Cvar_VariableStringBuffer("RMG_weather", temp, MAX_QPATH); // Set up any weather effects switch(atol(temp)) { case 0: break; case 1: R_WorldEffectCommand("rain init 1000"); R_WorldEffectCommand("rain outside"); break; case 2: R_WorldEffectCommand("snow init 1000 outside"); R_WorldEffectCommand("snow outside"); break; } }
/* ============================== idFont::LoadFont ============================== */ bool idFont::LoadFont() { idStr fontName = va( "newfonts/%s/48.dat", GetName() ); idFile * fd = fileSystem->OpenFileRead( fontName ); if ( fd == NULL ) { return false; } const int FONT_INFO_VERSION = 42; const int FONT_INFO_MAGIC = ( FONT_INFO_VERSION | ( 'i' << 24 ) | ( 'd' << 16 ) | ( 'f' << 8 ) ); uint32 version = 0; fd->ReadBig( version ); if ( version != FONT_INFO_MAGIC ) { idLib::Warning( "Wrong version in %s", GetName() ); delete fd; return false; } fontInfo = new (TAG_FONT) fontInfo_t; short pointSize = 0; fd->ReadBig( pointSize ); assert( pointSize == 48 ); fd->ReadBig( fontInfo->ascender ); fd->ReadBig( fontInfo->descender ); fd->ReadBig( fontInfo->numGlyphs ); fontInfo->glyphData = (glyphInfo_t *)Mem_Alloc( sizeof( glyphInfo_t ) * fontInfo->numGlyphs, TAG_FONT ); fontInfo->charIndex = (uint32 *)Mem_Alloc( sizeof( uint32 ) * fontInfo->numGlyphs, TAG_FONT ); fd->Read( fontInfo->glyphData, fontInfo->numGlyphs * sizeof( glyphInfo_t ) ); for( int i = 0; i < fontInfo->numGlyphs; i++ ) { idSwap::Little( fontInfo->glyphData[i].width ); idSwap::Little( fontInfo->glyphData[i].height ); idSwap::Little( fontInfo->glyphData[i].top ); idSwap::Little( fontInfo->glyphData[i].left ); idSwap::Little( fontInfo->glyphData[i].xSkip ); idSwap::Little( fontInfo->glyphData[i].s ); idSwap::Little( fontInfo->glyphData[i].t ); } fd->Read( fontInfo->charIndex, fontInfo->numGlyphs * sizeof( uint32 ) ); idSwap::LittleArray( fontInfo->charIndex, fontInfo->numGlyphs ); memset( fontInfo->ascii, -1, sizeof( fontInfo->ascii ) ); for ( int i = 0; i < fontInfo->numGlyphs; i++ ) { if ( fontInfo->charIndex[i] < 128 ) { fontInfo->ascii[fontInfo->charIndex[i]] = i; } else { // Since the characters are sorted, as soon as we find a non-ascii character, we can stop break; } } idStr fontTextureName = fontName; fontTextureName.SetFileExtension( "tga" ); fontInfo->material = declManager->FindMaterial( fontTextureName ); fontInfo->material->SetSort( SS_GUI ); // Load the old glyph data because we want our new fonts to fit in the old glyph metrics int pointSizes[3] = { 12, 24, 48 }; float scales[3] = { 4.0f, 2.0f, 1.0f }; for ( int i = 0; i < 3; i++ ) { oldGlyphInfo_t oldGlyphInfo[GLYPHS_PER_FONT]; const char * oldFileName = va( "newfonts/%s/old_%d.dat", GetName(), pointSizes[i] ); if ( LoadOldGlyphData( oldFileName, oldGlyphInfo ) ) { int mh = 0; int mw = 0; for ( int g = 0; g < GLYPHS_PER_FONT; g++ ) { if ( mh < oldGlyphInfo[g].height ) { mh = oldGlyphInfo[g].height; } if ( mw < oldGlyphInfo[g].xSkip ) { mw = oldGlyphInfo[g].xSkip; } } fontInfo->oldInfo[i].maxWidth = scales[i] * mw; fontInfo->oldInfo[i].maxHeight = scales[i] * mh; } else { int mh = 0; int mw = 0; for( int g = 0; g < fontInfo->numGlyphs; g++ ) { if ( mh < fontInfo->glyphData[g].height ) { mh = fontInfo->glyphData[g].height; } if ( mw < fontInfo->glyphData[g].xSkip ) { mw = fontInfo->glyphData[g].xSkip; } } fontInfo->oldInfo[i].maxWidth = mw; fontInfo->oldInfo[i].maxHeight = mh; } } delete fd; return true; }
void MIDI_Play (const char *Name) { FILE *midiFile; char midiName[MAX_OSPATH], tempName[MAX_QPATH]; OSErr err; FSSpec midiSpec; FSRef midiRef; short midiRefNum; if (!bMidiInited) //don't try to play if there is no midi return; MIDI_Stop(); if (!Name || !*Name) { Sys_Printf("no midi music to play\n"); return; } q_snprintf (tempName, sizeof(tempName), "%s.%s", Name, "mid"); FS_OpenFile (va("%s/%s", "midi", tempName), &midiFile, false); if (!midiFile) { Con_Printf("music file %s not found\n", tempName); return; } else { if (file_from_pak) { int ret; Con_Printf("Extracting %s from pakfile\n", tempName); q_snprintf (midiName, sizeof(midiName), "%s/%s.%s", host_parms->userdir, TEMP_MUSICNAME, "mid"); ret = FS_CopyFromFile (midiFile, midiName, fs_filesize); fclose (midiFile); if (ret != 0) { Con_Printf("Error while extracting from pak\n"); return; } } else /* use the file directly */ { fclose (midiFile); q_snprintf (midiName, sizeof(midiName), "%s/%s/%s", fs_filepath, "midi", tempName); } } // converting path to FSSpec. found in CarbonCocoaIntegration.pdf: // page 27, Obtaining an FSSpec Structure err = FSPathMakeRef ((UInt8*)midiName, &midiRef, NULL); if (err != noErr) { Con_Printf ("MIDI: FSPathMakeRef: error while opening %s\n", midiName); return; } err = FSGetCatalogInfo (&midiRef, kFSCatInfoNone, NULL, NULL, &midiSpec, NULL); if (err != noErr) { Con_Printf ("MIDI: FSGetCatalogInfo: error while opening %s\n", midiName); return; } err = OpenMovieFile (&midiSpec, &midiRefNum, fsRdPerm); if (err != noErr) { Con_Printf ("MIDI: OpenMovieStream: error opening midi file\n"); return; } err = NewMovieFromFile (&midiTrack, midiRefNum, NULL, NULL, newMovieActive, NULL); if (err != noErr || !midiTrack) { Con_Printf ("MIDI: QuickTime error in creating stream.\n"); return; } GoToBeginningOfMovie (midiTrack); PrerollMovie (midiTrack, 0, 0); // pOx - set initial volume MIDI_SetVolume (&bgmvolume); StartMovie (midiTrack); Con_Printf ("Started midi music %s\n", tempName); }
static void CG_TaskDefense_f (void ) { trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONDEFENSE)); trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_DEFENSE)); }
// Dynamically names a demo and sets up the recording void demoAutoRecord(void) { //mod resetting allowed in init only memset(&demo.record, 0, sizeof(demo.record)-sizeof(demo.record.mod)); Q_strncpyz(demo.record.defaultName, "LastDemo/LastDemo_recording", sizeof(demo.record.defaultName)); Cbuf_AddText(va("record %s\n", demo.record.defaultName)); }
static void CG_TaskPatrol_f (void ) { trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONPATROL)); trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_PATROL)); }
/* ================= ConsoleCommand ================= */ qboolean ConsoleCommand( void ) { char cmd[MAX_TOKEN_CHARS]; trap_Argv( 0, cmd, sizeof( cmd ) ); if ( Q_stricmp (cmd, "entitylist") == 0 ) { Svcmd_EntityList_f(); return qtrue; } if ( Q_stricmp (cmd, "forceteam") == 0 ) { Svcmd_ForceTeam_f(); return qtrue; } if (Q_stricmp (cmd, "game_memory") == 0) { Svcmd_GameMem_f(); return qtrue; } if (Q_stricmp (cmd, "addbot") == 0) { Svcmd_AddBot_f(); return qtrue; } if (Q_stricmp (cmd, "botlist") == 0) { Svcmd_BotList_f(); return qtrue; } if (Q_stricmp (cmd, "abort_podium") == 0) { Svcmd_AbortPodium_f(); return qtrue; } if (Q_stricmp (cmd, "addip") == 0) { Svcmd_AddIP_f(); return qtrue; } if (Q_stricmp (cmd, "removeip") == 0) { Svcmd_RemoveIP_f(); return qtrue; } if (Q_stricmp (cmd, "listip") == 0) { trap_SendConsoleCommand( EXEC_NOW, "g_banIPs\n" ); return qtrue; } if (g_dedicated.integer) { if (Q_stricmp (cmd, "say") == 0) { trap_SendServerCommand( -1, va("print \"server: %s\"", ConcatArgs(1) ) ); return qtrue; } // everything else will also be printed as a say command trap_SendServerCommand( -1, va("print \"server: %s\"", ConcatArgs(0) ) ); return qtrue; } return qfalse; }
static void CG_TaskFollow_f (void ) { trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONFOLLOW)); trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_FOLLOW)); }
// called each map to initialize level.database struct // once initialized it must be deinitialized again to free resources associated with the database int G_DB_Init( void ) { char *dbpath; char fsgame[MAX_QPATH]; char homepath[MAX_OSPATH]; int err; #ifdef XPSAVE_SUPPORT qboolean xpsave_initialize = qfalse; #endif qboolean initialize = qfalse; if( level.database.initialized ) { G_DB_LogLastError( "G_DB_Init: attempt to initialize already initialized database" ); return DB_INIT_INIT; } if( g_dbpath.string ) { dbpath = va( "%s", g_dbpath.string ); } else { trap_Cvar_VariableStringBuffer( "fs_game", fsgame, sizeof( fsgame ) ); trap_Cvar_VariableStringBuffer( "fs_homepath", homepath, sizeof( homepath ) ); dbpath = va( "%s%c%s%c%s", homepath, PATH_SEP, fsgame, PATH_SEP, DB_STANDARD_FILENAME ); } #ifdef XPSAVE_SUPPORT // perform xpsave related sanity check on database if( g_xpsave.integer == 1 ) { err = G_XPSave_CheckDBSanity( dbpath ); if( err ) { switch( err ) { case XPSAVE_DB_READ: G_DB_LogLastError( "G_DB_Init: XPSave failed to read database" ); break; case XPSAVE_TABLE_NOTEXIST: err = G_XPSave_CreateNewDB( dbpath, qfalse ); break; case XPSAVE_TABLE_INCORRECT: G_DB_LogLastError( "G_DB_Init: XPSave failed to read schema" ); break; default: G_DB_LogLastError( va( "G_DB_Init: XPSave failed to initialize database default with error code %i", err ) ); break; } // if it still fails if( err ) { xpsave_initialize = qfalse; G_DB_PrintLastError(); } else { xpsave_initialize = qtrue; } } else { xpsave_initialize = qtrue; } } #endif // if one of the modules passes sanity tests, the database will be initialized #ifdef XPSAVE_SUPPORT // this only really makes sense if there are multiple modules operating on db, not just XPSave if( xpsave_initialize ) { initialize = qtrue; } #endif if( !initialize ) { G_LogPrintf( "G_DB_Init: no module initialized\n" ); return DB_INIT_MODFAIL; } // database can be initialized! Q_strncpyz( level.database.path, dbpath, MAX_OSPATH ); if( err = sqlite3_open( level.database.path, &level.database.db ) ) { // keep it open until deinit G_DB_LogLastError( va( "G_DB_Init: sqlite3_open failed with error code %i", err ) ); return err; } #ifdef XPSAVE_SUPPORT if( xpsave_initialize ) { level.database.initialized |= XPSAVE_INITIALZE_FLAG; } #endif G_LogPrintf( "Database: %s initialized\n", xpsave_initialize ? "XPSave" : "XPSave not" ); return 0; }
static void CG_TaskEscort_f (void ) { trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONFOLLOWCARRIER)); trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_ESCORT)); }
void GLSL_VertexAttribPointers(uint32_t attribBits) { qboolean animated; int newFrame, oldFrame; VBO_t *vbo = glState.currentVBO; if(!vbo) { ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VBO bound"); return; } // don't just call LogComment, or we will get a call to va() every frame! if(r_logFile->integer) { GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", vbo->name)); } // position/normal/tangent are always set in case of animation oldFrame = glState.vertexAttribsOldFrame; newFrame = glState.vertexAttribsNewFrame; animated = glState.vertexAnimation; if((attribBits & ATTR_POSITION) && (!(glState.vertexAttribPointersSet & ATTR_POSITION) || animated)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION )\n"); qglVertexAttribPointerARB(ATTR_INDEX_POSITION, 3, GL_FLOAT, 0, vbo->stride_xyz, BUFFER_OFFSET(vbo->ofs_xyz + newFrame * vbo->size_xyz)); glState.vertexAttribPointersSet |= ATTR_POSITION; } if((attribBits & ATTR_TEXCOORD) && !(glState.vertexAttribPointersSet & ATTR_TEXCOORD)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TEXCOORD )\n"); qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD0, 2, GL_FLOAT, 0, vbo->stride_st, BUFFER_OFFSET(vbo->ofs_st)); glState.vertexAttribPointersSet |= ATTR_TEXCOORD; } if((attribBits & ATTR_LIGHTCOORD) && !(glState.vertexAttribPointersSet & ATTR_LIGHTCOORD)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTCOORD )\n"); qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD1, 2, GL_FLOAT, 0, vbo->stride_lightmap, BUFFER_OFFSET(vbo->ofs_lightmap)); glState.vertexAttribPointersSet |= ATTR_LIGHTCOORD; } if((attribBits & ATTR_NORMAL) && (!(glState.vertexAttribPointersSet & ATTR_NORMAL) || animated)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL )\n"); qglVertexAttribPointerARB(ATTR_INDEX_NORMAL, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_normal, BUFFER_OFFSET(vbo->ofs_normal + newFrame * vbo->size_normal)); glState.vertexAttribPointersSet |= ATTR_NORMAL; } #ifdef USE_VERT_TANGENT_SPACE if((attribBits & ATTR_TANGENT) && (!(glState.vertexAttribPointersSet & ATTR_TANGENT) || animated)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT )\n"); qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_tangent, BUFFER_OFFSET(vbo->ofs_tangent + newFrame * vbo->size_normal)); // FIXME glState.vertexAttribPointersSet |= ATTR_TANGENT; } #endif if((attribBits & ATTR_COLOR) && !(glState.vertexAttribPointersSet & ATTR_COLOR)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_COLOR )\n"); qglVertexAttribPointerARB(ATTR_INDEX_COLOR, 4, GL_FLOAT, 0, vbo->stride_vertexcolor, BUFFER_OFFSET(vbo->ofs_vertexcolor)); glState.vertexAttribPointersSet |= ATTR_COLOR; } if((attribBits & ATTR_LIGHTDIRECTION) && !(glState.vertexAttribPointersSet & ATTR_LIGHTDIRECTION)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTDIRECTION )\n"); qglVertexAttribPointerARB(ATTR_INDEX_LIGHTDIRECTION, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_lightdir, BUFFER_OFFSET(vbo->ofs_lightdir)); glState.vertexAttribPointersSet |= ATTR_LIGHTDIRECTION; } if((attribBits & ATTR_POSITION2) && (!(glState.vertexAttribPointersSet & ATTR_POSITION2) || animated)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION2 )\n"); qglVertexAttribPointerARB(ATTR_INDEX_POSITION2, 3, GL_FLOAT, 0, vbo->stride_xyz, BUFFER_OFFSET(vbo->ofs_xyz + oldFrame * vbo->size_xyz)); glState.vertexAttribPointersSet |= ATTR_POSITION2; } if((attribBits & ATTR_NORMAL2) && (!(glState.vertexAttribPointersSet & ATTR_NORMAL2) || animated)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL2 )\n"); qglVertexAttribPointerARB(ATTR_INDEX_NORMAL2, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_normal, BUFFER_OFFSET(vbo->ofs_normal + oldFrame * vbo->size_normal)); glState.vertexAttribPointersSet |= ATTR_NORMAL2; } #ifdef USE_VERT_TANGENT_SPACE if((attribBits & ATTR_TANGENT2) && (!(glState.vertexAttribPointersSet & ATTR_TANGENT2) || animated)) { GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT2 )\n"); qglVertexAttribPointerARB(ATTR_INDEX_TANGENT2, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_tangent, BUFFER_OFFSET(vbo->ofs_tangent + oldFrame * vbo->size_normal)); // FIXME glState.vertexAttribPointersSet |= ATTR_TANGENT2; } #endif }
/* ================= CG_SizeDown_f Keybinding command ================= */ static void CG_SizeDown_f (void) { trap_Cvar_Set("cg_viewsize", va("%i",(int)(cg_viewsize.integer-10))); }
static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, char *dest, int size ) { float fbufWidthScale, fbufHeightScale; dest[0] = '\0'; // HACK: abuse the GLSL preprocessor to turn GLSL 1.20 shaders into 1.30 ones if(glRefConfig.glslMajorVersion > 1 || (glRefConfig.glslMajorVersion == 1 && glRefConfig.glslMinorVersion >= 30)) { Q_strcat(dest, size, "#version 130\n"); if(shaderType == GL_VERTEX_SHADER_ARB) { Q_strcat(dest, size, "#define attribute in\n"); Q_strcat(dest, size, "#define varying out\n"); } else { Q_strcat(dest, size, "#define varying in\n"); Q_strcat(dest, size, "out vec4 out_Color;\n"); Q_strcat(dest, size, "#define gl_FragColor out_Color\n"); } } else { Q_strcat(dest, size, "#version 120\n"); } // HACK: add some macros to avoid extra uniforms and save speed and code maintenance //Q_strcat(dest, size, // va("#ifndef r_SpecularExponent\n#define r_SpecularExponent %f\n#endif\n", r_specularExponent->value)); //Q_strcat(dest, size, // va("#ifndef r_SpecularScale\n#define r_SpecularScale %f\n#endif\n", r_specularScale->value)); //Q_strcat(dest, size, // va("#ifndef r_NormalScale\n#define r_NormalScale %f\n#endif\n", r_normalScale->value)); Q_strcat(dest, size, "#ifndef M_PI\n#define M_PI 3.14159265358979323846\n#endif\n"); //Q_strcat(dest, size, va("#ifndef MAX_SHADOWMAPS\n#define MAX_SHADOWMAPS %i\n#endif\n", MAX_SHADOWMAPS)); Q_strcat(dest, size, va("#ifndef deformGen_t\n" "#define deformGen_t\n" "#define DGEN_WAVE_SIN %i\n" "#define DGEN_WAVE_SQUARE %i\n" "#define DGEN_WAVE_TRIANGLE %i\n" "#define DGEN_WAVE_SAWTOOTH %i\n" "#define DGEN_WAVE_INVERSE_SAWTOOTH %i\n" "#define DGEN_BULGE %i\n" "#define DGEN_MOVE %i\n" "#endif\n", DGEN_WAVE_SIN, DGEN_WAVE_SQUARE, DGEN_WAVE_TRIANGLE, DGEN_WAVE_SAWTOOTH, DGEN_WAVE_INVERSE_SAWTOOTH, DGEN_BULGE, DGEN_MOVE)); Q_strcat(dest, size, va("#ifndef tcGen_t\n" "#define tcGen_t\n" "#define TCGEN_LIGHTMAP %i\n" "#define TCGEN_TEXTURE %i\n" "#define TCGEN_ENVIRONMENT_MAPPED %i\n" "#define TCGEN_FOG %i\n" "#define TCGEN_VECTOR %i\n" "#endif\n", TCGEN_LIGHTMAP, TCGEN_TEXTURE, TCGEN_ENVIRONMENT_MAPPED, TCGEN_FOG, TCGEN_VECTOR)); Q_strcat(dest, size, va("#ifndef colorGen_t\n" "#define colorGen_t\n" "#define CGEN_LIGHTING_DIFFUSE %i\n" "#endif\n", CGEN_LIGHTING_DIFFUSE)); Q_strcat(dest, size, va("#ifndef alphaGen_t\n" "#define alphaGen_t\n" "#define AGEN_LIGHTING_SPECULAR %i\n" "#define AGEN_PORTAL %i\n" "#endif\n", AGEN_LIGHTING_SPECULAR, AGEN_PORTAL)); Q_strcat(dest, size, va("#ifndef texenv_t\n" "#define texenv_t\n" "#define TEXENV_MODULATE %i\n" "#define TEXENV_ADD %i\n" "#define TEXENV_REPLACE %i\n" "#endif\n", GL_MODULATE, GL_ADD, GL_REPLACE)); fbufWidthScale = 1.0f / ((float)glConfig.vidWidth); fbufHeightScale = 1.0f / ((float)glConfig.vidHeight); Q_strcat(dest, size, va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale)); if (r_materialGamma->value != 1.0f) Q_strcat(dest, size, va("#ifndef r_materialGamma\n#define r_materialGamma %f\n#endif\n", r_materialGamma->value)); if (r_lightGamma->value != 1.0f) Q_strcat(dest, size, va("#ifndef r_lightGamma\n#define r_lightGamma %f\n#endif\n", r_lightGamma->value)); if (r_framebufferGamma->value != 1.0f) Q_strcat(dest, size, va("#ifndef r_framebufferGamma\n#define r_framebufferGamma %f\n#endif\n", r_framebufferGamma->value)); if (r_tonemapGamma->value != 1.0f) Q_strcat(dest, size, va("#ifndef r_tonemapGamma\n#define r_tonemapGamma %f\n#endif\n", r_tonemapGamma->value)); if (extra) { Q_strcat(dest, size, extra); } // OK we added a lot of stuff but if we do something bad in the GLSL shaders then we want the proper line // so we have to reset the line counting Q_strcat(dest, size, "#line 0\n"); }
/* =============== GLimp_Init This routine is responsible for initializing the OS specific portions of OpenGL =============== */ void GLimp_Init( void ) { ri.Printf( PRINT_DEVELOPER, "Glimp_Init( )\n" ); r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH ); r_sdlDriver = ri.Cvar_Get( "r_sdlDriver", "", CVAR_ROM ); r_allowResize = ri.Cvar_Get( "r_allowResize", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_centerWindow = ri.Cvar_Get( "r_centerWindow", "0", CVAR_ARCHIVE | CVAR_LATCH ); if( ri.Cvar_VariableIntegerValue( "com_abnormalExit" ) ) { ri.Cvar_Set( "r_mode", va( "%d", R_MODE_FALLBACK ) ); ri.Cvar_Set( "r_fullscreen", "0" ); ri.Cvar_Set( "r_centerWindow", "0" ); ri.Cvar_Set( "com_abnormalExit", "0" ); } ri.Sys_GLimpInit( ); // Create the window and set up the context if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, r_noborder->integer)) goto success; // Try again, this time in a platform specific "safe mode" ri.Sys_GLimpSafeInit( ); if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, qfalse)) goto success; // Finally, try the default screen resolution if( r_mode->integer != R_MODE_FALLBACK ) { ri.Printf( PRINT_ALL, "Setting r_mode %d failed, falling back on r_mode %d\n", r_mode->integer, R_MODE_FALLBACK ); if(GLimp_StartDriverAndSetMode(R_MODE_FALLBACK, qfalse, qfalse)) goto success; } // Nothing worked, give up ri.Error( ERR_FATAL, "GLimp_Init() - could not load OpenGL subsystem" ); success: // These values force the UI to disable driver selection glConfig.driverType = GLDRV_ICD; glConfig.hardwareType = GLHW_GENERIC; // Only using SDL_SetWindowBrightness to determine if hardware gamma is supported glConfig.deviceSupportsGamma = !r_ignorehwgamma->integer && SDL_SetWindowBrightness( SDL_window, 1.0f ) >= 0; // get our config strings Q_strncpyz( glConfig.vendor_string, (char *) qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) ); Q_strncpyz( glConfig.renderer_string, (char *) qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) ); if (*glConfig.renderer_string && glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] == '\n') glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] = 0; Q_strncpyz( glConfig.version_string, (char *) qglGetString (GL_VERSION), sizeof( glConfig.version_string ) ); Q_strncpyz( glConfig.extensions_string, (char *) qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) ); // initialize extensions GLimp_InitExtensions( ); ri.Cvar_Get( "r_availableModes", "", CVAR_ROM ); // This depends on SDL_INIT_VIDEO, hence having it here ri.IN_Init( SDL_window ); }
void GLSL_InitGPUShaders(void) { int startTime, endTime; int i; char extradefines[1024]; int attribs; int numGenShaders = 0, numLightShaders = 0, numEtcShaders = 0; ri.Printf(PRINT_ALL, "------- GLSL_InitGPUShaders -------\n"); R_IssuePendingRenderCommands(); startTime = ri.Milliseconds(); for (i = 0; i < GENERICDEF_COUNT; i++) { attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_NORMAL | ATTR_COLOR; extradefines[0] = '\0'; if (i & GENERICDEF_USE_DEFORM_VERTEXES) Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n"); if (i & GENERICDEF_USE_TCGEN_AND_TCMOD) { Q_strcat(extradefines, 1024, "#define USE_TCGEN\n"); Q_strcat(extradefines, 1024, "#define USE_TCMOD\n"); } if (i & GENERICDEF_USE_VERTEX_ANIMATION) { Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n"); attribs |= ATTR_POSITION2 | ATTR_NORMAL2; } if (i & GENERICDEF_USE_FOG) Q_strcat(extradefines, 1024, "#define USE_FOG\n"); if (i & GENERICDEF_USE_RGBAGEN) Q_strcat(extradefines, 1024, "#define USE_RGBAGEN\n"); if (i & GENERICDEF_USE_LIGHTMAP) Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); if (r_hdr->integer && !glRefConfig.floatLightmap) Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n"); if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackShader_generic_vp, fallbackShader_generic_fp)) { ri.Error(ERR_FATAL, "Could not load generic shader!"); } GLSL_InitUniforms(&tr.genericShader[i]); qglUseProgramObjectARB(tr.genericShader[i].program); GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.genericShader[i]); numGenShaders++; } attribs = ATTR_POSITION | ATTR_TEXCOORD; if (!GLSL_InitGPUShader(&tr.textureColorShader, "texturecolor", attribs, qtrue, NULL, qfalse, fallbackShader_texturecolor_vp, fallbackShader_texturecolor_fp)) { ri.Error(ERR_FATAL, "Could not load texturecolor shader!"); } GLSL_InitUniforms(&tr.textureColorShader); qglUseProgramObjectARB(tr.textureColorShader.program); GLSL_SetUniformInt(&tr.textureColorShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.textureColorShader); numEtcShaders++; for (i = 0; i < FOGDEF_COUNT; i++) { attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD; extradefines[0] = '\0'; if (i & FOGDEF_USE_DEFORM_VERTEXES) Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n"); if (i & FOGDEF_USE_VERTEX_ANIMATION) Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n"); if (!GLSL_InitGPUShader(&tr.fogShader[i], "fogpass", attribs, qtrue, extradefines, qtrue, fallbackShader_fogpass_vp, fallbackShader_fogpass_fp)) { ri.Error(ERR_FATAL, "Could not load fogpass shader!"); } GLSL_InitUniforms(&tr.fogShader[i]); GLSL_FinishGPUShader(&tr.fogShader[i]); numEtcShaders++; } for (i = 0; i < DLIGHTDEF_COUNT; i++) { attribs = ATTR_POSITION | ATTR_NORMAL | ATTR_TEXCOORD; extradefines[0] = '\0'; if (i & DLIGHTDEF_USE_DEFORM_VERTEXES) { Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n"); } if (!GLSL_InitGPUShader(&tr.dlightShader[i], "dlight", attribs, qtrue, extradefines, qtrue, fallbackShader_dlight_vp, fallbackShader_dlight_fp)) { ri.Error(ERR_FATAL, "Could not load dlight shader!"); } GLSL_InitUniforms(&tr.dlightShader[i]); qglUseProgramObjectARB(tr.dlightShader[i].program); GLSL_SetUniformInt(&tr.dlightShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.dlightShader[i]); numEtcShaders++; } for (i = 0; i < LIGHTDEF_COUNT; i++) { int lightType = i & LIGHTDEF_LIGHTTYPE_MASK; qboolean fastLight = !(r_normalMapping->integer || r_specularMapping->integer); // skip impossible combos if ((i & LIGHTDEF_USE_PARALLAXMAP) && !r_parallaxMapping->integer) continue; if (!lightType && (i & LIGHTDEF_USE_PARALLAXMAP)) continue; if (!lightType && (i & LIGHTDEF_USE_SHADOWMAP)) continue; attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL; extradefines[0] = '\0'; if (r_deluxeSpecular->value > 0.000001f) Q_strcat(extradefines, 1024, va("#define r_deluxeSpecular %f\n", r_deluxeSpecular->value)); if (r_specularIsMetallic->value) Q_strcat(extradefines, 1024, "#define SPECULAR_IS_METALLIC\n"); if (r_dlightMode->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); if (1) Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n"); if (r_hdr->integer && !glRefConfig.floatLightmap) Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n"); if (lightType) { Q_strcat(extradefines, 1024, "#define USE_LIGHT\n"); if (fastLight) Q_strcat(extradefines, 1024, "#define USE_FAST_LIGHT\n"); switch (lightType) { case LIGHTDEF_USE_LIGHTMAP: Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); if (r_deluxeMapping->integer && !fastLight) Q_strcat(extradefines, 1024, "#define USE_DELUXEMAP\n"); attribs |= ATTR_LIGHTCOORD | ATTR_LIGHTDIRECTION; break; case LIGHTDEF_USE_LIGHT_VECTOR: Q_strcat(extradefines, 1024, "#define USE_LIGHT_VECTOR\n"); break; case LIGHTDEF_USE_LIGHT_VERTEX: Q_strcat(extradefines, 1024, "#define USE_LIGHT_VERTEX\n"); attribs |= ATTR_LIGHTDIRECTION; break; default: break; } if (r_normalMapping->integer) { Q_strcat(extradefines, 1024, "#define USE_NORMALMAP\n"); if (r_normalMapping->integer == 2) Q_strcat(extradefines, 1024, "#define USE_OREN_NAYAR\n"); if (r_normalMapping->integer == 3) Q_strcat(extradefines, 1024, "#define USE_TRIACE_OREN_NAYAR\n"); #ifdef USE_VERT_TANGENT_SPACE Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n"); attribs |= ATTR_TANGENT; #endif if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer) Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n"); } if (r_specularMapping->integer) { Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n"); switch (r_specularMapping->integer) { case 1: default: Q_strcat(extradefines, 1024, "#define USE_BLINN\n"); break; case 2: Q_strcat(extradefines, 1024, "#define USE_BLINN_FRESNEL\n"); break; case 3: Q_strcat(extradefines, 1024, "#define USE_MCAULEY\n"); break; case 4: Q_strcat(extradefines, 1024, "#define USE_GOTANDA\n"); break; case 5: Q_strcat(extradefines, 1024, "#define USE_LAZAROV\n"); break; } } if (r_cubeMapping->integer) Q_strcat(extradefines, 1024, "#define USE_CUBEMAP\n"); } if (i & LIGHTDEF_USE_SHADOWMAP) { Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); if (r_sunlightMode->integer == 1) Q_strcat(extradefines, 1024, "#define SHADOWMAP_MODULATE\n"); else if (r_sunlightMode->integer == 2) Q_strcat(extradefines, 1024, "#define USE_PRIMARY_LIGHT\n"); } if (i & LIGHTDEF_USE_TCGEN_AND_TCMOD) { Q_strcat(extradefines, 1024, "#define USE_TCGEN\n"); Q_strcat(extradefines, 1024, "#define USE_TCMOD\n"); } if (i & LIGHTDEF_ENTITY) { Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n#define USE_MODELMATRIX\n"); attribs |= ATTR_POSITION2 | ATTR_NORMAL2; #ifdef USE_VERT_TANGENT_SPACE if (r_normalMapping->integer) { attribs |= ATTR_TANGENT2; } #endif } if (!GLSL_InitGPUShader(&tr.lightallShader[i], "lightall", attribs, qtrue, extradefines, qtrue, fallbackShader_lightall_vp, fallbackShader_lightall_fp)) { ri.Error(ERR_FATAL, "Could not load lightall shader!"); } GLSL_InitUniforms(&tr.lightallShader[i]); qglUseProgramObjectARB(tr.lightallShader[i].program); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_NORMALMAP, TB_NORMALMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_DELUXEMAP, TB_DELUXEMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SPECULARMAP, TB_SPECULARMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SHADOWMAP, TB_SHADOWMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_CUBEMAP, TB_CUBEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.lightallShader[i]); numLightShaders++; } attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.shadowmapShader, "shadowfill", attribs, qtrue, extradefines, qtrue, fallbackShader_shadowfill_vp, fallbackShader_shadowfill_fp)) { ri.Error(ERR_FATAL, "Could not load shadowfill shader!"); } GLSL_InitUniforms(&tr.shadowmapShader); GLSL_FinishGPUShader(&tr.shadowmapShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_NORMAL; extradefines[0] = '\0'; Q_strcat(extradefines, 1024, "#define USE_PCF\n#define USE_DISCARD\n"); if (!GLSL_InitGPUShader(&tr.pshadowShader, "pshadow", attribs, qtrue, extradefines, qtrue, fallbackShader_pshadow_vp, fallbackShader_pshadow_fp)) { ri.Error(ERR_FATAL, "Could not load pshadow shader!"); } GLSL_InitUniforms(&tr.pshadowShader); qglUseProgramObjectARB(tr.pshadowShader.program); GLSL_SetUniformInt(&tr.pshadowShader, UNIFORM_SHADOWMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.pshadowShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.down4xShader, "down4x", attribs, qtrue, extradefines, qtrue, fallbackShader_down4x_vp, fallbackShader_down4x_fp)) { ri.Error(ERR_FATAL, "Could not load down4x shader!"); } GLSL_InitUniforms(&tr.down4xShader); qglUseProgramObjectARB(tr.down4xShader.program); GLSL_SetUniformInt(&tr.down4xShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.down4xShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.bokehShader, "bokeh", attribs, qtrue, extradefines, qtrue, fallbackShader_bokeh_vp, fallbackShader_bokeh_fp)) { ri.Error(ERR_FATAL, "Could not load bokeh shader!"); } GLSL_InitUniforms(&tr.bokehShader); qglUseProgramObjectARB(tr.bokehShader.program); GLSL_SetUniformInt(&tr.bokehShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.bokehShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.tonemapShader, "tonemap", attribs, qtrue, extradefines, qtrue, fallbackShader_tonemap_vp, fallbackShader_tonemap_fp)) { ri.Error(ERR_FATAL, "Could not load tonemap shader!"); } GLSL_InitUniforms(&tr.tonemapShader); qglUseProgramObjectARB(tr.tonemapShader.program); GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_TEXTUREMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_LEVELSMAP, TB_LEVELSMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.tonemapShader); numEtcShaders++; for (i = 0; i < 2; i++) { attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!i) Q_strcat(extradefines, 1024, "#define FIRST_PASS\n"); if (!GLSL_InitGPUShader(&tr.calclevels4xShader[i], "calclevels4x", attribs, qtrue, extradefines, qtrue, fallbackShader_calclevels4x_vp, fallbackShader_calclevels4x_fp)) { ri.Error(ERR_FATAL, "Could not load calclevels4x shader!"); } GLSL_InitUniforms(&tr.calclevels4xShader[i]); qglUseProgramObjectARB(tr.calclevels4xShader[i].program); GLSL_SetUniformInt(&tr.calclevels4xShader[i], UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.calclevels4xShader[i]); numEtcShaders++; } attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (r_shadowFilter->integer >= 1) Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER\n"); if (r_shadowFilter->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER2\n"); if (r_shadowCascadeZFar->integer != 0) Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n"); Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %f\n", r_shadowMapSize->value)); Q_strcat(extradefines, 1024, va("#define r_shadowCascadeZFar %f\n", r_shadowCascadeZFar->value)); if (!GLSL_InitGPUShader(&tr.shadowmaskShader, "shadowmask", attribs, qtrue, extradefines, qtrue, fallbackShader_shadowmask_vp, fallbackShader_shadowmask_fp)) { ri.Error(ERR_FATAL, "Could not load shadowmask shader!"); } GLSL_InitUniforms(&tr.shadowmaskShader); qglUseProgramObjectARB(tr.shadowmaskShader.program); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP, TB_SHADOWMAP); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, TB_SHADOWMAP2); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, TB_SHADOWMAP3); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, TB_SHADOWMAP4); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.shadowmaskShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.ssaoShader, "ssao", attribs, qtrue, extradefines, qtrue, fallbackShader_ssao_vp, fallbackShader_ssao_fp)) { ri.Error(ERR_FATAL, "Could not load ssao shader!"); } GLSL_InitUniforms(&tr.ssaoShader); qglUseProgramObjectARB(tr.ssaoShader.program); GLSL_SetUniformInt(&tr.ssaoShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.ssaoShader); numEtcShaders++; for (i = 0; i < 2; i++) { attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (i & 1) Q_strcat(extradefines, 1024, "#define USE_VERTICAL_BLUR\n"); else Q_strcat(extradefines, 1024, "#define USE_HORIZONTAL_BLUR\n"); if (!GLSL_InitGPUShader(&tr.depthBlurShader[i], "depthBlur", attribs, qtrue, extradefines, qtrue, fallbackShader_depthblur_vp, fallbackShader_depthblur_fp)) { ri.Error(ERR_FATAL, "Could not load depthBlur shader!"); } GLSL_InitUniforms(&tr.depthBlurShader[i]); qglUseProgramObjectARB(tr.depthBlurShader[i].program); GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENIMAGEMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENDEPTHMAP, TB_LIGHTMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.depthBlurShader[i]); numEtcShaders++; } #if 0 attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.testcubeShader, "testcube", attribs, qtrue, extradefines, qtrue, NULL, NULL)) { ri.Error(ERR_FATAL, "Could not load testcube shader!"); } GLSL_InitUniforms(&tr.testcubeShader); qglUseProgramObjectARB(tr.testcubeShader.program); GLSL_SetUniformInt(&tr.testcubeShader, UNIFORM_TEXTUREMAP, TB_COLORMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.testcubeShader); numEtcShaders++; #endif endTime = ri.Milliseconds(); ri.Printf(PRINT_ALL, "loaded %i GLSL shaders (%i gen %i light %i etc) in %5.2f seconds\n", numGenShaders + numLightShaders + numEtcShaders, numGenShaders, numLightShaders, numEtcShaders, (endTime - startTime) / 1000.0); }
/* ================ idLight::Spawn ================ */ void idLight::Spawn( void ) { bool start_off; bool needBroken; const char *demonic_shader; // do the parsing the same way dmap and the editor do gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &renderLight ); // we need the origin and axis relative to the physics origin/axis localLightOrigin = ( renderLight.origin - GetPhysics()->GetOrigin() ) * GetPhysics()->GetAxis().Transpose(); localLightAxis = renderLight.axis * GetPhysics()->GetAxis().Transpose(); // set the base color from the shader parms baseColor.Set( renderLight.shaderParms[ SHADERPARM_RED ], renderLight.shaderParms[ SHADERPARM_GREEN ], renderLight.shaderParms[ SHADERPARM_BLUE ] ); // set the number of light levels spawnArgs.GetInt( "levels", "1", levels ); currentLevel = levels; if( levels <= 0 ) { gameLocal.Error( "Invalid light level set on entity #%d(%s)", entityNumber, name.c_str() ); } // make sure the demonic shader is cached if( spawnArgs.GetString( "mat_demonic", NULL, &demonic_shader ) ) { declManager->FindType( DECL_MATERIAL, demonic_shader ); } // game specific functionality, not mirrored in // editor or dmap light parsing // also put the light texture on the model, so light flares // can get the current intensity of the light renderEntity.referenceShader = renderLight.shader; lightDefHandle = -1; // no static version yet // see if an optimized shadow volume exists // the renderer will ignore this value after a light has been moved, // but there may still be a chance to get it wrong if the game moves // a light before the first present, and doesn't clear the prelight renderLight.prelightModel = 0; if( name[ 0 ] ) { // this will return 0 if not found renderLight.prelightModel = renderModelManager->CheckModel( va( "_prelight_%s", name.c_str() ) ); } spawnArgs.GetBool( "start_off", "0", start_off ); if( start_off ) { Off(); } health = spawnArgs.GetInt( "health", "0" ); spawnArgs.GetString( "broken", "", brokenModel ); spawnArgs.GetBool( "break", "0", breakOnTrigger ); spawnArgs.GetInt( "count", "1", count ); triggercount = 0; fadeFrom.Set( 1, 1, 1, 1 ); fadeTo.Set( 1, 1, 1, 1 ); fadeStart = 0; fadeEnd = 0; // if we have a health make light breakable if( health ) { idStr model = spawnArgs.GetString( "model" ); // get the visual model if( !model.Length() ) { gameLocal.Error( "Breakable light without a model set on entity #%d(%s)", entityNumber, name.c_str() ); } fl.takedamage = true; // see if we need to create a broken model name needBroken = true; if( model.Length() && !brokenModel.Length() ) { int pos; needBroken = false; pos = model.Find( "." ); if( pos < 0 ) { pos = model.Length(); } if( pos > 0 ) { model.Left( pos, brokenModel ); } brokenModel += "_broken"; if( pos > 0 ) { brokenModel += &model[ pos ]; } } // make sure the model gets cached if( !renderModelManager->CheckModel( brokenModel ) ) { if( needBroken ) { gameLocal.Error( "Model '%s' not found for entity %d(%s)", brokenModel.c_str(), entityNumber, name.c_str() ); } else { brokenModel = ""; } } GetPhysics()->SetContents( spawnArgs.GetBool( "nonsolid" ) ? 0 : CONTENTS_SOLID ); // make sure the collision model gets cached idClipModel::CheckModel( brokenModel ); } PostEventMS( &EV_PostSpawn, 0 ); // sikk---> Soft Shadows PostProcess // only put lights that cast shadows into the list if( spawnArgs.GetInt( "noshadows" ) == 0 ) { gameLocal.currentLights.Append( entityNumber ); } // <---sikk UpdateVisuals(); }
/* ================ GEOptionsDlg_GridProc Dialog procedure for the grid settings tab ================ */ static INT_PTR CALLBACK GEOptionsDlg_GridProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch ( msg ) { case WM_INITDIALOG: // Copy the options information to the dialog controls ColorButton_SetColor ( GetDlgItem ( hwnd, IDC_GUIED_GRIDCOLOR ), RGB(gApp.GetOptions().GetGridColor()[0]*255,gApp.GetOptions().GetGridColor()[1]*255,gApp.GetOptions().GetGridColor()[2]*255) ); SetWindowText ( GetDlgItem ( hwnd, IDC_GUIED_SPACINGWIDTH ), va("%d", gApp.GetOptions().GetGridWidth ( ) ) ); SetWindowText ( GetDlgItem ( hwnd, IDC_GUIED_SPACINGHEIGHT ), va("%d", gApp.GetOptions().GetGridHeight ( ) ) ); CheckDlgButton ( hwnd, IDC_GUIED_GRIDVISIBLE, gApp.GetOptions().GetGridVisible()?BST_CHECKED:BST_UNCHECKED ); CheckDlgButton ( hwnd, IDC_GUIED_GRIDSNAP, gApp.GetOptions().GetGridSnap()?BST_CHECKED:BST_UNCHECKED ); return TRUE; case WM_DRAWITEM: ColorButton_DrawItem ( GetDlgItem ( hwnd, wParam ), (LPDRAWITEMSTRUCT)lParam ); return TRUE; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_APPLY: { char temp[32]; // Copy the dialog control data back to the options GetWindowText ( GetDlgItem ( hwnd, IDC_GUIED_SPACINGWIDTH ), temp, 32 ); gApp.GetOptions().SetGridWidth(atol(temp)); GetWindowText ( GetDlgItem ( hwnd, IDC_GUIED_SPACINGHEIGHT ), temp, 32 ); gApp.GetOptions().SetGridHeight(atol(temp)); gApp.GetOptions().SetGridVisible ( IsDlgButtonChecked ( hwnd, IDC_GUIED_GRIDVISIBLE ) != 0 ); gApp.GetOptions().SetGridSnap ( IsDlgButtonChecked ( hwnd, IDC_GUIED_GRIDSNAP ) != 0 ); gApp.GetOptions().SetGridColor ( ColorButton_GetColor ( GetDlgItem ( hwnd, IDC_GUIED_GRIDCOLOR ) ) ); break; } } break; case WM_COMMAND: switch ( LOWORD ( wParam ) ) { case IDC_GUIED_GRIDCOLOR: { CHOOSECOLOR col; ZeroMemory ( &col, sizeof(col) ); col.lStructSize = sizeof(col); col.lpCustColors = gApp.GetOptions().GetCustomColors ( ); col.hwndOwner = hwnd; col.hInstance = NULL; col.Flags = CC_RGBINIT; col.rgbResult = RGB(gApp.GetOptions().GetGridColor()[0]*255,gApp.GetOptions().GetGridColor()[1]*255,gApp.GetOptions().GetGridColor()[2]*255); if ( ChooseColor ( &col ) ) { ColorButton_SetColor ( GetDlgItem ( hwnd, IDC_GUIED_GRIDCOLOR ), col.rgbResult ); } break; } } return TRUE; } return FALSE; }
/* ================= R_AddMDCSurfaces ================= */ void R_AddMDCSurfaces(trRefEntity_t *ent) { int i; mdcHeader_t *header = 0; mdcSurface_t *surface = 0; md3Shader_t *md3Shader = 0; shader_t *shader = 0; int cull; int lod; int fogNum; qboolean personalModel; // don't add third_person objects if not in a portal personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal; if (ent->e.renderfx & RF_WRAP_FRAMES) { ent->e.frame %= tr.currentModel->model.mdc[0]->numFrames; ent->e.oldframe %= tr.currentModel->model.mdc[0]->numFrames; } // // Validate the frames so there is no chance of a crash. // This will write directly into the entity structure, so // when the surfaces are rendered, they don't need to be // range checked again. // if ((ent->e.frame >= tr.currentModel->model.mdc[0]->numFrames) || (ent->e.frame < 0) || (ent->e.oldframe >= tr.currentModel->model.mdc[0]->numFrames) || (ent->e.oldframe < 0)) { ri.Printf(PRINT_DEVELOPER, "R_AddMDCSurfaces: no such frame %d to %d for '%s'\n", ent->e.oldframe, ent->e.frame, tr.currentModel->name); ent->e.frame = 0; ent->e.oldframe = 0; } // // compute LOD // if (ent->e.renderfx & RF_FORCENOLOD) { lod = 0; } else { lod = R_ComputeLOD(ent); } header = tr.currentModel->model.mdc[lod]; // // cull the entire model if merged bounding box of both frames // is outside the view frustum. // cull = R_CullModel(header, ent); if (cull == CULL_OUT) { return; } // // set up lighting now that we know we aren't culled // if (!personalModel || r_shadows->integer > 1) { R_SetupEntityLighting(&tr.refdef, ent); } // // see if we are in a fog volume // fogNum = R_ComputeFogNum(header, ent); // // draw all surfaces // surface = ( mdcSurface_t * )((byte *)header + header->ofsSurfaces); for (i = 0 ; i < header->numSurfaces ; i++) { if (ent->e.customShader) { shader = R_GetShaderByHandle(ent->e.customShader); } else if (ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins) { skin_t *skin; int hash; int j; skin = R_GetSkinByHandle(ent->e.customSkin); // match the surface name to something in the skin file shader = tr.defaultShader; //----(SA) added blink if (ent->e.renderfx & RF_BLINK) { char *s = va("%s_b", surface->name); // append '_b' for 'blink' hash = Com_HashKey(s, strlen(s)); for (j = 0 ; j < skin->numSurfaces ; j++) { if (hash != skin->surfaces[j]->hash) { continue; } if (!strcmp(skin->surfaces[j]->name, s)) { shader = skin->surfaces[j]->shader; break; } } } if (shader == tr.defaultShader) // blink reference in skin was not found { hash = Com_HashKey(surface->name, sizeof(surface->name)); for (j = 0 ; j < skin->numSurfaces ; j++) { // the names have both been lowercased if (hash != skin->surfaces[j]->hash) { continue; } if (!strcmp(skin->surfaces[j]->name, surface->name)) { shader = skin->surfaces[j]->shader; break; } } } //----(SA) end } else if (surface->numShaders <= 0) { shader = tr.defaultShader; } else { md3Shader = ( md3Shader_t * )((byte *)surface + surface->ofsShaders); md3Shader += ent->e.skinNum % surface->numShaders; shader = tr.shaders[md3Shader->shaderIndex]; } // we will add shadows even if the main object isn't visible in the view // stencil shadows can't do personal models unless I polyhedron clip if (!personalModel && r_shadows->integer == 2 && fogNum == 0 && !(ent->e.renderfx & (RF_NOSHADOW | RF_DEPTHHACK)) && shader->sort == SS_OPAQUE) { R_AddDrawSurf((void *)surface, tr.shadowShader, 0, 0, 0); } // projection shadows work fine with personal models if (r_shadows->integer == 3 && fogNum == 0 && (ent->e.renderfx & RF_SHADOW_PLANE) && shader->sort == SS_OPAQUE) { R_AddDrawSurf((void *)surface, tr.projectionShadowShader, 0, 0, 0); } //----(SA) for testing polygon shadows (on /all/ models) if (r_shadows->integer == 4) { R_AddDrawSurf((void *)surface, tr.projectionShadowShader, 0, 0, 0); } //----(SA) done testing // don't add third_person objects if not viewing through a portal if (!personalModel) { R_AddDrawSurf((void *)surface, shader, fogNum, 0, 0); } surface = ( mdcSurface_t * )((byte *)surface + surface->ofsEnd); } }
// ************** PLAYERS // // Show client info void G_players_cmd(gentity_t *ent, unsigned int dwCommand, qboolean fValue) { int i, idnum, max_rate, cnt=0, tteam; int user_rate, user_snaps; gclient_t *cl; gentity_t *cl_ent; char n2[MAX_NETNAME], ready[16], ref[16], rate[256]; char *s, *tc, *coach, userinfo[MAX_INFO_STRING]; if(g_gamestate.integer == GS_PLAYING) { if(ent) { CP("print \"\n^3 ID^1 : ^3Player Nudge Rate MaxPkts Snaps\n\""); CP( "print \"^1-----------------------------------------------------------^7\n\""); } else { G_Printf(" ID : Player Nudge Rate MaxPkts Snaps\n"); G_Printf("-----------------------------------------------------------\n"); } } else { if(ent) { CP("print \"\n^3Status^1 : ^3ID^1 : ^3Player Nudge Rate MaxPkts Snaps\n\""); CP( "print \"^1---------------------------------------------------------------------^7\n\""); } else { G_Printf("Status : ID : Player Nudge Rate MaxPkts Snaps\n"); G_Printf("---------------------------------------------------------------------\n"); } } max_rate = trap_Cvar_VariableIntegerValue("sv_maxrate"); for(i=0; i<level.numConnectedClients; i++) { idnum = level.sortedClients[i];//level.sortedNames[i]; cl = &level.clients[idnum]; cl_ent = g_entities + idnum; SanitizeString(cl->pers.netname, n2, qtrue); n2[26] = 0; ref[0] = 0; ready[0] = 0; // Rate info if(cl_ent->r.svFlags & SVF_BOT) { strcpy(rate, va("%s%s%s%s", "[BOT]", " -----", " --", " --")); } else if(cl->pers.connected == CON_CONNECTING) { strcpy(rate, va("%s", "^3>>> CONNECTING <<<")); } else { trap_GetUserinfo( idnum, userinfo, sizeof(userinfo)); s = Info_ValueForKey( userinfo, "rate" ); user_rate = (max_rate > 0 && atoi(s) > max_rate) ? max_rate : atoi(s); s = Info_ValueForKey( userinfo, "snaps" ); user_snaps = atoi(s); strcpy(rate, va("%5d%6d%9d%7d", cl->pers.clientTimeNudge, user_rate, cl->pers.clientMaxPackets, user_snaps)); } if(g_gamestate.integer != GS_PLAYING) { if(cl->sess.sessionTeam == TEAM_SPECTATOR || cl->pers.connected == CON_CONNECTING) strcpy(ready, ((ent) ? "^5--------^1 :" : "-------- :")); else if(cl->pers.ready || (g_entities[idnum].r.svFlags & SVF_BOT)) strcpy(ready, ((ent) ? "^3(READY)^1 :" : "(READY) :")); else strcpy(ready, ((ent) ? "NOTREADY^1 :" : "NOTREADY :")); } if(cl->sess.referee) strcpy(ref, "REF"); if(cl->sess.coach_team) { tteam = cl->sess.coach_team; coach = (ent) ? "^3C" : "C"; } else { tteam = cl->sess.sessionTeam; coach = " "; } tc = (ent) ? "^7 " : " "; if(g_gametype.integer >= GT_WOLF) { if(tteam == TEAM_AXIS) tc = (ent) ? "^1X^7" : "X"; if(tteam == TEAM_ALLIES) tc = (ent) ? "^4L^7" : "L"; } if(ent) CP(va("print \"%s%s%2d%s^1:%s %-26s^7%s ^3%s\n\"", ready, tc, idnum, coach, ((ref[0])?"^3":"^7"), n2, rate, ref)); else G_Printf("%s%s%2d%s: %-26s%s %s\n", ready, tc, idnum, coach, n2, rate, ref); cnt++; } if(ent) CP(va("print \"\n^3%2d^7 total players\n\n\"", cnt)); else G_Printf("\n%2d total players\n\n", cnt); // Team speclock info if(g_gametype.integer >= GT_WOLF) { for(i=TEAM_AXIS; i<=TEAM_ALLIES; i++) { if(teamInfo[i].spec_lock) { if(ent) CP(va("print \"** %s team is speclocked.\n\"", aTeams[i])); else G_Printf("** %s team is speclocked.\n", aTeams[i]); } } } }