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 <QFile>
20 #include <QTextStream>
21 #include <QStringList>
22 #include <QLineEdit>
23 #include <QCryptographicHash>
24 #include <QSettings>
25 #include <QStandardItemModel>
26 #include <QDebug>
27 
28 #include "team.h"
29 #include "hwform.h"
30 #include "DataManager.h"
31 #include "gameuiconfig.h"
32 
HWTeam(const QString & teamname)33 HWTeam::HWTeam(const QString & teamname) :
34     QObject(0)
35     , m_difficulty(0)
36     , m_numHedgehogs(4)
37     , m_isNetTeam(false)
38     , m_isMissionTeam(false)
39 {
40     m_name = teamname;
41     OldTeamName = m_name;
42     for (int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
43     {
44         m_hedgehogs.append(HWHog());
45         m_hedgehogs[i].Name = (QLineEdit::tr("Hedgehog %1").arg(i+1));
46         m_hedgehogs[i].Hat = "NoHat";
47     }
48     m_grave = "Statue";
49     m_fort = "Plane";
50     m_voicepack = "Default";
51     m_flag = "hedgewars";
52     for(int i = 0; i < BINDS_NUMBER; i++)
53     {
54         m_binds.append(BindAction());
55         m_binds[i].action = cbinds[i].action;
56         m_binds[i].strbind = QString();
57     }
58     m_color = 0;
59 }
60 
HWTeam(const QStringList & strLst)61 HWTeam::HWTeam(const QStringList& strLst) :
62     QObject(0)
63     , m_numHedgehogs(4)
64     , m_isNetTeam(true)
65     , m_isMissionTeam(false)
66 {
67     // net teams are configured from QStringList
68     if(strLst.size() != 23) throw HWTeamConstructException();
69     m_name = strLst[0];
70     m_grave = strLst[1];
71     m_fort = strLst[2];
72     m_voicepack = strLst[3];
73     m_flag = strLst[4];
74     m_owner = strLst[5];
75     m_difficulty = strLst[6].toUInt();
76     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
77     {
78         m_hedgehogs.append(HWHog());
79         m_hedgehogs[i].Name=strLst[i * 2 + 7];
80         m_hedgehogs[i].Hat=strLst[i * 2 + 8];
81 // Somehow claymore managed an empty hat.  Until we figure out how, this should avoid a repeat
82 // Checking net teams is probably pointless, but can't hurt.
83         if (m_hedgehogs[i].Hat.isEmpty()) m_hedgehogs[i].Hat = "NoHat";
84     }
85     m_color = 0;
86 }
87 
HWTeam()88 HWTeam::HWTeam() :
89     QObject(0)
90     , m_difficulty(0)
91     , m_numHedgehogs(4)
92     , m_isNetTeam(false)
93     , m_isMissionTeam(false)
94 {
95     m_name = QString("Team");
96     for (int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
97     {
98         m_hedgehogs.append(HWHog());
99         m_hedgehogs[i].Name.sprintf("hedgehog %d", i);
100         m_hedgehogs[i].Hat = "NoHat";
101     }
102 
103     m_grave = QString("Simple"); // default
104     m_fort = QString("Island"); // default
105     m_voicepack = "Default";
106     m_flag = "hedgewars";
107 
108     for(int i = 0; i < BINDS_NUMBER; i++)
109     {
110         m_binds.append(BindAction());
111         m_binds[i].action = cbinds[i].action;
112         m_binds[i].strbind = QString();
113     }
114     m_color = 0;
115 }
116 
HWTeam(const HWTeam & other)117 HWTeam::HWTeam(const HWTeam & other) :
118     QObject(0)
119     , OldTeamName(other.OldTeamName)
120     , m_name(other.m_name)
121     , m_grave(other.m_grave)
122     , m_fort(other.m_fort)
123     , m_flag(other.m_flag)
124     , m_voicepack(other.m_voicepack)
125     , m_hedgehogs(other.m_hedgehogs)
126     , m_difficulty(other.m_difficulty)
127     , m_binds(other.m_binds)
128     , m_numHedgehogs(other.m_numHedgehogs)
129     , m_color(other.m_color)
130     , m_isNetTeam(other.m_isNetTeam)
131     , m_isMissionTeam(other.m_isMissionTeam)
132     , m_owner(other.m_owner)
133 //      , AchievementProgress(other.AchievementProgress)
134 {
135 
136 }
137 
operator =(const HWTeam & other)138 HWTeam & HWTeam::operator = (const HWTeam & other)
139 {
140     if(this != &other)
141     {
142         OldTeamName = other.OldTeamName;
143         m_name = other.m_name;
144         m_grave = other.m_grave;
145         m_fort = other.m_fort;
146         m_flag = other.m_flag;
147         m_voicepack = other.m_voicepack;
148         m_hedgehogs = other.m_hedgehogs;
149         m_difficulty = other.m_difficulty;
150         m_binds = other.m_binds;
151         m_numHedgehogs = other.m_numHedgehogs;
152         m_color = other.m_color;
153         m_isNetTeam = other.m_isNetTeam;
154         m_owner = other.m_owner;
155         m_color = other.m_color;
156         m_isMissionTeam = other.m_isMissionTeam;
157     }
158 
159     return *this;
160 }
161 
loadFromFile()162 bool HWTeam::loadFromFile()
163 {
164     QSettings teamfile(QString(cfgdir->absolutePath() + "/Teams/%1.hwt").arg(DataManager::safeFileName(m_name)), QSettings::IniFormat, 0);
165     teamfile.setIniCodec("UTF-8");
166     m_name = teamfile.value("Team/Name", m_name).toString();
167     m_grave = teamfile.value("Team/Grave", "Statue").toString();
168     m_fort = teamfile.value("Team/Fort", "Plane").toString();
169     m_voicepack = teamfile.value("Team/Voicepack", "Default").toString();
170     m_flag = teamfile.value("Team/Flag", "hedgewars").toString();
171     m_difficulty = teamfile.value("Team/Difficulty", 0).toInt();
172     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
173     {
174         QString hh = QString("Hedgehog%1/").arg(i);
175         m_hedgehogs[i].Name = teamfile.value(hh + "Name", QString("Hedgehog %1").arg(i+1)).toString();
176         m_hedgehogs[i].Hat = teamfile.value(hh + "Hat", "NoHat").toString();
177     }
178     for(int i = 0; i < BINDS_NUMBER; i++)
179         m_binds[i].strbind = teamfile.value(QString("Binds/%1").arg(m_binds[i].action), QString()).toString();
180     for(int i = 0; i < MAX_ACHIEVEMENTS; i++)
181         if(achievements[i][0][0])
182             AchievementProgress[i] = teamfile.value(QString("Achievements/%1").arg(achievements[i][0]), 0).toUInt();
183         else
184             break;
185     return true;
186 }
187 
fileExists()188 bool HWTeam::fileExists()
189 {
190     QFile f(QString(cfgdir->absolutePath() + "/Teams/%1.hwt").arg(DataManager::safeFileName(m_name)));
191     return f.exists();
192 }
193 
194 // Returns true if the team name has been changed but a file with the same team name already exists.
195 // So if this team would be saved, another team file would be overwritten, which is generally not
196 // desired.
wouldOverwriteOtherFile()197 bool HWTeam::wouldOverwriteOtherFile()
198 {
199     return (m_name != OldTeamName) && fileExists();
200 }
201 
deleteFile()202 bool HWTeam::deleteFile()
203 {
204     if(m_isNetTeam)
205         return false;
206     QFile cfgfile(QString(cfgdir->absolutePath() + "/Teams/%1.hwt").arg(DataManager::safeFileName(m_name)));
207     cfgfile.remove();
208     return true;
209 }
210 
saveToFile()211 bool HWTeam::saveToFile()
212 {
213     if (OldTeamName != m_name)
214     {
215         QFile cfgfile(QString(cfgdir->absolutePath() + "/Teams/%1.hwt").arg(DataManager::safeFileName(OldTeamName)));
216         cfgfile.remove();
217         OldTeamName = m_name;
218     }
219 
220     QString fileName = QString(cfgdir->absolutePath() + "/Teams/%1.hwt").arg(DataManager::safeFileName(m_name));
221     DataManager::ensureFileExists(fileName);
222     QSettings teamfile(fileName, QSettings::IniFormat, 0);
223     teamfile.setIniCodec("UTF-8");
224     teamfile.setValue("Team/Name", m_name);
225     teamfile.setValue("Team/Grave", m_grave);
226     teamfile.setValue("Team/Fort", m_fort);
227     teamfile.setValue("Team/Voicepack", m_voicepack);
228     teamfile.setValue("Team/Flag", m_flag);
229     teamfile.setValue("Team/Difficulty", m_difficulty);
230 
231     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
232     {
233         QString hh = QString("Hedgehog%1/").arg(i);
234         teamfile.setValue(hh + "Name", m_hedgehogs[i].Name);
235         teamfile.setValue(hh + "Hat", m_hedgehogs[i].Hat);
236     }
237     for(int i = 0; i < BINDS_NUMBER; i++)
238     {
239         if(QString(m_binds[i].action) != QString("!MULTI"))
240             teamfile.setValue(QString("Binds/%1").arg(m_binds[i].action), m_binds[i].strbind);
241     }
242     for(int i = 0; i < MAX_ACHIEVEMENTS; i++)
243         if(achievements[i][0][0])
244             teamfile.setValue(QString("Achievements/%1").arg(achievements[i][0]), AchievementProgress[i]);
245         else
246             break;
247 
248     return true;
249 }
250 
teamGameConfig(quint32 InitHealth) const251 QStringList HWTeam::teamGameConfig(quint32 InitHealth) const
252 {
253     QStringList sl;
254     QString cmdAddHog = "eaddhh";
255 
256     if (m_isNetTeam)
257     {
258         sl.push_back(QString("eaddteam %3 %1 %2").arg(qcolor().rgb() & 0xffffff).arg(m_name).arg(QString(QCryptographicHash::hash(m_owner.toUtf8(), QCryptographicHash::Md5).toHex())));
259         sl.push_back("erdriven");
260     }
261     else
262     {
263         if (m_isMissionTeam)
264         {
265             sl.push_back(QString("esetmissteam %3 %1 %2").arg(qcolor().rgb() & 0xffffff).arg(m_name).arg(playerHash));
266             cmdAddHog = "eaddmisshh";
267         }
268         else
269         {
270             sl.push_back(QString("eaddteam %3 %1 %2").arg(qcolor().rgb() & 0xffffff).arg(m_name).arg(playerHash));
271         }
272     }
273 
274     sl.push_back(QString("egrave " + m_grave));
275     sl.push_back(QString("efort " + m_fort));
276     sl.push_back(QString("evoicepack " + m_voicepack));
277     sl.push_back(QString("eflag " + m_flag));
278 
279     if(!m_owner.isEmpty())
280         sl.push_back(QString("eowner ") + m_owner);
281 
282     for (int t = 0; t < m_numHedgehogs; t++)
283     {
284         sl.push_back(QString(cmdAddHog + " %1 %2 %3")
285                      .arg(QString::number(m_difficulty),
286                           QString::number(InitHealth),
287                           m_hedgehogs[t].Name));
288         sl.push_back(QString("ehat %1")
289                      .arg(m_hedgehogs[t].Hat));
290     }
291     return sl;
292 }
293 
294 
setNetTeam(bool isNetTeam)295 void HWTeam::setNetTeam(bool isNetTeam)
296 {
297     m_isNetTeam = isNetTeam;
298 }
299 
isNetTeam() const300 bool HWTeam::isNetTeam() const
301 {
302     return m_isNetTeam;
303 }
304 
setMissionTeam(bool isMissionTeam)305 void HWTeam::setMissionTeam(bool isMissionTeam)
306 {
307     m_isMissionTeam = isMissionTeam;
308 }
309 
isMissionTeam() const310 bool HWTeam::isMissionTeam() const
311 {
312     return m_isMissionTeam;
313 }
314 
operator ==(const HWTeam & t1) const315 bool HWTeam::operator==(const HWTeam& t1) const
316 {
317     return m_name==t1.m_name;
318 }
319 
operator <(const HWTeam & t1) const320 bool HWTeam::operator<(const HWTeam& t1) const
321 {
322     return m_name<t1.m_name; // if names are equal - test if it is net team
323 }
324 
325 
326 //// Methods for member inspection+modification ////
327 
328 
329 // name
name() const330 QString HWTeam::name() const
331 {
332     return m_name;
333 }
setName(const QString & name)334 void HWTeam::setName(const QString & name)
335 {
336     m_name = name;
337 }
338 
339 // single hedgehog
hedgehog(unsigned int idx) const340 const HWHog & HWTeam::hedgehog(unsigned int idx) const
341 {
342     return m_hedgehogs[idx];
343 }
setHedgehog(unsigned int idx,HWHog hh)344 void HWTeam::setHedgehog(unsigned int idx, HWHog hh)
345 {
346     m_hedgehogs[idx] = hh;
347 }
348 
349 // owner
owner() const350 QString HWTeam::owner() const
351 {
352     return m_owner;
353 }
354 
setOwner(const QString & owner)355 void HWTeam::setOwner(const QString & owner)
356 {
357     m_owner = owner;
358 }
359 
360 
361 // difficulty
difficulty() const362 unsigned int HWTeam::difficulty() const
363 {
364     return m_difficulty;
365 }
setDifficulty(unsigned int level)366 void HWTeam::setDifficulty(unsigned int level)
367 {
368     m_difficulty = level;
369 }
370 
371 // color
color() const372 int HWTeam::color() const
373 {
374     return m_color;
375 }
376 
qcolor() const377 QColor HWTeam::qcolor() const
378 {
379     return DataManager::instance().colorsModel()->item(m_color)->data().value<QColor>();
380 }
381 
setColor(int color)382 void HWTeam::setColor(int color)
383 {
384     m_color = color % DataManager::instance().colorsModel()->rowCount();
385 }
386 
387 
388 // binds
keyBind(unsigned int idx) const389 QString HWTeam::keyBind(unsigned int idx) const
390 {
391     return m_binds[idx].strbind;
392 }
bindKey(unsigned int idx,const QString & key)393 void HWTeam::bindKey(unsigned int idx, const QString & key)
394 {
395     m_binds[idx].strbind = key;
396 }
397 
398 // flag
setFlag(const QString & flag)399 void    HWTeam::setFlag(const QString & flag)
400 {
401     m_flag = flag;
402 }
flag() const403 QString HWTeam::flag() const
404 {
405     return m_flag;
406 }
407 
408 // fort
setFort(const QString & fort)409 void    HWTeam::setFort(const QString & fort)
410 {
411     m_fort = fort;
412 }
fort() const413 QString HWTeam::fort() const
414 {
415     return m_fort;
416 }
417 
418 // grave
setGrave(const QString & grave)419 void HWTeam::setGrave(const QString & grave)
420 {
421     m_grave = grave;
422 }
grave() const423 QString HWTeam::grave() const
424 {
425     return m_grave;
426 }
427 
428 // voicepack - getter/setter
setVoicepack(const QString & voicepack)429 void HWTeam::setVoicepack(const QString & voicepack)
430 {
431     m_voicepack = voicepack;
432 }
voicepack() const433 QString HWTeam::voicepack() const
434 {
435     return m_voicepack;
436 }
437 
438 // amount of hedgehogs
numHedgehogs() const439 unsigned char HWTeam::numHedgehogs() const
440 {
441     return m_numHedgehogs;
442 }
setNumHedgehogs(unsigned char num)443 void HWTeam::setNumHedgehogs(unsigned char num)
444 {
445     m_numHedgehogs = num;
446 }
447 
448