2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Stats/Stats.cpp $
15 * module for running the stats screen
18 * Revision 1.5 2002/06/09 04:41:27 relnev
19 * added copyright header
21 * Revision 1.4 2002/06/02 04:26:34 relnev
24 * Revision 1.3 2002/05/26 20:22:48 theoddone33
25 * Most of network/ works
27 * Revision 1.2 2002/05/04 04:36:56 theoddone33
28 * More changes, took out a lot of the sound stuff which will bite later but
31 * Revision 1.1.1.1 2002/05/03 03:28:10 root
35 * 5 10/15/99 3:56p Jefff
36 * lifetime score to alltime stats printout (multi debrief screen)
38 * 4 10/15/99 3:01p Jefff
39 * mission score shows up in multiplayer debrief
41 * 3 3/19/99 9:51a Dave
42 * Checkin to repair massive source safe crash. Also added support for
43 * pof-style nebulae, and some new weapons code.
45 * 3 3/15/99 10:30a Neilk
48 * 2 10/07/98 10:54a Dave
51 * 1 10/07/98 10:51a Dave
53 * 38 6/09/98 10:31a Hoffoss
54 * Created index numbers for all xstr() references. Any new xstr() stuff
55 * added from here on out should be added to the end if the list. The
56 * current list count can be found in FreeSpace.cpp (search for
59 * 37 5/18/98 5:25p Chad
60 * Removed old-ass stats display code.
62 * 36 5/18/98 12:52a Allender
63 * make initialization of multiplayer stats initialize all players, not
64 * just connected players (fixed ingame join stats problems)
66 * 35 5/15/98 4:12p Allender
67 * removed redbook code. Put back in ingame join timer. Major fixups for
68 * stats in multiplayer. Pass correct score, medals, etc when leaving
69 * game. Be sure clients display medals, badges, etc.
71 * 34 5/07/98 12:57a Dave
72 * Fixed incorrect calls to free() from stats code. Put in new artwork for
73 * debrief and host options screens. Another modification to scoring
74 * system for secondary weapons.
76 * 33 4/21/98 11:56p Dave
77 * Put in player deaths statskeeping. Use arrow keys in the ingame join
78 * ship select screen. Don't quit the game if in the debriefing and server
81 * 32 4/09/98 10:31a Dave
82 * Don't display player deaths statistic under single player (doesn't make
85 * 31 3/31/98 5:18p John
86 * Removed demo/save/restore. Made NDEBUG defined compile. Removed a
87 * bunch of debug stuff out of player file. Made model code be able to
88 * unload models and malloc out only however many models are needed.
91 * 30 3/27/98 3:59p Hoffoss
92 * Due to everyone using different assumptions about what a length define
93 * means, changed code to account for safest assumption.
95 * 29 3/17/98 12:29a Dave
96 * Put in hud support for rtvoice. Several ui interface changes.
98 * 28 3/15/98 4:17p Dave
99 * Fixed oberver hud problems. Put in handy netplayer macros. Reduced size
100 * of network orientation matrices.
102 * 27 2/22/98 2:48p John
103 * More String Externalization Classification
105 * 26 2/12/98 5:00p Lawrance
106 * underline kills in the stats section
108 * 25 1/06/98 5:08p Dave
109 * Put in stats display change to show alltime+mission stats during
110 * debriefing. Fixed a object update sequencing bug.
112 * 24 12/10/97 4:45p Dave
113 * Added in more detailed support for multiplayer packet lag/loss. Fixed
114 * some multiplayer stuff. Added some controls to the standalone.
116 * 23 11/06/97 9:53a Dave
118 * 22 10/25/97 7:23p Dave
119 * Moved back to single set stats storing. Put in better respawning
122 * 21 10/24/97 6:19p Dave
123 * More standalone testing/fixing. Added reliable endgame sequencing.
124 * Added reliable ingame joining. Added reliable stats transfer (endgame).
125 * Added support for dropping players in debriefing. Removed a lot of old
128 * 20 10/23/97 7:44p Hoffoss
129 * Added 2 defines to replace hard-coded values in the code.
131 * 19 10/21/97 5:21p Dave
132 * Fixed pregame mission load/file verify debacle. Added single vs.
133 * multiplayer stats system.
135 * 18 10/14/97 5:37p Dave
136 * Fixed a memory allocation bug
138 * 17 10/08/97 4:47p Dave
139 * Fixed bugs turned up in testing. Added some brief comments.
141 * 16 9/30/97 8:48p Lawrance
142 * generalize some functions for displaying stats info
144 * 15 9/24/97 5:03p Dave
145 * Beginning changes on how kills/assists are evaluated in both single and
148 * 14 9/18/97 10:14p Dave
149 * Updated the scoring system struct. Added rank.tbl. Modified how medal
150 * names are displayed.
152 * 13 9/17/97 5:12p John
153 * Restructured collision routines. Probably broke a lot of stuff.
155 * 12 9/09/97 4:31p Dave
156 * Put in multiplayer post-game stats stuff.
158 * 11 8/26/97 4:59p Dave
159 * Changed display from bonehead hits to friendly hits.
161 * 10 8/23/97 11:31a Dave
162 * Changed the definition of bonehead hit %
164 * 9 8/20/97 12:31p Dave
165 * Added a death count for auto ressurected players.
166 * Made it easier to reorganize the stats page
168 * 8 8/19/97 5:14p Dave
169 * Added a sucker check. :)
171 * 7 8/15/97 2:20p Allender
172 * fix stats code to properly get connected players
174 * 6 8/15/97 9:28a Dave
175 * Fixed minor bug in multiplayer stats init.
177 * 5 8/14/97 5:20p Dave
178 * Made initialization/clearing of players stats more thorough.
180 * 4 7/25/97 5:23p Dave
181 * Made text displayed in antialiased font.
183 * 3 7/25/97 4:33p Dave
184 * Spiffed up statistics screen considerably. Currently reports all
185 * statistics in the game (except mission/campaign related scores)
187 * 2 7/24/97 2:31p Dave
188 * Added basic screen, no interaction yet.
190 * 1 7/24/97 1:50p Dave
195 #include "freespace.h"
196 #include "gamesequence.h"
207 // static UI_WINDOW Player_stats_window;
209 player *Active_player;
211 void show_stats_init()
213 // Player_stats_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
215 if (Game_mode & GM_MULTIPLAYER) {
216 set_player_stats(MY_NET_PLAYER_NUM);
218 Active_player = Player;
222 // write out the label for each stat
223 void show_stats_label(int stage, int sx, int sy, int dy)
227 gr_printf(sx,sy,XSTR( "Mission Stats", 114));
229 gr_printf(sx,sy,XSTR( "Total kills", 115));
231 gr_printf(sx,sy,XSTR( "Primary weapon shots", 116));
233 gr_printf(sx,sy,XSTR( "Primary weapon hits", 117));
235 gr_printf(sx,sy,XSTR( "Primary friendly hits", 118));
237 gr_printf(sx,sy,XSTR( "Primary hit %%", 119));
239 gr_printf(sx,sy,XSTR( "Primary friendly hit %%", 120));
242 gr_printf(sx,sy,XSTR( "Secondary weapon shots", 121));
244 gr_printf(sx,sy,XSTR( "Secondary weapon hits", 122));
246 gr_printf(sx,sy,XSTR( "Secondary friendly hits", 123));
248 gr_printf(sx,sy,XSTR( "Secondary hit %%", 124));
250 gr_printf(sx,sy,XSTR( "Secondary friendly hit %%", 125));
253 gr_printf(sx,sy,XSTR( "Assists", 126));
256 if(Game_mode & GM_MULTIPLAYER){
257 gr_printf(sx,sy,XSTR( "Player Deaths", 127));
260 gr_printf(sx,sy,XSTR( "Mission score", 1526));
267 gr_printf(sx,sy,XSTR( "All Time Stats", 128));
269 gr_printf(sx,sy,XSTR( "Total kills", 115));
271 gr_printf(sx,sy,XSTR( "Primary weapon shots", 116));
273 gr_printf(sx,sy,XSTR( "Primary weapon hits", 117));
275 gr_printf(sx,sy,XSTR( "Primary friendly hits", 118));
277 gr_printf(sx,sy,XSTR( "Primary hit %%", 119));
279 gr_printf(sx,sy,XSTR( "Primary friendly hit %%", 120));
282 gr_printf(sx,sy,XSTR( "Secondary weapon shots", 121));
284 gr_printf(sx,sy,XSTR( "Secondary weapon hits", 122));
286 gr_printf(sx,sy,XSTR( "Secondary friendly hits", 123));
288 gr_printf(sx,sy,XSTR( "Secondary hit %%", 124));
290 gr_printf(sx,sy,XSTR( "Secondary friendly hit %%", 125));
293 gr_printf(sx,sy,XSTR( "Assists", 126));
296 if(Game_mode & GM_MULTIPLAYER){
297 gr_printf(sx,sy,XSTR( "Score", 1527));
303 void stats_underline_text(int sx, int sy, char *text)
307 gr_get_string_size(&w,&h,text);
308 fh=gr_get_font_height();
309 gr_line(sx-1, sy+fh, sx+w+1, sy+fh);
312 void show_stats_numbers(int stage, int sx, int sy, int dy,int add_mission)
320 // mission kills stats
321 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.m_kill_count_ok);
322 gr_printf(sx,sy,text);
323 // stats_underline_text(sx,sy,text);
325 // mission primary weapon stats
326 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.mp_shots_fired);
327 gr_printf(sx,sy,text);
329 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.mp_shots_hit);
330 gr_printf(sx,sy,text);
332 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.mp_bonehead_hits);
333 gr_printf(sx,sy,text);
335 if(Active_player->stats.mp_shots_fired>0)
336 pct=(float)100.0*((float)Active_player->stats.mp_shots_hit/(float)Active_player->stats.mp_shots_fired);
338 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)pct); SDL_strlcat(text," %%", SDL_arraysize(text));
339 gr_printf(sx,sy,text);
341 if(Active_player->stats.mp_bonehead_hits>0)
342 pct=(float)100.0*((float)Active_player->stats.mp_bonehead_hits/(float)Active_player->stats.mp_shots_fired);
344 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)pct); SDL_strlcat(text," %%", SDL_arraysize(text));
345 gr_printf(sx,sy,text);
348 // mission secondary weapon stats
349 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.ms_shots_fired);
350 gr_printf(sx,sy,text);
352 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.ms_shots_hit);
353 gr_printf(sx,sy,text);
355 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.ms_bonehead_hits);
356 gr_printf(sx,sy,text);
358 if(Active_player->stats.ms_shots_fired>0)
359 pct=(float)100.0*((float)Active_player->stats.ms_shots_hit/(float)Active_player->stats.ms_shots_fired);
361 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)pct); SDL_strlcat(text," %%", SDL_arraysize(text));
362 gr_printf(sx,sy,text);
364 if(Active_player->stats.ms_bonehead_hits>0)
365 pct=(float)100.0*((float)Active_player->stats.ms_bonehead_hits/(float)Active_player->stats.ms_shots_fired);
367 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)pct); SDL_strlcat(text," %%", SDL_arraysize(text));
368 gr_printf(sx,sy,text);
371 // mission assists and player rescues (respawns)
372 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)Active_player->stats.m_assists);
373 gr_printf(sx,sy,text);
376 if(Game_mode & GM_MULTIPLAYER){
377 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)Active_player->stats.m_player_deaths);
378 gr_printf(sx,sy,text);
382 gr_printf(sx, sy, "%d", (int)Active_player->stats.m_score);
391 // if we are passed mission_add (the stats for the current mission), copy it to "add", otherwise,
393 memset(&add,0,sizeof(scoring_struct));
395 add.kill_count_ok = Active_player->stats.m_kill_count_ok;
396 add.p_shots_fired = Active_player->stats.mp_shots_fired;
397 add.p_shots_hit = Active_player->stats.mp_shots_hit;
398 add.p_bonehead_hits = Active_player->stats.mp_bonehead_hits;
400 add.s_shots_fired = Active_player->stats.ms_shots_fired;
401 add.s_shots_hit = Active_player->stats.ms_shots_hit;
402 add.s_bonehead_hits = Active_player->stats.ms_bonehead_hits;
405 // mission kills stats
406 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.kill_count_ok + add.kill_count_ok);
407 hud_num_make_mono(text);
408 gr_printf(sx,sy,text);
409 // stats_underline_text(sx,sy,text);
411 // alltime primary weapon stats
412 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.p_shots_fired + add.p_shots_fired);
413 gr_printf(sx,sy,text);
415 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.p_shots_hit + add.p_shots_hit);
416 gr_printf(sx,sy,text);
418 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.p_bonehead_hits + add.p_bonehead_hits);
419 gr_printf(sx,sy,text);
421 if((Active_player->stats.p_shots_fired + add.p_shots_fired)>0)
422 pct=(float)100.0*((float)(Active_player->stats.p_shots_hit+add.p_shots_hit)/(float)(Active_player->stats.p_shots_fired + add.p_shots_fired));
424 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)pct); SDL_strlcat(text," %%", SDL_arraysize(text));
425 gr_printf(sx,sy,text);
427 if((Active_player->stats.p_bonehead_hits + add.p_bonehead_hits)>0)
428 pct=(float)100.0*((float)(Active_player->stats.p_bonehead_hits+add.p_bonehead_hits)/(float)(Active_player->stats.p_shots_fired + add.p_shots_fired));
430 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)pct); SDL_strlcat(text," %%", SDL_arraysize(text));
431 gr_printf(sx,sy,text);
434 // alltime secondary weapon stats
435 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.s_shots_fired + add.s_shots_fired);
436 gr_printf(sx,sy,text);
438 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.s_shots_hit + add.s_shots_hit);
439 gr_printf(sx,sy,text);
441 SDL_snprintf(text,SDL_arraysize(text),"%d",Active_player->stats.s_bonehead_hits + add.s_bonehead_hits);
442 gr_printf(sx,sy,text);
444 if((Active_player->stats.s_shots_fired+add.s_shots_fired)>0)
445 pct=(float)100.0*((float)(Active_player->stats.s_shots_hit + add.s_shots_hit)/(float)(Active_player->stats.s_shots_fired + add.s_shots_fired));
447 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)pct); SDL_strlcat(text," %%", SDL_arraysize(text));
448 gr_printf(sx,sy,text);
450 if((Active_player->stats.s_bonehead_hits + add.s_bonehead_hits)>0)
451 pct=(float)100.0*((float)(Active_player->stats.s_bonehead_hits+add.s_bonehead_hits)/(float)(Active_player->stats.s_shots_fired+add.s_shots_fired));
453 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)pct); SDL_strlcat(text," %%", SDL_arraysize(text));
454 gr_printf(sx,sy,text);
458 SDL_snprintf(text,SDL_arraysize(text),"%d",(int)Active_player->stats.assists + add.assists);
459 gr_printf(sx,sy,text);
462 if (Game_mode & GM_MULTIPLAYER) {
463 gr_printf(sx, sy, "%d", (int)Active_player->stats.score);
469 int find_netplayer_n(int n)
475 for(idx=0;idx<MAX_PLAYERS;idx++){
476 if(MULTI_CONNECTED(Net_players[idx])){
487 void show_stats_close()
491 // initialize the statistics portion of the player structure for multiplayer. Only the host of
492 // a netgame needs to be doing this (and if fact, only he *should* be doing this)
493 void init_multiplayer_stats( )
497 for (int idx=0; idx < MAX_PLAYERS; idx++) {
498 ptr = &Players[idx].stats;
499 scoring_level_init( ptr );
503 void set_player_stats(int pid)
505 Active_player = Net_players[pid].player;