]> icculus.org git repositories - taylor/freespace2.git/blob - src/stats/stats.cpp
More changes, took out a lot of the sound/* stuff which will bite later but
[taylor/freespace2.git] / src / stats / stats.cpp
1 /*
2  * $Logfile: /Freespace2/code/Stats/Stats.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * module for running the stats screen
8  *
9  * $Log$
10  * Revision 1.2  2002/05/04 04:36:56  theoddone33
11  * More changes, took out a lot of the sound/* stuff which will bite later but
12  * I don't care.
13  *
14  * Revision 1.1.1.1  2002/05/03 03:28:10  root
15  * Initial import.
16  *
17  * 
18  * 5     10/15/99 3:56p Jefff
19  * lifetime score to alltime stats printout (multi debrief screen)
20  * 
21  * 4     10/15/99 3:01p Jefff
22  * mission score shows up in multiplayer debrief
23  * 
24  * 3     3/19/99 9:51a Dave
25  * Checkin to repair massive source safe crash. Also added support for
26  * pof-style nebulae, and some new weapons code.
27  * 
28  * 3     3/15/99 10:30a Neilk
29  * Add hires support
30  * 
31  * 2     10/07/98 10:54a Dave
32  * Initial checkin.
33  * 
34  * 1     10/07/98 10:51a Dave
35  * 
36  * 38    6/09/98 10:31a Hoffoss
37  * Created index numbers for all xstr() references.  Any new xstr() stuff
38  * added from here on out should be added to the end if the list.  The
39  * current list count can be found in FreeSpace.cpp (search for
40  * XSTR_SIZE).
41  * 
42  * 37    5/18/98 5:25p Chad
43  * Removed old-ass stats display code.
44  * 
45  * 36    5/18/98 12:52a Allender
46  * make initialization of multiplayer stats initialize all players, not
47  * just connected players (fixed ingame join stats problems)
48  * 
49  * 35    5/15/98 4:12p Allender
50  * removed redbook code.  Put back in ingame join timer.  Major fixups for
51  * stats in multiplayer.  Pass correct score, medals, etc when leaving
52  * game.  Be sure clients display medals, badges, etc.
53  * 
54  * 34    5/07/98 12:57a Dave
55  * Fixed incorrect calls to free() from stats code. Put in new artwork for
56  * debrief and host options screens. Another modification to scoring
57  * system for secondary weapons.
58  * 
59  * 33    4/21/98 11:56p Dave
60  * Put in player deaths statskeeping. Use arrow keys in the ingame join
61  * ship select screen. Don't quit the game if in the debriefing and server
62  * leaves.
63  * 
64  * 32    4/09/98 10:31a Dave
65  * Don't display player deaths statistic under single player (doesn't make
66  * sense).
67  * 
68  * 31    3/31/98 5:18p John
69  * Removed demo/save/restore.  Made NDEBUG defined compile.  Removed a
70  * bunch of debug stuff out of player file.  Made model code be able to
71  * unload models and malloc out only however many models are needed.
72  *  
73  * 
74  * 30    3/27/98 3:59p Hoffoss
75  * Due to everyone using different assumptions about what a length define
76  * means, changed code to account for safest assumption.
77  * 
78  * 29    3/17/98 12:29a Dave
79  * Put in hud support for rtvoice. Several ui interface changes.
80  * 
81  * 28    3/15/98 4:17p Dave
82  * Fixed oberver hud problems. Put in handy netplayer macros. Reduced size
83  * of network orientation matrices.
84  * 
85  * 27    2/22/98 2:48p John
86  * More String Externalization Classification
87  * 
88  * 26    2/12/98 5:00p Lawrance
89  * underline kills in the stats section
90  * 
91  * 25    1/06/98 5:08p Dave
92  * Put in stats display change to show alltime+mission stats during
93  * debriefing. Fixed a object update sequencing bug.
94  * 
95  * 24    12/10/97 4:45p Dave
96  * Added in more detailed support for multiplayer packet lag/loss. Fixed
97  * some multiplayer stuff. Added some controls to the standalone.
98  * 
99  * 23    11/06/97 9:53a Dave
100  * 
101  * 22    10/25/97 7:23p Dave
102  * Moved back to single set stats storing. Put in better respawning
103  * locations system.
104  * 
105  * 21    10/24/97 6:19p Dave
106  * More standalone testing/fixing. Added reliable endgame sequencing.
107  * Added reliable ingame joining. Added reliable stats transfer (endgame).
108  * Added support for dropping players in debriefing. Removed a lot of old
109  * unused code.
110  * 
111  * 20    10/23/97 7:44p Hoffoss
112  * Added 2 defines to replace hard-coded values in the code.
113  * 
114  * 19    10/21/97 5:21p Dave
115  * Fixed pregame mission load/file verify debacle. Added single vs.
116  * multiplayer stats system.
117  * 
118  * 18    10/14/97 5:37p Dave
119  * Fixed a memory allocation bug
120  * 
121  * 17    10/08/97 4:47p Dave
122  * Fixed bugs turned up in testing. Added some brief comments.
123  * 
124  * 16    9/30/97 8:48p Lawrance
125  * generalize some functions for displaying stats info
126  * 
127  * 15    9/24/97 5:03p Dave
128  * Beginning changes on how kills/assists are evaluated in both single and
129  * multiplayer
130  * 
131  * 14    9/18/97 10:14p Dave
132  * Updated the scoring system struct. Added rank.tbl. Modified how medal
133  * names are displayed.
134  * 
135  * 13    9/17/97 5:12p John
136  * Restructured collision routines.  Probably broke a lot of stuff.
137  * 
138  * 12    9/09/97 4:31p Dave
139  * Put in multiplayer post-game stats stuff.
140  * 
141  * 11    8/26/97 4:59p Dave
142  * Changed display from bonehead hits to friendly hits.
143  * 
144  * 10    8/23/97 11:31a Dave
145  * Changed the definition of bonehead hit %
146  * 
147  * 9     8/20/97 12:31p Dave
148  * Added a death count for auto ressurected players.
149  * Made it easier to reorganize the stats page
150  * 
151  * 8     8/19/97 5:14p Dave
152  * Added a sucker check. :)
153  * 
154  * 7     8/15/97 2:20p Allender
155  * fix stats code to properly get connected players
156  * 
157  * 6     8/15/97 9:28a Dave
158  * Fixed minor bug in multiplayer stats init.
159  * 
160  * 5     8/14/97 5:20p Dave
161  * Made initialization/clearing of players stats more thorough.
162  * 
163  * 4     7/25/97 5:23p Dave
164  * Made text displayed in antialiased font.
165  * 
166  * 3     7/25/97 4:33p Dave
167  * Spiffed up statistics screen considerably. Currently reports all
168  * statistics in the game (except mission/campaign related scores)
169  * 
170  * 2     7/24/97 2:31p Dave
171  * Added basic screen, no interaction yet.
172  * 
173  * 1     7/24/97 1:50p Dave
174  * 
175  * $NoKeywords: $
176  */
177
178 #ifndef PLAT_UNIX
179 #include <io.h>
180 #include <winsock.h>
181 #endif
182 #include "freespace.h"
183 #include "gamesequence.h"
184 #include "key.h"
185 #include "2d.h"
186 #include "ui.h"
187 #include "timer.h"
188 #include "player.h"
189 #include "stats.h"
190 #include "multi.h"
191 #include "hud.h"
192 #include "font.h"
193
194 #define MISSION_STATS_START_Y 80
195 #define ALLTIME_STATS_START_Y 270
196 #define MULTIPLAYER_LIST_START 20
197
198 static int Mission_stats_start_y[GR_NUM_RESOLUTIONS] = {
199         80,     // GR_640
200         80              // GR_1024
201 };
202
203 static int Alltime_stats_start_y[GR_NUM_RESOLUTIONS] = {
204         270,    // GR_640
205         270     // GR_1024
206 };
207
208 static int Multiplayer_list_start[GR_NUM_RESOLUTIONS] = {
209         20,     // GR_640
210         20              // GR_1024
211 };
212
213 // static UI_WINDOW Player_stats_window;
214
215 player *Active_player;
216
217 void show_stats_init()
218 {
219         // Player_stats_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
220
221         if (Game_mode & GM_MULTIPLAYER) {                               
222                 set_player_stats(MY_NET_PLAYER_NUM);
223         } else {
224                 Active_player = Player;         
225         }       
226 }
227
228 // write out the label for each stat
229 void show_stats_label(int stage, int sx, int sy, int dy)
230 {
231         switch ( stage ) {
232                 case MISSION_STATS:
233                         gr_printf(sx,sy,XSTR( "Mission Stats", 114));
234                         sy += 2*dy;
235                         gr_printf(sx,sy,XSTR( "Total kills", 115));
236                         sy += 2*dy;
237                         gr_printf(sx,sy,XSTR( "Primary weapon shots", 116));
238                         sy += dy;
239                         gr_printf(sx,sy,XSTR( "Primary weapon hits", 117));
240                         sy += dy;
241                         gr_printf(sx,sy,XSTR( "Primary friendly hits", 118));
242                         sy += dy;
243                         gr_printf(sx,sy,XSTR( "Primary hit %%", 119));
244                         sy += dy;
245                         gr_printf(sx,sy,XSTR( "Primary friendly hit %%", 120));
246                         sy += 2*dy;
247
248                         gr_printf(sx,sy,XSTR( "Secondary weapon shots", 121));
249                         sy += dy;
250                         gr_printf(sx,sy,XSTR( "Secondary weapon hits", 122));
251                         sy += dy;
252                         gr_printf(sx,sy,XSTR( "Secondary friendly hits", 123));
253                         sy += dy;
254                         gr_printf(sx,sy,XSTR( "Secondary hit %%", 124));
255                         sy += dy;
256                         gr_printf(sx,sy,XSTR( "Secondary friendly hit %%", 125));
257                         sy += 2*dy;
258
259                         gr_printf(sx,sy,XSTR( "Assists", 126));
260                         sy += 2*dy;
261
262                         if(Game_mode & GM_MULTIPLAYER){
263                                 gr_printf(sx,sy,XSTR( "Player Deaths", 127));
264                                 sy += 2*dy;
265
266                                 gr_printf(sx,sy,XSTR( "Mission score", 1526));
267                         }
268
269
270                         break;
271
272                 case ALL_TIME_STATS:
273                         gr_printf(sx,sy,XSTR( "All Time Stats", 128));
274                         sy += 2*dy;                     
275                         gr_printf(sx,sy,XSTR( "Total kills", 115));
276                         sy += 2*dy;
277                         gr_printf(sx,sy,XSTR( "Primary weapon shots", 116));
278                         sy += dy;
279                         gr_printf(sx,sy,XSTR( "Primary weapon hits", 117));
280                         sy += dy;
281                         gr_printf(sx,sy,XSTR( "Primary friendly hits", 118));
282                         sy += dy;
283                         gr_printf(sx,sy,XSTR( "Primary hit %%", 119));
284                         sy += dy;
285                         gr_printf(sx,sy,XSTR( "Primary friendly hit %%", 120));
286                         sy += 2*dy;
287
288                         gr_printf(sx,sy,XSTR( "Secondary weapon shots", 121));
289                         sy += dy;
290                         gr_printf(sx,sy,XSTR( "Secondary weapon hits", 122));
291                         sy += dy;
292                         gr_printf(sx,sy,XSTR( "Secondary friendly hits", 123));
293                         sy += dy;
294                         gr_printf(sx,sy,XSTR( "Secondary hit %%", 124));
295                         sy += dy;
296                         gr_printf(sx,sy,XSTR( "Secondary friendly hit %%", 125));
297                         sy += 2*dy;                     
298
299                         gr_printf(sx,sy,XSTR( "Assists", 126));
300                         sy += 2*dy;
301
302                         if(Game_mode & GM_MULTIPLAYER){
303                                 gr_printf(sx,sy,XSTR( "Score", 1527));
304                         }
305                         break;
306                 } // end switch
307 }
308
309 void stats_underline_text(int sx, int sy, char *text)
310 {
311         int w,h,fh;
312
313         gr_get_string_size(&w,&h,text);
314         fh=gr_get_font_height();
315         gr_line(sx-1, sy+fh, sx+w+1, sy+fh);
316 }
317
318 void show_stats_numbers(int stage, int sx, int sy, int dy,int add_mission)
319 {
320    char         text[30];
321         float           pct;
322
323         sy += 2*dy;
324         switch ( stage ) {
325                 case MISSION_STATS:
326          // mission kills stats
327                         sprintf(text,"%d",Active_player->stats.m_kill_count_ok);
328                         gr_printf(sx,sy,text);
329                         // stats_underline_text(sx,sy,text);
330                         sy += 2*dy;
331          // mission primary weapon stats
332                         sprintf(text,"%d",Active_player->stats.mp_shots_fired);
333                         gr_printf(sx,sy,text);
334                         sy += dy;
335                         sprintf(text,"%d",Active_player->stats.mp_shots_hit);
336                         gr_printf(sx,sy,text);
337                         sy += dy;
338                         sprintf(text,"%d",Active_player->stats.mp_bonehead_hits);
339                         gr_printf(sx,sy,text);
340                         sy += dy;
341                         if(Active_player->stats.mp_shots_fired>0)
342                                 pct=(float)100.0*((float)Active_player->stats.mp_shots_hit/(float)Active_player->stats.mp_shots_fired);
343                         else pct=(float)0.0;
344                         sprintf(text,"%d",(int)pct); strcat(text," %%");
345                         gr_printf(sx,sy,text);
346                         sy += dy;
347                         if(Active_player->stats.mp_bonehead_hits>0)
348                                 pct=(float)100.0*((float)Active_player->stats.mp_bonehead_hits/(float)Active_player->stats.mp_shots_fired);
349                         else pct=(float)0.0;
350                         sprintf(text,"%d",(int)pct); strcat(text," %%");
351                         gr_printf(sx,sy,text);
352                         sy += 2*dy;
353
354                         // mission secondary weapon stats
355                         sprintf(text,"%d",Active_player->stats.ms_shots_fired);
356                         gr_printf(sx,sy,text);
357                         sy += dy;
358                         sprintf(text,"%d",Active_player->stats.ms_shots_hit);
359                         gr_printf(sx,sy,text);
360                         sy += dy;
361                         sprintf(text,"%d",Active_player->stats.ms_bonehead_hits);
362                         gr_printf(sx,sy,text);
363                         sy += dy;
364                         if(Active_player->stats.ms_shots_fired>0)
365                                 pct=(float)100.0*((float)Active_player->stats.ms_shots_hit/(float)Active_player->stats.ms_shots_fired);
366                         else pct=(float)0.0;
367                         sprintf(text,"%d",(int)pct); strcat(text," %%");
368                         gr_printf(sx,sy,text);
369                         sy += dy;
370                         if(Active_player->stats.ms_bonehead_hits>0)
371                                 pct=(float)100.0*((float)Active_player->stats.ms_bonehead_hits/(float)Active_player->stats.ms_shots_fired);
372                         else pct=(float)0.0;
373                         sprintf(text,"%d",(int)pct); strcat(text," %%");
374                         gr_printf(sx,sy,text);
375                         sy += 2*dy;
376
377                         // mission assists and player rescues (respawns)
378                         sprintf(text,"%d",(int)Active_player->stats.m_assists);
379                         gr_printf(sx,sy,text);
380                         sy += 2*dy;
381
382                         if(Game_mode & GM_MULTIPLAYER){
383                                 sprintf(text,"%d",(int)Active_player->stats.m_player_deaths);
384                                 gr_printf(sx,sy,text);
385                                 sy += 2*dy;
386
387                                 // mission score
388                                 gr_printf(sx, sy, "%d", (int)Active_player->stats.m_score);
389                         }
390
391
392                         break;
393
394                 case ALL_TIME_STATS:
395                          scoring_struct add;
396                         
397                         // if we are passed mission_add (the stats for the current mission), copy it to "add", otherwise,
398                         // zero it out
399                         memset(&add,0,sizeof(scoring_struct));                          
400                         if(add_mission){
401                                 add.kill_count_ok = Active_player->stats.m_kill_count_ok;
402                                 add.p_shots_fired  = Active_player->stats.mp_shots_fired;
403                                 add.p_shots_hit = Active_player->stats.mp_shots_hit;
404                                 add.p_bonehead_hits = Active_player->stats.mp_bonehead_hits;                            
405                                 
406                                 add.s_shots_fired = Active_player->stats.ms_shots_fired;
407                                 add.s_shots_hit = Active_player->stats.ms_shots_hit;
408                                 add.s_bonehead_hits = Active_player->stats.ms_bonehead_hits;                            
409                         }                       
410
411          // mission kills stats
412                         sprintf(text,"%d",Active_player->stats.kill_count_ok + add.kill_count_ok);
413                         hud_num_make_mono(text);
414                         gr_printf(sx,sy,text);
415                         // stats_underline_text(sx,sy,text);
416                         sy += 2*dy;
417          // alltime primary weapon stats
418                         sprintf(text,"%d",Active_player->stats.p_shots_fired + add.p_shots_fired);
419                         gr_printf(sx,sy,text);
420                         sy += dy;
421                         sprintf(text,"%d",Active_player->stats.p_shots_hit + add.p_shots_hit);
422                         gr_printf(sx,sy,text);
423                         sy += dy;
424                         sprintf(text,"%d",Active_player->stats.p_bonehead_hits + add.p_bonehead_hits);
425                         gr_printf(sx,sy,text);
426                         sy += dy;
427                         if((Active_player->stats.p_shots_fired + add.p_shots_fired)>0)
428                                 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));
429                         else pct=(float)0.0;
430                         sprintf(text,"%d",(int)pct); strcat(text," %%");
431                         gr_printf(sx,sy,text);
432                         sy += dy;
433                         if((Active_player->stats.p_bonehead_hits + add.p_bonehead_hits)>0)
434                                 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));
435                         else pct=(float)0.0;
436                         sprintf(text,"%d",(int)pct); strcat(text," %%");
437                         gr_printf(sx,sy,text);
438                         sy += 2*dy;
439
440                         // alltime secondary weapon stats
441                         sprintf(text,"%d",Active_player->stats.s_shots_fired + add.s_shots_fired);
442                         gr_printf(sx,sy,text);
443                         sy += dy;
444                         sprintf(text,"%d",Active_player->stats.s_shots_hit + add.s_shots_hit);
445                         gr_printf(sx,sy,text);
446                         sy += dy;
447                         sprintf(text,"%d",Active_player->stats.s_bonehead_hits + add.s_bonehead_hits);
448                         gr_printf(sx,sy,text);
449                         sy += dy;
450                         if((Active_player->stats.s_shots_fired+add.s_shots_fired)>0)
451                                 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));
452                         else pct=(float)0.0;
453                         sprintf(text,"%d",(int)pct); strcat(text," %%");
454                         gr_printf(sx,sy,text);
455                         sy += dy;
456                         if((Active_player->stats.s_bonehead_hits + add.s_bonehead_hits)>0)
457                                 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));
458                         else pct=(float)0.0;
459                         sprintf(text,"%d",(int)pct); strcat(text," %%");
460                         gr_printf(sx,sy,text);
461                         sy += 2*dy;
462
463                         // alltime assists
464                         sprintf(text,"%d",(int)Active_player->stats.assists + add.assists);
465                         gr_printf(sx,sy,text);
466                         sy += 2*dy;
467
468                         if (Game_mode & GM_MULTIPLAYER) {
469                                 gr_printf(sx, sy, "%d", (int)Active_player->stats.score);
470                         }
471                         break;
472         } // end switch
473 }
474
475 int find_netplayer_n(int n)
476 {
477         int idx;
478         int target;
479    target = n;
480         n=0;
481    for(idx=0;idx<MAX_PLAYERS;idx++){
482                 if(MULTI_CONNECTED(Net_players[idx])){
483                         n++;
484                         if(n == target)
485                                 return idx;
486                 }
487         }
488         return -1;
489 }
490
491
492
493 void show_stats_close()
494 {       
495 }
496  
497 // initialize the statistics portion of the player structure for multiplayer.  Only the host of
498 // a netgame needs to be doing this (and if fact, only he *should* be doing this)
499 void init_multiplayer_stats( )
500 {
501         scoring_struct *ptr;
502
503         for (int idx=0; idx < MAX_PLAYERS; idx++) {
504                 ptr = &Players[idx].stats;
505                 scoring_level_init( ptr );
506         }
507 }
508
509 void set_player_stats(int pid)
510 {
511    Active_player = Net_players[pid].player;
512 }
513