]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/dumpstats.cpp
Initial revision
[taylor/freespace2.git] / src / fred2 / dumpstats.cpp
1 // DumpStats.cpp : implementation file
2 //
3
4 #include "stdafx.h"
5 #include "fred.h"
6 #include "dumpstats.h"
7 #include "starfield.h"
8 #include "neb.h"
9 #include "linklist.h"
10 #include "object.h"
11 #include "jumpnode.h"
12 #include        "missiongoals.h"
13 #include "eventmusic.h"
14 #include "asteroid.h"
15
16 #ifdef _DEBUG
17 #define new DEBUG_NEW
18 #undef THIS_FILE
19 static char THIS_FILE[] = __FILE__;
20 #endif
21
22 /////////////////////////////////////////////////////////////////////////////
23 // DumpStats dialog
24
25
26 DumpStats::DumpStats(CWnd* pParent /*=NULL*/)
27         : CDialog(DumpStats::IDD, pParent)
28 {
29         //{{AFX_DATA_INIT(DumpStats)
30                 // NOTE: the ClassWizard will add member initialization here
31         //}}AFX_DATA_INIT
32 }
33
34
35 void DumpStats::DoDataExchange(CDataExchange* pDX)
36 {
37         CDialog::DoDataExchange(pDX);
38         //{{AFX_DATA_MAP(DumpStats)
39                 // NOTE: the ClassWizard will add DDX and DDV calls here
40         //}}AFX_DATA_MAP
41 }
42
43
44 BEGIN_MESSAGE_MAP(DumpStats, CDialog)
45         //{{AFX_MSG_MAP(DumpStats)
46         ON_BN_CLICKED(IDC_DUMP_TO_FILE, OnDumpToFile)
47         //}}AFX_MSG_MAP
48 END_MESSAGE_MAP()
49
50 /////////////////////////////////////////////////////////////////////////////
51 // DumpStats message handlers
52
53 BOOL DumpStats::OnInitDialog() 
54 {
55         CDialog::OnInitDialog();
56         
57         CString buffer;
58         int i;
59
60         // get author, title, etc
61         get_mission_stats(buffer);
62
63         // get nebula, stars, etc.
64         get_background_stats(buffer);
65
66         // get number or ships, waypoints, start points, etc.
67         get_object_stats(buffer);
68
69         // get objectives / goals
70         get_objectives_and_goals(buffer);
71
72         // get ship selection for player wings
73         get_ship_weapon_selection(buffer);
74
75         // get messaging info
76         get_messaging_info(buffer);
77
78         // get species ship breakdown
79         get_species_ship_breakdown(buffer);
80
81         // get default loadouts
82         get_default_ship_loadouts(buffer);
83
84         int num_tab_stops = 5;
85         int tab_stops[5];
86         for (i=0; i<5; i++) {
87                 tab_stops[i] = (i+1) * 16;
88         }
89
90         ((CEdit*) GetDlgItem(IDC_STATS_TEXT))->SetTabStops(num_tab_stops, tab_stops);
91         ((CEdit*) GetDlgItem(IDC_STATS_TEXT))->SetWindowText(buffer);
92         
93         return TRUE;  // return TRUE unless you set the focus to a control
94                       // EXCEPTION: OCX Property Pages should return FALSE
95 }
96
97 void DumpStats::OnDumpToFile() 
98 {
99         // TODO: Add your control notification handler code here
100
101         // get dump from window
102         CString buffer;
103         ((CEdit*) GetDlgItem(IDC_STATS_TEXT))->GetWindowText(buffer);
104
105         CString dump_filename;
106         dump_filename.Format("%s.dmp", Mission_filename);
107
108         CFILE *fp;
109
110         fp = cfopen((char *)LPCTSTR(dump_filename), "wt", CFILE_NORMAL, CF_TYPE_MISSIONS);
111         cfputs((char *)LPCTSTR(buffer), fp);
112         cfclose(fp);
113 }
114
115 void DumpStats::get_mission_stats(CString &buffer)
116 {
117         CString temp;
118
119         // Mission info
120         buffer += "\t MISSION INFO\r\n";
121
122         temp.Format("Title: %s\r\n", The_mission.name);
123         buffer += temp;
124
125         temp.Format("Filename: %s\r\n", Mission_filename);
126         buffer += temp;
127
128         temp.Format("Author: %s\r\n", The_mission.author);
129         buffer += temp;
130
131         temp.Format("Description: %s\r\n", The_mission.mission_desc);
132         buffer += temp;
133
134         temp.Format("Notes: %s\r\n", The_mission.notes);
135         buffer += temp;
136
137         if (The_mission.game_type & MISSION_TYPE_SINGLE) {
138                 temp.Format("Mission type: Single Player\r\n");
139         } else if (The_mission.game_type & MISSION_TYPE_MULTI_COOP) {
140                 temp.Format("Mission type: Multi Coop\r\n");
141         } else if (The_mission.game_type & MISSION_TYPE_MULTI_TEAMS) {
142                 temp.Format("Mission type: Multi Team vs. Team\r\n");
143         } else if (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT) {
144                 temp.Format("Mission type: Dogfight\r\n");
145         }
146         buffer += temp;
147
148         if (The_mission.game_type & MISSION_TYPE_MULTI) {
149                 temp.Format("\tNum respawns: %d\r\n", The_mission.num_respawns);
150                 buffer += temp;
151         }
152
153         if (Current_soundtrack_num >= 0) {
154                 temp.Format("\tMusic: %s\r\n", Soundtracks[Current_soundtrack_num].name);
155                 buffer += temp;
156         }
157
158         if (The_mission.red_alert) {
159                 buffer += "\tRed Alert\r\n";
160         }
161
162         if (The_mission.scramble) {
163                 buffer += "\tScramble\r\n";
164         }
165
166         if (The_mission.flags & MISSION_FLAG_NO_PROMOTION) {
167                 buffer += "\tNo Promotions\r\n";
168         }
169
170         if (The_mission.disallow_support) {
171                 buffer += "\tNo Support ships\r\n";
172         }
173
174         temp.Format("Squadron: %s,  Squadron logo: %s\r\n", The_mission.squad_name, The_mission.squad_filename);
175         buffer += temp;
176 }
177
178 void DumpStats::get_background_stats(CString &buffer)
179 {
180         CString temp;
181         int i;
182
183         // Background
184         buffer += "\r\n\tBACKGROUND INFO\r\n";
185
186         // Num stars
187         temp.Format("Num_stars: %d\r\n", Num_stars);
188         buffer += temp;
189
190         // Suns
191         temp.Format("Num_suns: %d\r\n", Num_suns);
192         buffer += temp;
193         
194         for (i=0; i<Num_suns; i++) {
195                 temp.Format("\tSun%d bitmap name: %s\r\n", i, Sun_bitmaps[i].filename);
196                 buffer += temp;
197                 //temp.Format("Sun%d glow name: %s\r\n", i, Sun_bitmaps[i].glow_filename);
198                 //buffer += temp;
199         }
200
201         // Starfield bitmaps
202         temp.Format("Num_starfield_bitmaps: %d\r\n", Num_starfield_bitmaps);
203         buffer += temp;
204
205         for (i=0; i<Num_starfield_bitmaps; i++) {
206                 temp.Format("\tStarfield%d bitmap name: %s\r\n", i, Starfield_bitmap_instance[i].filename);
207                 buffer += temp;
208         }
209
210         // Asteroids
211         temp.Format("Num Field Debris Chunks: %d\r\n", Asteroid_field.num_initial_asteroids);
212         buffer += temp;
213         if (Asteroid_field.num_initial_asteroids > 0) {
214                 // active or passive
215                 if (Asteroid_field.field_type == FT_ACTIVE) {
216                         temp.Format("\tActive Field\r\n");
217                         buffer += temp;
218
219                         temp.Format("\tAsteroid Debris\r\n");
220                         buffer += temp;
221                 } else {
222                         // passive
223                         temp.Format("\tPassive Field\r\n");
224                         buffer += temp;
225
226                         if (Asteroid_field.debris_genre == DG_ASTEROID) {
227                                 temp.Format("\tAsteroid Debris\r\n");
228                                 buffer += temp;
229                         } else {
230                                 temp.Format("\tShip Debris\r\n");
231                                 buffer += temp;
232
233                                 // species
234                                 temp.Format("\t\tSpecies: ");
235                                 for (i=0; i<3; i++) {
236                                         if (Asteroid_field.field_debris_type[i] >= 0) {
237                                                 switch(Asteroid_field.field_debris_type[i]) {
238                                                 case DEBRIS_TERRAN_SMALL:
239                                                 case DEBRIS_TERRAN_MEDIUM:
240                                                 case DEBRIS_TERRAN_LARGE:
241                                                         temp += "Terran ";
242                                                         break;
243
244                                                 case DEBRIS_VASUDAN_SMALL:
245                                                 case DEBRIS_VASUDAN_MEDIUM:
246                                                 case DEBRIS_VASUDAN_LARGE:
247                                                         temp += "Vasudan ";
248                                                         break;
249
250                                                 case DEBRIS_SHIVAN_SMALL:
251                                                 case DEBRIS_SHIVAN_MEDIUM:
252                                                 case DEBRIS_SHIVAN_LARGE:
253                                                         temp += "Shivan ";
254                                                         break;
255                                                 }
256                                         }
257                                 }
258
259                                 temp += "\r\n";
260
261                                 buffer += temp;
262                         }
263                 }
264         }
265
266         // Nebula mission
267         int nebula_mission = (The_mission.flags & MISSION_FLAG_FULLNEB);
268         temp = "Nebula mission:";
269         if (nebula_mission) {
270                 temp += " Yes\r\n";
271         } else {
272                 temp += " No\r\n";
273         }
274         buffer += temp;
275
276         if (nebula_mission) {
277                 // range
278                 temp.Format("\tNebula awacs range: %.0f\r\n", Neb2_awacs);
279                 buffer += temp;
280
281                 // list of poofs
282                 for (i=0; i<MAX_NEB2_POOFS; i++) {
283                         if ( Neb2_poof_flags & (1<<i) ) {
284                                 temp.Format("\tNebula poof: %s\r\n", Neb2_poof_filenames[i]);
285                                 buffer += temp;
286                         }
287                 }
288
289                 // nebula texture
290                 if (strlen(Neb2_texture_name) > 0) {
291                         temp.Format("\tNebula texture: %s\r\n", Neb2_texture_name);
292                         buffer += temp;
293                 }
294         } else {
295                 // FS! nebula pattern
296                 if (Nebula_index > 0) {
297                         temp.Format("\tOld style FS1 nebula filename: %s\r\n", Nebula_filenames[Nebula_index]);
298                         buffer += temp;
299                 }
300         }
301
302         // Subspace mission
303         temp = "Subspace mission:";
304         if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
305                 temp += " Yes\r\n";
306         } else {
307                 temp += " No\r\n";
308         }
309         buffer += temp;
310 }
311
312 void DumpStats::get_object_stats(CString &buffer)
313 {
314         object *objp;
315         int obj_type_count[MAX_OBJECT_TYPES];
316         CString temp;
317         int num_small_ships, num_big_ships, num_huge_ships;
318
319         memset(obj_type_count,0, sizeof(obj_type_count));
320         num_small_ships = num_big_ships = num_huge_ships= 0;
321
322         for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
323
324                 // inc big ship or small ship count
325                 if ( (objp->type == OBJ_SHIP) || (objp->type == OBJ_START) ) {
326                         if ( Ship_info[Ships[objp->instance].ship_info_index].flags & SIF_SMALL_SHIP ) {
327                                 num_small_ships++;
328                         } else if ( Ship_info[Ships[objp->instance].ship_info_index].flags & SIF_BIG_SHIP ) {
329                                 num_big_ships++;
330                         } else if ( Ship_info[Ships[objp->instance].ship_info_index].flags & SIF_HUGE_SHIP ) {
331                                 num_huge_ships++;
332                         }
333                 }
334
335                 obj_type_count[objp->type]++;
336         }
337
338         // Statistics
339         buffer += "\r\n\tMISSION STATISTICS\r\n";
340
341         // OBJ_START is also a OBJ_SHIP
342         // not counting num_waves (for wings)
343         obj_type_count[OBJ_SHIP] += obj_type_count[OBJ_START];
344
345         for (int i=0; i<MAX_OBJECT_TYPES; i++) {
346                 if (obj_type_count[i] > 0) {
347                         switch(i) {
348                         case OBJ_SHIP:
349                                 temp.Format("Ship Count: %d\r\n", obj_type_count[i]);
350                                 buffer += temp;
351                                 break;
352
353                         case OBJ_START:
354                                 temp.Format("Start Count: %d\r\n", obj_type_count[i]);
355                                 buffer += temp;
356                                 break;
357
358                         case OBJ_WAYPOINT:
359                                 temp.Format("Waypoint Count: %d\r\n", obj_type_count[i]);
360                                 buffer += temp;
361                                 break;
362
363                         case OBJ_WING:
364                                 temp.Format("Wing Count: %d\r\n", obj_type_count[i]);
365                                 buffer += temp;
366                                 break;
367
368                         case OBJ_JUMP_NODE:
369                                 temp.Format("Jump Node Count: %d\r\n", obj_type_count[i]);
370                                 buffer += temp;
371                                 break;
372
373                         default:
374                                 Int3();
375                                 break;
376                         }
377                 }
378         }
379
380         buffer += "\r\nSHIPS\r\n";
381         temp.Format("\tNum small ships: %d\r\n", num_small_ships);
382         buffer += temp;
383
384         temp.Format("\tNum big ships: %d\r\n", num_big_ships);
385         buffer += temp;
386
387         temp.Format("\tNum huge ships: %d\r\n", num_huge_ships);
388         buffer += temp;
389
390         // Waypoints
391         int total_waypoints = 0;
392         buffer += "\r\nWAYPOINTS\r\n";
393         for (i=0; i<Num_waypoint_lists; i++) {
394                 temp.Format("\tWaypoint: %s, count: %d\r\n", Waypoint_lists[i].name, Waypoint_lists[i].count);
395                 buffer += temp;
396                 total_waypoints += Waypoint_lists[i].count;
397
398         }
399
400         if (total_waypoints > 0) {
401                 temp.Format("\ttotal_waypoints: %d\r\n", total_waypoints);
402                 buffer += temp;
403         }
404
405         // Jumpnodes
406         int total_jumpnodes = 0;
407         buffer += "\r\nJUMPNODES\r\n";
408         for (i=0; i<Num_jump_nodes; i++) {
409                 temp.Format("\tJumpnode: %s\r\n", Jump_nodes[i].name);
410                 buffer += temp;
411                 total_jumpnodes++;
412
413         }
414
415         if (total_jumpnodes > 0) {
416                 temp.Format("\ttotal_jumpnodes: %d\r\n", total_jumpnodes);
417                 buffer += temp;
418         }
419
420
421         // Wings
422         int num_counted_wings = 0;
423         buffer += "\r\nWINGS\r\n";
424         for (i=0; i<MAX_WINGS; i++) {
425                 if (Wings[i].wave_count > 0) {
426                         temp.Format("\tWing Name: %s,  num_ships: %d,  num_waves: %d\r\n", Wings[i].name, Wings[i].wave_count, Wings[i].num_waves);
427                         buffer += temp;
428
429                         num_counted_wings++;
430                         if (num_counted_wings == num_wings) {
431                                 break;
432                         }
433                 }
434         }
435
436         // Escort
437         buffer += "\r\nESCORT\r\n";
438         for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
439                 if ( (objp->type == OBJ_SHIP) || (objp->type == OBJ_START) ) {
440                         if (Ships[objp->instance].flags & SF_ESCORT) {
441                                 temp.Format("\tShip name: %s, priority: %d\r\n", Ships[objp->instance].ship_name, Ships[objp->instance].escort_priority);
442                                 buffer += temp;
443                         }
444                 }
445         }
446
447         // Hotkeys
448         buffer += "\r\nHOTKEYS\r\n";
449
450         // ship hotkeys
451         for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
452                 if ( (objp->type == OBJ_SHIP) || (objp->type == OBJ_START) ) {
453                         if (Ships[objp->instance].hotkey != -1) {
454                                 temp.Format("\tShip name: %s, hotkey: F%d\r\n", Ships[objp->instance].ship_name, (Ships[objp->instance].hotkey + 5));
455                                 buffer += temp;
456                         }
457                 }
458         }
459
460         // wing hotkeys
461         for (i=0; i<MAX_WINGS; i++) {
462                 if (Wings[i].wave_count > 0) {
463                         if (Wings[i].hotkey != -1) {
464                                 temp.Format("\tWing name: %s, hotkey: F%d\r\n", Wings[i].name, (Wings[i].hotkey + 5));
465                                 buffer += temp;
466                         }
467                 }
468         }
469
470 }
471
472 void DumpStats::get_objectives_and_goals(CString &buffer)
473 {
474         CString temp;
475         int i;
476
477         buffer += "\r\nOBJECTIVES AND GOALS\r\n";
478
479         // objectives
480         for (i=0; i<Num_mission_events; i++) {
481                 // name, objective_text, objective_key_text
482                 if ( Mission_events[i].objective_text == NULL ) {
483                         continue;
484                 }
485                 temp.Format("\tObjective: %s,  text: %s,  key_text: %s\r\n", Mission_events[i].name, Mission_events[i].objective_text, Mission_events[i].objective_key_text);
486                 buffer += temp;
487         }
488
489         buffer += "\r\n";
490
491         // goals
492         for (i=0; i<Num_goals; i++) {
493                 temp.Format("\tGoal: %s, text: ", Mission_goals[i].name, Mission_goals[i].message);
494                 buffer += temp;
495
496                 switch(Mission_goals[i].type & GOAL_TYPE_MASK) {
497                 case PRIMARY_GOAL:
498                         buffer += ",  type: primary\r\n";
499                         break;
500
501                 case SECONDARY_GOAL:
502                         buffer += ",  type: secondary\r\n";
503                         break;
504
505                 case BONUS_GOAL:
506                         buffer += ",  type: bonus\r\n";
507                         break;
508
509                 default:
510                         Int3();
511                         break;
512                 }
513         }
514
515 }
516
517 void DumpStats::get_ship_weapon_selection(CString &buffer)
518 {
519         CString temp;
520         int i,j;
521
522         buffer += "\r\nSHIP WEAPON/SELECTION\r\n";
523         buffer += "Reported numbers are in addition to assigned ships and their default weapons\r\n";
524
525         for (i=0; i<Num_teams; i++) {
526                 temp.Format("Team %d\r\n", i);
527                 buffer += temp;
528
529                 // ships
530                 for (j=0; j<Team_data[i].number_choices; j++) {
531                         temp.Format("\tShip name: %s, count %d", Ship_info[Ships[Team_data[i].ship_list[j]].ship_info_index].name, Team_data[i].ship_count[j]);
532                         buffer += temp;
533
534                         if (Team_data[i].ship_list[j] == Team_data[i].default_ship) {
535                                 temp = "  DEFAULT SHIP\r\n";
536                         } else {
537                                 temp = "\r\n";
538                         }
539                         buffer += temp;
540                 }
541
542                 buffer += "\r\n";
543
544                 // weapons
545                 for (j=0; j<MAX_WEAPON_TYPES; j++) {
546                         if (Team_data[i].weaponry_pool[j] > 0) {
547                                 temp.Format("\tWeapon name: %s, count %d\r\n", Weapon_info[j].name, Team_data[i].weaponry_pool[j]);
548                                 buffer += temp;
549                         }
550                 }
551         }
552
553 }
554
555 void DumpStats::get_messaging_info(CString &buffer)
556 {
557         CString temp;
558         object *objp;
559         ship *shipp;
560
561         buffer += "\r\nSHIP ACCEPTED ORDERS\r\n";
562
563         // go through all ships and check (.orders_accepted against default_orders)
564         for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
565                 if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
566                         shipp = &Ships[objp->instance];
567
568                         if (shipp->orders_accepted != ship_get_default_orders_accepted(&Ship_info[shipp->ship_info_index])) {
569                                 temp.Format("\tShip: %s with nonstandard accepted orders\r\n", shipp->ship_name);
570                                 buffer += temp;
571                         }
572                 }
573         }
574 }
575
576 void DumpStats::get_species_ship_breakdown(CString &buffer)
577 {
578         CString temp;
579         int i, species;
580         object *objp;
581         ship *shipp;
582
583         buffer += "\r\nSHIP SPECIES BREAKDOWN\r\n";
584
585         for (species=0; species<3; species++) {
586
587                 switch(species) {
588                 case SPECIES_TERRAN:
589                         buffer += "Terran\r\n";
590                         break;
591
592                 case SPECIES_VASUDAN:
593                         buffer += "Vasudan\r\n";
594                         break;
595
596                 case SPECIES_SHIVAN:
597                         buffer += "Shivan\r\n";
598                         break;
599                 }
600
601
602                 // fighter wings
603                 buffer += "\tFighter wings:\r\n";
604                 for (i=0; i<MAX_WINGS; i++) {
605                         if (Wings[i].wave_count > 0) {
606                                 int wing_leader_shipnum = Wings[i].ship_index[Wings[i].special_ship];
607                                 if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].species == species) {
608                                         if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].flags & SIF_FIGHTER) {
609                                                 temp.Format("\t\tWing: %s, count: %d, waves: %d, type: %s\r\n", Wings[i].name, Wings[i].wave_count, Wings[i].num_waves, Ship_info[Ships[wing_leader_shipnum].ship_info_index].name);
610                                                 buffer += temp;
611                                         }
612                                 }
613                         }
614                 }
615
616                 // bomber wings
617                 buffer += "\tBomber wings:\r\n";
618                 for (i=0; i<MAX_WINGS; i++) {
619                         if (Wings[i].wave_count > 0) {
620                                 int wing_leader_shipnum = Wings[i].ship_index[Wings[i].special_ship];
621                                 if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].species == species) {
622                                         if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].flags & SIF_BOMBER) {
623                                                 temp.Format("\t\tWing: %s, count: %d, waves: %d, type: %s\r\n", Wings[i].name, Wings[i].wave_count, Wings[i].num_waves, Ship_info[Ships[wing_leader_shipnum].ship_info_index].name);
624                                                 buffer += temp;
625                                         }
626                                 }
627                         }
628                 }
629
630                 buffer += "\tFreighters, Cargo, Transports:\r\n";
631                 // freighters and transports (cargo)
632                 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
633                         if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
634                                 shipp = &Ships[objp->instance];
635
636                                 if (Ship_info[shipp->ship_info_index].species == species) {
637                                         //if (shipp->wingnum == -1)
638                                         //if (shipp->cargo1 > 0)
639                                         if (Ship_info[shipp->ship_info_index].flags & (SIF_FREIGHTER | SIF_TRANSPORT | SIF_CARGO)) {
640                                                 temp.Format("\t\tName: %s Type: %s, Cargo: %s\r\n", shipp->ship_name, Ship_info[shipp->ship_info_index].name, Cargo_names[shipp->cargo1]);
641                                                 buffer += temp;
642                                         }
643                                 }
644                         }
645                 }
646
647                 buffer += "\tNav buoy, Escape pod, Sentry gun:\r\n";
648                 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
649                         if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
650                                 shipp = &Ships[objp->instance];
651
652                                 if (Ship_info[shipp->ship_info_index].species == species) {
653                                         //if (shipp->wingnum == -1)
654                                         //if (shipp->cargo1 > 0)
655                                         if (Ship_info[shipp->ship_info_index].flags & (SIF_NAVBUOY | SIF_ESCAPEPOD | SIF_SENTRYGUN)) {
656                                                 temp.Format("\t\tName: %s, Type: %s Cargo: %s\r\n", shipp->ship_name, Ship_info[shipp->ship_info_index].name, Cargo_names[shipp->cargo1]);
657                                                 buffer += temp;
658                                         }
659                                 }
660                         }
661                 }
662
663
664                 // cruiser
665                 buffer += "\tCruiser:\r\n";
666                 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
667                         if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
668                                 shipp = &Ships[objp->instance];
669
670                                 if (Ship_info[shipp->ship_info_index].species == species) {
671                                         //if (shipp->wingnum == -1)
672                                         //if (shipp->cargo1 > 0)
673                                         if (Ship_info[shipp->ship_info_index].flags & (SIF_CRUISER)) {
674                                                 temp.Format("\t\tName: %s, Type: %s, Cargo: %s\r\n", shipp->ship_name, Ship_info[shipp->ship_info_index].name, Cargo_names[shipp->cargo1]);
675                                                 buffer += temp;
676                                         }
677                                 }
678                         }
679                 }
680
681                 // dry dock, cap, super cap
682                 buffer += "\tDry dock, Capital, Supercap:\r\n";
683                 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
684                         if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
685                                 shipp = &Ships[objp->instance];
686
687                                 if (Ship_info[shipp->ship_info_index].species == species) {
688                                         //if (shipp->wingnum == -1)
689                                         //if (shipp->cargo1 > 0)
690                                         if (Ship_info[shipp->ship_info_index].flags & (SIF_DRYDOCK|SIF_CAPITAL|SIF_SUPERCAP)) {
691                                                 temp.Format("\t\tName: %s, Type: %s, Cargo: %s\r\n", shipp->ship_name, Ship_info[shipp->ship_info_index].name, Cargo_names[shipp->cargo1]);
692                                                 buffer += temp;
693                                         }
694                                 }
695                         }
696                 }
697
698                 buffer += "\r\n";
699         }
700 }
701
702 void dump_loadout(ship *shipp, CString &loadout)
703 {
704         CString temp;
705         char *weapon_name;
706
707         loadout = "";
708
709 //      PRIMARY
710         int pri_idx, sec_idx;
711
712         for (pri_idx=0; pri_idx < shipp->weapons.num_primary_banks; pri_idx++) {
713                 if (shipp->weapons.primary_bank_weapons[pri_idx] == -1) {
714                         weapon_name = "none";
715                 } else {
716                         weapon_name = Weapon_info[shipp->weapons.primary_bank_weapons[pri_idx]].name;
717                 } 
718                 temp.Format("\t\t\tPrimary[%d]: %s\r\n", pri_idx+1, weapon_name);
719                 loadout += temp;
720         }
721
722 // SECONDARY
723         for (sec_idx=0; sec_idx < shipp->weapons.num_secondary_banks; sec_idx++) {
724                 if (shipp->weapons.secondary_bank_weapons[sec_idx] == -1) {
725                         weapon_name = "none";
726                 } else {
727                         weapon_name = Weapon_info[shipp->weapons.secondary_bank_weapons[sec_idx]].name;
728                 } 
729                 temp.Format("\t\t\tSecondary[%d]: %s\r\n", sec_idx+1, weapon_name);
730                 loadout += temp;
731         }
732
733 // TURRET
734         ship_subsys *ss;
735         for (ss = GET_FIRST(&shipp->subsys_list); ss != END_OF_LIST(&shipp->subsys_list); ss = GET_NEXT(ss) ) {
736                 if ( (ss->system_info->type == SUBSYSTEM_TURRET) ) {
737 //                      ss->weapons.num_primary_banks, ss->weapons.num_secondary_banks, ss->weapons.primary_bank_weapons[3], ss->weapons.secondary_bank_weapons[2]
738 //                      ss->system_info->primary_banks, ss->system_info->secondary_banks
739                         temp.Format("\t\t\tTurret: %s\r\n", ss->system_info->subobj_name);
740                         loadout += temp;
741
742                         // PRIMARY
743                         for (pri_idx=0; pri_idx < ss->weapons.num_primary_banks; pri_idx++) {
744                                 if (ss->weapons.primary_bank_weapons[pri_idx] == -1) {
745                                         weapon_name = "none";
746                                 } else {
747                                         weapon_name = Weapon_info[ss->weapons.primary_bank_weapons[pri_idx]].name;
748                                 } 
749                                 temp.Format("\t\t\t\tPrimary[%d]: %s\r\n", pri_idx+1, weapon_name);
750                                 loadout += temp;
751                         }
752
753                         // SECONDARY
754                         for (sec_idx=0; sec_idx < ss->weapons.num_secondary_banks; sec_idx++) {
755                                 if (ss->weapons.secondary_bank_weapons[sec_idx] == -1) {
756                                         weapon_name = "none";
757                                 } else {
758                                         weapon_name = Weapon_info[ss->weapons.secondary_bank_weapons[sec_idx]].name;
759                                 } 
760                                 temp.Format("\t\t\t\tSecondary[%d]: %s\r\n", sec_idx+1, weapon_name);
761                                 loadout += temp;
762                         }
763                 }
764         }
765
766 }
767
768 void DumpStats::get_default_ship_loadouts(CString &buffer)
769 {
770         int i, species;
771         object *objp;
772         ship *shipp;
773         CString temp, loadout;
774
775         buffer += "\r\nSHIP SPECIES BREAKDOWN\r\n";
776
777         for (species=0; species<3; species++) {
778                 switch(species) {
779                 case SPECIES_TERRAN:
780                         buffer += "Terran\r\n";
781                         break;
782
783                 case SPECIES_VASUDAN:
784                         buffer += "Vasudan\r\n";
785                         break;
786
787                 case SPECIES_SHIVAN:
788                         buffer += "Shivan\r\n";
789                         break;
790                 }
791
792
793                 // fighter wings
794                 buffer += "\tFighter wings:\r\n";
795                 for (i=0; i<MAX_WINGS; i++) {
796                         if (Wings[i].wave_count > 0) {
797                                 int wing_leader_shipnum = Wings[i].ship_index[Wings[i].special_ship];
798                                 if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].species == species) {
799                                         if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].flags & SIF_FIGHTER) {
800                                                 temp.Format("\t\tWing: %s\r\n", Wings[i].name);
801                                                 buffer += temp;
802                                                 dump_loadout(&Ships[wing_leader_shipnum], loadout);
803                                                 buffer += loadout;
804                                         }
805                                 }
806                         }
807                 }
808
809                 // bomber wings
810                 buffer += "\tBomber wings:\r\n";
811                 for (i=0; i<MAX_WINGS; i++) {
812                         if (Wings[i].wave_count > 0) {
813                                 int wing_leader_shipnum = Wings[i].ship_index[Wings[i].special_ship];
814                                 if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].species == species) {
815                                         if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].flags & SIF_BOMBER) {
816                                                 temp.Format("\t\tWing: %s\r\n", Wings[i].name);
817                                                 buffer += temp;
818                                                 dump_loadout(&Ships[wing_leader_shipnum], loadout);
819                                                 buffer += loadout;
820                                         }
821                                 }
822                         }
823                 }
824
825                 buffer += "\tFreighters, Cargo, Transports:\r\n";
826                 // freighters and transports (cargo)
827                 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
828                         if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
829                                 shipp = &Ships[objp->instance];
830
831                                 if (Ship_info[shipp->ship_info_index].species == species) {
832                                         //if (shipp->wingnum == -1)
833                                         //if (shipp->cargo1 > 0)
834                                         if (Ship_info[shipp->ship_info_index].flags & (SIF_FREIGHTER | SIF_TRANSPORT)) {
835                                                 temp.Format("\t\tName: %s\r\n", shipp->ship_name);
836                                                 buffer += temp;
837                                                 dump_loadout(shipp, loadout);
838                                                 buffer += loadout;
839                                         }
840                                 }
841                         }
842                 }
843
844                 buffer += "\tEscape pod, Sentry gun:\r\n";
845                 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
846                         if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
847                                 shipp = &Ships[objp->instance];
848
849                                 if (Ship_info[shipp->ship_info_index].species == species) {
850                                         //if (shipp->wingnum == -1)
851                                         //if (shipp->cargo1 > 0)
852                                         if (Ship_info[shipp->ship_info_index].flags & (SIF_ESCAPEPOD | SIF_SENTRYGUN)) {
853                                                 temp.Format("\t\tName: %s\r\n", shipp->ship_name);
854                                                 buffer += temp;
855                                                 dump_loadout(shipp, loadout);
856                                                 buffer += loadout;
857                                         }
858                                 }
859                         }
860                 }
861
862
863                 // cruiser
864                 buffer += "\tCruiser:\r\n";
865                 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
866                         if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
867                                 shipp = &Ships[objp->instance];
868
869                                 if (Ship_info[shipp->ship_info_index].species == species) {
870                                         //if (shipp->wingnum == -1)
871                                         //if (shipp->cargo1 > 0)
872                                         if (Ship_info[shipp->ship_info_index].flags & (SIF_CRUISER)) {
873                                                 temp.Format("\t\tName: %s\r\n", shipp->ship_name);
874                                                 buffer += temp;
875                                                 dump_loadout(shipp, loadout);
876                                                 buffer += loadout;
877                                         }
878                                 }
879                         }
880                 }
881
882                 // dry dock, cap, super cap
883                 buffer += "\tCapital, Supercap:\r\n";
884                 for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
885                         if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
886                                 shipp = &Ships[objp->instance];
887
888                                 if (Ship_info[shipp->ship_info_index].species == species) {
889                                         //if (shipp->wingnum == -1)
890                                         //if (shipp->cargo1 > 0)
891                                         if (Ship_info[shipp->ship_info_index].flags & (SIF_CAPITAL|SIF_SUPERCAP)) {
892                                                 temp.Format("\t\tName: %s\r\n", shipp->ship_name);
893                                                 buffer += temp;
894                                                 dump_loadout(shipp, loadout);
895                                                 buffer += loadout;
896                                         }
897                                 }
898                         }
899                 }
900
901                 buffer += "\r\n";
902         }
903         // go through all wings
904
905         // go through all ships not in wings and FLYABLE
906
907         // print primary, secondary, and BIG turrets
908 }