Index: code/mission/missionbriefcommon.cpp
===================================================================
--- code/mission/missionbriefcommon.cpp	(revision 10840)
+++ code/mission/missionbriefcommon.cpp	(working copy)
@@ -136,6 +136,8 @@
 
 const char BRIEF_META_CHAR = '$';
 
+const int HIGHEST_COLOR_STACK_INDEX = 9;
+
 // camera related
 static vec3d	Current_cam_pos;		// current camera position
 static vec3d	Target_cam_pos;		// desired camera position
@@ -186,28 +188,6 @@
 typedef SCP_vector<briefing_line> briefing_stream; 
 static briefing_stream Colored_stream[MAX_TEXT_STREAMS];
 
-#define MAX_BRIEF_TEXT_COLORS		20
-#define BRIEF_TEXT_WHITE			0
-#define BRIEF_TEXT_BRIGHT_WHITE		1
-#define BRIEF_TEXT_RED				2
-#define BRIEF_TEXT_GREEN			3
-#define BRIEF_TEXT_YELLOW			4
-#define BRIEF_TEXT_BLUE				5
-#define BRIEF_TEXT_FRIENDLY			6
-#define BRIEF_TEXT_HOSTILE			7
-#define BRIEF_TEXT_NEUTRAL			8
-#define BRIEF_TEXT_BRIGHT_BLUE		9
-#define BRIEF_TEXT_BRIGHT_GREEN		10
-#define BRIEF_TEXT_BRIGHT_RED		11
-#define BRIEF_TEXT_BRIGHT_YELLOW	12
-#define BRIEF_TEXT_BLACK			13
-#define BRIEF_TEXT_GREY				14
-#define BRIEF_TEXT_SILVER			15
-#define BRIEF_TEXT_VIOLET_GRAY		16
-#define BRIEF_TEXT_VIOLET			17
-#define BRIEF_TEXT_PINK				18
-#define BRIEF_TEXT_LIGHT_PINK		19
-
 color Brief_color_red, Brief_color_green, Brief_color_legacy_neutral;
 
 color *Brief_text_colors[MAX_BRIEF_TEXT_COLORS] = 
@@ -242,7 +222,6 @@
 static int Voice_started_time;
 static int Voice_ended_time;
 
-const float		BRIEF_TEXT_WIPE_TIME	= 1.5f;		// time in seconds for wipe to occur
 static int		Brief_text_wipe_snd;					// sound handle of sound effect for text wipe
 static int		Play_brief_voice;
 
@@ -1556,23 +1535,19 @@
  *
  * @param src a not null pointer to a C string terminated by a /0 char.
  * @param instance index into Colored_stream where the result should be placed. Value is 0 unless multiple text streams are required.
+ * @param[in,out] default_color_stack pointer to an array containing a stack of default colors (for color spans)
+ * @param[in,out] color_stack_index pointer to the current index in the above stack
  * @return number of character of the resulting sequence.
  */
-int brief_text_colorize(char *src, int instance)
+int brief_text_colorize(char *src, int instance, ubyte default_color_stack[], int &color_stack_index)
 {
 	Assert(src);
 	Assert((0 <= instance) && (instance < (int)(sizeof(Colored_stream) / sizeof(*Colored_stream))));
 
-	// manage different default colors (don't use a SCP_ stack because eh)
-	const int HIGHEST_COLOR_STACK_INDEX = 9;
-	ubyte default_color_stack[10];
-	int color_stack_index = 0;
-
 	briefing_line dest_line;	//the resulting vector of colored character
 	ubyte active_color_index;	//the current drawing color
 
-	// start off with white
-	default_color_stack[0] = active_color_index = BRIEF_TEXT_WHITE;
+	active_color_index = default_color_stack[color_stack_index];
 
 	int src_len = strlen(src);
 	for (int i = 0; i < src_len; i++)
@@ -1644,8 +1619,10 @@
  * @param w	max width of line in pixels
  * @param instance optional parameter, used when multiple text streams are required (default value is 0)
  * @param max_lines maximum number of lines
+ * @param[in] default_color default color for this text (defaults to BRIEF_TEXT_WHITE)
+ * @param[in] append add on to the existing lines instead of replacing them (defaults to false)
  */
-int brief_color_text_init(const char* src, int w, int instance, int max_lines)
+int brief_color_text_init(const char* src, int w, int instance, int max_lines, const ubyte default_color, const bool append)
 {
 	int i, n_lines, len;
 	SCP_vector<int> n_chars;
@@ -1652,6 +1629,13 @@
 	SCP_vector<const char*> p_str;
 	char brief_line[MAX_BRIEF_LINE_LEN];
 
+	// manage different default colors (don't use a SCP_ stack because eh)
+	ubyte default_color_stack[HIGHEST_COLOR_STACK_INDEX + 1];
+	int color_stack_index = 0;
+
+	// start off with white, or whatever our default is
+	default_color_stack[0] = default_color;
+
 	Assert(src != NULL);
 	n_lines = split_str(src, w, n_chars, p_str, BRIEF_META_CHAR);
 	Assert(n_lines >= 0);
@@ -1661,14 +1645,20 @@
 		n_lines = max_lines; 
 	}
 
-	Max_briefing_line_len = 1;
-	Colored_stream[instance].clear();
+	if (!append) {
+		Max_briefing_line_len = 1;
+		Colored_stream[instance].clear();
+	} else if (n_lines == 0 && !strcmp(src, "\n")) {	// Silly hack to allow inserting blank lines for debriefings -MageKing17
+		n_lines = 1;
+		p_str.push_back(0);
+		n_chars.push_back(0);
+	}
 	for (i=0; i<n_lines; i++) {
 		Assert(n_chars[i] < MAX_BRIEF_LINE_LEN);
 		strncpy(brief_line, p_str[i], n_chars[i]);
 		brief_line[n_chars[i]] = 0;
 		drop_leading_white_space(brief_line);
-		len = brief_text_colorize(&brief_line[0], instance);
+		len = brief_text_colorize(&brief_line[0], instance, default_color_stack, color_stack_index);
 		if (len > Max_briefing_line_len)
 			Max_briefing_line_len = len;
 	}
@@ -1676,7 +1666,11 @@
 	Brief_text_wipe_time_elapsed = 0.0f;
 	Play_brief_voice = 0;
 
-	Num_brief_text_lines[instance] = n_lines;
+	if (append) {
+		Num_brief_text_lines[instance] += n_lines;
+	} else {
+		Num_brief_text_lines[instance] = n_lines;
+	}
 	return n_lines;
 }
 
Index: code/mission/missionbriefcommon.h
===================================================================
--- code/mission/missionbriefcommon.h	(revision 10840)
+++ code/mission/missionbriefcommon.h	(working copy)
@@ -72,6 +72,38 @@
 struct brief_icon;
 extern briefing_icon_info *brief_get_icon_info(brief_icon *bi);
 
+
+
+// Moving briefing color definitions out of missionbriefcommon.cpp so they can be referenced elsewhere -MageKing17
+
+enum
+{
+	BRIEF_TEXT_WHITE = 0,
+	BRIEF_TEXT_BRIGHT_WHITE,
+	BRIEF_TEXT_RED,
+	BRIEF_TEXT_GREEN,
+	BRIEF_TEXT_YELLOW,
+	BRIEF_TEXT_BLUE,
+	BRIEF_TEXT_FRIENDLY,
+	BRIEF_TEXT_HOSTILE,
+	BRIEF_TEXT_NEUTRAL,
+	BRIEF_TEXT_BRIGHT_BLUE,
+	BRIEF_TEXT_BRIGHT_GREEN,
+	BRIEF_TEXT_BRIGHT_RED,
+	BRIEF_TEXT_BRIGHT_YELLOW,
+	BRIEF_TEXT_BLACK,
+	BRIEF_TEXT_GREY,
+	BRIEF_TEXT_SILVER,
+	BRIEF_TEXT_VIOLET_GRAY,
+	BRIEF_TEXT_VIOLET,
+	BRIEF_TEXT_PINK,
+	BRIEF_TEXT_LIGHT_PINK,
+	MAX_BRIEF_TEXT_COLORS,
+};
+
+// And the same here
+const float		BRIEF_TEXT_WIPE_TIME	= 1.5f;		// time in seconds for wipe to occur
+
 // ------------------------------------------------------------------------
 // Structures to hold briefing data
 // ------------------------------------------------------------------------
@@ -303,7 +335,7 @@
 void brief_voice_unpause(int stage_num);
 
 // fancy briefing style text functions for use in other modules.
-int brief_color_text_init(const char *src, int w, int instance = 0, int max_lines = MAX_BRIEF_LINES);
+int brief_color_text_init(const char *src, int w, int instance = 0, int max_lines = MAX_BRIEF_LINES, const ubyte default_color = BRIEF_TEXT_WHITE, const bool append = false);
 int brief_render_text(int line_offset, int x, int y, int h, float frametime, int instance = 0, int line_spacing = 0);
 
 void cmd_brief_reset();
Index: code/missionui/missiondebrief.cpp
===================================================================
--- code/missionui/missiondebrief.cpp	(revision 10840)
+++ code/missionui/missiondebrief.cpp	(working copy)
@@ -61,6 +61,8 @@
 #define DEBRIEF_ALLTIME_STATS		2
 #define DEBRIEF_ALLTIME_KILLS		3
 
+extern float Brief_text_wipe_time_elapsed;
+
 // 3rd coord is max width in pixels
 int Debrief_title_coords[GR_NUM_RESOLUTIONS][3] = {
 	{ // GR_640
@@ -326,10 +328,6 @@
 static int Award_active;
 static int Text_offset;
 static int Num_text_lines = 0;
-static int Num_debrief_lines = 0;
-//static int Num_normal_debrief_lines = 0;
-static int Text_type[MAX_TOTAL_DEBRIEF_LINES];
-static char *Text[MAX_TOTAL_DEBRIEF_LINES];
 
 static int Debrief_inited = 0;
 static int New_stage;
@@ -1515,38 +1513,6 @@
 	gr_string(Debrief_text_x2[gr_screen.res], y_loc, time_str, GR_RESIZE_MENU);	
 }
 
-// render out the debriefing text to the scroll window
-void debrief_render()
-{
-	int y, z, font_height;
-
-	if ( Num_stages <= 0 )
-		return;
-
-	font_height = gr_get_font_height();
-
-	gr_set_clip(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], Debrief_text_wnd_coords[gr_screen.res][2], Debrief_text_wnd_coords[gr_screen.res][3], GR_RESIZE_MENU);
-	y = 0;
-	z = Text_offset;
-	while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
-		if (z >= Num_text_lines)
-			break;
-
-		if (Text_type[z] == TEXT_TYPE_NORMAL)
-			gr_set_color_fast(&Color_white);
-		else
-			gr_set_color_fast(&Color_bright_red);
-
-		if (Text[z])
-			gr_string(0, y, Text[z], GR_RESIZE_MENU);
-
-		y += font_height;
-		z++;
-	}
-
-	gr_reset_clip();
-}
-
 // render out the stats info to the scroll window
 //
 void debrief_stats_render()
@@ -1856,44 +1822,6 @@
 	*/
 }
 
-void debrief_text_stage_init(const char *src, int type)
-{
-	int i, n_lines, n_chars[MAX_DEBRIEF_LINES];
-	char line[MAX_DEBRIEF_LINE_LEN];
-	const char *p_str[MAX_DEBRIEF_LINES];
-
-	n_lines = split_str(src, Debrief_text_wnd_coords[gr_screen.res][2], n_chars, p_str, MAX_DEBRIEF_LINES);
-	Assert(n_lines >= 0);
-
-	// if you hit this, you proba	
-	if(n_lines >= MAX_DEBRIEF_LINES){
-		Warning(LOCATION, "You have come close to the limit of debriefing lines, try adding more stages");	
-	}
-
-	for ( i=0; i<n_lines; i++ ) {
-		Assert(n_chars[i] < MAX_DEBRIEF_LINE_LEN);
-		Assert(Num_text_lines < MAX_TOTAL_DEBRIEF_LINES);
-		strncpy(line, p_str[i], n_chars[i]);
-		line[n_chars[i]] = 0;
-		drop_white_space(line);
-		Text_type[Num_text_lines] = type;
-		Text[Num_text_lines++] = vm_strdup(line);
-	}
-
-	return;
-}
-
-void debrief_free_text()
-{
-	int i;
-
-	for (i=0; i<Num_debrief_lines; i++)
-		if (Text[i])
-			vm_free(Text[i]);
-
-	Num_debrief_lines = 0;
-}
-
 // setup the debriefing text lines for rendering
 void debrief_text_init()
 {
@@ -1910,9 +1838,7 @@
 		}
 	}
 
-	// release old text lines first
-	debrief_free_text();
-	Num_text_lines = Text_offset = 0;
+	Num_text_lines = Text_offset = brief_color_text_init("", Debrief_text_wnd_coords[gr_screen.res][2], 0, 0);	// Initialize color stuff -MageKing17
 
 	fsspeech_start_buffer();
 
@@ -1919,12 +1845,13 @@
 	if (Current_mode == DEBRIEF_TAB) {
 		for (i=0; i<Num_debrief_stages; i++) {
 			if (i)
-				Text[Num_text_lines++] = NULL;  // add a blank line between stages
+				// add a blank line between stages
+				Num_text_lines += brief_color_text_init("\n", Debrief_text_wnd_coords[gr_screen.res][2], 0, MAX_DEBRIEF_LINES, BRIEF_TEXT_WHITE, true);
 
 			src = Debrief_stages[i]->text.c_str();
 
 			if (*src) {
-				debrief_text_stage_init(src, TEXT_TYPE_NORMAL);
+				Num_text_lines += brief_color_text_init(src, Debrief_text_wnd_coords[gr_screen.res][2], 0, MAX_DEBRIEF_LINES, BRIEF_TEXT_WHITE, true);
 
 				if (use_sim_speech && !Recommend_active) {
 					fsspeech_stuff_buffer(src);
@@ -1939,8 +1866,9 @@
 					src = XSTR( "We have no recommendations for you.", 1054);
 
 				if (*src) {
-					Text[Num_text_lines++] = NULL;
-					debrief_text_stage_init(src, TEXT_TYPE_RECOMMENDATION);
+					Num_text_lines += brief_color_text_init("\n", Debrief_text_wnd_coords[gr_screen.res][2], 0, MAX_DEBRIEF_LINES, BRIEF_TEXT_RED, true);
+
+					Num_text_lines += brief_color_text_init(src, Debrief_text_wnd_coords[gr_screen.res][2], 0, MAX_DEBRIEF_LINES, BRIEF_TEXT_RED, true);
 					r_count++;
 
 					if (use_sim_speech) {
@@ -1950,8 +1878,8 @@
 				}
 			}
 		}
+		Brief_text_wipe_time_elapsed = BRIEF_TEXT_WIPE_TIME;	// Skip the wipe effect
 
-		Num_debrief_lines = Num_text_lines;
 		if(use_sim_speech) {
 			fsspeech_play_buffer(FSSPEECH_FROM_BRIEFING);
 		}
@@ -2027,7 +1955,7 @@
 	Current_stage = -1;
 	New_stage = 0;
 	Debrief_cue_voice = 0;
-	Num_text_lines = Num_debrief_lines = 0;
+	Num_text_lines = 0;
 	Debrief_first_voice_flag = 1;
 
 	Debrief_multi_voice_loaded = 0;
@@ -2092,6 +2020,9 @@
 	}
 	*/
 
+	// Just calculate this once instead of every frame. -MageKing17
+	Max_debrief_Lines = Debrief_text_wnd_coords[gr_screen.res][3]/gr_get_font_height(); //Make the max number of lines dependent on the font height.
+
 	// start up the appropriate music
 	debrief_init_music();
 
@@ -2171,14 +2102,6 @@
 		Player->show_skip_popup = 1;
 	}
 
-	if (Num_debrief_lines) {
-		for (i=0; i<Num_debrief_lines; i++){
-			if (Text[i]){
-				vm_free(Text[i]);
-			}
-		}
-	}
-
 	// clear out debrief info parsed from mission file - taylor
 	mission_debrief_common_reset();
 
@@ -2556,7 +2479,7 @@
 				gr_printf_menu(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], XSTR( "No Debriefing for mission: %s", 458), Game_current_mission_filename);
 
 			} else {
-				debrief_render();
+				brief_render_text(Text_offset, Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], Debrief_text_wnd_coords[gr_screen.res][3], frametime);
 			}
 
 			break;
@@ -2566,8 +2489,6 @@
 			break;
 	} // end switch
 
-	Max_debrief_Lines = Debrief_text_wnd_coords[gr_screen.res][3]/gr_get_font_height(); //Make the max number of lines dependent on the font height.
-
 	if ( (Max_debrief_Lines + Text_offset) < Num_text_lines ) {
 		int w;
 
