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