]> icculus.org git repositories - taylor/freespace2.git/blob - src/stats/stats.cpp
remove mission_load_menu
[taylor/freespace2.git] / src / stats / stats.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Stats/Stats.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * module for running the stats screen
16  *
17  * $Log$
18  * Revision 1.5  2002/06/09 04:41:27  relnev
19  * added copyright header
20  *
21  * Revision 1.4  2002/06/02 04:26:34  relnev
22  * warning cleanup
23  *
24  * Revision 1.3  2002/05/26 20:22:48  theoddone33
25  * Most of network/ works
26  *
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
29  * I don't care.
30  *
31  * Revision 1.1.1.1  2002/05/03 03:28:10  root
32  * Initial import.
33  *
34  * 
35  * 5     10/15/99 3:56p Jefff
36  * lifetime score to alltime stats printout (multi debrief screen)
37  * 
38  * 4     10/15/99 3:01p Jefff
39  * mission score shows up in multiplayer debrief
40  * 
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.
44  * 
45  * 3     3/15/99 10:30a Neilk
46  * Add hires support
47  * 
48  * 2     10/07/98 10:54a Dave
49  * Initial checkin.
50  * 
51  * 1     10/07/98 10:51a Dave
52  * 
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
57  * XSTR_SIZE).
58  * 
59  * 37    5/18/98 5:25p Chad
60  * Removed old-ass stats display code.
61  * 
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)
65  * 
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.
70  * 
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.
75  * 
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
79  * leaves.
80  * 
81  * 32    4/09/98 10:31a Dave
82  * Don't display player deaths statistic under single player (doesn't make
83  * sense).
84  * 
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.
89  *  
90  * 
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.
94  * 
95  * 29    3/17/98 12:29a Dave
96  * Put in hud support for rtvoice. Several ui interface changes.
97  * 
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.
101  * 
102  * 27    2/22/98 2:48p John
103  * More String Externalization Classification
104  * 
105  * 26    2/12/98 5:00p Lawrance
106  * underline kills in the stats section
107  * 
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.
111  * 
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.
115  * 
116  * 23    11/06/97 9:53a Dave
117  * 
118  * 22    10/25/97 7:23p Dave
119  * Moved back to single set stats storing. Put in better respawning
120  * locations system.
121  * 
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
126  * unused code.
127  * 
128  * 20    10/23/97 7:44p Hoffoss
129  * Added 2 defines to replace hard-coded values in the code.
130  * 
131  * 19    10/21/97 5:21p Dave
132  * Fixed pregame mission load/file verify debacle. Added single vs.
133  * multiplayer stats system.
134  * 
135  * 18    10/14/97 5:37p Dave
136  * Fixed a memory allocation bug
137  * 
138  * 17    10/08/97 4:47p Dave
139  * Fixed bugs turned up in testing. Added some brief comments.
140  * 
141  * 16    9/30/97 8:48p Lawrance
142  * generalize some functions for displaying stats info
143  * 
144  * 15    9/24/97 5:03p Dave
145  * Beginning changes on how kills/assists are evaluated in both single and
146  * multiplayer
147  * 
148  * 14    9/18/97 10:14p Dave
149  * Updated the scoring system struct. Added rank.tbl. Modified how medal
150  * names are displayed.
151  * 
152  * 13    9/17/97 5:12p John
153  * Restructured collision routines.  Probably broke a lot of stuff.
154  * 
155  * 12    9/09/97 4:31p Dave
156  * Put in multiplayer post-game stats stuff.
157  * 
158  * 11    8/26/97 4:59p Dave
159  * Changed display from bonehead hits to friendly hits.
160  * 
161  * 10    8/23/97 11:31a Dave
162  * Changed the definition of bonehead hit %
163  * 
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
167  * 
168  * 8     8/19/97 5:14p Dave
169  * Added a sucker check. :)
170  * 
171  * 7     8/15/97 2:20p Allender
172  * fix stats code to properly get connected players
173  * 
174  * 6     8/15/97 9:28a Dave
175  * Fixed minor bug in multiplayer stats init.
176  * 
177  * 5     8/14/97 5:20p Dave
178  * Made initialization/clearing of players stats more thorough.
179  * 
180  * 4     7/25/97 5:23p Dave
181  * Made text displayed in antialiased font.
182  * 
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)
186  * 
187  * 2     7/24/97 2:31p Dave
188  * Added basic screen, no interaction yet.
189  * 
190  * 1     7/24/97 1:50p Dave
191  * 
192  * $NoKeywords: $
193  */
194
195 #ifndef PLAT_UNIX
196 #include <io.h>
197 #include <winsock.h>
198 #endif
199 #include "freespace.h"
200 #include "gamesequence.h"
201 #include "key.h"
202 #include "2d.h"
203 #include "ui.h"
204 #include "timer.h"
205 #include "player.h"
206 #include "stats.h"
207 #include "multi.h"
208 #include "hud.h"
209 #include "font.h"
210
211 // static UI_WINDOW Player_stats_window;
212
213 player *Active_player;
214
215 void show_stats_init()
216 {
217         // Player_stats_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
218
219         if (Game_mode & GM_MULTIPLAYER) {                               
220                 set_player_stats(MY_NET_PLAYER_NUM);
221         } else {
222                 Active_player = Player;         
223         }       
224 }
225
226 // write out the label for each stat
227 void show_stats_label(int stage, int sx, int sy, int dy)
228 {
229         switch ( stage ) {
230                 case MISSION_STATS:
231                         gr_printf(sx,sy,XSTR( "Mission Stats", 114));
232                         sy += 2*dy;
233                         gr_printf(sx,sy,XSTR( "Total kills", 115));
234                         sy += 2*dy;
235                         gr_printf(sx,sy,XSTR( "Primary weapon shots", 116));
236                         sy += dy;
237                         gr_printf(sx,sy,XSTR( "Primary weapon hits", 117));
238                         sy += dy;
239                         gr_printf(sx,sy,XSTR( "Primary friendly hits", 118));
240                         sy += dy;
241                         gr_printf(sx,sy,XSTR( "Primary hit %%", 119));
242                         sy += dy;
243                         gr_printf(sx,sy,XSTR( "Primary friendly hit %%", 120));
244                         sy += 2*dy;
245
246                         gr_printf(sx,sy,XSTR( "Secondary weapon shots", 121));
247                         sy += dy;
248                         gr_printf(sx,sy,XSTR( "Secondary weapon hits", 122));
249                         sy += dy;
250                         gr_printf(sx,sy,XSTR( "Secondary friendly hits", 123));
251                         sy += dy;
252                         gr_printf(sx,sy,XSTR( "Secondary hit %%", 124));
253                         sy += dy;
254                         gr_printf(sx,sy,XSTR( "Secondary friendly hit %%", 125));
255                         sy += 2*dy;
256
257                         gr_printf(sx,sy,XSTR( "Assists", 126));
258                         sy += 2*dy;
259
260                         if(Game_mode & GM_MULTIPLAYER){
261                                 gr_printf(sx,sy,XSTR( "Player Deaths", 127));
262                                 sy += 2*dy;
263
264                                 gr_printf(sx,sy,XSTR( "Mission score", 1526));
265                         }
266
267
268                         break;
269
270                 case ALL_TIME_STATS:
271                         gr_printf(sx,sy,XSTR( "All Time Stats", 128));
272                         sy += 2*dy;                     
273                         gr_printf(sx,sy,XSTR( "Total kills", 115));
274                         sy += 2*dy;
275                         gr_printf(sx,sy,XSTR( "Primary weapon shots", 116));
276                         sy += dy;
277                         gr_printf(sx,sy,XSTR( "Primary weapon hits", 117));
278                         sy += dy;
279                         gr_printf(sx,sy,XSTR( "Primary friendly hits", 118));
280                         sy += dy;
281                         gr_printf(sx,sy,XSTR( "Primary hit %%", 119));
282                         sy += dy;
283                         gr_printf(sx,sy,XSTR( "Primary friendly hit %%", 120));
284                         sy += 2*dy;
285
286                         gr_printf(sx,sy,XSTR( "Secondary weapon shots", 121));
287                         sy += dy;
288                         gr_printf(sx,sy,XSTR( "Secondary weapon hits", 122));
289                         sy += dy;
290                         gr_printf(sx,sy,XSTR( "Secondary friendly hits", 123));
291                         sy += dy;
292                         gr_printf(sx,sy,XSTR( "Secondary hit %%", 124));
293                         sy += dy;
294                         gr_printf(sx,sy,XSTR( "Secondary friendly hit %%", 125));
295                         sy += 2*dy;                     
296
297                         gr_printf(sx,sy,XSTR( "Assists", 126));
298                         sy += 2*dy;
299
300                         if(Game_mode & GM_MULTIPLAYER){
301                                 gr_printf(sx,sy,XSTR( "Score", 1527));
302                         }
303                         break;
304                 } // end switch
305 }
306
307 void stats_underline_text(int sx, int sy, char *text)
308 {
309         int w,h,fh;
310
311         gr_get_string_size(&w,&h,text);
312         fh=gr_get_font_height();
313         gr_line(sx-1, sy+fh, sx+w+1, sy+fh);
314 }
315
316 void show_stats_numbers(int stage, int sx, int sy, int dy,int add_mission)
317 {
318    char         text[30];
319         float           pct;
320
321         sy += 2*dy;
322         switch ( stage ) {
323                 case MISSION_STATS:
324          // mission kills stats
325                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.m_kill_count_ok);
326                         gr_printf(sx,sy,text);
327                         // stats_underline_text(sx,sy,text);
328                         sy += 2*dy;
329          // mission primary weapon stats
330                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.mp_shots_fired);
331                         gr_printf(sx,sy,text);
332                         sy += dy;
333                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.mp_shots_hit);
334                         gr_printf(sx,sy,text);
335                         sy += dy;
336                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.mp_bonehead_hits);
337                         gr_printf(sx,sy,text);
338                         sy += dy;
339                         if(Active_player->stats.mp_shots_fired>0)
340                                 pct=(float)100.0*((float)Active_player->stats.mp_shots_hit/(float)Active_player->stats.mp_shots_fired);
341                         else pct=(float)0.0;
342                         SDL_snprintf(text,sizeof(text),"%d",(int)pct); SDL_strlcat(text," %%", sizeof(text));
343                         gr_printf(sx,sy,text);
344                         sy += dy;
345                         if(Active_player->stats.mp_bonehead_hits>0)
346                                 pct=(float)100.0*((float)Active_player->stats.mp_bonehead_hits/(float)Active_player->stats.mp_shots_fired);
347                         else pct=(float)0.0;
348                         SDL_snprintf(text,sizeof(text),"%d",(int)pct); SDL_strlcat(text," %%", sizeof(text));
349                         gr_printf(sx,sy,text);
350                         sy += 2*dy;
351
352                         // mission secondary weapon stats
353                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.ms_shots_fired);
354                         gr_printf(sx,sy,text);
355                         sy += dy;
356                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.ms_shots_hit);
357                         gr_printf(sx,sy,text);
358                         sy += dy;
359                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.ms_bonehead_hits);
360                         gr_printf(sx,sy,text);
361                         sy += dy;
362                         if(Active_player->stats.ms_shots_fired>0)
363                                 pct=(float)100.0*((float)Active_player->stats.ms_shots_hit/(float)Active_player->stats.ms_shots_fired);
364                         else pct=(float)0.0;
365                         SDL_snprintf(text,sizeof(text),"%d",(int)pct); SDL_strlcat(text," %%", sizeof(text));
366                         gr_printf(sx,sy,text);
367                         sy += dy;
368                         if(Active_player->stats.ms_bonehead_hits>0)
369                                 pct=(float)100.0*((float)Active_player->stats.ms_bonehead_hits/(float)Active_player->stats.ms_shots_fired);
370                         else pct=(float)0.0;
371                         SDL_snprintf(text,sizeof(text),"%d",(int)pct); SDL_strlcat(text," %%", sizeof(text));
372                         gr_printf(sx,sy,text);
373                         sy += 2*dy;
374
375                         // mission assists and player rescues (respawns)
376                         SDL_snprintf(text,sizeof(text),"%d",(int)Active_player->stats.m_assists);
377                         gr_printf(sx,sy,text);
378                         sy += 2*dy;
379
380                         if(Game_mode & GM_MULTIPLAYER){
381                                 SDL_snprintf(text,sizeof(text),"%d",(int)Active_player->stats.m_player_deaths);
382                                 gr_printf(sx,sy,text);
383                                 sy += 2*dy;
384
385                                 // mission score
386                                 gr_printf(sx, sy, "%d", (int)Active_player->stats.m_score);
387                         }
388
389
390                         break;
391
392                 case ALL_TIME_STATS:
393                          scoring_struct add;
394                         
395                         // if we are passed mission_add (the stats for the current mission), copy it to "add", otherwise,
396                         // zero it out
397                         memset(&add,0,sizeof(scoring_struct));                          
398                         if(add_mission){
399                                 add.kill_count_ok = Active_player->stats.m_kill_count_ok;
400                                 add.p_shots_fired  = Active_player->stats.mp_shots_fired;
401                                 add.p_shots_hit = Active_player->stats.mp_shots_hit;
402                                 add.p_bonehead_hits = Active_player->stats.mp_bonehead_hits;                            
403                                 
404                                 add.s_shots_fired = Active_player->stats.ms_shots_fired;
405                                 add.s_shots_hit = Active_player->stats.ms_shots_hit;
406                                 add.s_bonehead_hits = Active_player->stats.ms_bonehead_hits;                            
407                         }                       
408
409          // mission kills stats
410                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.kill_count_ok + add.kill_count_ok);
411                         hud_num_make_mono(text);
412                         gr_printf(sx,sy,text);
413                         // stats_underline_text(sx,sy,text);
414                         sy += 2*dy;
415          // alltime primary weapon stats
416                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.p_shots_fired + add.p_shots_fired);
417                         gr_printf(sx,sy,text);
418                         sy += dy;
419                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.p_shots_hit + add.p_shots_hit);
420                         gr_printf(sx,sy,text);
421                         sy += dy;
422                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.p_bonehead_hits + add.p_bonehead_hits);
423                         gr_printf(sx,sy,text);
424                         sy += dy;
425                         if((Active_player->stats.p_shots_fired + add.p_shots_fired)>0)
426                                 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));
427                         else pct=(float)0.0;
428                         SDL_snprintf(text,sizeof(text),"%d",(int)pct); SDL_strlcat(text," %%", sizeof(text));
429                         gr_printf(sx,sy,text);
430                         sy += dy;
431                         if((Active_player->stats.p_bonehead_hits + add.p_bonehead_hits)>0)
432                                 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));
433                         else pct=(float)0.0;
434                         SDL_snprintf(text,sizeof(text),"%d",(int)pct); SDL_strlcat(text," %%", sizeof(text));
435                         gr_printf(sx,sy,text);
436                         sy += 2*dy;
437
438                         // alltime secondary weapon stats
439                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.s_shots_fired + add.s_shots_fired);
440                         gr_printf(sx,sy,text);
441                         sy += dy;
442                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.s_shots_hit + add.s_shots_hit);
443                         gr_printf(sx,sy,text);
444                         sy += dy;
445                         SDL_snprintf(text,sizeof(text),"%d",Active_player->stats.s_bonehead_hits + add.s_bonehead_hits);
446                         gr_printf(sx,sy,text);
447                         sy += dy;
448                         if((Active_player->stats.s_shots_fired+add.s_shots_fired)>0)
449                                 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));
450                         else pct=(float)0.0;
451                         SDL_snprintf(text,sizeof(text),"%d",(int)pct); SDL_strlcat(text," %%", sizeof(text));
452                         gr_printf(sx,sy,text);
453                         sy += dy;
454                         if((Active_player->stats.s_bonehead_hits + add.s_bonehead_hits)>0)
455                                 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));
456                         else pct=(float)0.0;
457                         SDL_snprintf(text,sizeof(text),"%d",(int)pct); SDL_strlcat(text," %%", sizeof(text));
458                         gr_printf(sx,sy,text);
459                         sy += 2*dy;
460
461                         // alltime assists
462                         SDL_snprintf(text,sizeof(text),"%d",(int)Active_player->stats.assists + add.assists);
463                         gr_printf(sx,sy,text);
464                         sy += 2*dy;
465
466                         if (Game_mode & GM_MULTIPLAYER) {
467                                 gr_printf(sx, sy, "%d", (int)Active_player->stats.score);
468                         }
469                         break;
470         } // end switch
471 }
472
473 int find_netplayer_n(int n)
474 {
475         int idx;
476         int target;
477    target = n;
478         n=0;
479    for(idx=0;idx<MAX_PLAYERS;idx++){
480                 if(MULTI_CONNECTED(Net_players[idx])){
481                         n++;
482                         if(n == target)
483                                 return idx;
484                 }
485         }
486         return -1;
487 }
488
489
490
491 void show_stats_close()
492 {       
493 }
494  
495 // initialize the statistics portion of the player structure for multiplayer.  Only the host of
496 // a netgame needs to be doing this (and if fact, only he *should* be doing this)
497 void init_multiplayer_stats( )
498 {
499         scoring_struct *ptr;
500
501         for (int idx=0; idx < MAX_PLAYERS; idx++) {
502                 ptr = &Players[idx].stats;
503                 scoring_level_init( ptr );
504         }
505 }
506
507 void set_player_stats(int pid)
508 {
509    Active_player = Net_players[pid].player;
510 }
511