/* ================== SCR_DrawSmallString[Color] Draws a multi-colored string with a drop shadow, optionally forcing to a fixed color. Coordinates are at 640 by 480 virtual resolution ================== */ void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor, qboolean noColorEscape ) { vec4_t color; const char *s; int xx; // draw the colored text s = string; xx = x; re->SetColor( setColor ); while ( *s ) { int colorLen = Q_parseColorString( s, color ); if ( colorLen ) { if ( !forceColor ) { color[3] = setColor[3]; re->SetColor( color ); } if ( !noColorEscape ) { s += colorLen; continue; } } SCR_DrawSmallChar( xx, y, *s ); xx += SMALLCHAR_WIDTH; s++; } re->SetColor( NULL ); }
/* ================== SCR_DrawBigString[Color] Draws a multi-colored string with a drop shadow, optionally forcing to a fixed color. Coordinates are at 640 by 480 virtual resolution ================== */ void SCR_DrawStringExt( int x, int y, float size, const char *string, float *setColor, qboolean forceColor, qboolean noColorEscape ) { vec4_t color; const char *s; int xx; // draw the drop shadow color[0] = color[1] = color[2] = 0; color[3] = setColor[3]; re->SetColor( color ); s = string; xx = x; while ( *s ) { int colorLen = Q_parseColorString( s, nullptr ); if ( !noColorEscape && colorLen ) { s += colorLen; continue; } SCR_DrawChar( xx+2, y+2, size, *s ); xx += size; s++; } // draw the colored text s = string; xx = x; re->SetColor( setColor ); while ( *s ) { int colorLen = Q_parseColorString( s, color ); if ( colorLen ) { if ( !forceColor ) { color[3] = setColor[3]; re->SetColor( color ); } if ( !noColorEscape ) { s += colorLen; continue; } } SCR_DrawChar( xx, y, size, *s ); xx += size; s++; } re->SetColor( NULL ); }
void SCR_DrawStringExt2( float x, float y, float charWidth, float charHeight, const char *string, float *setColor, qboolean forceColor, qboolean noColorEscape ) { vec4_t color; const char *s; float xx; // draw the drop shadow color[0] = color[1] = color[2] = 0; color[3] = setColor[3]; re.SetColor( color ); s = string; xx = x; while ( *s ) { int colorLen = Q_parseColorString( s, 0, cls.cTable ); if ( !noColorEscape && colorLen ) { s += colorLen; continue; } SCR_DrawChar2( xx+2*cls.ratioFix, y+2, charWidth, charHeight, *s ); xx += charWidth; s++; } // draw the colored text s = string; xx = x; re.SetColor( setColor ); while ( *s ) { int colorLen = Q_parseColorString( s, color, cls.cTable ); if ( colorLen ) { if ( !forceColor ) { color[3] = setColor[3]; re.SetColor( color ); } if ( !noColorEscape ) { s += colorLen; continue; } } SCR_DrawChar2( xx, y, charWidth, charHeight, *s ); xx += charWidth; s++; } re.SetColor( NULL ); }
/* ** SCR_Strlen -- skips color escape codes */ static int SCR_Strlen( const char *str ) { const char *s = str; int count = 0; while ( *s ) { int colorLen = Q_parseColorString( s, nullptr ); if( colorLen ) { s += colorLen; continue; } count++; s++; } return count; }
/* ** Conbuf_AppendText */ void Conbuf_AppendText( const char *pMsg ) { #define CONSOLE_BUFFER_SIZE 16384 if ( !s_wcd.hWnd ) { return; } char buffer[CONSOLE_BUFFER_SIZE*4]; char *b = buffer; const char *msg; int bufLen; int i = 0; static unsigned long s_totalChars; // // if the message is REALLY long, use just the last portion of it // if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 ) { msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1; } else { msg = pMsg; } // // copy into an intermediate buffer // while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) ) { int colorLen = Q_parseColorString( msg + i, 0, CT_DEFAULT ); if ( colorLen ) { i += colorLen; } else if ( msg[i] == '\n' && msg[i+1] == '\r' ) { b[0] = '\r'; b[1] = '\n'; b += 2; i++; } else if ( msg[i] == '\r' ) { b[0] = '\r'; b[1] = '\n'; b += 2; } else if ( msg[i] == '\n' ) { b[0] = '\r'; b[1] = '\n'; b += 2; } else { *b= msg[i]; b++; } i++; } *b = 0; bufLen = b - buffer; s_totalChars += bufLen; // // replace selection instead of appending if we're overflowing // if ( s_totalChars > 0x7fff ) { SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 ); s_totalChars = bufLen; } // // put this text into the windows console // SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff ); SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 ); SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer ); }
/* ============= CG_Obituary ============= */ static void CG_Obituary( entityState_t *ent ) { int mod; int target, attacker; char *message; char *message2; const char *targetName; const char *attackerName; gender_t gender; clientInfo_t *ci; target = ent->otherEntityNum; attacker = ent->otherEntityNum2; mod = ent->eventParm; if ( target < 0 || target >= MAX_CLIENTS ) { CG_Error( "CG_Obituary: target out of range" ); } ci = &cgs.clientinfo[target]; if ( attacker < 0 || attacker >= MAX_CLIENTS ) { attacker = ENTITYNUM_WORLD; attackerName = "noname"; } else { attackerName = cgs.clientinfo[attacker].name; } if (!cgs.clientinfo[target].infoValid) return; targetName = cgs.clientinfo[target].name; message2 = ""; // check for single client messages switch( mod ) { case MOD_SUICIDE: message = "suicides"; break; case MOD_FALLING: message = "cratered"; break; case MOD_CRUSH: message = "was squished"; break; case MOD_WATER: message = "sank like a rock"; break; case MOD_SLIME: message = "melted"; break; case MOD_LAVA: message = "does a back flip into the lava"; break; case MOD_TARGET_LASER: message = "saw the light"; break; case MOD_TRIGGER_HURT: message = "was in the wrong place"; break; default: message = NULL; break; } if (attacker == target) { gender = ci->gender; switch (mod) { #ifdef MISSIONPACK case MOD_KAMIKAZE: message = "goes out with a bang"; break; #endif case MOD_GRENADE_SPLASH: if ( gender == GENDER_FEMALE ) message = "tripped on her own grenade"; else if ( gender == GENDER_NEUTER ) message = "tripped on its own grenade"; else message = "tripped on his own grenade"; break; case MOD_ROCKET_SPLASH: if ( gender == GENDER_FEMALE ) message = "blew herself up"; else if ( gender == GENDER_NEUTER ) message = "blew itself up"; else message = "blew himself up"; break; case MOD_PLASMA_SPLASH: if ( gender == GENDER_FEMALE ) message = "melted herself"; else if ( gender == GENDER_NEUTER ) message = "melted itself"; else message = "melted himself"; break; case MOD_BFG_SPLASH: message = "should have used a smaller gun"; break; #ifdef MISSIONPACK case MOD_PROXIMITY_MINE: if( gender == GENDER_FEMALE ) { message = "found her prox mine"; } else if ( gender == GENDER_NEUTER ) { message = "found it's prox mine"; } else { message = "found his prox mine"; } break; #endif default: if ( gender == GENDER_FEMALE ) message = "killed herself"; else if ( gender == GENDER_NEUTER ) message = "killed itself"; else message = "killed himself"; break; } } if (message) { CG_Printf( "%s %s.\n", targetName, message); return; } // check for kill messages from the current clientNum if ( cg.playerCent && attacker == cg.playerCent->currentState.clientNum ) { char *s; const char *format; qboolean haveTag = qfalse; char outBuf[512]; int outIndex = 0; int outLeft = sizeof(outBuf) - 1; char lastColor[16]; int testColor, colorLen = 0; format = mov_fragFormat.string; if (!format || !format[0]) format = "You fragged %t%"; while (*format && outLeft > 0) { if (haveTag) { char ch = *format++; haveTag = qfalse; switch (ch) { case 't': //Target Q_strncpyz( outBuf + outIndex, targetName, outLeft ); outIndex += strlen( outBuf + outIndex ); break; case 'p': //Place Q_strncpyz( outBuf + outIndex, CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ), outLeft ); outIndex += strlen( outBuf + outIndex ); break; case 'n': //NewLine outBuf[outIndex++] = '\n'; outLeft--; continue; case 'a': //Attacker if (!attackerName) break; Q_strncpyz( outBuf + outIndex, attackerName, outLeft ); outIndex += strlen( outBuf + outIndex ); break; case 's': //Score Com_sprintf( outBuf + outIndex, outLeft, "%d", cg.snap->ps.persistant[PERS_SCORE]); outIndex += strlen( outBuf + outIndex ); break; case '%': outBuf[outIndex++] = '%'; break; default: continue; } outLeft = sizeof(outBuf) - outIndex - 1; if (colorLen && (outLeft > colorLen)) { memcpy( outBuf + outIndex, lastColor, colorLen ); outLeft -= colorLen; outIndex += colorLen; } continue; } testColor = Q_parseColorString( format, 0 ); if (testColor ) { if (testColor < sizeof( lastColor)) { colorLen = testColor; memcpy( lastColor, format, colorLen ); } if (testColor < outLeft) { memcpy( outBuf + outIndex, format, testColor ); outIndex += testColor; outLeft -= testColor; } format += testColor; continue; } if (*format == '%') { haveTag = qtrue; format++; continue; } outBuf[outIndex++] = *format++; outLeft = sizeof(outBuf) - outIndex - 1; } outBuf[ outIndex ] = 0; s = outBuf; CG_CenterPrint( s ); // print the text message as well } if (!mov_Obituaries.integer) return; if ( attacker != ENTITYNUM_WORLD ) { switch (mod) { case MOD_GRAPPLE: message = "was caught by"; break; case MOD_GAUNTLET: message = "was pummeled by"; break; case MOD_MACHINEGUN: message = "was machinegunned by"; break; case MOD_SHOTGUN: message = "was gunned down by"; break; case MOD_GRENADE: message = "ate"; message2 = "'s grenade"; break; case MOD_GRENADE_SPLASH: message = "was shredded by"; message2 = "'s shrapnel"; break; case MOD_ROCKET: message = "ate"; message2 = "'s rocket"; break; case MOD_ROCKET_SPLASH: message = "almost dodged"; message2 = "'s rocket"; break; case MOD_PLASMA: message = "was melted by"; message2 = "'s plasmagun"; break; case MOD_PLASMA_SPLASH: message = "was melted by"; message2 = "'s plasmagun"; break; case MOD_RAILGUN: message = "was railed by"; break; case MOD_LIGHTNING: message = "was electrocuted by"; break; case MOD_BFG: case MOD_BFG_SPLASH: message = "was blasted by"; message2 = "'s BFG"; break; case MOD_TELEFRAG: message = "tried to invade"; message2 = "'s personal space"; break; default: message = "was killed by"; break; } if (message) { CG_Printf( "%s %s %s%s\n", targetName, message, attackerName, message2); return; } } // we don't know what it was CG_Printf( "%s died.\n", targetName ); }
/* ================ CL_ConsolePrint Handles cursor positioning, line wrapping, etc All console printing must go through this in order to be logged to disk If no console is visible, the text will appear at the top of the game window ================ */ void CL_ConsolePrint( const char *txt) { int y; int c, l; int color; qboolean skipnotify = qfalse; // NERVE - SMF int prev; // NERVE - SMF // TTimo - prefix for text that shows up in console but not in notify // backported from RTCW if ( !Q_strncmp( txt, "[skipnotify]", 12 ) ) { skipnotify = qtrue; txt += 12; } if ( txt[0] == '*' ) { skipnotify = qtrue; txt += 1; } // for some demos we don't want to ever show anything on the console if ( cl_noprint && cl_noprint->integer ) { return; } if (!con.initialized) { con.color[0] = con.color[1] = con.color[2] = con.color[3] = 1.0f; con.linewidth = -1; Con_CheckResize (); con.initialized = qtrue; } //color = ColorIndex(COLOR_WHITE); color = 0xfff00000; while ( (c = (unsigned char) *txt) != 0 ) { vec4_t newColor; int colorLen = Q_parseColorString( txt, newColor ); if ( colorLen ) { color = Q_PackRGB( newColor ); txt += colorLen; continue; } // count word length for (l=0 ; l< con.linewidth ; l++) { if ( txt[l] <= ' ') { break; } } // word wrap if (l != con.linewidth && (con.x + l >= con.linewidth) ) { Con_Linefeed(skipnotify); } txt++; switch (c) { case '\n': Con_Linefeed (skipnotify); break; case '\r': con.x = 0; break; default: // display character and advance y = con.current % con.totallines; con.text[y*con.linewidth+con.x] = color | c; con.x++; if (con.x >= con.linewidth) { Con_Linefeed(skipnotify); } break; } } // mark time for transparent overlay if (con.current >= 0 ) { // NERVE - SMF if ( skipnotify ) { prev = con.current % NUM_CON_TIMES - 1; if ( prev < 0 ) prev = NUM_CON_TIMES - 1; con.times[prev] = 0; } else // -NERVE - SMF con.times[con.current % NUM_CON_TIMES] = cls.realtime; } }