Subversion Repositories spk

Rev

Rev 158 | Rev 165 | 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
			{
127 cycrow 444
				newFile = new C_File(file);
1 cycrow 445
				special = 1;
446
			}
447
			else if ( file.Compare("types/Bodies.txt") || file.Compare("types/Bodies.pck") )
448
			{
127 cycrow 449
				newFile = new C_File(file);
1 cycrow 450
				special = 2;
451
			}
452
			else if ( file.Compare("types/Animations.txt") || file.Compare("types/Animations.pck") )
453
			{
127 cycrow 454
				newFile = new C_File(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
 
127 cycrow 772
bool CXspFile::GeneratePackagerScript(bool wildcard, Utils::CStringList *list, int game, const Utils::CStringList &gameAddons, bool datafile)
1 cycrow 773
{
127 cycrow 774
	if ( !CBaseFile::GeneratePackagerScript(wildcard, list, game, gameAddons, datafile) )
1 cycrow 775
		return false;
776
 
126 cycrow 777
	list->pushBack("# File Type, Script or Ship");
778
	list->pushBack("FileType: Ship");
779
	list->pushBack("");
98 cycrow 780
 
1 cycrow 781
	if ( m_iShipyard )
782
	{
126 cycrow 783
		list->pushBack("# Shipyards, Set which shipyards to add ships for sale to");
1 cycrow 784
		for ( int i = SHIPYARD_ARGON; i <= SHIPYARD_MAX; i *= 2 )
785
		{
786
			if ( this->IsShipyard(i) )
126 cycrow 787
				list->pushBack("Shipyard: " + GetShipyardName(i));
1 cycrow 788
		}
126 cycrow 789
		list->pushBack("");
1 cycrow 790
	}
791
 
792
	if ( m_iOrgDesc > 0 )
793
	{
126 cycrow 794
		list->pushBack("# Use Original Description, overrides text entrys to use one of the built in text");
795
		list->pushBack(Utils::String("OriginalDescription: ") + (long)m_iOrgDesc);
796
		list->pushBack("");
1 cycrow 797
	}
798
 
14 cycrow 799
	if ( !m_sID.empty() )
1 cycrow 800
	{
126 cycrow 801
		list->pushBack("# Ship ID, the ship id to identify the ship as");
802
		list->pushBack("ShipID: " + m_sID);
1 cycrow 803
	}
804
 
108 cycrow 805
	if ( m_bExistingShip )
806
	{
126 cycrow 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("");
108 cycrow 810
	}
811
 
14 cycrow 812
	if ( !m_sData.empty() )
1 cycrow 813
	{
126 cycrow 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("ShipData: " + m_sData);
816
		list->pushBack("");
1 cycrow 817
	}
818
 
108 cycrow 819
	if ( m_lText.size() ) {
126 cycrow 820
		list->pushBack("# Ship Texts, the name/description of the ship in each language: <LANGID> <NAME>|<DESCRIPTION>");
108 cycrow 821
		for(CListNode<SText> *node = m_lText.Front(); node; node = node->next()) {
126 cycrow 822
			list->pushBack(Utils::String("ShipText: ") + (long)node->Data()->iId + " " + node->Data()->sName + "|" + node->Data()->sDesc);
108 cycrow 823
		}
824
 
126 cycrow 825
		list->pushBack("");
1 cycrow 826
	}
827
 
108 cycrow 828
	if ( this->m_lWeaponMasks.size() ) {
126 cycrow 829
		list->pushBack("# Weapon Masks, the weapons for each game: <GAME> <MASK>");
108 cycrow 830
		for(CListNode<SWeaponMask> *node = m_lWeaponMasks.Front(); node; node = node->next()) {
126 cycrow 831
			list->pushBack(Utils::String("WeaponMask: ") + (long)node->Data()->iGame + " " + (long)node->Data()->iMask);
108 cycrow 832
		}
833
 
126 cycrow 834
		list->pushBack("");
108 cycrow 835
	}
836
 
837
	if ( this->m_lMissileMasks.size() ) {
126 cycrow 838
		list->pushBack("# Missile Masks, the missiles for each game: <GAME> <MASK>");
108 cycrow 839
		for(CListNode<SWeaponMask> *node = m_lMissileMasks.Front(); node; node = node->next()) {
126 cycrow 840
			list->pushBack(Utils::String("WeaponMask: ") + (long)node->Data()->iGame + " " + (long)node->Data()->iMask);
108 cycrow 841
		}
842
 
126 cycrow 843
		list->pushBack("");
108 cycrow 844
	}
845
 
846
	if ( this->m_lComponent.size() ) {
126 cycrow 847
		list->pushBack("# Ship Components, each component used in the ships scene: <SECTION> <MODELENTRY> <VALUES>");
108 cycrow 848
		for(CListNode<SComponent> *node = m_lComponent.Front(); node; node = node->next()) {
126 cycrow 849
			list->pushBack(Utils::String("Component: ") + node->Data()->sSection + " " + node->Data()->sSection2 + " " + node->Data()->sData);
108 cycrow 850
		}
126 cycrow 851
		list->pushBack("");
108 cycrow 852
	}
853
 
854
	if ( this->m_lDummy.size() ) {
126 cycrow 855
		list->pushBack("# Ship Dummies, each dummy entry used in the ships scene: <SECTION> <VALUE>");
108 cycrow 856
		for(CListNode<SDummy> *node = m_lDummy.Front(); node; node = node->next()) {
126 cycrow 857
			list->pushBack("Dummy: " + node->Data()->sSection + " " + node->Data()->sData);
108 cycrow 858
		}
126 cycrow 859
		list->pushBack("");
108 cycrow 860
	}
861
 
862
	if ( this->m_lCockpit.size() ) {
126 cycrow 863
		list->pushBack("# Cockpit entries, each cockpit value with thier weapons mask");
108 cycrow 864
		for(CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next()) {
126 cycrow 865
			list->pushBack("Cockpit: " + node->Data()->sCockpit.token(";", 19) + " " + node->Data()->sCockpit);
108 cycrow 866
			for(SWeaponMask *mask = node->Data()->lWeaponMask.First(); mask; mask = node->Data()->lWeaponMask.Next()) {
126 cycrow 867
				list->pushBack("CockpitWeapon: " + node->Data()->sCockpit.token(";", 19) + " " + (long)mask->iGame + " " + (long)mask->iMask);
108 cycrow 868
			}
869
		}
870
 
126 cycrow 871
		list->pushBack("");
108 cycrow 872
	}
873
 
874
	if ( !this->m_lCutData.Empty() ) {
126 cycrow 875
		list->pushBack("# Ship Cut Data");
108 cycrow 876
		for(SStringList *str = m_lCutData.Head(); str; str = str->next) {
126 cycrow 877
			list->pushBack(Utils::String("CutData: ") + str->str.ToString());
108 cycrow 878
		}
126 cycrow 879
		list->pushBack("");
108 cycrow 880
	}
881
 
882
	if ( !this->m_lBodies.Empty() ) {
126 cycrow 883
		list->pushBack("# Ship Bodies");
108 cycrow 884
		for(SStringList *str = m_lBodies.Head(); str; str = str->next) {
126 cycrow 885
			list->pushBack(Utils::String("Bodies: ") + str->str.ToString());
108 cycrow 886
		}
126 cycrow 887
		list->pushBack("");
108 cycrow 888
	}
889
 
890
	if ( !this->m_lAnimations.Empty() ) {
126 cycrow 891
		list->pushBack("# Ship Animations");
108 cycrow 892
		for(SStringList *str = m_lAnimations.Head(); str; str = str->next) {
126 cycrow 893
			list->pushBack(Utils::String("Animation: ") + str->str.ToString());
108 cycrow 894
		}
126 cycrow 895
		list->pushBack("");
108 cycrow 896
	}
897
 
1 cycrow 898
	if ( !datafile )
899
	{
127 cycrow 900
		if ( !CBaseFile::GeneratePackagerScriptFile(wildcard, list, game, gameAddons) )
1 cycrow 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
 
134 cycrow 1044
bool CXspFile::LoadPackageData(const Utils::String &sFirst, const Utils::String &sRest, const Utils::String &sMainGame, Utils::CStringList &otherGames, Utils::CStringList &gameAddons, CProgressInfo *progress)
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);
134 cycrow 1090
	else if ( !CBaseFile::LoadPackageData(sFirst, sRest, sMainGame, otherGames, gameAddons, progress) )
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
						}
1 cycrow 1981
					}
1982
 
1983
					CLEANSPLIT(strs, max)
1984
				}
1985
			}
1986
 
1987
			startLine = pos + 1;
1988
		}
1989
	}
1990
 
1991
	delete [] data;
1992
 
1993
	return true;
1994
}
1995
 
35 cycrow 1996
void CXspFile::extractTextures(CVirtualFileSystem *pVfs)
1 cycrow 1997
{
1998
	CyStringList lTextures;
1999
 
2000
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
2001
	{
2002
		C_File *f = node->Data();
2003
		if ( f->GetFileType() != FILETYPE_SHIPMODEL )
2004
			continue;
2005
 
115 cycrow 2006
		bool deleteData = false;
114 cycrow 2007
		unsigned char *data = NULL;
2008
		size_t size;
2009
 
1 cycrow 2010
		// cant do these yet
2011
		if ( f->CheckFileExt("pbb") || f->CheckFileExt("bob") )
2012
		{
115 cycrow 2013
			data = f->BobDecompile(&size);
2014
			if ( !data || !size ) {
114 cycrow 2015
				// search for the pbd or bod files that match and use them instead
2016
				Utils::String file;
2017
 
160 cycrow 2018
				file = CFileIO(f->getNameDirectory(NULL)).changeFileExtension("pbd");
114 cycrow 2019
				file = pVfs->ExtractGameFile(file, CPackages::tempDirectory() + "tmp.tmp");
2020
 
2021
				if ( file.empty() ) {
160 cycrow 2022
					file = CFileIO(f->getNameDirectory(NULL)).changeFileExtension("bod");
114 cycrow 2023
					file = pVfs->ExtractGameFile(file, CPackages::tempDirectory() + "tmp.tmp");
2024
				}
2025
 
2026
				if ( !file.empty() ) {
2027
					CFileIO File(file);
2028
					if ( File.exists() ) {
2029
						data = File.readAll(&size);
2030
						File.remove();
2031
					}
2032
				}
2033
 
2034
				if ( data && size ) 
2035
					this->GetTextureList(&lTextures, data, size);
1 cycrow 2036
				continue;
114 cycrow 2037
			}
1 cycrow 2038
 
115 cycrow 2039
			deleteData = true;
1 cycrow 2040
		}
2041
 
115 cycrow 2042
		if ( !data || !size ) {
2043
			if ( !f->GetData() )
2044
			{
2045
				if ( !f->ReadFromFile() )
2046
					continue;
2047
			}
1 cycrow 2048
 
115 cycrow 2049
 
2050
			if ( f->CheckFileExt("pbb") || f->CheckFileExt("pbd") )
2051
				data = f->UnPCKFile(&size);
2052
			else
2053
			{
2054
				data = f->GetData();
2055
				size = f->GetDataSize();
2056
			}
1 cycrow 2057
		}
115 cycrow 2058
		this->GetTextureList(&lTextures, data, size);
1 cycrow 2059
 
115 cycrow 2060
		if ( deleteData ) delete data;
1 cycrow 2061
	}
2062
 
2063
	for ( SStringList *node = lTextures.Head(); node; node = node->next )
2064
	{
114 cycrow 2065
		CFileIO F(node->str);
160 cycrow 2066
		if ( F.isFileExtension("fx") ) {
116 cycrow 2067
			/*
2068
			if ( !pVfs->extractGameFileToPackage(this, "shader\\1_1\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER) )
2069
				pVfs->extractGameFileToPackage(this, "shader\\1_1\\" + CFileIO(node->str.ToString()).ChangeFileExtension("fb").ToString(), FILETYPE_SHIPOTHER);
2070
			if ( !pVfs->extractGameFileToPackage(this, "shader\\1_4\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER) )
2071
				pVfs->extractGameFileToPackage(this, "shader\\1_4\\" + CFileIO(node->str.ToString()).ChangeFileExtension("fb").ToString(), FILETYPE_SHIPOTHER);
2072
			if ( !pVfs->extractGameFileToPackage(this, "shader\\2_0\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER) )
2073
				pVfs->extractGameFileToPackage(this, "shader\\2_0\\" + CFileIO(node->str.ToString()).ChangeFileExtension("fb").ToString(), FILETYPE_SHIPOTHER);
2074
			if ( !pVfs->extractGameFileToPackage(this, "shader\\2_a\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER) )
2075
				pVfs->extractGameFileToPackage(this, "shader\\2_a\\" + CFileIO(node->str.ToString()).ChangeFileExtension("fb").ToString(), FILETYPE_SHIPOTHER);
2076
			if ( !pVfs->extractGameFileToPackage(this, "shader\\2_b\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER) )
2077
				pVfs->extractGameFileToPackage(this, "shader\\2_b\\" + CFileIO(node->str.ToString()).ChangeFileExtension("fb").ToString(), FILETYPE_SHIPOTHER);
2078
			if ( !pVfs->extractGameFileToPackage(this, "shader\\3_0\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER) )
2079
				pVfs->extractGameFileToPackage(this, "shader\\3_0\\" + CFileIO(node->str.ToString()).ChangeFileExtension("fb").ToString(), FILETYPE_SHIPOTHER);
2080
				*/
114 cycrow 2081
		}
2082
		else {
116 cycrow 2083
			if ( pVfs->extractGameFileToPackage(this, "dds\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER) )
2084
				continue;
2085
 
2086
			if ( pVfs->extractGameFileToPackage(this, "dds\\" + Utils::String(node->str.ToString()).token(".", -1), FILETYPE_SHIPOTHER) )
2087
				continue;
2088
 
2089
			if ( pVfs->extractGameFileToPackage(this, "dds\\" + Utils::String(node->str.ToString()) + ".dds", FILETYPE_SHIPOTHER) )
2090
				continue;
2091
 
160 cycrow 2092
			if ( pVfs->extractGameFileToPackage(this, "dds\\" + Utils::String(F.changeFileExtension("dds")), FILETYPE_SHIPOTHER) )
116 cycrow 2093
				continue;
2094
 
2095
			if ( pVfs->extractGameFileToPackage(this, "textures\\" + Utils::String(node->str.ToString()), FILETYPE_SHIPOTHER) )
2096
				continue;
2097
 
2098
			if ( pVfs->extractGameFileToPackage(this, "textures\\" + Utils::String(node->str.ToString()).token(".", -1), FILETYPE_SHIPOTHER) )
2099
				continue;
2100
 
2101
			if ( pVfs->extractGameFileToPackage(this, "textures\\" + Utils::String(node->str.ToString()) + ".jpg", FILETYPE_SHIPOTHER) )
2102
				continue;
2103
 
160 cycrow 2104
			if ( pVfs->extractGameFileToPackage(this, "textures\\" + Utils::String(F.changeFileExtension("jpg")), FILETYPE_SHIPOTHER) )
116 cycrow 2105
				continue;
114 cycrow 2106
		}
1 cycrow 2107
	}
2108
}
2109
 
39 cycrow 2110
bool CXspFile::AddTextFromFile(const Utils::String &sFile, int textId)
1 cycrow 2111
{
39 cycrow 2112
	Utils::String file = sFile;
2113
 
1 cycrow 2114
	bool remove = false;
160 cycrow 2115
	if ( CFileIO(file).isFileExtension("pck") )
1 cycrow 2116
	{
39 cycrow 2117
		C_File F;
2118
		F.SetFilename(CyString(file));
1 cycrow 2119
		F.UnPCKFile();
129 cycrow 2120
		if (F.writeToFile(CPackages::tempDirectory() + "tmp.dat"))
1 cycrow 2121
		{
2122
			remove = true;
79 cycrow 2123
			file = CPackages::tempDirectory() + "tmp.dat";
1 cycrow 2124
		}
2125
	}
2126
 
78 cycrow 2127
	/*
68 cycrow 2128
	std::wfstream fileStream(file.c_str());
2129
	if ( fileStream.is_open() ) {
2130
		while(!fileStream.eof()) {
2131
			std::wstring line;
2132
			std::getline(fileStream, line);
2133
			int i =0;
2134
		}
2135
		fileStream.close();
2136
	}
78 cycrow 2137
	*/
68 cycrow 2138
 
118 cycrow 2139
	CFileIO F(file);
2140
	if ( F.exists() && F.startRead() ) {
2141
		bool ret = this->_addTextFromFile(F, textId);
2142
		F.close();
1 cycrow 2143
 
52 cycrow 2144
		if ( remove ) CFileIO::Remove(file);
50 cycrow 2145
		_changed();
1 cycrow 2146
		return ret;
2147
	}
2148
 
2149
	return false;
2150
}
2151
 
39 cycrow 2152
bool CXspFile::ImportBodies(CyStringList *sceneModels, const Utils::String &filename)
1 cycrow 2153
{
2154
	CFileIO File(filename);
52 cycrow 2155
	if ( File.exists() )
1 cycrow 2156
	{
39 cycrow 2157
		Utils::String sSection;
1 cycrow 2158
		int section = 0;
2159
		CyStringList *lines = File.ReadLinesStr();
2160
		for ( SStringList *node = lines->Head(); node; node = node->next )
2161
		{
2162
			node->str.RemoveChar(9);
2163
			node->str.RemoveChar('\r');
2164
			node->str.RemoveFirstSpace();
2165
			if ( node->str.Empty() )
2166
				continue;
2167
			if ( node->str[0] == '/' )
2168
				continue;
2169
 
2170
			// are we looking for a section
2171
			if ( section <= 0 )
2172
			{
39 cycrow 2173
				sSection = node->str.GetToken(";", 1, 1).ToString();
1 cycrow 2174
				section = node->str.GetToken(";", 2, 2).ToInt();
2175
			}
2176
			else
2177
			{
2178
				int max;
2179
				CyString *strs = node->str.SplitToken(";", &max);
2180
				if ( strs && max )
2181
				{
2182
					for ( int i = 0; i < max; i++ )
2183
					{
2184
						strs[i].RemoveSpaces();
2185
						if (strs[i].Empty() )
2186
							continue;
2187
						if ( sceneModels->FindString(strs[i]) )
39 cycrow 2188
							this->AddBody(sSection, strs[i].ToString());
1 cycrow 2189
						--section;
2190
					}
2191
				}
2192
				CLEANSPLIT(strs, max)
2193
			}
2194
		}
2195
		delete lines;
2196
		return true;
2197
	}
2198
 
2199
	return false;
2200
}
2201
 
39 cycrow 2202
bool CXspFile::ImportCockpits(const Utils::String &filename)
1 cycrow 2203
{
2204
	CFileIO File(filename);
52 cycrow 2205
	if ( File.exists() )
1 cycrow 2206
	{
2207
		CyStringList *lines = File.ReadLinesStr();
2208
		int entries = 0;
2209
		for ( SStringList *node = lines->Head(); node; node = node->next )
2210
		{
2211
			node->str.RemoveChar(9);
2212
			node->str.RemoveChar('\r');
2213
			node->str.RemoveFirstSpace();
2214
			if ( node->str.Empty() )
2215
				node->remove = true;
2216
			else if ( node->str[0] == '/' )
2217
				node->remove = true;
2218
			else if ( !entries )
2219
			{
2220
				entries = node->str.GetToken(";", 2, 2).ToInt();
2221
				node->remove = true;
2222
			}
2223
		}
2224
		lines->RemoveMarked();
2225
 
2226
		// now get all the entries from TShips
2227
		for ( int i = 0; i < 6; i++ )
2228
		{
14 cycrow 2229
			int idx = m_sData.token(";", 32 + (i * 2));
1 cycrow 2230
			if ( idx < lines->Count() && idx )
2231
			{
39 cycrow 2232
				Utils::String turret = lines->GetAt(idx)->str.ToString();
1 cycrow 2233
				int pos = -1;
14 cycrow 2234
				Utils::String id;
39 cycrow 2235
				while ( id.empty() && pos > -100 ) id = turret.token(";", pos--);
14 cycrow 2236
				m_sData = m_sData.replaceToken(";", 32 + (i * 2), id + "(" + (long)idx + ")");
1 cycrow 2237
 
2238
				this->AddCockpit(turret, 0);
2239
			}
2240
		}
2241
 
2242
		delete lines;
2243
		return true;
2244
	}
2245
	return false;
2246
}
2247
 
35 cycrow 2248
bool CXspFile::extractCockpits(CVirtualFileSystem *pVfs)
1 cycrow 2249
{
79 cycrow 2250
	if ( !pVfs->ExtractGameFile("types/TCockpits.pck", CPackages::tempDirectory() + "tmp.dat").empty() ) {
2251
		bool ret = this->ImportCockpits(CPackages::tempDirectory() + "tmp.dat");
2252
		CFileIO::Remove(CPackages::tempDirectory() + "tmp.dat");
1 cycrow 2253
 
2254
		return ret;
2255
	}
2256
 
2257
	return false;
2258
}
2259
 
35 cycrow 2260
bool CXspFile::extractBodies(CVirtualFileSystem *pVfs, CyStringList *sceneModels)
1 cycrow 2261
{
2262
	if ( !sceneModels ) return false;
31 cycrow 2263
 
79 cycrow 2264
	if ( !pVfs->ExtractGameFile("types/Bodies.pck", CPackages::tempDirectory() + "tmp.dat").empty() ) {
2265
		bool ret = this->ImportBodies(sceneModels, CPackages::tempDirectory() + "tmp.dat");
2266
		CFileIO::Remove(CPackages::tempDirectory() + "tmp.dat");
1 cycrow 2267
 
2268
		return ret;
2269
	}
2270
 
2271
	return false;
2272
}
2273
 
118 cycrow 2274
bool CXspFile::_addTextFromFile(CFileIO &F, int textId)
1 cycrow 2275
{
14 cycrow 2276
	if ( textId == -1 && !m_sData.empty() )
2277
		textId = m_sData.token(";", 7);
1 cycrow 2278
 
2279
	if ( textId <= 0 )
2280
		return false;
2281
 
118 cycrow 2282
	if ( !F.isOpened() )
1 cycrow 2283
		return false;
2284
 
2285
	bool added = false;
2286
 
39 cycrow 2287
	Utils::String shipName;
2288
	Utils::String shipDesc;
1 cycrow 2289
 
68 cycrow 2290
	int lastAddedGameID = 0;
2291
	int currentGameID = 0;
1 cycrow 2292
	int lang = 0;
2293
	bool inpage = false;
118 cycrow 2294
 
2295
	while(!F.atEnd()) {
39 cycrow 2296
		if ( !shipName.empty() && !shipDesc.empty() )
1 cycrow 2297
		{
2298
			added = true;
2299
			break;
2300
		}
2301
 
118 cycrow 2302
		Utils::String line = F.readEndOfLine();
39 cycrow 2303
		line.removeChar(9);
2304
		line.removeChar('\r');
2305
		line.removeFirstSpace();
118 cycrow 2306
 
1 cycrow 2307
		if ( inpage )
2308
		{
68 cycrow 2309
			if ( line.left(6).Compare("</page") ) {
2310
				inpage = false;
2311
				continue;
2312
			}
1 cycrow 2313
 
2314
			// find matching id
39 cycrow 2315
			if ( line.left(6).Compare("<t id=") )
1 cycrow 2316
			{
39 cycrow 2317
				int pos = line.findPos("id=\"", 0);
1 cycrow 2318
				if ( pos != -1 )
2319
				{
68 cycrow 2320
					pos += 4;
2321
					int endpos = line.findPos("\"", pos);
1 cycrow 2322
					if ( endpos != -1 )
2323
					{
68 cycrow 2324
						int id = line.mid(pos, endpos);
1 cycrow 2325
						if ( id == textId || id == (textId + 1) )
2326
						{
39 cycrow 2327
							pos = line.findPos(">", endpos);
1 cycrow 2328
							if ( pos != -1 )
2329
							{
39 cycrow 2330
								endpos = line.findPos("</t>", pos);
1 cycrow 2331
								if ( endpos != -1 )
2332
								{
2333
									if ( id == textId )
68 cycrow 2334
										shipName = line.mid(pos + 1, endpos);
1 cycrow 2335
									else
68 cycrow 2336
										shipDesc = line.mid(pos + 1, endpos);
2337
									lastAddedGameID = currentGameID;
1 cycrow 2338
								}
2339
							}
2340
						}
2341
					}
2342
				}
2343
			}
2344
		}
2345
		else if ( lang ) // search for page 17
2346
		{
39 cycrow 2347
			if ( line.left(8).Compare("<page id") )
1 cycrow 2348
			{
39 cycrow 2349
				int pos = line.findPos("id=\"");
1 cycrow 2350
				if ( pos != -1 )
2351
				{
68 cycrow 2352
					pos += 4;
2353
					int endpos = line.findPos("\"", pos);
1 cycrow 2354
					if ( endpos != -1 )
2355
					{
68 cycrow 2356
						Utils::String sId = line.mid(pos, endpos);
39 cycrow 2357
						int id = sId;
68 cycrow 2358
						if ( sId.length() > 4 ) {
2359
							id = sId.right(4);
2360
							currentGameID = sId.left(sId.length() - 4);
2361
						}
2362
 
2363
						if ( currentGameID >= lastAddedGameID && id == 17 )
1 cycrow 2364
							inpage = true;
2365
					}
2366
				}
2367
			}
2368
		}
39 cycrow 2369
		else if ( line.left(12).Compare("<language id") )
1 cycrow 2370
		{
39 cycrow 2371
			int pos = line.findPos("id=\"");
1 cycrow 2372
			if ( pos != -1 )
2373
			{
68 cycrow 2374
				// move past the id=
2375
				pos += 4;
2376
 
2377
				Utils::String s = line.right(-pos);
2378
				Utils::String s2 = line.mid(pos, -1);
2379
				int endpos = line.findPos("\"", pos);
1 cycrow 2380
				if ( endpos != -1 )
68 cycrow 2381
					lang = line.mid(pos, endpos);
1 cycrow 2382
			}
2383
		}
2384
	}
2385
 
2386
	// incase we only found the shipname
39 cycrow 2387
	if ( !shipName.empty() )
1 cycrow 2388
		added = true;
2389
 
2390
	if ( added )
2391
	{
50 cycrow 2392
		if ( lang == 44 || this->name().empty())
1 cycrow 2393
		{
50 cycrow 2394
			this->setName(shipName);
48 cycrow 2395
			this->setDescription(shipDesc.findReplace("&amp", "&"));
1 cycrow 2396
		}
2397
		this->AddText(lang, shipName, shipDesc);
2398
		return true;	
2399
	}
2400
 
2401
	return false;
2402
}
2403
 
31 cycrow 2404
void CXspFile::ExtractTexts(CCatFile *catFile, CCatFile *secondCatFile, int textId)
1 cycrow 2405
{
124 cycrow 2406
	for (auto itr = catFile->GetFiles()->begin(); itr != catFile->GetFiles()->end(); itr++ )
1 cycrow 2407
	{
124 cycrow 2408
		SInCatFile *f = *itr;
2409
		if ( !f->sFile.left(2).Compare("t\\") && !f->sFile.left(2).Compare("t/") )
1 cycrow 2410
			continue;
2411
 
2412
		// extract the text file and read in the data
158 cycrow 2413
		bool extracted = catFile->ExtractFile(f->sFile, CPackages::tempDirectory() + "/tmp.dat");
2414
		if ( !extracted && secondCatFile ) extracted = secondCatFile->ExtractFile(f->sFile, CPackages::tempDirectory() + "/tmp.dat");
31 cycrow 2415
		if ( extracted ) {
108 cycrow 2416
			this->AddTextFromFile(CPackages::tempDirectory() + "/tmp.dat", textId);
2417
			CFileIO::Remove(CPackages::tempDirectory() + "/tmp.dat");
1 cycrow 2418
		}
2419
	}
2420
}
2421
 
35 cycrow 2422
bool CXspFile::processSceneFileSection(int section, CVirtualFileSystem *pVfs, CyStringList *lModels, CProgressInfo *progress)
1 cycrow 2423
{
2424
	if ( progress ) progress->UpdateStatus(section);
2425
 
2426
	switch ( section )
2427
	{
2428
		case IMPORTSHIP_COMPONANT:
2429
			if ( !lModels ) return false;
35 cycrow 2430
			this->extractComponants(pVfs, lModels);
1 cycrow 2431
			break;
2432
 
2433
		case IMPORTSHIP_MODELS:
2434
			{
2435
				if ( !lModels ) return false;
2436
				for ( SStringList *node = lModels->Head(); node; node = node->next )
2437
				{
2438
					if ( node->str.IsNumber() ) // count be componants or dummy
2439
						continue;
35 cycrow 2440
					if ( pVfs->extractGameFileToPackage(this, "objects\\" + Utils::String(node->str.ToString()) + ".pbb", FILETYPE_SHIPMODEL, "objects\\" + Utils::String(node->str.ToString()) + ".bob") )
1 cycrow 2441
						continue;
35 cycrow 2442
					if ( pVfs->extractGameFileToPackage(this, "objects\\" + Utils::String(node->str.ToString()) + ".pbd", FILETYPE_SHIPMODEL, "objects\\" + Utils::String(node->str.ToString()) + ".bod") )
1 cycrow 2443
						continue;
2444
				}
2445
			}
2446
			break;
2447
 
2448
		case IMPORTSHIP_DUMMIES:
2449
			if ( !lModels ) return false;
35 cycrow 2450
			this->extractDummies(pVfs, lModels, true);
42 cycrow 2451
			this->extractCutData(pVfs, lModels, true);
1 cycrow 2452
			break;
2453
 
2454
		// extract the textures
2455
		case IMPORTSHIP_TEXTURES:
35 cycrow 2456
			this->extractTextures(pVfs);
1 cycrow 2457
			break;
2458
 
2459
		case IMPORTSHIP_TEXTS:
2460
			// extract the text file entries
35 cycrow 2461
			pVfs->extractTexts(this, m_sData.token(";", 7));
1 cycrow 2462
			break;
2463
 
2464
		case IMPORTSHIP_BODIES:
2465
			// extract the bodies entries
2466
			if ( !lModels ) return false;
35 cycrow 2467
			this->extractBodies(pVfs, lModels);
1 cycrow 2468
			break;
2469
 
2470
		case IMPORTSHIP_COCKPITS:
2471
			// extract the cockpit entries
35 cycrow 2472
			this->extractCockpits(pVfs);
1 cycrow 2473
			break;
2474
	}
2475
 
2476
	return true;
2477
}
2478
 
35 cycrow 2479
bool CXspFile::processSceneFiles(CVirtualFileSystem *pVfs, CProgressInfo *progress)
1 cycrow 2480
{
2481
	// now lets parse our files
2482
	if ( progress ) progress->UpdateStatus(IMPORTSHIP_EXTRACTSCENE);
2483
	CyStringList *lModels = this->ReadSceneModels();
2484
	if ( !lModels )
2485
		return false;
2486
 
2487
	// extract componants, and add extra items to list
35 cycrow 2488
	if ( !this->processSceneFileSection(IMPORTSHIP_COMPONANT, pVfs, lModels, progress) )
1 cycrow 2489
		return false;
2490
 
2491
	//lets first find any model files
35 cycrow 2492
	if ( !this->processSceneFileSection(IMPORTSHIP_MODELS, pVfs, lModels, progress) )
1 cycrow 2493
		return false;
2494
 
2495
	// extract the dummies
35 cycrow 2496
	if ( !this->processSceneFileSection(IMPORTSHIP_DUMMIES, pVfs, lModels, progress) )
1 cycrow 2497
		return false;
2498
 
2499
	// extract the textures
35 cycrow 2500
	if ( !this->processSceneFileSection(IMPORTSHIP_TEXTURES, pVfs, lModels, progress) )
1 cycrow 2501
		return false;
2502
 
2503
	// extract the text file entries
35 cycrow 2504
	if ( !this->processSceneFileSection(IMPORTSHIP_TEXTS, pVfs, lModels, progress) )
1 cycrow 2505
		return false;
2506
 
2507
	// extract the bodies entries
35 cycrow 2508
	if ( !this->processSceneFileSection(IMPORTSHIP_BODIES, pVfs, lModels, progress) )
1 cycrow 2509
		return false;
2510
 
2511
	// extract the cockpit entries
35 cycrow 2512
	if ( !this->processSceneFileSection(IMPORTSHIP_COCKPITS, pVfs, lModels, progress) )
1 cycrow 2513
		return false;
2514
 
2515
	delete lModels;
2516
 
2517
	return true;
2518
}
2519
 
2520
 
2521
void CXspFile::PackAllFiles()
2522
{
2523
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
2524
	{
2525
		C_File *f = node->Data();
2526
		if ( f->GetFileType() == FILETYPE_SHIPSCENE || f->GetFileType() == FILETYPE_COCKPITSCENE || f->GetFileType() == FILETYPE_SHIPMODEL || f->GetFileType() == FILETYPE_SHIPOTHER )
41 cycrow 2527
		{	
2528
			/*
1 cycrow 2529
			if ( f->CheckFileExt("bod") )
2530
			{
2531
				if ( f->PCKFile() )
2532
					f->ChangeFileExt("pbd");
41 cycrow 2533
			}	
42 cycrow 2534
 
2535
			else */if ( f->CheckFileExt("bob") )
1 cycrow 2536
			{
2537
				if ( f->PCKFile() )
2538
					f->ChangeFileExt("pbb");
42 cycrow 2539
			}
1 cycrow 2540
		}
2541
	}
2542
}
2543
 
2544
void CXspFile::AdjustCockpits()
2545
{
2546
	for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() )
2547
	{
2548
		SCockpit *c = node->Data();
2549
		if ( c->iIndex < 0 )
2550
			continue;
2551
 
39 cycrow 2552
		Utils::String id = c->sCockpit.token(";", 19);
1 cycrow 2553
 
2554
		for ( int i = 0; i < 6; i++ )
2555
		{
39 cycrow 2556
			Utils::String tId = m_sData.token(";", 32 + (i * 2));
2557
			if ( tId.isNumber() && ((int)tId) == c->iIndex )
50 cycrow 2558
				m_sData = m_sData.replaceToken(";", 32 + (i * 2), (id + "(" + Utils::String::Number(c->iIndex) + ")").c_str());
1 cycrow 2559
		}
2560
	}
2561
}
2562
 
39 cycrow 2563
Utils::String CXspFile::FormatShipData(CyStringList *cockpits, int *text, int game)
1 cycrow 2564
{
39 cycrow 2565
	Utils::String data = (game == GAME_X3) ? this->GetX3ShipData() : this->GetTCShipData();
1 cycrow 2566
	// do turrets
2567
	for ( int t = 0; t < 6; t++ )
2568
	{
2569
		int oldPos = 0;
39 cycrow 2570
		Utils::String turret = data.token(";", 32 + (t * 2));
2571
		if ( !turret.isNumber() )
1 cycrow 2572
		{
39 cycrow 2573
			if ( turret.isin("(") )
1 cycrow 2574
			{
39 cycrow 2575
				oldPos = turret.tokens("(", 2).token(")", 1);
2576
				turret = turret.token("(", 1);
1 cycrow 2577
			}
2578
			int pos = cockpits->FindStringPos(turret);
2579
			if ( pos < 0 )	pos = oldPos;
39 cycrow 2580
			if ( pos >= cockpits->Count() ) pos = 0;
2581
			data = data.replaceToken(";", 32 + (t * 2), (long)pos);
1 cycrow 2582
		}
2583
	}
2584
	// adjust the weapons
2585
	int mask = this->GetLaserMask(game - 1);
2586
	if ( mask != -1 )
39 cycrow 2587
		data = data.replaceToken(";", 19, (long)mask);
1 cycrow 2588
	mask = this->GetMissileMask(game - 1);
2589
	if ( mask != -1 )
39 cycrow 2590
		data = data.replaceToken(";", 25, (long)mask);
1 cycrow 2591
 
2592
	// fix the ship text
2593
	if ( m_iOrgDesc > 0 )
2594
		(*text) = m_iOrgDesc;
39 cycrow 2595
	data = data.replaceToken(";", 7, (long)*text);
1 cycrow 2596
 
2597
	// add the ware id
39 cycrow 2598
	data.removeChar(9);
2599
	data.removeEndSpace();
1 cycrow 2600
	// remove the end ;
39 cycrow 2601
	while ( data.right(1) == ";" ) data.truncate(-1);
2602
	data = data.replaceToken(";", data.countToken(";"), this->GetShipID());
2603
	if ( data.right(1) != ";" )
1 cycrow 2604
		data += ";";
2605
 
2606
	return data;
35 cycrow 2607
}
2608