int _buildFileList(const char* path, bool insert, bool buildList) { WIN32_FIND_DATA data; char spec[MAX_OSPATH]; int count = 0; // Look for all files Com_sprintf(spec, sizeof(spec), "%s\\*.*", path); HANDLE h = FindFirstFile(spec, &data); while (h != INVALID_HANDLE_VALUE) { char full[MAX_OSPATH]; Com_sprintf(full, sizeof(full), "%s\\%s", path, data.cFileName); if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // Directory -- lets go recursive if (data.cFileName[0] != '.') { count += _buildFileList(full, insert, buildList); } } else { if(insert || buildList) { // Regular file -- add it to the table strlwr(full); unsigned int code = crc32(0, (const byte *)full, strlen(full)); FileInfo info; info.name = CopyString(full); info.size = data.nFileSizeLow; if(insert) { s_Files->Insert(info, code); } if(buildList) { // get the length of the filename int len; len = strlen(info.name) + 1; // save the file code *(int*)buffer = code; buffer += sizeof(code); // save the name of the file strcpy((char*)buffer,info.name); buffer += len; // save the size of the file *(int*)buffer = info.size; buffer += sizeof(info.size); } } count++; } // Continue the loop if (!FindNextFile(h, &data)) { FindClose(h); return count; } } return count; }
qboolean HTTPCreateWebadminMessage(ftRequest_t* request, msg_t* msg, char* sessionkey, httpPostVals_t* values) { byte *buf; char qpath[MAX_QPATH]; int len; const char *session; char banmsg[1024]; buf = NULL; MSG_Init(msg, buf, 0); Com_Printf("URL: %s\n", request->url); if(!Q_strncmp(request->url, "/files", 6)) { if(request->url[6] != '/' || request->url[7] == '\0') { return qfalse; } Com_sprintf(qpath, sizeof(qpath), "/webadmindata/%s", &request->url[7]); if(strstr(qpath, "..") != NULL || strstr(qpath, "::") != NULL) { return qfalse; } len = FS_ReadFile(qpath, (void**)&buf); if(len < 0) { return qfalse; } msg->data = buf; msg->cursize = len; msg->maxsize = len; FS_FreeFileKeepBuf( ); return qtrue; } len = 0x20000; buf = Z_Malloc(len); if(buf == NULL) { return qfalse; } msg->data = buf; msg->cursize = 0; msg->maxsize = len; if (Q_stricmpn(request->url, "/webadmin", 9)) { Webadmin_BuildMessage(msg, NULL, qfalse, NULL ,request->url, values); return qtrue; } qboolean invalidlogin = qfalse; const char* username = NULL; const char* password = NULL; if(SV_PlayerBannedByip(&request->remote, banmsg, sizeof(banmsg))) { Webadmin_BuildMessage(msg, NULL, qfalse, banmsg, request->url, values); return qtrue; } username = Auth_FindSessionID(sessionkey); if(username == NULL) { username = Webadmin_GetPostVal(values, "username"); password = Webadmin_GetPostVal(values, "password"); if(username && password) { session = Auth_GetSessionId(username, password); if(session == NULL) { Com_Printf("^1Invalid login\n"); invalidlogin = qtrue; SV_PlayerAddBanByip(&request->remote, "Invalid login attempt. You have to wait 20 seconds", 0, NULL, 0, Com_GetRealtime() + 10); username = NULL; } else { Com_Printf("^2Successful login with username: %s\n", username); } } else { Com_Printf("No login!\n"); session = NULL; username = NULL; } /* not longer than 127 or overflow */ if(session != NULL) { strcpy(sessionkey, session); } } else { Com_Printf("Already logged in as: %s\n", username); } Webadmin_BuildMessage(msg, username, invalidlogin, NULL, request->url, values); return qtrue; }
/* ================== Cmd_CallVote_f ================== */ void Cmd_CallVote_f( gentity_t *ent ) { char* c; int i; char arg1[MAX_STRING_TOKENS]; char arg2[MAX_STRING_TOKENS]; if ( !g_allowVote.integer ) { trap_SendServerCommand( ent-g_entities, "print \"Voting not allowed here.\n\"" ); return; } if ( level.voteTime ) { trap_SendServerCommand( ent-g_entities, "print \"A vote is already in progress.\n\"" ); return; } if ( ent->client->pers.voteCount >= MAX_VOTE_COUNT ) { trap_SendServerCommand( ent-g_entities, "print \"You have called the maximum number of votes.\n\"" ); return; } if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) { trap_SendServerCommand( ent-g_entities, "print \"Not allowed to call a vote as spectator.\n\"" ); return; } // make sure it is a valid command to vote on trap_Argv( 1, arg1, sizeof( arg1 ) ); trap_Argv( 2, arg2, sizeof( arg2 ) ); // check for command separators in arg2 for( c = arg2; *c; ++c) { switch(*c) { case '\n': case '\r': case ';': trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" ); return; break; } } if ( !Q_stricmp( arg1, "map_restart" ) ) { } else if ( !Q_stricmp( arg1, "nextmap" ) ) { } else if ( !Q_stricmp( arg1, "map" ) ) { } else if ( !Q_stricmp( arg1, "g_gametype" ) ) { } else if ( !Q_stricmp( arg1, "kick" ) ) { } else if ( !Q_stricmp( arg1, "clientkick" ) ) { } else if ( !Q_stricmp( arg1, "g_doWarmup" ) ) { } else if ( !Q_stricmp( arg1, "timelimit" ) ) { } else if ( !Q_stricmp( arg1, "fraglimit" ) ) { } else { trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" ); trap_SendServerCommand( ent-g_entities, "print \"Vote commands are: map_restart, nextmap, map <mapname>, g_gametype <n>, kick <player>, clientkick <clientnum>, g_doWarmup, timelimit <time>, fraglimit <frags>.\n\"" ); return; } // if there is still a vote to be executed if ( level.voteExecuteTime ) { level.voteExecuteTime = 0; trap_SendConsoleCommand( EXEC_APPEND, va("%s\n", level.voteString ) ); } // special case for g_gametype, check for bad values if ( !Q_stricmp( arg1, "g_gametype" ) ) { i = atoi( arg2 ); if( i == GT_SINGLE_PLAYER || i < GT_FFA || i >= GT_MAX_GAME_TYPE) { trap_SendServerCommand( ent-g_entities, "print \"Invalid gametype.\n\"" ); return; } Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %d", arg1, i ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s %s", arg1, gameNames[i] ); } else if ( !Q_stricmp( arg1, "map" ) ) { // special case for map changes, we want to reset the nextmap setting // this allows a player to change maps, but not upset the map rotation char s[MAX_STRING_CHARS]; trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) ); if (*s) { Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s; set nextmap \"%s\"", arg1, arg2, s ); } else { Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 ); } Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); } else if ( !Q_stricmp( arg1, "nextmap" ) ) { char s[MAX_STRING_CHARS]; trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) ); if (!*s) { trap_SendServerCommand( ent-g_entities, "print \"nextmap not set.\n\"" ); return; } Com_sprintf( level.voteString, sizeof( level.voteString ), "vstr nextmap"); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); } else { Com_sprintf( level.voteString, sizeof( level.voteString ), "%s \"%s\"", arg1, arg2 ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); } trap_SendServerCommand( -1, va("print \"%s called a vote.\n\"", ent->client->pers.netname ) ); // start the voting, the caller autoamtically votes yes level.voteTime = level.time; level.voteYes = 1; level.voteNo = 0; for ( i = 0 ; i < level.maxclients ; i++ ) { level.clients[i].ps.eFlags &= ~EF_VOTED; } ent->client->ps.eFlags |= EF_VOTED; trap_SetConfigstring( CS_VOTE_TIME, va("%i", level.voteTime ) ); trap_SetConfigstring( CS_VOTE_STRING, level.voteDisplayString ); trap_SetConfigstring( CS_VOTE_YES, va("%i", level.voteYes ) ); trap_SetConfigstring( CS_VOTE_NO, va("%i", level.voteNo ) ); }
//Mostly parts of other functions merged into one another. //Puts the current UI stuff into a string, legalizes it, and then reads it back out. void UI_ReadLegalForce(void) { char fcfString[512]; char forceStringValue[4]; int strPlace = 0; int forcePlace = 0; int i = 0; char singleBuf[64]; char info[MAX_INFO_VALUE]; int c = 0; int iBuf = 0; int forcePowerRank = 0; int currank = 0; int forceTeam = 0; qboolean updateForceLater = qfalse; //First, stick them into a string. Com_sprintf(fcfString, sizeof(fcfString), "%i-%i-", uiForceRank, uiForceSide); strPlace = strlen(fcfString); while (forcePlace < NUM_FORCE_POWERS) { Com_sprintf(forceStringValue, sizeof(forceStringValue), "%i", uiForcePowersRank[forcePlace]); //Just use the force digit even if multiple digits. Shouldn't be longer than 1. fcfString[strPlace] = forceStringValue[0]; strPlace++; forcePlace++; } fcfString[strPlace] = '\n'; fcfString[strPlace+1] = 0; info[0] = '\0'; trap_GetConfigString(CS_SERVERINFO, info, sizeof(info)); if (atoi( Info_ValueForKey( info, "g_forceBasedTeams" ) )) { switch((int)(trap_Cvar_VariableValue("ui_myteam"))) { case TEAM_RED: forceTeam = FORCE_DARKSIDE; break; case TEAM_BLUE: forceTeam = FORCE_LIGHTSIDE; break; default: break; } } //Second, legalize them. if (!BG_LegalizedForcePowers(fcfString, uiMaxRank, ui_freeSaber.integer, forceTeam, atoi( Info_ValueForKey( info, "g_gametype" )), 0)) { //if they were illegal, we should refresh them. updateForceLater = qtrue; } //Lastly, put them back into the UI storage from the legalized string i = 0; while (fcfString[i] && fcfString[i] != '-') { singleBuf[c] = fcfString[i]; c++; i++; } singleBuf[c] = 0; c = 0; i++; iBuf = atoi(singleBuf); if (iBuf > uiMaxRank || iBuf < 0) { //this force config uses a rank level higher than our currently restricted level.. so we can't use it //FIXME: Print a message indicating this to the user // return; } uiForceRank = iBuf; while (fcfString[i] && fcfString[i] != '-') { singleBuf[c] = fcfString[i]; c++; i++; } singleBuf[c] = 0; c = 0; i++; uiForceSide = atoi(singleBuf); if (uiForceSide != FORCE_LIGHTSIDE && uiForceSide != FORCE_DARKSIDE) { uiForceSide = FORCE_LIGHTSIDE; return; } //clear out the existing powers while (c < NUM_FORCE_POWERS) { uiForcePowersRank[c] = 0; c++; } uiForceUsed = 0; uiForceAvailable = forceMasteryPoints[uiForceRank]; gTouchedForce = qtrue; for (c=0;fcfString[i]&&c<NUM_FORCE_POWERS;c++,i++) { singleBuf[0] = fcfString[i]; singleBuf[1] = 0; iBuf = atoi(singleBuf); // So, that means that Force Power "c" wants to be set to rank "iBuf". if (iBuf < 0) { iBuf = 0; } forcePowerRank = iBuf; if (forcePowerRank > FORCE_LEVEL_3 || forcePowerRank < 0) { //err.. not correct continue; // skip this power } if (uiForcePowerDarkLight[c] && uiForcePowerDarkLight[c] != uiForceSide) { //Apparently the user has crafted a force config that has powers that don't fit with the config's side. continue; // skip this power } // Accrue cost for each assigned rank for this power. for (currank=FORCE_LEVEL_1;currank<=forcePowerRank;currank++) { if (bgForcePowerCost[c][currank] > uiForceAvailable) { // Break out, we can't afford any more power. break; } // Pay for this rank of this power. uiForceUsed += bgForcePowerCost[c][currank]; uiForceAvailable -= bgForcePowerCost[c][currank]; uiForcePowersRank[c]++; } } if (uiForcePowersRank[FP_LEVITATION] < 1) { uiForcePowersRank[FP_LEVITATION]=1; } if (uiForcePowersRank[FP_SABER_OFFENSE] < 1 && ui_freeSaber.integer) { uiForcePowersRank[FP_SABER_OFFENSE]=1; } if (uiForcePowersRank[FP_SABER_DEFENSE] < 1 && ui_freeSaber.integer) { uiForcePowersRank[FP_SABER_DEFENSE]=1; } UpdateForceUsed(); if (updateForceLater) { gTouchedForce = qtrue; UI_UpdateClientForcePowers(NULL); } }
void Webadmin_BuildServerStatus(xml_t* xmlobj, qboolean showfullguid) { int i, numcl; client_t* cl; char strbuf[MAX_STRING_CHARS]; char colorbuf[2048]; mvabuf; char teamallies[32]; char teamaxis[32]; gclient_t *gclient; qboolean teambased = qfalse; qboolean ffabased = qfalse; numcl = 0; for (cl = svs.clients, gclient = level.clients, i = 0; i < sv_maxclients->integer; i++, cl++, gclient++) { if (cl->state < CS_CONNECTED) { continue; } if(gclient->sess.sessionTeam == TEAM_RED || gclient->sess.sessionTeam == TEAM_BLUE) { teambased = qtrue; break; } if(gclient->sess.sessionTeam == TEAM_FREE) { ffabased = qtrue; break; } } XO1("table","class","table table-striped table-bordered cod4xtable"); XA("<th>CID</th><th>Name</th><th>UID/GUID</th><th>Power</th><th>Score</th><th>Ping</th>"); if(teambased) { if(!Q_strncmp(g_TeamName_Axis->string,"MPUI_SPETSNAZ", 13)) Q_strncpyz(teamaxis, "Spetsnaz", sizeof(teamaxis)); else if(!Q_strncmp(g_TeamName_Axis->string,"MPUI_OPFOR", 10)) Q_strncpyz(teamaxis, "Opfor", sizeof(teamaxis)); else Q_strncpyz(teamaxis, g_TeamName_Axis->string, sizeof(teamaxis)); if(!Q_strncmp(g_TeamName_Allies->string,"MPUI_MARINES", 12)) Q_strncpyz(teamallies, "Marines", sizeof(teamallies)); else if(!Q_strncmp(g_TeamName_Allies->string,"MPUI_SAS", 8)) Q_strncpyz(teamallies, "S.A.S.", sizeof(teamallies)); else Q_strncpyz(teamallies, g_TeamName_Allies->string, sizeof(teamallies)); XO("tr"); XO1("td", "colspan", "6"); XA(teamaxis); XC; XC; for (cl = svs.clients, gclient = level.clients, i = 0; i < sv_maxclients->integer; i++, cl++, gclient++) { if (cl->state < CS_CONNECTED) { continue; } if(gclient->sess.sessionTeam != TEAM_RED) { continue; } ++numcl; XO("tr"); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", i);//CID XA(strbuf); XO("td");//Name XA(Webadmin_ConvertToHTMLColor(cl->name, colorbuf, sizeof(colorbuf))); XC; XO("td");//GUID if(cl->uid > 0) { XA(va("%d", cl->uid)); } else { if(showfullguid) XA(cl->pbguid); else XA(&cl->pbguid[24]); } XC; Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", cl->power);//Ping XA(strbuf); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", gclient->pers.scoreboard.score);//Score XA(strbuf); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", cl->ping);//Ping XA(strbuf); XC; } XO("tr"); XO1("td", "colspan", "6"); XA(teamallies); XC; XC; for (cl = svs.clients, gclient = level.clients, i = 0; i < sv_maxclients->integer; i++, cl++, gclient++) { if (cl->state < CS_CONNECTED) { continue; } if(gclient->sess.sessionTeam != TEAM_BLUE) { continue; } ++numcl; XO("tr"); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", i);//CID XA(strbuf); XO("td");//Name XA(Webadmin_ConvertToHTMLColor(cl->name, colorbuf, sizeof(colorbuf))); XC; XO("td");//GUID if(cl->uid > 0) { XA(va("%d", cl->uid)); } else { if(showfullguid) XA(cl->pbguid); else XA(&cl->pbguid[24]); } XC; Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", cl->power);//Ping XA(strbuf); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", gclient->pers.scoreboard.score);//Score XA(strbuf); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", cl->ping);//Ping XA(strbuf); XC; } } else if(ffabased) { XO("tr"); XO1("td", "colspan", "6"); XA("Players"); XC; XC; for (cl = svs.clients, gclient = level.clients, i = 0; i < sv_maxclients->integer; i++, cl++, gclient++) { if (cl->state < CS_CONNECTED) { continue; } if(gclient->sess.sessionTeam != TEAM_FREE) { continue; } ++numcl; XO("tr"); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", i);//CID XA(strbuf); XO("td");//Name XA(Webadmin_ConvertToHTMLColor(cl->name, colorbuf, sizeof(colorbuf))); XC; XO("td");//GUID if(cl->uid > 0) { XA(va("%d", cl->uid)); } else { if(showfullguid) XA(cl->pbguid); else XA(&cl->pbguid[24]); } XC; Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", cl->power);//Ping XA(strbuf); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", gclient->pers.scoreboard.score);//Score XA(strbuf); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", cl->ping);//Ping XA(strbuf); XC; } } XO("tr"); XO1("td", "colspan", "6"); XA("Spectators"); XC; XC; for (cl = svs.clients, gclient = level.clients, i = 0; i < sv_maxclients->integer; i++, cl++, gclient++) { if (cl->state < CS_CONNECTED) { continue; } if(gclient->sess.sessionTeam != TEAM_SPECTATOR) { continue; } ++numcl; XO("tr"); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", i);//CID XA(strbuf); XO("td");//Name XA(Webadmin_ConvertToHTMLColor(cl->name, colorbuf, sizeof(colorbuf))); XC; XO("td");//GUID if(cl->uid > 0) { XA(va("%d", cl->uid)); } else { if(showfullguid) XA(cl->pbguid); else XA(&cl->pbguid[24]); } XC; Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", cl->power);//Ping XA(strbuf); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", gclient->pers.scoreboard.score);//Score XA(strbuf); Com_sprintf(strbuf, sizeof(strbuf), "<td>%d</td>", cl->ping);//Ping XA(strbuf); XC; } XC; XA(va("%d players are on server", numcl)); }
// This function is called recursively when a logical message has to be split into multiple lines void CG_ChatboxAdd( const char *message, qboolean multiLine ) { chatEntry_t *chat = &chatbox.chatBuffer[MAX_CHATBOX_ENTRIES-1]; size_t strLength = 0; int i = 0; float accumLength = 0.0f; chatbox.numActiveLines++; //Stop scrolling up if we've already scrolled, similar to console behaviour if ( chatbox.scrollAmount < 0 ) chatbox.scrollAmount = MAX( chatbox.scrollAmount - 1, chatbox.numActiveLines >= cg_chatboxLineCount->integer ? ((MIN(chatbox.numActiveLines, MAX_CHATBOX_ENTRIES)-cg_chatboxLineCount->integer)*-1) : 0 ); //cb->scrollAmount--; for ( i=0, strLength=strlen( message ); i<strLength && i<CHAT_MESSAGE_LENGTH; i++ ) { char *p = (char*)&message[i]; char buf[1]; buf[0] = *p; if ( !Q_IsColorString( p ) && (i > 0 && !Q_IsColorString( p-1 )) ) accumLength += CG_Text_Width( buf, CHATBOX_FONT_SCALE, -1 ); if ( accumLength > SCREEN_WIDTH && (i>0 && !Q_IsColorString( p-1 )) ) { char lastColor = '2'; int j = i; int savedOffset = i; char tempMessage[CHAT_MESSAGE_LENGTH]; //Attempt to back-track, find a space (' ') within X characters or pixels //RAZTODO: Another method using character width? Meh while ( message[i] != ' ' ) { if ( i <= 0 || i < savedOffset-16 ) { i = j = savedOffset; break; } i--; j--; } memmove( &chatbox.chatBuffer[0], &chatbox.chatBuffer[1], sizeof( chatbox.chatBuffer ) - sizeof( chatEntry_t ) ); memset( chat, 0, sizeof( chatEntry_t ) ); //Clear the last element, ready for writing Q_strncpyz( chat->message, message, i+1 ); chat->time = cg.time + cg_chatboxMsgTime->integer*1000; chat->isUsed = qtrue; for ( j=i; j>=0; j-- ) { if ( message[j] == '^' && message[j+1] >= '0' && message[j+1] <= '9' ) { lastColor = message[j+1]; break; } } Com_sprintf( tempMessage, sizeof( tempMessage ), "^%c%s", lastColor, (const char *)(message + i) ); //Recursively insert until we don't have to split the message CG_ChatboxAdd( tempMessage, qtrue ); return; } } memmove( &chatbox.chatBuffer[0], &chatbox.chatBuffer[1], sizeof( chatbox.chatBuffer ) - sizeof( chatEntry_t ) ); memset( chat, 0, sizeof( chatEntry_t ) ); //Clear the last element, ready for writing Q_strncpyz( chat->message, message, i+1 ); chat->time = cg.time + cg_chatboxMsgTime->integer*1000; chat->isUsed = qtrue; }
/* ============== SV_InitGame A brand new game has been started ============== */ void SV_InitGame (void) { int i; edict_t *ent; char idmaster[32]; if (svs.initialized) { // cause any connected clients to reconnect SV_Shutdown ("Server restarted\n", true); } else { // make sure the client is down CL_Drop (); SCR_BeginLoadingPlaque (); } // get any latched variable changes (maxclients, etc) Cvar_GetLatchedVars (); svs.initialized = true; if (Cvar_VariableValue ("coop") && Cvar_VariableValue ("deathmatch")) { Com_Printf("Deathmatch and Coop both set, disabling Coop\n"); Cvar_FullSet ("coop", "0", CVAR_SERVERINFO | CVAR_LATCH); } // dedicated servers are can't be single player and are usually DM // so unless they explicity set coop, force it to deathmatch if (dedicated->value) { if (!Cvar_VariableValue ("coop")) Cvar_FullSet ("deathmatch", "1", CVAR_SERVERINFO | CVAR_LATCH); } // init clients if (Cvar_VariableValue ("deathmatch")) { if (maxclients->value <= 1) Cvar_FullSet ("maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH); else if (maxclients->value > MAX_CLIENTS) Cvar_FullSet ("maxclients", va("%i", MAX_CLIENTS), CVAR_SERVERINFO | CVAR_LATCH); } else if (Cvar_VariableValue ("coop")) { if (maxclients->value <= 1 || maxclients->value > 4) Cvar_FullSet ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH); #ifdef COPYPROTECT if (!sv.attractloop && !dedicated->value) Sys_CopyProtect (); #endif } else // non-deathmatch, non-coop is one player { Cvar_FullSet ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH); #ifdef COPYPROTECT if (!sv.attractloop) Sys_CopyProtect (); #endif } svs.spawncount = rand(); svs.clients = Z_Malloc (sizeof(client_t)*maxclients->value); svs.num_client_entities = maxclients->value*UPDATE_BACKUP*64; svs.client_entities = Z_Malloc (sizeof(entity_state_t)*svs.num_client_entities); // init network stuff NET_Config ( (maxclients->value > 1) ); // heartbeats will always be sent to the id master svs.last_heartbeat = -99999; // send immediately Com_sprintf(idmaster, sizeof(idmaster), "192.246.40.37:%i", PORT_MASTER); NET_StringToAdr (idmaster, &master_adr[0]); // init game SV_InitGameProgs (); for (i=0 ; i<maxclients->value ; i++) { ent = EDICT_NUM(i+1); ent->s.number = i+1; svs.clients[i].edict = ent; memset (&svs.clients[i].lastcmd, 0, sizeof(svs.clients[i].lastcmd)); } }
/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. ================ */ void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate, qboolean attractloop, qboolean loadgame) { int i; unsigned checksum; float cer_public; float cer_sv_login; float cer_sv_forcesky; float cer_guntemp_inc; float cer_guntemp_dec; float cer_elim; float cer_fraglimit; float cer_timelimit; if (attractloop) Cvar_Set("paused", "0"); Com_Printf("------- Server Initialization -------\n"); Com_DPrintf("SpawnServer: %s\n", server); if (sv.demofile) fclose(sv.demofile); svs.spawncount++; // any partially connected client will be restarted sv.state = ss_dead; Com_SetServerState(sv.state); // wipe the entire per-level structure memset(&sv, 0, sizeof(sv)); svs.realtime = 0; sv.loadgame = loadgame; sv.attractloop = attractloop; // save name for levels that don't set message strcpy(sv.configstrings[CS_NAME], server); sprintf(sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value); pm_airaccelerate = sv_airaccelerate->value; SV_ReplicatePhysicsSettings(); // jitmovephysics sprintf(sv.configstrings[CS_SERVEREVERSION], "Enginever: %g Enginebuild: %d", VERSION, BUILD); SZ_Init(&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf)); strcpy(sv.name, server); // leave slots at start for clients only for (i = 0; i < maxclients->value; i++) { // needs to reconnect if (svs.clients[i].state > cs_connected) svs.clients[i].state = cs_connected; svs.clients[i].lastframe = -1; } sv.time = 1000; strcpy(sv.name, server); strcpy(sv.configstrings[CS_NAME], server); if (serverstate != ss_game) { sv.models[1] = CM_LoadMap("", false, &checksum); // no real map } else { Com_sprintf(sv.configstrings[CS_MODELS + 1], sizeof(sv.configstrings[CS_MODELS + 1]), "maps/%s.bsp", server); sv.models[1] = CM_LoadMap(sv.configstrings[CS_MODELS + 1], false, &checksum); } Com_sprintf(sv.configstrings[CS_MAPCHECKSUM], sizeof(sv.configstrings[CS_MAPCHECKSUM]), "%i", checksum); // clear physics interaction links SV_ClearWorld(); for (i = 1; i < CM_NumInlineModels(); i++) { Com_sprintf (sv.configstrings[CS_MODELS + 1 + i], sizeof(sv.configstrings[CS_MODELS + 1 + i]), "*%i", i); sv.models[i + 1] = CM_InlineModel(sv.configstrings[CS_MODELS + 1 + i]); } // // spawn the rest of the entities on the map // // precache and static commands can be issued during // map initialization sv.state = ss_loading; Com_SetServerState(sv.state); //if(!sv.attractloop) // jitdemo -- don't spawn game stuff while demo is playing! { // load and spawn all other entities ge->SpawnEntities(sv.name, CM_EntityString(), spawnpoint); // run two frames to allow everything to settle ge->RunFrame(); ge->RunFrame(); } // all precaches are complete sv.state = serverstate; Com_SetServerState(sv.state); // create a baseline for more efficient communications SV_CreateBaseline(); // check for a savegame SV_CheckForSavegame(); // set serverinfo variable Cvar_FullSet("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET, true); // T3RR0R15T: certificated server info (default settings atm) //cer_maxclients = Cvar_VariableValue("maxclients"); cer_elim = Cvar_VariableValue("elim"); cer_fraglimit = Cvar_VariableValue("fraglimit"); cer_timelimit = Cvar_VariableValue("timelimit"); //cer_sv_minclientbuild = Cvar_VariableValue("sv_minclientbuild"); cer_guntemp_inc = Cvar_VariableValue("guntemp_inc"); cer_guntemp_dec = Cvar_VariableValue("guntemp_dec"); cer_sv_forcesky = Cvar_VariableValue("sv_forcesky"); cer_sv_login = Cvar_VariableValue("sv_login"); cer_public = Cvar_VariableValue("public"); // Don't forget to change the SV_Certificatedinfo_f (sv_ccmds.c), if you change something here ! if (//cer_maxclients->value == 16 && (cer_elim >= 60.0f || cer_elim == 0.0f) && cer_fraglimit == 50.0f && cer_timelimit == 20.0f && //cer_sv_minclientbuild >= 28.0f && cer_guntemp_inc >= 10.5f && // 11 + some leeway cer_guntemp_dec <= 4.2f && // 4 + some leeway cer_sv_forcesky && cer_sv_login && cer_public) { Cvar_FullSet("sv_certificated", "1", CVAR_SERVERINFO | CVAR_NOSET, true); } else { Cvar_FullSet("sv_certificated", "0", CVAR_SERVERINFO | CVAR_NOSET, true); } Com_Printf("-------------------------------------\n"); }
/* ====================== SV_Map the full syntax is: map [*]<map>$<startspot>+<nextserver> command from the console or progs. Map can also be a.cin, .pcx, or .dm2 file Nextserver is used to allow a cinematic to play, then proceed to another level: map tram.cin+jail_e3 ====================== */ void SV_Map (qboolean attractloop, const char *levelstring, qboolean loadgame) { char level[MAX_QPATH]; char *ch; int l; char spawnpoint[MAX_QPATH]; strcpy(level, levelstring); // jit - copy level string before it gets modified by other commands (since it's a command argument) sv.loadgame = loadgame; sv.attractloop = attractloop; if (sv.state == ss_dead && !sv.loadgame) SV_InitGame(); // the game is just starting // if there is a + in the map, set nextserver to the remainder ch = strstr(level, "+"); if (ch) { *ch = 0; Cvar_Set("nextserver", va("gamemap \"%s\"", ch + 1)); } else { Cvar_Set("nextserver", ""); } //ZOID special hack for end game screen in coop mode if (Cvar_VariableValue("coop") && Q_strcaseeq(level, "victory.pcx")) Cvar_Set("nextserver", "gamemap \"*base1\""); // if there is a $, use the remainder as a spawnpoint ch = strstr(level, "$"); if (ch) { *ch = 0; strcpy(spawnpoint, ch + 1); } else { spawnpoint[0] = 0; } // skip the end-of-unit flag if necessary if (level[0] == '*') strcpy (level, level+1); l = strlen(level); if (l > 4 && Q_streq(level + l - 4, ".cin")) { SCR_BeginLoadingPlaque(NULL); // for local system SV_BroadcastCommand("changing\n"); SV_SpawnServer(level, spawnpoint, ss_cinematic, attractloop, loadgame); } else if (l > 4 && Q_streq(level + l - 4, ".dm2")) { SCR_BeginLoadingPlaque(NULL); // for local system SV_BroadcastCommand("changing\n"); SV_SpawnServer(level, spawnpoint, ss_demo, attractloop, loadgame); } else if (l > 4 && Q_streq(level + l - 4, ".pcx")) { SCR_BeginLoadingPlaque(NULL); // for local system SV_BroadcastCommand("changing\n"); SV_SpawnServer(level, spawnpoint, ss_pic, attractloop, loadgame); } else { char changing_cmd[1024]; if (!dedicated->value) SCR_BeginLoadingPlaque(level); // for local system Com_sprintf(changing_cmd, sizeof(changing_cmd), "changing \"%s\"\n", level); SV_BroadcastCommand(changing_cmd); SV_SendClientMessages(); SV_SpawnServer(level, spawnpoint, ss_game, attractloop, loadgame); Cbuf_CopyToDefer(); } SV_BroadcastCommand("reconnect\n"); }
// *** Referee voting *** int G_Referee_v(gentity_t *ent, unsigned int dwVoteIndex, char *arg, char *arg2, qboolean fRefereeCmd) { // Vote request (vote is being initiated) if (arg) { int pid; if (!vote_allow_referee.integer && ent && !ent->client->sess.referee) { G_voteDisableMessage(ent, arg); return(G_INVALID); } if (!ent->client->sess.referee && level.numPlayingClients < 3) { G_refPrintf(ent, "Sorry, not enough clients in the game to vote for a referee"); return(G_INVALID); } if (ent->client->sess.referee && trap_Argc() == 2) { G_playersMessage(ent); return(G_INVALID); } else if (trap_Argc() == 2) { pid = ent - g_entities; } else if (G_voteDescription(ent, fRefereeCmd, dwVoteIndex)) { return(G_INVALID); } else if ((pid = ClientNumberFromString(ent, arg2)) == -1) { return(G_INVALID); } if (level.clients[pid].sess.referee) { G_refPrintf(ent, "[lof]%s [lon]is already a referee!", level.clients[pid].pers.netname); return(-1); } Com_sprintf(level.voteInfo.vote_value, VOTE_MAXSTRING, "%d", pid); Com_sprintf(arg2, VOTE_MAXSTRING, "%s", level.clients[pid].pers.netname); // Vote action (vote has passed) } else { // Voting in a new referee gclient_t *cl = &level.clients[atoi(level.voteInfo.vote_value)]; if (cl->pers.connected == CON_DISCONNECTED) { AP("print \"Player left before becoming referee\n\""); } else { cl->sess.referee = RL_REFEREE; // FIXME: Differentiate voted refs from passworded refs cl->sess.spec_invite = TEAM_AXIS | TEAM_ALLIES; AP(va("cp \"%s^7 is now a referee\n\"", cl->pers.netname)); ClientUserinfoChanged(atoi(level.voteInfo.vote_value)); } } return(G_OK); }
script_t *LoadScriptFile(const char *filename) { fileHandle_t h_up, h_patch; char pathname[MAX_QPATH], pathpatch[MAX_QPATH]; unsigned long inhash = 0; int inlength, outlength, plength; char *inbuffer, *outbuffer, *pbuffer; script_t *script; if (strlen(basefolder)) { Com_sprintf(pathname, sizeof(pathname), "%s/%s", basefolder, filename); Com_sprintf(pathpatch, sizeof(pathpatch), "%s/%s_patch", basefolder, filename); } else { Com_sprintf(pathname, sizeof(pathname), "%s", filename); Com_sprintf(pathpatch, sizeof(pathpatch), "%s_patch", filename); } inlength = botimport.FS_FOpenFileHash(pathname, &h_up, FS_READ, &inhash); if (!h_up) return NULL; plength = botimport.FS_FOpenFile(pathpatch, &h_patch, FS_READ); inbuffer = (char *)GetClearedMemory(inlength + 1); botimport.FS_Read(inbuffer, inlength, h_up); botimport.FS_FCloseFile(h_up); if (h_patch) { pbuffer = (char *)GetClearedMemory(plength + 1); botimport.FS_Read(pbuffer, plength, h_patch); botimport.FS_FCloseFile(h_patch); Com_Printf("patching menu file %s...\n", pathname); outlength = MV_MenuPatchFile(inbuffer, inhash, pbuffer, &outbuffer); if (outlength < 0) { if (outlength == ERROR_SYNTAX) { Com_Printf("patching failed: syntax error in patchfile\n"); } else if (outlength == ERROR_HASH) { Com_Printf("patching skipped: hash mismatch\n"); } outbuffer = inbuffer; outlength = inlength; } FreeMemory(pbuffer); // uncomment to dump patched file with _patched suffix; menu_patch /* char patchedName[MAX_QPATH]; fileHandle_t patchedFile; Com_sprintf(patchedName, sizeof(patchedName), "%s_patched", pathname); botimport.FS_FOpenFile(patchedName, &patchedFile, FS_WRITE); botimport.FS_Write(outbuffer, outlength, patchedFile); botimport.FS_FCloseFile(patchedFile); */ } else { outbuffer = inbuffer; outlength = inlength; } script = (script_t *)GetClearedMemory(sizeof(script_t) + outlength + 1); Com_Memset(script, 0, sizeof(script_t)); strcpy(script->filename, filename); script->buffer = (char *)script + sizeof(script_t); script->buffer[outlength] = 0; script->length = outlength; script->script_p = script->buffer; script->lastscript_p = script->buffer; script->end_p = &script->buffer[outlength]; script->tokenavailable = 0; script->line = 1; script->lastline = 1; SetScriptPunctuations(script, NULL); Com_Memcpy(script->buffer, outbuffer, outlength); FreeMemory(outbuffer); if (outbuffer != inbuffer) FreeMemory(inbuffer); script->length = COM_Compress(script->buffer); return script; } //end of the function LoadScriptFile
// *** Player Mute *** int G_Mute_v(gentity_t *ent, unsigned int dwVoteIndex, char *arg, char *arg2, qboolean fRefereeCmd) { if (fRefereeCmd) { // handled elsewhere return(G_NOTFOUND); } // Vote request (vote is being initiated) if (arg) { int pid; if (!vote_allow_muting.integer && ent && !ent->client->sess.referee) { G_voteDisableMessage(ent, arg); return(G_INVALID); } else if (G_voteDescription(ent, fRefereeCmd, dwVoteIndex)) { return(G_INVALID); } else if ((pid = ClientNumberFromString(ent, arg2)) == -1) { return(G_INVALID); } if (level.clients[pid].sess.referee) { G_refPrintf(ent, "Can't vote to mute referees!"); return(G_INVALID); } if (level.clients[pid].sess.muted) { G_refPrintf(ent, "Player is already muted!"); return(G_INVALID); } Com_sprintf(level.voteInfo.vote_value, VOTE_MAXSTRING, "%d", pid); Com_sprintf(arg2, VOTE_MAXSTRING, "%s", level.clients[pid].pers.netname); // Vote action (vote has passed) } else { int pid = atoi(level.voteInfo.vote_value); // Mute a player if (level.clients[pid].sess.referee != RL_RCON) { trap_SendServerCommand(pid, va("cpm \"^3You have been muted\"")); level.clients[pid].sess.muted = qtrue; AP(va("cp \"%s\n^3has been muted!\n\"", level.clients[pid].pers.netname)); ClientUserinfoChanged(pid); } else { G_Printf("Cannot mute a referee.\n"); } } return(G_OK); }
// *** Un-Referee voting *** int G_Unreferee_v(gentity_t *ent, unsigned int dwVoteIndex, char *arg, char *arg2, qboolean fRefereeCmd) { // Vote request (vote is being initiated) if (arg) { int pid; if (!vote_allow_referee.integer && ent && !ent->client->sess.referee) { G_voteDisableMessage(ent, arg); return(G_INVALID); } if (ent->client->sess.referee && trap_Argc() == 2) { G_playersMessage(ent); return(G_INVALID); } else if (trap_Argc() == 2) { pid = ent - g_entities; } else if (G_voteDescription(ent, fRefereeCmd, dwVoteIndex)) { return(G_INVALID); } else if ((pid = ClientNumberFromString(ent, arg2)) == -1) { return(G_INVALID); } if (level.clients[pid].sess.referee == RL_NONE) { G_refPrintf(ent, "[lof]%s [lon]isn't a referee!", level.clients[pid].pers.netname); return(G_INVALID); } if (level.clients[pid].sess.referee == RL_RCON) { G_refPrintf(ent, "[lof]%s's [lon]status cannot be removed", level.clients[pid].pers.netname); return(G_INVALID); } if (level.clients[pid].pers.localClient) { G_refPrintf(ent, "[lof]%s's [lon]is the Server Host", level.clients[pid].pers.netname); return(G_INVALID); } Com_sprintf(level.voteInfo.vote_value, VOTE_MAXSTRING, "%d", pid); Com_sprintf(arg2, VOTE_MAXSTRING, "%s", level.clients[pid].pers.netname); // Vote action (vote has passed) } else { // Stripping of referee status gclient_t *cl = &level.clients[atoi(level.voteInfo.vote_value)]; cl->sess.referee = RL_NONE; cl->sess.spec_invite = 0; AP(va("cp \"%s^7\nis no longer a referee\n\"", cl->pers.netname)); ClientUserinfoChanged(atoi(level.voteInfo.vote_value)); } return(G_OK); }
/* ======================================================================================================================================= CL_GetServerCommand Set up argc/argv for the given command. ======================================================================================================================================= */ qboolean CL_GetServerCommand(int serverCommandNumber) { char *s; char *cmd; static char bigConfigString[BIG_INFO_STRING]; int argc; // if we have irretrievably lost a reliable command, drop the connection if (serverCommandNumber <= clc.serverCommandSequence - MAX_RELIABLE_COMMANDS) { // when a demo record was started after the client got a whole bunch of reliable commands then the client never got those first // reliable commands if (clc.demoplaying) { return qfalse; } Com_Error(ERR_DROP, "CL_GetServerCommand: a reliable command was cycled out"); return qfalse; } if (serverCommandNumber > clc.serverCommandSequence) { Com_Error(ERR_DROP, "CL_GetServerCommand: requested a command not received"); return qfalse; } s = clc.serverCommands[serverCommandNumber & (MAX_RELIABLE_COMMANDS - 1)]; clc.lastExecutedServerCommand = serverCommandNumber; Com_DPrintf("serverCommand: %i : %s\n", serverCommandNumber, s); rescan: Cmd_TokenizeString(s); cmd = Cmd_Argv(0); argc = Cmd_Argc(); if (!strcmp(cmd, "disconnect")) { // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=552 // allow server to indicate why they were disconnected if (argc >= 2) { Com_Error(ERR_SERVERDISCONNECT, "Server disconnected - %s", Cmd_Argv(1)); } else { Com_Error(ERR_SERVERDISCONNECT, "Server disconnected"); } } if (!strcmp(cmd, "bcs0")) { Com_sprintf(bigConfigString, BIG_INFO_STRING, "cs %s \"%s", Cmd_Argv(1), Cmd_Argv(2)); return qfalse; } if (!strcmp(cmd, "bcs1")) { s = Cmd_Argv(2); if (strlen(bigConfigString) + strlen(s) >= BIG_INFO_STRING) { Com_Error(ERR_DROP, "bcs exceeded BIG_INFO_STRING"); } strcat(bigConfigString, s); return qfalse; } if (!strcmp(cmd, "bcs2")) { s = Cmd_Argv(2); if (strlen(bigConfigString) + strlen(s) + 1 >= BIG_INFO_STRING) { Com_Error(ERR_DROP, "bcs exceeded BIG_INFO_STRING"); } strcat(bigConfigString, s); strcat(bigConfigString, "\""); s = bigConfigString; goto rescan; } if (!strcmp(cmd, "cs")) { CL_ConfigstringModified(); // reparse the string, because CL_ConfigstringModified may have done another Cmd_TokenizeString() Cmd_TokenizeString(s); return qtrue; } if (!strcmp(cmd, "map_restart")) { // clear notify lines and outgoing commands before passing the restart to the cgame Con_ClearNotify(); // reparse the string, because Con_ClearNotify() may have done another Cmd_TokenizeString() Cmd_TokenizeString(s); Com_Memset(cl.cmds, 0, sizeof(cl.cmds)); return qtrue; } // the clientLevelShot command is used during development to generate 128 * 128 screenshots from the intermission // point of levels for the menu system to use // we pass it along to the cgame to make appropriate adjustments, but we also clear the console and notify lines here if (!strcmp(cmd, "clientLevelShot")) { // don't do it if we aren't running the server locally, otherwise malicious remote servers could overwrite the existing thumbnails if (!com_sv_running->integer) { return qfalse; } // close the console Con_Close(); // take a special screenshot next frame Cbuf_AddText("wait; wait; wait; wait; screenshot levelshot\n"); return qtrue; } // we may want to put a "connect to other server" command here // cgame can now act on the command return qtrue; }
/* ============== TDM_Disconnected ============== A player disconnected, do things. */ void TDM_Disconnected (edict_t *ent) { qboolean removeTimeout; removeTimeout = false; //have to check this right up here since we nuke the teamplayer just below! if (tdm_match_status == MM_TIMEOUT && level.tdm_timeout_caller && level.tdm_timeout_caller->client == ent) removeTimeout = true; //we remove this up here so TDM_LeftTeam doesn't try to resume if we become implicit timeout caller TDM_RemoveStatsLink (ent); if (ent->client->pers.team) { if (tdm_match_status >= MM_PLAYING && tdm_match_status != MM_SCOREBOARD) { //do joincode stuff if a team player disconnects - save all their client info ent->client->resp.teamplayerinfo->saved_client = gi.TagMalloc (sizeof(gclient_t), TAG_GAME); *ent->client->resp.teamplayerinfo->saved_client = *ent->client; ent->client->resp.teamplayerinfo->saved_entity = gi.TagMalloc (sizeof(edict_t), TAG_GAME); *ent->client->resp.teamplayerinfo->saved_entity = *ent; if (TDM_Is1V1() && g_1v1_timeout->value > 0) { edict_t *ghost; //may have already been set by a player or previous client disconnect if (tdm_match_status != MM_TIMEOUT) { edict_t *opponent; //timeout is called implicitly in 1v1 games or the other player would auto win level.timeout_end_framenum = level.realframenum + SECS_TO_FRAMES(g_1v1_timeout->value); level.last_tdm_match_status = tdm_match_status; tdm_match_status = MM_TIMEOUT; level.tdm_timeout_caller = ent->client->resp.teamplayerinfo; gi.bprintf (PRINT_CHAT, "%s disconnected and has %s to reconnect.\n", level.tdm_timeout_caller->name, TDM_SecsToString (g_1v1_timeout->value)); //show the opponent their options opponent = TDM_FindPlayerForTeam (TEAM_A); if (opponent) gi.cprintf (opponent, PRINT_HIGH, "Your opponent has disconnected. You can allow them %s to reconnect, or you can force a forfeit by typing 'win' in the console.\n", TDM_SecsToString (g_1v1_timeout->value)); opponent = TDM_FindPlayerForTeam (TEAM_B); if (opponent) gi.cprintf (opponent, PRINT_HIGH, "Your opponent has disconnected. You can allow them %s to reconnect, or you can force a forfeit by typing 'win' in the console.\n", TDM_SecsToString (g_1v1_timeout->value)); } //show a "ghost" player where the player was ghost = G_Spawn (); VectorCopy (ent->s.origin, ghost->s.origin); VectorCopy (ent->s.origin, ghost->old_origin); VectorCopy (ent->s.angles, ghost->s.angles); ghost->s.effects = EF_SPHERETRANS; ghost->s.modelindex = 255; ghost->s.modelindex2 = 255; ghost->s.skinnum = ent - g_edicts - 1; ghost->s.frame = ent->s.frame; ghost->count = ent->s.number; ghost->classname = "ghost"; ghost->target_ent = ent; ghost->enttype = ENT_GHOST; gi.linkentity (ghost); } } if (removeTimeout) TDM_ResumeGame (); TDM_LeftTeam (ent, false); } TDM_TeamsChanged (); if (tdm_match_status == MM_WARMUP && teaminfo[TEAM_SPEC].players == 0 && teaminfo[TEAM_A].players == 0 && teaminfo[TEAM_B].players == 0) { if (vote.active) TDM_RemoveVote (); //reset the map if it's been running for over 7 days to workaround time precision bugs in the engine, fixes 0000208 if (time (NULL) - level.spawntime > (86400 * 7)) { char command[256]; Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.mapname); gi.AddCommandString (command); } } else TDM_CheckVote (); //zero for connecting clients on server browsers ent->client->ps.stats[STAT_FRAGS] = 0; }
void DeathmatchScoreboardMessage (edict_t *ent, edict_t *killer) { char entry[MAX_ENTRY_SIZE]; char string[MAX_STRING_SIZE]; char name[20], classname[20];//3.78 int stringlength; int i, j, k; int sorted[MAX_CLIENTS]; int sortedscores[MAX_CLIENTS]; int score, total, highscore=0; int y; //float accuracy; int time_left=999, frag_left=999; gclient_t *cl; edict_t *cl_ent; // if we are looking at the scoreboard or inventory, deactivate the scanner if (ent->client->showscores || ent->client->showinventory) { if (ent->client->pers.scanner_active) ent->client->pers.scanner_active = 2; } else { *string = 0; // Scanner active ? if (ent->client->pers.scanner_active & 1) ShowScanner(ent,string); // normal quake code ... gi.WriteByte (svc_layout); gi.WriteString (string); return; } // sort the clients by score total = 0; for (i=0 ; i<game.maxclients ; i++) { cl_ent = g_edicts + 1 + i; //3.0 scoreboard code fix if (!cl_ent->client || !cl_ent->inuse || cl_ent->client->resp.spectator) continue; score = game.clients[i].resp.score; for (j=0 ; j<total ; j++) { if (score > sortedscores[j]) break; } for (k=total ; k>j ; k--) { sorted[k] = sorted[k-1]; sortedscores[k] = sortedscores[k-1]; } sorted[j] = i; sortedscores[j] = score; total++; } // print level name and exit rules string[0] = 0; stringlength = strlen(string); // make a header for the data //K03 Begin if (timelimit->value) time_left = (timelimit->value*60 - level.time); else time_left = 60*99; if (fraglimit->value) frag_left = (fraglimit->value - V_HighestFragScore()); if (time_left < 0) time_left = 0; Com_sprintf(entry, sizeof(entry), "xv 0 yv 16 string2 \"Time:%2im %2is Frags:%3i Players:%3i\" " "xv 0 yv 24 string2 \"Name Lv Cl Score Frg Spr Png\" ", (int)(time_left/60), (int)(time_left-(int)((time_left/60)*60)), frag_left, total_players()); //K03 End j = strlen(entry); //gi.dprintf("header string length=%d\n", j); if (stringlength + j < MAX_ENTRY_SIZE) { strcpy (string + stringlength, entry); stringlength += j; } // add the clients in sorted order if (total > 24) total = 24; /* The screen is only so big :( */ for (i=0 ; i<total ; i++) { cl = &game.clients[sorted[i]]; cl_ent = g_edicts + 1 + sorted[i]; if (!cl_ent) continue; y = 34 + 8 * i; // 3.78 truncate client's name and class string strcpy(name, V_TruncateString(cl->pers.netname, 11)); strcpy(classname, V_TruncateString(GetClassString(cl_ent->myskills.class_num), 3)); padRight(name, 10); Com_sprintf(entry, sizeof(entry), "xv 0 yv %i string \"%s %2i %s %5i %3i %3i %3i\" ", y, name, cl_ent->myskills.level, classname, cl->resp.score, cl->resp.frags, cl_ent->myskills.streak, cl->ping); j = strlen(entry); //gi.dprintf("player string length=%d\n", j); if (stringlength + j > MAX_ENTRY_SIZE) break; strcpy (string + stringlength, entry); stringlength += j; } gi.WriteByte (svc_layout); gi.WriteString (string); }
/* ================ CL_DrawInventory ================ */ void CL_DrawInventory(void) { int i, j; int num, selected_num, item; int index[MAX_ITEMS]; char string[1024]; int x, y; char binding[1024]; const char * bind; int selected; int top; enum { DISPLAY_ITEMS = 17 }; selected = cl.frame.playerstate.stats[STAT_SELECTED_ITEM]; num = 0; selected_num = 0; for (i = 0; i < MAX_ITEMS; i++) { if (i == selected) { selected_num = num; } if (cl.inventory[i]) { index[num] = i; num++; } } // determine scroll point top = selected_num - DISPLAY_ITEMS / 2; if (num - top < DISPLAY_ITEMS) { top = num - DISPLAY_ITEMS; } if (top < 0) { top = 0; } x = (viddef.width - 256) / 2; y = (viddef.height - 240) / 2; // repaint everything next frame SCR_DirtyScreen(); re.DrawPic(x, y + 8, "inventory"); y += 24; x += 24; Inv_DrawString(x, y, "hotkey ### item"); Inv_DrawString(x, y + 8, "------ --- ----"); y += 16; for (i = top; i < num && i < top + DISPLAY_ITEMS; i++) { item = index[i]; // search for a binding Com_sprintf(binding, sizeof(binding), "use %s", cl.configstrings[CS_ITEMS + item]); bind = ""; for (j = 0; j < 256; j++) { if (keybindings[j] && !Q_stricmp(keybindings[j], binding)) { bind = Key_KeynumToString(j); break; } } Com_sprintf(string, sizeof(string), "%6s %3i %s", bind, cl.inventory[item], cl.configstrings[CS_ITEMS + item]); if (item != selected) { SetStringHighBit(string); } else // draw a blinky cursor by the selected item { if ((int)(cls.realtime * 10) & 1) re.DrawChar(x - 8, y, 15); } Inv_DrawString(x, y, string); y += 8; } }
unsigned int __stdcall png_write_thread (byte *buffer) { char picname[MAX_OSPATH]; char checkname[MAX_OSPATH]; int i; FILE *f; png_structp png_ptr; png_infop info_ptr; unsigned k; png_bytepp row_pointers; // create the scrnshots directory if it doesn't exist Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/", ri.FS_Gamedir()); FS_CreatePath (checkname); for (i = 0; i < 999; i++) { sprintf (picname, "%s/scrnshot/quake%.3d.png", ri.FS_Gamedir(), i); f = fopen (picname, "rb"); if (!f) break; fclose (f); } f = fopen (picname, "wb"); if (!f) { ri.Con_Printf (PRINT_ALL, "Couldn't open %s for writing.\n", picname); #ifdef USE_THREADS ExitThread (1); #else return 1; #endif } png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { ri.Con_Printf (PRINT_ALL, "libpng error\n", picname); #ifdef USE_THREADS ExitThread (1); #else return 1; #endif } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); ri.Con_Printf (PRINT_ALL, "libpng error\n", picname); #ifdef USE_THREADS ExitThread (1); #else return 1; #endif } png_init_io(png_ptr, f); png_set_IHDR(png_ptr, info_ptr, vid.width, vid.height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION); png_set_compression_mem_level(png_ptr, 9); png_set_compression_buffer_size(png_ptr, vid.width * vid.height * 3); png_write_info(png_ptr, info_ptr); row_pointers = malloc(vid.height * sizeof(png_bytep)); if (!row_pointers) ri.Sys_Error (ERR_FATAL, "png_write_thread: out of memory"); for (k = 0; k < vid.height; k++) row_pointers[k] = buffer + (vid.height-1-k)*3*vid.width; png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose (f); free (buffer); free (row_pointers); ri.Con_Printf (PRINT_ALL, "Finished, wrote %s\n", picname); #ifdef USE_THREADS ExitThread (0); #endif return 0; }
/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. ================ */ void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate, qboolean attractloop, qboolean loadgame) { int i; unsigned checksum; if (attractloop) Cvar_Set ("paused", "0"); Com_Printf ("------- Server Initialization -------\n"); Com_DPrintf ("SpawnServer: %s\n",server); if (sv.demofile) fclose (sv.demofile); svs.spawncount++; // any partially connected client will be // restarted sv.state = ss_dead; Com_SetServerState (sv.state); // wipe the entire per-level structure memset (&sv, 0, sizeof(sv)); svs.realtime = 0; sv.loadgame = loadgame; sv.attractloop = attractloop; // save name for levels that don't set message strcpy (sv.configstrings[CS_NAME], server); if (Cvar_VariableValue ("deathmatch")) { sprintf(sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value); pm_airaccelerate = sv_airaccelerate->value; } else { strcpy(sv.configstrings[CS_AIRACCEL], "0"); pm_airaccelerate = 0; } SZ_Init (&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf)); strcpy (sv.name, server); // leave slots at start for clients only for (i=0 ; i<maxclients->value ; i++) { // needs to reconnect if (svs.clients[i].state > cs_connected) svs.clients[i].state = cs_connected; svs.clients[i].lastframe = -1; } sv.time = 1000; strcpy (sv.name, server); strcpy (sv.configstrings[CS_NAME], server); if (serverstate != ss_game) { sv.models[1] = CM_LoadMap ("", false, &checksum); // no real map } else { Com_sprintf (sv.configstrings[CS_MODELS+1],sizeof(sv.configstrings[CS_MODELS+1]), "maps/%s.bsp", server); sv.models[1] = CM_LoadMap (sv.configstrings[CS_MODELS+1], false, &checksum); } Com_sprintf (sv.configstrings[CS_MAPCHECKSUM],sizeof(sv.configstrings[CS_MAPCHECKSUM]), "%i", checksum); // // clear physics interaction links // SV_ClearWorld (); for (i=1 ; i< CM_NumInlineModels() ; i++) { Com_sprintf (sv.configstrings[CS_MODELS+1+i], sizeof(sv.configstrings[CS_MODELS+1+i]), "*%i", i); sv.models[i+1] = CM_InlineModel (sv.configstrings[CS_MODELS+1+i]); } // // spawn the rest of the entities on the map // // precache and static commands can be issued during // map initialization sv.state = ss_loading; Com_SetServerState (sv.state); // load and spawn all other entities ge->SpawnEntities ( sv.name, CM_EntityString(), spawnpoint ); // run two frames to allow everything to settle ge->RunFrame (); ge->RunFrame (); // all precaches are complete sv.state = serverstate; Com_SetServerState (sv.state); // create a baseline for more efficient communications SV_CreateBaseline (); // check for a savegame SV_CheckForSavegame (); // set serverinfo variable Cvar_FullSet ("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET); Com_Printf ("-------------------------------------\n"); }
void GL_ScreenShot_JPG (byte *buffer) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW s[1]; FILE *f; char picname[80], checkname[MAX_OSPATH]; int i, offset, w3; // create the scrnshots directory if it doesn't exist Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/", ri.FS_Gamedir()); FS_CreatePath (checkname); for (i = 0; i < 999; i++) { sprintf (picname, "%s/scrnshot/quake%.3d.jpg", ri.FS_Gamedir(), i); f = fopen (picname, "rb"); if (!f) break; fclose (f); } f = fopen (picname, "wb"); if (!f) { ri.Con_Printf (PRINT_ALL, "Couldn't open %s for writing.\n", picname); return; } // Initialise the JPEG compression object cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, f); // Setup JPEG Parameters cinfo.image_width = vid.width; cinfo.image_height = vid.height; cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3; jpeg_set_defaults(&cinfo); // Niceass: 85 is the quality. 0-100 jpeg_set_quality(&cinfo, Q_ftol(gl_jpg_quality->value), TRUE); // Start Compression jpeg_start_compress(&cinfo, true); // Feed scanline data w3 = cinfo.image_width * 3; offset = w3 * cinfo.image_height - w3; while (cinfo.next_scanline < cinfo.image_height) { s[0] = &buffer[offset - cinfo.next_scanline * w3]; jpeg_write_scanlines(&cinfo, s, 1); } // Finish Compression jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); fclose(f); free(buffer); ri.Con_Printf (PRINT_ALL, "Wrote %s\n", picname); }
void UI_SaveForceTemplate() { char *selectedName = UI_Cvar_VariableString("ui_SaveFCF"); char fcfString[512]; char forceStringValue[4]; fileHandle_t f; int strPlace = 0; int forcePlace = 0; int i = 0; qboolean foundFeederItem = qfalse; if (!selectedName || !selectedName[0]) { Com_Printf("You did not provide a name for the template.\n"); return; } if (uiForceSide == FORCE_LIGHTSIDE) { //write it into the light side folder trap_FS_FOpenFile(va("forcecfg/light/%s.fcf", selectedName), &f, FS_WRITE); } else { //if it isn't light it must be dark trap_FS_FOpenFile(va("forcecfg/dark/%s.fcf", selectedName), &f, FS_WRITE); } if (!f) { Com_Printf("There was an error writing the template file (read-only?).\n"); return; } Com_sprintf(fcfString, sizeof(fcfString), "%i-%i-", uiForceRank, uiForceSide); strPlace = strlen(fcfString); while (forcePlace < NUM_FORCE_POWERS) { Com_sprintf(forceStringValue, sizeof(forceStringValue), "%i", uiForcePowersRank[forcePlace]); //Just use the force digit even if multiple digits. Shouldn't be longer than 1. fcfString[strPlace] = forceStringValue[0]; strPlace++; forcePlace++; } fcfString[strPlace] = '\n'; fcfString[strPlace+1] = 0; trap_FS_Write(fcfString, strlen(fcfString), f); trap_FS_FCloseFile(f); Com_Printf("Template saved as \"%s\".\n", selectedName); //Now, update the FCF list UI_LoadForceConfig_List(); //Then, scroll through and select the template for the file we just saved while (i < uiInfo.forceConfigCount) { if (!Q_stricmp(uiInfo.forceConfigNames[i], selectedName)) { if ((uiForceSide == FORCE_LIGHTSIDE && uiInfo.forceConfigSide[i]) || (uiForceSide == FORCE_DARKSIDE && !uiInfo.forceConfigSide[i])) { Menu_SetFeederSelection(NULL, FEEDER_FORCECFG, UI_TranslateFCFIndex(i), NULL); foundFeederItem = qtrue; } } i++; } //Else, go back to 0 if (!foundFeederItem) { Menu_SetFeederSelection(NULL, FEEDER_FORCECFG, 0, NULL); } }
/* ================== Cmd_CallTeamVote_f ================== */ void Cmd_CallTeamVote_f( gentity_t *ent ) { int i, team, cs_offset; char arg1[MAX_STRING_TOKENS]; char arg2[MAX_STRING_TOKENS]; team = ent->client->sess.sessionTeam; if ( team == TEAM_RED ) cs_offset = 0; else if ( team == TEAM_BLUE ) cs_offset = 1; else return; if ( !g_allowVote.integer ) { trap_SendServerCommand( ent-g_entities, "print \"Voting not allowed here.\n\"" ); return; } if ( level.teamVoteTime[cs_offset] ) { trap_SendServerCommand( ent-g_entities, "print \"A team vote is already in progress.\n\"" ); return; } if ( ent->client->pers.teamVoteCount >= MAX_VOTE_COUNT ) { trap_SendServerCommand( ent-g_entities, "print \"You have called the maximum number of team votes.\n\"" ); return; } if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) { trap_SendServerCommand( ent-g_entities, "print \"Not allowed to call a vote as spectator.\n\"" ); return; } // make sure it is a valid command to vote on trap_Argv( 1, arg1, sizeof( arg1 ) ); arg2[0] = '\0'; for ( i = 2; i < trap_Argc(); i++ ) { if (i > 2) strcat(arg2, " "); trap_Argv( i, &arg2[strlen(arg2)], sizeof( arg2 ) - strlen(arg2) ); } if( strchr( arg1, ';' ) || strchr( arg2, ';' ) ) { trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" ); return; } if ( !Q_stricmp( arg1, "leader" ) ) { char netname[MAX_NETNAME], leader[MAX_NETNAME]; if ( !arg2[0] ) { i = ent->client->ps.clientNum; } else { // numeric values are just slot numbers for (i = 0; i < 3; i++) { if ( !arg2[i] || arg2[i] < '0' || arg2[i] > '9' ) break; } if ( i >= 3 || !arg2[i]) { i = atoi( arg2 ); if ( i < 0 || i >= level.maxclients ) { trap_SendServerCommand( ent-g_entities, va("print \"Bad client slot: %i\n\"", i) ); return; } if ( !g_entities[i].inuse ) { trap_SendServerCommand( ent-g_entities, va("print \"Client %i is not active\n\"", i) ); return; } } else { Q_strncpyz(leader, arg2, sizeof(leader)); Q_CleanStr(leader); for ( i = 0 ; i < level.maxclients ; i++ ) { if ( level.clients[i].pers.connected == CON_DISCONNECTED ) continue; if (level.clients[i].sess.sessionTeam != team) continue; Q_strncpyz(netname, level.clients[i].pers.netname, sizeof(netname)); Q_CleanStr(netname); if ( !Q_stricmp(netname, leader) ) { break; } } if ( i >= level.maxclients ) { trap_SendServerCommand( ent-g_entities, va("print \"%s is not a valid player on your team.\n\"", arg2) ); return; } } } Com_sprintf(arg2, sizeof(arg2), "%d", i); } else { trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" ); trap_SendServerCommand( ent-g_entities, "print \"Team vote commands are: leader <player>.\n\"" ); return; } Com_sprintf( level.teamVoteString[cs_offset], sizeof( level.teamVoteString[cs_offset] ), "%s %s", arg1, arg2 ); for ( i = 0 ; i < level.maxclients ; i++ ) { if ( level.clients[i].pers.connected == CON_DISCONNECTED ) continue; if (level.clients[i].sess.sessionTeam == team) trap_SendServerCommand( i, va("print \"%s called a team vote.\n\"", ent->client->pers.netname ) ); } // start the voting, the caller autoamtically votes yes level.teamVoteTime[cs_offset] = level.time; level.teamVoteYes[cs_offset] = 1; level.teamVoteNo[cs_offset] = 0; for ( i = 0 ; i < level.maxclients ; i++ ) { if (level.clients[i].sess.sessionTeam == team) level.clients[i].ps.eFlags &= ~EF_TEAMVOTED; } ent->client->ps.eFlags |= EF_TEAMVOTED; trap_SetConfigstring( CS_TEAMVOTE_TIME + cs_offset, va("%i", level.teamVoteTime[cs_offset] ) ); trap_SetConfigstring( CS_TEAMVOTE_STRING + cs_offset, level.teamVoteString[cs_offset] ); trap_SetConfigstring( CS_TEAMVOTE_YES + cs_offset, va("%i", level.teamVoteYes[cs_offset] ) ); trap_SetConfigstring( CS_TEAMVOTE_NO + cs_offset, va("%i", level.teamVoteNo[cs_offset] ) ); }
/* ================ CL_ParseSnapshot If the snapshot is parsed properly, it will be copied to cl.snap and saved in cl.snapshots[]. If the snapshot is invalid for any reason, no changes to the state will be made at all. ================ */ void CL_ParseSnapshot(msg_t* msg) { int len; clSnapshot_t* old; clSnapshot_t newSnap; int deltaNum; int oldMessageNum; int i, packetNum; // get the reliable sequence acknowledge number // NOTE: now sent with all server to client messages // clc.reliableAcknowledge = MSG_ReadLong( msg ); // read in the new snapshot to a temporary buffer // we will only copy to cl.snap if it is valid Com_Memset(&newSnap, 0, sizeof(newSnap)); // we will have read any new server commands in this // message before we got to svc_snapshot newSnap.serverCommandNum = clc.serverCommandSequence; newSnap.serverTime = MSG_ReadLong(msg); // if we were just unpaused, we can only *now* really let the // change come into effect or the client hangs. cl_paused->modified = 0; newSnap.messageNum = clc.serverMessageSequence; deltaNum = MSG_ReadByte(msg); if (!deltaNum) { newSnap.deltaNum = -1; } else { newSnap.deltaNum = newSnap.messageNum - deltaNum; } newSnap.snapFlags = MSG_ReadByte(msg); // If the frame is delta compressed from data that we // no longer have available, we must suck up the rest of // the frame, but not use it, then ask for a non-compressed // message if (newSnap.deltaNum <= 0) { newSnap.valid = true; // uncompressed frame old = nullptr; if (clc.demorecording) { clc.demowaiting = false; // we can start recording now // if(cl_autorecord->integer) { // Cvar_Set( "g_synchronousClients", "0" ); // } } else { if (cl_autorecord ->integer /*&& Cvar_VariableValue( "g_synchronousClients") */) { char name[256]; char mapname[MAX_QPATH]; char* period; qtime_t time; Com_RealTime(&time); Q_strncpyz(mapname, cl.mapname, MAX_QPATH); for (period = mapname; *period; period++) { if (*period == '.') { *period = '\0'; break; } } for (period = mapname; *period; period++) { if (*period == '/') { break; } } if (*period) { period++; } Com_sprintf(name, sizeof(name), "demos/%s_%04i-%02i-%02i_%02i%02i%02i.dm_%d", period, 1900 + time.tm_year, time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec, PROTOCOL_VERSION); CL_Record(name); } } } else { old = &cl.snapshots[newSnap.deltaNum & PACKET_MASK]; if (!old->valid) { // should never happen Com_Printf("Delta from invalid frame (not supposed to happen!).\n"); } else if (old->messageNum != newSnap.deltaNum) { // The frame that the server did the delta from // is too old, so we can't reconstruct it properly. Com_DPrintf("Delta frame too old.\n"); } else if (cl.parseEntitiesNum - old->parseEntitiesNum > MAX_PARSE_ENTITIES - 128) { Com_DPrintf("Delta parseEntitiesNum too old.\n"); } else { newSnap.valid = true; // valid delta parse } } // read areamask len = MSG_ReadByte(msg); if (len > sizeof(newSnap.areamask)) { Com_Error(ERR_DROP, "CL_ParseSnapshot: Invalid size %d for areamask.", len); } MSG_ReadData(msg, &newSnap.areamask, len); // read playerinfo SHOWNET(msg, "playerstate"); if (old) { MSG_ReadDeltaPlayerstate(msg, &old->ps, &newSnap.ps); } else { MSG_ReadDeltaPlayerstate(msg, nullptr, &newSnap.ps); } // read packet entities SHOWNET(msg, "packet entities"); CL_ParsePacketEntities(msg, old, &newSnap); // if not valid, dump the entire thing now that it has // been properly read if (!newSnap.valid) { return; } // clear the valid flags of any snapshots between the last // received and this one, so if there was a dropped packet // it won't look like something valid to delta from next // time we wrap around in the buffer oldMessageNum = cl.snap.messageNum + 1; if (newSnap.messageNum - oldMessageNum >= PACKET_BACKUP) { oldMessageNum = newSnap.messageNum - (PACKET_BACKUP - 1); } for (; oldMessageNum < newSnap.messageNum; oldMessageNum++) { cl.snapshots[oldMessageNum & PACKET_MASK].valid = false; } // copy to the current good spot cl.snap = newSnap; cl.snap.ping = 999; // calculate ping time for (i = 0; i < PACKET_BACKUP; i++) { packetNum = (clc.netchan.outgoingSequence - 1 - i) & PACKET_MASK; if (cl.snap.ps.commandTime >= cl.outPackets[packetNum].p_serverTime) { cl.snap.ping = cls.realtime - cl.outPackets[packetNum].p_realtime; break; } } // save the frame off in the backup array for later delta comparisons cl.snapshots[cl.snap.messageNum & PACKET_MASK] = cl.snap; if (cl_shownet->integer == 3) { Com_Printf(" snapshot:%i delta:%i ping:%i\n", cl.snap.messageNum, cl.snap.deltaNum, cl.snap.ping); } cl.newSnapshots = true; }
void func_clock_think (edict_t * self) { if (!self->enemy) { self->enemy = G_Find (NULL, FOFS (targetname), self->target); if (!self->enemy) return; } if (self->spawnflags & 1) { func_clock_format_countdown (self); self->health++; } else if (self->spawnflags & 2) { func_clock_format_countdown (self); self->health--; } else { struct tm *ltime; time_t gmtime; time (&gmtime); ltime = localtime (&gmtime); Com_sprintf (self->message, CLOCK_MESSAGE_SIZE, "%2i:%2i:%2i", ltime->tm_hour, ltime->tm_min, ltime->tm_sec); if (self->message[3] == ' ') self->message[3] = '0'; if (self->message[6] == ' ') self->message[6] = '0'; } self->enemy->message = self->message; self->enemy->use (self->enemy, self, self); if (((self->spawnflags & 1) && (self->health > self->wait)) || ((self->spawnflags & 2) && (self->health < self->wait))) { if (self->pathtarget) { char *savetarget; char *savemessage; savetarget = self->target; savemessage = self->message; self->target = self->pathtarget; self->message = NULL; G_UseTargets (self, self->activator); self->target = savetarget; self->message = savemessage; } if (!(self->spawnflags & 8)) return; func_clock_reset (self); if (self->spawnflags & 4) return; } self->nextthink = level.time + 1; }
void InitSiegeMode( void ) { vmCvar_t mapname; char levelname[512]; char teamIcon[128]; char goalreq[64]; char teams[2048]; char objective[MAX_SIEGE_INFO_SIZE]; char objecStr[8192]; int len = 0; int i = 0; // int j = 0; int objectiveNumTeam1 = 0; int objectiveNumTeam2 = 0; fileHandle_t f; if ( level.gametype != GT_SIEGE ) { goto failure; } //reset SiegeSetCompleteData( 0 ); //get pers data in case it existed from last level if ( g_siegeTeamSwitch.integer ) { trap->SiegePersGet( &g_siegePersistant ); if ( g_siegePersistant.beatingTime ) { trap->SetConfigstring( CS_SIEGE_TIMEOVERRIDE, va( "%i", g_siegePersistant.lastTime ) ); } else { trap->SetConfigstring( CS_SIEGE_TIMEOVERRIDE, "0" ); } } else { //hmm, ok, nothing. trap->SetConfigstring( CS_SIEGE_TIMEOVERRIDE, "0" ); } imperial_goals_completed = 0; rebel_goals_completed = 0; trap->Cvar_Register( &mapname, "mapname", "", CVAR_SERVERINFO | CVAR_ROM ); Com_sprintf( levelname, sizeof(levelname), "maps/%s.siege\0", mapname.string ); if ( !levelname[0] ) { goto failure; } len = trap->FS_Open( levelname, &f, FS_READ ); if ( !f || len >= MAX_SIEGE_INFO_SIZE ) { goto failure; } trap->FS_Read( siege_info, len, f ); trap->FS_Close( f ); siege_valid = 1; //See if players should be specs or ingame preround if ( BG_SiegeGetPairedValue( siege_info, "preround_state", teams ) ) { if ( teams[0] ) { g_preroundState = atoi( teams ); } } if ( BG_SiegeGetValueGroup( siege_info, "Teams", teams ) ) { if ( g_siegeTeam1.string[0] && Q_stricmp( g_siegeTeam1.string, "none" ) ) { //check for override Q_strncpyz( team1, g_siegeTeam1.string, sizeof(team1) ); } else { //otherwise use level default BG_SiegeGetPairedValue( teams, "team1", team1 ); } if ( g_siegeTeam2.string[0] && Q_stricmp( g_siegeTeam2.string, "none" ) ) { //check for override Q_strncpyz( team2, g_siegeTeam2.string, sizeof(team2) ); } else { //otherwise use level default BG_SiegeGetPairedValue( teams, "team2", team2 ); } } else { trap->Error( ERR_DROP, "Siege teams not defined" ); } if ( BG_SiegeGetValueGroup( siege_info, team2, gParseObjectives ) ) { if ( BG_SiegeGetPairedValue( gParseObjectives, "TeamIcon", teamIcon ) ) { trap->Cvar_Set( "team2_icon", teamIcon ); } if ( BG_SiegeGetPairedValue( gParseObjectives, "RequiredObjectives", goalreq ) ) { rebel_goals_required = atoi( goalreq ); } if ( BG_SiegeGetPairedValue( gParseObjectives, "Timed", goalreq ) ) { rebel_time_limit = atoi( goalreq ) * 1000; if ( g_siegeTeamSwitch.integer && g_siegePersistant.beatingTime ) { gRebelCountdown = level.time + g_siegePersistant.lastTime; } else { gRebelCountdown = level.time + rebel_time_limit; } } if ( BG_SiegeGetPairedValue( gParseObjectives, "attackers", goalreq ) ) { rebel_attackers = atoi( goalreq ); } } if ( BG_SiegeGetValueGroup( siege_info, team1, gParseObjectives ) ) { if ( BG_SiegeGetPairedValue( gParseObjectives, "TeamIcon", teamIcon ) ) { trap->Cvar_Set( "team1_icon", teamIcon ); } if ( BG_SiegeGetPairedValue( gParseObjectives, "RequiredObjectives", goalreq ) ) { imperial_goals_required = atoi( goalreq ); } if ( BG_SiegeGetPairedValue( gParseObjectives, "Timed", goalreq ) ) { if ( rebel_time_limit ) { Com_Printf( "Tried to set imperial time limit, but there's already a rebel time limit!\nOnly one team can have a time limit.\n" ); } else { imperial_time_limit = atoi( goalreq ) * 1000; if ( g_siegeTeamSwitch.integer && g_siegePersistant.beatingTime ) { gImperialCountdown = level.time + g_siegePersistant.lastTime; } else { gImperialCountdown = level.time + imperial_time_limit; } } } if ( BG_SiegeGetPairedValue( gParseObjectives, "attackers", goalreq ) ) { imperial_attackers = atoi( goalreq ); } } //Load the player class types BG_SiegeLoadClasses( NULL ); if ( !bgNumSiegeClasses ) { //We didn't find any?! trap->Error( ERR_DROP, "Couldn't find any player classes for Siege" ); } /* //We could probably just see what teams are used on this level, //then see what classes are used by those teams, and then precache //all weapons for said classes. However, I'm just going to do them //all for now. while (i < bgNumSiegeClasses) { cl = &bgSiegeClasses[i]; j = 0; while (j < WP_NUM_WEAPONS) { if (cl->weapons & (1 << j)) { //we use this weapon so register it. RegisterItem(BG_FindItemForWeapon(j)); } j++; } i++; } */ //Ok, I'm adding inventory item precaching now, so I'm finally going to optimize this //to only do weapons/items for the current teams used on the level. //Now load the teams since we have class data. BG_SiegeLoadTeams(); if ( !bgNumSiegeTeams ) { //React same as with classes. trap->Error( ERR_DROP, "Couldn't find any player teams for Siege" ); } //Get and set the team themes for each team. This will control which classes can be //used on each team. if ( BG_SiegeGetValueGroup( siege_info, team1, gParseObjectives ) ) { if ( BG_SiegeGetPairedValue( gParseObjectives, "UseTeam", goalreq ) ) { BG_SiegeSetTeamTheme( SIEGETEAM_TEAM1, goalreq ); } //Now count up the objectives for this team. i = 1; strcpy( objecStr, va( "Objective%i", i ) ); while ( BG_SiegeGetValueGroup( gParseObjectives, objecStr, objective ) ) { objectiveNumTeam1++; i++; strcpy( objecStr, va( "Objective%i", i ) ); } } if ( BG_SiegeGetValueGroup( siege_info, team2, gParseObjectives ) ) { if ( BG_SiegeGetPairedValue( gParseObjectives, "UseTeam", goalreq ) ) { BG_SiegeSetTeamTheme( SIEGETEAM_TEAM2, goalreq ); } //Now count up the objectives for this team. i = 1; strcpy( objecStr, va( "Objective%i", i ) ); while ( BG_SiegeGetValueGroup( gParseObjectives, objecStr, objective ) ) { objectiveNumTeam2++; i++; strcpy( objecStr, va( "Objective%i", i ) ); } } //Set the configstring to show status of all current objectives strcpy( gObjectiveCfgStr, "t1" ); while ( objectiveNumTeam1 > 0 ) { //mark them all as not completed since we just initialized Q_strcat( gObjectiveCfgStr, 1024, "-0" ); objectiveNumTeam1--; } //Finished doing team 1's objectives, now do team 2's Q_strcat( gObjectiveCfgStr, 1024, "|t2" ); while ( objectiveNumTeam2 > 0 ) { Q_strcat( gObjectiveCfgStr, 1024, "-0" ); objectiveNumTeam2--; } //And finally set the actual config string trap->SetConfigstring( CS_SIEGE_OBJECTIVES, gObjectiveCfgStr ); //precache saber data for classes that use sabers on both teams BG_PrecacheSabersForSiegeTeam( SIEGETEAM_TEAM1 ); BG_PrecacheSabersForSiegeTeam( SIEGETEAM_TEAM2 ); G_SiegeRegisterWeaponsAndHoldables( SIEGETEAM_TEAM1 ); G_SiegeRegisterWeaponsAndHoldables( SIEGETEAM_TEAM2 ); return; failure: siege_valid = 0; }
/* ================== SCR_PlayCinematic ================== */ void SCR_PlayCinematic (char *arg) { int width, height; byte *palette; char name[MAX_OSPATH], *dot; int old_khz; // make sure CD isn't playing music CDAudio_Stop(); cl.cinematicframe = 0; dot = strstr (arg, "."); if (dot && !strcmp (dot, ".pcx")) { // static pcx image Com_sprintf (name, sizeof(name), "pics/%s", arg); SCR_LoadPCX (name, &cin.pic, &palette, &cin.width, &cin.height); cl.cinematicframe = -1; cl.cinematictime = 1; SCR_EndLoadingPlaque (); cls.state = ca_active; if (!cin.pic) { Com_Printf ("%s not found.\n", name); cl.cinematictime = 0; } else { memcpy (cl.cinematicpalette, palette, sizeof(cl.cinematicpalette)); Z_Free (palette); } return; } Com_sprintf (name, sizeof(name), "video/%s", arg); FS_FOpenFile (name, &cl.cinematic_file); if (!cl.cinematic_file) { // Com_Error (ERR_DROP, "Cinematic %s not found.\n", name); SCR_FinishCinematic (); cl.cinematictime = 0; // done return; } SCR_EndLoadingPlaque (); cls.state = ca_active; FS_Read (&width, 4, cl.cinematic_file); FS_Read (&height, 4, cl.cinematic_file); cin.width = LittleLong(width); cin.height = LittleLong(height); FS_Read (&cin.s_rate, 4, cl.cinematic_file); cin.s_rate = LittleLong(cin.s_rate); FS_Read (&cin.s_width, 4, cl.cinematic_file); cin.s_width = LittleLong(cin.s_width); FS_Read (&cin.s_channels, 4, cl.cinematic_file); cin.s_channels = LittleLong(cin.s_channels); Huff1TableInit (); // switch up to 22 khz sound if necessary old_khz = Cvar_VariableValue ("s_khz"); if (old_khz != cin.s_rate/1000) { cin.restart_sound = true; Cvar_SetValue ("s_khz", cin.s_rate/1000); CL_Snd_Restart_f (); Cvar_SetValue ("s_khz", old_khz); } cl.cinematicframe = 0; cin.pic = SCR_ReadNextFrame (); cl.cinematictime = Sys_Milliseconds (); }
/* ================== UpdateTournamentInfo ================== */ void UpdateTournamentInfo(void) { int i; gentity_t *player; int playerClientNum; int n, accuracy, perfect, msglen; int buflen; int score1, score2; qboolean won; char buf[32]; char msg[MAX_STRING_CHARS]; // find the real player player = NULL; for(i = 0; i < level.maxclients; i++) { player = &g_entities[i]; if(!player->inuse) { continue; } if(!(player->r.svFlags & SVF_BOT)) { break; } } // this should never happen! if(!player || i == level.maxclients) { return; } playerClientNum = i; CalculateRanks(); if(level.clients[playerClientNum].sess.sessionTeam == TEAM_SPECTATOR) { Com_sprintf(msg, sizeof(msg), "postgame %i %i 0 0 0 0 0 0 0 0 0 0 0 0", level.numNonSpectatorClients, playerClientNum); } else { if(player->client->accuracy_shots) { accuracy = player->client->accuracy_hits * 100 / player->client->accuracy_shots; } else { accuracy = 0; } won = qfalse; if(g_gametype.integer >= GT_CTF) { score1 = level.teamScores[TEAM_RED]; score2 = level.teamScores[TEAM_BLUE]; if(level.clients[playerClientNum].sess.sessionTeam == TEAM_RED) { won = (level.teamScores[TEAM_RED] > level.teamScores[TEAM_BLUE]); } else { won = (level.teamScores[TEAM_BLUE] > level.teamScores[TEAM_RED]); } } else { if(&level.clients[playerClientNum] == &level.clients[level.sortedClients[0]]) { won = qtrue; score1 = level.clients[level.sortedClients[0]].ps.persistant[PERS_SCORE]; score2 = level.clients[level.sortedClients[1]].ps.persistant[PERS_SCORE]; } else { score2 = level.clients[level.sortedClients[0]].ps.persistant[PERS_SCORE]; score1 = level.clients[level.sortedClients[1]].ps.persistant[PERS_SCORE]; } } if(won && player->client->ps.persistant[PERS_KILLED] == 0) { perfect = 1; } else { perfect = 0; } Com_sprintf(msg, sizeof(msg), "postgame %i %i %i %i %i %i %i %i %i %i %i %i %i %i", level.numNonSpectatorClients, playerClientNum, accuracy, player->client->ps.persistant[PERS_IMPRESSIVE_COUNT], player->client->ps.persistant[PERS_EXCELLENT_COUNT], player->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT], player->client->ps.persistant[PERS_TELEFRAG_FRAG_COUNT], player->client->ps.persistant[PERS_SCORE], perfect, won, score1, score2, level.time, player->client->ps.persistant[PERS_CAPTURES]); } msglen = strlen(msg); for(i = 0; i < level.numNonSpectatorClients; i++) { n = level.sortedClients[i]; Com_sprintf(buf, sizeof(buf), " %i %i %i", n, level.clients[n].ps.persistant[PERS_RANK], level.clients[n].ps.persistant[PERS_SCORE]); buflen = strlen(buf); if(msglen + buflen + 1 >= sizeof(msg)) { break; } strcat(msg, buf); } trap_SendConsoleCommand(EXEC_APPEND, msg); }
/* ================= S_CodecGetSound Opens/loads a sound, tries codec based on the sound's file extension then tries all supported codecs. ================= */ static void *S_CodecGetSound(const char *filename, snd_info_t *info) { snd_codec_t *codec; snd_codec_t *orgCodec = NULL; qboolean orgNameFailed = qfalse; char localName[ MAX_QPATH ]; const char *ext; char altName[ MAX_QPATH ]; void *rtn = NULL; Q_strncpyz(localName, filename, MAX_QPATH); ext = COM_GetExtension(localName); if( *ext ) { // Look for the correct loader and use it for( codec = codecs; codec; codec = codec->next ) { if( !Q_stricmp( ext, codec->ext ) ) { // Load if( info ) rtn = codec->load(localName, info); else rtn = codec->open(localName); break; } } // A loader was found if( codec ) { if( !rtn ) { // Loader failed, most likely because the file isn't there; // try again without the extension orgNameFailed = qtrue; orgCodec = codec; COM_StripExtension( filename, localName, MAX_QPATH ); } else { // Something loaded return rtn; } } } // Try and find a suitable match using all // the sound codecs supported for( codec = codecs; codec; codec = codec->next ) { if( codec == orgCodec ) continue; Com_sprintf( altName, sizeof (altName), "%s.%s", localName, codec->ext ); // Load if( info ) rtn = codec->load(altName, info); else rtn = codec->open(altName); if( rtn ) { if( orgNameFailed ) { Com_DPrintf(S_COLOR_YELLOW "WARNING: %s not present, using %s instead\n", filename, altName ); } return rtn; } } Com_Printf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename); return NULL; }
void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) { clc.cURLUsed = qtrue; Com_Printf("URL: %s\n", remoteURL); Com_DPrintf("***** CL_cURL_BeginDownload *****\n" "Localname: %s\n" "RemoteURL: %s\n" "****************************\n", localName, remoteURL); CL_cURL_Cleanup(); Q_strncpyz(clc.downloadURL, remoteURL, sizeof(clc.downloadURL)); Q_strncpyz(clc.downloadName, localName, sizeof(clc.downloadName)); Com_sprintf(clc.downloadTempName, sizeof(clc.downloadTempName), "%s.tmp", localName); // Set so UI gets access to it Cvar_Set("cl_downloadName", localName); Cvar_Set("cl_downloadSize", "0"); Cvar_Set("cl_downloadCount", "0"); Cvar_SetValue("cl_downloadTime", cls.realtime); clc.downloadBlock = 0; // Starting new file clc.downloadCount = 0; clc.downloadCURL = qcurl_easy_init(); if(!clc.downloadCURL) { Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_easy_init() " "failed\n"); return; } clc.download = FS_SV_FOpenFileWrite(clc.downloadTempName); if(!clc.download) { Com_Error(ERR_DROP, "CL_cURL_BeginDownload: failed to open " "%s for writing\n", clc.downloadTempName); return; } qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, clc.download); if(com_developer->integer) qcurl_easy_setopt(clc.downloadCURL, CURLOPT_VERBOSE, 1); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_REFERER, va("ioQ3://%s", NET_AdrToString(clc.serverAddress))); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", Q3_VERSION, qcurl_version())); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEFUNCTION, CL_cURL_CallbackWrite); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, CL_cURL_CallbackProgress); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FAILONERROR, 1); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); clc.downloadCURLM = qcurl_multi_init(); if(!clc.downloadCURLM) { qcurl_easy_cleanup(clc.downloadCURL); clc.downloadCURL = NULL; Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_multi_init() " "failed\n"); return; } qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL); if(!(clc.sv_allowDownload & DLF_NO_DISCONNECT) && !clc.cURLDisconnected) { CL_AddReliableCommand("disconnect", qtrue); CL_WritePacket(); CL_WritePacket(); CL_WritePacket(); clc.cURLDisconnected = qtrue; } }
void R_RemapDeluxeImages( world_t *world ) { int i; if( !tr.deluxemaps[0] ) return; R_InitConverter(); R_StateSetActiveTmuUntracked( GL_TEXTURE0 ); R_StateSetActiveClientTmuUntracked( GL_TEXTURE0 ); glPushAttrib( GL_ALL_ATTRIB_BITS ); glPushClientAttrib( GL_CLIENT_ALL_ATTRIB_BITS ); glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glEnableVertexAttribArrayARB( 6 ); glEnableVertexAttribArrayARB( 7 ); glClearColor( 0, 0, 0, 0 ); glDisable( GL_DEPTH_TEST ); glDisable( GL_STENCIL_TEST ); glDisable( GL_ALPHA_TEST ); glDisable( GL_BLEND ); glDisable( GL_CULL_FACE ); glDisable( GL_MULTISAMPLE ); glEnable( GL_POLYGON_SMOOTH ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glEnable( GL_VERTEX_PROGRAM_ARB ); glBindProgramARB( GL_VERTEX_PROGRAM_ARB, conv.vp ); glEnable( GL_FRAGMENT_PROGRAM_ARB ); glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, conv.fp ); glEnable( GL_TEXTURE_2D ); for( i = 0; i < tr.numLightmaps; i++ ) { int j, y; unsigned *buf0, *buf1; image_t *img = tr.deluxemaps[i]; glBindTexture( GL_TEXTURE_2D, img->texnum ); glClear( GL_COLOR_BUFFER_BIT ); glViewport( 0, img->uploadHeight, img->uploadWidth, img->uploadHeight ); glDisable( GL_VERTEX_PROGRAM_ARB ); glDisable( GL_FRAGMENT_PROGRAM_ARB ); glBegin( GL_QUADS ); { glTexCoord2f( 0, 0 ); glVertex2f( -1, -1 ); glTexCoord2f( 0, 1 ); glVertex2f( -1, 1 ); glTexCoord2f( 1, 1 ); glVertex2f( 1, 1 ); glTexCoord2f( 1, 0 ); glVertex2f( 1, -1 ); } glEnd(); glEnable( GL_VERTEX_PROGRAM_ARB ); glEnable( GL_FRAGMENT_PROGRAM_ARB ); glViewport( 0, 0, img->uploadWidth, img->uploadHeight ); glProgramLocalParameter4fARB( GL_VERTEX_PROGRAM_ARB, 0, img->uploadWidth, img->uploadHeight, 1.0F / img->uploadWidth, 1.0F / img->uploadHeight ); for( j = 0; j < world->numsurfaces; j++ ) { const msurface_t *srf = world->surfaces + j; const shader_t *shader = srf->shader; const msurface_ex_t *exsrf = srf->redirect; if( !shader->stages[0] || !shader->stages[0]->active ) continue; if( shader->stages[0]->deluxeMap != img ) continue; if( !exsrf ) continue; glVertexPointer( 2, GL_FLOAT, sizeof( drawVert_ex_t ), &exsrf->verts[0].uvL ); glNormalPointer( GL_FLOAT, sizeof( drawVert_ex_t ), &exsrf->verts[0].norm ); glVertexAttribPointerARB( 6, 3, GL_FLOAT, GL_FALSE, sizeof( drawVert_ex_t ), &exsrf->verts[0].tan ); glVertexAttribPointerARB( 7, 3, GL_FLOAT, GL_FALSE, sizeof( drawVert_ex_t ), &exsrf->verts[0].bin ); glDrawElements( exsrf->primType, exsrf->numIndices, GL_UNSIGNED_SHORT, exsrf->indices ); } glFinish(); buf0 = (unsigned*)ri.Hunk_AllocateTempMemory( img->uploadWidth * img->uploadHeight * 4 ); buf1 = (unsigned*)ri.Hunk_AllocateTempMemory( img->uploadWidth * img->uploadHeight * 4 ); //can't just copy to the texture since we //need the custom mipmap generator glReadPixels( 0, 0, img->uploadWidth, img->uploadHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf0 ); #define DELUXEL( buf, x, y ) ((byte*)(buf) + (((y) * img->uploadWidth + (x)) * 4)) Com_Memcpy( buf1, buf0, img->uploadWidth * img->uploadHeight * 4 ); for( j = 0; j < 4; j++ ) { for( y = 0; y < img->uploadHeight; y++ ) { int x; for( x = 0; x < img->uploadWidth; x++ ) { static int neighbors[8][2] = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } }; int i; int sum[3], c; byte *cIn = DELUXEL( buf0, x, y ); byte *cOut = DELUXEL( buf1, x, y ); cOut[3] = cIn[3]; if( cIn[2] ) { //if it has some Z value //then it's already good cOut[0] = cIn[0]; cOut[1] = cIn[1]; cOut[2] = cIn[2]; continue; } c = 0; sum[0] = sum[1] = sum[2] = 0; for( i = 0; i < lengthof( neighbors ); i++ ) { int nx = x + neighbors[i][0]; int ny = y + neighbors[i][1]; if( nx >= 0 && nx < img->uploadWidth && ny >= 0 && ny < img->uploadHeight ) { byte *n = DELUXEL( buf0, nx, ny ); if( !n[2] ) continue; sum[0] += n[0]; sum[1] += n[1]; sum[2] += n[2]; c++; } } if( c ) { cOut[0] = sum[0] / c; cOut[1] = sum[1] / c; cOut[2] = sum[2] / c; } } } Com_Memcpy( buf0, buf1, img->uploadWidth * img->uploadHeight * 4 ); } for( y = 0; y < img->uploadHeight; y++ ) { int x; for( x = 0; x < img->uploadWidth; x++ ) { byte *d = DELUXEL( buf1, x, y ); if( !d[2] ) { d[0] = 0; d[1] = 0; d[2] = 0xFF; } } } //write it out to file { int size; char path[MAX_QPATH]; byte *out_buf; Com_sprintf( path, sizeof( path ), "deluxe/%s/dm_%04d.tga", world->baseName, i ); size = 18 + img->uploadWidth * img->uploadHeight * 3; out_buf = (byte*)ri.Hunk_AllocateTempMemory( size ); Com_Memset( out_buf, 0, 18 ); out_buf[2] = 2; // uncompressed type out_buf[12] = img->uploadWidth & 255; out_buf[13] = img->uploadWidth >> 8; out_buf[14] = img->uploadHeight & 255; out_buf[15] = img->uploadHeight >> 8; out_buf[16] = 24; // pixel size out_buf[17] = 0x20; // reverse row order for( y = 0; y < img->uploadHeight; y++ ) { int x; for( x = 0; x < img->uploadWidth; x++ ) { byte *d = DELUXEL( buf1, x, y ); out_buf[18 + (y * img->uploadWidth + x) * 3 + 0] = d[2]; out_buf[18 + (y * img->uploadWidth + x) * 3 + 1] = d[1]; out_buf[18 + (y * img->uploadWidth + x) * 3 + 2] = d[0]; } } ri.FS_WriteFile( path, out_buf, size ); ri.Hunk_FreeTempMemory( out_buf ); } #undef DELUXEL Upload32( buf1, qfalse, img, ILF_VECTOR_SB3 ); #ifdef _DEBUG glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, img->texnum ); glViewport( img->uploadWidth, 0, img->uploadWidth, img->uploadHeight ); glDisable( GL_VERTEX_PROGRAM_ARB ); glDisable( GL_FRAGMENT_PROGRAM_ARB ); glBegin( GL_QUADS ); { glTexCoord2f( 0, 0 ); glVertex2f( -1, -1 ); glTexCoord2f( 0, 1 ); glVertex2f( -1, 1 ); glTexCoord2f( 1, 1 ); glVertex2f( 1, 1 ); glTexCoord2f( 1, 0 ); glVertex2f( 1, -1 ); } glEnd(); glEnable( GL_VERTEX_PROGRAM_ARB ); glEnable( GL_FRAGMENT_PROGRAM_ARB ); GLimp_EndFrame(); #endif ri.Hunk_FreeTempMemory( buf1 ); ri.Hunk_FreeTempMemory( buf0 ); } glPopClientAttrib(); glPopAttrib(); glDeleteProgramsARB( 1, &conv.vp ); glDeleteProgramsARB( 1, &conv.fp ); }