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 <QResizeEvent>
20 #include <QGroupBox>
21 #include <QCheckBox>
22 #include <QGridLayout>
23 #include <QSpinBox>
24 #include <QLabel>
25 #include <QMessageBox>
26 #include <QTableView>
27 #include <QScrollBar>
28 #include <QTabWidget>
29 #include <QPushButton>
30 #include <QDebug>
31 #include <QList>
32 
33 #include "gamecfgwidget.h"
34 #include "igbox.h"
35 #include "DataManager.h"
36 #include "hwconsts.h"
37 #include "gameSchemeModel.h"
38 #include "proto.h"
39 #include "GameStyleModel.h"
40 #include "themeprompt.h"
41 
GameCFGWidget(QWidget * parent,bool randomWithoutDLC)42 GameCFGWidget::GameCFGWidget(QWidget* parent, bool randomWithoutDLC) :
43     QGroupBox(parent)
44     , mainLayout(this)
45     , seedRegexp("\\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\}")
46 {
47     mainLayout.setMargin(0);
48     setMinimumHeight(310);
49     setMaximumHeight(447);
50     setMinimumWidth(470);
51     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
52     m_master = true;
53 
54     // Easy containers for the map/game options in either stacked or tabbed mode
55 
56     mapContainerFree = new QWidget();
57     mapContainerTabbed = new QWidget();
58     optionsContainerFree = new QWidget();
59     optionsContainerTabbed = new QWidget();
60     tabbed = false;
61 
62     // Container for when in tabbed mode
63 
64     tabs = new QTabWidget(this);
65     tabs->setFixedWidth(470);
66     tabs->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
67     tabs->addTab(mapContainerTabbed, tr("Map"));
68     tabs->addTab(optionsContainerTabbed, tr("Game options"));
69     tabs->setObjectName("gameCfgWidgetTabs");
70     mainLayout.addWidget(tabs, 1);
71     tabs->setVisible(false);
72 
73     // Container for when in stacked mode
74 
75     StackContainer = new QWidget();
76     StackContainer->setObjectName("gameStackContainer");
77     mainLayout.addWidget(StackContainer, 1);
78     QVBoxLayout * stackLayout = new QVBoxLayout(StackContainer);
79 
80     // Map options
81 
82     pMapContainer = new HWMapContainer(mapContainerFree);
83     pMapContainer->setRandomWithoutDLC(randomWithoutDLC);
84     stackLayout->addWidget(mapContainerFree, 0, Qt::AlignHCenter);
85     pMapContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
86     pMapContainer->setFixedSize(width() - 14, 278);
87     mapContainerFree->setFixedSize(pMapContainer->width(), pMapContainer->height());
88 
89     // Horizontal divider
90 
91     QFrame * divider = new QFrame();
92     divider->setFrameShape(QFrame::HLine);
93     divider->setFrameShadow(QFrame::Plain);
94     stackLayout->addWidget(divider, 0, Qt::AlignBottom);
95     //stackLayout->setRowMinimumHeight(1, 10);
96 
97     // Game options
98 
99     optionsContainerTabbed->setContentsMargins(0, 0, 0, 0);
100     optionsContainerFree->setFixedSize(width() - 14, 140);
101     stackLayout->addWidget(optionsContainerFree, 0, Qt::AlignHCenter);
102 
103     OptionsInnerContainer = new QWidget(optionsContainerFree);
104     m_childWidgets << OptionsInnerContainer;
105     OptionsInnerContainer->setFixedSize(optionsContainerFree->width(), optionsContainerFree->height());
106     OptionsInnerContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
107     GBoxOptionsLayout = new QGridLayout(OptionsInnerContainer);
108 
109     lblScript = new QLabel(QLabel::tr("Style"), this);
110     GBoxOptionsLayout->addWidget(lblScript, 1, 0);
111 
112     Scripts = new QComboBox(this);
113     Scripts->setMaxVisibleItems(30);
114     GBoxOptionsLayout->addWidget(Scripts, 1, 1);
115     Scripts->setModel(DataManager::instance().gameStyleModel());
116     m_curScript = Scripts->currentText();
117 
118     ScriptsLabel = new QLabel(this);
119     ScriptsLabel->setHidden(true);
120     ScriptsLabel->setTextFormat(Qt::PlainText);
121     GBoxOptionsLayout->addWidget(ScriptsLabel, 1, 1);
122 
123     connect(Scripts, SIGNAL(currentIndexChanged(int)), this, SLOT(scriptChanged(int)));
124 
125     QWidget *SchemeWidget = new QWidget(this);
126     GBoxOptionsLayout->addWidget(SchemeWidget, 2, 0, 1, 2);
127 
128     QGridLayout *SchemeWidgetLayout = new QGridLayout(SchemeWidget);
129     SchemeWidgetLayout->setMargin(0);
130 
131     GameSchemes = new QComboBox(SchemeWidget);
132     GameSchemes->setMaxVisibleItems(30);
133     SchemeWidgetLayout->addWidget(GameSchemes, 0, 2);
134 
135     GameSchemesLabel = new QLabel(SchemeWidget);
136     GameSchemesLabel->setHidden(true);
137     GameSchemesLabel->setTextFormat(Qt::PlainText);
138     SchemeWidgetLayout->addWidget(GameSchemesLabel, 0, 2);
139 
140     connect(GameSchemes, SIGNAL(currentIndexChanged(int)), this, SLOT(schemeChanged(int)));
141 
142     lblScheme = new QLabel(QLabel::tr("Scheme"), SchemeWidget);
143     SchemeWidgetLayout->addWidget(lblScheme, 0, 0);
144 
145     QPixmap pmEdit(":/res/edit.png");
146     QIcon iconEdit = QIcon(pmEdit);
147 
148     goToSchemePage = new QPushButton(SchemeWidget);
149     goToSchemePage->setWhatsThis(tr("Edit schemes"));
150     goToSchemePage->setIconSize(pmEdit.size());
151     goToSchemePage->setIcon(iconEdit);
152     goToSchemePage->setMaximumWidth(pmEdit.width() + 6);
153     goToSchemePage->setStyleSheet("padding: 0px;");
154     SchemeWidgetLayout->addWidget(goToSchemePage, 0, 3);
155     connect(goToSchemePage, SIGNAL(clicked()), this, SLOT(jumpToSchemes()));
156 
157     lblWeapons = new QLabel(QLabel::tr("Weapons"), SchemeWidget);
158     SchemeWidgetLayout->addWidget(lblWeapons, 1, 0);
159 
160     WeaponsName = new QComboBox(SchemeWidget);
161     WeaponsName->setMaxVisibleItems(30);
162     SchemeWidgetLayout->addWidget(WeaponsName, 1, 2);
163 
164     WeaponsNameLabel = new QLabel(SchemeWidget);
165     WeaponsNameLabel->setHidden(true);
166     WeaponsNameLabel->setTextFormat(Qt::PlainText);
167     SchemeWidgetLayout->addWidget(WeaponsNameLabel, 1, 2);
168 
169     connect(WeaponsName, SIGNAL(currentIndexChanged(int)), this, SLOT(ammoChanged(int)));
170 
171     goToWeaponPage = new QPushButton(SchemeWidget);
172     goToWeaponPage->setWhatsThis(tr("Edit weapons"));
173     goToWeaponPage->setIconSize(pmEdit.size());
174     goToWeaponPage->setIcon(pmEdit);
175     goToWeaponPage->setMaximumWidth(pmEdit.width() + 6);
176     goToWeaponPage->setStyleSheet("padding: 0px;");
177     SchemeWidgetLayout->addWidget(goToWeaponPage, 1, 3);
178     connect(goToWeaponPage, SIGNAL(clicked()), this, SLOT(jumpToWeapons()));
179 
180     bindEntries = new QCheckBox(SchemeWidget);
181     bindEntries->setWhatsThis(tr("Game scheme will auto-select a weapon"));
182     bindEntries->setChecked(true);
183     bindEntries->setMaximumWidth(42);
184     bindEntries->setStyleSheet( "QCheckBox::indicator:checked:enabled    { image: url(\":/res/lock.png\"); }"
185                                 "QCheckBox::indicator:checked:disabled   { image: url(\":/res/lock_disabled.png\"); }"
186                                 "QCheckBox::indicator:unchecked:enabled  { image: url(\":/res/unlock.png\");   }"
187                                 "QCheckBox::indicator:unchecked:disabled { image: url(\":/res/unlock_disabled.png\");   }" );
188     SchemeWidgetLayout->addWidget(bindEntries, 0, 1, 0, 1, Qt::AlignVCenter);
189 
190     connect(pMapContainer, SIGNAL(seedChanged(const QString &)), this, SLOT(seedChanged(const QString &)));
191     connect(pMapContainer, SIGNAL(mapChanged(const QString &)), this, SLOT(mapChanged(const QString &)));
192     connect(pMapContainer, SIGNAL(mapgenChanged(MapGenerator)), this, SLOT(mapgenChanged(MapGenerator)));
193     connect(pMapContainer, SIGNAL(mazeSizeChanged(int)), this, SLOT(maze_sizeChanged(int)));
194     connect(pMapContainer, SIGNAL(mapFeatureSizeChanged(int)), this, SLOT(slMapFeatureSizeChanged(int)));
195     connect(pMapContainer, SIGNAL(themeChanged(const QString &)), this, SLOT(themeChanged(const QString &)));
196     connect(pMapContainer, SIGNAL(newTemplateFilter(int)), this, SLOT(templateFilterChanged(int)));
197     connect(pMapContainer, SIGNAL(drawMapRequested()), this, SIGNAL(goToDrawMap()));
198     connect(pMapContainer, SIGNAL(drawnMapChanged(const QByteArray &)), this, SLOT(onDrawnMapChanged(const QByteArray &)));
199 
200     connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
201 }
202 
setTabbed(bool tabbed)203 void GameCFGWidget::setTabbed(bool tabbed)
204 {
205     if (tabbed && !this->tabbed)
206     { // Make tabbed
207         tabs->setCurrentIndex(0);
208         StackContainer->setVisible(false);
209         tabs->setVisible(true);
210         pMapContainer->setParent(mapContainerTabbed);
211         OptionsInnerContainer->setParent(optionsContainerTabbed);
212         pMapContainer->setVisible(true);
213         setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
214         this->tabbed = true;
215     }
216     else if (!tabbed && this->tabbed)
217     { // Make stacked
218         pMapContainer->setParent(mapContainerFree);
219         OptionsInnerContainer->setParent(optionsContainerFree);
220         tabs->setVisible(false);
221         StackContainer->setVisible(true);
222         pMapContainer->setVisible(true);
223         setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
224         this->tabbed = false;
225     }
226 
227     // Restore scrollbar palettes, since Qt seems to forget them easily when switching parents
228     QList<QScrollBar *> allSBars = findChildren<QScrollBar *>();
229     QPalette pal = palette();
230     pal.setColor(QPalette::WindowText, QColor(0xff, 0xcc, 0x00));
231     pal.setColor(QPalette::Button, QColor(0x00, 0x35, 0x1d));
232     pal.setColor(QPalette::Base, QColor(0x00, 0x35, 0x1d));
233     pal.setColor(QPalette::Window, QColor(0x00, 0x00, 0x00));
234 
235     for (int i = 0; i < allSBars.size(); ++i)
236         allSBars.at(i)->setPalette(pal);
237 }
238 
jumpToSchemes()239 void GameCFGWidget::jumpToSchemes()
240 {
241     emit goToSchemes(GameSchemes->currentIndex());
242 }
243 
jumpToWeapons()244 void GameCFGWidget::jumpToWeapons()
245 {
246     emit goToWeapons(WeaponsName->currentIndex());
247 }
248 
schemeData(int column) const249 QVariant GameCFGWidget::schemeData(int column) const
250 {
251     return GameSchemes->model()->data(GameSchemes->model()->index(GameSchemes->currentIndex(), column));
252 }
253 
getGameFlags() const254 quint32 GameCFGWidget::getGameFlags() const
255 {
256     quint32 result = 0;
257 
258     if (schemeData(1).toBool())
259         result |= 0x00001000;       // fort
260     if (schemeData(2).toBool())
261         result |= 0x00000010;       // divide teams
262     if (schemeData(3).toBool())
263         result |= 0x00000004;       // solid land
264     if (schemeData(4).toBool())
265         result |= 0x00000008;       // border
266     if (schemeData(5).toBool())
267         result |= 0x00000020;       // low gravity
268     if (schemeData(6).toBool())
269         result |= 0x00000040;       // laser sight
270     if (schemeData(7).toBool())
271         result |= 0x00000080;       // invulnerable
272     if (schemeData(8).toBool())
273         result |= 0x00000100;       // mines
274     if (schemeData(9).toBool())
275         result |= 0x00000200;       // vampirism
276     if (schemeData(10).toBool())
277         result |= 0x00000400;       // karma
278     if (schemeData(11).toBool())
279         result |= 0x00000800;       // artillery
280     if (schemeData(12).toBool())
281         result |= 0x00002000;       // random
282     if (schemeData(13).toBool())
283         result |= 0x00004000;       // king
284     if (schemeData(14).toBool())
285         result |= 0x00008000;       // place hogs
286     if (schemeData(15).toBool())
287         result |= 0x00010000;       // shared ammo
288     if (schemeData(16).toBool())
289         result |= 0x00020000;       // disable girders
290     if (schemeData(17).toBool())
291         result |= 0x00040000;       // disable land obj
292     if (schemeData(18).toBool())
293         result |= 0x00080000;       // ai survival
294     if (schemeData(19).toBool())
295         result |= 0x00100000;       // infinite attacks
296     if (schemeData(20).toBool())
297         result |= 0x00200000;       // reset weaps
298     if (schemeData(21).toBool())
299         result |= 0x00400000;       // per hog ammo
300     if (schemeData(22).toBool())
301         result |= 0x00800000;       // no wind
302     if (schemeData(23).toBool())
303         result |= 0x01000000;       // more wind
304     if (schemeData(24).toBool())
305         result |= 0x02000000;       // tag team
306     if (schemeData(25).toBool())
307         result |= 0x04000000;       // bottom
308 
309     return result;
310 }
311 
getInitHealth() const312 quint32 GameCFGWidget::getInitHealth() const
313 {
314     return schemeData(28).toInt();
315 }
316 
getFullConfig() const317 QByteArray GameCFGWidget::getFullConfig() const
318 {
319     QList<QByteArray> bcfg;
320     int mapgen = pMapContainer->get_mapgen();
321     if (Scripts->currentIndex() > 0)
322     {
323         bcfg << QString("escript Scripts/Multiplayer/%1.lua").arg(Scripts->itemData(Scripts->currentIndex(), GameStyleModel::ScriptRole).toString()).toUtf8();
324     }
325 
326     QString currentMap = pMapContainer->getCurrentMap();
327     if (currentMap.size() > 0)
328     {
329         bcfg << QString("emap " + currentMap).toUtf8();
330 
331 // engine should figure it out on its own
332 //        if(pMapContainer->getCurrentIsMission())
333 //            bcfg << QString("escript Maps/%1/map.lua").arg(currentMap).toUtf8();
334     }
335     bcfg << QString("etheme " + pMapContainer->getCurrentTheme()).toUtf8();
336 
337     bcfg << QString("eseed " + pMapContainer->getCurrentSeed()).toUtf8();
338     bcfg << QString("e$gmflags %1").arg(getGameFlags()).toUtf8();
339     bcfg << QString("e$damagepct %1").arg(schemeData(26).toInt()).toUtf8();
340     bcfg << QString("e$turntime %1").arg(schemeData(27).toInt() * 1000).toUtf8();
341     bcfg << QString("e$inithealth %1").arg(schemeData(28).toInt()).toUtf8();
342     bcfg << QString("e$sd_turns %1").arg(schemeData(29).toInt()).toUtf8();
343     bcfg << QString("e$casefreq %1").arg(schemeData(30).toInt()).toUtf8();
344     bcfg << QString("e$minestime %1").arg(schemeData(31).toInt() * 1000).toUtf8();
345     bcfg << QString("e$minesnum %1").arg(schemeData(32).toInt()).toUtf8();
346     bcfg << QString("e$minedudpct %1").arg(schemeData(33).toInt()).toUtf8();
347     bcfg << QString("e$explosives %1").arg(schemeData(34).toInt()).toUtf8();
348     bcfg << QString("e$airmines %1").arg(schemeData(35).toInt()).toUtf8();
349     bcfg << QString("e$healthprob %1").arg(schemeData(36).toInt()).toUtf8();
350     bcfg << QString("e$hcaseamount %1").arg(schemeData(37).toInt()).toUtf8();
351     bcfg << QString("e$waterrise %1").arg(schemeData(38).toInt()).toUtf8();
352     bcfg << QString("e$healthdec %1").arg(schemeData(39).toInt()).toUtf8();
353     bcfg << QString("e$ropepct %1").arg(schemeData(40).toInt()).toUtf8();
354     bcfg << QString("e$getawaytime %1").arg(schemeData(41).toInt()).toUtf8();
355     bcfg << QString("e$worldedge %1").arg(schemeData(42).toInt()).toUtf8();
356     bcfg << QString("e$template_filter %1").arg(pMapContainer->getTemplateFilter()).toUtf8();
357     bcfg << QString("e$feature_size %1").arg(pMapContainer->getFeatureSize()).toUtf8();
358     bcfg << QString("e$mapgen %1").arg(mapgen).toUtf8();
359     if(!schemeData(43).isNull())
360         bcfg << QString("e$scriptparam %1").arg(schemeData(43).toString()).toUtf8();
361     else
362         bcfg << QString("e$scriptparam ").toUtf8();
363 
364 
365     switch (mapgen)
366     {
367         case MAPGEN_MAZE:
368         case MAPGEN_PERLIN:
369             bcfg << QString("e$maze_size %1").arg(pMapContainer->getMazeSize()).toUtf8();
370             break;
371 
372         case MAPGEN_DRAWN:
373         {
374             QByteArray data = pMapContainer->getDrawnMapData();
375             while(data.size() > 0)
376             {
377                 QByteArray tmp = data;
378                 tmp.truncate(200);
379                 tmp.prepend("edraw ");
380                 bcfg << tmp;
381                 data.remove(0, 200);
382             }
383             break;
384         }
385         default:
386             ;
387     }
388 
389     QByteArray result;
390 
391     foreach(QByteArray ba, bcfg)
392     HWProto::addByteArrayToBuffer(result, ba);
393 
394     return result;
395 }
396 
setNetAmmo(const QString & name,const QString & ammo)397 void GameCFGWidget::setNetAmmo(const QString& name, const QString& ammo)
398 {
399     bool illegal = ammo.size() != cDefaultAmmoStore->size();
400     if (illegal)
401     {
402         QMessageBox illegalMsg(parentWidget());
403         illegalMsg.setIcon(QMessageBox::Warning);
404         illegalMsg.setWindowTitle(QMessageBox::tr("Error"));
405         illegalMsg.setText(QMessageBox::tr("Cannot use the weapon scheme '%1'!").arg(name));
406         illegalMsg.setTextFormat(Qt::PlainText);
407         illegalMsg.setWindowModality(Qt::WindowModal);
408         illegalMsg.exec();
409     }
410 
411     int pos = WeaponsName->findText(name);
412     if ((pos == -1) || illegal)   // prevent from overriding schemes with bad ones
413     {
414         WeaponsName->addItem(name, ammo);
415         WeaponsName->setCurrentIndex(WeaponsName->count() - 1);
416     }
417     else
418     {
419         WeaponsName->setItemData(pos, ammo);
420         WeaponsName->setCurrentIndex(pos);
421     }
422 }
423 
fullNetConfig()424 void GameCFGWidget::fullNetConfig()
425 {
426     ammoChanged(WeaponsName->currentIndex());
427 
428     seedChanged(pMapContainer->getCurrentSeed());
429     templateFilterChanged(pMapContainer->getTemplateFilter());
430 
431     QString t = pMapContainer->getCurrentTheme();
432     if(!t.isEmpty())
433         themeChanged(t);
434 
435     schemeChanged(GameSchemes->currentIndex());
436     scriptChanged(Scripts->currentIndex());
437 
438     mapgenChanged(pMapContainer->get_mapgen());
439     maze_sizeChanged(pMapContainer->getMazeSize());
440     slMapFeatureSizeChanged(pMapContainer->getFeatureSize());
441 
442     if(pMapContainer->get_mapgen() == 2)
443         onDrawnMapChanged(pMapContainer->getDrawnMapData());
444 
445     // map must be the last
446     QString map = pMapContainer->getCurrentMap();
447     if (map.size())
448         mapChanged(map);
449 }
450 
setParam(const QString & param,const QStringList & slValue)451 void GameCFGWidget::setParam(const QString & param, const QStringList & slValue)
452 {
453     if (slValue.size() == 1)
454     {
455         QString value = slValue[0];
456         if (param == "MAP")
457         {
458             pMapContainer->setMap(value);
459             return;
460         }
461         if (param == "SEED")
462         {
463             pMapContainer->setSeed(value);
464             return;
465         }
466         if (param == "THEME")
467         {
468             pMapContainer->setTheme(value);
469             return;
470         }
471         if (param == "TEMPLATE")
472         {
473             pMapContainer->setTemplateFilter(value.toUInt());
474             return;
475         }
476         if (param == "MAPGEN")
477         {
478             pMapContainer->setMapgen((MapGenerator)value.toUInt());
479             return;
480         }
481         if (param == "FEATURE_SIZE")
482         {
483             pMapContainer->setFeatureSize(value.toUInt());
484             return;
485         }
486         if (param == "MAZE_SIZE")
487         {
488             pMapContainer->setMazeSize(value.toUInt());
489             return;
490         }
491         if (param == "SCRIPT")
492         {
493             int in = Scripts->findText(value);
494             Scripts->setCurrentIndex(in);
495             ScriptsLabel->setText(value);
496             pMapContainer->setScript(Scripts->itemData(Scripts->currentIndex(), GameStyleModel::ScriptRole).toString().toUtf8(), schemeData(43).toString());
497             return;
498         }
499         if (param == "DRAWNMAP")
500         {
501             pMapContainer->setDrawnMapData(qUncompress(QByteArray::fromBase64(slValue[0].toLatin1())));
502             return;
503         }
504     }
505 
506     if (slValue.size() == 2)
507     {
508         if (param == "AMMO")
509         {
510             setNetAmmo(slValue[0], slValue[1]);
511             return;
512         }
513     }
514 
515     if (slValue.size() == 6)
516     {
517         if (param == "FULLMAPCONFIG")
518         {
519             QString seed = slValue[4];
520 
521             pMapContainer->setAllMapParameters(
522                 slValue[1],
523                 (MapGenerator)slValue[2].toUInt(),
524                 slValue[3].toUInt(),
525                 seed,
526                 slValue[5].toUInt(),
527                 slValue[0].toUInt()
528             );
529             return;
530         }
531     }
532 
533     qWarning("Got bad config param from net");
534 }
535 
ammoChanged(int index)536 void GameCFGWidget::ammoChanged(int index)
537 {
538     if (index >= 0)
539     {
540         WeaponsNameLabel->setText(WeaponsName->currentText());
541         emit paramChanged(
542             "AMMO",
543             QStringList() << WeaponsName->itemText(index) << WeaponsName->itemData(index).toString()
544         );
545     }
546     else
547     {
548         WeaponsNameLabel->setText("");
549     }
550 }
551 
resetSchemeStates()552 void GameCFGWidget::resetSchemeStates()
553 {
554     updateSchemeEnabledStates(Scripts->currentIndex());
555 }
556 
updateSchemeEnabledStates(int scriptIndex)557 void GameCFGWidget::updateSchemeEnabledStates(int scriptIndex)
558 {
559     QString scheme;
560     QString weapons;
561     if(scriptIndex > 0)
562     {
563         scheme = Scripts->itemData(scriptIndex, GameStyleModel::SchemeRole).toString();
564         weapons = Scripts->itemData(scriptIndex, GameStyleModel::WeaponsRole).toString();
565     }
566     else
567     {
568         scheme = pMapContainer->getCurrentScheme();
569         weapons = pMapContainer->getCurrentWeapons();
570     }
571     if (scheme == "locked")
572     {
573         GameSchemes->setEnabled(false);
574         goToSchemePage->setEnabled(false);
575         lblScheme->setEnabled(false);
576         GameSchemes->setCurrentIndex(GameSchemes->findText("Default"));
577     }
578     else if(m_master)
579     {
580         GameSchemes->setEnabled(true);
581         goToSchemePage->setEnabled(true);
582         lblScheme->setEnabled(true);
583         int num = GameSchemes->findText(scheme);
584         if (num != -1)
585             GameSchemes->setCurrentIndex(num);
586     }
587 
588     if (weapons == "locked")
589     {
590         WeaponsName->setEnabled(false);
591         goToWeaponPage->setEnabled(false);
592         lblWeapons->setEnabled(false);
593         WeaponsName->setCurrentIndex(WeaponsName->findText("Default"));
594     }
595     else if(m_master)
596     {
597         WeaponsName->setEnabled(true);
598         goToWeaponPage->setEnabled(true);
599         lblWeapons->setEnabled(true);
600         int num = WeaponsName->findText(weapons);
601         if (num != -1)
602             WeaponsName->setCurrentIndex(num);
603     }
604 
605     if (scheme != "locked" && weapons != "locked")
606         bindEntries->setEnabled(true);
607     else
608         bindEntries->setEnabled(false);
609 }
610 
mapChanged(const QString & value)611 void GameCFGWidget::mapChanged(const QString & value)
612 {
613     if(isEnabled() && pMapContainer->getCurrentIsMission())
614     {
615         Scripts->setEnabled(false);
616         lblScript->setEnabled(false);
617         Scripts->setCurrentIndex(0);
618         updateSchemeEnabledStates(0);
619     }
620     else
621     {
622         Scripts->setEnabled(true);
623         lblScript->setEnabled(true);
624         GameSchemes->setEnabled(true);
625         goToSchemePage->setEnabled(true);
626         lblScheme->setEnabled(true);
627         WeaponsName->setEnabled(true);
628         goToWeaponPage->setEnabled(true);
629         lblWeapons->setEnabled(true);
630         bindEntries->setEnabled(true);
631     }
632     emit paramChanged("MAP", QStringList(value));
633 }
634 
templateFilterChanged(int value)635 void GameCFGWidget::templateFilterChanged(int value)
636 {
637     emit paramChanged("TEMPLATE", QStringList(QString::number(value)));
638 }
639 
seedChanged(const QString & value)640 void GameCFGWidget::seedChanged(const QString & value)
641 {
642     emit paramChanged("SEED", QStringList(value));
643 }
644 
themeChanged(const QString & value)645 void GameCFGWidget::themeChanged(const QString & value)
646 {
647     emit paramChanged("THEME", QStringList(value));
648 }
649 
schemeChanged(int index)650 void GameCFGWidget::schemeChanged(int index)
651 {
652     QStringList sl;
653 
654     int size = GameSchemes->model()->columnCount();
655     for(int i = 0; i < size; ++i)
656         sl << schemeData(i).toString();
657 
658     if (sl.size() >= 42)
659     {
660         sl[sl.size()-1].prepend('!');
661         emit paramChanged("SCHEME", sl);  // this is a stupid hack for the fact that SCHEME is being sent once, empty. Still need to find out why.
662     }
663 
664     if (isEnabled() && bindEntries->isEnabled() && bindEntries->isChecked())
665     {
666         QString schemeName = GameSchemes->itemText(index);
667         for (int i = 0; i < WeaponsName->count(); i++)
668         {
669             QString weapName = WeaponsName->itemText(i);
670             int res = QString::compare(weapName, schemeName, Qt::CaseSensitive);
671             if (0 == res)
672             {
673                 WeaponsName->setCurrentIndex(i);
674                 emit ammoChanged(i);
675                 break;
676             }
677         }
678     }
679 
680     if(index == -1)
681         GameSchemesLabel->setText("");
682     else
683         GameSchemesLabel->setText(GameSchemes->currentText());
684 
685     pMapContainer->setScript(Scripts->itemData(Scripts->currentIndex(), GameStyleModel::ScriptRole).toString().toUtf8(), schemeData(43).toString());
686 }
687 
scriptChanged(int index)688 void GameCFGWidget::scriptChanged(int index)
689 {
690     const QString & name = Scripts->itemText(index);
691     m_curScript = name;
692 
693     if(isEnabled() && index > 0)
694     {
695         updateSchemeEnabledStates(index);
696     }
697     else
698     {
699         GameSchemes->setEnabled(true);
700         goToSchemePage->setEnabled(true);
701         lblScheme->setEnabled(true);
702         WeaponsName->setEnabled(true);
703         goToWeaponPage->setEnabled(true);
704         lblWeapons->setEnabled(true);
705         bindEntries->setEnabled(true);
706     }
707     if (index == -1)
708     {
709         pMapContainer->setScript(QString(""), QString(""));
710         ScriptsLabel->setStyleSheet("color: #b50000;");
711     }
712     else
713     {
714         pMapContainer->setScript(Scripts->itemData(index, GameStyleModel::ScriptRole).toString().toUtf8(), schemeData(43).toString());
715         ScriptsLabel->setText(Scripts->currentText());
716         ScriptsLabel->setStyleSheet("");
717     }
718 
719     emit paramChanged("SCRIPT", QStringList(name));
720 }
721 
mapgenChanged(MapGenerator m)722 void GameCFGWidget::mapgenChanged(MapGenerator m)
723 {
724     int scriptIndex = Scripts->currentIndex();
725     updateSchemeEnabledStates(scriptIndex);
726     emit paramChanged("MAPGEN", QStringList(QString::number(m)));
727 }
728 
maze_sizeChanged(int s)729 void GameCFGWidget::maze_sizeChanged(int s)
730 {
731     emit paramChanged("MAZE_SIZE", QStringList(QString::number(s)));
732 }
733 
slMapFeatureSizeChanged(int s)734 void GameCFGWidget::slMapFeatureSizeChanged(int s)
735 {
736     emit paramChanged("FEATURE_SIZE", QStringList(QString::number(s)));
737 }
738 
resendSchemeData()739 void GameCFGWidget::resendSchemeData()
740 {
741     schemeChanged(GameSchemes->currentIndex());
742 }
743 
resendAmmoData()744 void GameCFGWidget::resendAmmoData()
745 {
746     ammoChanged(WeaponsName->currentIndex());
747 }
748 
onDrawnMapChanged(const QByteArray & data)749 void GameCFGWidget::onDrawnMapChanged(const QByteArray & data)
750 {
751     emit paramChanged("DRAWNMAP", QStringList(qCompress(data, 9).toBase64()));
752 }
753 
754 
updateModelViews()755 void GameCFGWidget::updateModelViews()
756 {
757     // restore game-style selection
758     if (!m_curScript.isEmpty())
759     {
760         int idx = Scripts->findText(m_curScript);
761         if (idx >= 0)
762             Scripts->setCurrentIndex(idx);
763         else
764             Scripts->setCurrentIndex(0);
765     }
766 }
767 
isMaster()768 bool GameCFGWidget::isMaster()
769 {
770     return m_master;
771 }
772 
setMaster(bool master)773 void GameCFGWidget::setMaster(bool master)
774 {
775     if (master == m_master) return;
776     m_master = master;
777 
778     if (master)
779     {
780         // Reset script if not found
781         if (Scripts->currentIndex() == -1)
782         {
783             Scripts->setCurrentIndex(Scripts->findText("Normal"));
784         }
785     }
786 
787     pMapContainer->setMaster(master);
788 
789     GameSchemes->setHidden(!master);
790     WeaponsName->setHidden(!master);
791     Scripts->setHidden(!master);
792     goToSchemePage->setHidden(!master);
793     goToWeaponPage->setHidden(!master);
794     bindEntries->setHidden(!master);
795 
796     GameSchemesLabel->setHidden(master);
797     WeaponsNameLabel->setHidden(master);
798     ScriptsLabel->setHidden(master);
799 
800     foreach (QWidget *widget, m_childWidgets)
801         widget->setEnabled(master);
802 }
803