Subversion Repositories spk

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
 
2
#include "SpkFile.h"
3
 
4
CSpkFile::CSpkFile() : CBaseFile ()
5
{
6
	SetDefaults ();
7
 
8
	m_iType = TYPE_SPK;
9
}
10
 
11
CSpkFile::~CSpkFile()
12
{
13
	Delete ();
14
}
15
/*
16
	Func:   SetDefaults
17
	Desc:   Sets the  default values when class is created
18
*/
19
void CSpkFile::SetDefaults ()
20
{
21
	m_pLastWare = NULL;
22
	m_iPackageType = PACKAGETYPE_NORMAL;
23
	m_bForceProfile = false;
24
	m_iScriptType = SCRIPTTYPE_CUSTOM;
25
 
26
	CBaseFile::SetDefaults ();
27
}
28
 
29
void CSpkFile::Delete ()
30
{
31
	m_lWares.clear(true);
32
	m_lSettings.clear(true);
33
 
34
	CBaseFile::Delete ();
35
}
36
 
37
 
38
bool CSpkFile::CheckHeader ( CyString header )
39
{
40
	if ( header.Compare("SPKCycrow") )
41
		return true;
42
	return false;
43
}
44
/*
45
	Func:   ParseValueLine
46
	Input:  String - single line from a file to set
47
	Return: Boolean - returns true if value exists
48
	Desc:   Reads the line and assigns the parameters for the file
49
*/
50
bool CSpkFile::ParseValueLine ( CyString line )
51
{
52
	CyString first = line.GetToken ( 1, ' ' );
53
	CyString rest  = line.GetToken ( 2, -1, ' ' );
54
 
55
	if ( first == "AnotherMod:" )
56
	{
57
		m_sOtherAuthor = rest.GetToken ( 1, '|' );
58
		m_sOtherName = rest.GetToken ( 2, -1, '|' );
59
	}
60
	else if ( line == "CustomStart" )
61
		m_iPackageType = PACKAGETYPE_CUSTOMSTART;
62
	else if ( line == "PackageUpdate" )
63
		m_iPackageType = PACKAGETYPE_UPDATE;
64
	else if ( line == "Patch" )
65
		m_iPackageType = PACKAGETYPE_PATCH;
66
	else if ( line == "ForceProfile" )
67
		m_bForceProfile = true;
68
	else if ( line == "Signed" )
69
		m_bSigned = true;
70
	else if ( first == "ScriptType:" )
71
		m_sScriptType = rest;
72
	else if ( first == "ScriptTypeNew:" )
73
		m_iScriptType = rest.ToInt();
74
	else if ( first == "PackageType:" )
75
		m_iPackageType = rest.ToInt();
76
	else if ( first == "Ware:" )
77
		AddWare ( rest );
78
	else if ( (first == "WareText:") && (m_pLastWare) )
79
		AddWareText ( rest );
80
	else if ( first == "Setting:" )
81
	{
82
		SSettingType *t = AddSetting ( rest.GetToken ( 2, '|' ), rest.GetToken ( 1, '|' ).ToInt() );
83
		ConvertSetting ( t, rest.GetToken ( 3, -1, '|' ) );
84
	}
85
	else
86
		return CBaseFile::ParseValueLine ( line );
87
 
88
	return true;
89
}
90
 
91
/*
92
	Func:   CreateValuesLine
93
	Return: String - returns the full string for values
94
	Desc:   Creates a single string for all values, this is used when compressing to write to the spk file
95
*/
96
CyString CSpkFile::CreateValuesLine ()
97
{
98
	CyString values = CBaseFile::CreateValuesLine ();
99
	// combine all values together
100
	if ( (!m_sOtherAuthor.Empty()) && (!m_sOtherName.Empty()) )
101
		values += (CyString("AnotherMod: ") + m_sOtherAuthor + "|" + m_sOtherName + "\n");
102
	if ( m_bForceProfile )
103
		values += "ForceProfile\n";
104
	if ( !m_sScriptType.Empty() )
105
		values += (CyString("ScriptType: ") + m_sScriptType + "\n");
106
	values += (CyString("PackageType: ") + (long)m_iPackageType + "\n");
107
	values += (CyString("ScriptTypeNew: ") + (long)m_iScriptType + "\n");
108
 
109
	for ( SSettingType *st = m_lSettings.First(); st; st = m_lSettings.Next() )
110
		values += (CyString("Setting: ") + CyString::Number(st->iType) + "|" + st->sKey + "|" + GetSetting(st) + "\n");
111
 
112
	for ( SWares *ware = m_lWares.First(); ware; ware = m_lWares.Next() )
113
	{
114
		if ( ware->iTextID > 0 )
115
			values += CyString("Ware: ") + ware->cType + ":" + ware->iPrice + ":" + (long)ware->iSize + ":" + (long)ware->iVolumn + ":" + ware->sID + ":" + (long)ware->iNotority + ":" + (long)ware->iTextID + "," + (long)ware->iTextPage + "\n";
116
		else
117
			values += CyString("Ware: ") + ware->cType + ":" + ware->iPrice + ":" + (long)ware->iSize + ":" + (long)ware->iVolumn + ":" + ware->sID + ":" + (long)ware->iNotority + "\n";
118
		for ( SWaresText *wt = ware->lText.First(); wt; wt = ware->lText.Next() )
119
			values += CyString("WareText: ") + (long)wt->iLang + " " + wt->sName + "|" + wt->sDesc + "\n";
120
	}
121
 
122
	return values;
123
}
124
 
125
CyString CSpkFile::GetCustomScriptType (int lang)
126
{
127
	if ( !m_sScriptType.Empty() )
128
	{
129
		int max;
130
		CyString *split = m_sScriptType.SplitToken("<br>", &max);
131
		if ( max && split )
132
		{
133
			for ( int i = 1; i < max; i++ )
134
			{
135
				CyString str = split[i];
136
				int num = str.GetToken(":", 1, 1).ToInt();
137
				CyString name = str.GetToken(":", 2);
138
 
139
				if ( num == lang )
140
				{
141
					CLEANSPLIT(split, max)
142
					return name;
143
				}
144
			}
145
 
146
			CyString ret = split[0];
147
			CLEANSPLIT(split, max)
148
 
149
			return ret;
150
		}
151
		CLEANSPLIT(split, max)
152
	}
153
	return m_sScriptType;
154
}
155
 
156
bool CSpkFile::WriteHeader(FILE *id, int valueheader, int valueComprLen)
157
{
158
	fprintf ( id, "SPKCycrow;%.2f;%d;%d\n", FILEVERSION, valueheader, valueComprLen );
159
	if ( ferror(id) )
160
		return false;
161
	return true;
162
}
163
 
164
void CSpkFile::AddWareText ( CyString rest )
165
{
166
	if ( !m_pLastWare )
167
		return;
168
 
169
	SWaresText *wt = new SWaresText;
170
	wt->iLang = rest.GetToken ( 1, ' ' ).ToInt();
171
	wt->sName = rest.GetToken ( 2, -1, ' ' ).GetToken ( 1, '|' );
172
	wt->sDesc = rest.GetToken ( 2, -1, ' ' ).GetToken ( 2, -1, '|' );
173
	m_pLastWare->lText.push_back ( wt );
174
 
175
	m_bChanged = true;
176
}
177
 
178
void CSpkFile::AddWare ( CyString rest )
179
{
180
	SWares *ware = new SWares;
181
	ware->iTextID = -1;
182
	ware->iTextPage = 0;
183
	ware->cType = rest.GetToken ( 1, ':' )[0];
184
	ware->iPrice = rest.GetToken ( 2, ':' ).ToLong();
185
	ware->iSize = rest.GetToken ( 3, ':' ).ToInt();
186
	ware->iVolumn = rest.GetToken ( 4, ':' ).ToInt();
187
	ware->sID = rest.GetToken ( 5, ':' );
188
	ware->iNotority = rest.GetToken ( 6, ':' ).ToInt();
189
	if ( !rest.GetToken( 7, ':' ).Empty() )
190
	{
191
		CyString r = rest.GetToken ( 7, ':' );
192
		ware->iTextID = r.GetToken(",", 1, 1).ToInt();
193
		ware->iTextPage = r.GetToken(",", 2, 2).ToInt();
194
	}
195
	m_lWares.push_back ( ware );
196
	m_pLastWare = ware;
197
 
198
	m_bChanged = true;
199
}
200
 
201
 
202
 
203
bool CSpkFile::ReadFileToMemory ( C_File *file )
204
{
205
	if ( !file )
206
		return false;
207
 
208
	// check if data is already extracted
209
	if ( (file->GetDataSize ()) && (file->GetData()) )
210
		return true;
211
 
212
	// no file to read from
213
	if ( m_sFilename.Empty() )
214
		return false;
215
 
216
	// now open the file
217
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
218
	if ( !id )
219
		return false;
220
 
221
	// read the header
222
	GetEndOfLine ( id, NULL, false );
223
	// skip past values
224
	fseek ( id, m_SHeader.lValueCompressSize, SEEK_CUR );
225
 
226
	// read the next header
227
	GetEndOfLine ( id, NULL, false );
228
	// skip past files
229
	fseek ( id, 4, SEEK_CUR );
230
	fseek ( id, m_SHeader2.lSize, SEEK_CUR );
231
 
232
	// skip the icon file
233
	if ( m_pIconFile )
234
	{
235
		fseek ( id, 4, SEEK_CUR );
236
		fseek ( id, m_pIconFile->GetDataSize (), SEEK_CUR );
237
	}
238
 
239
	// now were in the file section
240
	// skip past each one
241
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
242
	{
243
		C_File *fit = node->Data();
244
		if ( fit == file )
245
			break;
246
 
247
		fseek ( id, 4, SEEK_CUR );
248
		fseek ( id, fit->GetDataSize(), SEEK_CUR );
249
	}
250
 
251
	// now we should be at the start of the file
252
	// read the data into memory
253
	if ( !file->ReadFromFile ( id, file->GetDataSize() ) )
254
	{
255
		fclose ( id );
256
		return false;
257
	}
258
	fclose ( id );
259
 
260
	return true;
261
}
262
 
263
bool CSpkFile::CheckValidReadmes ()
264
{
265
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
266
	{
267
		C_File *file = node->Data();
268
		if ( file->GetFileType() != FILETYPE_README )
269
			continue;
270
		if ( !file->CheckValidFilePointer() )
271
			continue;
272
		return true;
273
	}
274
 
275
	return false;
276
}
277
 
278
 
279
 
280
void CSpkFile::ClearWares()
281
{
282
	for ( CListNode<SWares> *node = m_lWares.Front(); node; node = node->next() )
283
	{
284
		node->Data()->lText.clear(true);
285
		node->DeleteData();
286
	}
287
	m_bChanged = true;
288
	m_lWares.clear(true);
289
}
290
 
291
SWares *CSpkFile::FindWare ( CyString id )
292
{
293
	for ( SWares *w = m_lWares.First(); w; w = m_lWares.Next() )
294
	{
295
		if ( w->sID.ToUpper() == id.ToUpper() )
296
			return w;
297
	}
298
	return NULL;
299
}
300
 
301
void CSpkFile::RemoveWare ( CyString id )
302
{
303
	for ( SWares *w = m_lWares.First(); w; w = m_lWares.Next() )
304
	{
305
		if ( w->sID.ToUpper() == id.ToUpper() )
306
		{
307
			m_lWares.RemoveCurrent ();
308
			delete w;
309
			m_bChanged = true;
310
			return;
311
		}
312
	}
313
}
314
 
315
void CSpkFile::AddWare ( SWares *ware )
316
{
317
	ware->sID.RemoveChar ( ' ' );
318
	ware->sID = ware->sID.ToUpper();
319
 
320
	SWares *newware = FindWare ( ware->sID );
321
	if ( newware )
322
		m_lWares.remove ( newware );
323
 
324
	m_lWares.push_back ( ware );
325
	m_bChanged = true;
326
}
327
 
328
void CSpkFile::AddWareText ( SWares *w, int lang, CyString name, CyString desc )
329
{
330
	SWaresText *wt;
331
	for ( wt = w->lText.First(); wt; wt = w->lText.Next() )
332
	{
333
		if ( wt->iLang == lang )
334
		{
335
			wt->sDesc = desc;
336
			wt->sName = name;
337
			return;
338
		}
339
	}
340
 
341
	wt = new SWaresText;
342
	wt->iLang = lang;
343
	wt->sName = name;
344
	wt->sDesc = desc;
345
 
346
	w->lText.push_back ( wt );
347
	m_bChanged = true;
348
}
349
 
350
 
351
void CSpkFile::ClearWareText ( CyString id )
352
{
353
	SWares *w = FindWare ( id );
354
	ClearWareText ( w );
355
}
356
 
357
void CSpkFile::ClearWareText ( SWares *w )
358
{
359
	if ( !w ) return;
360
 
361
	w->lText.clear(true);
362
	m_bChanged = true;
363
}
364
 
365
void CSpkFile::RemoveWareText ( CyString wid, int lang )
366
{
367
	SWares *w = FindWare ( wid );
368
	if ( w )
369
	{
370
		for ( SWaresText *wt = w->lText.First(); wt; wt = w->lText.Next() )
371
		{
372
			if ( wt->iLang == lang )
373
			{
374
				w->lText.RemoveCurrent();
375
				m_bChanged = true;
376
				delete wt;
377
				break;
378
			}
379
		}
380
	}
381
}
382
 
383
int CSpkFile::CheckValidCustomStart ()
384
{
385
 
386
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
387
	{
388
		C_File *file = node->Data();
389
		if ( file->GetFileType() != FILETYPE_SCRIPT )
390
			continue;
391
 
392
		CyString basename = file->GetName().GetToken ( 1, file->GetName().NumToken('.') - 1, '.' );
393
		if ( basename.ToLower().Right(15) == ".initplayership" )
394
			return 0;
395
	}
396
	if ( !IsAnotherMod() )
397
		return 1;
398
	else
399
		return 2;
400
}
401
 
402
bool CSpkFile::UpdateSigned (bool updateFiles)
403
{
404
	// check for any custom wares
405
	// patch mods and custom starts are also not signed
406
	if ( (!m_lWares.empty()) || (this->IsPatch()) || (this->IsCustomStart()) )
407
	{
408
		m_bSigned = false;
409
		return false;
410
	}
411
 
412
	return CBaseFile::UpdateSigned(updateFiles);
413
}
414
 
415
SSettingType *CSpkFile::AddSetting ( CyString key, int type )
416
{
417
	key.RemoveChar ( '|' );
418
	SSettingType *t;
419
	for ( t = m_lSettings.First(); t; t = m_lSettings.Next() )
420
	{
421
		if ( t->sKey.upper() == key.lower() )
422
			return NULL;
423
	}
424
 
425
	switch ( type )
426
	{
427
		case SETTING_STRING:
428
			t = new SSettingString;
429
			break;
430
		case SETTING_INTEGER:
431
			t = new SSettingInteger;
432
			break;
433
		case SETTING_CHECK:
434
			t = new SSettingCheck;
435
			break;
436
	}
437
 
438
	if ( !t )
439
		return NULL;
440
 
441
	t->sKey = key;
442
	t->iType = type;
443
 
444
	m_lSettings.push_back ( t );
445
	m_bChanged = true;
446
 
447
	return t;
448
}
449
 
450
void CSpkFile::ConvertSetting ( SSettingType *t, CyString set )
451
{
452
	if ( !t )
453
		return;
454
 
455
	switch ( t->iType )
456
	{
457
		case SETTING_STRING:
458
			((SSettingString *)t)->sValue = set;
459
			break;
460
		case SETTING_INTEGER:
461
			((SSettingInteger *)t)->iValue = set.ToInt();
462
			break;
463
		case SETTING_CHECK:
464
			((SSettingCheck *)t)->bValue = set.ToBool();
465
			break;
466
	}
467
}
468
CyString CSpkFile::GetSetting ( SSettingType *t )
469
{
470
	if ( !t )
471
		return "";
472
 
473
	switch ( t->iType )
474
	{
475
		case SETTING_STRING:
476
			return ((SSettingString *)t)->sValue;
477
		case SETTING_INTEGER:
478
			return CyString::Number(((SSettingInteger *)t)->iValue);
479
		case SETTING_CHECK:
480
			return (((SSettingInteger *)t)->iValue) ? "1" : "0";
481
	}
482
 
483
	return "";
484
}
485
 
486
void CSpkFile::ClearSettings ()
487
{
488
	m_lSettings.clear(true);
489
	m_bChanged = true;
490
}
491
 
492
 
493
bool CSpkFile::IsMatchingMod ( CyString mod )
494
{
495
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
496
	{
497
		C_File *file = node->Data();
498
		if ( file->GetFileType() != FILETYPE_MOD )
499
			continue;
500
 
501
		if ( file->IsFakePatch() )
502
			continue;
503
 
504
		CyString filename = file->GetBaseName();
505
		if ( filename.lower() == mod.lower() )
506
			return true;
507
	}
508
	return false;
509
}
510
 
511
CyString CSpkFile::GetScriptTypeString(int lang)
512
{
513
	int iType = m_iScriptType;
514
 
515
	if ( this->IsLibrary() )
516
		return "Library";
517
	else if ( this->IsPackageUpdate() )
518
		return "Package Update";
519
	else if ( this->IsCustomStart() )
520
		return "Custom Start";
521
	else if ( this->IsPatch() )
522
		return "Patch";
523
	else if ( m_iScriptType == SCRIPTTYPE_CUSTOM )
524
	{
525
		CyString type = this->GetCustomScriptType(lang);
526
		if ( !type.Empty() )
527
			return type;
528
		iType = -1;
529
	}
530
 
531
	if (iType == -1)  // no script type
532
	{
533
		if ( this->IsFakePatch() )
534
			return "Fake Patch";
535
	}
536
 
537
	CyString sType = CSpkFile::GetScriptTypeStringStatic(m_iScriptType);
538
 
539
	if ( sType.Empty() )
540
		return "Other";
541
 
542
	return sType;	
543
}
544
 
545
int CSpkFile::ConvertScriptType(CyString sType)
546
{
547
	for ( int i = 0; i < SCRIPTTYPE_MAX; i++ )
548
	{
549
		if ( sType.Compare(CSpkFile::GetScriptTypeStringStatic(i)) )
550
			return i;
551
	}
552
 
553
	return -1;
554
}
555
 
556
CyString CSpkFile::GetScriptTypeStringStatic(int type)
557
{
558
	switch ( type )
559
	{
560
		case SCRIPTTYPE_CUSTOM:
561
			return "Custom";
562
		case SCRIPTTYPE_NAVIGATION:
563
			return "Navigation";
564
		case SCRIPTTYPE_COMBAT:
565
			return "Combat";
566
		case SCRIPTTYPE_MISSION:
567
			return "Mission";
568
		case SCRIPTTYPE_ALPLUGIN:
569
			return "AL Plugin";
570
		case SCRIPTTYPE_HOTKEY:
571
			return "Hotkey";
572
		case SCRIPTTYPE_SHIPUPGRADE:
573
			return "Ship Upgrade";
574
		case SCRIPTTYPE_SHIPCOMMAND:
575
			return "Ship Command";
576
		case SCRIPTTYPE_STATIONCOMMAND:
577
			return "Station Command";
578
		case SCRIPTTYPE_FLEET:
579
			return "Fleet Management";
580
		case SCRIPTTYPE_TRADE:
581
			return "Trade";
582
		case SCRIPTTYPE_PIRACY:
583
			return "Piracy";
584
		case SCRIPTTYPE_CHEAT:
585
			return "Cheat";
586
		case SCRIPTTYPE_EXTENSION:
587
			return "Extension Mods";
588
		case SCRIPTTYPE_REBALANCE:
589
			return "Rebalance";
590
		case SCRIPTTYPE_FIX:
591
			return "Vanilla Fix";
592
		case SCRIPTTYPE_GENERALMOD:
593
			return "General Mod";
594
		case SCRIPTTYPE_TOTAL:
595
			return "Totel Conversion";
596
		case SCRIPTTYPE_WINGCOMMAND:
597
			return "Wing Command";
598
	}
599
 
600
	return "Other";
601
}
602
 
603
bool CSpkFile::LoadPackageData(CyString first, CyString rest)
604
{
605
	if ( first.Compare("ScriptType") )
606
	{
607
		if ( rest.Compare("Library") || rest.Compare("Library Script") )
608
			this->SetLibrary();
609
		else if ( rest.Compare("Update") || rest.Compare("Package Update") || rest.Compare("Mod Update") )
610
			this->SetPackageUpdate();
611
		else if ( rest.Compare("Start") || rest.Compare("Custom Start") )
612
			this->SetCustomStart();
613
		else if ( rest.Compare("Patch") || rest.Compare("Patch Mod") )
614
			this->SetPatch();
615
		else
616
		{
617
			int check = rest.ToInt();
618
			if ( check || rest == "0" )
619
				m_iScriptType = check;
620
			else
621
			{
622
				m_iScriptType = CSpkFile::ConvertScriptType(rest);
623
				if ( m_iScriptType == -1 )
624
					m_sScriptType = rest;
625
			}
626
		}
627
	}
628
	else if ( first.Compare("AnotherMod") )
629
	{
630
		m_sOtherName = rest.GetToken("|", 1, 1);
631
		m_sOtherAuthor = rest.GetToken("|", 2);
632
	}
633
	else if ( first.Compare("WareName") || first.Compare("WareDesc") )
634
	{
635
		// find the ware to use
636
		SWares *useWare = m_pLastWare;
637
		CyString id = rest.GetToken(" ", 1, 1);
638
		for ( CListNode<SWares> *wNode = m_lWares.Front(); wNode; wNode = wNode->next() )
639
		{
640
			if ( wNode->Data()->sID.Compare(id) )
641
			{
642
				useWare = wNode->Data();
643
				break;
644
			}
645
		}
646
 
647
		// check if we have the id already
648
		if ( useWare )
649
		{
650
			int lang = rest.GetToken(" ", 2, 2).ToInt();
651
			SWaresText *wt = NULL;
652
			for ( CListNode<SWaresText> *tNode = useWare->lText.Front(); tNode; tNode = tNode->next() )
653
			{
654
				if ( tNode->Data()->iLang == lang )
655
				{
656
					wt = tNode->Data();
657
					break;
658
				}
659
			}
660
 
661
			if ( !wt )
662
			{
663
				wt = new SWaresText;
664
				wt->iLang = lang;
665
				useWare->lText.push_back(wt);
666
			}
667
 
668
			if ( first.Compare("WareName") )
669
				wt->sName = rest.GetToken(" ", 3);
670
			else
671
				wt->sDesc = rest.GetToken(" ", 3);
672
		}
673
	}
674
	else if ( first.Left(4).Compare("Ware") )
675
	{
676
		SWares *ware = new SWares;
677
		ware->iTextID = -1;
678
		ware->iTextPage = 0;
679
		ware->cType = first[4];
680
		ware->iPrice = rest.GetToken ( " ", 2, 2 ).ToLong();
681
		ware->iSize = rest.GetToken ( " ", 3, 3 ).ToInt();
682
		ware->iVolumn = rest.GetToken ( " ", 4, 4 ).ToInt();
683
		ware->sID = rest.GetToken ( " ", 1, 1 );
684
		ware->iNotority = rest.GetToken ( " ", 5, 5 ).ToInt();
685
		if ( !rest.GetToken(" ", 6, 6).Empty() )
686
		{
687
			ware->iTextID = rest.GetToken ( " ", 6, 6 ).GetToken(",", 2, 2).ToInt();
688
			ware->iTextPage = rest.GetToken ( " ", 6, 6 ).GetToken(",", 1, 1).ToInt();
689
		}
690
		m_lWares.push_back ( ware );
691
		m_pLastWare = ware;
692
	}
693
 
694
	else if ( CBaseFile::LoadPackageData(first, rest) )
695
		return true;
696
	else
697
		return false;
698
 
699
	return true;
700
}
701
 
702
bool CSpkFile::GeneratePackagerScript(bool wildcard, CyStringList *list, bool datafile)
703
{
704
	if ( !CBaseFile::GeneratePackagerScript(wildcard, list, datafile) )
705
		return false;
706
 
707
	list->PushBack("# Script Type, the type of package file, some are special types, others are just for show");
708
	if ( this->IsLibrary() )
709
		list->PushBack("ScriptType: Library");
710
	else if ( this->IsPackageUpdate() )
711
		list->PushBack("ScriptType: Package Update");
712
	else if ( this->IsCustomStart() )
713
		list->PushBack("ScriptType: Custom Start");
714
	else if ( this->IsPatch() )
715
		list->PushBack("ScriptType: Patch");
716
	else
717
		list->PushBack(CyString("ScriptType: ") + this->GetScriptTypeString(44));
718
	list->PushBack("");
719
 
720
	if ( this->IsAnotherMod() )
721
	{
722
		list->PushBack("# For another mod/package, this is a child package");
723
		list->PushBack(CyString("AnotherMod: ") + m_sOtherName + "|" + m_sOtherAuthor);
724
		list->PushBack("");
725
	}
726
 
727
	if ( !m_lWares.empty() )
728
	{
729
		list->PushBack("# Custom Wares, Ware<type>: <id> <price> <size> <volumn> <notority>");
730
		for ( CListNode<SWares> *node = m_lWares.Front(); node; node = node->next() )
731
		{
732
			SWares *w = node->Data();
733
			if ( w->iTextID > 0 )
734
				list->PushBack(CyString("Ware") + (char)w->cType + ": " + w->sID + " " + (long)w->iPrice + " " + (long)w->iSize + " " + (long)w->iVolumn + " " + (long)w->iNotority + " " + (long)w->iTextPage + "," + (long)w->iTextID);
735
			else
736
				list->PushBack(CyString("Ware") + (char)w->cType + ": " + w->sID + " " + (long)w->iPrice + " " + (long)w->iSize + " " + (long)w->iVolumn + " " + (long)w->iNotority);
737
			for ( CListNode<SWaresText> *wNode = w->lText.Front(); wNode; wNode = wNode->next() )
738
			{
739
				SWaresText *wt = wNode->Data();
740
				if ( !wt->sName.Empty() )
741
					list->PushBack(CyString("WareName: ") + w->sID + " " + (long)wt->iLang + " " + wt->sName);
742
				if ( !wt->sDesc.Empty() )
743
					list->PushBack(CyString("WareDesc: ") + w->sID + " " + (long)wt->iLang + " " + wt->sDesc);
744
			}
745
			list->PushBack("");
746
		}
747
	}
748
 
749
	if ( !datafile )
750
	{
751
		if ( !CBaseFile::GeneratePackagerScriptFile(wildcard, list) )
752
			return false;
753
	}
754
 
755
	return true;
756
 
757
}
758
 
759
CyString CSpkFile::GetWareText(SWares *w, int lang)
760
{
761
	// return the text page if being used
762
	if ( w->iTextID > 0 && w->iTextPage > 0 )
763
		return CyString("{") + (long)w->iTextPage + "," + (long)w->iTextID + "}";
764
 
765
	CyString name;
766
	for ( CListNode<SWaresText> *wt = w->lText.Front(); wt; wt = wt->next() )
767
	{
768
		if ( wt->Data()->sName.Empty() )
769
			continue;
770
		if ( wt->Data()->iLang == lang )
771
			name = wt->Data()->sName;
772
		else if ( name.Empty() && wt->Data()->iLang == 44 )
773
			name = wt->Data()->sName;
774
		else if ( name.Empty() )
775
			name = wt->Data()->sName;
776
	}
777
 
778
	return name;
779
}
780
CyString CSpkFile::GetWareDesc(SWares *w, int lang)
781
{
782
	// return the text page if being used
783
	if ( w->iTextID > 0 && w->iTextPage > 0 )
784
		return CyString("{") + (long)w->iTextPage + "," + ((long)w->iTextID + 1) + "}";
785
 
786
	CyString name;
787
	for ( CListNode<SWaresText> *wt = w->lText.Front(); wt; wt = wt->next() )
788
	{
789
		if ( wt->Data()->sDesc.Empty() )
790
			continue;
791
 
792
		if ( wt->Data()->iLang == lang )
793
			name = wt->Data()->sDesc;
794
		else if ( name.Empty() && wt->Data()->iLang == 44 )
795
			name = wt->Data()->sDesc;
796
		else if ( name.Empty() )
797
			name = wt->Data()->sDesc;
798
	}
799
 
800
	return name;
801
}
802
 
803
CyString CSpkFile::GetCustomStartName()
804
{
805
	if ( !this->IsCustomStart() )
806
		return NullString;
807
 
808
	// else find the custom start script
809
	C_File *file = NULL;
810
	for ( file = this->GetFirstFile(FILETYPE_SCRIPT); file; file = this->GetNextFile(file) )
811
	{
812
		if ( file->GetFilename().IsIn("initplayership")	&& file->GetFilename().GetToken(".", 1, 1).Compare("galaxy") )
813
			break;
814
	}
815
 
816
	if ( !file )
817
		return NullString;
818
 
819
	return file->GetFilename().GetToken(".", 2, 2);
820
}
821
 
822
void CSpkFile::MergePackage(CBaseFile *base)
823
{
824
	// update version information
825
	m_sVersion = base->GetVersion();
826
	m_sCreationDate = base->GetCreationDate();
827
	m_iPluginType = base->GetPluginType();
828
 
829
	// update possible changes
830
	if ( base->GetType() == TYPE_SPK )
831
	{
832
		CSpkFile *spk = (CSpkFile *)base;
833
		m_bForceProfile = spk->IsForceProfile();
834
 
835
		// add any new wares
836
		if ( spk->AnyWares() )
837
		{
838
			for ( CListNode<SWares> *node = spk->GetWaresList()->Front(); node; node = node->next() )
839
				this->AddWare(node->Data());
840
			spk->GetWaresList()->clear(); // remove wares so they aren't deleted
841
		}
842
 
843
		// add any settings
844
		if ( spk->AnySettings() )
845
		{
846
			for ( CListNode<SSettingType> *node = spk->GetSettingsList()->Front(); node; node = node->next() )
847
				this->AddSetting(node->Data()->sKey, node->Data()->iType);
848
		}
849
 
850
		if ( !spk->GetOtherName().Empty() )
851
		{
852
			m_sOtherName = spk->GetOtherName();
853
			m_sOtherAuthor = spk->GetOtherAuthor();
854
		}
855
	}
856
 
857
	// copy settings from base class
858
	m_iGameChanging = base->GetGameChanging();
859
	m_iRecommended = base->GetRecommended();
860
	m_iEaseOfUse = base->GetEaseOfUse();
861
 
862
	for ( CListNode<SGameCompat> *gNode = base->GetGameCompatabilityList()->Front(); gNode; gNode = gNode->next() ) {
863
		if ( !gNode->Data()->sVersion.Empty() )
864
			this->AddGameCompatability(gNode->Data()->iGame, gNode->Data()->sVersion);
865
		else
866
			this->AddGameCompatability(gNode->Data()->iGame, CyString::Number(gNode->Data()->iVersion));
867
	}
868
 
869
	if ( !base->GetWebAddress().Empty() )
870
		m_sWebAddress = base->GetWebAddress();
871
	if ( !base->GetWebSite().Empty() )
872
		m_sWebSite = base->GetWebSite();
873
	if ( !base->GetEmail().Empty() )
874
		m_sEmail = base->GetEmail();
875
	if ( !base->GetForumLink().Empty() )
876
		m_sForumLink = base->GetForumLink();
877
 
878
	m_sDescription = base->GetDescription();
879
 
880
	// copy over needed librarys
881
	for ( CListNode<SNeededLibrary> *lNode = base->GetNeededLibraries()->Front(); lNode; lNode = lNode->next() )
882
		this->AddNeededLibrary(lNode->Data()->sName, lNode->Data()->sAuthor, lNode->Data()->sMinVersion);
883
 
884
	// web mirror address, add any new ones
885
	for ( SStringList *str = base->GetWebMirrors()->Head(); str; str = str->next )
886
		this->AddWebMirror(str->str);
887
 
888
	// copy over any install text
889
	for ( CListNode<SInstallText> *iNode = base->GetInstallTextList()->Front(); iNode; iNode = iNode->next() )
890
	{
891
		if ( !iNode->Data()->sAfter.Empty() )
892
			this->AddInstallAfterText(iNode->Data()->iLanguage, iNode->Data()->sAfter);
893
		if ( !iNode->Data()->sBefore.Empty() )
894
			this->AddInstallBeforeText(iNode->Data()->iLanguage, iNode->Data()->sBefore);
895
	}
896
 
897
	for ( CListNode<SInstallText> *iNode = base->GetUninstallTextList()->Front(); iNode; iNode = iNode->next() )
898
	{
899
		if ( !iNode->Data()->sAfter.Empty() )
900
			this->AddUninstallAfterText(iNode->Data()->iLanguage, iNode->Data()->sAfter);
901
		if ( !iNode->Data()->sBefore.Empty() )
902
			this->AddUninstallBeforeText(iNode->Data()->iLanguage, iNode->Data()->sBefore);
903
	}
904
 
905
	// copy over package names
906
	for ( CListNode<SNames> *nNode = base->GetNamesList()->Front(); nNode; nNode = nNode->next() )
907
		this->AddLanguageName(nNode->Data()->iLanguage, nNode->Data()->sName);
908
 
909
	// finally do all the files
910
	for ( CListNode<C_File> *node = base->GetFileList()->Front(); node; node = node->next() )
911
	{
912
		C_File *f = node->Data();
913
		// if it exists, remove the old
914
		for ( CListNode<C_File> *thisNode = m_lFiles.Front(); thisNode; thisNode = thisNode->next() )
915
		{
916
			if ( thisNode->Data()->GetFileType() == f->GetFileType() && thisNode->Data()->GetFilename().Compare(f->GetFilename()) && thisNode->Data()->GetDir().Compare(f->GetDir()) )
917
			{
918
				m_lFiles.remove(thisNode);
919
				break;
920
			}
921
		}
922
 
923
		m_lFiles.push_back(f);
924
	}
925
 
926
	// clear the files so we dont delete them later
927
	base->GetFileList()->clear();
928
}