/* * Copyright 2010-2013 OpenXcom Developers. * * This file is part of OpenXcom. * * OpenXcom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenXcom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenXcom. If not, see . */ #include "XcomResourcePack.h" #include #include "../Engine/CrossPlatform.h" #include "../Engine/Palette.h" #include "../Engine/Font.h" #include "../Engine/Surface.h" #include "../Engine/SurfaceSet.h" #include "../Engine/Language.h" #include "../Engine/Music.h" #include "../Engine/GMCat.h" #include "../Engine/SoundSet.h" #include "../Engine/Sound.h" #include "../Engine/Options.h" #include "../Geoscape/Globe.h" #include "../Geoscape/Polygon.h" #include "../Geoscape/Polyline.h" #include "../Interface/TextButton.h" #include "../Interface/Window.h" #include "../Savegame/SavedBattleGame.h" #include "../Savegame/Tile.h" #include "../Savegame/Node.h" #include "../Battlescape/Position.h" #include "../Ruleset/MapDataSet.h" #include "../Engine/ShaderDraw.h" #include "../Engine/ShaderMove.h" #include "../Engine/Exception.h" #include "../Engine/Logger.h" #include "../Ruleset/ExtraSprites.h" #include "../Ruleset/ExtraSounds.h" namespace OpenXcom { namespace { struct HairBleach { static const Uint8 ColorGroup = 15<<4; static const Uint8 ColorShade = 15; static const Uint8 Hair = 9 << 4; static const Uint8 Face = 6 << 4; static inline void func(Uint8& src, const Uint8& cutoff, int, int, int) { if(src > cutoff && src <= Face + 15) { src = Hair + (src & ColorShade) - 6; //make hair color like male in xcom_0.pck } } }; } /** * Initializes the resource pack by loading all the resources * contained in the original game folder. */ XcomResourcePack::XcomResourcePack(std::vector > extraSprites, std::vector > extraSounds) : ResourcePack() { // Load palettes for (int i = 0; i < 5; ++i) { std::stringstream s1, s2; s1 << "GEODATA/PALETTES.DAT"; s2 << "PALETTES.DAT_" << i; _palettes[s2.str()] = new Palette(); _palettes[s2.str()]->loadDat(CrossPlatform::getDataFile(s1.str()), 256, Palette::palOffset(i)); } std::stringstream s1, s2; s1 << "GEODATA/BACKPALS.DAT"; s2 << "BACKPALS.DAT"; _palettes[s2.str()] = new Palette(); _palettes[s2.str()]->loadDat(CrossPlatform::getDataFile(s1.str()), 128); // Load fonts YAML::Node doc = YAML::LoadFile(CrossPlatform::getDataFile("Language/Font.dat")); Font::setIndex(Language::utf8ToWstr(doc["chars"].as())); for (YAML::const_iterator i = doc["fonts"].begin(); i != doc["fonts"].end(); ++i) { std::string id = (*i)["id"].as(); Font *font = new Font(); font->load(*i); _fonts[id] = font; } // Load surfaces { std::stringstream s; s << "GEODATA/" << "INTERWIN.DAT"; _surfaces["INTERWIN.DAT"] = new Surface(160, 556); _surfaces["INTERWIN.DAT"]->loadScr(CrossPlatform::getDataFile(s.str())); } std::string geograph = CrossPlatform::getDataFolder("GEOGRAPH/"); std::vector scrs = CrossPlatform::getFolderContents(geograph, "SCR"); for (std::vector::iterator i = scrs.begin(); i != scrs.end(); ++i) { std::string path = geograph + *i; std::transform(i->begin(), i->end(), i->begin(), toupper); _surfaces[*i] = new Surface(320, 200); _surfaces[*i]->loadScr(path); } // here we create an "alternate" background surface for the base info screen. _surfaces["ALTBACK07.SCR"] = new Surface(320, 200); _surfaces["ALTBACK07.SCR"]->loadScr(CrossPlatform::getDataFile("GEOGRAPH/BACK07.SCR")); for (int y = 172; y >= 152; --y) for (int x = 5; x <= 314; ++x) _surfaces["ALTBACK07.SCR"]->setPixel(x, y+4, _surfaces["ALTBACK07.SCR"]->getPixel(x,y)); for (int y = 147; y >= 134; --y) for (int x = 5; x <= 314; ++x) _surfaces["ALTBACK07.SCR"]->setPixel(x, y+9, _surfaces["ALTBACK07.SCR"]->getPixel(x,y)); for (int y = 132; y >= 109; --y) for (int x = 5; x <= 314; ++x) _surfaces["ALTBACK07.SCR"]->setPixel(x, y+10, _surfaces["ALTBACK07.SCR"]->getPixel(x,y)); std::vector spks = CrossPlatform::getFolderContents(geograph, "SPK"); for (std::vector::iterator i = spks.begin(); i != spks.end(); ++i) { std::string path = geograph + *i; std::transform(i->begin(), i->end(), i->begin(), toupper); _surfaces[*i] = new Surface(320, 200); _surfaces[*i]->loadSpk(path); } // Load intro std::string ufointro = CrossPlatform::getDataFolder("UFOINTRO/"); std::vector lbms = CrossPlatform::getFolderContents(ufointro, "LBM"); for (std::vector::iterator i = lbms.begin(); i != lbms.end(); ++i) { std::string path = ufointro + *i; std::transform(i->begin(), i->end(), i->begin(), toupper); _surfaces[*i] = new Surface(320, 200); _surfaces[*i]->loadImage(path); } // Load surface sets std::string sets[] = {"BASEBITS.PCK", "INTICON.PCK", "TEXTURE.DAT"}; for (int i = 0; i < 3; ++i) { std::stringstream s; s << "GEOGRAPH/" << sets[i]; std::string ext = sets[i].substr(sets[i].length()-3, sets[i].length()); if (ext == "PCK") { std::string tab = sets[i].substr(0, sets[i].length()-4) + ".TAB"; std::stringstream s2; s2 << "GEOGRAPH/" << tab; _sets[sets[i]] = new SurfaceSet(32, 40); _sets[sets[i]]->loadPck(CrossPlatform::getDataFile(s.str()), CrossPlatform::getDataFile(s2.str())); } else { _sets[sets[i]] = new SurfaceSet(32, 32); _sets[sets[i]]->loadDat(CrossPlatform::getDataFile(s.str())); } } _sets["SCANG.DAT"] = new SurfaceSet(4, 4); std::stringstream scang; scang << "GEODATA/" << "SCANG.DAT"; _sets["SCANG.DAT"]->loadDat (CrossPlatform::getDataFile(scang.str())); // Load polygons std::stringstream s; s << "GEODATA/" << "WORLD.DAT"; Globe::loadDat(CrossPlatform::getDataFile(s.str()), &_polygons); // Load polylines (extracted from game) // -10 = Start of line // -20 = End of data double lines[] = {-10, 1.18901, -0.412334, 1.23918, -0.425424, 1.213, -0.471239, 1.22828, -0.490874, 1.23482, -0.482147, 1.30245, -0.541052, 1.29373, -0.608684, 1.35918, -0.61741, 1.38099, -0.53887, 1.41154, -0.530144, 1.39626, -0.503964, 1.53153, -0.460331, 1.54025, -0.488692, 1.55116, -0.490874, 1.55334, -0.466876, 1.60352, -0.469057, 1.59916, -0.488692, 1.67552, -0.517054, 1.69515, -0.475602, 1.61661, -0.386154, 1.61225, -0.436332, 1.56861, -0.440696, 1.56425, -0.460331, 1.54243, -0.462512, 1.53589, -0.449422, 1.55552, -0.373064, -10, 6.13047, -0.726493, 6.17628, -0.726493, 6.1501, -0.645772, -10, 6.25264, -0.759218, 0.0109083, -0.73522, 0.0567232, -0.741765, -10, 0.128718, -0.7614, 0.122173, -0.80067, 0.102538, -0.807215, 0.1309, -0.829031, 0.14399, -0.85303, 0.111265, -0.863938, 0.0719948, -0.870483, 0.0501782, -0.885755, -10, 0.122173, -0.80067, 0.148353, -0.811578, 0.159261, -0.80067, 0.211621, -0.820305, 0.239983, -0.811578, 0.239983, -0.794125, -10, 0.111265, -0.863938, 0.102538, -0.907571, 0.11781, -0.90539, 0.122173, -0.938114, -10, 0.139626, -0.959931, 0.181078, -0.953386, -10, 0.248709, -0.942478, 0.261799, -0.887936, 0.213803, -0.877028, 0.242164, -0.85303, 0.229074, -0.829031, 0.1309, -0.829031, -10, 0.0458149, -0.109083, 0.0479966, -0.148353, 0.0654498, -0.185441, 0.0698132, -0.237801, 0.0981748, -0.244346, 0.122173, -0.224711, 0.17017, -0.222529, 0.231256, -0.235619, 0.257436, -0.211621, 0.19635, -0.113446, 0.176715, -0.126536, 0.148353, -0.0763582, -10, 0.438514, -0.554142, 0.436332, -0.383972, 0.595594, -0.383972, 0.628319, -0.410152, -10, 0.59123, -0.547597, 0.619592, -0.493056, -10, 0.283616, 0.4996, 0.349066, 0.495237, 0.349066, 0.434151, 0.362156, 0.469057, 0.407971, 0.440696, 0.447241, 0.449422, 0.510509, 0.386154, 0.545415, 0.390517, 0.558505, 0.469057, 0.575959, 0.464694, -10, 5.36252, 0.580322, 5.27962, 0.523599, 5.34071, 0.449422, 5.27089, 0.386154, 5.26653, 0.283616, 5.14436, 0.174533, 5.05491, 0.194168, 4.996, 0.14399, 5.01564, 0.0872665, 5.06364, 0.0763582, 5.06582, -0.0305433, 5.18145, -0.0370882, 5.15527, -0.0698132, 5.2229, -0.0938114, 5.2578, -0.019635, 5.35816, -0.0327249, 5.38652, -0.0741765, -10, 4.10152, -0.85303, 4.45059, -0.85303, 4.62512, -0.855211, 4.71893, -0.837758, -10, 5.116, -0.776672, 5.08545, -0.824668, 5.03309, -0.785398, 4.97419, -0.785398, 4.95019, -0.770127, -10, 3.82227, -1.21519, 3.82227, -1.05374, 4.01426, -0.977384, 3.95972, -0.949023, -10, 4.23897, -0.569414, 4.42659, -0.554142, 4.48113, -0.503964, 4.51386, -0.519235, 4.55531, -0.460331, 4.59022, -0.455967, -10, 4.82584, -0.728675, 4.84983, -0.750492, -10, 4.8062, -0.81376, 4.82802, -0.80067, -10, 0.545415, -1.21955, 0.549779, -1.09738, 0.490874, -1.05156, -10, 0.488692, -1.04283, 0.490874, -0.981748, 0.569414, -0.933751, 0.554142, -0.909753, 0.698132, -0.863938, 0.665407, -0.818123, -10, 0.693768, -0.763582, 0.857393, -0.730857, -10, 0.861756, -0.805033, 0.831213, -0.87921, 1.0472, -0.885755, 1.0712, -0.944659, 1.2021, -0.966476, 1.34172, -0.951204, 1.39626, -0.885755, 1.53589, -0.857393, 1.71042, -0.872665, 1.72569, -0.909753, 1.91986, -0.859575, 2.03767, -0.870483, 2.08131, -0.872665, 2.09658, -0.922843, 2.19693, -0.925025, 2.23184, -0.86612, 2.34747, -0.842121, 2.32129, -0.785398, 2.28638, -0.783217, 2.27984, -0.73522, 2.16857, -0.698132, -10, 1.88277, -0.375246, 1.8435, -0.407971, 1.77587, -0.370882, 1.73006, -0.386154, 1.72569, -0.423242, 1.7017, -0.418879, 1.72569, -0.477784, 1.69515, -0.475602, -10, 1.59916, -0.488692, 1.55116, -0.490874, -10, 1.54025, -0.488692, 1.41154, -0.530144, -10, 1.35918, -0.61741, 1.28064, -0.687223, 1.40499, -0.737402, 1.39626, -0.785398, 1.4399, -0.78758, 1.44644, -0.824668, 1.49662, -0.822486, 1.50753, -0.857393, 1.53589, -0.857393, 1.5817, -0.789761, 1.67988, -0.746128, 1.8326, -0.724312, 1.95477, -0.7614, 1.95695, -0.785398, 2.09221, -0.815941, 2.02022, -0.833395, 2.03767, -0.870483, -20}; Polyline *l = 0; int start = 0; for (int i = 0; lines[i] > -19.999; ++i) { if (lines[i] < -9.999 && lines[i] > -10.001) { if (l != 0) { _polylines.push_back(l); } int points = 0; for (int j = i + 1; lines[j] > -9.999; ++j) { points++; } points /= 2; l = new Polyline(points); start = i + 1; } else { if ((i - start) % 2 == 0) { l->setLongitude((i - start) / 2, lines[i]); } else { l->setLatitude((i - start) / 2, lines[i]); } } } _polylines.push_back(l); if (!Options::getBool("mute")) { // Load musics std::string mus[] = {"GMDEFEND", "GMENBASE", "GMGEO1", "GMGEO2", "GMGEO3", "GMGEO4", "GMINTER", "GMINTRO1", "GMINTRO2", "GMINTRO3", "GMLOSE", "GMMARS", "GMNEWMAR", "GMSTORY", "GMTACTIC", "GMTACTIC2", "GMWIN"}; std::string exts[] = {"flac", "ogg", "mp3", "mod"}; int tracks[] = {3, 6, 0, 18, -1, -1, 2, 19, 20, 21, 10, 9, 8, 12, 17, -1, 11}; #ifndef __NO_MUSIC // Check which music version is available bool cat = true; GMCatFile *gmcat = 0; std::string musDos = "SOUND/GM.CAT"; if (CrossPlatform::fileExists(CrossPlatform::getDataFile(musDos))) { cat = true; gmcat = new GMCatFile(CrossPlatform::getDataFile(musDos).c_str()); } else { cat = false; } for (int i = 0; i < 17; ++i) { bool loaded = false; // Try digital tracks for (int j = 0; j < 3; ++j) { std::stringstream s; s << "SOUND/" << mus[i] << "." << exts[j]; if (CrossPlatform::fileExists(CrossPlatform::getDataFile(s.str()))) { _musics[mus[i]] = new Music(); _musics[mus[i]]->load(CrossPlatform::getDataFile(s.str())); loaded = true; break; } } if (!loaded) { // Try Adlib music if (cat && tracks[i] != -1) { _musics[mus[i]] = gmcat->loadMIDI(tracks[i]); loaded = true; } // Try MIDI music else { std::stringstream s; s << "SOUND/" << mus[i] << ".mid"; if (CrossPlatform::fileExists(CrossPlatform::getDataFile(s.str()))) { _musics[mus[i]] = new Music(); _musics[mus[i]]->load(CrossPlatform::getDataFile(s.str())); loaded = true; } } } if (!loaded && tracks[i] != -1) { throw Exception(mus[i] + " not found"); } } delete gmcat; #endif // Load sounds std::string catsId[] = {"GEO.CAT", "BATTLE.CAT"}; std::string catsDos[] = {"SOUND2.CAT", "SOUND1.CAT"}; std::string catsWin[] = {"SAMPLE.CAT", "SAMPLE2.CAT"}; // Check which sound version is available std::string *cats = 0; bool wav = true; std::stringstream win, dos; win << "SOUND/" << catsWin[0]; dos << "SOUND/" << catsDos[0]; if (CrossPlatform::fileExists(CrossPlatform::getDataFile(win.str()))) { cats = catsWin; wav = true; } else if (CrossPlatform::fileExists(CrossPlatform::getDataFile(dos.str()))) { cats = catsDos; wav = false; } for (int i = 0; i < 2; ++i) { if (cats == 0) { std::stringstream ss; ss << catsDos[i] << " not found"; throw Exception(ss.str()); } else { std::stringstream s; s << "SOUND/" << cats[i]; _sounds[catsId[i]] = new SoundSet(); _sounds[catsId[i]]->loadCat(CrossPlatform::getDataFile(s.str()), wav); } } if (CrossPlatform::fileExists(CrossPlatform::getDataFile("SOUND/INTRO.CAT"))) { SoundSet *s = _sounds["INTRO.CAT"] = new SoundSet(); s->loadCat(CrossPlatform::getDataFile("SOUND/INTRO.CAT"), false); } else { Log(LOG_WARNING) << "INTRO.CAT is missing! :("; } if (CrossPlatform::fileExists(CrossPlatform::getDataFile("SOUND/SAMPLE3.CAT"))) { SoundSet *s = _sounds["SAMPLE3.CAT"] = new SoundSet(); wav = true; s->loadCat(CrossPlatform::getDataFile("SOUND/SAMPLE3.CAT"), true); } else { Log(LOG_WARNING) << "SAMPLE3.CAT is missing! :("; } } TextButton::soundPress = getSound("GEO.CAT", 0); Window::soundPopup[0] = getSound("GEO.CAT", 1); Window::soundPopup[1] = getSound("GEO.CAT", 2); Window::soundPopup[2] = getSound("GEO.CAT", 3); loadBattlescapeResources(); // TODO load this at battlescape start, unload at battlescape end? Log(LOG_INFO) << "Loading extra resources from ruleset..."; bool debugOutput = Options::getBool("debug"); for (std::vector >::const_iterator i = extraSprites.begin(); i != extraSprites.end(); ++i) { std::string sheetName = i->first; ExtraSprites *spritePack = i->second; bool subdivision = (spritePack->getSubX() != 0 && spritePack->getSubY() != 0); if (spritePack->getSingleImage()) { if (_surfaces.find(sheetName) == _surfaces.end()) { if (debugOutput) { Log(LOG_INFO) << "Creating new single image: " << sheetName; } _surfaces[sheetName] = new Surface(spritePack->getWidth(), spritePack->getHeight()); } else { if (debugOutput) { Log(LOG_INFO) << "Adding/Replacing single image: " << sheetName; } delete _surfaces[sheetName]; _surfaces[sheetName] = new Surface(spritePack->getWidth(), spritePack->getHeight()); } s.str(""); s << CrossPlatform::getDataFile(spritePack->getSprites()->operator[](0)); _surfaces[sheetName]->loadImage(s.str()); } else { bool adding = false; if (_sets.find(sheetName) == _sets.end()) { if (debugOutput) { Log(LOG_INFO) << "Creating new surface set: " << sheetName; } adding = true; if (subdivision) { _sets[sheetName] = new SurfaceSet(spritePack->getSubX(), spritePack->getSubY()); } else { _sets[sheetName] = new SurfaceSet(spritePack->getWidth(), spritePack->getHeight()); } } else if (debugOutput) { Log(LOG_INFO) << "Adding/Replacing items in surface set: " << sheetName; } if (subdivision && debugOutput) { int frames = (spritePack->getWidth() / spritePack->getSubX())*(spritePack->getHeight() / spritePack->getSubY()); Log(LOG_INFO) << "Subdividing into " << frames << " frames."; } for (std::map::iterator j = spritePack->getSprites()->begin(); j != spritePack->getSprites()->end(); ++j) { int startFrame = j->first; std:: string fileName = j->second; s.str(""); if (fileName.substr(fileName.length() - 1, 1) == "/") { if (debugOutput) { Log(LOG_INFO) << "Loading surface set from folder: " << fileName << " starting at frame: " << startFrame; } int offset = startFrame; std::stringstream folder; folder << CrossPlatform::getDataFolder(fileName); std::vector contents = CrossPlatform::getFolderContents(folder.str()); for (std::vector::iterator k = contents.begin(); k != contents.end(); ++k) { try { s.str(""); s << folder.str() << CrossPlatform::getDataFile(*k); if (_sets[sheetName]->getFrame(offset)) { if (debugOutput) { Log(LOG_INFO) << "Replacing frame: " << offset; } _sets[sheetName]->getFrame(offset)->loadImage(s.str()); } else { if (adding) { _sets[sheetName]->addFrame(offset)->loadImage(s.str()); } else { if (debugOutput) { Log(LOG_INFO) << "Adding frame: " << offset + spritePack->getModIndex(); } _sets[sheetName]->addFrame(offset + spritePack->getModIndex())->loadImage(s.str()); } } offset++; } catch (Exception &e) { Log(LOG_WARNING) << e.what(); } } } else { if (spritePack->getSubX() == 0 && spritePack->getSubY() == 0) { s << CrossPlatform::getDataFile(fileName); if (_sets[sheetName]->getFrame(startFrame)) { if (debugOutput) { Log(LOG_INFO) << "Replacing frame: " << startFrame; } _sets[sheetName]->getFrame(startFrame)->loadImage(s.str()); } else { if (debugOutput) { Log(LOG_INFO) << "Adding frame: " << startFrame << ", using index: " << startFrame + spritePack->getModIndex(); } _sets[sheetName]->addFrame(startFrame + spritePack->getModIndex())->loadImage(s.str()); } } else { Surface *temp = new Surface(spritePack->getWidth(), spritePack->getHeight()); s.str(""); s << CrossPlatform::getDataFile(spritePack->getSprites()->operator[](startFrame)); temp->loadImage(s.str()); int xDivision = spritePack->getWidth() / spritePack->getSubX(); int yDivision = spritePack->getHeight() / spritePack->getSubY(); int offset = startFrame; for (int y = 0; y != yDivision; ++y) { for (int x = 0; x != xDivision; ++x) { if (_sets[sheetName]->getFrame(offset)) { if (debugOutput) { Log(LOG_INFO) << "Replacing frame: " << offset; } _sets[sheetName]->getFrame(offset)->clear(); // for some reason regular blit() doesn't work here how i want it, so i use this function instead. temp->blitNShade(_sets[sheetName]->getFrame(offset), 0 - (x * spritePack->getSubX()), 0 - (y * spritePack->getSubY()), 0); } else { if (adding) { // for some reason regular blit() doesn't work here how i want it, so i use this function instead. temp->blitNShade(_sets[sheetName]->addFrame(offset), 0 - (x * spritePack->getSubX()), 0 - (y * spritePack->getSubY()), 0); } else { if (debugOutput) { Log(LOG_INFO) << "Adding frame: " << offset + spritePack->getModIndex(); } // for some reason regular blit() doesn't work here how i want it, so i use this function instead. temp->blitNShade(_sets[sheetName]->addFrame(offset + spritePack->getModIndex()), 0 - (x * spritePack->getSubX()), 0 - (y * spritePack->getSubY()), 0); } } ++offset; } } delete temp; } } } } } // copy constructor doesn't like doing this directly, so let's make a second handobs file the old fashioned way. // handob2 is used for all the left handed sprites. _sets["HANDOB2.PCK"] = new SurfaceSet(_sets["HANDOB.PCK"]->getWidth(), _sets["HANDOB.PCK"]->getHeight()); std::map *handob = _sets["HANDOB.PCK"]->getFrames(); for (std::map::const_iterator i = handob->begin(); i != handob->end(); ++i) { (i->second)->blit(_sets["HANDOB2.PCK"]->addFrame(i->first)); } for (std::vector >::const_iterator i = extraSounds.begin(); i != extraSounds.end(); ++i) { std::string setName = i->first; ExtraSounds *soundPack = i->second; if (_sounds.find(setName) == _sounds.end()) { if (debugOutput) { Log(LOG_INFO) << "Creating new sound set: " << setName << ", this will likely have no in-game use."; } _sounds[setName] = new SoundSet(); } else if (debugOutput) { Log(LOG_INFO) << "Adding/Replacing items in sound set: " << setName; } for (std::map::iterator j = soundPack->getSounds()->begin(); j != soundPack->getSounds()->end(); ++j) { int startSound = j->first; std::string fileName = j->second; s.str(""); if (fileName.substr(fileName.length() - 1, 1) == "/") { if (debugOutput) { Log(LOG_INFO) << "Loading sound set from folder: " << fileName << " starting at index: " << startSound; } int offset = startSound; std::stringstream folder; folder << CrossPlatform::getDataFolder(fileName); std::vector contents = CrossPlatform::getFolderContents(folder.str()); for (std::vector::iterator k = contents.begin(); k != contents.end(); ++k) { try { s.str(""); s << folder.str() << CrossPlatform::getDataFile(*k); if (_sounds[setName]->getSound(offset)) { _sounds[setName]->getSound(offset)->load(s.str()); } else { _sounds[setName]->addSound(offset + soundPack->getModIndex())->load(s.str()); } offset++; } catch (Exception &e) { Log(LOG_WARNING) << e.what(); } } } else { s << CrossPlatform::getDataFile(fileName); if (_sounds[setName]->getSound(startSound)) { if (debugOutput) { Log(LOG_INFO) << "Replacing index: " << startSound; } _sounds[setName]->getSound(startSound)->load(s.str()); } else { if (debugOutput) { Log(LOG_INFO) << "Adding index: " << startSound; } _sounds[setName]->addSound(startSound + soundPack->getModIndex())->load(s.str()); } } } } } /** * */ XcomResourcePack::~XcomResourcePack() { } void XcomResourcePack::loadBattlescapeResources() { // Load Battlescape ICONS std::stringstream s; s << "UFOGRAPH/" << "SPICONS.DAT"; _sets["SPICONS.DAT"] = new SurfaceSet(32, 24); _sets["SPICONS.DAT"]->loadDat(CrossPlatform::getDataFile(s.str())); s.str(""); std::stringstream s2; s << "UFOGRAPH/" << "CURSOR.PCK"; s2 << "UFOGRAPH/" << "CURSOR.TAB"; _sets["CURSOR.PCK"] = new SurfaceSet(32, 40); _sets["CURSOR.PCK"]->loadPck(CrossPlatform::getDataFile(s.str()), CrossPlatform::getDataFile(s2.str())); s.str(""); s2.str(""); s << "UFOGRAPH/" << "SMOKE.PCK"; s2 << "UFOGRAPH/" << "SMOKE.TAB"; _sets["SMOKE.PCK"] = new SurfaceSet(32, 40); _sets["SMOKE.PCK"]->loadPck(CrossPlatform::getDataFile(s.str()), CrossPlatform::getDataFile(s2.str())); s.str(""); s2.str(""); s << "UFOGRAPH/" << "HIT.PCK"; s2 << "UFOGRAPH/" << "HIT.TAB"; _sets["HIT.PCK"] = new SurfaceSet(32, 40); _sets["HIT.PCK"]->loadPck(CrossPlatform::getDataFile(s.str()), CrossPlatform::getDataFile(s2.str())); s.str(""); s2.str(""); s << "UFOGRAPH/" << "X1.PCK"; s2 << "UFOGRAPH/" << "X1.TAB"; _sets["X1.PCK"] = new SurfaceSet(128, 64); _sets["X1.PCK"]->loadPck(CrossPlatform::getDataFile(s.str()), CrossPlatform::getDataFile(s2.str())); s.str(""); _sets["MEDIBITS.DAT"] = new SurfaceSet(52, 58); s << "UFOGRAPH/" << "MEDIBITS.DAT"; _sets["MEDIBITS.DAT"]->loadDat (CrossPlatform::getDataFile(s.str())); s.str(""); _sets["DETBLOB.DAT"] = new SurfaceSet(16, 16); s << "UFOGRAPH/" << "DETBLOB.DAT"; _sets["DETBLOB.DAT"]->loadDat (CrossPlatform::getDataFile(s.str())); // Load Battlescape Terrain (only blacks are loaded, others are loaded just in time) std::string bsets[] = {"BLANKS.PCK"}; for (int i = 0; i < 1; ++i) { std::stringstream s; s << "TERRAIN/" << bsets[i]; std::string tab = bsets[i].substr(0, bsets[i].length()-4) + ".TAB"; std::stringstream s2; s2 << "TERRAIN/" << tab; _sets[bsets[i]] = new SurfaceSet(32, 40); _sets[bsets[i]]->loadPck(CrossPlatform::getDataFile(s.str()), CrossPlatform::getDataFile(s2.str())); } // Load Battlescape units std::string units = CrossPlatform::getDataFolder("UNITS/"); std::vector usets = CrossPlatform::getFolderContents(units, "PCK"); for (std::vector::iterator i = usets.begin(); i != usets.end(); ++i) { std::string path = units + *i; std::string tab = CrossPlatform::getDataFile("UNITS/" + i->substr(0, i->length() - 4) + ".TAB"); std::transform(i->begin(), i->end(), i->begin(), toupper); if (*i != "BIGOBS.PCK") _sets[*i] = new SurfaceSet(32, 40); else _sets[*i] = new SurfaceSet(32, 48); _sets[*i]->loadPck(path, tab); } s.str(""); s << "GEODATA/" << "LOFTEMPS.DAT"; MapDataSet::loadLOFTEMPS(CrossPlatform::getDataFile(s.str()), &_voxelData); std::string scrs[] = {"TAC00.SCR"}; for (int i = 0; i < 1; ++i) { std::stringstream s; s << "UFOGRAPH/" << scrs[i]; _surfaces[scrs[i]] = new Surface(320, 200); _surfaces[scrs[i]]->loadScr(CrossPlatform::getDataFile(s.str())); } std::string spks[] = {"TAC01.SCR", "DETBORD.PCK", "DETBORD2.PCK", "ICONS.PCK", "MEDIBORD.PCK", "SCANBORD.PCK", "UNIBORD.PCK"}; for (int i = 0; i < 7; ++i) { std::stringstream s; s << "UFOGRAPH/" << spks[i]; _surfaces[spks[i]] = new Surface(320, 200); _surfaces[spks[i]]->loadSpk(CrossPlatform::getDataFile(s.str())); } // Load Battlescape inventory std::string ufograph = CrossPlatform::getDataFolder("UFOGRAPH/"); std::vector invs = CrossPlatform::getFolderContents(ufograph, "SPK"); for (std::vector::iterator i = invs.begin(); i != invs.end(); ++i) { std::string path = ufograph + *i; std::transform(i->begin(), i->end(), i->begin(), toupper); _surfaces[*i] = new Surface(320, 200); _surfaces[*i]->loadSpk(path); } //"fix" of hair color of male personal armor if (Options::getBool("battleHairBleach")) { SurfaceSet *xcom_1 = _sets["XCOM_1.PCK"]; for (int i = 0; i < 16; ++i) { //chest frame Surface *surf = xcom_1->getFrame(4 * 8 + i); ShaderMove head = ShaderMove(surf); GraphSubset dim = head.getBaseDomain(); surf->lock(); dim.beg_y = 6; dim.end_y = 9; head.setDomain(dim); ShaderDraw(head, ShaderScalar(HairBleach::Face + 5)); dim.beg_y = 9; dim.end_y = 10; head.setDomain(dim); ShaderDraw(head, ShaderScalar(HairBleach::Face + 6)); surf->unlock(); } for (int i = 0; i < 3; ++i) { //fall frame Surface *surf = xcom_1->getFrame(264 + i); ShaderMove head = ShaderMove(surf); GraphSubset dim = head.getBaseDomain(); dim.beg_y = 0; dim.end_y = 24; dim.beg_x = 11; dim.end_x = 20; head.setDomain(dim); surf->lock(); ShaderDraw(head, ShaderScalar(HairBleach::Face + 6)); surf->unlock(); } } } }