Subversion Repositories spk

Rev

Rev 108 | Rev 112 | 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;								\
11
									std::vector<STypesSection *> list;		\
12
									ADDSECTIONLIST(T, L);					\
13
									data = CXspFile::TypesListToString(list, true); \
14
								}
15
 
16
#define GENERATESTRINGSECTION(F, L) if ( !L.Empty() ) {						\
17
									type = F;								\
18
									std::vector<STypesSection *> list;		\
19
									_addDataSection(L, list);				\
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
 
109 cycrow 907
void CXspFile::_addSection(std::vector<STypesSection *> &list, const Utils::String &section, const Utils::String &data)
908
{
909
	STypesSection *currentSubSection = NULL;
910
	for(std::vector<STypesSection *>::iterator itr = list.begin(); itr != list.end(); itr++) {
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
 
926
void CXspFile::_addDataSection(CyStringList &list, std::vector<STypesSection *> &sectionList)
927
{
928
	for(SStringList *str = list.Head(); str; str = str->next) {
929
		_addSection(sectionList, str->str.ToString(), str->data.ToString());
930
	}
931
}
932
 
933
void CXspFile::addDummiesToList(std::vector<STypesSection *> &list)
934
{
935
	ADDSECTIONLIST(SDummy, m_lDummy);
936
}
937
 
938
void CXspFile::addComponentsToList(CLinkList<SComponentEntry> &componentList)
939
{
940
	for(CListNode<SComponent> *node = m_lComponent.Front(); node; node = node->next()) {
941
		SComponentEntry *currentSection = NULL;
942
		for(CListNode<SComponentEntry> *cNode = componentList.Front(); cNode; cNode = cNode->next()) {
943
			if ( cNode->Data()->sSection.Compare(node->Data()->sSection) ) {
944
				currentSection = cNode->Data();
945
				break;
946
			}
947
		}
948
 
949
		if ( !currentSection ) {
950
			currentSection = new SComponentEntry();
951
			currentSection->sSection = node->Data()->sSection;
952
			componentList.push_back(currentSection);
953
		}
954
 
955
		_addSection(currentSection->lEntries, node->Data()->sSection2, node->Data()->sData);
956
	}
957
}
958
 
959
void CXspFile::addCutDataToList(std::vector<STypesSection *> &list)
960
{
961
	_addDataSection(this->m_lCutData, list);
962
}
963
 
964
void CXspFile::addBodiesToList(std::vector<STypesSection *> &list)
965
{
966
	_addDataSection(this->m_lBodies, list);
967
}
968
 
969
void CXspFile::addAnimationsToList(std::vector<STypesSection *> &list)
970
{
971
	_addDataSection(this->m_lAnimations, list);
972
}
973
 
974
 
975
void CXspFile::addGeneratedFiles(HZIP &hz)
976
{
977
	TCHAR buf[5000];
978
 
979
	CFileIO tmpFile(CPackages::tempDirectory() + "/temp.tmp");
980
 
981
	for(int i = 0; i < 5; i++) {
982
		Utils::String type;
983
		Utils::String data;
984
		switch(i) {
985
			case 0:
986
				data = "50;1\r\n" + this->m_sData;
987
				type = "TShips";
988
				break;
989
			case 1:
990
				if ( !this->m_lCockpit.empty() ) {
991
					data = Utils::String("51;") + (long)this->m_lCockpit.size() + ";\r\n";
992
					for(CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next()) {
993
						data += node->Data()->sCockpit + "\r\n";
994
					}
995
					type = "TCockpits";
996
				}
997
				break;
998
			case 2:
999
				if ( !this->m_lComponent.empty() ) {
1000
					type = "Components";
1001
					CLinkList<SComponentEntry> componentList;
1002
					this->addComponentsToList(componentList);
1003
					for(CListNode<SComponentEntry> *node = componentList.Front(); node; node = node->next()) {
1004
						data += node->Data()->sSection + "; " + (long)node->Data()->lEntries.size() + ";\r\n";
1005
						data += CXspFile::TypesListToString(node->Data()->lEntries, true);
1006
						delete node->Data();
1007
					}
1008
				}
1009
				break;
1010
			case 3:
1011
				GENERATESECTION("Dummies", SDummy, this->m_lDummy);
1012
				break;
1013
			case 4:
1014
				GENERATESTRINGSECTION("Bodies", this->m_lBodies);
1015
				break;
1016
		}
1017
 
1018
		if ( type.empty() ) continue;
1019
 
1020
		Utils::String fname = "GENERATED/types/" + type + ".txt";
1021
 
1022
		Utils::String fileData = "// Exported " + type + " file, Generated by SPK Libraries V" + Utils::String::FromFloat(GetLibraryVersion(), 2) + "\r\n" + data;
1023
		if ( tmpFile.startWrite() ) {
1024
			tmpFile.write(fileData.c_str(), fileData.length());
1025
			tmpFile.close();
1026
		}
1027
 
1028
		// tships files
1029
		wsprintf(buf, L"%hs", fname.c_str());
1030
 
1031
		if ( tmpFile.startRead() ) {
1032
			size_t dataSize = 0;
1033
			unsigned char *data = tmpFile.readAll(&dataSize);
1034
			ZipAdd(hz, buf, data, dataSize);
1035
		}
1036
	}
1037
}
1038
 
98 cycrow 1039
bool CXspFile::LoadPackageData(const Utils::String &sFirst, const Utils::String &sRest, const Utils::String &sMainGame, Utils::CStringList &otherGames)
1 cycrow 1040
{
14 cycrow 1041
	if ( sFirst.Compare("Shipyard") )
1 cycrow 1042
	{
1043
		for ( int i = SHIPYARD_ARGON; i <= SHIPYARD_MAX; i *= 2 )
1044
		{
39 cycrow 1045
			if ( sRest.Compare(GetShipyardName(i)) )
1 cycrow 1046
			{
1047
				this->AddShipyard(i);
1048
				break;
1049
			}
1050
		}
1051
	}
14 cycrow 1052
	else if ( sFirst.Compare("OriginalDescription") )
1053
		m_iOrgDesc = sRest;
1054
	else if ( sFirst.Compare("ShipData") )
1055
		m_sData = sRest;
1056
	else if ( sFirst.Compare("ReadData") ) // read data from a tships file
1 cycrow 1057
	{
1058
		CPackages p;
14 cycrow 1059
		m_sData = p.ReadShipData(sRest.tokens(" ", 2), sRest.token(" ", 1)).ToString();
1 cycrow 1060
	}
14 cycrow 1061
	else if ( sFirst.Compare("ExistingShip") )
1 cycrow 1062
		m_bExistingShip = true;
14 cycrow 1063
	else if ( sFirst.Compare("ShipID") )
1064
		m_sID = sRest;
108 cycrow 1065
	else if ( sFirst.Compare("ShipText") )
1066
		this->AddText(sRest.token(" ", 1).toLong(), sRest.tokens(" ", 2).token("|", 1), sRest.tokens(" ", 2).tokens("|", 2));
1067
	else if ( sFirst.Compare("Component") )
1068
		this->AddComponent(sRest.token(" ", 1), sRest.token(" ", 2), sRest.tokens(" ", 3));
1069
	else if ( sFirst.Compare("Cockpit") )
1070
		this->AddCockpit(sRest.tokens(" ", 2).replaceToken(";", 19, sRest.token(" ", 1)), 0);
1071
	else if ( sFirst.Compare("CockpitWeapon") )
1072
		this->AddCockpitWeapon(sRest.token(" ", 1), sRest.token(" ", 2), sRest.token(" ", 3));
1073
	else if ( sFirst.Compare("WeaponMask") )
1074
		this->AddWeaponMask(sRest.token(" ", 1), sRest.token(" ", 2));
1075
	else if ( sFirst.Compare("MissileMask") )
1076
		this->AddMissileMask(sRest.token(" ", 1), sRest.token(" ", 2));
1077
	else if ( sFirst.Compare("Dummy") )
1078
		this->AddDummy(sRest.token(" ", 1), sRest.token(" ", 2));
1079
	else if ( sFirst.Compare("CutData") )
1080
		this->AddCutData(sRest);
1081
	else if ( sFirst.Compare("Animation") )
1082
		this->AddAnimation(sRest);
1083
	else if ( sFirst.Compare("Bodies") )
1084
		this->AddBodies(sRest);
98 cycrow 1085
	else if ( !CBaseFile::LoadPackageData(sFirst, sRest, sMainGame, otherGames) )
1 cycrow 1086
	{
1087
		return false;
1088
	}
1089
 
1090
	return true;
1091
}
1092
 
1093
 
39 cycrow 1094
Utils::String CXspFile::GetX3ShipData()
1 cycrow 1095
{
39 cycrow 1096
	Utils::String data = m_sData;
1 cycrow 1097
 
1098
	// change the ship subtype, Reunion uses number, TC uses a define
39 cycrow 1099
	Utils::String sSubType = data.token(";", 6);
1100
	if ( !((long)sSubType) && sSubType != "0" )
1101
		data = data.replaceToken(";", 6, (long)CShipData::ConvertShipSubType(CyString(sSubType)));
1 cycrow 1102
 
39 cycrow 1103
	Utils::String sClass = data.token(";", TSHIPPOS_CLASS);
1104
	if ( !((long)sClass) && sClass != "0" )
1 cycrow 1105
	{
1106
		int num = 0;
1107
		for ( int i = 0; i < OBJ_SHIP_MAX; i++ )
1108
		{
94 cycrow 1109
			if ( sClass.Compare(CShipData::ConvertShipClass(CShipData::GetShipClassFromNum(i))) )
1 cycrow 1110
			{
1111
				num = i;
1112
				break;
1113
			}
1114
		}
1115
 
39 cycrow 1116
		data = data.replaceToken(";", TSHIPPOS_CLASS, (long)num);
1 cycrow 1117
	}
1118
 
1119
	return data;
1120
}
1121
 
39 cycrow 1122
Utils::String CXspFile::GetTCShipData()
1 cycrow 1123
{
39 cycrow 1124
	Utils::String data = m_sData;
1 cycrow 1125
 
39 cycrow 1126
	Utils::String sSubType = data.token(";", 6);
1127
	if ( ((long)sSubType) || sSubType == "0" )
1128
		data = data.replaceToken(";", 6, CShipData::ConvertShipSubType((long)sSubType).ToString());
1 cycrow 1129
 
39 cycrow 1130
	Utils::String sClass = data.token(";", TSHIPPOS_CLASS);
1131
	if ( ((long)sClass) || sClass == "0" )
94 cycrow 1132
		data = data.replaceToken(";", TSHIPPOS_CLASS, CShipData::ConvertShipClass((long)sClass));
1 cycrow 1133
 
1134
	return data;
1135
}
1136
 
39 cycrow 1137
bool CXspFile::RemoveCockpit(const Utils::String &sCockpitId)
1 cycrow 1138
{
39 cycrow 1139
	Utils::String cockpitid = sCockpitId;
1 cycrow 1140
	// if its a whole line, just get the end
39 cycrow 1141
	if ( cockpitid.isin(";") )
1 cycrow 1142
	{
39 cycrow 1143
		cockpitid = cockpitid.tokens(";", -2);
1144
		while ( cockpitid.right(1) == ";" )
1145
			cockpitid.truncate(-1);
1 cycrow 1146
	}
1147
 
1148
	bool ret = false;
1149
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
1150
	{
39 cycrow 1151
		Utils::String id = node->Data()->sCockpit.token(";", 19);
1 cycrow 1152
		if ( id.Compare(cockpitid) )
1153
		{
1154
			node->DeleteData();
1155
			ret = true;
1156
			break;
1157
		}
1158
	}
1159
 
1160
	m_lCockpit.RemoveEmpty();
1161
 
1162
	return ret;
1163
}
1164
 
39 cycrow 1165
bool CXspFile::RemoveComponent(const Utils::String &section1, const Utils::String &section2, const Utils::String &data)
1 cycrow 1166
{
1167
	bool ret = false;
1168
	for ( CListNode<SComponent> *node = m_lComponent.Front(); node; node = node->next() )
1169
	{
1170
		if ( node->Data()->sSection.Compare(section1) && node->Data()->sSection2.Compare(section2) && node->Data()->sData.Compare(data) )
1171
		{
1172
			ret = true;
1173
			node->DeleteData();
1174
			break;
1175
		}
1176
	}
1177
	m_lComponent.RemoveEmpty();
1178
	return ret;
1179
}
1180
 
39 cycrow 1181
bool CXspFile::RemoveDummy(const Utils::String &section, const Utils::String &data)
1 cycrow 1182
{
1183
	bool ret = false;
1184
	for ( CListNode<SDummy> *node = m_lDummy.Front(); node; node = node->next() )
1185
	{
1186
		if ( node->Data()->sSection.Compare(section) && node->Data()->sData.Compare(data) )
1187
		{
1188
			ret = true;
1189
			node->DeleteData();
1190
			break;
1191
		}
1192
	}
1193
	m_lDummy.RemoveEmpty();
1194
 
1195
	return ret;
1196
}
1197
 
39 cycrow 1198
Utils::String CXspFile::GetCockpitData(const Utils::String &cid)
1 cycrow 1199
{
1200
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
1201
	{
39 cycrow 1202
		Utils::String id = node->Data()->sCockpit.token(";", 19);
1 cycrow 1203
		if ( id.Compare(cid) )
1204
			return node->Data()->sCockpit;
1205
	}
1206
 
39 cycrow 1207
	return "";
1 cycrow 1208
}
1209
 
39 cycrow 1210
SCockpit *CXspFile::FindCockpit(const Utils::String &cid)
1 cycrow 1211
{
1212
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
1213
	{
39 cycrow 1214
		Utils::String id = node->Data()->sCockpit.token(";", 19);
1 cycrow 1215
		if ( id.Compare(cid) )
1216
			return node->Data();
1217
	}
1218
 
1219
	return NULL;
1220
}
1221
 
39 cycrow 1222
void CXspFile::EditCockpit(const Utils::String &cid, const Utils::String &cockpit)
1 cycrow 1223
{
1224
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
1225
	{
39 cycrow 1226
		Utils::String id = node->Data()->sCockpit.token(";", 19);
1 cycrow 1227
		if ( id.Compare(cid) )
1228
		{
1229
			node->Data()->sCockpit = cockpit;
1230
			break;
1231
		}
1232
	}
1233
}
1234
 
39 cycrow 1235
void CXspFile::EditCockpit(const Utils::String &cid, const Utils::String &scene, int mask)
1 cycrow 1236
{
1237
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
1238
	{
39 cycrow 1239
		Utils::String id = node->Data()->sCockpit.token(";", 19);
1 cycrow 1240
		if ( id.Compare(cid) )
1241
		{
39 cycrow 1242
			Utils::String cockpit = node->Data()->sCockpit;
1243
			cockpit = cockpit.replaceToken(";", 8, scene);
1244
			cockpit = cockpit.replaceToken(";", 9, (long)mask);
1 cycrow 1245
			node->Data()->sCockpit = cockpit;
1246
			break;
1247
		}
1248
	}
1249
}
39 cycrow 1250
void CXspFile::NewCockpit(const Utils::String &id, const Utils::String &scene, int mask)
1 cycrow 1251
{
39 cycrow 1252
	Utils::String cockpit = "0;0;0;0;0;0;0;";
1 cycrow 1253
	cockpit += scene + ";";
39 cycrow 1254
	cockpit += (long)mask;
1 cycrow 1255
	cockpit += ";0;0;0;0;0;0;-100000;0;0;";
1256
	cockpit += id + ";";
1257
	this->AddCockpit(cockpit, -1);
1258
}
1259
 
39 cycrow 1260
bool CXspFile::RemoveCutData(const Utils::String &cut)
1 cycrow 1261
{
1262
	bool ret = false;
1263
	for ( SStringList *str = m_lCutData.Head(); str; str = str->next )
1264
	{
39 cycrow 1265
		if ( str->str.GetToken(";", 1, 1).Compare(CyString(cut.token(";", 1))) )
1 cycrow 1266
		{
1267
			ret = true;
1268
			str->remove = true;
1269
			break;
1270
		}
1271
	}
1272
 
1273
	m_lCutData.RemoveMarked();
1274
 
1275
	return ret;
1276
}
1277
 
39 cycrow 1278
bool CXspFile::RemoveBodies(const Utils::String &cut)
1 cycrow 1279
{
1280
	bool ret = false;
1281
	for ( SStringList *str = m_lBodies.Head(); str; str = str->next )
1282
	{
39 cycrow 1283
		if ( str->str.Remove(' ').Compare(CyString(cut.remove(' '))) )
1 cycrow 1284
		{
1285
			ret = true;
1286
			str->remove = true;
1287
			break;
1288
		}
1289
	}
1290
 
1291
	m_lBodies.RemoveMarked();
1292
 
1293
	return ret;
1294
}
1295
 
39 cycrow 1296
bool CXspFile::RemoveAnimation(const Utils::String &cut)
1 cycrow 1297
{
1298
	bool ret = false;
1299
	for ( SStringList *str = m_lAnimations.Head(); str; str = str->next )
1300
	{
39 cycrow 1301
		if ( str->str.Remove(' ').Remove('\n').Compare(CyString(cut.remove(' ').remove('\n'))) )
1 cycrow 1302
		{
1303
			ret = true;
1304
			str->remove = true;
1305
			break;
1306
		}
1307
	}
1308
 
1309
	m_lAnimations.RemoveMarked();
1310
 
1311
	return ret;
1312
}
1313
 
108 cycrow 1314
SCockpit *CXspFile::_findCockpit(const Utils::String &sID)
1 cycrow 1315
{
108 cycrow 1316
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ) {
1317
		Utils::String id = node->Data()->sCockpit.token(";", 19);
1318
		if ( id.Compare(sID) )
1319
			return node->Data();
1320
	}
1 cycrow 1321
 
108 cycrow 1322
	return NULL;
1323
}
1324
 
1325
void CXspFile::AddCockpitWeapon(const Utils::String &cockpit, int game, int mask)
1326
{
1327
	SCockpit *pCockpit = _findCockpit(cockpit);
1328
 
1329
	// search if the game mask already exists
1330
	SWeaponMask *wm = NULL;
1331
	for ( CListNode<SWeaponMask> *node = pCockpit->lWeaponMask.Front(); node; node = node->next() )
1 cycrow 1332
	{
108 cycrow 1333
		if ( node->Data()->iGame == game )
1 cycrow 1334
		{
108 cycrow 1335
			wm = node->Data();
1 cycrow 1336
			break;
1337
		}
1338
	}
1339
 
108 cycrow 1340
	if ( !wm )
1341
	{
1342
		wm = new SWeaponMask;
1343
		pCockpit->lWeaponMask.push_back(wm);
1344
	}
1345
 
1346
	wm->iGame = game;
1347
	if ( mask == -1 )
1348
		wm->iMask = pCockpit->sCockpit.token(";", 9);
1349
	else
1350
		wm->iMask = mask;
1351
	_changed();
1352
}
1353
 
1354
void CXspFile::AddCockpit(const Utils::String &cockpit, int game, int mask, int index)
1355
{
1356
	Utils::String cid = cockpit.token(";", 19);
1357
	SCockpit *pCockpit = _findCockpit(cid);
1358
 
1 cycrow 1359
	if ( !pCockpit )
1360
	{
1361
		pCockpit = new SCockpit;
1362
		pCockpit->sCockpit = cockpit;
1363
		pCockpit->iIndex = index;
1364
		m_lCockpit.push_back(pCockpit);
1365
	}
1366
	if ( index != -1 )
1367
		pCockpit->iIndex = index;
1368
 
1369
	// now add the game mask
1370
	if ( game > 0 )
108 cycrow 1371
		AddCockpitWeapon(cid, game, mask);
50 cycrow 1372
	_changed();
1 cycrow 1373
}
1374
 
39 cycrow 1375
void CXspFile::AddBody(const Utils::String &section, const Utils::String &data)
1 cycrow 1376
{
1377
	this->AddBodies(section + ";" + data);
50 cycrow 1378
	_changed();
1 cycrow 1379
}
39 cycrow 1380
void CXspFile::AddBodies(const Utils::String &sData)
1 cycrow 1381
{
39 cycrow 1382
	Utils::String data = sData;
1383
	if ( !data.isNumber() )
1 cycrow 1384
	{
39 cycrow 1385
		if ( data[(int)(data.length() - 5)] == '.' )
1386
			data = data.left(-5);
1387
		else if ( data[(int)(data.length() - 4)] == '.' )
1388
			data = data.left(-4);
1389
		if ( data.right(1) != ";" )
1 cycrow 1390
			data += ";";
1391
	}
39 cycrow 1392
	m_lBodies.PushBack(CyString(data), true);
50 cycrow 1393
	_changed();
1 cycrow 1394
}
1395
 
39 cycrow 1396
int CXspFile::GetAnimationType(const Utils::String &type)
1 cycrow 1397
{
1398
	if ( type.Compare("TAT_TAGSINGLESTEP") )
1399
		return TAT_SINGLE;
1400
	else if ( type.Compare("TAT_TAGONESHOT") 
1401
				|| type.Compare("TAT_TAGONESHOT_REINIT") 
1402
				|| type.Compare("TAT_PINGPONG")
1403
				|| type.Compare("TAT_TAGLOOP") )
1404
		return TAT_3;
1405
 
1406
	return TAT_NONE;
1407
}
1408
 
109 cycrow 1409
Utils::String CXspFile::TypesListToString(std::vector<STypesSection *> &list, bool deleteAfter)
1410
{
1411
	Utils::String data;
1412
 
1413
	for(std::vector<STypesSection *>::iterator itr = list.begin(); itr != list.end(); itr++) {
1414
		data += (*itr)->sSection + "; " + (long)(*itr)->lEntries.size() + ";\r\n";
1415
		for(Utils::SStringList *str = (*itr)->lEntries.First(); str; str = (*itr)->lEntries.Next()) {
1416
			data += str->str + "\r\n";
1417
		}
1418
 
1419
		if ( deleteAfter ) {
1420
			(*itr)->lEntries.MemoryClear();
1421
			delete *itr;
1422
		}
1423
	}
1424
 
1425
	return data;
1426
}
1427
 
1 cycrow 1428
bool CXspFile::ReadAnimations(CyStringList *lIn, CyStringList *lOut, int startRecord)
1429
{
39 cycrow 1430
	Utils::String lastComment;
1431
	Utils::String addEntry;
1 cycrow 1432
	int remaining = 0;
39 cycrow 1433
	Utils::String lastType;
1 cycrow 1434
	int newEntries = 0;
1435
	int entries = -1;
1436
	for ( SStringList *strNode = lIn->Head(); strNode; strNode = strNode->next )
1437
	{
39 cycrow 1438
		Utils::String line = strNode->str.ToString();
1439
		line.removeChar('\r');
1440
		line.removeChar(9);
1441
		if ( line.empty() || line[0] == '/' )
1 cycrow 1442
			continue;
1443
		if ( entries == -1)
1444
		{
39 cycrow 1445
			entries	= line.token(";", 1);
1 cycrow 1446
			newEntries = entries - startRecord;
1447
		}
1448
		else
1449
		{
1450
			// remove comments, endspaces and last ;
39 cycrow 1451
			Utils::String sStriped = line;
1452
			if ( sStriped.isin("//") )
1 cycrow 1453
			{
1454
				if ( entries <= newEntries )
39 cycrow 1455
					lastComment = "//" + sStriped.tokens("//", 2);
1456
				sStriped = sStriped.token("//", 1);
1 cycrow 1457
			}
39 cycrow 1458
			sStriped.removeEndSpace();
1459
			if ( sStriped.right(1) == ";" )
1460
				sStriped.truncate(-1);
1 cycrow 1461
 
39 cycrow 1462
			Utils::String sRemainingLeft;
1 cycrow 1463
			if ( remaining > 0 )
1464
				sRemainingLeft = sStriped;
1465
			else
1466
			{
1467
				// each line should be a new entry, with some exceptions
1468
				// potection for new lines
39 cycrow 1469
				lastType = sStriped.token(";", 1);
1 cycrow 1470
 
1471
				switch (CXspFile::GetAnimationType(lastType))
1472
				{
1473
					case TAT_SINGLE:
39 cycrow 1474
						remaining = (long)sStriped.token(";", 5) + 1;
1475
						sRemainingLeft = sStriped.tokens(";", 6);
1 cycrow 1476
						if ( entries <= newEntries )
39 cycrow 1477
							addEntry = sStriped.tokens(";", 1, 5) + ";";
1 cycrow 1478
						break;
1479
					case TAT_3:
39 cycrow 1480
						remaining = (long)sStriped.token(";", 5) + 1;
1481
						sRemainingLeft = sStriped.tokens(";", 6);
1 cycrow 1482
						if ( entries <= newEntries )
39 cycrow 1483
							addEntry = sStriped.tokens(";", 1, 5) + ";";
1 cycrow 1484
						break;
1485
 
1486
					default:
1487
						remaining = 0;
1488
						if ( entries <= newEntries )
1489
							addEntry = sStriped;
1490
 
1491
				}
1492
			}
1493
 
39 cycrow 1494
			if ( !sRemainingLeft.empty() )
1 cycrow 1495
			{
1496
				int tatType = CXspFile::GetAnimationType(lastType);
1497
				if ( tatType == TAT_SINGLE )
1498
				{
39 cycrow 1499
					if ( sRemainingLeft.isin(";") )
1500
						remaining -= sRemainingLeft.countToken(";");
1501
					else if ( !sRemainingLeft.empty() )
1 cycrow 1502
						--remaining;
1503
 
1504
					if ( entries <= newEntries )
1505
						addEntry += sRemainingLeft + ";";
1506
				}
1507
				else if ( tatType == TAT_3 )
1508
				{
1509
					// last entry
1510
					if ( remaining == 1 )
1511
						--remaining;
39 cycrow 1512
					else if ( sRemainingLeft.isin(";") )
1 cycrow 1513
					{
39 cycrow 1514
						if ( !sRemainingLeft.isin("TATF_COORDS") )
1 cycrow 1515
						{
39 cycrow 1516
							int amt = sRemainingLeft.countToken(";") / 3;
1 cycrow 1517
							remaining -= amt;
39 cycrow 1518
							if ( remaining == 1 && (sRemainingLeft.countToken(";") - (amt * 3)) == 1 )
1 cycrow 1519
								--remaining;
1520
						}
1521
						else
1522
						{
39 cycrow 1523
							int iRem = sRemainingLeft.countToken(";");
1 cycrow 1524
							int iPos = 1;
1525
							while ( iPos < iRem )
1526
							{
39 cycrow 1527
								Utils::String first = sRemainingLeft.token(";", iPos);
1528
								if ( first.isin("TATF_COORDS") )
1 cycrow 1529
									iPos += 5;
1530
								else
1531
									iPos += 3;
1532
								--remaining;
1533
							}
1534
 
1535
							if ( remaining == 1 && iPos == iRem )
1536
								--remaining;
1537
						}
1538
					}
1539
 
1540
					if ( entries <= newEntries )
1541
						addEntry += sRemainingLeft + ";";
1542
				}
1543
			}
1544
 
1545
			if ( remaining <= 0 )
1546
			{
39 cycrow 1547
				if ( entries <= newEntries && !addEntry.empty())
1 cycrow 1548
				{
39 cycrow 1549
					if ( addEntry[(int)addEntry.length() - 1] != ';' )
1 cycrow 1550
						addEntry += ";";
39 cycrow 1551
					lOut->PushBack(CyString(addEntry + lastComment));
1 cycrow 1552
				}
1553
				--entries;
1554
			}
1555
		}
1556
	}
1557
 
1558
	return !lOut->Empty();
1559
}
1560
 
1561
void CXspFile::AddAnimation(CyStringList *list)
1562
{
1563
	for ( SStringList *strNode = list->Head(); strNode; strNode = strNode->next )
39 cycrow 1564
		this->AddAnimation(strNode->str.ToString());
50 cycrow 1565
	_changed();
1 cycrow 1566
}
1567
 
1568
SText *CXspFile::FindShipText(int lang)
1569
{
1570
	if ( m_lText.empty() )
1571
		return NULL;
1572
 
1573
	SText *english = NULL;
1574
	SText *german = NULL;
1575
	SText *found = NULL;
1576
	for ( CListNode<SText> *node = m_lText.Front(); node; node = node->next() )
1577
	{
1578
		SText *text = node->Data();
1579
		// matched language
1580
		if ( text->iId == lang )
1581
			return text;
1582
		else if ( text->iId == 44 )
1583
			english = text;
1584
		else if ( text->iId == 49 )
1585
			german = text;
1586
		else if ( !found )
1587
			found = text;
1588
	}
1589
 
1590
	// if we've found an english version, use that
1591
	if ( english )
1592
		return english;
1593
	// otherwise try a german
1594
	if ( german )
1595
		return german;
1596
	// otherwise use any we've found (usually first one)
1597
	return found;
1598
}
1599
 
39 cycrow 1600
Utils::String CXspFile::GetTextName(int lang)
1 cycrow 1601
{
1602
	SText *t = FindShipText(lang);
1603
	if ( t )
1604
	{
1605
		// return the correct language text
39 cycrow 1606
		if ( !t->sName.empty() )
1 cycrow 1607
			return t->sName;
1608
		// we have found a text, but there is no ship name ??
1609
		else if ( lang != 44 )
1610
		{
1611
			// reget the english one
1612
			t = FindShipText(44);
39 cycrow 1613
			if ( t && !t->sName.empty() )
1 cycrow 1614
				return t->sName;
1615
		}
1616
	}
1617
 
1618
	// still not found one, return the ships name
1619
	return this->GetShipName(lang);
1620
}
1621
 
39 cycrow 1622
Utils::String CXspFile::GetTextDescription(int lang)
1 cycrow 1623
{
1624
	SText *t = FindShipText(lang);
1625
	if ( t )
1626
	{
1627
		// return the correct language text
39 cycrow 1628
		if ( !t->sDesc.empty() )
1 cycrow 1629
			return t->sDesc;
1630
		// we have found a text, but there is no ship name ??
1631
		else if ( lang != 44 )
1632
		{
1633
			// reget the english one
1634
			t = FindShipText(44);
39 cycrow 1635
			if ( t && !t->sDesc.empty() )
1 cycrow 1636
				return t->sDesc;
1637
		}
1638
	}
1639
 
1640
	// still not found one, return the ships name
48 cycrow 1641
	if ( !this->description().empty() ) return this->description();
1 cycrow 1642
	return this->GetShipName(lang);
1643
}
1644
 
35 cycrow 1645
bool CXspFile::startExtractShip(CVirtualFileSystem *pVfs, const Utils::String &sId, CProgressInfo *pProgress)
1 cycrow 1646
{
39 cycrow 1647
	m_sID = sId.remove('\r');
35 cycrow 1648
	while ( m_sID.right(1) == ";" )
1649
		m_sID.truncate(-1);
1 cycrow 1650
 
35 cycrow 1651
	m_sData = pVfs->getTShipsEntry(m_sID);
1652
 
1 cycrow 1653
	// get scene files
35 cycrow 1654
	if ( pProgress ) pProgress->UpdateStatus(IMPORTSHIP_SCENE);
1655
	if ( !this->extractSceneFiles(pVfs) )
1 cycrow 1656
		return false;
1657
 
1658
	return true;
1659
}
1660
 
35 cycrow 1661
bool CXspFile::extractShip(CVirtualFileSystem *pVfs, const Utils::String &sId, CProgressInfo *progress)
1 cycrow 1662
{
35 cycrow 1663
	if ( !this->startExtractShip(pVfs, sId, progress) )
1 cycrow 1664
		return false;
1665
 
1666
	// read the scene file and get the files list
35 cycrow 1667
	if ( !this->processSceneFiles(pVfs, progress) )
1 cycrow 1668
		return false;
1669
 
1670
	// pack all the ship files
1671
	this->PackAllFiles();
1672
 
1673
	return true;
1674
}
1675
 
35 cycrow 1676
bool CXspFile::extractSceneFiles(CVirtualFileSystem *pVfs)
1 cycrow 1677
{
35 cycrow 1678
	m_pSceneFile = pVfs->extractGameFileToPackage(this, "objects\\" + m_sData.token(";", 17) + ".pbd", FILETYPE_SHIPSCENE, "objects\\" + m_sData.token(";", 17) + ".bod");
1679
	if ( !m_pSceneFile ) return false;
1680
	m_pCockpitFile = pVfs->extractGameFileToPackage(this, "objects\\" + m_sData.token(";", 18) + ".pbd", FILETYPE_COCKPITSCENE, "objects\\" + m_sData.token(";", 18) + ".bod");
1 cycrow 1681
 
1682
	return true;
1683
}
1684
 
1685
CyStringList *CXspFile::ReadSceneModels()
1686
{
1687
	// read the scene file
1688
	if ( !m_pSceneFile )
1689
		m_pSceneFile = this->GetFirstFile(FILETYPE_SHIPSCENE);
1690
 
1691
	if ( !m_pSceneFile )
1692
		return NULL;
1693
 
1694
	// check if its packed
1695
	size_t datasize;
1696
	unsigned char *data = m_pSceneFile->UncompressData((long *)&datasize, 0);
1697
 
1698
	// if data wasn't compressed, then copy it itself as we are editing it
1699
	bool deleteData = false;
1700
	if ( data == m_pSceneFile->GetData() )
1701
	{
1702
		data = new unsigned char[m_pSceneFile->GetDataSize()];
1703
		memcpy(data, m_pSceneFile->GetData(), m_pSceneFile->GetDataSize());
1704
		deleteData = true;
1705
	}
1706
 
1707
	if ( data && datasize )
1708
	{
1709
		if ( m_pSceneFile->CheckPackedExtension() )
1710
			data = UnPCKData(data, datasize, &datasize);
1711
	}
1712
 
1713
	if ( !data || !datasize )
1714
		return NULL;
1715
 
1716
	CyStringList *lModels = new CyStringList;
1717
 
1718
	size_t pos = 0;
1719
	bool newline = true;
1720
	bool online = false;
1721
	while ( pos < datasize )
1722
	{
1723
		char c = data[pos];
1724
		++pos;
1725
 
1726
		// skip until next line
1727
		if ( !newline && !online )
1728
		{
1729
			if ( c == '\n' )
1730
				newline = true;
1731
			continue;
1732
		}
1733
 
1734
		if ( newline )
1735
		{
1736
			if ( c == ' ' || c == 9 || c == '\n' || c == '\r' )
1737
				continue;
1738
 
1739
			newline = false;
1740
 
1741
			if ( c == 'P' || c == 'p' )
1742
			{
1743
				while ( data[pos] == ' ' ) pos++;
1744
				unsigned char *line = (data + pos);
1745
				while ( data[pos] != ' ' && data[pos] != ';' ) pos++;
1746
				data[pos] = '\0';
1747
				if ( atoi((const char *)line) == lModels->Count() )
1748
					online = true;
1749
			}
1750
		}
1751
		// this line is out model
1752
		else if ( online )
1753
		{
1754
			if ( c == 'B' || c == 'b' )
1755
			{
1756
				while(data[pos] == ' ') pos++;
1757
				unsigned char *line = (data + pos);
1758
				while(data[pos] != ';') pos++;
1759
				data[pos] = '\0';
1760
 
1761
				lModels->PushBack((char *)line);
1762
				online = false;
1763
			}
1764
		}
1765
	}
1766
 
1767
	if ( deleteData )
1768
		delete data;
1769
 
1770
	return lModels;
1771
}
1772
 
42 cycrow 1773
void CXspFile::extractCutData(CVirtualFileSystem *pVfs, CyStringList *sceneModels, bool add)
1774
{
1775
	std::vector<int> cuts;
1776
	for ( CListNode<SDummy> *node = m_lDummy.Front(); node; node = node->next() ) {
1777
		Utils::String data = node->Data()->sData;
1778
		int states = data.token(";", 3);
1779
		for ( int i = 0; i < states; i++ ) {
1780
			int cutid = data.token(";", (i * 2) + 5);
1781
			if ( !cutid ) continue;
1782
			cuts.push_back(cutid);
1783
		}
1784
	}
1785
 
1786
	if ( cuts.empty() ) return;
1787
 
79 cycrow 1788
	if ( pVfs->ExtractGameFile("types/CutData.pck", CPackages::tempDirectory() + "tmp.dat").empty() ) return;
42 cycrow 1789
 
79 cycrow 1790
	CFileIO File(CPackages::tempDirectory() + "tmp.dat");
52 cycrow 1791
	if ( !File.exists() ) return;
42 cycrow 1792
 
1793
	CyStringList *lines = File.ReadLinesStr();
1794
	int count = -1;
1795
	for ( SStringList *node = lines->Head(); node; node = node->next ) {
1796
		Utils::String line = node->str.ToString();
1797
		line.removeChar('\r');
1798
		line.removeChar(' ');
1799
		line.removeFirstSpace();
1800
		if ( line[0] == '/' ) continue;
1801
		if ( count == -1 ) count = line.token(";", 1);
1802
		else {
1803
			int max;
1804
			Utils::String *words = line.tokenise(";", &max);
1805
			if ( words && max ) {
1806
				for ( int i = 0; i < max; i += 2 ) {
1807
					int cutid = words[i];
1808
					if ( !cutid ) continue;
1809
					for ( std::vector<int>::iterator itr = cuts.begin(); itr != cuts.end(); itr++ ) {
1810
						if ( (*itr) == cutid ) {
1811
							this->AddCutData(words[i] + ";" + words[i + 1] + ";");
1812
							if ( add ) {
1813
								sceneModels->PushBack(CyString(words[i + 1]));
1814
							}
1815
							break;
1816
						}
1817
					}
1818
				}
1819
				CLEANSPLIT(words, max);
1820
			}
1821
		}
1822
	}
1823
}
1824
 
35 cycrow 1825
void CXspFile::extractDummies(CVirtualFileSystem *pVfs, CyStringList *sceneModels, bool add)
1 cycrow 1826
{
1827
	if ( !sceneModels ) return;
31 cycrow 1828
 
1829
	bool extracted = false;
79 cycrow 1830
	if ( !pVfs->ExtractGameFile("types/dummies.pck", CPackages::tempDirectory() + "tmp.dat").empty() ) {
1831
		CFileIO File(CPackages::tempDirectory() + "tmp.dat");
52 cycrow 1832
		if ( File.exists() )
1 cycrow 1833
		{
39 cycrow 1834
			Utils::String section;
1 cycrow 1835
			int secCount = 0;
1836
			CyStringList *lines = File.ReadLinesStr();
1837
			for ( SStringList *node = lines->Head(); node; node = node->next )
1838
			{
1839
				node->str.RemoveFirstSpace();
1840
				node->str.RemoveChar(9);
1841
				node->str.RemoveChar('\r');
1842
				if ( node->str.Empty() )
1843
					continue;
1844
				if ( node->str[0] == '/' )
1845
					continue;
1846
 
1847
				// not in a section yet
1848
				if ( secCount <= 0 )
1849
				{
39 cycrow 1850
					section = node->str.GetToken(";", 1, 1).ToString();
1 cycrow 1851
					secCount = node->str.GetToken(";", 2, 2).ToInt();
1852
				}
1853
				else
1854
				{
39 cycrow 1855
					Utils::String first = node->str.GetToken(";", 1, 1).ToString();
1 cycrow 1856
					if ( sceneModels->FindString(first) )
1857
					{
39 cycrow 1858
						this->AddDummy(section, node->str.ToString());
1 cycrow 1859
 
1860
						if ( add )
1861
						{
1862
							int pos = 4;
1863
							int scene = node->str.GetToken(";", 3, 3).ToInt();
1864
							for ( int i = 0; i < scene; i++ )
1865
							{
1866
								sceneModels->PushBack(node->str.GetToken(";", 5 + (i * 2), 5 + (i * 2)));
1867
								pos += 2;
1868
							}
1869
 
1870
							int model = node->str.GetToken(";", pos, pos).ToInt();
1871
							for ( int i = 0; i < model; i++ )
1872
								sceneModels->PushBack(node->str.GetToken(";", pos + (i * 2) + 1, pos + (i * 2) + 1));
1873
						}
1874
					}
1875
					--secCount;
1876
 
1877
				}
1878
			}
1879
 
1880
			delete lines;
52 cycrow 1881
			File.remove();
1 cycrow 1882
		}
1883
	}
1884
}
1885
 
35 cycrow 1886
void CXspFile::extractComponants(CVirtualFileSystem *pVfs, CyStringList *sceneModels)
1 cycrow 1887
{
1888
	if ( !sceneModels ) return;
79 cycrow 1889
	if ( !pVfs->ExtractGameFile("types/components.pck", CPackages::tempDirectory() + "tmp.dat").empty() )
1 cycrow 1890
	{
79 cycrow 1891
		CFileIO File(CPackages::tempDirectory() + "tmp.dat");
52 cycrow 1892
		if ( File.exists() )
1 cycrow 1893
		{
39 cycrow 1894
			Utils::String file;
1895
			Utils::String section;
1 cycrow 1896
			int secCount = 0;
1897
			int secCount2 = 0;
1898
			CyStringList *lines = File.ReadLinesStr();
1899
			for ( SStringList *node = lines->Head(); node; node = node->next )
1900
			{
1901
				node->str.RemoveFirstSpace();
1902
				node->str.RemoveChar(9);
1903
				node->str.RemoveChar('\r');
1904
				if ( node->str.Empty() )
1905
					continue;
1906
				if ( node->str[0] == '/' )
1907
					continue;
1908
 
1909
				// not in a section yet
1910
				if ( secCount2 )
1911
				{
1912
					if ( sceneModels->FindString(file) )
39 cycrow 1913
						this->AddComponent(section, file, node->str.ToString());
1 cycrow 1914
					--secCount2;
1915
				}
1916
				else if ( secCount <= 0 )
1917
				{
39 cycrow 1918
					section = node->str.GetToken(";", 1, 1).ToString();
1 cycrow 1919
					secCount = node->str.GetToken(";", 2, 2).ToInt();
1920
				}
1921
				else
1922
				{
39 cycrow 1923
					file = node->str.GetToken(";", 1, 1).ToString();
1 cycrow 1924
					secCount2 = node->str.GetToken(";", 2, 2).ToInt();
1925
					--secCount;
1926
				}
1927
			}
1928
 
1929
			delete lines;
52 cycrow 1930
			File.remove();
1 cycrow 1931
		}
1932
	}
1933
}
1934
 
1935
bool CXspFile::GetTextureList(CyStringList *list, const unsigned char *olddata, size_t size)
1936
{
1937
	if ( !olddata || !size )
1938
		return false;
1939
 
1940
	size_t startLine = 0;
1941
	CyString line;
1942
	size_t pos = 0;
1943
 
1944
	unsigned char *data = new unsigned char[size];
1945
	memcpy(data, olddata, size);
1946
 
1947
	while ( (pos++) < size )
1948
	{
1949
		if ( data[pos] == '\n' )
1950
		{
1951
			data[pos] = '\0';
1952
			line = (char *)(data + startLine);
1953
			line.RemoveChar(9);
1954
			line.RemoveChar('\r');
1955
			line.RemoveFirstSpace();
1956
 
1957
			if ( !line.Empty() && line[0] != '/' )
1958
			{
1959
				CyString first = line.GetToken(":", 1, 1);
1960
				if ( first.Compare("MATERIAL6") )
1961
				{
1962
					int max;
1963
					CyString *strs = line.GetToken(":", 2).SplitToken("; ", &max);
1964
 
1965
					if ( strs && max >= 2)
1966
					{
1967
						for ( int i = 2; i < max; i++ )
1968
						{
1969
							CyString s = strs[i];
1970
							if ( s.IsIn(";") )
1971
								s = s.GetToken(";", 1, 1);
1972
							if ( !s.IsNumber() && !s.Compare("NULL") && s.IsIn(".") )
1973
								list->PushBack(s, "", true);
1974
						}
1975
					}
1976
 
1977
					CLEANSPLIT(strs, max)
1978
				}
1979
			}
1980
 
1981
			startLine = pos + 1;
1982
		}
1983
	}
1984
 
1985
	delete [] data;
1986
 
1987
	return true;
1988
}
1989
 
35 cycrow 1990
void CXspFile::extractTextures(CVirtualFileSystem *pVfs)
1 cycrow 1991
{
1992
	CyStringList lTextures;
1993
 
1994
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
1995
	{
1996
		C_File *f = node->Data();
1997
		if ( f->GetFileType() != FILETYPE_SHIPMODEL )
1998
			continue;
1999
 
2000
		// cant do these yet
2001
		if ( f->CheckFileExt("pbb") || f->CheckFileExt("bob") )
2002
		{
2003
			if ( !f->BobDecompile() )
2004
				continue;
2005
		}
2006
 
2007
		if ( !f->GetData() )
2008
		{
2009
			if ( !f->ReadFromFile() )
2010
				continue;
2011
		}
2012
 
2013
		unsigned char *data = NULL;
2014
		size_t size;
2015
 
2016
		if ( f->CheckFileExt("pbb") || f->CheckFileExt("pbd") )
2017
			data = f->UnPCKFile(&size);
2018
		else
2019
		{
2020
			data = f->GetData();
2021
			size = f->GetDataSize();
2022
		}
2023
 
2024
		this->GetTextureList(&lTextures, data, size);
2025
	}
2026
 
2027
	for ( SStringList *node = lTextures.Head(); node; node = node->next )
2028
	{
35 cycrow 2029
		if ( CFileIO(node->str).CheckFileExtension("dds") )
2030
			pVfs->extractGameFileToPackage(this, "dds\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER);
2031
		else 
2032
			pVfs->extractGameFileToPackage(this, "textures\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER);
1 cycrow 2033
	}
2034
}
2035
 
39 cycrow 2036
bool CXspFile::AddTextFromFile(const Utils::String &sFile, int textId)
1 cycrow 2037
{
39 cycrow 2038
	Utils::String file = sFile;
2039
 
1 cycrow 2040
	bool remove = false;
2041
	if ( CFileIO(file).CheckFileExtension("pck") )
2042
	{
39 cycrow 2043
		C_File F;
2044
		F.SetFilename(CyString(file));
1 cycrow 2045
		F.UnPCKFile();
79 cycrow 2046
		if ( F.WriteToFile(CPackages::tempDirectory() + "tmp.dat") )
1 cycrow 2047
		{
2048
			remove = true;
79 cycrow 2049
			file = CPackages::tempDirectory() + "tmp.dat";
1 cycrow 2050
		}
2051
	}
2052
 
78 cycrow 2053
	/*
68 cycrow 2054
	std::wfstream fileStream(file.c_str());
2055
	if ( fileStream.is_open() ) {
2056
		while(!fileStream.eof()) {
2057
			std::wstring line;
2058
			std::getline(fileStream, line);
2059
			int i =0;
2060
		}
2061
		fileStream.close();
2062
	}
78 cycrow 2063
	*/
68 cycrow 2064
 
1 cycrow 2065
	FILE *fid = fopen(file.c_str(), "r");
2066
	if ( fid )
2067
	{
2068
		bool ret = this->AddTextFromFile(fid, textId);
2069
		fclose(fid);
2070
 
52 cycrow 2071
		if ( remove ) CFileIO::Remove(file);
50 cycrow 2072
		_changed();
1 cycrow 2073
		return ret;
2074
	}
2075
 
2076
	return false;
2077
}
2078
 
39 cycrow 2079
bool CXspFile::ImportBodies(CyStringList *sceneModels, const Utils::String &filename)
1 cycrow 2080
{
2081
	CFileIO File(filename);
52 cycrow 2082
	if ( File.exists() )
1 cycrow 2083
	{
39 cycrow 2084
		Utils::String sSection;
1 cycrow 2085
		int section = 0;
2086
		CyStringList *lines = File.ReadLinesStr();
2087
		for ( SStringList *node = lines->Head(); node; node = node->next )
2088
		{
2089
			node->str.RemoveChar(9);
2090
			node->str.RemoveChar('\r');
2091
			node->str.RemoveFirstSpace();
2092
			if ( node->str.Empty() )
2093
				continue;
2094
			if ( node->str[0] == '/' )
2095
				continue;
2096
 
2097
			// are we looking for a section
2098
			if ( section <= 0 )
2099
			{
39 cycrow 2100
				sSection = node->str.GetToken(";", 1, 1).ToString();
1 cycrow 2101
				section = node->str.GetToken(";", 2, 2).ToInt();
2102
			}
2103
			else
2104
			{
2105
				int max;
2106
				CyString *strs = node->str.SplitToken(";", &max);
2107
				if ( strs && max )
2108
				{
2109
					for ( int i = 0; i < max; i++ )
2110
					{
2111
						strs[i].RemoveSpaces();
2112
						if (strs[i].Empty() )
2113
							continue;
2114
						if ( sceneModels->FindString(strs[i]) )
39 cycrow 2115
							this->AddBody(sSection, strs[i].ToString());
1 cycrow 2116
						--section;
2117
					}
2118
				}
2119
				CLEANSPLIT(strs, max)
2120
			}
2121
		}
2122
		delete lines;
2123
		return true;
2124
	}
2125
 
2126
	return false;
2127
}
2128
 
39 cycrow 2129
bool CXspFile::ImportCockpits(const Utils::String &filename)
1 cycrow 2130
{
2131
	CFileIO File(filename);
52 cycrow 2132
	if ( File.exists() )
1 cycrow 2133
	{
2134
		CyStringList *lines = File.ReadLinesStr();
2135
		int entries = 0;
2136
		for ( SStringList *node = lines->Head(); node; node = node->next )
2137
		{
2138
			node->str.RemoveChar(9);
2139
			node->str.RemoveChar('\r');
2140
			node->str.RemoveFirstSpace();
2141
			if ( node->str.Empty() )
2142
				node->remove = true;
2143
			else if ( node->str[0] == '/' )
2144
				node->remove = true;
2145
			else if ( !entries )
2146
			{
2147
				entries = node->str.GetToken(";", 2, 2).ToInt();
2148
				node->remove = true;
2149
			}
2150
		}
2151
		lines->RemoveMarked();
2152
 
2153
		// now get all the entries from TShips
2154
		for ( int i = 0; i < 6; i++ )
2155
		{
14 cycrow 2156
			int idx = m_sData.token(";", 32 + (i * 2));
1 cycrow 2157
			if ( idx < lines->Count() && idx )
2158
			{
39 cycrow 2159
				Utils::String turret = lines->GetAt(idx)->str.ToString();
1 cycrow 2160
				int pos = -1;
14 cycrow 2161
				Utils::String id;
39 cycrow 2162
				while ( id.empty() && pos > -100 ) id = turret.token(";", pos--);
14 cycrow 2163
				m_sData = m_sData.replaceToken(";", 32 + (i * 2), id + "(" + (long)idx + ")");
1 cycrow 2164
 
2165
				this->AddCockpit(turret, 0);
2166
			}
2167
		}
2168
 
2169
		delete lines;
2170
		return true;
2171
	}
2172
	return false;
2173
}
2174
 
35 cycrow 2175
bool CXspFile::extractCockpits(CVirtualFileSystem *pVfs)
1 cycrow 2176
{
79 cycrow 2177
	if ( !pVfs->ExtractGameFile("types/TCockpits.pck", CPackages::tempDirectory() + "tmp.dat").empty() ) {
2178
		bool ret = this->ImportCockpits(CPackages::tempDirectory() + "tmp.dat");
2179
		CFileIO::Remove(CPackages::tempDirectory() + "tmp.dat");
1 cycrow 2180
 
2181
		return ret;
2182
	}
2183
 
2184
	return false;
2185
}
2186
 
35 cycrow 2187
bool CXspFile::extractBodies(CVirtualFileSystem *pVfs, CyStringList *sceneModels)
1 cycrow 2188
{
2189
	if ( !sceneModels ) return false;
31 cycrow 2190
 
79 cycrow 2191
	if ( !pVfs->ExtractGameFile("types/Bodies.pck", CPackages::tempDirectory() + "tmp.dat").empty() ) {
2192
		bool ret = this->ImportBodies(sceneModels, CPackages::tempDirectory() + "tmp.dat");
2193
		CFileIO::Remove(CPackages::tempDirectory() + "tmp.dat");
1 cycrow 2194
 
2195
		return ret;
2196
	}
2197
 
2198
	return false;
2199
}
2200
 
2201
bool CXspFile::AddTextFromFile(FILE *id, int textId)
2202
{
14 cycrow 2203
	if ( textId == -1 && !m_sData.empty() )
2204
		textId = m_sData.token(";", 7);
1 cycrow 2205
 
2206
	if ( textId <= 0 )
2207
		return false;
2208
 
39 cycrow 2209
	Utils::String line;
1 cycrow 2210
	if ( !id )
2211
		return false;
2212
 
2213
	bool added = false;
2214
 
39 cycrow 2215
	Utils::String shipName;
2216
	Utils::String shipDesc;
1 cycrow 2217
 
68 cycrow 2218
	int lastAddedGameID = 0;
2219
	int currentGameID = 0;
1 cycrow 2220
	int lang = 0;
2221
	bool inpage = false;
2222
	while ( !feof(id) )
2223
	{
39 cycrow 2224
		if ( !shipName.empty() && !shipDesc.empty() )
1 cycrow 2225
		{
2226
			added = true;
2227
			break;
2228
		}
2229
 
39 cycrow 2230
		line.readToEndOfLine(id, 0, false);
2231
		line.removeChar(9);
2232
		line.removeChar('\r');
2233
		line.removeFirstSpace();
1 cycrow 2234
 
2235
		if ( inpage )
2236
		{
68 cycrow 2237
			if ( line.left(6).Compare("</page") ) {
2238
				inpage = false;
2239
				continue;
2240
			}
1 cycrow 2241
 
2242
			// find matching id
39 cycrow 2243
			if ( line.left(6).Compare("<t id=") )
1 cycrow 2244
			{
39 cycrow 2245
				int pos = line.findPos("id=\"", 0);
1 cycrow 2246
				if ( pos != -1 )
2247
				{
68 cycrow 2248
					pos += 4;
2249
					int endpos = line.findPos("\"", pos);
1 cycrow 2250
					if ( endpos != -1 )
2251
					{
68 cycrow 2252
						int id = line.mid(pos, endpos);
1 cycrow 2253
						if ( id == textId || id == (textId + 1) )
2254
						{
39 cycrow 2255
							pos = line.findPos(">", endpos);
1 cycrow 2256
							if ( pos != -1 )
2257
							{
39 cycrow 2258
								endpos = line.findPos("</t>", pos);
1 cycrow 2259
								if ( endpos != -1 )
2260
								{
2261
									if ( id == textId )
68 cycrow 2262
										shipName = line.mid(pos + 1, endpos);
1 cycrow 2263
									else
68 cycrow 2264
										shipDesc = line.mid(pos + 1, endpos);
2265
									lastAddedGameID = currentGameID;
1 cycrow 2266
								}
2267
							}
2268
						}
2269
					}
2270
				}
2271
			}
2272
		}
2273
		else if ( lang ) // search for page 17
2274
		{
39 cycrow 2275
			if ( line.left(8).Compare("<page id") )
1 cycrow 2276
			{
39 cycrow 2277
				int pos = line.findPos("id=\"");
1 cycrow 2278
				if ( pos != -1 )
2279
				{
68 cycrow 2280
					pos += 4;
2281
					int endpos = line.findPos("\"", pos);
1 cycrow 2282
					if ( endpos != -1 )
2283
					{
68 cycrow 2284
						Utils::String sId = line.mid(pos, endpos);
39 cycrow 2285
						int id = sId;
68 cycrow 2286
						if ( sId.length() > 4 ) {
2287
							id = sId.right(4);
2288
							currentGameID = sId.left(sId.length() - 4);
2289
						}
2290
 
2291
						if ( currentGameID >= lastAddedGameID && id == 17 )
1 cycrow 2292
							inpage = true;
2293
					}
2294
				}
2295
			}
2296
		}
39 cycrow 2297
		else if ( line.left(12).Compare("<language id") )
1 cycrow 2298
		{
39 cycrow 2299
			int pos = line.findPos("id=\"");
1 cycrow 2300
			if ( pos != -1 )
2301
			{
68 cycrow 2302
				// move past the id=
2303
				pos += 4;
2304
 
2305
				Utils::String s = line.right(-pos);
2306
				Utils::String s2 = line.mid(pos, -1);
2307
				int endpos = line.findPos("\"", pos);
1 cycrow 2308
				if ( endpos != -1 )
68 cycrow 2309
					lang = line.mid(pos, endpos);
1 cycrow 2310
			}
2311
		}
2312
	}
2313
 
2314
	// incase we only found the shipname
39 cycrow 2315
	if ( !shipName.empty() )
1 cycrow 2316
		added = true;
2317
 
2318
	if ( added )
2319
	{
50 cycrow 2320
		if ( lang == 44 || this->name().empty())
1 cycrow 2321
		{
50 cycrow 2322
			this->setName(shipName);
48 cycrow 2323
			this->setDescription(shipDesc.findReplace("&amp", "&"));
1 cycrow 2324
		}
2325
		this->AddText(lang, shipName, shipDesc);
2326
		return true;	
2327
	}
2328
 
2329
	return false;
2330
}
2331
 
31 cycrow 2332
void CXspFile::ExtractTexts(CCatFile *catFile, CCatFile *secondCatFile, int textId)
1 cycrow 2333
{
2334
	for ( CListNode<SInCatFile> *node = catFile->GetFiles()->Front(); node; node = node->next() )
2335
	{
2336
		SInCatFile *f = node->Data();
2337
		if ( !f->sFile.Left(2).Compare("t\\") && !f->sFile.Left(2).Compare("t/") )
2338
			continue;
2339
 
2340
		// extract the text file and read in the data
108 cycrow 2341
		bool extracted = catFile->ExtractFile(f->sFile, CPackages::GetTempDirectory() + "/tmp.dat");
2342
		if ( !extracted && secondCatFile ) extracted = secondCatFile->ExtractFile(f->sFile, CPackages::GetTempDirectory() + "/tmp.dat");
31 cycrow 2343
		if ( extracted ) {
108 cycrow 2344
			this->AddTextFromFile(CPackages::tempDirectory() + "/tmp.dat", textId);
2345
			CFileIO::Remove(CPackages::tempDirectory() + "/tmp.dat");
1 cycrow 2346
		}
2347
	}
2348
}
2349
 
35 cycrow 2350
bool CXspFile::processSceneFileSection(int section, CVirtualFileSystem *pVfs, CyStringList *lModels, CProgressInfo *progress)
1 cycrow 2351
{
2352
	if ( progress ) progress->UpdateStatus(section);
2353
 
2354
	switch ( section )
2355
	{
2356
		case IMPORTSHIP_COMPONANT:
2357
			if ( !lModels ) return false;
35 cycrow 2358
			this->extractComponants(pVfs, lModels);
1 cycrow 2359
			break;
2360
 
2361
		case IMPORTSHIP_MODELS:
2362
			{
2363
				if ( !lModels ) return false;
2364
				for ( SStringList *node = lModels->Head(); node; node = node->next )
2365
				{
2366
					if ( node->str.IsNumber() ) // count be componants or dummy
2367
						continue;
35 cycrow 2368
					if ( pVfs->extractGameFileToPackage(this, "objects\\" + Utils::String(node->str.ToString()) + ".pbb", FILETYPE_SHIPMODEL, "objects\\" + Utils::String(node->str.ToString()) + ".bob") )
1 cycrow 2369
						continue;
35 cycrow 2370
					if ( pVfs->extractGameFileToPackage(this, "objects\\" + Utils::String(node->str.ToString()) + ".pbd", FILETYPE_SHIPMODEL, "objects\\" + Utils::String(node->str.ToString()) + ".bod") )
1 cycrow 2371
						continue;
2372
				}
2373
			}
2374
			break;
2375
 
2376
		case IMPORTSHIP_DUMMIES:
2377
			if ( !lModels ) return false;
35 cycrow 2378
			this->extractDummies(pVfs, lModels, true);
42 cycrow 2379
			this->extractCutData(pVfs, lModels, true);
1 cycrow 2380
			break;
2381
 
2382
		// extract the textures
2383
		case IMPORTSHIP_TEXTURES:
35 cycrow 2384
			this->extractTextures(pVfs);
1 cycrow 2385
			break;
2386
 
2387
		case IMPORTSHIP_TEXTS:
2388
			// extract the text file entries
35 cycrow 2389
			pVfs->extractTexts(this, m_sData.token(";", 7));
1 cycrow 2390
			break;
2391
 
2392
		case IMPORTSHIP_BODIES:
2393
			// extract the bodies entries
2394
			if ( !lModels ) return false;
35 cycrow 2395
			this->extractBodies(pVfs, lModels);
1 cycrow 2396
			break;
2397
 
2398
		case IMPORTSHIP_COCKPITS:
2399
			// extract the cockpit entries
35 cycrow 2400
			this->extractCockpits(pVfs);
1 cycrow 2401
			break;
2402
	}
2403
 
2404
	return true;
2405
}
2406
 
35 cycrow 2407
bool CXspFile::processSceneFiles(CVirtualFileSystem *pVfs, CProgressInfo *progress)
1 cycrow 2408
{
2409
	// now lets parse our files
2410
	if ( progress ) progress->UpdateStatus(IMPORTSHIP_EXTRACTSCENE);
2411
	CyStringList *lModels = this->ReadSceneModels();
2412
	if ( !lModels )
2413
		return false;
2414
 
2415
	// extract componants, and add extra items to list
35 cycrow 2416
	if ( !this->processSceneFileSection(IMPORTSHIP_COMPONANT, pVfs, lModels, progress) )
1 cycrow 2417
		return false;
2418
 
2419
	//lets first find any model files
35 cycrow 2420
	if ( !this->processSceneFileSection(IMPORTSHIP_MODELS, pVfs, lModels, progress) )
1 cycrow 2421
		return false;
2422
 
2423
	// extract the dummies
35 cycrow 2424
	if ( !this->processSceneFileSection(IMPORTSHIP_DUMMIES, pVfs, lModels, progress) )
1 cycrow 2425
		return false;
2426
 
2427
	// extract the textures
35 cycrow 2428
	if ( !this->processSceneFileSection(IMPORTSHIP_TEXTURES, pVfs, lModels, progress) )
1 cycrow 2429
		return false;
2430
 
2431
	// extract the text file entries
35 cycrow 2432
	if ( !this->processSceneFileSection(IMPORTSHIP_TEXTS, pVfs, lModels, progress) )
1 cycrow 2433
		return false;
2434
 
2435
	// extract the bodies entries
35 cycrow 2436
	if ( !this->processSceneFileSection(IMPORTSHIP_BODIES, pVfs, lModels, progress) )
1 cycrow 2437
		return false;
2438
 
2439
	// extract the cockpit entries
35 cycrow 2440
	if ( !this->processSceneFileSection(IMPORTSHIP_COCKPITS, pVfs, lModels, progress) )
1 cycrow 2441
		return false;
2442
 
2443
	delete lModels;
2444
 
2445
	return true;
2446
}
2447
 
2448
 
2449
void CXspFile::PackAllFiles()
2450
{
2451
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
2452
	{
2453
		C_File *f = node->Data();
2454
		if ( f->GetFileType() == FILETYPE_SHIPSCENE || f->GetFileType() == FILETYPE_COCKPITSCENE || f->GetFileType() == FILETYPE_SHIPMODEL || f->GetFileType() == FILETYPE_SHIPOTHER )
41 cycrow 2455
		{	
2456
			/*
1 cycrow 2457
			if ( f->CheckFileExt("bod") )
2458
			{
2459
				if ( f->PCKFile() )
2460
					f->ChangeFileExt("pbd");
41 cycrow 2461
			}	
42 cycrow 2462
 
2463
			else */if ( f->CheckFileExt("bob") )
1 cycrow 2464
			{
2465
				if ( f->PCKFile() )
2466
					f->ChangeFileExt("pbb");
42 cycrow 2467
			}
1 cycrow 2468
		}
2469
	}
2470
}
2471
 
2472
void CXspFile::AdjustCockpits()
2473
{
2474
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
2475
	{
2476
		SCockpit *c = node->Data();
2477
		if ( c->iIndex < 0 )
2478
			continue;
2479
 
39 cycrow 2480
		Utils::String id = c->sCockpit.token(";", 19);
1 cycrow 2481
 
2482
		for ( int i = 0; i < 6; i++ )
2483
		{
39 cycrow 2484
			Utils::String tId = m_sData.token(";", 32 + (i * 2));
2485
			if ( tId.isNumber() && ((int)tId) == c->iIndex )
50 cycrow 2486
				m_sData = m_sData.replaceToken(";", 32 + (i * 2), (id + "(" + Utils::String::Number(c->iIndex) + ")").c_str());
1 cycrow 2487
		}
2488
	}
2489
}
2490
 
39 cycrow 2491
Utils::String CXspFile::FormatShipData(CyStringList *cockpits, int *text, int game)
1 cycrow 2492
{
39 cycrow 2493
	Utils::String data = (game == GAME_X3) ? this->GetX3ShipData() : this->GetTCShipData();
1 cycrow 2494
	// do turrets
2495
	for ( int t = 0; t < 6; t++ )
2496
	{
2497
		int oldPos = 0;
39 cycrow 2498
		Utils::String turret = data.token(";", 32 + (t * 2));
2499
		if ( !turret.isNumber() )
1 cycrow 2500
		{
39 cycrow 2501
			if ( turret.isin("(") )
1 cycrow 2502
			{
39 cycrow 2503
				oldPos = turret.tokens("(", 2).token(")", 1);
2504
				turret = turret.token("(", 1);
1 cycrow 2505
			}
2506
			int pos = cockpits->FindStringPos(turret);
2507
			if ( pos < 0 )	pos = oldPos;
39 cycrow 2508
			if ( pos >= cockpits->Count() ) pos = 0;
2509
			data = data.replaceToken(";", 32 + (t * 2), (long)pos);
1 cycrow 2510
		}
2511
	}
2512
	// adjust the weapons
2513
	int mask = this->GetLaserMask(game - 1);
2514
	if ( mask != -1 )
39 cycrow 2515
		data = data.replaceToken(";", 19, (long)mask);
1 cycrow 2516
	mask = this->GetMissileMask(game - 1);
2517
	if ( mask != -1 )
39 cycrow 2518
		data = data.replaceToken(";", 25, (long)mask);
1 cycrow 2519
 
2520
	// fix the ship text
2521
	if ( m_iOrgDesc > 0 )
2522
		(*text) = m_iOrgDesc;
39 cycrow 2523
	data = data.replaceToken(";", 7, (long)*text);
1 cycrow 2524
 
2525
	// add the ware id
39 cycrow 2526
	data.removeChar(9);
2527
	data.removeEndSpace();
1 cycrow 2528
	// remove the end ;
39 cycrow 2529
	while ( data.right(1) == ";" ) data.truncate(-1);
2530
	data = data.replaceToken(";", data.countToken(";"), this->GetShipID());
2531
	if ( data.right(1) != ";" )
1 cycrow 2532
		data += ";";
2533
 
2534
	return data;
35 cycrow 2535
}
2536