FS2_Open
Open source remastering of the Freespace 2 engine
pilotfile.cpp
Go to the documentation of this file.
1 
2 #include "pilotfile/pilotfile.h"
3 #include "ship/ship.h"
4 #include "stats/medals.h"
5 
6 
8 
9 
11 {
12  m_have_flags = false;
13  m_have_info = false;
14 
15  m_data_invalid = false;
16 
17  m_size_offset = 0;
18 
19  cfp = NULL;
20  p = NULL;
21 }
22 
24 {
25  if (cfp) {
26  cfclose(cfp);
27  }
28 }
29 
30 void pilotfile::startSection(Section::id section_id)
31 {
32  Assert( cfp );
33 
34  const int zero = 0;
35 
36  cfwrite_ushort( (ushort)section_id, cfp );
37 
38  // to be updated when endSection() is called
39  cfwrite_int(zero, cfp);
40 
41  // starting offset, for size of section
42  m_size_offset = cftell(cfp);
43 }
44 
45 void pilotfile::endSection()
46 {
47  Assert( cfp );
48  Assert( m_size_offset > 0 );
49 
50  size_t cur = cftell(cfp);
51 
52  Assert( cur >= m_size_offset );
53 
54  size_t section_size = cur - m_size_offset;
55 
56  if (section_size) {
57  // go back to section size in file and write proper value
58  cfseek(cfp, cur - section_size - sizeof(int), CF_SEEK_SET);
59  cfwrite_int((int)section_size, cfp);
60 
61  // go back to previous location for next section
62  cfseek(cfp, cur, CF_SEEK_SET);
63  }
64 }
65 
66 void pilotfile::update_stats(scoring_struct *stats, bool training)
67 {
68  int idx, i, j, list_size;
69  index_list_t ilist;
70  scoring_special_t *p_stats = NULL;
71 
72  if (Game_mode & GM_MULTIPLAYER) {
73  p_stats = &multi_stats;
74  } else {
75  p_stats = &all_time_stats;
76  }
77 
78  // medals
79  if (stats->m_medal_earned >= 0) {
80  list_size = (int)p_stats->medals_earned.size();
81 
82  j = -1;
83 
84  for (idx = 0; idx < list_size; idx++) {
85  if ( p_stats->medals_earned[idx].name.compare(Medals[stats->m_medal_earned].name) == 0 ) {
86  j = idx;
87  break;
88  }
89  }
90 
91  if (j >= 0) {
92  p_stats->medals_earned[j].val++;
93  } else {
94  ilist.name = Medals[stats->m_medal_earned].name;
95  ilist.index = stats->m_medal_earned;
96  ilist.val = 1;
97 
98  p_stats->medals_earned.push_back(ilist);
99  }
100  }
101 
102  // early out if these stats are from a training mission
103  if (training) {
104  return;
105  }
106 
107  if (stats->m_promotion_earned >= 0) {
108  p_stats->rank = stats->m_promotion_earned;
109  }
110 
111  p_stats->score += stats->m_score;
112 
113  p_stats->assists += stats->m_assists;
114  p_stats->kill_count += stats->m_kill_count;
115  p_stats->kill_count_ok += stats->m_kill_count_ok;
116  p_stats->bonehead_kills += stats->m_bonehead_kills;
117 
118  p_stats->p_shots_fired += stats->mp_shots_fired;
119  p_stats->p_shots_hit += stats->mp_shots_hit;
120  p_stats->p_bonehead_hits += stats->mp_bonehead_hits;
121 
122  p_stats->s_shots_fired += stats->ms_shots_fired;
123  p_stats->s_shots_hit += stats->ms_shots_hit;
124  p_stats->s_bonehead_hits += stats->ms_bonehead_hits;
125 
126  p_stats->flight_time += (unsigned int)f2i(Missiontime);
127  p_stats->last_backup = p_stats->last_flown;
128  p_stats->last_flown = stats->last_flown;
129  p_stats->missions_flown++;
130 
131  // badges
132  if (stats->m_badge_earned.size()) {
133  list_size = (int)p_stats->medals_earned.size();
134  for (size_t medal = 0; medal < stats->m_badge_earned.size(); medal++) {
135  j = -1;
136 
137  for (idx = 0; idx < list_size; idx++) {
138  if ( p_stats->medals_earned[idx].name.compare(Medals[stats->m_badge_earned[medal]].name) == 0 ) {
139  j = idx;
140  break;
141  }
142  }
143 
144  if (j >= 0) {
145  p_stats->medals_earned[j].val = 1;
146  } else {
147  ilist.name = Medals[stats->m_badge_earned[medal]].name;
148  ilist.index = stats->m_badge_earned[medal];
149  ilist.val = 1;
150 
151  p_stats->medals_earned.push_back(ilist);
152  list_size++;
153  }
154  }
155  }
156 
157  // ship kills
158  idx = 0;
159  for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); idx++, ++it) {
160  if (stats->m_okKills[idx] > 0) {
161  list_size = (int)p_stats->ship_kills.size();
162 
163  j = -1;
164 
165  for (i = 0; i < list_size; i++) {
166  if ( p_stats->ship_kills[i].name.compare(it->name) == 0 ) {
167  j = i;
168  break;
169  }
170  }
171 
172  if (j >= 0) {
173  p_stats->ship_kills[j].val += stats->m_okKills[idx];
174  } else {
175  ilist.name = it->name;
176  ilist.index = idx;
177  ilist.val = stats->m_okKills[idx];
178 
179  p_stats->ship_kills.push_back(ilist);
180  }
181  }
182  }
183 }
184 
186 {
187  int i, j;
188  uint idx;
189  size_t list_size;
190  index_list_t ilist;
191  scoring_special_t *p_stats = NULL;
192 
193  if (Game_mode & GM_MULTIPLAYER) {
194  p_stats = &multi_stats;
195  } else {
196  p_stats = &all_time_stats;
197  }
198 
199  // medals
200  if (stats->m_medal_earned >= 0) {
201  list_size = p_stats->medals_earned.size();
202 
203  j = -1;
204 
205  for (idx = 0; idx < list_size; idx++) {
206  if ( p_stats->medals_earned[idx].name.compare(Medals[stats->m_medal_earned].name) == 0 ) {
207  j = idx;
208  break;
209  }
210  }
211 
212  if (j >= 0) {
213  p_stats->medals_earned[j].val = MAX(0,p_stats->medals_earned[j].val--);
214  } else {
215  Assertion(true, "Medal '%s' not found, should have been added by pilotfile::update_stats.", Medals[stats->m_medal_earned].name);
216  }
217  }
218 
219  // only medals can be awarded in training missions
220  if (training) {
221  return;
222  }
223 
224  p_stats->score -= stats->m_score;
225 
226  p_stats->assists -= stats->m_assists;
227  p_stats->kill_count -= stats->m_kill_count;
228  p_stats->kill_count_ok -= stats->m_kill_count_ok;
229  p_stats->bonehead_kills -= stats->m_bonehead_kills;
230 
231  p_stats->p_shots_fired -= stats->mp_shots_fired;
232  p_stats->p_shots_hit -= stats->mp_shots_hit;
233  p_stats->p_bonehead_hits -= stats->mp_bonehead_hits;
234 
235  p_stats->s_shots_fired -= stats->ms_shots_fired;
236  p_stats->s_shots_hit -= stats->ms_shots_hit;
237  p_stats->s_bonehead_hits -= stats->ms_bonehead_hits;
238 
239  p_stats->flight_time -= (unsigned int)f2i(Missiontime);
240  p_stats->last_flown = p_stats->last_backup;
241  p_stats->missions_flown--;
242 
243  if (stats->m_promotion_earned >= 0) {
244  // deal with a multi-rank promotion mission
245  for (i = 0; i < MAX_FREESPACE2_RANK; ++i) {
246  if (p_stats->score <= Ranks[i].points) {
247  p_stats->rank = i-1;
248  break;
249  }
250  }
251  Assertion (p_stats->rank >= 0, "Rank became negative.");
252  }
253 
254  // badges
255  if (stats->m_badge_earned.size()) {
256  list_size = p_stats->medals_earned.size();
257  for (size_t medal = 0; medal < stats->m_badge_earned.size(); medal++) {
258  j = -1;
259 
260  for (idx = 0; idx < list_size; idx++) {
261  if ( p_stats->medals_earned[idx].name.compare(Medals[stats->m_badge_earned[medal]].name) == 0 ) {
262  j = idx;
263  break;
264  }
265  }
266 
267  if (j >= 0) {
268  p_stats->medals_earned[j].val = 0;
269  } else {
270  Assertion (false, "Badge '%s' not found, should have been added by pilotfile::update_stats.", Medals[stats->m_badge_earned[medal]].name);
271  }
272  }
273  }
274 
275  // ship kills
276  i = 0;
277  for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); i++, ++it) {
278  if (stats->m_okKills[i] > 0) {
279  list_size = p_stats->ship_kills.size();
280 
281  j = -1;
282 
283  for (idx = 0; idx < list_size; idx++) {
284  if ( p_stats->ship_kills[idx].name.compare(it->name) == 0 ) {
285  j = idx;
286  break;
287  }
288  }
289 
290  if (j >= 0) {
291  p_stats->ship_kills[j].val -= stats->m_okKills[i];
292  } else {
293  Assertion(false, "Ship kills of '%s' not found, should have been added by pilotfile::update_stats.", Ship_info[i].name);
294  }
295  }
296  }
297 }
298 
303 {
304  scoring_special_t *ss_stats[] = {&all_time_stats, &multi_stats};
305 
306  for (int i = 0; i < 2; ++i) {
307  ss_stats[i]->score = 0;
308  ss_stats[i]->assists = 0;
309  ss_stats[i]->score = 0;
310  ss_stats[i]->rank = 0;
311  ss_stats[i]->assists = 0;
312  ss_stats[i]->kill_count = 0;
313  ss_stats[i]->kill_count_ok = 0;
314  ss_stats[i]->bonehead_kills = 0;
315 
316  ss_stats[i]->p_shots_fired = 0;
317  ss_stats[i]->p_shots_hit = 0;
318  ss_stats[i]->p_bonehead_hits = 0;
319 
320  ss_stats[i]->s_shots_fired = 0;
321  ss_stats[i]->s_shots_hit = 0;
322  ss_stats[i]->s_bonehead_hits = 0;
323 
324  ss_stats[i]->missions_flown = 0;
325  ss_stats[i]->flight_time = 0;
326  ss_stats[i]->last_flown = 0;
327  ss_stats[i]->last_backup = 0;
328 
329  ss_stats[i]->ship_kills.clear();
330  ss_stats[i]->medals_earned.clear();
331  }
332 }
pilotfile Pilot
Definition: pilotfile.cpp:7
int cfwrite_ushort(ushort s, CFILE *file)
Definition: cfile.cpp:1328
int i
Definition: multi_pxo.cpp:466
fix Missiontime
Definition: systemvars.cpp:19
SCP_vector< medal_stuff > Medals
Definition: medals.cpp:33
int Game_mode
Definition: systemvars.cpp:24
int points
Definition: scoring.h:68
Assert(pm!=NULL)
unsigned int mp_shots_fired
Definition: scoring.h:117
unsigned int mp_bonehead_hits
Definition: scoring.h:121
int m_bonehead_kills
Definition: scoring.h:123
_fs_time_t last_flown
Definition: scoring.h:103
#define Assertion(expr, msg,...)
Definition: clang.h:41
#define CF_SEEK_SET
Definition: cfile.h:24
unsigned int ms_bonehead_hits
Definition: scoring.h:122
void reset_stats()
Definition: pilotfile.cpp:302
unsigned int mp_shots_hit
Definition: scoring.h:119
SCP_vector< int > m_badge_earned
Definition: scoring.h:108
unsigned int ms_shots_fired
Definition: scoring.h:118
int m_kill_count_ok
Definition: scoring.h:115
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
int m_okKills[MAX_SHIP_CLASSES]
Definition: scoring.h:113
unsigned int uint
Definition: pstypes.h:64
int m_promotion_earned
Definition: scoring.h:109
#define GM_MULTIPLAYER
Definition: systemvars.h:18
#define f2i(a)
Definition: fix.h:22
GLenum GLuint id
Definition: Glext.h:5156
int idx
Definition: multiui.cpp:761
int cfwrite_int(int i, CFILE *file)
Definition: cfile.cpp:1310
GLuint const GLchar * name
Definition: Glext.h:5608
int cftell(CFILE *fp)
void update_stats_backout(scoring_struct *stats, bool training=false)
Definition: pilotfile.cpp:185
int m_medal_earned
Definition: scoring.h:107
void update_stats(scoring_struct *stats, bool training=false)
Definition: pilotfile.cpp:66
unsigned short ushort
Definition: pstypes.h:63
GLfloat GLfloat p
Definition: Glext.h:8373
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
rank_stuff Ranks[NUM_RANKS]
Definition: scoring.cpp:45
#define MAX(a, b)
Definition: pstypes.h:299
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
#define MAX_FREESPACE2_RANK
Definition: scoring.h:42
int m_kill_count
Definition: scoring.h:114
unsigned int ms_shots_hit
Definition: scoring.h:120
int cfseek(CFILE *fp, int offset, int where)