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