Subversion Repositories spk

Rev

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