Subversion Repositories spk

Rev

Rev 35 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
#include "XspFile.h"
2
#include "File_IO.h"
3
#include "Packages.h"
4
#include "CatFile.h"
5
 
6
CXspFile::CXspFile () : CBaseFile()
7
{
8
	SetDefaults ();
9
 
10
	m_iType = TYPE_XSP;
11
}
12
 
13
void CXspFile::Delete ()
14
{
15
	CBaseFile::Delete();
16
	m_pSceneFile = m_pCockpitFile = NULL;
17
 
18
	// delete lists
19
	m_lMissileMasks.MemoryClear();
20
	m_lWeaponMasks.MemoryClear();
21
 
22
	m_lMissileMasks.destroy();
23
	m_lWeaponMasks.destroy();
24
 
25
	for ( CListNode<SCockpit> *n = m_lCockpit.Front(); n; n = n->next() )
26
		n->Data()->lWeaponMask.MemoryClear();
27
	m_lCockpit.MemoryClear();
28
	m_lCockpit.destroy();
29
	m_lCutData.Clear();
30
	m_lBodies.Clear();
31
}
32
 
33
void CXspFile::SetDefaults ()
34
{
35
	CBaseFile::SetDefaults ();
36
 
37
	m_pSceneFile = m_pCockpitFile = NULL;
38
	m_bLanguageText = m_bExistingShip = false;
39
	m_iOrgDesc = 0;
40
 
41
	m_iShipyard = SHIPYARD_NONE;
42
}
43
 
44
void CXspFile::AddText ( int id, CyString name, CyString desc )
45
{
46
	// first check if theres an existing id
47
	SText *newtext = NULL;
48
	for ( SText *t = m_lText.First(); t; t = m_lText.Next() )
49
	{
50
		if ( t->iId == id )
51
		{
52
			newtext = t;
53
			break;
54
		}
55
	}
56
 
57
	if ( !newtext )
58
	{
59
		newtext = new SText;
60
		newtext->iId = id;
61
		m_lText.push_back ( newtext );
62
	}
63
 
64
	newtext->sName = name;
65
	newtext->sDesc = desc;
66
 
67
	m_bChanged = true; 
68
}
69
 
70
void CXspFile::RemoveText(int id)
71
{
72
	for ( SText *t = m_lText.First(); t; t = m_lText.Next() )
73
	{
74
		if ( t->iId == id )
75
		{
76
			m_bChanged = true; 
77
			m_lText.RemoveCurrent();
78
			return;
79
		}
80
	}
81
}
82
 
83
void CXspFile::AddDummy ( CyString section, CyString data )
84
{
85
	SDummy *d = new SDummy;
86
	d->sData = data;
87
	d->sSection = section;
88
 
89
	if ( d->sData.Right (1) != ";" )
90
		d->sData += ";";
91
 
92
	m_lDummy.push_back ( d );
93
 
94
	m_bChanged = true; 
95
}
96
 
97
void CXspFile::AddComponent ( CyString section, CyString section2, CyString data )
98
{
99
	SComponent *c = new SComponent;
100
	c->sData = data;
101
	c->sSection = section;
102
	c->sSection2 = section2;
103
 
104
	if ( c->sData.Right (1) != ";" )
105
		c->sData += ";";
106
 
107
	m_lComponent.push_back ( c );
108
 
109
	m_bChanged = true; 
110
}
111
 
112
void CXspFile::AddWeaponMask ( int game, int mask )
113
{
114
	// first check if we have one for the game
115
	SWeaponMask *m = NULL;
116
	for ( CListNode<SWeaponMask> *node = m_lWeaponMasks.Front(); node; node = node->next() )
117
	{
118
		if ( node->Data()->iGame == game )
119
		{
120
			m = node->Data();
121
			break;
122
		}
123
	}
124
 
125
	// not found, create one
126
	if ( !m )
127
	{
128
		m = new SWeaponMask;
129
		m_lWeaponMasks.push_back(m);
130
		m->iGame = game;
131
	}
132
 
133
	m->iMask = mask;
134
	m_bChanged = true; 
135
}
136
void CXspFile::AddMissileMask ( int game, int mask )
137
{
138
	// first check if we have one for the game
139
	SWeaponMask *m = NULL;
140
	for ( CListNode<SWeaponMask> *node = m_lMissileMasks.Front(); node; node = node->next() )
141
	{
142
		if ( node->Data()->iGame == game )
143
		{
144
			m = node->Data();
145
			break;
146
		}
147
	}
148
 
149
	// not found, create one
150
	if ( !m )
151
	{
152
		m = new SWeaponMask;
153
		m_lMissileMasks.push_back(m);
154
		m->iGame = game;
155
	}
156
 
157
	m->iMask = mask;
158
	m_bChanged = true; 
159
}
160
 
161
bool CXspFile::IsValid ()
162
{
163
	if ( m_sName.Empty() )
164
		return false;
165
	if ( m_sAuthor.Empty() )
166
		return false;
167
 
168
	return true;
169
}
170
 
14 cycrow 171
Utils::String CXspFile::CreateValuesLine() const
1 cycrow 172
{
14 cycrow 173
	Utils::String values = CBaseFile::CreateValuesLine ();
1 cycrow 174
 
14 cycrow 175
	values += "Data: " + m_sData + "\n";
176
	values += "ID: " + m_sID + "\n";
1 cycrow 177
 
178
	if ( m_bLanguageText )
179
		values += "LanguageText\n";
180
	if ( m_bExistingShip )
181
		values += "ExistingShip\n";
14 cycrow 182
	values += Utils::String("OrgDesc: ") + (long)m_iOrgDesc + "\n";
183
	values += Utils::String("Shipyard: ") + (long)m_iShipyard + "\n";
1 cycrow 184
 
14 cycrow 185
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ) {
186
		SCockpit *cockpit = node->Data();
187
		values += Utils::String("CockpitNew: ") + (long)cockpit->lWeaponMask.size();
188
		for ( CListNode<SWeaponMask> *wNode = cockpit->lWeaponMask.Front(); wNode; wNode = wNode->next() ) {
1 cycrow 189
			values += ":";
14 cycrow 190
			values += (long)wNode->Data()->iGame;
1 cycrow 191
			values += ":";
14 cycrow 192
			values += (long)wNode->Data()->iMask;
1 cycrow 193
		}
194
		values += " ";
14 cycrow 195
		values += cockpit->sCockpit.ToString() + "\n";
1 cycrow 196
	}
197
 
14 cycrow 198
	for ( CListNode<SText> *tNode = m_lText.Front(); tNode; tNode = tNode->next() )
199
		values += Utils::String("Text: ") + (long)tNode->Data()->iId + "|" + tNode->Data()->sName.FindReplace("|", "<::PiPe::>").ToString() + "|" + tNode->Data()->sDesc.ToString() + "\n";
1 cycrow 200
 
14 cycrow 201
	for ( CListNode<SComponent> *cNode = m_lComponent.Front(); cNode; cNode = cNode->next() )
202
		values += Utils::String("Component: ") + cNode->Data()->sData.FindReplace("|", "<::PiPe::>").ToString() + "|" + cNode->Data()->sSection.FindReplace("|", "<::PiPe::>").ToString() + "|" + cNode->Data()->sSection2.ToString() + "\n";
1 cycrow 203
 
14 cycrow 204
	for ( CListNode<SDummy> *dNode = m_lDummy.Front(); dNode; dNode = dNode->next() )
205
		values += Utils::String("Dummy: ") + dNode->Data()->sData.FindReplace("|", "<::PiPe::>").ToString() + "|" + dNode->Data()->sSection.ToString() + "\n";
1 cycrow 206
 
14 cycrow 207
	for ( CListNode<SWeaponMask> *wNode = m_lWeaponMasks.Front(); wNode; wNode = wNode->next() )
208
		values += Utils::String("WeaponMask: ") + (long)wNode->Data()->iGame + " " + (long)wNode->Data()->iMask + "\n";
209
	for ( CListNode<SWeaponMask> *mNode = m_lMissileMasks.Front(); mNode; mNode = mNode->next() )
210
		values += Utils::String("MissileMask: ") + (long)mNode->Data()->iGame + " " + (long)mNode->Data()->iMask + "\n";
1 cycrow 211
	for ( SStringList *cut = m_lCutData.Head(); cut; cut = cut->next )
14 cycrow 212
		values += Utils::String("CutData: ") + cut->str.ToString() + "\n";
1 cycrow 213
	for ( SStringList *body = m_lBodies.Head(); body; body = body->next )
14 cycrow 214
		values += Utils::String("Bodies: ") + body->str.ToString() + "\n";
1 cycrow 215
	for ( SStringList *ani = m_lAnimations.Head(); ani; ani = ani->next )
14 cycrow 216
		values += Utils::String("Animations: ") + ani->str.ToString() + "\n";
1 cycrow 217
 
218
	return values;
219
}
220
 
14 cycrow 221
bool CXspFile::ParseValueLine(const Utils::String &sLine)
1 cycrow 222
{
14 cycrow 223
	Utils::String first = sLine.token(":", 1);
224
	Utils::String rest  = sLine.tokens(":", 2).removeFirstSpace();
1 cycrow 225
 
14 cycrow 226
	if ( first.Compare("Data") )
1 cycrow 227
		m_sData = rest;
14 cycrow 228
	else if ( first.Compare("ID") )
1 cycrow 229
		m_sID = rest;
14 cycrow 230
	else if ( sLine.Compare("LanguageText") )
1 cycrow 231
		m_bLanguageText = true;
14 cycrow 232
	else if ( sLine.Compare("ExistingShip") )
1 cycrow 233
		m_bExistingShip = true;
14 cycrow 234
	else if ( first.Compare("OrgDesc") || first.Compare("OriginalDesc") )
235
		m_iOrgDesc = rest;
236
	else if ( first.Compare("Shipyard") )
237
		m_iShipyard = rest;
238
	else if ( first.Compare("CutData") )
1 cycrow 239
		this->AddCutData(rest);
14 cycrow 240
	else if ( first.Compare("Bodies") )
1 cycrow 241
		this->AddBodies(rest);
14 cycrow 242
	else if ( first.Compare("Animations") )
1 cycrow 243
		this->AddAnimation(rest);
14 cycrow 244
	else if ( first.Compare("Cockpit") )
1 cycrow 245
		this->AddCockpit(rest, 0);
14 cycrow 246
	else if ( first.Compare("CockpitNew") )
1 cycrow 247
	{
14 cycrow 248
		Utils::String cockpit = rest.tokens(" ", 2);
249
		Utils::String sMasks = rest.token(" ", 1);
1 cycrow 250
		this->AddCockpit(cockpit, 0, -1);
14 cycrow 251
		int num = sMasks.token(":", 1);
1 cycrow 252
		for ( int i = 0; i < num; i++ )
253
		{
14 cycrow 254
			int mask = sMasks.token(":", ((i + 1) * 2) + 1);
255
			int game = sMasks.token(":", ((i + 1) * 2));
1 cycrow 256
			this->AddCockpit(cockpit, game, mask);
257
		}
258
	}
259
	else if ( first == "Web" )
260
		m_sWebSite = rest;
261
	else if ( first.Compare("WeaponMask") )
14 cycrow 262
		this->AddWeaponMask(rest.token(" ", 1), rest.token(" ", 2));
1 cycrow 263
	else if ( first.Compare("MissileMask") )
14 cycrow 264
		this->AddMissileMask(rest.token(" ", 1), rest.token(" ", 2));
1 cycrow 265
	else if ( first == "Text" )
266
	{
267
		SText *text = new SText;
14 cycrow 268
		text->iId = rest.token("|", 1);
269
		text->sName = rest.token("|", 2);
270
		text->sName = text->sName.FindReplace("<::PiPe::>", "|");
271
		text->sDesc = rest.tokens( "|", 3);
1 cycrow 272
		m_lText.push_back ( text );
273
	}
274
	else if ( first == "Component" )
275
	{
276
		SComponent *c = new SComponent;
14 cycrow 277
		c->sData = rest.token("|", 1);
1 cycrow 278
		c->sData = c->sData.FindReplace ("<::PiPe::>", "|");
14 cycrow 279
		c->sSection = rest.token("|", 2);
1 cycrow 280
		c->sSection = c->sSection.FindReplace ("<::PiPe::>", "|");
14 cycrow 281
		c->sSection2 = rest.tokens("|", 3);
1 cycrow 282
		m_lComponent.push_back ( c );
283
	}
284
	else if ( first == "Dummy" )
285
	{
286
		SDummy *d = new SDummy;
14 cycrow 287
		d->sData = rest.token("|", 1);
1 cycrow 288
		d->sData = d->sData.FindReplace ("<::PiPe::>", "|");
14 cycrow 289
		d->sSection = rest.tokens( "|", 2);
1 cycrow 290
		m_lDummy.push_back ( d );
291
	}
292
	else if ( first == "Comment" )
14 cycrow 293
		m_sDescription = rest.findReplace("<newline>", "<br>");
1 cycrow 294
	else
14 cycrow 295
		return CBaseFile::ParseValueLine(sLine);
1 cycrow 296
 
297
	return true;
298
}
299
 
300
CyString CXspFile::GetShipName(int lang)
301
{
302
	CyString name;
303
	if ( (m_bLanguageText) && (lang) )
304
	{
305
		for ( SText *text = m_lText.First(); text; text = m_lText.Next() )
306
		{
307
			if ( text->iId == lang )
308
			{
309
				name = text->sName;
310
				break;
311
			}
312
		}
313
	}
314
 
315
	if ( name.Empty() )
316
		name = GetLanguageName(lang);
317
 
318
	return name;
319
}
320
 
321
bool CXspFile::ConvertOld(CyString file)
322
{
323
	// open the file
324
	FILE *id = fopen(file.c_str(), "rb");
325
	if ( !id )
326
		return false;
327
 
328
	// read to memory
329
	fseek(id, 0, SEEK_END);
330
	size_t size = ftell(id);
331
	fseek(id, 0, SEEK_SET);
332
	unsigned char *data = new unsigned char[size + 1];
333
	fread(data, sizeof(unsigned char), size, id);
334
	data[size] = '\0';
335
	fclose(id);
336
 
337
	// uncompress the file
338
	size_t len;
339
	unsigned char *compr = LZMADecode_C ( data, size, &len, NULL );
340
 
341
	delete data;
342
 
343
	if ( !compr )
344
		return false;
345
 
346
	this->Delete();
347
	this->SetDefaults();
348
 
349
	// now read the data line by line
350
	size_t pos = 0;
351
	size_t start = 0;
352
	int packageVersion = 0;
353
	while ( pos < len )
354
	{
355
		while ( compr[pos++] != '\n' && pos < len );
356
 
357
		compr[pos - 1] = '\0';
358
		CyString line = (char *)(compr + start);
359
		start = pos;
360
		if ( line.Empty() )
361
			continue;
362
		CyString first = line.GetToken(":", 1, 1);
363
		CyString rest = line.GetToken(":", 2);
364
		rest = rest.RemoveFirstSpace();
365
 
366
		// now check each line
367
		if ( first.Compare("Packager") )
368
			packageVersion = rest.ToInt();
369
		else if ( first.Compare("Shipyard") )
370
		{
371
			int max;
372
			CyString *strs = rest.SplitToken(";", &max);
373
			if ( strs && max )
374
			{
375
				int cur = 1;
376
				for ( int i = 0; i < max; i++, cur *= 2 )
377
				{
378
					if ( strs[i] == "1" )
379
						this->AddShipyard(cur);
380
				}
381
			}
382
			CLEANSPLIT(strs, max)
383
		}
384
		else if ( first.Compare("ScreenShot") )
385
		{
386
			int size = rest.GetToken(" ", 1, 1).ToInt();
387
			CyString ext = rest.GetToken(" ", 2, 2);
388
 
14 cycrow 389
			C_File *newFile = this->AddFile(CyString(m_sID) + "_" + CyString::Number(this->CountFiles(FILETYPE_SCREEN) + 1) + "." + ext, "", FILETYPE_SCREEN);
1 cycrow 390
			newFile->ReadFromData((char *)(compr + pos), size); 
391
 
392
			start += (size + 1);
393
		}
394
		else if ( first.Compare("SceneFile") )
395
		{
396
			CyString file = rest.GetToken(" ", 3);
397
			m_pSceneFile = this->AddFile(CFileIO(file).GetFilename(), CFileIO(file).GetDir(), FILETYPE_SHIPSCENE);
398
			m_pSceneFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());
399
			m_pSceneFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());
400
 
401
			start += m_pSceneFile->GetDataSize();
402
		}
403
		else if ( first.Compare("CockpitFile") )
404
		{
405
			CyString file = rest.GetToken(" ", 3);
406
			m_pCockpitFile = this->AddFile(CFileIO(file).GetFilename(), CFileIO(file).GetDir(), FILETYPE_COCKPITSCENE);
407
			m_pCockpitFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());
408
			m_pCockpitFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());
409
 
410
			start += m_pCockpitFile->GetDataSize();
411
		}
412
		else if ( first.Compare("Model") )
413
		{
414
			CyString file = rest.GetToken(" ", 3);
415
			C_File *newFile= this->AddFile(CFileIO(file).GetFilename(), CFileIO(file).GetDir(), FILETYPE_SHIPMODEL);
416
			newFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());
417
			newFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());
418
 
419
			start += (newFile->GetDataSize() + 1);
420
		}
421
		else if ( first.Compare("Files") )
422
		{
423
			CyString file = rest.GetToken(" ", 3);
424
 
425
			C_File *newFile = NULL;
426
			int special = 0;
427
			if ( file.Compare("types/CutData.txt") || file.Compare("types/CutData.pck") )
428
			{
429
				newFile = new C_File(file);
430
				special = 1;
431
			}
432
			else if ( file.Compare("types/Bodies.txt") || file.Compare("types/Bodies.pck") )
433
			{
434
				newFile = new C_File(file);
435
				special = 2;
436
			}
437
			else if ( file.Compare("types/Animations.txt") || file.Compare("types/Animations.pck") )
438
			{
439
				newFile = new C_File(file);
440
				special = 3;
441
			}
442
			else
443
			{
444
				newFile = this->AddFile(CFileIO(file).GetFilename(), CFileIO(file).GetDir(), FILETYPE_SHIPOTHER);
445
				newFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());
446
			}
447
			newFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());
448
			start += (newFile->GetDataSize() + 1);
449
 
450
			if ( special )
451
			{
452
				if ( newFile->CheckFileExt("pck") )
453
					newFile->UnPCKFile();
454
 
455
				// read data into lines
456
				CyString data((const char *)newFile->GetData());
457
				data.RemoveChar('\r');
458
				int iLines;
459
				CyString *sLines = data.SplitToken("\n", &iLines);
460
 
461
				if ( sLines && iLines )
462
				{
463
					// cut data
464
					int entries = -1;
465
					if ( special == 1 )
466
					{
467
						CyStringList newLines;
468
						for ( int i = 0; i < iLines; i++ )
469
						{
470
							CyString line = sLines[i];
471
							line.RemoveChar(' ');
472
							line.RemoveChar(9);
473
							if ( line.Empty() || line[0] == '/' )
474
								continue;
475
							if ( entries == -1 )
476
							{
477
								entries	= line.GetToken(";", 1, 1).ToInt() - 36;
478
								if ( entries <= 0 )
479
									break;
480
							}
481
							else
482
							{
483
								int id = line.GetToken(";", 1, 1).ToInt();
484
								if ( id >= 9000 && id <= 9017 )
485
									continue;
486
 
487
								switch (id)
488
								{
489
									case 948:
490
									case 4111:
491
									case 4112:
492
									case 4064:
493
									case 4169:
494
									case 4178:
495
									case 4177:
496
									case 4163:
497
									case 4194:
498
									case 4162:
499
									case 4191:
500
									case 4200:
501
									case 4161:
502
									case 4097:
503
									case 4205:
504
									case 4206:
505
									case 4207:
506
									case 4107:
507
										break;
508
 
509
									default:
510
										newLines.PushBack(line);
511
								}
512
								if ( newLines.Count() == entries )
513
									break;
514
							}
515
						}
516
 
517
						for ( SStringList *strNode = newLines.Head(); strNode; strNode = strNode->next )
518
							this->AddCutData(strNode->str);
519
					}
520
					// bodies
521
					else if ( special == 2 )
522
					{
523
						entries = 0;
524
						CyString section;
525
						for ( int i = 0; i < iLines; i++ )
526
						{
527
							CyString line = sLines[i];
528
							line.RemoveChar(' ');
529
							line.RemoveChar(9);
530
							if ( line.Empty() || line[0] == '/' )
531
								continue;
532
							if ( entries <= 0)
533
							{
534
								section = line.GetToken(";", 1, 1);
535
								entries	= line.GetToken(";", 2, 2).ToInt();
536
							}
537
							else
538
							{
539
								if ( !line.IsIn(";") )
540
									continue;
541
								if ( line.NumToken(";") <= 2 )
542
								{
543
									this->AddBodies(section + ";" + line.GetToken(";", 1, 1) + ";");
544
									--entries;
545
								}
546
								else
547
								{
548
									bool done = false;
549
									while (!done)
550
									{
551
										int num;
552
										CyString *strs = line.SplitToken(";", &num);
553
										done = true;
554
										for ( int j = 0; j < num; j++ )
555
										{
556
											if ( !entries )
557
											{
558
												line = line.GetToken(";", j + 1);
559
												if ( !line.Empty() )
560
													done = false;
561
												break;
562
											}
563
 
564
											if ( strs[j].Empty() )
565
												continue;
566
 
567
											this->AddBodies(section + ";" + strs[j] + ";");
568
											--entries;
569
										}
570
										//we must be at another section
571
										if ( !done )
572
										{
573
											section = line.GetToken(";", 1, 1);
574
											entries	= line.GetToken(";", 2, 2).ToInt();
575
											line = line.RemToken(";", 1);
576
											line = line.RemToken(";", 1);
577
 
578
											if (line.Empty())
579
												done = true;
580
										}
581
 
582
										CLEANSPLIT(strs, num)
583
									}									
584
								}
585
							}
586
						}
587
					}
588
					// animations
589
					else if ( special == 3 )
590
					{
591
						CyStringList in;
592
						for ( int i = 0; i < iLines; i++ )
593
						{
594
							CyString line = sLines[i];
595
							in.PushBack(line);
596
						}
597
 
598
						CyStringList out;
599
						if ( CXspFile::ReadAnimations(&in, &out, 87) )
600
							this->AddAnimation(&out);
601
					}
602
				}
603
				CLEANSPLIT(sLines, iLines)
604
				delete newFile;
605
			}
606
		}
607
		else if ( first.Compare("Script") )
608
		{
609
			CyString file = rest.GetToken(" ", 3);
610
			C_File *newFile= this->AddFile(file, NullString, FILETYPE_SCRIPT);
611
			newFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());
612
			newFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());
613
 
614
			start += (newFile->GetDataSize() + 1);
615
		}
616
		else if ( first.Compare("Text") )
617
			this->AddText(rest.GetToken ( ":", 1, 1 ).ToInt(), rest.GetToken ( ":", 2, 2 ), rest.GetToken ( ":", 3 ));
618
		else if ( first.Compare("Component") )
619
			this->AddComponent(rest.GetToken ( ";", 1, 1 ), rest.GetToken ( ";", 2, 2 ), rest.GetToken ( ";", 3 ));
620
		else if ( first.Compare("Dummy") )
621
		{
622
			SDummy *d = new SDummy;
623
			d->sData = rest.GetToken ( ";", 2 );
624
			d->sSection = rest.GetToken ( ";", 1, 1 );
625
			m_lDummy.push_back ( d );
626
		}
14 cycrow 627
		else if ( !this->ParseValueLine(line.ToString()) )
1 cycrow 628
		{
629
		//	printf ( "Command: %s, Rest: %s\n", first.c_str(), rest.c_str());
630
		}
631
 
632
		pos = start;
633
	}
634
 
635
	// assume all old ones are for X3
14 cycrow 636
	if ( !m_sData.empty() )
1 cycrow 637
	{
14 cycrow 638
		this->AddWeaponMask(GAME_X3 - 1, m_sData.token(";", 19));
639
		this->AddMissileMask(GAME_X3 - 1, m_sData.token(";", 25));
1 cycrow 640
	}
641
 
642
	return true;
643
}
644
 
645
 
646
int GetMaxShipyards() { return (int)SHIPYARD_MAX; }
647
 
648
CyString GetShipyardName (int s)
649
{
650
	switch (s)
651
	{
652
		case SHIPYARD_ARGON:
653
			return "Argon";
654
		case SHIPYARD_BORON:
655
			return "Boron";
656
		case SHIPYARD_PARANID:
657
			return "Paranid";
658
		case SHIPYARD_SPLIT:
659
			return "Split";
660
		case SHIPYARD_TELADI:
661
			return "Teladi";
662
		case SHIPYARD_PIRATES:
663
			return "Pirates";
664
		case SHIPYARD_FRIEND:
665
			return "Friendly";
666
		case SHIPYARD_XENON:
667
			return "Xenon";
668
		case SHIPYARD_TERRAN:
669
			return "Terran";
670
	}
671
 
672
	return "Unknown";
673
}
674
 
675
bool CXspFile::WriteHeader(FILE *id, int valueheader, int valueComprLen)
676
{
677
	fprintf ( id, "XSPCycrow;%.2f;%d;%d\n", FILEVERSION, valueheader, valueComprLen );
678
	if ( ferror(id) )
679
		return false;
680
	return true;
681
}
682
 
14 cycrow 683
bool CXspFile::CheckHeader(const Utils::String header) const
1 cycrow 684
{
685
	if ( header.Compare("XSPCycrow") )
686
		return true;
687
	return false;
688
}
689
 
690
void CXspFile::SetLaserMask(int game, int mask)
691
{
692
	for ( CListNode<SWeaponMask> *node = m_lWeaponMasks.Front(); node; node = node->next() )
693
	{
694
		SWeaponMask *m = node->Data();
695
		if ( m->iGame == game )
696
		{
697
			m->iMask = mask;
698
			return;
699
		}
700
	}
701
 
702
	// no found, need to add it
703
	this->AddWeaponMask(game, mask);
704
}
705
 
706
void CXspFile::SetMissileMask(int game, int mask)
707
{
708
	for ( CListNode<SWeaponMask> *node = m_lMissileMasks.Front(); node; node = node->next() )
709
	{
710
		SWeaponMask *m = node->Data();
711
		if ( m->iGame == game )
712
		{
713
			m->iMask = mask;
714
			return;
715
		}
716
	}
717
 
718
	// no found, need to add it
719
	this->AddMissileMask(game, mask);
720
}
721
int CXspFile::GetLaserMask(int game, bool getOnly)
722
{
723
	int mask = -1;
724
	for ( CListNode<SWeaponMask> *node = m_lWeaponMasks.Front(); node; node = node->next() )
725
	{
726
		SWeaponMask *m = node->Data();
727
		if ( m->iGame == game )
728
			return m->iMask;
729
 
730
		if ( !mask && !getOnly )
731
			mask = m->iMask;
732
	}
733
 
734
	return mask;
735
}
736
 
737
int CXspFile::GetMissileMask(int game, bool getOnly)
738
{
739
	int mask = -1;
740
	for ( CListNode<SWeaponMask> *node = m_lMissileMasks.Front(); node; node = node->next() )
741
	{
742
		SWeaponMask *m = node->Data();
743
		if ( m->iGame == game )
744
			return m->iMask;
745
 
746
		if ( !mask && !getOnly )
747
			mask = m->iMask;
748
	}
749
 
750
	return mask;
751
}
752
 
753
CyString CXspFile::GetShipClass()
754
{
14 cycrow 755
	if ( !m_sData.empty() )
756
		return m_sData.token(";", TSHIPPOS_CLASS);
1 cycrow 757
	return "OBJ_SHIP_M5";
758
}
759
 
760
bool CXspFile::GeneratePackagerScript(bool wildcard, CyStringList *list, bool datafile)
761
{
762
	if ( !CBaseFile::GeneratePackagerScript(wildcard, list, datafile) )
763
		return false;
764
 
765
	if ( m_iShipyard )
766
	{
767
		list->PushBack("# Shipyards, Set which shipyards to add ships for sale to");
768
		for ( int i = SHIPYARD_ARGON; i <= SHIPYARD_MAX; i *= 2 )
769
		{
770
			if ( this->IsShipyard(i) )
771
				list->PushBack(CyString("Shipyard: ") + GetShipyardName(i));
772
		}
773
		list->PushBack("");
774
	}
775
 
776
	if ( m_iOrgDesc > 0 )
777
	{
778
		list->PushBack("# Use Original Description, overrides text entrys to use one of the built in text");
779
		list->PushBack(CyString("OriginalDescription: ") + (long)m_iOrgDesc);
780
		list->PushBack("");
781
	}
782
 
14 cycrow 783
	if ( !m_sID.empty() )
1 cycrow 784
	{
785
		list->PushBack("# Ship ID, the ship id to identify the ship as");
786
		list->PushBack(CyString("ShipID: ") + m_sID);
787
	}
788
 
14 cycrow 789
	if ( !m_sData.empty() )
1 cycrow 790
	{
791
		list->PushBack("# Ship Data, the TShip data entry to add to the game (parts of this are adjusted and auto generated by the installer)");
792
		list->PushBack(CyString("ShipData: ") + m_sData);
793
		list->PushBack("");
794
	}
795
 
796
	if ( m_bExistingShip )
797
	{
798
		list->PushBack("# Existing Ship, replaces an existing ship in the game with ship package instead of creating a new entry");
799
		list->PushBack("ExistingShip");
800
		list->PushBack("");
801
	}
802
 
803
	if ( !datafile )
804
	{
805
		if ( !CBaseFile::GeneratePackagerScriptFile(wildcard, list) )
806
			return false;
807
	}
808
 
809
	return true;
810
}
811
 
14 cycrow 812
bool CXspFile::LoadPackageData(const Utils::String &sFirst, const Utils::String &sRest)
1 cycrow 813
{
14 cycrow 814
	if ( sFirst.Compare("Shipyard") )
1 cycrow 815
	{
816
		for ( int i = SHIPYARD_ARGON; i <= SHIPYARD_MAX; i *= 2 )
817
		{
14 cycrow 818
			if ( sRest.Compare(GetShipyardName(i).ToString()) )
1 cycrow 819
			{
820
				this->AddShipyard(i);
821
				break;
822
			}
823
		}
824
	}
14 cycrow 825
	else if ( sFirst.Compare("OriginalDescription") )
826
		m_iOrgDesc = sRest;
827
	else if ( sFirst.Compare("ShipData") )
828
		m_sData = sRest;
829
	else if ( sFirst.Compare("ReadData") ) // read data from a tships file
1 cycrow 830
	{
831
		CPackages p;
14 cycrow 832
		m_sData = p.ReadShipData(sRest.tokens(" ", 2), sRest.token(" ", 1)).ToString();
1 cycrow 833
	}
14 cycrow 834
	else if ( sFirst.Compare("ExistingShip") )
1 cycrow 835
		m_bExistingShip = true;
14 cycrow 836
	else if ( sFirst.Compare("ShipID") )
837
		m_sID = sRest;
838
	else if ( !CBaseFile::LoadPackageData(sFirst, sRest) )
1 cycrow 839
	{
840
		return false;
841
	}
842
 
843
	return true;
844
}
845
 
846
 
847
CyString CXspFile::GetX3ShipData()
848
{
849
	CyString data = m_sData;
850
 
851
	// change the ship subtype, Reunion uses number, TC uses a define
852
	CyString sSubType = data.GetToken(";", 6, 6);
853
	if ( !sSubType.ToInt() && sSubType != "0" )
854
		data = data.RepToken(";", 6, CyString::Number(CShipData::ConvertShipSubType(sSubType)));
855
 
856
	CyString sClass = data.GetToken(";", TSHIPPOS_CLASS, TSHIPPOS_CLASS);
857
	if ( !sClass.ToInt() && sClass != "0" )
858
	{
859
		int num = 0;
860
		for ( int i = 0; i < OBJ_SHIP_MAX; i++ )
861
		{
862
			if ( sClass.Compare(CShipData::ConvertShipClass(CShipData::GetShipClassFromNum(i))) )
863
			{
864
				num = i;
865
				break;
866
			}
867
		}
868
 
869
		data = data.RepToken(";", TSHIPPOS_CLASS, CyString::Number(num));
870
	}
871
 
872
	return data;
873
}
874
 
875
CyString CXspFile::GetTCShipData()
876
{
877
	CyString data = m_sData;
878
 
879
	CyString sSubType = data.GetToken(";", 6, 6);
880
	if ( sSubType.ToInt() || sSubType == "0" )
881
		data = data.RepToken(";", 6, CShipData::ConvertShipSubType(sSubType.ToInt()));
882
 
883
	CyString sClass = data.GetToken(";", TSHIPPOS_CLASS, TSHIPPOS_CLASS);
884
	if ( sClass.ToInt() || sClass == "0" )
885
		data = data.RepToken(";", TSHIPPOS_CLASS, CShipData::ConvertShipClass(sClass.ToInt()));
886
 
887
	return data;
888
}
889
 
890
bool CXspFile::RemoveCockpit(CyString cockpitid)
891
{
892
	// if its a whole line, just get the end
893
	if ( cockpitid.IsIn(";") )
894
	{
895
		cockpitid = cockpitid.GetToken(";", -2);
896
		while ( cockpitid.Right(1) == ";" )
897
			cockpitid.Truncate((int)cockpitid.Length() - 1);
898
	}
899
 
900
	bool ret = false;
901
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
902
	{
903
		CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);
904
		if ( id.Compare(cockpitid) )
905
		{
906
			node->DeleteData();
907
			ret = true;
908
			break;
909
		}
910
	}
911
 
912
	m_lCockpit.RemoveEmpty();
913
 
914
	return ret;
915
}
916
 
917
bool CXspFile::RemoveComponent(CyString section1, CyString section2, CyString data)
918
{
919
	bool ret = false;
920
	for ( CListNode<SComponent> *node = m_lComponent.Front(); node; node = node->next() )
921
	{
922
		if ( node->Data()->sSection.Compare(section1) && node->Data()->sSection2.Compare(section2) && node->Data()->sData.Compare(data) )
923
		{
924
			ret = true;
925
			node->DeleteData();
926
			break;
927
		}
928
	}
929
	m_lComponent.RemoveEmpty();
930
	return ret;
931
}
932
 
933
bool CXspFile::RemoveDummy(CyString section, CyString data)
934
{
935
	bool ret = false;
936
	for ( CListNode<SDummy> *node = m_lDummy.Front(); node; node = node->next() )
937
	{
938
		if ( node->Data()->sSection.Compare(section) && node->Data()->sData.Compare(data) )
939
		{
940
			ret = true;
941
			node->DeleteData();
942
			break;
943
		}
944
	}
945
	m_lDummy.RemoveEmpty();
946
 
947
	return ret;
948
}
949
 
950
CyString CXspFile::GetCockpitData(CyString cid)
951
{
952
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
953
	{
954
		CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);
955
		if ( id.Compare(cid) )
956
			return node->Data()->sCockpit;
957
	}
958
 
959
	return NullString;
960
}
961
 
962
SCockpit *CXspFile::FindCockpit(CyString cid)
963
{
964
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
965
	{
966
		CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);
967
		if ( id.Compare(cid) )
968
			return node->Data();
969
	}
970
 
971
	return NULL;
972
}
973
 
974
void CXspFile::EditCockpit(CyString cid, CyString cockpit)
975
{
976
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
977
	{
978
		CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);
979
		if ( id.Compare(cid) )
980
		{
981
			node->Data()->sCockpit = cockpit;
982
			break;
983
		}
984
	}
985
}
986
 
987
void CXspFile::EditCockpit(CyString cid, CyString scene, int mask)
988
{
989
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
990
	{
991
		CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);
992
		if ( id.Compare(cid) )
993
		{
994
			CyString cockpit = node->Data()->sCockpit;
995
			cockpit = cockpit.RepToken(";", 8, scene);
996
			cockpit = cockpit.RepToken(";", 9, CyString::Number(mask));
997
			node->Data()->sCockpit = cockpit;
998
			break;
999
		}
1000
	}
1001
}
1002
void CXspFile::NewCockpit(CyString id, CyString scene, int mask)
1003
{
1004
	CyString cockpit = "0;0;0;0;0;0;0;";
1005
	cockpit += scene + ";";
1006
	cockpit += CyString::Number(mask);
1007
	cockpit += ";0;0;0;0;0;0;-100000;0;0;";
1008
	cockpit += id + ";";
1009
	this->AddCockpit(cockpit, -1);
1010
}
1011
 
1012
bool CXspFile::RemoveCutData(CyString cut)
1013
{
1014
	bool ret = false;
1015
	for ( SStringList *str = m_lCutData.Head(); str; str = str->next )
1016
	{
1017
		if ( str->str.GetToken(";", 1, 1).Compare(cut.GetToken(";", 1, 1)) )
1018
		{
1019
			ret = true;
1020
			str->remove = true;
1021
			break;
1022
		}
1023
	}
1024
 
1025
	m_lCutData.RemoveMarked();
1026
 
1027
	return ret;
1028
}
1029
 
1030
bool CXspFile::RemoveBodies(CyString cut)
1031
{
1032
	bool ret = false;
1033
	for ( SStringList *str = m_lBodies.Head(); str; str = str->next )
1034
	{
1035
		if ( str->str.Remove(' ').Compare(cut.Remove(' ')) )
1036
		{
1037
			ret = true;
1038
			str->remove = true;
1039
			break;
1040
		}
1041
	}
1042
 
1043
	m_lBodies.RemoveMarked();
1044
 
1045
	return ret;
1046
}
1047
 
1048
bool CXspFile::RemoveAnimation(CyString cut)
1049
{
1050
	bool ret = false;
1051
	for ( SStringList *str = m_lAnimations.Head(); str; str = str->next )
1052
	{
1053
		if ( str->str.Remove(' ').Remove('\n').Compare(cut.Remove(' ').Remove('\n')) )
1054
		{
1055
			ret = true;
1056
			str->remove = true;
1057
			break;
1058
		}
1059
	}
1060
 
1061
	m_lAnimations.RemoveMarked();
1062
 
1063
	return ret;
1064
}
1065
 
1066
void CXspFile::AddCockpit(CyString cockpit, int game, int mask, int index)
1067
{
1068
	SCockpit *pCockpit = NULL;
1069
 
1070
	// first search for the cockpit entry
1071
	CyString cid = cockpit.GetToken(";", 19, 19);
1072
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
1073
	{
1074
		CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);
1075
		if ( id.Compare(cid) )
1076
		{
1077
			pCockpit = node->Data();
1078
			break;
1079
		}
1080
	}
1081
 
1082
	if ( !pCockpit )
1083
	{
1084
		pCockpit = new SCockpit;
1085
		pCockpit->sCockpit = cockpit;
1086
		pCockpit->iIndex = index;
1087
		m_lCockpit.push_back(pCockpit);
1088
	}
1089
	if ( index != -1 )
1090
		pCockpit->iIndex = index;
1091
 
1092
	// now add the game mask
1093
	if ( game > 0 )
1094
	{
1095
		// search if the game mask already exists
1096
		SWeaponMask *wm = NULL;
1097
		for ( CListNode<SWeaponMask> *node = pCockpit->lWeaponMask.Front(); node; node = node->next() )
1098
		{
1099
			if ( node->Data()->iGame == game )
1100
			{
1101
				wm = node->Data();
1102
				break;
1103
			}
1104
		}
1105
 
1106
		if ( !wm )
1107
		{
1108
			wm = new SWeaponMask;
1109
			pCockpit->lWeaponMask.push_back(wm);
1110
		}
1111
 
1112
		wm->iGame = game;
1113
		if ( mask == -1 )
1114
			wm->iMask = cockpit.GetToken(";", 9, 9).ToInt();
1115
		else
1116
			wm->iMask = mask;
1117
	}
1118
	m_bChanged = true; 
1119
}
1120
 
1121
void CXspFile::AddBody(CyString section, CyString data)
1122
{
1123
	this->AddBodies(section + ";" + data);
1124
	m_bChanged = true; 
1125
}
1126
void CXspFile::AddBodies(CyString data)
1127
{
1128
	if ( !data.IsNumber() )
1129
	{
1130
		if ( data[(int)(data.Length() - 5)] == '.' )
1131
			data = data.Left(-5);
1132
		else if ( data[(int)(data.Length() - 4)] == '.' )
1133
			data = data.Left(-4);
1134
		if ( data.Right(1) != ";" )
1135
			data += ";";
1136
	}
1137
	m_lBodies.PushBack(data, true);
1138
	m_bChanged = true; 
1139
}
1140
 
1141
int CXspFile::GetAnimationType(CyString type)
1142
{
1143
	if ( type.Compare("TAT_TAGSINGLESTEP") )
1144
		return TAT_SINGLE;
1145
	else if ( type.Compare("TAT_TAGONESHOT") 
1146
				|| type.Compare("TAT_TAGONESHOT_REINIT") 
1147
				|| type.Compare("TAT_PINGPONG")
1148
				|| type.Compare("TAT_TAGLOOP") )
1149
		return TAT_3;
1150
 
1151
	return TAT_NONE;
1152
}
1153
 
1154
bool CXspFile::ReadAnimations(CyStringList *lIn, CyStringList *lOut, int startRecord)
1155
{
1156
	CyString lastComment;
1157
	CyString addEntry;
1158
	int remaining = 0;
1159
	CyString lastType;
1160
	int newEntries = 0;
1161
	int entries = -1;
1162
	for ( SStringList *strNode = lIn->Head(); strNode; strNode = strNode->next )
1163
	{
1164
		CyString line = strNode->str;
1165
		line.RemoveChar('\r');
1166
		line.RemoveChar(9);
1167
		if ( line.Empty() || line[0] == '/' )
1168
			continue;
1169
		if ( entries == -1)
1170
		{
1171
			entries	= line.GetToken(";", 1, 1).ToInt();
1172
			newEntries = entries - startRecord;
1173
		}
1174
		else
1175
		{
1176
			// remove comments, endspaces and last ;
1177
			CyString sStriped = line;
1178
			if ( sStriped.IsIn("//") )
1179
			{
1180
				if ( entries <= newEntries )
1181
					lastComment = CyString("//") + sStriped.GetToken("//", 2);
1182
				sStriped = sStriped.GetToken("//", 1, 1);
1183
			}
1184
			sStriped.RemoveEndSpace();
1185
			if ( sStriped.Right(1) == ";" )
1186
				sStriped.Truncate(-1);
1187
 
1188
			CyString sRemainingLeft;
1189
			if ( remaining > 0 )
1190
				sRemainingLeft = sStriped;
1191
			else
1192
			{
1193
				// each line should be a new entry, with some exceptions
1194
				// potection for new lines
1195
				lastType = sStriped.GetToken(";", 1, 1);
1196
 
1197
				switch (CXspFile::GetAnimationType(lastType))
1198
				{
1199
					case TAT_SINGLE:
1200
						remaining = sStriped.GetToken(";", 5, 5).ToInt() + 1;
1201
						sRemainingLeft = sStriped.GetToken(";", 6);
1202
						if ( entries <= newEntries )
1203
							addEntry = sStriped.GetToken(";", 1, 5) + ";";
1204
						break;
1205
					case TAT_3:
1206
						remaining = sStriped.GetToken(";", 5, 5).ToInt() + 1;
1207
						sRemainingLeft = sStriped.GetToken(";", 6);
1208
						if ( entries <= newEntries )
1209
							addEntry = sStriped.GetToken(";", 1, 5) + ";";
1210
						break;
1211
 
1212
					default:
1213
						remaining = 0;
1214
						if ( entries <= newEntries )
1215
							addEntry = sStriped;
1216
 
1217
				}
1218
			}
1219
 
1220
			if ( !sRemainingLeft.Empty() )
1221
			{
1222
				int tatType = CXspFile::GetAnimationType(lastType);
1223
				if ( tatType == TAT_SINGLE )
1224
				{
1225
					if ( sRemainingLeft.IsIn(";") )
1226
						remaining -= sRemainingLeft.NumToken(";");
1227
					else if ( !sRemainingLeft.Empty() )
1228
						--remaining;
1229
 
1230
					if ( entries <= newEntries )
1231
						addEntry += sRemainingLeft + ";";
1232
				}
1233
				else if ( tatType == TAT_3 )
1234
				{
1235
					// last entry
1236
					if ( remaining == 1 )
1237
						--remaining;
1238
					else if ( sRemainingLeft.IsIn(";") )
1239
					{
1240
						if ( !sRemainingLeft.IsIn("TATF_COORDS") )
1241
						{
1242
							int amt = sRemainingLeft.NumToken(";") / 3;
1243
							remaining -= amt;
1244
							if ( remaining == 1 && (sRemainingLeft.NumToken(";") - (amt * 3)) == 1 )
1245
								--remaining;
1246
						}
1247
						else
1248
						{
1249
							int iRem = sRemainingLeft.NumToken(";");
1250
							int iPos = 1;
1251
							while ( iPos < iRem )
1252
							{
1253
								CyString first = sRemainingLeft.GetToken(";", iPos, iPos);
1254
								if ( first.IsIn("TATF_COORDS") )
1255
									iPos += 5;
1256
								else
1257
									iPos += 3;
1258
								--remaining;
1259
							}
1260
 
1261
							if ( remaining == 1 && iPos == iRem )
1262
								--remaining;
1263
						}
1264
					}
1265
 
1266
					if ( entries <= newEntries )
1267
						addEntry += sRemainingLeft + ";";
1268
				}
1269
			}
1270
 
1271
			if ( remaining <= 0 )
1272
			{
1273
				if ( entries <= newEntries && !addEntry.Empty())
1274
				{
1275
					if ( addEntry[(int)addEntry.Length() - 1] != ';' )
1276
						addEntry += ";";
1277
					lOut->PushBack(addEntry + lastComment);
1278
				}
1279
				--entries;
1280
			}
1281
		}
1282
	}
1283
 
1284
	return !lOut->Empty();
1285
}
1286
 
1287
void CXspFile::AddAnimation(CyStringList *list)
1288
{
1289
	for ( SStringList *strNode = list->Head(); strNode; strNode = strNode->next )
1290
		this->AddAnimation(strNode->str);
1291
	m_bChanged = true; 
1292
}
1293
 
1294
SText *CXspFile::FindShipText(int lang)
1295
{
1296
	if ( m_lText.empty() )
1297
		return NULL;
1298
 
1299
	SText *english = NULL;
1300
	SText *german = NULL;
1301
	SText *found = NULL;
1302
	for ( CListNode<SText> *node = m_lText.Front(); node; node = node->next() )
1303
	{
1304
		SText *text = node->Data();
1305
		// matched language
1306
		if ( text->iId == lang )
1307
			return text;
1308
		else if ( text->iId == 44 )
1309
			english = text;
1310
		else if ( text->iId == 49 )
1311
			german = text;
1312
		else if ( !found )
1313
			found = text;
1314
	}
1315
 
1316
	// if we've found an english version, use that
1317
	if ( english )
1318
		return english;
1319
	// otherwise try a german
1320
	if ( german )
1321
		return german;
1322
	// otherwise use any we've found (usually first one)
1323
	return found;
1324
}
1325
 
1326
CyString CXspFile::GetTextName(int lang)
1327
{
1328
	SText *t = FindShipText(lang);
1329
	if ( t )
1330
	{
1331
		// return the correct language text
1332
		if ( !t->sName.Empty() )
1333
			return t->sName;
1334
		// we have found a text, but there is no ship name ??
1335
		else if ( lang != 44 )
1336
		{
1337
			// reget the english one
1338
			t = FindShipText(44);
1339
			if ( t && !t->sName.Empty() )
1340
				return t->sName;
1341
		}
1342
	}
1343
 
1344
	// still not found one, return the ships name
1345
	return this->GetShipName(lang);
1346
}
1347
 
1348
CyString CXspFile::GetTextDescription(int lang)
1349
{
1350
	SText *t = FindShipText(lang);
1351
	if ( t )
1352
	{
1353
		// return the correct language text
1354
		if ( !t->sDesc.Empty() )
1355
			return t->sDesc;
1356
		// we have found a text, but there is no ship name ??
1357
		else if ( lang != 44 )
1358
		{
1359
			// reget the english one
1360
			t = FindShipText(44);
1361
			if ( t && !t->sDesc.Empty() )
1362
				return t->sDesc;
1363
		}
1364
	}
1365
 
1366
	// still not found one, return the ships name
1367
	if ( !m_sDescription.Empty() )
1368
		return m_sDescription;
1369
	return this->GetShipName(lang);
1370
}
1371
 
35 cycrow 1372
bool CXspFile::startExtractShip(CVirtualFileSystem *pVfs, const Utils::String &sId, CProgressInfo *pProgress)
1 cycrow 1373
{
35 cycrow 1374
	m_sID = sId.removeChar('\r');
1375
	while ( m_sID.right(1) == ";" )
1376
		m_sID.truncate(-1);
1 cycrow 1377
 
35 cycrow 1378
	m_sData = pVfs->getTShipsEntry(m_sID);
1379
 
1 cycrow 1380
	// get scene files
35 cycrow 1381
	if ( pProgress ) pProgress->UpdateStatus(IMPORTSHIP_SCENE);
1382
	if ( !this->extractSceneFiles(pVfs) )
1 cycrow 1383
		return false;
1384
 
1385
	return true;
1386
}
1387
 
35 cycrow 1388
bool CXspFile::extractShip(CVirtualFileSystem *pVfs, const Utils::String &sId, CProgressInfo *progress)
1 cycrow 1389
{
35 cycrow 1390
	if ( !this->startExtractShip(pVfs, sId, progress) )
1 cycrow 1391
		return false;
1392
 
1393
	// read the scene file and get the files list
35 cycrow 1394
	if ( !this->processSceneFiles(pVfs, progress) )
1 cycrow 1395
		return false;
1396
 
1397
	// pack all the ship files
1398
	this->PackAllFiles();
1399
 
1400
	return true;
1401
}
1402
 
35 cycrow 1403
bool CXspFile::extractSceneFiles(CVirtualFileSystem *pVfs)
1 cycrow 1404
{
35 cycrow 1405
	m_pSceneFile = pVfs->extractGameFileToPackage(this, "objects\\" + m_sData.token(";", 17) + ".pbd", FILETYPE_SHIPSCENE, "objects\\" + m_sData.token(";", 17) + ".bod");
1406
	if ( !m_pSceneFile ) return false;
1407
	m_pCockpitFile = pVfs->extractGameFileToPackage(this, "objects\\" + m_sData.token(";", 18) + ".pbd", FILETYPE_COCKPITSCENE, "objects\\" + m_sData.token(";", 18) + ".bod");
1 cycrow 1408
 
1409
	return true;
1410
}
1411
 
1412
CyStringList *CXspFile::ReadSceneModels()
1413
{
1414
	// read the scene file
1415
	if ( !m_pSceneFile )
1416
		m_pSceneFile = this->GetFirstFile(FILETYPE_SHIPSCENE);
1417
 
1418
	if ( !m_pSceneFile )
1419
		return NULL;
1420
 
1421
	// check if its packed
1422
	size_t datasize;
1423
	unsigned char *data = m_pSceneFile->UncompressData((long *)&datasize, 0);
1424
 
1425
	// if data wasn't compressed, then copy it itself as we are editing it
1426
	bool deleteData = false;
1427
	if ( data == m_pSceneFile->GetData() )
1428
	{
1429
		data = new unsigned char[m_pSceneFile->GetDataSize()];
1430
		memcpy(data, m_pSceneFile->GetData(), m_pSceneFile->GetDataSize());
1431
		deleteData = true;
1432
	}
1433
 
1434
	if ( data && datasize )
1435
	{
1436
		if ( m_pSceneFile->CheckPackedExtension() )
1437
			data = UnPCKData(data, datasize, &datasize);
1438
	}
1439
 
1440
	if ( !data || !datasize )
1441
		return NULL;
1442
 
1443
	CyStringList *lModels = new CyStringList;
1444
 
1445
	size_t pos = 0;
1446
	bool newline = true;
1447
	bool online = false;
1448
	while ( pos < datasize )
1449
	{
1450
		char c = data[pos];
1451
		++pos;
1452
 
1453
		// skip until next line
1454
		if ( !newline && !online )
1455
		{
1456
			if ( c == '\n' )
1457
				newline = true;
1458
			continue;
1459
		}
1460
 
1461
		if ( newline )
1462
		{
1463
			if ( c == ' ' || c == 9 || c == '\n' || c == '\r' )
1464
				continue;
1465
 
1466
			newline = false;
1467
 
1468
			if ( c == 'P' || c == 'p' )
1469
			{
1470
				while ( data[pos] == ' ' ) pos++;
1471
				unsigned char *line = (data + pos);
1472
				while ( data[pos] != ' ' && data[pos] != ';' ) pos++;
1473
				data[pos] = '\0';
1474
				if ( atoi((const char *)line) == lModels->Count() )
1475
					online = true;
1476
			}
1477
		}
1478
		// this line is out model
1479
		else if ( online )
1480
		{
1481
			if ( c == 'B' || c == 'b' )
1482
			{
1483
				while(data[pos] == ' ') pos++;
1484
				unsigned char *line = (data + pos);
1485
				while(data[pos] != ';') pos++;
1486
				data[pos] = '\0';
1487
 
1488
				lModels->PushBack((char *)line);
1489
				online = false;
1490
			}
1491
		}
1492
	}
1493
 
1494
	if ( deleteData )
1495
		delete data;
1496
 
1497
	return lModels;
1498
}
1499
 
35 cycrow 1500
void CXspFile::extractDummies(CVirtualFileSystem *pVfs, CyStringList *sceneModels, bool add)
1 cycrow 1501
{
1502
	if ( !sceneModels ) return;
31 cycrow 1503
 
1504
	bool extracted = false;
35 cycrow 1505
	if ( pVfs->ExtractGameFile("types/dummies.pck", "tmp") ) {
1 cycrow 1506
		CFileIO File("tmp");
1507
		if ( File.Exists() )
1508
		{
1509
			CyString section;
1510
			int secCount = 0;
1511
			CyStringList *lines = File.ReadLinesStr();
1512
			for ( SStringList *node = lines->Head(); node; node = node->next )
1513
			{
1514
				node->str.RemoveFirstSpace();
1515
				node->str.RemoveChar(9);
1516
				node->str.RemoveChar('\r');
1517
				if ( node->str.Empty() )
1518
					continue;
1519
				if ( node->str[0] == '/' )
1520
					continue;
1521
 
1522
				// not in a section yet
1523
				if ( secCount <= 0 )
1524
				{
1525
					section = node->str.GetToken(";", 1, 1);
1526
					secCount = node->str.GetToken(";", 2, 2).ToInt();
1527
				}
1528
				else
1529
				{
1530
					CyString first = node->str.GetToken(";", 1, 1);
1531
					if ( sceneModels->FindString(first) )
1532
					{
1533
						this->AddDummy(section, node->str);
1534
 
1535
						if ( add )
1536
						{
1537
							int pos = 4;
1538
							int scene = node->str.GetToken(";", 3, 3).ToInt();
1539
							for ( int i = 0; i < scene; i++ )
1540
							{
1541
								sceneModels->PushBack(node->str.GetToken(";", 5 + (i * 2), 5 + (i * 2)));
1542
								pos += 2;
1543
							}
1544
 
1545
							int model = node->str.GetToken(";", pos, pos).ToInt();
1546
							for ( int i = 0; i < model; i++ )
1547
								sceneModels->PushBack(node->str.GetToken(";", pos + (i * 2) + 1, pos + (i * 2) + 1));
1548
						}
1549
					}
1550
					--secCount;
1551
 
1552
				}
1553
			}
1554
 
1555
			delete lines;
1556
			File.Remove();
1557
		}
1558
	}
1559
}
1560
 
35 cycrow 1561
void CXspFile::extractComponants(CVirtualFileSystem *pVfs, CyStringList *sceneModels)
1 cycrow 1562
{
1563
	if ( !sceneModels ) return;
35 cycrow 1564
	if ( pVfs->ExtractGameFile("types/components.pck", "tmp") )
1 cycrow 1565
	{
1566
		CFileIO File("tmp");
1567
		if ( File.Exists() )
1568
		{
1569
			CyString file;
1570
			CyString section;
1571
			int secCount = 0;
1572
			int secCount2 = 0;
1573
			CyStringList *lines = File.ReadLinesStr();
1574
			for ( SStringList *node = lines->Head(); node; node = node->next )
1575
			{
1576
				node->str.RemoveFirstSpace();
1577
				node->str.RemoveChar(9);
1578
				node->str.RemoveChar('\r');
1579
				if ( node->str.Empty() )
1580
					continue;
1581
				if ( node->str[0] == '/' )
1582
					continue;
1583
 
1584
				// not in a section yet
1585
				if ( secCount2 )
1586
				{
1587
					if ( sceneModels->FindString(file) )
1588
						this->AddComponent(section, file, node->str);
1589
					--secCount2;
1590
				}
1591
				else if ( secCount <= 0 )
1592
				{
1593
					section = node->str.GetToken(";", 1, 1);
1594
					secCount = node->str.GetToken(";", 2, 2).ToInt();
1595
				}
1596
				else
1597
				{
1598
					file = node->str.GetToken(";", 1, 1);
1599
					secCount2 = node->str.GetToken(";", 2, 2).ToInt();
1600
					--secCount;
1601
				}
1602
			}
1603
 
1604
			delete lines;
1605
			File.Remove();
1606
		}
1607
	}
1608
}
1609
 
1610
bool CXspFile::GetTextureList(CyStringList *list, const unsigned char *olddata, size_t size)
1611
{
1612
	if ( !olddata || !size )
1613
		return false;
1614
 
1615
	size_t startLine = 0;
1616
	CyString line;
1617
	size_t pos = 0;
1618
 
1619
	unsigned char *data = new unsigned char[size];
1620
	memcpy(data, olddata, size);
1621
 
1622
	while ( (pos++) < size )
1623
	{
1624
		if ( data[pos] == '\n' )
1625
		{
1626
			data[pos] = '\0';
1627
			line = (char *)(data + startLine);
1628
			line.RemoveChar(9);
1629
			line.RemoveChar('\r');
1630
			line.RemoveFirstSpace();
1631
 
1632
			if ( !line.Empty() && line[0] != '/' )
1633
			{
1634
				CyString first = line.GetToken(":", 1, 1);
1635
				if ( first.Compare("MATERIAL6") )
1636
				{
1637
					int max;
1638
					CyString *strs = line.GetToken(":", 2).SplitToken("; ", &max);
1639
 
1640
					if ( strs && max >= 2)
1641
					{
1642
						for ( int i = 2; i < max; i++ )
1643
						{
1644
							CyString s = strs[i];
1645
							if ( s.IsIn(";") )
1646
								s = s.GetToken(";", 1, 1);
1647
							if ( !s.IsNumber() && !s.Compare("NULL") && s.IsIn(".") )
1648
								list->PushBack(s, "", true);
1649
						}
1650
					}
1651
 
1652
					CLEANSPLIT(strs, max)
1653
				}
1654
			}
1655
 
1656
			startLine = pos + 1;
1657
		}
1658
	}
1659
 
1660
	delete [] data;
1661
 
1662
	return true;
1663
}
1664
 
35 cycrow 1665
void CXspFile::extractTextures(CVirtualFileSystem *pVfs)
1 cycrow 1666
{
1667
	CyStringList lTextures;
1668
 
1669
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
1670
	{
1671
		C_File *f = node->Data();
1672
		if ( f->GetFileType() != FILETYPE_SHIPMODEL )
1673
			continue;
1674
 
1675
		// cant do these yet
1676
		if ( f->CheckFileExt("pbb") || f->CheckFileExt("bob") )
1677
		{
1678
			if ( !f->BobDecompile() )
1679
				continue;
1680
		}
1681
 
1682
		if ( !f->GetData() )
1683
		{
1684
			if ( !f->ReadFromFile() )
1685
				continue;
1686
		}
1687
 
1688
		unsigned char *data = NULL;
1689
		size_t size;
1690
 
1691
		if ( f->CheckFileExt("pbb") || f->CheckFileExt("pbd") )
1692
			data = f->UnPCKFile(&size);
1693
		else
1694
		{
1695
			data = f->GetData();
1696
			size = f->GetDataSize();
1697
		}
1698
 
1699
		this->GetTextureList(&lTextures, data, size);
1700
	}
1701
 
1702
	for ( SStringList *node = lTextures.Head(); node; node = node->next )
1703
	{
35 cycrow 1704
		if ( CFileIO(node->str).CheckFileExtension("dds") )
1705
			pVfs->extractGameFileToPackage(this, "dds\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER);
1706
		else 
1707
			pVfs->extractGameFileToPackage(this, "textures\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER);
1 cycrow 1708
	}
1709
}
1710
 
1711
bool CXspFile::AddTextFromFile(CyString file, int textId)
1712
{
1713
	bool remove = false;
1714
	if ( CFileIO(file).CheckFileExtension("pck") )
1715
	{
1716
		C_File F(file);
1717
		F.UnPCKFile();
1718
		if ( F.WriteToFile("tmp") )
1719
		{
1720
			remove = true;
1721
			file = "tmp";
1722
		}
1723
	}
1724
 
1725
	FILE *fid = fopen(file.c_str(), "r");
1726
	if ( fid )
1727
	{
1728
		bool ret = this->AddTextFromFile(fid, textId);
1729
		fclose(fid);
1730
 
1731
		if ( remove )
1732
			CFileIO(file).Remove();
1733
		m_bChanged = true; 
1734
		return ret;
1735
	}
1736
 
1737
	return false;
1738
}
1739
 
1740
bool CXspFile::ImportBodies(CyStringList *sceneModels, CyString filename)
1741
{
1742
	CFileIO File(filename);
1743
	if ( File.Exists() )
1744
	{
1745
		CyString sSection;
1746
		int section = 0;
1747
		CyStringList *lines = File.ReadLinesStr();
1748
		for ( SStringList *node = lines->Head(); node; node = node->next )
1749
		{
1750
			node->str.RemoveChar(9);
1751
			node->str.RemoveChar('\r');
1752
			node->str.RemoveFirstSpace();
1753
			if ( node->str.Empty() )
1754
				continue;
1755
			if ( node->str[0] == '/' )
1756
				continue;
1757
 
1758
			// are we looking for a section
1759
			if ( section <= 0 )
1760
			{
1761
				sSection = node->str.GetToken(";", 1, 1);
1762
				section = node->str.GetToken(";", 2, 2).ToInt();
1763
			}
1764
			else
1765
			{
1766
				int max;
1767
				CyString *strs = node->str.SplitToken(";", &max);
1768
				if ( strs && max )
1769
				{
1770
					for ( int i = 0; i < max; i++ )
1771
					{
1772
						strs[i].RemoveSpaces();
1773
						if (strs[i].Empty() )
1774
							continue;
1775
						if ( sceneModels->FindString(strs[i]) )
1776
							this->AddBody(sSection, strs[i]);
1777
						--section;
1778
					}
1779
				}
1780
				CLEANSPLIT(strs, max)
1781
			}
1782
		}
1783
		delete lines;
1784
		return true;
1785
	}
1786
 
1787
	return false;
1788
}
1789
 
1790
bool CXspFile::ImportCockpits(CyString filename)
1791
{
1792
	CFileIO File(filename);
1793
	if ( File.Exists() )
1794
	{
1795
		CyStringList *lines = File.ReadLinesStr();
1796
		int entries = 0;
1797
		for ( SStringList *node = lines->Head(); node; node = node->next )
1798
		{
1799
			node->str.RemoveChar(9);
1800
			node->str.RemoveChar('\r');
1801
			node->str.RemoveFirstSpace();
1802
			if ( node->str.Empty() )
1803
				node->remove = true;
1804
			else if ( node->str[0] == '/' )
1805
				node->remove = true;
1806
			else if ( !entries )
1807
			{
1808
				entries = node->str.GetToken(";", 2, 2).ToInt();
1809
				node->remove = true;
1810
			}
1811
		}
1812
		lines->RemoveMarked();
1813
 
1814
		// now get all the entries from TShips
1815
		for ( int i = 0; i < 6; i++ )
1816
		{
14 cycrow 1817
			int idx = m_sData.token(";", 32 + (i * 2));
1 cycrow 1818
			if ( idx < lines->Count() && idx )
1819
			{
1820
				CyString turret = lines->GetAt(idx)->str;
1821
				int pos = -1;
14 cycrow 1822
				Utils::String id;
1823
				while ( id.empty() && pos > -100 ) id = turret.GetToken(";", pos, pos--).ToString();
1824
				m_sData = m_sData.replaceToken(";", 32 + (i * 2), id + "(" + (long)idx + ")");
1 cycrow 1825
 
1826
				this->AddCockpit(turret, 0);
1827
			}
1828
		}
1829
 
1830
		delete lines;
1831
		return true;
1832
	}
1833
	return false;
1834
}
1835
 
35 cycrow 1836
bool CXspFile::extractCockpits(CVirtualFileSystem *pVfs)
1 cycrow 1837
{
35 cycrow 1838
	if ( pVfs->ExtractGameFile("types/TCockpits.pck", "tmp") ) {
1 cycrow 1839
		bool ret = this->ImportCockpits("tmp");
1840
		CFileIO("tmp").Remove();
1841
 
1842
		return ret;
1843
	}
1844
 
1845
	return false;
1846
}
1847
 
35 cycrow 1848
bool CXspFile::extractBodies(CVirtualFileSystem *pVfs, CyStringList *sceneModels)
1 cycrow 1849
{
1850
	if ( !sceneModels ) return false;
31 cycrow 1851
 
35 cycrow 1852
	if ( pVfs->ExtractGameFile("types/Bodies.pck", "tmp") ) {
1 cycrow 1853
		bool ret = this->ImportBodies(sceneModels, "tmp");
1854
		CFileIO("tmp").Remove();
1855
 
1856
		return ret;
1857
	}
1858
 
1859
	return false;
1860
}
1861
 
1862
bool CXspFile::AddTextFromFile(FILE *id, int textId)
1863
{
14 cycrow 1864
	if ( textId == -1 && !m_sData.empty() )
1865
		textId = m_sData.token(";", 7);
1 cycrow 1866
 
1867
	if ( textId <= 0 )
1868
		return false;
1869
 
1870
	CyString line;
1871
	if ( !id )
1872
		return false;
1873
 
1874
	bool added = false;
1875
 
1876
	CyString shipName;
1877
	CyString shipDesc;
1878
 
1879
	int lang = 0;
1880
	bool inpage = false;
1881
	while ( !feof(id) )
1882
	{
1883
		if ( !shipName.Empty() && !shipDesc.Empty() )
1884
		{
1885
			added = true;
1886
			break;
1887
		}
1888
 
1889
		line.GetEndOfLine(id, 0, false);
1890
		line.RemoveChar(9);
1891
		line.RemoveChar('\r');
1892
		line.RemoveFirstSpace();
1893
 
1894
		if ( inpage )
1895
		{
1896
			if ( line.Left(6).Compare("</page") )
1897
				break;
1898
 
1899
			// find matching id
1900
			if ( line.Left(6).Compare("<t id=") )
1901
			{
1902
				int pos = line.FindPos("id=\"");
1903
				if ( pos != -1 )
1904
				{
1905
					int endpos = line.FindPos("\"", pos + 5);
1906
					if ( endpos != -1 )
1907
					{
1908
						int id = line.Mid(pos + 5, endpos).ToInt();
1909
						if ( id == textId || id == (textId + 1) )
1910
						{
1911
							pos = line.FindPos(">", endpos);
1912
							if ( pos != -1 )
1913
							{
1914
								endpos = line.FindPos("</t>", pos);
1915
								if ( endpos != -1 )
1916
								{
1917
									if ( id == textId )
1918
										shipName = line.Mid(pos + 2, endpos - (pos + 1));
1919
									else
1920
										shipDesc = line.Mid(pos + 2, endpos - (pos + 1));
1921
								}
1922
							}
1923
						}
1924
					}
1925
				}
1926
			}
1927
		}
1928
		else if ( lang ) // search for page 17
1929
		{
1930
			if ( line.Left(8).Compare("<page id") )
1931
			{
1932
				int pos = line.FindPos("id=\"");
1933
				if ( pos != -1 )
1934
				{
1935
					int endpos = line.FindPos("\"", pos + 5);
1936
					if ( endpos != -1 )
1937
					{
1938
						CyString sId = line.Mid(pos + 5, endpos - (pos + 4));
1939
						int id = sId.ToInt();
1940
						if ( id == 17 || sId.Right(4).ToInt() == 17 )
1941
							inpage = true;
1942
					}
1943
				}
1944
			}
1945
		}
1946
		else if ( line.Left(12).Compare("<language id") )
1947
		{
1948
			int pos = line.FindPos("id=\"");
1949
			if ( pos != -1 )
1950
			{
1951
				int endpos = line.FindPos("\"", pos + 5);
1952
				if ( endpos != -1 )
1953
					lang = line.Mid(pos + 5, endpos - (pos + 4)).ToInt();
1954
			}
1955
		}
1956
	}
1957
 
1958
	// incase we only found the shipname
1959
	if ( !shipName.Empty() )
1960
		added = true;
1961
 
1962
	if ( added )
1963
	{
1964
		if ( lang == 44 || m_sName.Empty())
1965
		{
1966
			m_sName = shipName;
1967
			m_sDescription= shipDesc;
1968
			m_sDescription = m_sDescription.FindReplace("&amp", "&");
1969
		}
1970
		this->AddText(lang, shipName, shipDesc);
1971
		return true;	
1972
	}
1973
 
1974
	return false;
1975
}
1976
 
31 cycrow 1977
void CXspFile::ExtractTexts(CCatFile *catFile, CCatFile *secondCatFile, int textId)
1 cycrow 1978
{
1979
	for ( CListNode<SInCatFile> *node = catFile->GetFiles()->Front(); node; node = node->next() )
1980
	{
1981
		SInCatFile *f = node->Data();
1982
		if ( !f->sFile.Left(2).Compare("t\\") && !f->sFile.Left(2).Compare("t/") )
1983
			continue;
1984
 
1985
		// extract the text file and read in the data
31 cycrow 1986
		bool extracted = catFile->ExtractFile(f->sFile, "tmp");
1987
		if ( !extracted && secondCatFile ) extracted = secondCatFile->ExtractFile(f->sFile, "tmp");
1988
		if ( extracted ) {
1 cycrow 1989
			this->AddTextFromFile("tmp", textId);
1990
			CFileIO("tmp").Remove();
1991
		}
1992
	}
1993
}
1994
 
35 cycrow 1995
bool CXspFile::processSceneFileSection(int section, CVirtualFileSystem *pVfs, CyStringList *lModels, CProgressInfo *progress)
1 cycrow 1996
{
1997
	if ( progress ) progress->UpdateStatus(section);
1998
 
1999
	switch ( section )
2000
	{
2001
		case IMPORTSHIP_COMPONANT:
2002
			if ( !lModels ) return false;
35 cycrow 2003
			this->extractComponants(pVfs, lModels);
1 cycrow 2004
			break;
2005
 
2006
		case IMPORTSHIP_MODELS:
2007
			{
2008
				if ( !lModels ) return false;
2009
				for ( SStringList *node = lModels->Head(); node; node = node->next )
2010
				{
2011
					if ( node->str.IsNumber() ) // count be componants or dummy
2012
						continue;
35 cycrow 2013
					if ( pVfs->extractGameFileToPackage(this, "objects\\" + Utils::String(node->str.ToString()) + ".pbb", FILETYPE_SHIPMODEL, "objects\\" + Utils::String(node->str.ToString()) + ".bob") )
1 cycrow 2014
						continue;
35 cycrow 2015
					if ( pVfs->extractGameFileToPackage(this, "objects\\" + Utils::String(node->str.ToString()) + ".pbd", FILETYPE_SHIPMODEL, "objects\\" + Utils::String(node->str.ToString()) + ".bod") )
1 cycrow 2016
						continue;
2017
				}
2018
			}
2019
			break;
2020
 
2021
		case IMPORTSHIP_DUMMIES:
2022
			if ( !lModels ) return false;
35 cycrow 2023
			this->extractDummies(pVfs, lModels, true);
1 cycrow 2024
			break;
2025
 
2026
		// extract the textures
2027
		case IMPORTSHIP_TEXTURES:
35 cycrow 2028
			this->extractTextures(pVfs);
1 cycrow 2029
			break;
2030
 
2031
		case IMPORTSHIP_TEXTS:
2032
			// extract the text file entries
35 cycrow 2033
			pVfs->extractTexts(this, m_sData.token(";", 7));
1 cycrow 2034
			break;
2035
 
2036
		case IMPORTSHIP_BODIES:
2037
			// extract the bodies entries
2038
			if ( !lModels ) return false;
35 cycrow 2039
			this->extractBodies(pVfs, lModels);
1 cycrow 2040
			break;
2041
 
2042
		case IMPORTSHIP_COCKPITS:
2043
			// extract the cockpit entries
35 cycrow 2044
			this->extractCockpits(pVfs);
1 cycrow 2045
			break;
2046
	}
2047
 
2048
	return true;
2049
}
2050
 
35 cycrow 2051
bool CXspFile::processSceneFiles(CVirtualFileSystem *pVfs, CProgressInfo *progress)
1 cycrow 2052
{
2053
	// now lets parse our files
2054
	if ( progress ) progress->UpdateStatus(IMPORTSHIP_EXTRACTSCENE);
2055
	CyStringList *lModels = this->ReadSceneModels();
2056
	if ( !lModels )
2057
		return false;
2058
 
2059
	// extract componants, and add extra items to list
35 cycrow 2060
	if ( !this->processSceneFileSection(IMPORTSHIP_COMPONANT, pVfs, lModels, progress) )
1 cycrow 2061
		return false;
2062
 
2063
	//lets first find any model files
35 cycrow 2064
	if ( !this->processSceneFileSection(IMPORTSHIP_MODELS, pVfs, lModels, progress) )
1 cycrow 2065
		return false;
2066
 
2067
	// extract the dummies
35 cycrow 2068
	if ( !this->processSceneFileSection(IMPORTSHIP_DUMMIES, pVfs, lModels, progress) )
1 cycrow 2069
		return false;
2070
 
2071
	// extract the textures
35 cycrow 2072
	if ( !this->processSceneFileSection(IMPORTSHIP_TEXTURES, pVfs, lModels, progress) )
1 cycrow 2073
		return false;
2074
 
2075
	// extract the text file entries
35 cycrow 2076
	if ( !this->processSceneFileSection(IMPORTSHIP_TEXTS, pVfs, lModels, progress) )
1 cycrow 2077
		return false;
2078
 
2079
	// extract the bodies entries
35 cycrow 2080
	if ( !this->processSceneFileSection(IMPORTSHIP_BODIES, pVfs, lModels, progress) )
1 cycrow 2081
		return false;
2082
 
2083
	// extract the cockpit entries
35 cycrow 2084
	if ( !this->processSceneFileSection(IMPORTSHIP_COCKPITS, pVfs, lModels, progress) )
1 cycrow 2085
		return false;
2086
 
2087
	delete lModels;
2088
 
2089
	return true;
2090
}
2091
 
2092
 
2093
void CXspFile::PackAllFiles()
2094
{
2095
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
2096
	{
2097
		C_File *f = node->Data();
2098
		if ( f->GetFileType() == FILETYPE_SHIPSCENE || f->GetFileType() == FILETYPE_COCKPITSCENE || f->GetFileType() == FILETYPE_SHIPMODEL || f->GetFileType() == FILETYPE_SHIPOTHER )
2099
		{
2100
			if ( f->CheckFileExt("bod") )
2101
			{
2102
				if ( f->PCKFile() )
2103
					f->ChangeFileExt("pbd");
2104
			}
2105
			else if ( f->CheckFileExt("bob") )
2106
			{
2107
				if ( f->PCKFile() )
2108
					f->ChangeFileExt("pbb");
2109
			}
2110
		}
2111
	}
2112
}
2113
 
2114
void CXspFile::AdjustCockpits()
2115
{
2116
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
2117
	{
2118
		SCockpit *c = node->Data();
2119
		if ( c->iIndex < 0 )
2120
			continue;
2121
 
2122
		CyString id = c->sCockpit.GetToken(";", 19, 19);
2123
 
2124
		for ( int i = 0; i < 6; i++ )
2125
		{
14 cycrow 2126
			CyString tId = m_sData.token(";", 32 + (i * 2));
1 cycrow 2127
			if ( tId.IsNumber() && tId.ToInt() == c->iIndex )
14 cycrow 2128
				m_sData = m_sData.replaceToken(";", 32 + (i * 2), (id + "(" + CyString::Number(c->iIndex) + ")").c_str());
1 cycrow 2129
		}
2130
	}
2131
}
2132
 
2133
CyString CXspFile::FormatShipData(CyStringList *cockpits, int *text, int game)
2134
{
2135
	CyString data = (game == GAME_X3) ? this->GetX3ShipData() : this->GetTCShipData();
2136
	// do turrets
2137
	for ( int t = 0; t < 6; t++ )
2138
	{
2139
		int oldPos = 0;
2140
		CyString turret = data.GetToken(";", 32 + (t * 2), 32 + (t * 2));
2141
		if ( !turret.IsNumber() )
2142
		{
2143
			if ( turret.IsIn("(") )
2144
			{
2145
				oldPos = turret.GetToken("(", 2).GetToken(")", 1, 1).ToInt();
2146
				turret = turret.GetToken("(", 1, 1);
2147
			}
2148
			int pos = cockpits->FindStringPos(turret);
2149
			if ( pos < 0 )	pos = oldPos;
2150
			data = data.RepToken(";", 32 + (t * 2), CyString::Number(pos));
2151
		}
2152
	}
2153
	// adjust the weapons
2154
	int mask = this->GetLaserMask(game - 1);
2155
	if ( mask != -1 )
2156
		data = data.RepToken(";", 19, CyString::Number(mask));
2157
	mask = this->GetMissileMask(game - 1);
2158
	if ( mask != -1 )
2159
		data = data.RepToken(";", 25, CyString::Number(mask));
2160
 
2161
	// fix the ship text
2162
	if ( m_iOrgDesc > 0 )
2163
		(*text) = m_iOrgDesc;
2164
	data = data.RepToken(";", 7, CyString::Number(*text));
2165
 
2166
	// add the ware id
2167
	data.RemoveChar(9);
2168
	data.RemoveEndSpace();
2169
	// remove the end ;
2170
	while ( data.Right(1) == ";" ) data.Truncate((int)data.Length() - 1);
2171
	data = data.RepToken(";", data.NumToken(";"), this->GetShipID());
2172
	if ( data.Right(1) != ";" )
2173
		data += ";";
2174
 
2175
	return data;
35 cycrow 2176
}
2177