1 /////////////////////////////////////////
2 //
3 // OpenLieroX
4 //
5 // code under LGPL, based on JasonBs work,
6 // enhanced by Dark Charlie and Albert Zeyer
7 //
8 //
9 /////////////////////////////////////////
10
11
12 // Profile system
13 // Created 13/8/02
14 // Jason Boettcher
15
16
17 #include <assert.h>
18
19 #include "LieroX.h"
20 #include "ProfileSystem.h"
21 #include "EndianSwap.h"
22 #include "GfxPrimitives.h"
23 #include "FindFile.h"
24 #include "StringUtils.h"
25 #include "FileUtils.h"
26
27 profile_t *tProfiles = NULL;
28
29
30 ///////////////////
31 // Load the profiles
LoadProfiles()32 int LoadProfiles()
33 {
34 int i;
35
36 //
37 // Open the file
38 //
39 FILE *fp = OpenGameFile("cfg/players.dat","rb");
40 if(fp == NULL) {
41 // Add the default players
42 AddDefaultPlayers();
43 return false;
44 }
45
46
47 //
48 // Header
49 //
50
51 // Check ID
52 std::string id;
53 fread_fixedwidthstr<32>(id, fp);
54 if(id != "lx:profile") {
55 errors << "Could not load profiles: \"" << id << "\" is not equal to \"lx:profile\"" << endl;
56
57 // Add the default players
58 AddDefaultPlayers();
59 fclose(fp);
60 return false;
61 }
62
63 // Check version
64 int ver = 0;
65 fread_compat(ver, sizeof(int), 1, fp);
66 EndianSwap(ver);
67 if(ver != PROFILE_VERSION) {
68 std::string tmp = "Could not load profiles: \""+itoa(ver)+"\" is not equal to \""+itoa(PROFILE_VERSION)+"\"";
69 errors << tmp << endl;
70
71 // Add the default players
72 AddDefaultPlayers();
73 fclose(fp);
74 return false;
75 }
76
77 // Get number of profiles
78 int num = 0;
79 fread_compat(num, sizeof(int), 1, fp);
80 EndianSwap(num);
81
82 // Safety check
83 if(num < 0) {
84 // Just leave
85 fclose(fp);
86 // Add the default players
87 AddDefaultPlayers();
88 return true;
89 }
90
91
92 // Load the profiles
93 for(i=0; i<num; i++)
94 LoadProfile(fp, i);
95
96 fclose(fp);
97
98 return true;
99 }
100
101
102 ///////////////////
103 // Add the default players to the list
AddDefaultPlayers()104 void AddDefaultPlayers()
105 {
106 short i;
107 std::string buf;
108
109 // Pre-set cpu colours
110 Uint32 cpuColours[] = { 255,0,0, 0,255,0, 0,0,255, 255,0,255, 0,255,255, 128,128,128,
111 128,255,0, 0,128,255, 0,128,0 };
112
113 // Pre-set cpu difficulties
114 int Diff[] = {AI_EASY, AI_MEDIUM, AI_MEDIUM, AI_HARD, AI_XTREME, AI_MEDIUM, AI_EASY};
115
116 // Add the default worm
117 AddProfile("worm", "default.png", "", "", 100,100,255, PRF_HUMAN->toInt(),0);
118
119 // Add 7 ai players
120 for(i=0; i<7; i++) {
121 buf = "CPU "+itoa(i+1);
122
123 AddProfile(buf, "default.png", "", "", cpuColours[i*3], cpuColours[i*3+1], cpuColours[i*3+2], PRF_COMPUTER->toInt(), Diff[i]);
124 }
125 }
126
127
128 ///////////////////
129 // Save the profiles
SaveProfiles()130 void SaveProfiles()
131 {
132 profile_t *p = tProfiles;
133 profile_t *pf;
134
135
136 //
137 // Open the file
138 //
139 FILE *fp = OpenGameFile("cfg/players.dat","wb");
140 if(fp == NULL) {
141 errors << "Could not open cfg/players.dat for writing" << endl;
142 return;
143 }
144
145 // ID & Version
146 fwrite("lx:profile", 32, fp);
147
148 int ver = PROFILE_VERSION;
149 fwrite_endian_compat((ver), sizeof(int), 1, fp);
150
151
152 // Count how many profiles we have
153 int Num=0;
154 for(;p;p=p->tNext)
155 Num++;
156
157 fwrite_endian_compat((Num), sizeof(int), 1, fp);
158
159
160 p = tProfiles;
161 for(; p; p = pf) {
162 pf = p->tNext;
163
164 // Save the profile
165 SaveProfile(fp, p);
166 }
167
168 }
169
170
171 ///////////////////
172 // Shutdown & save the profiles
ShutdownProfiles()173 void ShutdownProfiles()
174 {
175 if (!tProfiles) // Profiles not loaded, don't write and empty file (and delete all user's prifiles!)
176 return;
177
178 profile_t *p = tProfiles;
179 profile_t *pf = NULL;
180
181
182 //
183 // Open the file
184 //
185 FILE *fp = OpenGameFile("cfg/players.dat","wb");
186 if(fp == NULL) {
187 errors << "Could not open cfg/players.dat for writing" << endl;
188 return;
189 }
190
191 // ID & Version
192 fwrite("lx:profile", 32, fp);
193
194
195 int ver = PROFILE_VERSION;
196 fwrite_endian_compat((ver), sizeof(int), 1, fp);
197
198
199 // Count how many profiles we have
200 int Num=0;
201 for(;p;p=p->tNext)
202 Num++;
203
204 fwrite_endian_compat((Num), sizeof(int), 1, fp);
205
206
207 p = tProfiles;
208 for(; p; p = pf) {
209 pf = p->tNext;
210
211 // Save the profile
212 SaveProfile(fp, p);
213
214 // Free the actual profile
215 assert(p);
216 delete p;
217 }
218
219
220 fclose(fp);
221
222 tProfiles = NULL;
223 }
224
225
226 ///////////////////
227 // Load a profile
LoadProfile(FILE * fp,int id)228 void LoadProfile(FILE *fp, int id)
229 {
230 profile_t *p;
231
232 p = new profile_t();
233 if(p == NULL)
234 return;
235
236 p->iID = id;
237 p->tNext = NULL;
238
239
240 // Name
241 p->sName = freadfixedcstr(fp, 32);
242 p->cSkin.Change(freadfixedcstr(fp, 128));
243 fread_compat(p->iType, sizeof(int), 1, fp);
244 EndianSwap(p->iType);
245 fread_compat(p->nDifficulty,sizeof(int), 1, fp);
246 EndianSwap(p->nDifficulty);
247
248 if (p->iType == PRF_COMPUTER->toInt())
249 p->cSkin.setBotIcon(p->nDifficulty);
250
251 // Multiplayer
252 p->sUsername = freadfixedcstr(fp,16);
253 p->sPassword = freadfixedcstr(fp,16);
254
255 // Colour
256 fread_compat(p->R, sizeof(Uint8), 1, fp);
257 EndianSwap(p->R);
258 fread_compat(p->G, sizeof(Uint8), 1, fp);
259 EndianSwap(p->G);
260 fread_compat(p->B, sizeof(Uint8), 1, fp);
261 EndianSwap(p->B);
262
263 p->cSkin.setDefaultColor(Color(p->R, p->G, p->B));
264 p->cSkin.Colorize(p->cSkin.getDefaultColor());
265
266 // Weapons
267 for(int i=0; i<5; i++)
268 p->sWeaponSlots[i] = freadfixedcstr(fp,64);
269
270 // Add the profile onto the list
271 if(tProfiles) {
272 profile_t *pf = tProfiles;
273 for(;pf;pf = pf->tNext) {
274 if(pf->tNext == NULL) {
275 pf->tNext = p;
276 break;
277 }
278 }
279 }
280 else
281 tProfiles = p;
282 }
283
284
285 ///////////////////
286 // Save a profile
SaveProfile(FILE * fp,profile_t * p)287 void SaveProfile(FILE *fp, profile_t *p)
288 {
289 // Name & Type
290 fwrite(p->sName, 32, fp);
291 fwrite(p->cSkin.getFileName(), 128,fp);
292 fwrite_endian_compat((p->iType), sizeof(int), 1, fp);
293 fwrite_endian_compat((p->nDifficulty),sizeof(int), 1, fp);
294
295 // Multiplayer
296 fwrite(p->sUsername, 16, fp);
297 fwrite(p->sPassword, 16, fp);
298
299 // Colour
300 fwrite(&p->R, 1, 1, fp);
301 fwrite(&p->G, 1, 1, fp);
302 fwrite(&p->B, 1, 1, fp);
303
304 // Weapons
305 for(int i=0; i<5; i++)
306 fwrite(p->sWeaponSlots[i], 64, fp);
307 }
308
309
310 ///////////////////
311 // Delete a profile
DeleteProfile(int id)312 void DeleteProfile(int id)
313 {
314 profile_t *prv = NULL;
315 profile_t *p = tProfiles;
316
317 // Find it's previous
318 for(; p; p=p->tNext) {
319
320 if(p->iID == id) {
321
322 // Set the previous profiles next to my next one
323 // Thus removing me from the list
324 if(prv)
325 prv->tNext = p->tNext;
326 else
327 tProfiles = p->tNext;
328
329 // Free me
330 delete p;
331
332 break;
333 }
334
335 prv = p;
336 }
337
338
339 // Reset the id's
340 p = tProfiles;
341 int i=0;
342 for(;p;p = p->tNext)
343 p->iID = i++;
344 }
345
346
347 ///////////////////
348 // Add a profile to the list
AddProfile(const std::string & name,const std::string & skin,const std::string & username,const std::string & password,int R,int G,int B,int type,int difficulty)349 void AddProfile(const std::string& name, const std::string& skin, const std::string& username, const std::string& password, int R, int G, int B, int type, int difficulty)
350 {
351 profile_t *p;
352
353 p = new profile_t();
354 if(p == NULL)
355 return;
356
357 // Find a free id
358 int id = FindProfileID();
359
360 p->iID = id;
361 p->iType = type;
362 p->nDifficulty = difficulty;
363 p->tNext = NULL;
364
365 p->sName = name;
366 p->cSkin.Change(skin);
367 p->R = R;
368 p->G = G;
369 p->B = B;
370 p->cSkin.Colorize(Color(R, G, B));
371
372 p->sUsername = username;
373 p->sPassword = password;
374
375
376 // Default weapons
377 p->sWeaponSlots[0] = "minigun";
378 p->sWeaponSlots[1] = "super shotgun";
379 p->sWeaponSlots[2] = "blaster";
380 p->sWeaponSlots[3] = "gauss gun";
381 p->sWeaponSlots[4] = "big nuke";
382
383
384 // Add the profile onto the list
385 if(tProfiles) {
386
387 profile_t *pf = tProfiles;
388 profile_t *prv = NULL;
389
390 for(;pf;pf = pf->tNext) {
391
392 // If we are human, we need to insert ourselves into the list before the ai players
393 if(p->iType == PRF_HUMAN->toInt()) {
394 if(pf->iType == PRF_COMPUTER->toInt()) {
395
396 p->tNext = pf;
397 if(prv)
398 prv->tNext = p;
399 else
400 // Must be first one
401 tProfiles = p;
402
403 break;
404 }
405 }
406
407
408 if(pf->tNext == NULL) {
409
410 pf->tNext = p;
411 break;
412 }
413
414 prv = pf;
415 }
416 }
417 else
418 tProfiles = p;
419
420
421 // Reset the id's
422 p = tProfiles;
423 int i=0;
424 for(;p;p = p->tNext)
425 p->iID = i++;
426 }
427
428
429 ///////////////////
430 // Find a free profile id
FindProfileID()431 int FindProfileID()
432 {
433 profile_t *p = tProfiles;
434
435 int id = -1;
436
437 for(; p; p=p->tNext)
438 id = p->iID;
439
440 return id+1;
441 }
442
443
444 ///////////////////
445 // Get the profiles
GetProfiles()446 profile_t *GetProfiles()
447 {
448 return tProfiles;
449 }
450
451
452 ///////////////////
453 // Find a profile based on id
FindProfile(int id)454 profile_t *FindProfile(int id)
455 {
456 profile_t *p = tProfiles;
457
458 for(;p;p=p->tNext) {
459 if(p->iID == id)
460 return p;
461 }
462
463 return NULL;
464 }
465
FindProfile(const std::string & name)466 profile_t *FindProfile(const std::string& name) {
467 profile_t *p = tProfiles;
468
469 for(;p;p=p->tNext) {
470 if(p->sName == name)
471 return p;
472 }
473
474 return NULL;
475 }
476
477
FindFirstCPUProfileName()478 std::string FindFirstCPUProfileName() {
479 profile_t *p = tProfiles;
480
481 for(;p;p=p->tNext) {
482 if(p->iType == PRF_COMPUTER->toInt())
483 return p->sName;
484 }
485
486 return "";
487 }
488