1 /*
2  * Hedgewars, a free turn based strategy game
3  * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; version 2 of the License
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 
19 #include "campaign.h"
20 #include "hwconsts.h"
21 #include "DataManager.h"
22 #include <QSettings>
23 #include <QObject>
24 #include <QLocale>
25 
getCampTeamFile(QString & campaignName,QString & teamName)26 QSettings* getCampTeamFile(QString & campaignName, QString & teamName)
27 {
28     QSettings* teamfile = new QSettings(cfgdir->absolutePath() + "/Teams/" + teamName + ".hwt", QSettings::IniFormat, 0);
29     teamfile->setIniCodec("UTF-8");
30     // if entry not found check if there is written without _
31     // if then is found rename it to use _
32     QString spaceCampName = campaignName;
33     spaceCampName = spaceCampName.replace(QString("_"),QString(" "));
34     if (!teamfile->childGroups().contains("Campaign " + campaignName) &&
35             teamfile->childGroups().contains("Campaign " + spaceCampName)){
36         teamfile->beginGroup("Campaign " + spaceCampName);
37         QStringList keys = teamfile->childKeys();
38         teamfile->endGroup();
39         for (int i=0;i<keys.size();i++) {
40             QVariant value = teamfile->value("Campaign " + spaceCampName + "/" + keys[i]);
41             teamfile->setValue("Campaign " + campaignName + "/" + keys[i], value);
42         }
43         teamfile->remove("Campaign " + spaceCampName);
44     }
45 
46     return teamfile;
47 }
48 
49 /**
50     Returns true if the specified mission has been completed
51     campaignName: Name of the campaign in question
52     missionInList: QComboBox index of the mission as selected in the mission widget
53     teamName: Name of the playing team
54 */
isCampMissionWon(QString & campaignName,int missionInList,QString & teamName)55 bool isCampMissionWon(QString & campaignName, int missionInList, QString & teamName)
56 {
57     QSettings* teamfile = getCampTeamFile(campaignName, teamName);
58     int progress = teamfile->value("Campaign " + campaignName + "/Progress", 0).toInt();
59     int unlockedMissions = teamfile->value("Campaign " + campaignName + "/UnlockedMissions", 0).toInt();
60     // The CowardMode cheat unlocks all campaign missions,
61     // but as "punishment", none of them will be marked as completed.
62     // Added to make it easier to test campaigns.
63     bool cheat = teamfile->value("Team/CowardMode", false).toBool();
64     if(cheat)
65     {
66         return false;
67     }
68     else if(progress>0 && unlockedMissions==0)
69     {
70         QSettings campfile("physfs://Missions/Campaign/" + campaignName + "/campaign.ini", QSettings::IniFormat, 0);
71         campfile.setIniCodec("UTF-8");
72         int totalMissions = campfile.value("MissionNum", 1).toInt();
73         return (progress > (progress - missionInList)) || (progress >= totalMissions);
74     }
75     else if(unlockedMissions>0)
76     {
77         int fileMissionId = missionInList + 1;
78         int actualMissionId = teamfile->value(QString("Campaign %1/Mission%2").arg(campaignName, QString::number(fileMissionId)), false).toInt();
79         return teamfile->value(QString("Campaign %1/Mission%2Won").arg(campaignName, QString::number(actualMissionId)), false).toBool();
80     }
81     else
82         return false;
83 }
84 
85 /** Returns true if the campaign has been won by the team */
isCampWon(QString & campaignName,QString & teamName)86 bool isCampWon(QString & campaignName, QString & teamName)
87 {
88     QSettings* teamfile = getCampTeamFile(campaignName, teamName);
89     bool won = teamfile->value("Campaign " + campaignName + "/Won", false).toBool();
90     bool cheat = teamfile->value("Team/CowardMode", false).toBool();
91     return won && !cheat;
92 }
93 
getCampMetaInfo()94 QSettings* getCampMetaInfo()
95 {
96     DataManager & dataMgr = DataManager::instance();
97     // get locale
98     QSettings settings(dataMgr.settingsFileName(),
99     QSettings::IniFormat);
100     QString loc = QLocale().name();
101     QString campaignDescFile = QString("physfs://Locale/campaigns_" + loc + ".txt");
102     // if file is non-existant try with language only
103     if (!QFile::exists(campaignDescFile))
104     campaignDescFile = QString("physfs://Locale/campaigns_" + loc.remove(QRegExp("_.*$")) + ".txt");
105 
106     // fallback if file for current locale is non-existant
107     if (!QFile::exists(campaignDescFile))
108         campaignDescFile = QString("physfs://Locale/campaigns_en.txt");
109 
110     QSettings* m_info = new QSettings(campaignDescFile, QSettings::IniFormat, 0);
111     m_info->setIniCodec("UTF-8");
112 
113     return m_info;
114 }
115 
116 /** Returns the localized campaign name */
getRealCampName(const QString & campaignName)117 QString getRealCampName(const QString & campaignName)
118 {
119     QString campaignNameSpaces = QString(campaignName).replace(QString("_"), QString(" "));
120     return getCampMetaInfo()->value(campaignName+".name", campaignNameSpaces).toString();
121 }
122 
getCampMissionList(QString & campaignName,QString & teamName)123 QList<MissionInfo> getCampMissionList(QString & campaignName, QString & teamName)
124 {
125     QList<MissionInfo> missionInfoList;
126     QSettings* teamfile = getCampTeamFile(campaignName, teamName);
127 
128     int progress = teamfile->value("Campaign " + campaignName + "/Progress", 0).toInt();
129     int unlockedMissions = teamfile->value("Campaign " + campaignName + "/UnlockedMissions", 0).toInt();
130     bool cheat = teamfile->value("Team/CowardMode", false).toBool();
131 
132     QSettings campfile("physfs://Missions/Campaign/" + campaignName + "/campaign.ini", QSettings::IniFormat, 0);
133     campfile.setIniCodec("UTF-8");
134 
135     QSettings* m_info = getCampMetaInfo();
136 
137     if(cheat)
138     {
139         progress = campfile.value("MissionNum", 1).toInt();
140     }
141     if((progress >= 0 && unlockedMissions == 0) || cheat)
142     {
143         for(unsigned int i = progress + 1; i > 0; i--)
144         {
145             MissionInfo missionInfo;
146             QString script = campfile.value(QString("Mission %1/Script").arg(i)).toString();
147             if(!script.isNull()) {
148                 missionInfo.script = script;
149                 missionInfo.name = campfile.value(QString("Mission %1/Name").arg(i)).toString();
150                 QString scriptPrefix = campaignName+"-"+ script.replace(QString(".lua"),QString(""));
151                 missionInfo.realName = m_info->value(scriptPrefix+".name", missionInfo.name).toString();
152                 missionInfo.description = m_info->value(scriptPrefix + ".desc",
153                                             QObject::tr("No description available")).toString();
154                 QString image = campfile.value(QString("Mission %1/Script").arg(i)).toString().replace(QString(".lua"),QString("@2x.png"));
155                 missionInfo.image = "physfs://Graphics/Missions/Campaign/"+campaignName+"/"+image;
156                 if (!QFile::exists(missionInfo.image))
157                     missionInfo.image = ":/res/CampaignDefault.png";
158                 missionInfoList.append(missionInfo);
159             }
160         }
161     }
162     else if(unlockedMissions>0)
163     {
164         for(int i=1;i<=unlockedMissions;i++)
165         {
166             QString missionNum = QString("%1").arg(i);
167             int missionNumber = teamfile->value("Campaign " + campaignName + "/Mission"+missionNum, -1).toInt();
168             MissionInfo missionInfo;
169             QString script = campfile.value(QString("Mission %1/Script").arg(missionNumber)).toString();
170             missionInfo.script = script;
171             missionInfo.name = campfile.value(QString("Mission %1/Name").arg(missionNumber)).toString();
172             QString scriptPrefix = campaignName+"-"+ script.replace(QString(".lua"),QString(""));
173             missionInfo.realName = m_info->value(scriptPrefix+".name", missionInfo.name).toString();
174             missionInfo.description = m_info->value(scriptPrefix + ".desc",
175                                             QObject::tr("No description available")).toString();
176             QString image = campfile.value(QString("Mission %1/Script").arg(missionNumber)).toString().replace(QString(".lua"),QString("@2x.png"));
177             missionInfo.image = "physfs://Graphics/Missions/Campaign/"+campaignName+"/"+image;
178             if (!QFile::exists(missionInfo.image))
179                 missionInfo.image = ":/res/CampaignDefault.png";
180             missionInfoList.append(missionInfo);
181         }
182     }
183     return missionInfoList;
184 }
185