# HG changeset patch # User nemo # Date 1308326307 14400 # Node ID bc80445549e0d763e3ce817b57eb5634fe5e3503 # Parent f2e31a7f953a8956b0bdc36fadfdf31c2f664c89# Parent 69ed8cb551ef7ec723a4aeed07d80b6b43170291 merge of tsleon's updated russian. I assume unc0rr will vet the phrasing diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/SDLs.cpp --- a/QTfrontend/SDLs.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/SDLs.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -164,9 +164,12 @@ void SDLInteraction::StartMusic() { SDLMusicInit(); + QFile tmpfile; + tmpfile.setFileName(cfgdir->absolutePath() + "/Data/Music/main_theme.ogg"); + if (!tmpfile.exists()) tmpfile.setFileName(datadir->absolutePath() + "/Music/main_theme.ogg"); if (music == NULL) { - music = Mix_LoadMUS((datadir->absolutePath() + "/Music/main_theme.ogg").toLocal8Bit().constData()); + music = Mix_LoadMUS(QFileInfo(tmpfile).absoluteFilePath().toLocal8Bit().constData()); } Mix_VolumeMusic(MIX_MAX_VOLUME - 28); diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/chatwidget.cpp --- a/QTfrontend/chatwidget.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/chatwidget.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -122,15 +122,14 @@ this->sdli = sdli; this->notify = notify; if(notify && gameSettings->value("frontend/sound", true).toBool()) { - QDir tmpdir; - - tmpdir.cd(datadir->absolutePath()); - tmpdir.cd("Sounds/voices"); - sdli->SDLMusicInit(); - sound[0] = Mix_LoadWAV(QString(tmpdir.absolutePath() + "/Classic/Hello.ogg").toLocal8Bit().constData()); - sound[1] = Mix_LoadWAV(QString(tmpdir.absolutePath() + "/Default/Hello.ogg").toLocal8Bit().constData()); - sound[2] = Mix_LoadWAV(QString(tmpdir.absolutePath() + "/Mobster/Hello.ogg").toLocal8Bit().constData()); - sound[3] = Mix_LoadWAV(QString(tmpdir.absolutePath() + "/Russian/Hello.ogg").toLocal8Bit().constData()); + QFile tmpfile; + sdli->SDLMusicInit(); + for(int i=0;i<4;i++) { + tmpfile.setFileName(cfgdir->absolutePath() + "/Data/Sounds/voices/Classic/Hello.ogg"); + if (tmpfile.exists()) sound[i] = Mix_LoadWAV(QFileInfo(tmpfile).absoluteFilePath().toLocal8Bit().constData()); + else sound[i] = Mix_LoadWAV(QString(datadir->absolutePath() + + "/Sounds/voices/Classic/Hello.ogg").toLocal8Bit().constData()); + } } mainLayout.setSpacing(1); diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/gamecfgwidget.cpp --- a/QTfrontend/gamecfgwidget.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/gamecfgwidget.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -61,7 +61,9 @@ QString script = (*scriptList)[i].remove(".lua", Qt::CaseInsensitive); QList scriptInfo; scriptInfo.push_back(script); - QFile scriptCfgFile(QString("%1/Scripts/Multiplayer/%2.cfg").arg(datadir->absolutePath()).arg(script)); + QFile scriptCfgFile; + scriptCfgFile.setFileName(QString("%1/Data/Scripts/Multiplayer/%2.cfg").arg(cfgdir->absolutePath()).arg(script)); + if (!scriptCfgFile.exists()) scriptCfgFile.setFileName(QString("%1/Scripts/Multiplayer/%2.cfg").arg(datadir->absolutePath()).arg(script)); if (scriptCfgFile.exists() && scriptCfgFile.open(QFile::ReadOnly)) { QString scheme; QString weapons; diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/gameuiconfig.cpp --- a/QTfrontend/gameuiconfig.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/gameuiconfig.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -44,7 +44,14 @@ Form->ui.pageOptions->WeaponTooltip->setChecked(value("misc/weaponTooltips", true).toBool()); int t = Form->ui.pageOptions->CBResolution->findText(value("video/resolution").toString()); - Form->ui.pageOptions->CBResolution->setCurrentIndex((t < 0) ? 0 : t); + if (t < 0) { + if (Form->ui.pageOptions->CBResolution->count() > 1) + Form->ui.pageOptions->CBResolution->setCurrentIndex(1); + else + Form->ui.pageOptions->CBResolution->setCurrentIndex(0); + } + else Form->ui.pageOptions->CBResolution->setCurrentIndex(t); + Form->ui.pageOptions->CBResolution->setCurrentIndex((t < 0) ? 1 : t); Form->ui.pageOptions->CBFullscreen->setChecked(value("video/fullscreen", false).toBool()); bool ffscr=value("frontend/fullscreen", false).toBool(); Form->ui.pageOptions->CBFrontendFullscreen->setChecked(ffscr); diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/hats.cpp --- a/QTfrontend/hats.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/hats.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -26,19 +26,46 @@ HatsModel::HatsModel(QObject* parent) : QAbstractListModel(parent) { - QPixmap hhpix = QPixmap(datadir->absolutePath() + "/Graphics/Hedgehog/Idle.png").copy(0, 0, 32, 32); + QFile hhfile; + hhfile.setFileName(cfgdir->absolutePath() + "/Data/Graphics/Hedgehog/Idle.png"); + if (!hhfile.exists()) hhfile.setFileName(datadir->absolutePath() + "/Graphics/Hedgehog/Idle.png"); + QPixmap hhpix = QPixmap(QFileInfo(hhfile).absoluteFilePath()).copy(0, 0, 32, 32); QDir tmpdir; - tmpdir.cd(datadir->absolutePath()); + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data"); tmpdir.cd("Graphics"); tmpdir.cd("Hats"); tmpdir.setFilter(QDir::Files); + QStringList userhatsList = tmpdir.entryList(QStringList("*.png")); + for (QStringList::Iterator it = userhatsList.begin(); it != userhatsList.end(); ++it ) + { + QString str = QString(*it).replace(QRegExp("^(.*)\\.png"), "\\1"); + QPixmap pix(cfgdir->absolutePath() + "/Data/Graphics/Hats/" + str + ".png"); + + QPixmap tmppix(32, 37); + tmppix.fill(QColor(Qt::transparent)); + + QPainter painter(&tmppix); + painter.drawPixmap(QPoint(0, 5), hhpix); + painter.drawPixmap(QPoint(0, 0), pix.copy(0, 0, 32, 32)); + if(pix.width() > 32) + painter.drawPixmap(QPoint(0, 0), pix.copy(32, 0, 32, 32)); + painter.end(); + + hats.append(qMakePair(str, QIcon(tmppix))); + } + + tmpdir.cd(datadir->absolutePath()); + tmpdir.cd("Graphics"); + tmpdir.cd("Hats"); QStringList hatsList = tmpdir.entryList(QStringList("*.png")); for (QStringList::Iterator it = hatsList.begin(); it != hatsList.end(); ++it ) { + if (userhatsList.contains(*it,Qt::CaseInsensitive)) continue; QString str = (*it).replace(QRegExp("^(.*)\\.png"), "\\1"); QPixmap pix(datadir->absolutePath() + "/Graphics/Hats/" + str + ".png"); diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/hwform.cpp --- a/QTfrontend/hwform.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/hwform.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -1201,13 +1201,23 @@ ui.pageCampaign->CBSelect->clear(); QDir tmpdir; + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Missions/Campaign"); + tmpdir.setFilter(QDir::Files); + QStringList userentries = tmpdir.entryList(QStringList("*#*.lua")); + //entries.sort(); + for(int i = 0; (i < userentries.count()) && (i <= team.CampaignProgress); i++) + ui.pageCampaign->CBSelect->addItem(QString(userentries[i]).replace(QRegExp("^(\\d+)#(.+)\\.lua"), QComboBox::tr("Mission") + " \\1: \\2").replace("_", " "), QString(userentries[i]).replace(QRegExp("^(.*)\\.lua"), "\\1")); + tmpdir.cd(datadir->absolutePath()); tmpdir.cd("Missions/Campaign"); tmpdir.setFilter(QDir::Files); QStringList entries = tmpdir.entryList(QStringList("*#*.lua")); //entries.sort(); - for(int i = 0; (i < entries.count()) && (i <= team.CampaignProgress); i++) + for(int i = 0; (i < entries.count()) && (i <= team.CampaignProgress); i++) { + if (userentries.contains(entries[i])) continue; ui.pageCampaign->CBSelect->addItem(QString(entries[i]).replace(QRegExp("^(\\d+)#(.+)\\.lua"), QComboBox::tr("Mission") + " \\1: \\2").replace("_", " "), QString(entries[i]).replace(QRegExp("^(.*)\\.lua"), "\\1")); + } } // used for --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality] @@ -1240,8 +1250,8 @@ registry_hkcr.setValue("Hedgewars.Save/Default", tr("Hedgewars Save File", "File Types")); registry_hkcr.setValue("Hedgewars.Demo/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwdfile.ico\",0"); registry_hkcr.setValue("Hedgewars.Save/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwsfile.ico\",0"); - registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments); - registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments); + registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + cfgdir->absolutePath().replace("/","\\") + "\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments); + registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + cfgdir->absolutePath().replace("/","\\") + "\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments); #elif defined __APPLE__ success = false; // TODO; also enable button in pages.cpp and signal in hwform.cpp @@ -1259,8 +1269,8 @@ if (success) success = system(("update-mime-database "+QDir::home().absolutePath()+"/.local/share/mime").toLocal8Bit().constData())==0; if (success) success = system("xdg-mime default hwengine.desktop application/x-hedgewars-demo")==0; if (success) success = system("xdg-mime default hwengine.desktop application/x-hedgewars-save")==0; - // hack to add user's settings to hwengine. might be better at this point to read in the file, append it, and write it out to its new home - if (success) success = system(("sed -i 's/^\\(Exec=.*\\)/\\1 --set-everything "+arguments+"/' "+QDir::home().absolutePath()+"/.local/share/applications/hwengine.desktop").toLocal8Bit().constData())==0; + // hack to add user's settings to hwengine. might be better at this point to read in the file, append it, and write it out to its new home. This assumes no spaces in the data dir path + if (success) success = system(("sed -i 's/^\\(Exec=.*\\) \\([^ ]* %f\\)/\\1 "+cfgdir->absolutePath().replace(" ","\\\\ ").replace("/","\\/")+" \\2 --set-everything "+arguments+"/' "+QDir::home().absolutePath()+"/.local/share/applications/hwengine.desktop").toLocal8Bit().constData())==0; #endif if (success) QMessageBox::information(0, "", QMessageBox::tr("All file associations have been set.")); else QMessageBox::information(0, "", QMessageBox::tr("File association failed.")); diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/main.cpp --- a/QTfrontend/main.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/main.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -384,13 +384,19 @@ } Themes = new QStringList(); + QFile userthemesfile(cfgdir->absolutePath() + "/Data/Themes/themes.cfg"); + if (userthemesfile.open(QIODevice::ReadOnly)) { + QTextStream stream(&userthemesfile); + while (!stream.atEnd()) Themes->append(stream.readLine()); + userthemesfile.close(); + } QFile themesfile(datadir->absolutePath() + "/Themes/themes.cfg"); + QString str; if (themesfile.open(QIODevice::ReadOnly)) { QTextStream stream(&themesfile); - QString str; - while (!stream.atEnd()) - { - Themes->append(stream.readLine()); + while (!stream.atEnd()) { + str = stream.readLine(); + if (!Themes->contains(str)) Themes->append(str); } themesfile.close(); } else { @@ -398,16 +404,29 @@ } QDir tmpdir; - tmpdir.cd(datadir->absolutePath()); - tmpdir.cd("Maps"); + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Maps"); tmpdir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); mapList = new QStringList(tmpdir.entryList(QStringList("*"))); tmpdir.cd(datadir->absolutePath()); - tmpdir.cd("Scripts/Multiplayer"); + tmpdir.cd("Maps"); + tmpdir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); + QStringList tmplist = QStringList(tmpdir.entryList(QStringList("*"))); + for (QStringList::Iterator it = tmplist.begin(); it != tmplist.end(); ++it) + if (!mapList->contains(*it,Qt::CaseInsensitive)) mapList->append(*it); + + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Scripts/Multiplayer"); tmpdir.setFilter(QDir::Files | QDir::NoDotAndDotDot); scriptList = new QStringList(tmpdir.entryList(QStringList("*.lua"))); + tmpdir.cd(datadir->absolutePath()); + tmpdir.cd("Scripts/Multiplayer"); + tmpdir.setFilter(QDir::Files | QDir::NoDotAndDotDot); + tmplist = QStringList(tmpdir.entryList(QStringList("*.lua"))); + for (QStringList::Iterator it = tmplist.begin(); it != tmplist.end(); ++it) + if (!scriptList->contains(*it,Qt::CaseInsensitive)) scriptList->append(*it); QTranslator Translator; { @@ -415,7 +434,10 @@ QString cc = settings.value("misc/locale", "").toString(); if(!cc.compare("")) cc = QLocale::system().name(); - Translator.load(datadir->absolutePath() + "/Locale/hedgewars_" + cc); + QFile tmpfile; + tmpfile.setFileName(cfgdir->absolutePath() + "Data/Locale/hedgewars_" + cc); + if (!tmpfile.exists()) tmpfile.setFileName(datadir->absolutePath() + "Locale/hedgewars_" + cc); + Translator.load(QFileInfo(tmpfile).absoluteFilePath()); app.installTranslator(&Translator); } diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/mapContainer.cpp --- a/QTfrontend/mapContainer.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/mapContainer.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -85,16 +85,29 @@ int missionindex = chooseMap->count(); numMissions = 0; + QFile mapLuaFile; + QFile mapCfgFile; for (int i = 0; i < mapList->size(); ++i) { QString map = (*mapList)[i]; - QFile mapCfgFile( - QString("%1/Maps/%2/map.cfg") - .arg(datadir->absolutePath()) + mapCfgFile.setFileName( + QString("%1/Data/Maps/%2/map.cfg") + .arg(cfgdir->absolutePath()) .arg(map)); - QFile mapLuaFile( - QString("%1/Maps/%2/map.lua") - .arg(datadir->absolutePath()) - .arg(map)); + if (mapCfgFile.exists()) { + mapLuaFile.setFileName( + QString("%1/Data/Maps/%2/map.lua") + .arg(cfgdir->absolutePath()) + .arg(map)); + } else { + mapCfgFile.setFileName( + QString("%1/Maps/%2/map.cfg") + .arg(datadir->absolutePath()) + .arg(map)); + mapLuaFile.setFileName( + QString("%1/Maps/%2/map.lua") + .arg(datadir->absolutePath()) + .arg(map)); + } if (mapCfgFile.open(QFile::ReadOnly)) { QString theme; @@ -190,10 +203,13 @@ lwThemes = new QListWidget(mapWidget); lwThemes->setMinimumHeight(30); lwThemes->setFixedWidth(140); + QFile tmpfile; for (int i = 0; i < Themes->size(); ++i) { QListWidgetItem * lwi = new QListWidgetItem(); lwi->setText(Themes->at(i)); - lwi->setIcon(QIcon(QString("%1/Themes/%2/icon.png").arg(datadir->absolutePath()).arg(Themes->at(i)))); + tmpfile.setFileName(QString("%1/Data/Themes/%2/icon.png").arg(cfgdir->absolutePath()).arg(Themes->at(i))); + if (tmpfile.exists()) lwi->setIcon(QIcon(QFileInfo(tmpfile).absoluteFilePath())); + else lwi->setIcon(QIcon(QString("%1/Themes/%2/icon.png").arg(datadir->absolutePath()).arg(Themes->at(i)))); //lwi->setTextAlignment(Qt::AlignHCenter); lwThemes->addItem(lwi); } @@ -373,7 +389,10 @@ chooseMap->setItemData(1, mapInfo); mapInfo[0] = QString("+drawn+"); chooseMap->setItemData(2, mapInfo); - gbThemes->setIcon(QIcon(QString("%1/Themes/%2/icon@2x.png").arg(datadir->absolutePath()).arg(theme))); + QFile tmpfile; + tmpfile.setFileName(QString("%1/Data/Themes/%2/icon@2x.png").arg(cfgdir->absolutePath()).arg(theme)); + if (tmpfile.exists()) gbThemes->setIcon(QIcon(QFileInfo(tmpfile).absoluteFilePath())); + else gbThemes->setIcon(QIcon(QString("%1/Themes/%2/icon@2x.png").arg(datadir->absolutePath()).arg(theme))); emit themeChanged(theme); } @@ -632,7 +651,10 @@ default: QPixmap mapImage; qDebug() << "Map data" << curIndex << chooseMap->currentText() << chooseMap->itemData(curIndex); - if(!mapImage.load(datadir->absolutePath() + "/Maps/" + chooseMap->itemData(curIndex).toList()[0].toString() + "/preview.png")) { + QFile tmpfile; + tmpfile.setFileName(cfgdir->absolutePath() + "/Data//Maps/" + chooseMap->itemData(curIndex).toList()[0].toString() + "/preview.png"); + if (!tmpfile.exists()) tmpfile.setFileName(datadir->absolutePath() + "/Maps/" + chooseMap->itemData(curIndex).toList()[0].toString() + "/preview.png"); + if(!mapImage.load(QFileInfo(tmpfile).absoluteFilePath())) { imageButt->setIcon(QIcon()); return; } diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/namegen.cpp --- a/QTfrontend/namegen.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/namegen.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -88,21 +88,23 @@ void HWNamegen::DictLoad(const QString filename, QStringList &list) { - list.clear(); + list.clear(); - QFile file(QString("%1/Names/%2.txt").arg(datadir->absolutePath()).arg(filename)); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) - { + QFile file; + file.setFileName(QString("%1/Data/Names/%2.txt").arg(cfgdir->absolutePath()).arg(filename)); + if (!file.exists()) file.setFileName(QString("%1/Names/%2.txt").arg(datadir->absolutePath()).arg(filename)); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + { - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine(); - if(line != QString("")) - {list.append(line);} - } - } + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine(); + if(line != QString("")) + {list.append(line);} + } + } - if (list.size()==0) + if (list.size()==0) list.append(filename); } @@ -110,21 +112,23 @@ void HWNamegen::HatCfgLoad(const QString hatname, QStringList &list) { - list.clear(); + list.clear(); - QFile file(QString("%1/Names/%2.cfg").arg(datadir->absolutePath()).arg(hatname)); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) - { + QFile file; + file.setFileName(QString("%1/Data/Names/%2.cfg").arg(cfgdir->absolutePath()).arg(hatname)); + if (!file.exists()) file.setFileName(QString("%1/Names/%2.cfg").arg(datadir->absolutePath()).arg(hatname)); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + { - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine(); - if(line != QString("")) - {list.append(line);} - } - } + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine(); + if(line != QString("")) + {list.append(line);} + } + } - if (list.size()==0) + if (list.size()==0) list.append(QString("generic")); } @@ -132,37 +136,38 @@ void HWNamegen::TypesLoad() { + QFile file; + file.setFileName(QString("%1/Data/Names/types.ini").arg(cfgdir->absolutePath())); + if (!file.exists()) file.setFileName(QString("%1/Names/types.ini").arg(datadir->absolutePath())); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + {TypesAvliable = FALSE; return;} - QFile file(QString("%1/Names/types.ini").arg(datadir->absolutePath())); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - {TypesAvliable = FALSE; return;} - - int counter = 0; //counter starts with 0 (teamnames mode) - TypesTeamnames.append(QStringList()); - TypesHatnames.append(QStringList()); + int counter = 0; //counter starts with 0 (teamnames mode) + TypesTeamnames.append(QStringList()); + TypesHatnames.append(QStringList()); - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine(); - if (line == QString("#####")){ - counter++; //toggle mode (teamnames || hats) - if ((counter%2) == 0){ - TypesTeamnames.append(QStringList()); - TypesHatnames.append(QStringList()); - } - } else if ((line == QString("*****")) || (line == QString("*END*"))){ - TypesAvliable = TRUE; return; // bye bye - } else { - if ((counter%2) == 0){ // even => teamnames mode - TypesTeamnames[(counter/2)].append(line); - } else { // odd => hats mode - TypesHatnames[((counter-1)/2)].append(line); - } - } -// Types.append(line); - } - TypesAvliable = TRUE; - return; + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine(); + if (line == QString("#####")){ + counter++; //toggle mode (teamnames || hats) + if ((counter%2) == 0){ + TypesTeamnames.append(QStringList()); + TypesHatnames.append(QStringList()); + } + } else if ((line == QString("*****")) || (line == QString("*END*"))){ + TypesAvliable = TRUE; return; // bye bye + } else { + if ((counter%2) == 0){ // even => teamnames mode + TypesTeamnames[(counter/2)].append(line); + } else { // odd => hats mode + TypesHatnames[((counter-1)/2)].append(line); + } + } +// Types.append(line); + } + TypesAvliable = TRUE; + return; } @@ -173,10 +178,17 @@ //list all available Graves QDir tmpdir; + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Graphics/Graves"); + tmpdir.setFilter(QDir::Files); + Graves.append(tmpdir.entryList(QStringList("*.png")).replaceInStrings(QRegExp("^(.*)\\.png"), "\\1")); + tmpdir.cd(datadir->absolutePath()); tmpdir.cd("Graphics/Graves"); tmpdir.setFilter(QDir::Files); - Graves.append(tmpdir.entryList(QStringList("*.png")).replaceInStrings(QRegExp("^(.*)\\.png"), "\\1")); + QStringList tmpList = tmpdir.entryList(QStringList("*.png")).replaceInStrings(QRegExp("^(.*)\\.png"), "\\1"); + for (QStringList::Iterator it = tmpList.begin(); it != tmpList.end(); ++it) + if (!Graves.contains(*it,Qt::CaseInsensitive)) Graves.append(*it); if(Graves.size()==0) { diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/pageeditteam.cpp --- a/QTfrontend/pageeditteam.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/pageeditteam.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -145,10 +145,19 @@ CBVoicepack = new QComboBox(GBoxTeam); { QDir tmpdir; + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Sounds/voices"); + QStringList list = tmpdir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name); + CBVoicepack->addItems(list); + tmpdir.cd(datadir->absolutePath()); tmpdir.cd("Sounds/voices"); - QStringList list = tmpdir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name); - CBVoicepack->addItems(list); + QStringList tmplist = tmpdir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name); + QStringList tmplist2; + for (QStringList::Iterator it = tmplist.begin(); it != tmplist.end(); ++it) + if (!list.contains(*it,Qt::CaseInsensitive)) tmplist2.append(*it); + + CBVoicepack->addItems(tmplist2); } hbox->addWidget(CBVoicepack, 100); BtnTestSound = addButton(":/res/PlaySound.png", hbox, 1, true); @@ -173,45 +182,103 @@ vbox2->addWidget(GBoxFort); QDir tmpdir; + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Forts"); + tmpdir.setFilter(QDir::Files); + + QStringList userforts = tmpdir.entryList(QStringList("*L.png")).replaceInStrings(QRegExp("^(.*)L\\.png"), "\\1"); + CBFort->addItems(userforts); + + tmpdir.cd("../Graphics/Graves"); + QStringList userlist = tmpdir.entryList(QStringList("*.png")); + for (QStringList::Iterator it = userlist.begin(); it != userlist.end(); ++it ) + { + QPixmap pix(cfgdir->absolutePath() + "/Data/Graphics/Graves/" + *it); + QIcon icon(pix.copy(0, 0, 32, 32)); + CBGrave->addItem(icon, QString(*it).replace(QRegExp("^(.*)\\.png"), "\\1")); + } + tmpdir.cd(datadir->absolutePath()); tmpdir.cd("Forts"); tmpdir.setFilter(QDir::Files); + QStringList tmplist = tmpdir.entryList(QStringList("*L.png")).replaceInStrings(QRegExp("^(.*)L\\.png"), "\\1"); + QStringList dataforts; + for (QStringList::Iterator it = tmplist.begin(); it != tmplist.end(); ++it) + if (!userforts.contains(*it,Qt::CaseInsensitive)) dataforts.append(*it); + + CBVoicepack->addItems(dataforts); connect(CBFort, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(CBFort_activated(const QString &))); - CBFort->addItems(tmpdir.entryList(QStringList("*L.png")).replaceInStrings(QRegExp("^(.*)L\\.png"), "\\1")); tmpdir.cd("../Graphics/Graves"); - QStringList list = tmpdir.entryList(QStringList("*.png")); - for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + QStringList datalist = tmpdir.entryList(QStringList("*.png")); + for (QStringList::Iterator it = datalist.begin(); it != datalist.end(); ++it ) { + if (userlist.contains(*it,Qt::CaseInsensitive)) continue; QPixmap pix(datadir->absolutePath() + "/Graphics/Graves/" + *it); QIcon icon(pix.copy(0, 0, 32, 32)); CBGrave->addItem(icon, (*it).replace(QRegExp("^(.*)\\.png"), "\\1")); } - tmpdir.cd(datadir->absolutePath()); - tmpdir.cd("Graphics/Flags"); - list = tmpdir.entryList(QStringList("*.png")); - // add the default flag CBFlag->addItem(QIcon(QPixmap(datadir->absolutePath() + "/Graphics/Flags/hedgewars.png").copy(0, 0, 22, 15)), "Hedgewars", "hedgewars"); + CBFlag->insertSeparator(CBFlag->count()); + + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Graphics/Flags"); + userlist = tmpdir.entryList(QStringList("*.png")); + + // add all country flags + for (QStringList::Iterator it = userlist.begin(); it != userlist.end(); ++it ) + { + QPixmap pix(cfgdir->absolutePath() + "/Data/Graphics/Flags/" + *it); + QIcon icon(pix.copy(0, 0, 22, 15)); + if(it->compare("cpu.png") && it->compare("hedgewars.png") && (it->indexOf("cm_") == -1)) // skip cpu and hedgewars flags as well as all community flags + { + QString flag = QString(*it).replace(QRegExp("^(.*)\\.png"), "\\1"); + CBFlag->addItem(icon, QString(flag).replace("_", " "), flag); + } + } CBFlag->insertSeparator(CBFlag->count()); + + // add all community flags + for (QStringList::Iterator it = userlist.begin(); it != userlist.end(); ++it ) + { + QPixmap pix(cfgdir->absolutePath() + "/Data/Graphics/Flags/" + *it); + QIcon icon(pix.copy(0, 0, 22, 15)); + if(it->indexOf("cm_") > -1) // skip non community flags this time + { + QString flag = QString(*it).replace(QRegExp("^(.*)\\.png"), "\\1"); + CBFlag->addItem(icon, QString(flag).replace("cm_", QComboBox::tr("Community") + ": "), flag); + } + } + + CBFlag->insertSeparator(CBFlag->count()); + + tmpdir.cd(datadir->absolutePath()); + tmpdir.cd("Graphics/Flags"); + datalist = tmpdir.entryList(QStringList("*.png")); + // add all country flags - for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + for (QStringList::Iterator it = datalist.begin(); it != datalist.end(); ++it ) { + if (userlist.contains(*it,Qt::CaseInsensitive)) continue; QPixmap pix(datadir->absolutePath() + "/Graphics/Flags/" + *it); QIcon icon(pix.copy(0, 0, 22, 15)); if(it->compare("cpu.png") && it->compare("hedgewars.png") && (it->indexOf("cm_") == -1)) // skip cpu and hedgewars flags as well as all community flags { - QString flag = (*it).replace(QRegExp("^(.*)\\.png"), "\\1"); + QString flag = QString(*it).replace(QRegExp("^(.*)\\.png"), "\\1"); CBFlag->addItem(icon, QString(flag).replace("_", " "), flag); } } + CBFlag->insertSeparator(CBFlag->count()); + // add all community flags - for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + for (QStringList::Iterator it = datalist.begin(); it != datalist.end(); ++it ) { + if (userlist.contains(*it,Qt::CaseInsensitive)) continue; QPixmap pix(datadir->absolutePath() + "/Graphics/Flags/" + *it); QIcon icon(pix.copy(0, 0, 22, 15)); if(it->indexOf("cm_") > -1) // skip non community flags this time @@ -272,7 +339,10 @@ void PageEditTeam::CBFort_activated(const QString & fortname) { - QPixmap pix(datadir->absolutePath() + "/Forts/" + fortname + "L.png"); + QFile tmp; + tmp.setFileName(cfgdir->absolutePath() + "/Data/Forts/" + fortname + "L.png"); + if (!tmp.exists()) tmp.setFileName(datadir->absolutePath() + "/Forts/" + fortname + "L.png"); + QPixmap pix(QFileInfo(tmp).absoluteFilePath()); FortPreview->setPixmap(pix); } @@ -282,9 +352,16 @@ QDir tmpdir; mySdli->SDLMusicInit(); - tmpdir.cd(datadir->absolutePath()); - tmpdir.cd("Sounds/voices"); + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Sounds/voices"); tmpdir.cd(CBVoicepack->currentText()); + + if (!tmpdir.exists()) { + tmpdir.cd(datadir->absolutePath()); + tmpdir.cd("Sounds/voices"); + tmpdir.cd(CBVoicepack->currentText()); + } + QStringList list = tmpdir.entryList(QStringList() << "Illgetyou.ogg" << "Incoming.ogg" << "Stupid.ogg" << "Coward.ogg" << "Firstblood.ogg", QDir::Files); if (list.size()) { sound = Mix_LoadWAV(QString(tmpdir.absolutePath() + "/" + list[rand() % list.size()]).toLocal8Bit().constData()); diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/pageoptions.cpp --- a/QTfrontend/pageoptions.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/pageoptions.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -207,8 +207,8 @@ CBLanguage = new QComboBox(groupMisc); QDir tmpdir; - tmpdir.cd(datadir->absolutePath()); - tmpdir.cd("Locale"); + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Locale"); tmpdir.setFilter(QDir::Files); QStringList locs = tmpdir.entryList(QStringList("hedgewars_*.qm")); CBLanguage->addItem(QComboBox::tr("(System default)"), QString("")); @@ -218,6 +218,17 @@ CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name()); } + tmpdir.cd(datadir->absolutePath()); + tmpdir.cd("Locale"); + tmpdir.setFilter(QDir::Files); + QStringList tmplist = tmpdir.entryList(QStringList("hedgewars_*.qm")); + for(int i = 0; i < tmplist.count(); i++) + { + if (locs.contains(tmplist[i])) continue; + QLocale loc(tmplist[i].replace(QRegExp("hedgewars_(.*)\\.qm"), "\\1")); + CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name()); + } + MiscLayout->addWidget(CBLanguage, 2, 1); CBAltDamage = new QCheckBox(groupMisc); diff -r 69ed8cb551ef -r bc80445549e0 QTfrontend/pagetraining.cpp --- a/QTfrontend/pagetraining.cpp Fri Jun 10 17:28:53 2011 +0000 +++ b/QTfrontend/pagetraining.cpp Fri Jun 17 11:58:27 2011 -0400 @@ -35,10 +35,21 @@ CBSelect = new QComboBox(this); QDir tmpdir; + tmpdir.cd(cfgdir->absolutePath()); + tmpdir.cd("Data/Missions/Training"); + tmpdir.setFilter(QDir::Files); + QStringList userlist = tmpdir.entryList(QStringList("*.lua")).replaceInStrings(QRegExp("^(.*)\\.lua"), "\\1"); + CBSelect->addItems(userlist); + tmpdir.cd(datadir->absolutePath()); tmpdir.cd("Missions/Training"); tmpdir.setFilter(QDir::Files); - CBSelect->addItems(tmpdir.entryList(QStringList("*.lua")).replaceInStrings(QRegExp("^(.*)\\.lua"), "\\1")); + QStringList tmplist = tmpdir.entryList(QStringList("*.lua")).replaceInStrings(QRegExp("^(.*)\\.lua"), "\\1"); + QStringList datalist; + for (QStringList::Iterator it = tmplist.begin(); it != tmplist.end(); ++it) + if (!userlist.contains(*it,Qt::CaseInsensitive)) datalist.append(*it); + CBSelect->addItems(datalist); + for(int i = 0; i < CBSelect->count(); i++) { CBSelect->setItemData(i, CBSelect->itemText(i)); diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/ArgParsers.inc --- a/hedgewars/ArgParsers.inc Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/ArgParsers.inc Fri Jun 17 11:58:27 2011 -0400 @@ -34,6 +34,7 @@ procedure internalStartGameWithParameters(); var tmp: LongInt; begin + UserPathPrefix:= ParamStr(1); val(ParamStr(2), cScreenWidth); val(ParamStr(3), cScreenHeight); val(ParamStr(4), cBits); @@ -146,9 +147,10 @@ var paramIndex: LongInt; wrongParameter: boolean; begin - PathPrefix:= ParamStr(1); - recordFileName:= ParamStr(2); - paramIndex:= 3; + UserPathPrefix:= ParamStr(1); + PathPrefix:= ParamStr(2); + recordFileName:= ParamStr(3); + paramIndex:= 4; wrongParameter:= false; while (paramIndex <= ParamCount) and not wrongParameter do begin diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/GSHandlers.inc Fri Jun 17 11:58:27 2011 -0400 @@ -1601,7 +1601,6 @@ else if (Gear^.State and gsttmpFlag) = 0 then Gear^.State := Gear^.State or gsttmpFlag; - end; procedure doStepRopeAttach(Gear: PGear); @@ -1709,7 +1708,8 @@ Message := Message and not gmAttack end; DeleteGear(Gear) - end + end; + CheckGearDrowning(HHGear) end; procedure doStepRope(Gear: PGear); diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/VGSHandlers.inc --- a/hedgewars/VGSHandlers.inc Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/VGSHandlers.inc Fri Jun 17 11:58:27 2011 -0400 @@ -46,7 +46,7 @@ inc(Frame); if Frame = vobSDFramesCount then Frame:= 0 end; - X:= X + (cWindSpeedf * 200 + dX + tdX) * Steps; + X:= X + (cWindSpeedf * 600 + dX + tdX) * Steps; if SuddenDeathDmg then Y:= Y + (dY + tdY + cGravityf * vobSDFallSpeed) * Steps else @@ -649,7 +649,7 @@ Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; -if round(Gear^.Y) > cWaterLine then +if (round(Gear^.Y) > cWaterLine) and ((cReducedQuality and rqPlainSplash) = 0) then begin AddVisualGear(round(Gear^.X), round(Gear^.Y), vgtDroplet); DeleteVisualGear(Gear); diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/hwengine.pas Fri Jun 17 11:58:27 2011 -0400 @@ -214,6 +214,7 @@ cFullScreen:= false; cTimerInterval:= 8; PathPrefix:= 'Data'; + UserPathPrefix:= '.'; cShowFPS:= {$IFDEF DEBUGFILE}true{$ELSE}false{$ENDIF}; val(gameArgs[0], ipcPort); val(gameArgs[1], cScreenWidth); @@ -234,10 +235,16 @@ WriteLnToConsole('Hedgewars ' + cVersionString + ' engine (network protocol: ' + inttostr(cNetProtoVersion) + ')'); AddFileLog('Prefix: "' + PathPrefix +'"'); + AddFileLog('UserPrefix: "' + UserPathPrefix +'"'); for i:= 0 to ParamCount do AddFileLog(inttostr(i) + ': ' + ParamStr(i)); for p:= Succ(Low(TPathType)) to High(TPathType) do + if (p <> ptMapCurrent) and (p <> ptData) then UserPathz[p]:= UserPathPrefix + '/Data/' + Pathz[p]; + + UserPathz[ptData]:= UserPathPrefix + '/Data'; + + for p:= Succ(Low(TPathType)) to High(TPathType) do if p <> ptMapCurrent then Pathz[p]:= PathPrefix + '/' + Pathz[p]; WriteToConsole('Init SDL... '); @@ -263,6 +270,7 @@ InitKbdKeyTable(); AddProgress(); + LoadLocale(UserPathz[ptLocale] + '/en.txt'); // Do an initial load with english LoadLocale(Pathz[ptLocale] + '/en.txt'); // Do an initial load with english if (Length(cLocaleFName) > 6) then cLocale := Copy(cLocaleFName,1,5) else cLocale := Copy(cLocaleFName,1,2); @@ -270,8 +278,12 @@ begin // Try two letter locale first before trying specific locale overrides if (Length(cLocale) > 2) and (Copy(cLocale,1,2) <> 'en') then - LoadLocale(Pathz[ptLocale] + '/' + Copy(cLocale,1,2)+'.txt'); - LoadLocale(Pathz[ptLocale] + '/' + cLocaleFName); + begin + LoadLocale(UserPathz[ptLocale] + '/' + Copy(cLocale,1,2)+'.txt'); + LoadLocale(Pathz[ptLocale] + '/' + Copy(cLocale,1,2)+'.txt') + end; + LoadLocale(UserPathz[ptLocale] + '/' + cLocaleFName); + LoadLocale(Pathz[ptLocale] + '/' + cLocaleFName) end else cLocale := 'en'; @@ -430,7 +442,7 @@ begin WriteLn('Wrong argument format: correct configurations is'); WriteLn(); - WriteLn(' hwengine [options]'); + WriteLn(' hwengine [options]'); WriteLn(); WriteLn('where [options] must be specified either as:'); WriteLn(' --set-video [screen width] [screen height] [color dept]'); @@ -453,10 +465,10 @@ procedure GetParams; begin - if (ParamCount < 2) then + if (ParamCount < 3) then GameType:= gmtSyntax else - if (ParamCount = 3) then + if (ParamCount = 3) and ((ParamStr(3) = '--stats-only') or (ParamStr(3) = 'landpreview')) then internalSetGameTypeLandPreviewFromParameters() else if (ParamCount = cDefaultParamNum) then diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uCommandHandlers.pas Fri Jun 17 11:58:27 2011 -0400 @@ -447,6 +447,7 @@ begin if isDeveloperMode then begin +UserPathz[ptMapCurrent]:= UserPathz[ptMaps] + '/' + s; Pathz[ptMapCurrent]:= Pathz[ptMaps] + '/' + s; InitStepsFlags:= InitStepsFlags or cifMap end @@ -456,6 +457,7 @@ begin if isDeveloperMode then begin +UserPathz[ptCurrTheme]:= UserPathz[ptThemes] + '/' + s; Pathz[ptCurrTheme]:= Pathz[ptThemes] + '/' + s; Theme:= s; InitStepsFlags:= InitStepsFlags or cifTheme diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uLand.pas --- a/hedgewars/uLand.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uLand.pas Fri Jun 17 11:58:27 2011 -0400 @@ -283,7 +283,8 @@ r, rr: TSDL_Rect; x, yd, yu: LongInt; begin - tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/LandTex', ifCritical or ifIgnoreCaps); + tmpsurf:= LoadImage(UserPathz[ptCurrTheme] + '/LandTex', ifIgnoreCaps); + if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/LandTex', ifCritical or ifIgnoreCaps); r.y:= 0; while r.y < LAND_HEIGHT do begin @@ -298,9 +299,11 @@ SDL_FreeSurface(tmpsurf); // freed in freeModule() below - LandBackSurface:= LoadImage(Pathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent); + LandBackSurface:= LoadImage(UserPathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent); + if LandBackSurface = nil then LandBackSurface:= LoadImage(Pathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent); - tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Border', ifCritical or ifIgnoreCaps or ifTransparent); + tmpsurf:= LoadImage(UserPathz[ptCurrTheme] + '/Border', ifIgnoreCaps or ifTransparent); + if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Border', ifCritical or ifIgnoreCaps or ifTransparent); for x:= 0 to LAND_WIDTH - 1 do begin yd:= LAND_HEIGHT - 1; @@ -1104,21 +1107,18 @@ WriteLnToConsole('Generating forts land...'); -tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[0]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); +tmpsurf:= LoadImage(UserPathz[ptForts] + '/' + ClansArray[0]^.Teams[0]^.FortName + 'L', ifAlpha or ifTransparent or ifIgnoreCaps); +if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[0]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); BlitImageAndGenerateCollisionInfo(leftX+150, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); SDL_FreeSurface(tmpsurf); -tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[1]^.Teams[0]^.FortName + 'R', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); +tmpsurf:= LoadImage(UserPathz[ptForts] + '/' + ClansArray[1]^.Teams[0]^.FortName + 'R', ifAlpha or ifTransparent or ifIgnoreCaps); +if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[1]^.Teams[0]^.FortName + 'R', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); BlitImageAndGenerateCollisionInfo(rightX - 150 - tmpsurf^.w, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); SDL_FreeSurface(tmpsurf); end; -// Hi unC0Rr. -// This is a function that Tiy assures me would not be good for gameplay. -// It allows the setting of arbitrary portions of landscape as indestructible, or regular, or even blank. -// He said I could add it here only when I swore it would not impact gameplay. Which, as far as I can tell, is true. -// I would just like to play with it with my friends if you do not mind. -// Can allow for amusing maps. +// Loads Land[] from an image, allowing overriding standard collision procedure LoadMask(mapName: shortstring); var tmpsurf: PSDL_Surface; p: PLongwordArray; @@ -1167,16 +1167,19 @@ isMap:= true; WriteLnToConsole('Loading land from file...'); AddProgress; -tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', ifAlpha or ifTransparent or ifIgnoreCaps); +tmpsurf:= LoadImage(UserPathz[ptMapCurrent] + '/map', ifAlpha or ifTransparent or ifIgnoreCaps); +if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', ifAlpha or ifTransparent or ifIgnoreCaps); if tmpsurf = nil then begin mapName:= ExtractFileName(Pathz[ptMapCurrent]); - tmpsurf:= LoadImage(Pathz[ptMissionMaps] + '/' + mapName + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); + tmpsurf:= LoadImage(UserPathz[ptMissionMaps] + '/' + mapName + '/map', ifAlpha or ifTransparent or ifIgnoreCaps); + if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptMissionMaps] + '/' + mapName + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); end; TryDo((tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT), 'Map dimensions too big!', true); // unC0Rr - should this be passed from the GUI? I am not sure which layer does what -s:= Pathz[ptMapCurrent] + '/map.cfg'; +s:= UserPathz[ptMapCurrent] + '/map.cfg'; +if not FileExists(s) then s:= Pathz[ptMapCurrent] + '/map.cfg'; WriteLnToConsole('Fetching map HH limit'); {$I-} Assign(f, s); diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uLandObjects.pas --- a/hedgewars/uLandObjects.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uLandObjects.pas Fri Jun 17 11:58:27 2011 -0400 @@ -196,7 +196,9 @@ if x1 > 0 then begin bRes:= true; - tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Girder', ifTransparent or ifIgnoreCaps); + tmpsurf:= LoadImage(UserPathz[ptCurrTheme] + '/Girder', ifTransparent or ifIgnoreCaps); + if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Girder', ifTransparent or ifIgnoreCaps); + if tmpsurf = nil then tmpsurf:= LoadImage(UserPathz[ptGraphics] + '/Girder', ifTransparent or ifIgnoreCaps); if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptGraphics] + '/Girder', ifCritical or ifTransparent or ifIgnoreCaps); rr.x:= x1; @@ -383,7 +385,8 @@ AddProgress; -s:= Pathz[ptCurrTheme] + '/' + cThemeCFGFilename; +s:= UserPathz[ptCurrTheme] + '/' + cThemeCFGFilename; +if not FileExists(s) then s:= Pathz[ptCurrTheme] + '/' + cThemeCFGFilename; WriteLnToConsole('Reading objects info...'); Assign(f, s); {$I-} @@ -469,7 +472,8 @@ with ThemeObjects.objs[Pred(ThemeObjects.Count)] do begin i:= Pos(',', s); - Surf:= LoadImage(Pathz[ptCurrTheme] + '/' + Trim(Copy(s, 1, Pred(i))), ifCritical or ifTransparent or ifIgnoreCaps); + Surf:= LoadImage(UserPathz[ptCurrTheme] + '/' + Trim(Copy(s, 1, Pred(i))), ifTransparent or ifIgnoreCaps); + if Surf = nil then Surf:= LoadImage(Pathz[ptCurrTheme] + '/' + Trim(Copy(s, 1, Pred(i))), ifCritical or ifTransparent or ifIgnoreCaps); Width:= Surf^.w; Height:= Surf^.h; Delete(s, 1, i); @@ -525,7 +529,8 @@ with SprayObjects.objs[Pred(SprayObjects.Count)] do begin i:= Pos(',', s); - Surf:= LoadImage(Pathz[ptCurrTheme] + '/' + Trim(Copy(s, 1, Pred(i))), ifCritical or ifTransparent or ifIgnoreCaps); + Surf:= LoadImage(UserPathz[ptCurrTheme] + '/' + Trim(Copy(s, 1, Pred(i))), ifTransparent or ifIgnoreCaps); + if Surf = nil then Surf:= LoadImage(Pathz[ptCurrTheme] + '/' + Trim(Copy(s, 1, Pred(i))), ifCritical or ifTransparent or ifIgnoreCaps); Width:= Surf^.w; Height:= Surf^.h; Delete(s, 1, i); diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uMisc.pas --- a/hedgewars/uMisc.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uMisc.pas Fri Jun 17 11:58:27 2011 -0400 @@ -79,7 +79,7 @@ // update header information and file name -filename:= ParamStr(1) + '/Screenshots/' + filename + '.bmp'; +filename:= UserPathPrefix + '/Screenshots/' + filename + '.bmp'; head[$02]:= (size + 54) and $ff; head[$03]:= ((size + 54) shr 8) and $ff; diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uRender.pas --- a/hedgewars/uRender.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uRender.pas Fri Jun 17 11:58:27 2011 -0400 @@ -266,6 +266,7 @@ procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt); var row, col, numFramesFirstCol: LongInt; begin +if SpritesData[Sprite].imageHeight = 0 then exit; numFramesFirstCol:= SpritesData[Sprite].imageHeight div SpritesData[Sprite].Height; row:= Frame mod numFramesFirstCol; col:= Frame div numFramesFirstCol; diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uScript.pas --- a/hedgewars/uScript.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uScript.pas Fri Jun 17 11:58:27 2011 -0400 @@ -72,7 +72,8 @@ uRenderUtils, uTextures, uLandGraphics, - SDLh; + SDLh, + sysutils; var luaState : Plua_State; ScriptAmmoLoadout : shortstring; @@ -1220,6 +1221,18 @@ lc_getdatapath:= 1 end; +function lc_getuserdatapath(L : Plua_State) : LongInt; Cdecl; +begin + if lua_gettop(L) <> 0 then + begin + LuaError('Lua: Wrong number of parameters passed to GetUserDataPath!'); + lua_pushnil(L); + end + else + lua_pushstring(L, str2pchar(UserPathz[ptData])); + lc_getuserdatapath:= 1 +end; + function lc_maphasborder(L : Plua_State) : LongInt; Cdecl; begin if lua_gettop(L) <> 0 then @@ -1424,8 +1437,11 @@ procedure ScriptLoad(name : shortstring); var ret : LongInt; + s : shortstring; begin -ret:= luaL_loadfile(luaState, Str2PChar(Pathz[ptData] + '/' + name)); +s:= UserPathz[ptData] + '/' + name; +if not FileExists(s) then s:= Pathz[ptData] + '/' + name; +ret:= luaL_loadfile(luaState, Str2PChar(s)); if ret <> 0 then begin LuaError('Lua: Failed to load ' + name + '(error ' + IntToStr(ret) + ')'); @@ -1722,6 +1738,7 @@ lua_register(luaState, 'GetRandom', @lc_getrandom); lua_register(luaState, 'SetWind', @lc_setwind); lua_register(luaState, 'GetDataPath', @lc_getdatapath); +lua_register(luaState, 'GetUserDataPath', @lc_getuserdatapath); lua_register(luaState, 'MapHasBorder', @lc_maphasborder); lua_register(luaState, 'GetHogHat', @lc_gethoghat); lua_register(luaState, 'SetHogHat', @lc_sethoghat); diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uSound.pas --- a/hedgewars/uSound.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uSound.pas Fri Jun 17 11:58:27 2011 -0400 @@ -106,13 +106,23 @@ if cLocale <> 'en' then begin locName:= name+'_'+cLocale; - path:= Pathz[ptVoices] + '/' + locName; + path:= UserPathz[ptVoices] + '/' + locName; if DirectoryExists(path) then name:= locName - else if Length(cLocale) > 2 then + else begin - locName:= name+'_'+Copy(cLocale,1,2); path:= Pathz[ptVoices] + '/' + locName; if DirectoryExists(path) then name:= locName + else if Length(cLocale) > 2 then + begin + locName:= name+'_'+Copy(cLocale,1,2); + path:= UserPathz[ptVoices] + '/' + locName; + if DirectoryExists(path) then name:= locName + else + begin + path:= Pathz[ptVoices] + '/' + locName; + if DirectoryExists(path) then name:= locName + end + end end end; @@ -209,7 +219,8 @@ sndMolotov, sndMortar, sndRideOfTheValkyries, sndYoohoo]) and (Soundz[i].Path <> ptVoices) and (Soundz[i].FileName <> '') then begin - s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName; + s:= UserPathz[Soundz[i].Path] + '/' + Soundz[i].FileName; + if not FileExists(s) then s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName; WriteToConsole(msgLoading + s + ' '); defVoicepack^.chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); TryDo(defVoicepack^.chunks[i] <> nil, msgFailed, true); @@ -247,7 +258,8 @@ begin if (voicepack^.chunks[snd] = nil) and (Soundz[snd].Path = ptVoices) and (Soundz[snd].FileName <> '') then begin - s:= Pathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName; + s:= UserPathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName; + if not FileExists(s) then s:= Pathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName; WriteToConsole(msgLoading + s + ' '); voicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); if voicepack^.chunks[snd] = nil then @@ -261,7 +273,8 @@ begin if (defVoicepack^.chunks[snd] = nil) and (Soundz[snd].Path <> ptVoices) and (Soundz[snd].FileName <> '') then begin - s:= Pathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName; + s:= UserPathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName; + if not FileExists(s) then s:= Pathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName; WriteToConsole(msgLoading + s + ' '); defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); TryDo(defVoicepack^.chunks[snd] <> nil, msgFailed, true); @@ -300,7 +313,8 @@ begin if (voicepack^.chunks[snd] = nil) and (Soundz[snd].Path = ptVoices) and (Soundz[snd].FileName <> '') then begin - s:= Pathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName; + s:= UserPathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName; + if not FileExists(s) then s:= Pathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName; WriteToConsole(msgLoading + s + ' '); voicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); if voicepack^.chunks[snd] = nil then @@ -314,7 +328,8 @@ begin if (defVoicepack^.chunks[snd] = nil) and (Soundz[snd].Path <> ptVoices) and (Soundz[snd].FileName <> '') then begin - s:= Pathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName; + s:= UserPathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName; + if not FileExists(s) then s:= Pathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName; WriteToConsole(msgLoading + s + ' '); defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); TryDo(defVoicepack^.chunks[snd] <> nil, msgFailed, true); @@ -360,7 +375,8 @@ if (not isSoundEnabled) or (MusicFN = '') or (not isMusicEnabled) then exit; - s:= PathPrefix + '/Music/' + MusicFN; + s:= UserPathPrefix + '/Data/Music/' + MusicFN; + if not FileExists(s) then s:= PathPrefix + '/Music/' + MusicFN; WriteToConsole(msgLoading + s + ' '); Mus:= Mix_LoadMUS(Str2PChar(s)); diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uStore.pas --- a/hedgewars/uStore.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uStore.pas Fri Jun 17 11:58:27 2011 -0400 @@ -82,7 +82,8 @@ Color, i: Longword; s : shortstring; begin -s:= Pathz[ptGraphics] + '/' + cCHFileName; +s:= UserPathz[ptGraphics] + '/' + cCHFileName; +if not FileExists(s+'.png') then s:= Pathz[ptGraphics] + '/' + cCHFileName; tmpsurf:= LoadImage(s, ifAlpha or ifCritical); for t:= 0 to Pred(TeamsCount) do @@ -168,9 +169,10 @@ else if Flag = 'cpu' then Flag:= 'hedgewars'; - flagsurf:= LoadImage(Pathz[ptFlags] + '/' + Flag, ifNone); - if flagsurf = nil then - flagsurf:= LoadImage(Pathz[ptFlags] + '/hedgewars', ifNone); + flagsurf:= LoadImage(UserPathz[ptFlags] + '/' + Flag, ifNone); + if flagsurf = nil then flagsurf:= LoadImage(Pathz[ptFlags] + '/' + Flag, ifNone); + if flagsurf = nil then flagsurf:= LoadImage(UserPathz[ptFlags] + '/hedgewars', ifNone); + if flagsurf = nil then flagsurf:= LoadImage(Pathz[ptFlags] + '/hedgewars', ifNone); TryDo(flagsurf <> nil, 'Failed to load flag "' + Flag + '" as well as the default flag', true); copyToXY(flagsurf, texsurf, 2, 2); SDL_FreeSurface(flagsurf); @@ -204,7 +206,8 @@ end end; end; - MissionIcons:= LoadImage(Pathz[ptGraphics] + '/missions', ifCritical); + MissionIcons:= LoadImage(UserPathz[ptGraphics] + '/missions', ifNone); + if MissionIcons = nil then MissionIcons:= LoadImage(Pathz[ptGraphics] + '/missions', ifCritical); iconsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, 28, 28, 32, RMask, GMask, BMask, AMask); if iconsurf <> nil then begin @@ -241,7 +244,9 @@ with TeamsArray[t]^ do begin if GraveName = '' then GraveName:= 'Statue'; - texsurf:= LoadImage(Pathz[ptGraves] + '/' + GraveName, ifTransparent); + texsurf:= LoadImage(UserPathz[ptGraves] + '/' + GraveName, ifTransparent); + if texsurf = nil then texsurf:= LoadImage(Pathz[ptGraves] + '/' + GraveName, ifTransparent); + if texsurf = nil then texsurf:= LoadImage(UserPathz[ptGraves] + '/Statue', ifTransparent); if texsurf = nil then texsurf:= LoadImage(Pathz[ptGraves] + '/Statue', ifCritical or ifTransparent); GraveTex:= Surface2Tex(texsurf, false); SDL_FreeSurface(texsurf) @@ -258,7 +263,8 @@ for fi:= Low(THWFont) to High(THWFont) do with Fontz[fi] do begin - s:= Pathz[ptFonts] + '/' + Name; + s:= UserPathz[ptFonts] + '/' + Name; + if not FileExists(s) then s:= Pathz[ptFonts] + '/' + Name; WriteToConsole(msgLoading + s + ' (' + inttostr(Height) + 'pt)... '); Handle:= TTF_OpenFont(Str2PChar(s), Height); SDLTry(Handle <> nil, true); @@ -281,13 +287,20 @@ begin if AltPath = ptNone then if ii in [sprHorizontL, sprHorizontR, sprSkyL, sprSkyR] then // FIXME: hack - tmpsurf:= LoadImage(Pathz[Path] + '/' + FileName, ifAlpha or ifTransparent) + begin + tmpsurf:= LoadImage(UserPathz[Path] + '/' + FileName, ifAlpha or ifTransparent); + if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[Path] + '/' + FileName, ifAlpha or ifTransparent) + end else - tmpsurf:= LoadImage(Pathz[Path] + '/' + FileName, ifAlpha or ifTransparent or ifCritical) + begin + tmpsurf:= LoadImage(UserPathz[Path] + '/' + FileName, ifAlpha or ifTransparent); + if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[Path] + '/' + FileName, ifAlpha or ifTransparent or ifCritical) + end else begin - tmpsurf:= LoadImage(Pathz[Path] + '/' + FileName, ifAlpha or ifTransparent); - if tmpsurf = nil then - tmpsurf:= LoadImage(Pathz[AltPath] + '/' + FileName, ifAlpha or ifCritical or ifTransparent); + tmpsurf:= LoadImage(UserPathz[Path] + '/' + FileName, ifAlpha or ifTransparent); + if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[Path] + '/' + FileName, ifAlpha or ifTransparent); + if tmpsurf = nil then tmpsurf:= LoadImage(UserPathz[AltPath] + '/' + FileName, ifAlpha or ifTransparent); + if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[AltPath] + '/' + FileName, ifAlpha or ifCritical or ifTransparent); end; if tmpsurf <> nil then @@ -324,7 +337,8 @@ AddProgress; -tmpsurf:= LoadImage(Pathz[ptGraphics] + '/' + cHHFileName, ifAlpha or ifCritical or ifTransparent); +tmpsurf:= LoadImage(UserPathz[ptGraphics] + '/' + cHHFileName, ifAlpha or ifTransparent); +if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptGraphics] + '/' + cHHFileName, ifAlpha or ifCritical or ifTransparent); HHTexture:= Surface2Tex(tmpsurf, false); SDL_FreeSurface(tmpsurf); @@ -475,7 +489,8 @@ procedure LoadHedgehogHat(HHGear: PGear; newHat: shortstring); var texsurf: PSDL_Surface; begin - texsurf:= LoadImage(Pathz[ptHats] + '/' + newHat, ifNone); + texsurf:= LoadImage(UserPathz[ptHats] + '/' + newHat, ifNone); + if texsurf = nil then texsurf:= LoadImage(Pathz[ptHats] + '/' + newHat, ifNone); // only do something if the hat could be loaded if texsurf <> nil then @@ -667,7 +682,8 @@ if Step = 0 then begin WriteToConsole(msgLoading + 'progress sprite: '); - texsurf:= LoadImage(Pathz[ptGraphics] + '/Progress', ifCritical or ifTransparent); + texsurf:= LoadImage(UserPathz[ptGraphics] + '/Progress', ifTransparent); + if texsurf = nil then texsurf:= LoadImage(Pathz[ptGraphics] + '/Progress', ifCritical or ifTransparent); ProgrTex:= Surface2Tex(texsurf, false); @@ -906,9 +922,11 @@ {$ENDIF} // load engine icon {$IFDEF DARWIN} - ico:= LoadImage(Pathz[ptGraphics] + '/hwengine_mac', ifIgnoreCaps); + ico:= LoadImage(UserPathz[ptGraphics] + '/hwengine_mac', ifIgnoreCaps); + if ico = nil then ico:= LoadImage(Pathz[ptGraphics] + '/hwengine_mac', ifIgnoreCaps); {$ELSE} - ico:= LoadImage(Pathz[ptGraphics] + '/hwengine', ifIgnoreCaps); + ico:= LoadImage(UserPathz[ptGraphics] + '/hwengine', ifIgnoreCaps); + if ico = nil then ico:= LoadImage(Pathz[ptGraphics] + '/hwengine', ifIgnoreCaps); {$ENDIF} if ico <> nil then begin diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uUtils.pas --- a/hedgewars/uUtils.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uUtils.pas Fri Jun 17 11:58:27 2011 -0400 @@ -359,7 +359,7 @@ i:= 0; while(i < 7) do begin - assign(f, ParamStr(1) + '/Logs/' + cLogfileBase + inttostr(i) + '.log'); + assign(f, UserPathPrefix + '/Logs/' + cLogfileBase + inttostr(i) + '.log'); rewrite(f); if IOResult = 0 then break; inc(i) diff -r 69ed8cb551ef -r bc80445549e0 hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Fri Jun 10 17:28:53 2011 +0000 +++ b/hedgewars/uVariables.pas Fri Jun 17 11:58:27 2011 -0400 @@ -37,6 +37,7 @@ cInitVolume : LongInt = 100; cTimerInterval : LongInt = 8; PathPrefix : shortstring = './'; + UserPathPrefix : shortstring = './'; cShowFPS : boolean = false; cAltDamage : boolean = true; cReducedQuality : LongWord = rqNone; @@ -101,6 +102,7 @@ // originally from uConsts Pathz: array[TPathType] of shortstring; + UserPathz: array[TPathType] of shortstring; CountTexz: array[1..Pred(AMMO_INFINITE)] of PTexture; LAND_WIDTH : Word; LAND_HEIGHT : Word; @@ -2402,6 +2404,7 @@ cInitVolume := 100; cTimerInterval := 8; PathPrefix := './'; + UserPathPrefix := './'; cShowFPS := false; cAltDamage := true; cReducedQuality := rqNone;