Rev 14 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "XspFile.h"#include "File_IO.h"#include "Packages.h"#include "CatFile.h"CXspFile::CXspFile () : CBaseFile(){SetDefaults ();m_iType = TYPE_XSP;}void CXspFile::Delete (){CBaseFile::Delete();m_pSceneFile = m_pCockpitFile = NULL;// delete listsm_lMissileMasks.MemoryClear();m_lWeaponMasks.MemoryClear();m_lMissileMasks.destroy();m_lWeaponMasks.destroy();for ( CListNode<SCockpit> *n = m_lCockpit.Front(); n; n = n->next() )n->Data()->lWeaponMask.MemoryClear();m_lCockpit.MemoryClear();m_lCockpit.destroy();m_lCutData.Clear();m_lBodies.Clear();}void CXspFile::SetDefaults (){CBaseFile::SetDefaults ();m_pSceneFile = m_pCockpitFile = NULL;m_bLanguageText = m_bExistingShip = false;m_iOrgDesc = 0;m_iShipyard = SHIPYARD_NONE;}void CXspFile::AddText ( int id, CyString name, CyString desc ){// first check if theres an existing idSText *newtext = NULL;for ( SText *t = m_lText.First(); t; t = m_lText.Next() ){if ( t->iId == id ){newtext = t;break;}}if ( !newtext ){newtext = new SText;newtext->iId = id;m_lText.push_back ( newtext );}newtext->sName = name;newtext->sDesc = desc;m_bChanged = true;}void CXspFile::RemoveText(int id){for ( SText *t = m_lText.First(); t; t = m_lText.Next() ){if ( t->iId == id ){m_bChanged = true;m_lText.RemoveCurrent();return;}}}void CXspFile::AddDummy ( CyString section, CyString data ){SDummy *d = new SDummy;d->sData = data;d->sSection = section;if ( d->sData.Right (1) != ";" )d->sData += ";";m_lDummy.push_back ( d );m_bChanged = true;}void CXspFile::AddComponent ( CyString section, CyString section2, CyString data ){SComponent *c = new SComponent;c->sData = data;c->sSection = section;c->sSection2 = section2;if ( c->sData.Right (1) != ";" )c->sData += ";";m_lComponent.push_back ( c );m_bChanged = true;}void CXspFile::AddWeaponMask ( int game, int mask ){// first check if we have one for the gameSWeaponMask *m = NULL;for ( CListNode<SWeaponMask> *node = m_lWeaponMasks.Front(); node; node = node->next() ){if ( node->Data()->iGame == game ){m = node->Data();break;}}// not found, create oneif ( !m ){m = new SWeaponMask;m_lWeaponMasks.push_back(m);m->iGame = game;}m->iMask = mask;m_bChanged = true;}void CXspFile::AddMissileMask ( int game, int mask ){// first check if we have one for the gameSWeaponMask *m = NULL;for ( CListNode<SWeaponMask> *node = m_lMissileMasks.Front(); node; node = node->next() ){if ( node->Data()->iGame == game ){m = node->Data();break;}}// not found, create oneif ( !m ){m = new SWeaponMask;m_lMissileMasks.push_back(m);m->iGame = game;}m->iMask = mask;m_bChanged = true;}bool CXspFile::IsValid (){if ( m_sName.Empty() )return false;if ( m_sAuthor.Empty() )return false;return true;}Utils::String CXspFile::CreateValuesLine() const{Utils::String values = CBaseFile::CreateValuesLine ();values += "Data: " + m_sData + "\n";values += "ID: " + m_sID + "\n";if ( m_bLanguageText )values += "LanguageText\n";if ( m_bExistingShip )values += "ExistingShip\n";values += Utils::String("OrgDesc: ") + (long)m_iOrgDesc + "\n";values += Utils::String("Shipyard: ") + (long)m_iShipyard + "\n";for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ) {SCockpit *cockpit = node->Data();values += Utils::String("CockpitNew: ") + (long)cockpit->lWeaponMask.size();for ( CListNode<SWeaponMask> *wNode = cockpit->lWeaponMask.Front(); wNode; wNode = wNode->next() ) {values += ":";values += (long)wNode->Data()->iGame;values += ":";values += (long)wNode->Data()->iMask;}values += " ";values += cockpit->sCockpit.ToString() + "\n";}for ( CListNode<SText> *tNode = m_lText.Front(); tNode; tNode = tNode->next() )values += Utils::String("Text: ") + (long)tNode->Data()->iId + "|" + tNode->Data()->sName.FindReplace("|", "<::PiPe::>").ToString() + "|" + tNode->Data()->sDesc.ToString() + "\n";for ( CListNode<SComponent> *cNode = m_lComponent.Front(); cNode; cNode = cNode->next() )values += Utils::String("Component: ") + cNode->Data()->sData.FindReplace("|", "<::PiPe::>").ToString() + "|" + cNode->Data()->sSection.FindReplace("|", "<::PiPe::>").ToString() + "|" + cNode->Data()->sSection2.ToString() + "\n";for ( CListNode<SDummy> *dNode = m_lDummy.Front(); dNode; dNode = dNode->next() )values += Utils::String("Dummy: ") + dNode->Data()->sData.FindReplace("|", "<::PiPe::>").ToString() + "|" + dNode->Data()->sSection.ToString() + "\n";for ( CListNode<SWeaponMask> *wNode = m_lWeaponMasks.Front(); wNode; wNode = wNode->next() )values += Utils::String("WeaponMask: ") + (long)wNode->Data()->iGame + " " + (long)wNode->Data()->iMask + "\n";for ( CListNode<SWeaponMask> *mNode = m_lMissileMasks.Front(); mNode; mNode = mNode->next() )values += Utils::String("MissileMask: ") + (long)mNode->Data()->iGame + " " + (long)mNode->Data()->iMask + "\n";for ( SStringList *cut = m_lCutData.Head(); cut; cut = cut->next )values += Utils::String("CutData: ") + cut->str.ToString() + "\n";for ( SStringList *body = m_lBodies.Head(); body; body = body->next )values += Utils::String("Bodies: ") + body->str.ToString() + "\n";for ( SStringList *ani = m_lAnimations.Head(); ani; ani = ani->next )values += Utils::String("Animations: ") + ani->str.ToString() + "\n";return values;}bool CXspFile::ParseValueLine(const Utils::String &sLine){Utils::String first = sLine.token(":", 1);Utils::String rest = sLine.tokens(":", 2).removeFirstSpace();if ( first.Compare("Data") )m_sData = rest;else if ( first.Compare("ID") )m_sID = rest;else if ( sLine.Compare("LanguageText") )m_bLanguageText = true;else if ( sLine.Compare("ExistingShip") )m_bExistingShip = true;else if ( first.Compare("OrgDesc") || first.Compare("OriginalDesc") )m_iOrgDesc = rest;else if ( first.Compare("Shipyard") )m_iShipyard = rest;else if ( first.Compare("CutData") )this->AddCutData(rest);else if ( first.Compare("Bodies") )this->AddBodies(rest);else if ( first.Compare("Animations") )this->AddAnimation(rest);else if ( first.Compare("Cockpit") )this->AddCockpit(rest, 0);else if ( first.Compare("CockpitNew") ){Utils::String cockpit = rest.tokens(" ", 2);Utils::String sMasks = rest.token(" ", 1);this->AddCockpit(cockpit, 0, -1);int num = sMasks.token(":", 1);for ( int i = 0; i < num; i++ ){int mask = sMasks.token(":", ((i + 1) * 2) + 1);int game = sMasks.token(":", ((i + 1) * 2));this->AddCockpit(cockpit, game, mask);}}else if ( first == "Web" )m_sWebSite = rest;else if ( first.Compare("WeaponMask") )this->AddWeaponMask(rest.token(" ", 1), rest.token(" ", 2));else if ( first.Compare("MissileMask") )this->AddMissileMask(rest.token(" ", 1), rest.token(" ", 2));else if ( first == "Text" ){SText *text = new SText;text->iId = rest.token("|", 1);text->sName = rest.token("|", 2);text->sName = text->sName.FindReplace("<::PiPe::>", "|");text->sDesc = rest.tokens( "|", 3);m_lText.push_back ( text );}else if ( first == "Component" ){SComponent *c = new SComponent;c->sData = rest.token("|", 1);c->sData = c->sData.FindReplace ("<::PiPe::>", "|");c->sSection = rest.token("|", 2);c->sSection = c->sSection.FindReplace ("<::PiPe::>", "|");c->sSection2 = rest.tokens("|", 3);m_lComponent.push_back ( c );}else if ( first == "Dummy" ){SDummy *d = new SDummy;d->sData = rest.token("|", 1);d->sData = d->sData.FindReplace ("<::PiPe::>", "|");d->sSection = rest.tokens( "|", 2);m_lDummy.push_back ( d );}else if ( first == "Comment" )m_sDescription = rest.findReplace("<newline>", "<br>");elsereturn CBaseFile::ParseValueLine(sLine);return true;}CyString CXspFile::GetShipName(int lang){CyString name;if ( (m_bLanguageText) && (lang) ){for ( SText *text = m_lText.First(); text; text = m_lText.Next() ){if ( text->iId == lang ){name = text->sName;break;}}}if ( name.Empty() )name = GetLanguageName(lang);return name;}bool CXspFile::ConvertOld(CyString file){// open the fileFILE *id = fopen(file.c_str(), "rb");if ( !id )return false;// read to memoryfseek(id, 0, SEEK_END);size_t size = ftell(id);fseek(id, 0, SEEK_SET);unsigned char *data = new unsigned char[size + 1];fread(data, sizeof(unsigned char), size, id);data[size] = '\0';fclose(id);// uncompress the filesize_t len;unsigned char *compr = LZMADecode_C ( data, size, &len, NULL );delete data;if ( !compr )return false;this->Delete();this->SetDefaults();// now read the data line by linesize_t pos = 0;size_t start = 0;int packageVersion = 0;while ( pos < len ){while ( compr[pos++] != '\n' && pos < len );compr[pos - 1] = '\0';CyString line = (char *)(compr + start);start = pos;if ( line.Empty() )continue;CyString first = line.GetToken(":", 1, 1);CyString rest = line.GetToken(":", 2);rest = rest.RemoveFirstSpace();// now check each lineif ( first.Compare("Packager") )packageVersion = rest.ToInt();else if ( first.Compare("Shipyard") ){int max;CyString *strs = rest.SplitToken(";", &max);if ( strs && max ){int cur = 1;for ( int i = 0; i < max; i++, cur *= 2 ){if ( strs[i] == "1" )this->AddShipyard(cur);}}CLEANSPLIT(strs, max)}else if ( first.Compare("ScreenShot") ){int size = rest.GetToken(" ", 1, 1).ToInt();CyString ext = rest.GetToken(" ", 2, 2);C_File *newFile = this->AddFile(CyString(m_sID) + "_" + CyString::Number(this->CountFiles(FILETYPE_SCREEN) + 1) + "." + ext, "", FILETYPE_SCREEN);newFile->ReadFromData((char *)(compr + pos), size);start += (size + 1);}else if ( first.Compare("SceneFile") ){CyString file = rest.GetToken(" ", 3);m_pSceneFile = this->AddFile(CFileIO(file).GetFilename(), CFileIO(file).GetDir(), FILETYPE_SHIPSCENE);m_pSceneFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());m_pSceneFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());start += m_pSceneFile->GetDataSize();}else if ( first.Compare("CockpitFile") ){CyString file = rest.GetToken(" ", 3);m_pCockpitFile = this->AddFile(CFileIO(file).GetFilename(), CFileIO(file).GetDir(), FILETYPE_COCKPITSCENE);m_pCockpitFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());m_pCockpitFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());start += m_pCockpitFile->GetDataSize();}else if ( first.Compare("Model") ){CyString file = rest.GetToken(" ", 3);C_File *newFile= this->AddFile(CFileIO(file).GetFilename(), CFileIO(file).GetDir(), FILETYPE_SHIPMODEL);newFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());newFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());start += (newFile->GetDataSize() + 1);}else if ( first.Compare("Files") ){CyString file = rest.GetToken(" ", 3);C_File *newFile = NULL;int special = 0;if ( file.Compare("types/CutData.txt") || file.Compare("types/CutData.pck") ){newFile = new C_File(file);special = 1;}else if ( file.Compare("types/Bodies.txt") || file.Compare("types/Bodies.pck") ){newFile = new C_File(file);special = 2;}else if ( file.Compare("types/Animations.txt") || file.Compare("types/Animations.pck") ){newFile = new C_File(file);special = 3;}else{newFile = this->AddFile(CFileIO(file).GetFilename(), CFileIO(file).GetDir(), FILETYPE_SHIPOTHER);newFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());}newFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());start += (newFile->GetDataSize() + 1);if ( special ){if ( newFile->CheckFileExt("pck") )newFile->UnPCKFile();// read data into linesCyString data((const char *)newFile->GetData());data.RemoveChar('\r');int iLines;CyString *sLines = data.SplitToken("\n", &iLines);if ( sLines && iLines ){// cut dataint entries = -1;if ( special == 1 ){CyStringList newLines;for ( int i = 0; i < iLines; i++ ){CyString line = sLines[i];line.RemoveChar(' ');line.RemoveChar(9);if ( line.Empty() || line[0] == '/' )continue;if ( entries == -1 ){entries = line.GetToken(";", 1, 1).ToInt() - 36;if ( entries <= 0 )break;}else{int id = line.GetToken(";", 1, 1).ToInt();if ( id >= 9000 && id <= 9017 )continue;switch (id){case 948:case 4111:case 4112:case 4064:case 4169:case 4178:case 4177:case 4163:case 4194:case 4162:case 4191:case 4200:case 4161:case 4097:case 4205:case 4206:case 4207:case 4107:break;default:newLines.PushBack(line);}if ( newLines.Count() == entries )break;}}for ( SStringList *strNode = newLines.Head(); strNode; strNode = strNode->next )this->AddCutData(strNode->str);}// bodieselse if ( special == 2 ){entries = 0;CyString section;for ( int i = 0; i < iLines; i++ ){CyString line = sLines[i];line.RemoveChar(' ');line.RemoveChar(9);if ( line.Empty() || line[0] == '/' )continue;if ( entries <= 0){section = line.GetToken(";", 1, 1);entries = line.GetToken(";", 2, 2).ToInt();}else{if ( !line.IsIn(";") )continue;if ( line.NumToken(";") <= 2 ){this->AddBodies(section + ";" + line.GetToken(";", 1, 1) + ";");--entries;}else{bool done = false;while (!done){int num;CyString *strs = line.SplitToken(";", &num);done = true;for ( int j = 0; j < num; j++ ){if ( !entries ){line = line.GetToken(";", j + 1);if ( !line.Empty() )done = false;break;}if ( strs[j].Empty() )continue;this->AddBodies(section + ";" + strs[j] + ";");--entries;}//we must be at another sectionif ( !done ){section = line.GetToken(";", 1, 1);entries = line.GetToken(";", 2, 2).ToInt();line = line.RemToken(";", 1);line = line.RemToken(";", 1);if (line.Empty())done = true;}CLEANSPLIT(strs, num)}}}}}// animationselse if ( special == 3 ){CyStringList in;for ( int i = 0; i < iLines; i++ ){CyString line = sLines[i];in.PushBack(line);}CyStringList out;if ( CXspFile::ReadAnimations(&in, &out, 87) )this->AddAnimation(&out);}}CLEANSPLIT(sLines, iLines)delete newFile;}}else if ( first.Compare("Script") ){CyString file = rest.GetToken(" ", 3);C_File *newFile= this->AddFile(file, NullString, FILETYPE_SCRIPT);newFile->SetCreationTime(rest.GetToken(" ", 1, 1).ToLong());newFile->ReadFromData((char *)(compr + pos), rest.GetToken(" ", 2, 2).ToInt());start += (newFile->GetDataSize() + 1);}else if ( first.Compare("Text") )this->AddText(rest.GetToken ( ":", 1, 1 ).ToInt(), rest.GetToken ( ":", 2, 2 ), rest.GetToken ( ":", 3 ));else if ( first.Compare("Component") )this->AddComponent(rest.GetToken ( ";", 1, 1 ), rest.GetToken ( ";", 2, 2 ), rest.GetToken ( ";", 3 ));else if ( first.Compare("Dummy") ){SDummy *d = new SDummy;d->sData = rest.GetToken ( ";", 2 );d->sSection = rest.GetToken ( ";", 1, 1 );m_lDummy.push_back ( d );}else if ( !this->ParseValueLine(line.ToString()) ){// printf ( "Command: %s, Rest: %s\n", first.c_str(), rest.c_str());}pos = start;}// assume all old ones are for X3if ( !m_sData.empty() ){this->AddWeaponMask(GAME_X3 - 1, m_sData.token(";", 19));this->AddMissileMask(GAME_X3 - 1, m_sData.token(";", 25));}return true;}int GetMaxShipyards() { return (int)SHIPYARD_MAX; }CyString GetShipyardName (int s){switch (s){case SHIPYARD_ARGON:return "Argon";case SHIPYARD_BORON:return "Boron";case SHIPYARD_PARANID:return "Paranid";case SHIPYARD_SPLIT:return "Split";case SHIPYARD_TELADI:return "Teladi";case SHIPYARD_PIRATES:return "Pirates";case SHIPYARD_FRIEND:return "Friendly";case SHIPYARD_XENON:return "Xenon";case SHIPYARD_TERRAN:return "Terran";}return "Unknown";}bool CXspFile::WriteHeader(FILE *id, int valueheader, int valueComprLen){fprintf ( id, "XSPCycrow;%.2f;%d;%d\n", FILEVERSION, valueheader, valueComprLen );if ( ferror(id) )return false;return true;}bool CXspFile::CheckHeader(const Utils::String header) const{if ( header.Compare("XSPCycrow") )return true;return false;}void CXspFile::SetLaserMask(int game, int mask){for ( CListNode<SWeaponMask> *node = m_lWeaponMasks.Front(); node; node = node->next() ){SWeaponMask *m = node->Data();if ( m->iGame == game ){m->iMask = mask;return;}}// no found, need to add itthis->AddWeaponMask(game, mask);}void CXspFile::SetMissileMask(int game, int mask){for ( CListNode<SWeaponMask> *node = m_lMissileMasks.Front(); node; node = node->next() ){SWeaponMask *m = node->Data();if ( m->iGame == game ){m->iMask = mask;return;}}// no found, need to add itthis->AddMissileMask(game, mask);}int CXspFile::GetLaserMask(int game, bool getOnly){int mask = -1;for ( CListNode<SWeaponMask> *node = m_lWeaponMasks.Front(); node; node = node->next() ){SWeaponMask *m = node->Data();if ( m->iGame == game )return m->iMask;if ( !mask && !getOnly )mask = m->iMask;}return mask;}int CXspFile::GetMissileMask(int game, bool getOnly){int mask = -1;for ( CListNode<SWeaponMask> *node = m_lMissileMasks.Front(); node; node = node->next() ){SWeaponMask *m = node->Data();if ( m->iGame == game )return m->iMask;if ( !mask && !getOnly )mask = m->iMask;}return mask;}CyString CXspFile::GetShipClass(){if ( !m_sData.empty() )return m_sData.token(";", TSHIPPOS_CLASS);return "OBJ_SHIP_M5";}bool CXspFile::GeneratePackagerScript(bool wildcard, CyStringList *list, bool datafile){if ( !CBaseFile::GeneratePackagerScript(wildcard, list, datafile) )return false;if ( m_iShipyard ){list->PushBack("# Shipyards, Set which shipyards to add ships for sale to");for ( int i = SHIPYARD_ARGON; i <= SHIPYARD_MAX; i *= 2 ){if ( this->IsShipyard(i) )list->PushBack(CyString("Shipyard: ") + GetShipyardName(i));}list->PushBack("");}if ( m_iOrgDesc > 0 ){list->PushBack("# Use Original Description, overrides text entrys to use one of the built in text");list->PushBack(CyString("OriginalDescription: ") + (long)m_iOrgDesc);list->PushBack("");}if ( !m_sID.empty() ){list->PushBack("# Ship ID, the ship id to identify the ship as");list->PushBack(CyString("ShipID: ") + m_sID);}if ( !m_sData.empty() ){list->PushBack("# Ship Data, the TShip data entry to add to the game (parts of this are adjusted and auto generated by the installer)");list->PushBack(CyString("ShipData: ") + m_sData);list->PushBack("");}if ( m_bExistingShip ){list->PushBack("# Existing Ship, replaces an existing ship in the game with ship package instead of creating a new entry");list->PushBack("ExistingShip");list->PushBack("");}if ( !datafile ){if ( !CBaseFile::GeneratePackagerScriptFile(wildcard, list) )return false;}return true;}bool CXspFile::LoadPackageData(const Utils::String &sFirst, const Utils::String &sRest){if ( sFirst.Compare("Shipyard") ){for ( int i = SHIPYARD_ARGON; i <= SHIPYARD_MAX; i *= 2 ){if ( sRest.Compare(GetShipyardName(i).ToString()) ){this->AddShipyard(i);break;}}}else if ( sFirst.Compare("OriginalDescription") )m_iOrgDesc = sRest;else if ( sFirst.Compare("ShipData") )m_sData = sRest;else if ( sFirst.Compare("ReadData") ) // read data from a tships file{CPackages p;m_sData = p.ReadShipData(sRest.tokens(" ", 2), sRest.token(" ", 1)).ToString();}else if ( sFirst.Compare("ExistingShip") )m_bExistingShip = true;else if ( sFirst.Compare("ShipID") )m_sID = sRest;else if ( !CBaseFile::LoadPackageData(sFirst, sRest) ){return false;}return true;}CyString CXspFile::GetX3ShipData(){CyString data = m_sData;// change the ship subtype, Reunion uses number, TC uses a defineCyString sSubType = data.GetToken(";", 6, 6);if ( !sSubType.ToInt() && sSubType != "0" )data = data.RepToken(";", 6, CyString::Number(CShipData::ConvertShipSubType(sSubType)));CyString sClass = data.GetToken(";", TSHIPPOS_CLASS, TSHIPPOS_CLASS);if ( !sClass.ToInt() && sClass != "0" ){int num = 0;for ( int i = 0; i < OBJ_SHIP_MAX; i++ ){if ( sClass.Compare(CShipData::ConvertShipClass(CShipData::GetShipClassFromNum(i))) ){num = i;break;}}data = data.RepToken(";", TSHIPPOS_CLASS, CyString::Number(num));}return data;}CyString CXspFile::GetTCShipData(){CyString data = m_sData;CyString sSubType = data.GetToken(";", 6, 6);if ( sSubType.ToInt() || sSubType == "0" )data = data.RepToken(";", 6, CShipData::ConvertShipSubType(sSubType.ToInt()));CyString sClass = data.GetToken(";", TSHIPPOS_CLASS, TSHIPPOS_CLASS);if ( sClass.ToInt() || sClass == "0" )data = data.RepToken(";", TSHIPPOS_CLASS, CShipData::ConvertShipClass(sClass.ToInt()));return data;}bool CXspFile::RemoveCockpit(CyString cockpitid){// if its a whole line, just get the endif ( cockpitid.IsIn(";") ){cockpitid = cockpitid.GetToken(";", -2);while ( cockpitid.Right(1) == ";" )cockpitid.Truncate((int)cockpitid.Length() - 1);}bool ret = false;for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ){CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);if ( id.Compare(cockpitid) ){node->DeleteData();ret = true;break;}}m_lCockpit.RemoveEmpty();return ret;}bool CXspFile::RemoveComponent(CyString section1, CyString section2, CyString data){bool ret = false;for ( CListNode<SComponent> *node = m_lComponent.Front(); node; node = node->next() ){if ( node->Data()->sSection.Compare(section1) && node->Data()->sSection2.Compare(section2) && node->Data()->sData.Compare(data) ){ret = true;node->DeleteData();break;}}m_lComponent.RemoveEmpty();return ret;}bool CXspFile::RemoveDummy(CyString section, CyString data){bool ret = false;for ( CListNode<SDummy> *node = m_lDummy.Front(); node; node = node->next() ){if ( node->Data()->sSection.Compare(section) && node->Data()->sData.Compare(data) ){ret = true;node->DeleteData();break;}}m_lDummy.RemoveEmpty();return ret;}CyString CXspFile::GetCockpitData(CyString cid){for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ){CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);if ( id.Compare(cid) )return node->Data()->sCockpit;}return NullString;}SCockpit *CXspFile::FindCockpit(CyString cid){for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ){CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);if ( id.Compare(cid) )return node->Data();}return NULL;}void CXspFile::EditCockpit(CyString cid, CyString cockpit){for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ){CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);if ( id.Compare(cid) ){node->Data()->sCockpit = cockpit;break;}}}void CXspFile::EditCockpit(CyString cid, CyString scene, int mask){for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ){CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);if ( id.Compare(cid) ){CyString cockpit = node->Data()->sCockpit;cockpit = cockpit.RepToken(";", 8, scene);cockpit = cockpit.RepToken(";", 9, CyString::Number(mask));node->Data()->sCockpit = cockpit;break;}}}void CXspFile::NewCockpit(CyString id, CyString scene, int mask){CyString cockpit = "0;0;0;0;0;0;0;";cockpit += scene + ";";cockpit += CyString::Number(mask);cockpit += ";0;0;0;0;0;0;-100000;0;0;";cockpit += id + ";";this->AddCockpit(cockpit, -1);}bool CXspFile::RemoveCutData(CyString cut){bool ret = false;for ( SStringList *str = m_lCutData.Head(); str; str = str->next ){if ( str->str.GetToken(";", 1, 1).Compare(cut.GetToken(";", 1, 1)) ){ret = true;str->remove = true;break;}}m_lCutData.RemoveMarked();return ret;}bool CXspFile::RemoveBodies(CyString cut){bool ret = false;for ( SStringList *str = m_lBodies.Head(); str; str = str->next ){if ( str->str.Remove(' ').Compare(cut.Remove(' ')) ){ret = true;str->remove = true;break;}}m_lBodies.RemoveMarked();return ret;}bool CXspFile::RemoveAnimation(CyString cut){bool ret = false;for ( SStringList *str = m_lAnimations.Head(); str; str = str->next ){if ( str->str.Remove(' ').Remove('\n').Compare(cut.Remove(' ').Remove('\n')) ){ret = true;str->remove = true;break;}}m_lAnimations.RemoveMarked();return ret;}void CXspFile::AddCockpit(CyString cockpit, int game, int mask, int index){SCockpit *pCockpit = NULL;// first search for the cockpit entryCyString cid = cockpit.GetToken(";", 19, 19);for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ){CyString id = node->Data()->sCockpit.GetToken(";", 19, 19);if ( id.Compare(cid) ){pCockpit = node->Data();break;}}if ( !pCockpit ){pCockpit = new SCockpit;pCockpit->sCockpit = cockpit;pCockpit->iIndex = index;m_lCockpit.push_back(pCockpit);}if ( index != -1 )pCockpit->iIndex = index;// now add the game maskif ( game > 0 ){// search if the game mask already existsSWeaponMask *wm = NULL;for ( CListNode<SWeaponMask> *node = pCockpit->lWeaponMask.Front(); node; node = node->next() ){if ( node->Data()->iGame == game ){wm = node->Data();break;}}if ( !wm ){wm = new SWeaponMask;pCockpit->lWeaponMask.push_back(wm);}wm->iGame = game;if ( mask == -1 )wm->iMask = cockpit.GetToken(";", 9, 9).ToInt();elsewm->iMask = mask;}m_bChanged = true;}void CXspFile::AddBody(CyString section, CyString data){this->AddBodies(section + ";" + data);m_bChanged = true;}void CXspFile::AddBodies(CyString data){if ( !data.IsNumber() ){if ( data[(int)(data.Length() - 5)] == '.' )data = data.Left(-5);else if ( data[(int)(data.Length() - 4)] == '.' )data = data.Left(-4);if ( data.Right(1) != ";" )data += ";";}m_lBodies.PushBack(data, true);m_bChanged = true;}int CXspFile::GetAnimationType(CyString type){if ( type.Compare("TAT_TAGSINGLESTEP") )return TAT_SINGLE;else if ( type.Compare("TAT_TAGONESHOT")|| type.Compare("TAT_TAGONESHOT_REINIT")|| type.Compare("TAT_PINGPONG")|| type.Compare("TAT_TAGLOOP") )return TAT_3;return TAT_NONE;}bool CXspFile::ReadAnimations(CyStringList *lIn, CyStringList *lOut, int startRecord){CyString lastComment;CyString addEntry;int remaining = 0;CyString lastType;int newEntries = 0;int entries = -1;for ( SStringList *strNode = lIn->Head(); strNode; strNode = strNode->next ){CyString line = strNode->str;line.RemoveChar('\r');line.RemoveChar(9);if ( line.Empty() || line[0] == '/' )continue;if ( entries == -1){entries = line.GetToken(";", 1, 1).ToInt();newEntries = entries - startRecord;}else{// remove comments, endspaces and last ;CyString sStriped = line;if ( sStriped.IsIn("//") ){if ( entries <= newEntries )lastComment = CyString("//") + sStriped.GetToken("//", 2);sStriped = sStriped.GetToken("//", 1, 1);}sStriped.RemoveEndSpace();if ( sStriped.Right(1) == ";" )sStriped.Truncate(-1);CyString sRemainingLeft;if ( remaining > 0 )sRemainingLeft = sStriped;else{// each line should be a new entry, with some exceptions// potection for new lineslastType = sStriped.GetToken(";", 1, 1);switch (CXspFile::GetAnimationType(lastType)){case TAT_SINGLE:remaining = sStriped.GetToken(";", 5, 5).ToInt() + 1;sRemainingLeft = sStriped.GetToken(";", 6);if ( entries <= newEntries )addEntry = sStriped.GetToken(";", 1, 5) + ";";break;case TAT_3:remaining = sStriped.GetToken(";", 5, 5).ToInt() + 1;sRemainingLeft = sStriped.GetToken(";", 6);if ( entries <= newEntries )addEntry = sStriped.GetToken(";", 1, 5) + ";";break;default:remaining = 0;if ( entries <= newEntries )addEntry = sStriped;}}if ( !sRemainingLeft.Empty() ){int tatType = CXspFile::GetAnimationType(lastType);if ( tatType == TAT_SINGLE ){if ( sRemainingLeft.IsIn(";") )remaining -= sRemainingLeft.NumToken(";");else if ( !sRemainingLeft.Empty() )--remaining;if ( entries <= newEntries )addEntry += sRemainingLeft + ";";}else if ( tatType == TAT_3 ){// last entryif ( remaining == 1 )--remaining;else if ( sRemainingLeft.IsIn(";") ){if ( !sRemainingLeft.IsIn("TATF_COORDS") ){int amt = sRemainingLeft.NumToken(";") / 3;remaining -= amt;if ( remaining == 1 && (sRemainingLeft.NumToken(";") - (amt * 3)) == 1 )--remaining;}else{int iRem = sRemainingLeft.NumToken(";");int iPos = 1;while ( iPos < iRem ){CyString first = sRemainingLeft.GetToken(";", iPos, iPos);if ( first.IsIn("TATF_COORDS") )iPos += 5;elseiPos += 3;--remaining;}if ( remaining == 1 && iPos == iRem )--remaining;}}if ( entries <= newEntries )addEntry += sRemainingLeft + ";";}}if ( remaining <= 0 ){if ( entries <= newEntries && !addEntry.Empty()){if ( addEntry[(int)addEntry.Length() - 1] != ';' )addEntry += ";";lOut->PushBack(addEntry + lastComment);}--entries;}}}return !lOut->Empty();}void CXspFile::AddAnimation(CyStringList *list){for ( SStringList *strNode = list->Head(); strNode; strNode = strNode->next )this->AddAnimation(strNode->str);m_bChanged = true;}SText *CXspFile::FindShipText(int lang){if ( m_lText.empty() )return NULL;SText *english = NULL;SText *german = NULL;SText *found = NULL;for ( CListNode<SText> *node = m_lText.Front(); node; node = node->next() ){SText *text = node->Data();// matched languageif ( text->iId == lang )return text;else if ( text->iId == 44 )english = text;else if ( text->iId == 49 )german = text;else if ( !found )found = text;}// if we've found an english version, use thatif ( english )return english;// otherwise try a germanif ( german )return german;// otherwise use any we've found (usually first one)return found;}CyString CXspFile::GetTextName(int lang){SText *t = FindShipText(lang);if ( t ){// return the correct language textif ( !t->sName.Empty() )return t->sName;// we have found a text, but there is no ship name ??else if ( lang != 44 ){// reget the english onet = FindShipText(44);if ( t && !t->sName.Empty() )return t->sName;}}// still not found one, return the ships namereturn this->GetShipName(lang);}CyString CXspFile::GetTextDescription(int lang){SText *t = FindShipText(lang);if ( t ){// return the correct language textif ( !t->sDesc.Empty() )return t->sDesc;// we have found a text, but there is no ship name ??else if ( lang != 44 ){// reget the english onet = FindShipText(44);if ( t && !t->sDesc.Empty() )return t->sDesc;}}// still not found one, return the ships nameif ( !m_sDescription.Empty() )return m_sDescription;return this->GetShipName(lang);}bool CXspFile::StartExtractShip(CCatFile *catFile, CyString id, CProgressInfo *progress){id.RemoveChar('\r');while ( id.Right(1) == ";" )id.Truncate((int)id.Length() - 1);m_sID = id.ToString();m_sData = catFile->GetTShipsEntry(id).ToString();// get scene filesif ( progress ) progress->UpdateStatus(IMPORTSHIP_SCENE);if ( !this->ExtractSceneFiles(catFile) )return false;return true;}bool CXspFile::StartExtractShip(CyString catFile, CyString id, CProgressInfo *progress){CCatFile cat;if ( cat.Open(catFile, "", CATREAD_CATDECRYPT, false) != CATERR_NONE )return this->StartExtractShip(&cat, id, progress);return false;}bool CXspFile::ExtractShip(CCatFile *catFile, CyString id, CProgressInfo *progress){if ( !this->StartExtractShip(catFile, id, progress) )return false;// read the scene file and get the files listif ( !this->ProcessSceneFiles(catFile, progress) )return false;// pack all the ship filesthis->PackAllFiles();return true;}bool CXspFile::ExtractShip(CyString catFile, CyString id, CProgressInfo *progress){CCatFile cat;if ( cat.Open(catFile, "", CATREAD_CATDECRYPT, false) == CATERR_NONE )return ExtractShip(&cat, id, progress);return false;}C_File *CXspFile::ExtractFileToPackage(CCatFile *catFile, CyString file, int type, CyString addAs){if ( catFile->ExtractFile(file, "tmp") ){CFileIO File("tmp");C_File *f = this->AddFile(CFileIO(addAs.Empty() ? file : addAs).GetFilename(), CFileIO(addAs.Empty() ? file : addAs).GetDir(), type);if ( f ){if ( f->ReadFromFile("tmp") ){File.Remove();return f;}}File.Remove();}return NULL;}bool CXspFile::ExtractSceneFiles(CCatFile *catFile){m_pSceneFile = this->ExtractFileToPackage(catFile, CyString("objects\\") + m_sData.token(";", 17) + ".pbd", FILETYPE_SHIPSCENE, CyString("objects\\") + m_sData.token(";", 17) + ".bod");if ( !m_pSceneFile ){m_pSceneFile = this->ExtractFileToPackage(catFile, CyString("objects\\") + m_sData.token(";", 17) + ".bod", FILETYPE_SHIPSCENE);if ( !m_pSceneFile )return false;}m_pCockpitFile = this->ExtractFileToPackage(catFile, CyString("objects\\") + m_sData.token(";", 18) + ".pbd", FILETYPE_COCKPITSCENE, CyString("objects\\") + m_sData.token(";", 18) + ".bod");if ( !m_pCockpitFile )m_pCockpitFile = this->ExtractFileToPackage(catFile, CyString("objects\\") + m_sData.token(";", 18) + ".bod", FILETYPE_COCKPITSCENE);return true;}bool CXspFile::ExtractSceneFiles(CyString catFile){CCatFile cat;if ( cat.Open(catFile, "", CATREAD_CATDECRYPT, false) == CATERR_NONE )return ExtractSceneFiles(&cat);return false;}CyStringList *CXspFile::ReadSceneModels(){// read the scene fileif ( !m_pSceneFile )m_pSceneFile = this->GetFirstFile(FILETYPE_SHIPSCENE);if ( !m_pSceneFile )return NULL;// check if its packedsize_t datasize;unsigned char *data = m_pSceneFile->UncompressData((long *)&datasize, 0);// if data wasn't compressed, then copy it itself as we are editing itbool deleteData = false;if ( data == m_pSceneFile->GetData() ){data = new unsigned char[m_pSceneFile->GetDataSize()];memcpy(data, m_pSceneFile->GetData(), m_pSceneFile->GetDataSize());deleteData = true;}if ( data && datasize ){if ( m_pSceneFile->CheckPackedExtension() )data = UnPCKData(data, datasize, &datasize);}if ( !data || !datasize )return NULL;CyStringList *lModels = new CyStringList;size_t pos = 0;bool newline = true;bool online = false;while ( pos < datasize ){char c = data[pos];++pos;// skip until next lineif ( !newline && !online ){if ( c == '\n' )newline = true;continue;}if ( newline ){if ( c == ' ' || c == 9 || c == '\n' || c == '\r' )continue;newline = false;if ( c == 'P' || c == 'p' ){while ( data[pos] == ' ' ) pos++;unsigned char *line = (data + pos);while ( data[pos] != ' ' && data[pos] != ';' ) pos++;data[pos] = '\0';if ( atoi((const char *)line) == lModels->Count() )online = true;}}// this line is out modelelse if ( online ){if ( c == 'B' || c == 'b' ){while(data[pos] == ' ') pos++;unsigned char *line = (data + pos);while(data[pos] != ';') pos++;data[pos] = '\0';lModels->PushBack((char *)line);online = false;}}}if ( deleteData )delete data;return lModels;}void CXspFile::ExtractDummies(CCatFile *catFile, CyStringList *sceneModels, bool add){if ( !sceneModels ) return;if ( catFile->ExtractFile("types/dummies.pck", "tmp") ){CFileIO File("tmp");if ( File.Exists() ){CyString section;int secCount = 0;CyStringList *lines = File.ReadLinesStr();for ( SStringList *node = lines->Head(); node; node = node->next ){node->str.RemoveFirstSpace();node->str.RemoveChar(9);node->str.RemoveChar('\r');if ( node->str.Empty() )continue;if ( node->str[0] == '/' )continue;// not in a section yetif ( secCount <= 0 ){section = node->str.GetToken(";", 1, 1);secCount = node->str.GetToken(";", 2, 2).ToInt();}else{CyString first = node->str.GetToken(";", 1, 1);if ( sceneModels->FindString(first) ){this->AddDummy(section, node->str);if ( add ){int pos = 4;int scene = node->str.GetToken(";", 3, 3).ToInt();for ( int i = 0; i < scene; i++ ){sceneModels->PushBack(node->str.GetToken(";", 5 + (i * 2), 5 + (i * 2)));pos += 2;}int model = node->str.GetToken(";", pos, pos).ToInt();for ( int i = 0; i < model; i++ )sceneModels->PushBack(node->str.GetToken(";", pos + (i * 2) + 1, pos + (i * 2) + 1));}}--secCount;}}delete lines;File.Remove();}}}void CXspFile::ExtractComponants(CCatFile *catFile, CyStringList *sceneModels){if ( !sceneModels ) return;if ( catFile->ExtractFile("types/components.pck", "tmp") ){CFileIO File("tmp");if ( File.Exists() ){CyString file;CyString section;int secCount = 0;int secCount2 = 0;CyStringList *lines = File.ReadLinesStr();for ( SStringList *node = lines->Head(); node; node = node->next ){node->str.RemoveFirstSpace();node->str.RemoveChar(9);node->str.RemoveChar('\r');if ( node->str.Empty() )continue;if ( node->str[0] == '/' )continue;// not in a section yetif ( secCount2 ){if ( sceneModels->FindString(file) )this->AddComponent(section, file, node->str);--secCount2;}else if ( secCount <= 0 ){section = node->str.GetToken(";", 1, 1);secCount = node->str.GetToken(";", 2, 2).ToInt();}else{file = node->str.GetToken(";", 1, 1);secCount2 = node->str.GetToken(";", 2, 2).ToInt();--secCount;}}delete lines;File.Remove();}}}bool CXspFile::GetTextureList(CyStringList *list, const unsigned char *olddata, size_t size){if ( !olddata || !size )return false;size_t startLine = 0;CyString line;size_t pos = 0;unsigned char *data = new unsigned char[size];memcpy(data, olddata, size);while ( (pos++) < size ){if ( data[pos] == '\n' ){data[pos] = '\0';line = (char *)(data + startLine);line.RemoveChar(9);line.RemoveChar('\r');line.RemoveFirstSpace();if ( !line.Empty() && line[0] != '/' ){CyString first = line.GetToken(":", 1, 1);if ( first.Compare("MATERIAL6") ){int max;CyString *strs = line.GetToken(":", 2).SplitToken("; ", &max);if ( strs && max >= 2){for ( int i = 2; i < max; i++ ){CyString s = strs[i];if ( s.IsIn(";") )s = s.GetToken(";", 1, 1);if ( !s.IsNumber() && !s.Compare("NULL") && s.IsIn(".") )list->PushBack(s, "", true);}}CLEANSPLIT(strs, max)}}startLine = pos + 1;}}delete [] data;return true;}void CXspFile::ExtractTextures(CCatFile *catFile){CyStringList lTextures;for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ){C_File *f = node->Data();if ( f->GetFileType() != FILETYPE_SHIPMODEL )continue;// cant do these yetif ( f->CheckFileExt("pbb") || f->CheckFileExt("bob") ){if ( !f->BobDecompile() )continue;}if ( !f->GetData() ){if ( !f->ReadFromFile() )continue;}unsigned char *data = NULL;size_t size;if ( f->CheckFileExt("pbb") || f->CheckFileExt("pbd") )data = f->UnPCKFile(&size);else{data = f->GetData();size = f->GetDataSize();}this->GetTextureList(&lTextures, data, size);}for ( SStringList *node = lTextures.Head(); node; node = node->next ){if ( CFileIO(node->str).CheckFileExtension("dds") )this->ExtractFileToPackage(catFile, CyString("dds\\") + node->str, FILETYPE_SHIPOTHER);elsethis->ExtractFileToPackage(catFile, CyString("textures\\") + node->str, FILETYPE_SHIPOTHER);}}bool CXspFile::AddTextFromFile(CyString file, int textId){bool remove = false;if ( CFileIO(file).CheckFileExtension("pck") ){C_File F(file);F.UnPCKFile();if ( F.WriteToFile("tmp") ){remove = true;file = "tmp";}}FILE *fid = fopen(file.c_str(), "r");if ( fid ){bool ret = this->AddTextFromFile(fid, textId);fclose(fid);if ( remove )CFileIO(file).Remove();m_bChanged = true;return ret;}return false;}bool CXspFile::ImportBodies(CyStringList *sceneModels, CyString filename){CFileIO File(filename);if ( File.Exists() ){CyString sSection;int section = 0;CyStringList *lines = File.ReadLinesStr();for ( SStringList *node = lines->Head(); node; node = node->next ){node->str.RemoveChar(9);node->str.RemoveChar('\r');node->str.RemoveFirstSpace();if ( node->str.Empty() )continue;if ( node->str[0] == '/' )continue;// are we looking for a sectionif ( section <= 0 ){sSection = node->str.GetToken(";", 1, 1);section = node->str.GetToken(";", 2, 2).ToInt();}else{int max;CyString *strs = node->str.SplitToken(";", &max);if ( strs && max ){for ( int i = 0; i < max; i++ ){strs[i].RemoveSpaces();if (strs[i].Empty() )continue;if ( sceneModels->FindString(strs[i]) )this->AddBody(sSection, strs[i]);--section;}}CLEANSPLIT(strs, max)}}delete lines;return true;}return false;}bool CXspFile::ImportCockpits(CyString filename){CFileIO File(filename);if ( File.Exists() ){CyStringList *lines = File.ReadLinesStr();int entries = 0;for ( SStringList *node = lines->Head(); node; node = node->next ){node->str.RemoveChar(9);node->str.RemoveChar('\r');node->str.RemoveFirstSpace();if ( node->str.Empty() )node->remove = true;else if ( node->str[0] == '/' )node->remove = true;else if ( !entries ){entries = node->str.GetToken(";", 2, 2).ToInt();node->remove = true;}}lines->RemoveMarked();// now get all the entries from TShipsfor ( int i = 0; i < 6; i++ ){int idx = m_sData.token(";", 32 + (i * 2));if ( idx < lines->Count() && idx ){CyString turret = lines->GetAt(idx)->str;int pos = -1;Utils::String id;while ( id.empty() && pos > -100 ) id = turret.GetToken(";", pos, pos--).ToString();m_sData = m_sData.replaceToken(";", 32 + (i * 2), id + "(" + (long)idx + ")");this->AddCockpit(turret, 0);}}delete lines;return true;}return false;}bool CXspFile::ExtractCockpits(CCatFile *catFile){if ( catFile->ExtractFile("types/TCockpits.pck", "tmp") ){bool ret = this->ImportCockpits("tmp");CFileIO("tmp").Remove();return ret;}return false;}bool CXspFile::ExtractBodies(CCatFile *catFile, CyStringList *sceneModels){if ( !sceneModels ) return false;if ( catFile->ExtractFile("types/Bodies.pck", "tmp") ){bool ret = this->ImportBodies(sceneModels, "tmp");CFileIO("tmp").Remove();return ret;}return false;}bool CXspFile::AddTextFromFile(FILE *id, int textId){if ( textId == -1 && !m_sData.empty() )textId = m_sData.token(";", 7);if ( textId <= 0 )return false;CyString line;if ( !id )return false;bool added = false;CyString shipName;CyString shipDesc;int lang = 0;bool inpage = false;while ( !feof(id) ){if ( !shipName.Empty() && !shipDesc.Empty() ){added = true;break;}line.GetEndOfLine(id, 0, false);line.RemoveChar(9);line.RemoveChar('\r');line.RemoveFirstSpace();if ( inpage ){if ( line.Left(6).Compare("</page") )break;// find matching idif ( line.Left(6).Compare("<t id=") ){int pos = line.FindPos("id=\"");if ( pos != -1 ){int endpos = line.FindPos("\"", pos + 5);if ( endpos != -1 ){int id = line.Mid(pos + 5, endpos).ToInt();if ( id == textId || id == (textId + 1) ){pos = line.FindPos(">", endpos);if ( pos != -1 ){endpos = line.FindPos("</t>", pos);if ( endpos != -1 ){if ( id == textId )shipName = line.Mid(pos + 2, endpos - (pos + 1));elseshipDesc = line.Mid(pos + 2, endpos - (pos + 1));}}}}}}}else if ( lang ) // search for page 17{if ( line.Left(8).Compare("<page id") ){int pos = line.FindPos("id=\"");if ( pos != -1 ){int endpos = line.FindPos("\"", pos + 5);if ( endpos != -1 ){CyString sId = line.Mid(pos + 5, endpos - (pos + 4));int id = sId.ToInt();if ( id == 17 || sId.Right(4).ToInt() == 17 )inpage = true;}}}}else if ( line.Left(12).Compare("<language id") ){int pos = line.FindPos("id=\"");if ( pos != -1 ){int endpos = line.FindPos("\"", pos + 5);if ( endpos != -1 )lang = line.Mid(pos + 5, endpos - (pos + 4)).ToInt();}}}// incase we only found the shipnameif ( !shipName.Empty() )added = true;if ( added ){if ( lang == 44 || m_sName.Empty()){m_sName = shipName;m_sDescription= shipDesc;m_sDescription = m_sDescription.FindReplace("&", "&");}this->AddText(lang, shipName, shipDesc);return true;}return false;}void CXspFile::ExtractTexts(CCatFile *catFile, int textId){for ( CListNode<SInCatFile> *node = catFile->GetFiles()->Front(); node; node = node->next() ){SInCatFile *f = node->Data();if ( !f->sFile.Left(2).Compare("t\\") && !f->sFile.Left(2).Compare("t/") )continue;// extract the text file and read in the dataif ( catFile->ExtractFile(f->sFile, "tmp") ){this->AddTextFromFile("tmp", textId);CFileIO("tmp").Remove();}}}bool CXspFile::ProcessSceneFileSection(int section, CCatFile *catFile, CyStringList *lModels, CProgressInfo *progress){if ( progress ) progress->UpdateStatus(section);switch ( section ){case IMPORTSHIP_COMPONANT:if ( !lModels ) return false;this->ExtractComponants(catFile, lModels);break;case IMPORTSHIP_MODELS:{if ( !lModels ) return false;for ( SStringList *node = lModels->Head(); node; node = node->next ){if ( node->str.IsNumber() ) // count be componants or dummycontinue;if ( this->ExtractFileToPackage(catFile, CyString("objects\\") + node->str + ".pbb", FILETYPE_SHIPMODEL, CyString("objects\\") + node->str + ".bob") )continue;if ( this->ExtractFileToPackage(catFile, CyString("objects\\") + node->str + ".pbd", FILETYPE_SHIPMODEL, CyString("objects\\") + node->str + ".bod") )continue;if ( this->ExtractFileToPackage(catFile, CyString("objects\\") + node->str + ".bob", FILETYPE_SHIPMODEL) )continue;if ( this->ExtractFileToPackage(catFile, CyString("objects\\") + node->str + ".bod", FILETYPE_SHIPMODEL) )continue;}}break;case IMPORTSHIP_DUMMIES:if ( !lModels ) return false;this->ExtractDummies(catFile, lModels, true);break;// extract the texturescase IMPORTSHIP_TEXTURES:this->ExtractTextures(catFile);break;case IMPORTSHIP_TEXTS:// extract the text file entriesthis->ExtractTexts(catFile, m_sData.token(";", 7));break;case IMPORTSHIP_BODIES:// extract the bodies entriesif ( !lModels ) return false;this->ExtractBodies(catFile, lModels);break;case IMPORTSHIP_COCKPITS:// extract the cockpit entriesthis->ExtractCockpits(catFile);break;}return true;}bool CXspFile::ProcessSceneFiles(CCatFile *catFile, CProgressInfo *progress){// now lets parse our filesif ( progress ) progress->UpdateStatus(IMPORTSHIP_EXTRACTSCENE);CyStringList *lModels = this->ReadSceneModels();if ( !lModels )return false;// extract componants, and add extra items to listif ( !this->ProcessSceneFileSection(IMPORTSHIP_COMPONANT, catFile, lModels, progress) )return false;//lets first find any model filesif ( !this->ProcessSceneFileSection(IMPORTSHIP_MODELS, catFile, lModels, progress) )return false;// extract the dummiesif ( !this->ProcessSceneFileSection(IMPORTSHIP_DUMMIES, catFile, lModels, progress) )return false;// extract the texturesif ( !this->ProcessSceneFileSection(IMPORTSHIP_TEXTURES, catFile, lModels, progress) )return false;// extract the text file entriesif ( !this->ProcessSceneFileSection(IMPORTSHIP_TEXTS, catFile, lModels, progress) )return false;// extract the bodies entriesif ( !this->ProcessSceneFileSection(IMPORTSHIP_BODIES, catFile, lModels, progress) )return false;// extract the cockpit entriesif ( !this->ProcessSceneFileSection(IMPORTSHIP_COCKPITS, catFile, lModels, progress) )return false;delete lModels;return true;}bool CXspFile::ProcessSceneFiles(CyString catFile, CProgressInfo *progress){CCatFile cat;if ( cat.Open(catFile, "", CATREAD_CATDECRYPT, false) == CATERR_NONE )return ProcessSceneFiles(&cat, progress);return false;}void CXspFile::PackAllFiles(){for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ){C_File *f = node->Data();if ( f->GetFileType() == FILETYPE_SHIPSCENE || f->GetFileType() == FILETYPE_COCKPITSCENE || f->GetFileType() == FILETYPE_SHIPMODEL || f->GetFileType() == FILETYPE_SHIPOTHER ){if ( f->CheckFileExt("bod") ){if ( f->PCKFile() )f->ChangeFileExt("pbd");}else if ( f->CheckFileExt("bob") ){if ( f->PCKFile() )f->ChangeFileExt("pbb");}}}}void CXspFile::AdjustCockpits(){for ( CListNode<SCockpit> *node = m_lCockpit.Front(); node; node = node->next() ){SCockpit *c = node->Data();if ( c->iIndex < 0 )continue;CyString id = c->sCockpit.GetToken(";", 19, 19);for ( int i = 0; i < 6; i++ ){CyString tId = m_sData.token(";", 32 + (i * 2));if ( tId.IsNumber() && tId.ToInt() == c->iIndex )m_sData = m_sData.replaceToken(";", 32 + (i * 2), (id + "(" + CyString::Number(c->iIndex) + ")").c_str());}}}CyString CXspFile::FormatShipData(CyStringList *cockpits, int *text, int game){CyString data = (game == GAME_X3) ? this->GetX3ShipData() : this->GetTCShipData();// do turretsfor ( int t = 0; t < 6; t++ ){int oldPos = 0;CyString turret = data.GetToken(";", 32 + (t * 2), 32 + (t * 2));if ( !turret.IsNumber() ){if ( turret.IsIn("(") ){oldPos = turret.GetToken("(", 2).GetToken(")", 1, 1).ToInt();turret = turret.GetToken("(", 1, 1);}int pos = cockpits->FindStringPos(turret);if ( pos < 0 ) pos = oldPos;data = data.RepToken(";", 32 + (t * 2), CyString::Number(pos));}}// adjust the weaponsint mask = this->GetLaserMask(game - 1);if ( mask != -1 )data = data.RepToken(";", 19, CyString::Number(mask));mask = this->GetMissileMask(game - 1);if ( mask != -1 )data = data.RepToken(";", 25, CyString::Number(mask));// fix the ship textif ( m_iOrgDesc > 0 )(*text) = m_iOrgDesc;data = data.RepToken(";", 7, CyString::Number(*text));// add the ware iddata.RemoveChar(9);data.RemoveEndSpace();// remove the end ;while ( data.Right(1) == ";" ) data.Truncate((int)data.Length() - 1);data = data.RepToken(";", data.NumToken(";"), this->GetShipID());if ( data.Right(1) != ";" )data += ";";return data;}