2024-07-14 19:06:39 +02:00
|
|
|
/*
|
2024-07-22 21:09:57 +02:00
|
|
|
* towneventdialog.cpp, part of VCMI engine
|
2024-07-14 19:06:39 +02:00
|
|
|
*
|
|
|
|
* Authors: listed in file AUTHORS in main folder
|
|
|
|
*
|
|
|
|
* License: GNU General Public License v2.0 or later
|
|
|
|
* Full text of license available in license.txt file, in main folder
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "../StdInc.h"
|
|
|
|
#include "townbuildingswidget.h"
|
2024-07-22 21:09:57 +02:00
|
|
|
#include "towneventdialog.h"
|
|
|
|
#include "ui_towneventdialog.h"
|
2024-07-28 16:07:52 +02:00
|
|
|
#include "mapeditorroles.h"
|
|
|
|
#include "../../lib/entities/building/CBuilding.h"
|
|
|
|
#include "../../lib/entities/faction/CTownHandler.h"
|
2024-07-14 19:06:39 +02:00
|
|
|
#include "../../lib/constants/NumericConstants.h"
|
|
|
|
#include "../../lib/constants/StringConstants.h"
|
|
|
|
|
2024-08-01 22:28:23 +02:00
|
|
|
static const int FIRST_DAY_FOR_EVENT = 1;
|
|
|
|
static const int LAST_DAY_FOR_EVENT = 999;
|
|
|
|
static const int MAXIMUM_EVENT_REPEAT_AFTER = 999;
|
|
|
|
|
|
|
|
static const int MAXIMUM_GOLD_CHANGE = 999999;
|
|
|
|
static const int MAXIMUM_RESOURCE_CHANGE = 999;
|
|
|
|
static const int GOLD_STEP = 100;
|
|
|
|
static const int RESOURCE_STEP = 1;
|
|
|
|
|
|
|
|
static const int MAXIMUM_CREATURES_CHANGE = 999999;
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
TownEventDialog::TownEventDialog(CGTownInstance & t, QListWidgetItem * item, QWidget * parent) :
|
2024-07-14 19:06:39 +02:00
|
|
|
QDialog(parent),
|
2024-07-22 21:09:57 +02:00
|
|
|
ui(new Ui::TownEventDialog),
|
2024-07-14 19:06:39 +02:00
|
|
|
town(t),
|
2024-07-26 20:42:16 +02:00
|
|
|
townEventListItem(item)
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
|
|
ui->buildingsTree->setModel(&buildingsModel);
|
|
|
|
|
2024-07-28 16:07:52 +02:00
|
|
|
params = townEventListItem->data(MapEditorRoles::TownEventRole).toMap();
|
2024-07-26 22:30:51 +02:00
|
|
|
ui->eventFirstOccurrence->setMinimum(FIRST_DAY_FOR_EVENT);
|
|
|
|
ui->eventFirstOccurrence->setMaximum(LAST_DAY_FOR_EVENT);
|
2024-08-01 22:28:23 +02:00
|
|
|
ui->eventRepeatAfter->setMaximum(MAXIMUM_EVENT_REPEAT_AFTER);
|
2024-07-14 19:06:39 +02:00
|
|
|
ui->eventNameText->setText(params.value("name").toString());
|
|
|
|
ui->eventMessageText->setPlainText(params.value("message").toString());
|
|
|
|
ui->eventAffectsCpu->setChecked(params.value("computerAffected").toBool());
|
|
|
|
ui->eventAffectsHuman->setChecked(params.value("humanAffected").toBool());
|
|
|
|
ui->eventFirstOccurrence->setValue(params.value("firstOccurrence").toInt()+1);
|
|
|
|
ui->eventRepeatAfter->setValue(params.value("nextOccurrence").toInt());
|
|
|
|
|
|
|
|
initPlayers();
|
|
|
|
initResources();
|
|
|
|
initBuildings();
|
|
|
|
initCreatures();
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
TownEventDialog::~TownEventDialog()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
delete ui;
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
void TownEventDialog::initPlayers()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
for (int i = 0; i < PlayerColor::PLAYER_LIMIT_I; ++i)
|
|
|
|
{
|
|
|
|
bool isAffected = (1 << i) & params.value("players").toInt();
|
|
|
|
auto * item = new QListWidgetItem(QString::fromStdString(GameConstants::PLAYER_COLOR_NAMES[i]));
|
2024-07-28 16:07:52 +02:00
|
|
|
item->setData(MapEditorRoles::PlayerIDRole, QVariant::fromValue(i));
|
2024-07-14 19:06:39 +02:00
|
|
|
item->setCheckState(isAffected ? Qt::Checked : Qt::Unchecked);
|
|
|
|
ui->playersAffected->addItem(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
void TownEventDialog::initResources()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
ui->resourcesTable->setRowCount(GameConstants::RESOURCE_QUANTITY);
|
|
|
|
auto resourcesMap = params.value("resources").toMap();
|
|
|
|
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i)
|
|
|
|
{
|
|
|
|
auto name = QString::fromStdString(GameConstants::RESOURCE_NAMES[i]);
|
2024-08-01 22:28:23 +02:00
|
|
|
auto * item = new QTableWidgetItem();
|
|
|
|
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
|
|
|
item->setText(name);
|
|
|
|
ui->resourcesTable->setItem(i, 0, item);
|
2024-07-14 19:06:39 +02:00
|
|
|
|
2024-08-01 22:28:23 +02:00
|
|
|
int val = resourcesMap.value(name).toInt();
|
2024-07-14 19:06:39 +02:00
|
|
|
QSpinBox * edit = new QSpinBox(ui->resourcesTable);
|
2024-08-01 22:28:23 +02:00
|
|
|
edit->setMaximum(i == GameResID::GOLD ? MAXIMUM_GOLD_CHANGE : MAXIMUM_RESOURCE_CHANGE);
|
|
|
|
edit->setMinimum(i == GameResID::GOLD ? -MAXIMUM_GOLD_CHANGE : -MAXIMUM_RESOURCE_CHANGE);
|
2024-07-26 22:30:51 +02:00
|
|
|
edit->setSingleStep(i == GameResID::GOLD ? GOLD_STEP : RESOURCE_STEP);
|
2024-07-14 19:06:39 +02:00
|
|
|
edit->setValue(val);
|
|
|
|
|
|
|
|
ui->resourcesTable->setCellWidget(i, 1, edit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
void TownEventDialog::initBuildings()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
auto * ctown = town.town;
|
|
|
|
if (!ctown)
|
|
|
|
ctown = VLC->townh->randomTown;
|
|
|
|
if (!ctown)
|
|
|
|
throw std::runtime_error("No Town defined for type selected");
|
|
|
|
auto allBuildings = ctown->getAllBuildings();
|
|
|
|
while (!allBuildings.empty())
|
|
|
|
{
|
|
|
|
addBuilding(*ctown, *allBuildings.begin(), allBuildings);
|
|
|
|
}
|
|
|
|
ui->buildingsTree->resizeColumnToContents(0);
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
connect(&buildingsModel, &QStandardItemModel::itemChanged, this, &TownEventDialog::onItemChanged);
|
2024-07-14 19:06:39 +02:00
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
QStandardItem * TownEventDialog::addBuilding(const CTown& ctown, BuildingID buildingId, std::set<si32>& remaining)
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
auto bId = buildingId.num;
|
|
|
|
const CBuilding * building = ctown.buildings.at(buildingId);
|
|
|
|
|
2024-07-26 20:42:16 +02:00
|
|
|
QString name = QString::fromStdString(building->getNameTranslated());
|
2024-07-14 19:06:39 +02:00
|
|
|
|
|
|
|
if (name.isEmpty())
|
|
|
|
name = QString::fromStdString(defaultBuildingIdConversion(buildingId));
|
|
|
|
|
|
|
|
QList<QStandardItem *> checks;
|
|
|
|
|
|
|
|
checks << new QStandardItem(name);
|
2024-07-28 16:07:52 +02:00
|
|
|
checks.back()->setData(bId, MapEditorRoles::BuildingIDRole);
|
2024-07-14 19:06:39 +02:00
|
|
|
|
|
|
|
checks << new QStandardItem;
|
|
|
|
checks.back()->setCheckable(true);
|
|
|
|
checks.back()->setCheckState(params["buildings"].toList().contains(bId) ? Qt::Checked : Qt::Unchecked);
|
2024-07-28 16:07:52 +02:00
|
|
|
checks.back()->setData(bId, MapEditorRoles::BuildingIDRole);
|
2024-07-14 19:06:39 +02:00
|
|
|
|
|
|
|
if (building->getBase() == buildingId)
|
|
|
|
{
|
|
|
|
buildingsModel.appendRow(checks);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-07-26 20:42:16 +02:00
|
|
|
QStandardItem * parent = getBuildingParentFromTreeModel(building, buildingsModel);
|
2024-07-14 19:06:39 +02:00
|
|
|
|
|
|
|
if (!parent)
|
|
|
|
parent = addBuilding(ctown, building->upgrade.getNum(), remaining);
|
|
|
|
|
|
|
|
parent->appendRow(checks);
|
|
|
|
}
|
|
|
|
|
|
|
|
remaining.erase(bId);
|
|
|
|
return checks.front();
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
void TownEventDialog::initCreatures()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
auto creatures = params.value("creatures").toList();
|
|
|
|
auto * ctown = town.town;
|
2024-07-26 22:30:51 +02:00
|
|
|
for (int i = 0; i < GameConstants::CREATURES_PER_TOWN; ++i)
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
QString creatureNames;
|
|
|
|
if (!ctown)
|
|
|
|
{
|
2024-07-14 21:00:08 +02:00
|
|
|
creatureNames.append(tr("Creature level %1 / Creature level %1 Upgrade").arg(i + 1));
|
2024-07-14 19:06:39 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto creaturesOnLevel = ctown->creatures.at(i);
|
|
|
|
for (auto& creature : creaturesOnLevel)
|
|
|
|
{
|
|
|
|
auto cre = VLC->creatures()->getById(creature);
|
|
|
|
auto creatureName = QString::fromStdString(cre->getNameSingularTranslated());
|
|
|
|
creatureNames.append(creatureNames.isEmpty() ? creatureName : " / " + creatureName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
auto * item = new QTableWidgetItem();
|
|
|
|
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
|
|
|
item->setText(creatureNames);
|
|
|
|
ui->creaturesTable->setItem(i, 0, item);
|
|
|
|
|
|
|
|
auto creatureNumber = creatures.size() > i ? creatures.at(i).toInt() : 0;
|
|
|
|
QSpinBox* edit = new QSpinBox(ui->creaturesTable);
|
|
|
|
edit->setValue(creatureNumber);
|
2024-08-01 22:28:23 +02:00
|
|
|
edit->setMaximum(MAXIMUM_CREATURES_CHANGE);
|
2024-07-14 19:06:39 +02:00
|
|
|
ui->creaturesTable->setCellWidget(i, 1, edit);
|
|
|
|
|
|
|
|
}
|
|
|
|
ui->creaturesTable->resizeColumnToContents(0);
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
void TownEventDialog::on_TownEventDialog_finished(int result)
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
QVariantMap descriptor;
|
|
|
|
descriptor["name"] = ui->eventNameText->text();
|
|
|
|
descriptor["message"] = ui->eventMessageText->toPlainText();
|
|
|
|
descriptor["humanAffected"] = QVariant::fromValue(ui->eventAffectsHuman->isChecked());
|
|
|
|
descriptor["computerAffected"] = QVariant::fromValue(ui->eventAffectsCpu->isChecked());
|
|
|
|
descriptor["firstOccurrence"] = QVariant::fromValue(ui->eventFirstOccurrence->value()-1);
|
|
|
|
descriptor["nextOccurrence"] = QVariant::fromValue(ui->eventRepeatAfter->value());
|
|
|
|
descriptor["players"] = playersToVariant();
|
|
|
|
descriptor["resources"] = resourcesToVariant();
|
|
|
|
descriptor["buildings"] = buildingsToVariant();
|
|
|
|
descriptor["creatures"] = creaturesToVariant();
|
|
|
|
|
2024-07-28 16:07:52 +02:00
|
|
|
townEventListItem->setData(MapEditorRoles::TownEventRole, descriptor);
|
2024-07-14 21:00:08 +02:00
|
|
|
auto itemText = tr("Day %1 - %2").arg(ui->eventFirstOccurrence->value(), 3).arg(ui->eventNameText->text());
|
2024-07-26 20:42:16 +02:00
|
|
|
townEventListItem->setText(itemText);
|
2024-07-14 19:06:39 +02:00
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
QVariant TownEventDialog::playersToVariant()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
int players = 0;
|
|
|
|
for (int i = 0; i < ui->playersAffected->count(); ++i)
|
|
|
|
{
|
|
|
|
auto * item = ui->playersAffected->item(i);
|
|
|
|
if (item->checkState() == Qt::Checked)
|
|
|
|
players |= 1 << i;
|
|
|
|
}
|
|
|
|
return QVariant::fromValue(players);
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
QVariantMap TownEventDialog::resourcesToVariant()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
2024-07-28 16:07:52 +02:00
|
|
|
auto res = params.value("resources").toMap();
|
2024-07-14 19:06:39 +02:00
|
|
|
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; ++i)
|
|
|
|
{
|
|
|
|
auto * itemType = ui->resourcesTable->item(i, 0);
|
|
|
|
auto * itemQty = static_cast<QSpinBox *> (ui->resourcesTable->cellWidget(i, 1));
|
|
|
|
|
|
|
|
res[itemType->text()] = QVariant::fromValue(itemQty->value());
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
QVariantList TownEventDialog::buildingsToVariant()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
2024-08-01 22:28:23 +02:00
|
|
|
return getBuildingVariantsFromModel(buildingsModel, 1, Qt::Checked);
|
2024-07-14 19:06:39 +02:00
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
QVariantList TownEventDialog::creaturesToVariant()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
QVariantList creaturesList;
|
2024-07-26 22:30:51 +02:00
|
|
|
for (int i = 0; i < GameConstants::CREATURES_PER_TOWN; ++i)
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
auto * item = static_cast<QSpinBox *>(ui->creaturesTable->cellWidget(i, 1));
|
|
|
|
creaturesList.push_back(item->value());
|
|
|
|
}
|
|
|
|
return creaturesList;
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
void TownEventDialog::on_okButton_clicked()
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
void TownEventDialog::setRowColumnCheckState(QStandardItem * item, int column, Qt::CheckState checkState) {
|
2024-07-14 19:06:39 +02:00
|
|
|
auto sibling = item->model()->sibling(item->row(), column, item->index());
|
|
|
|
buildingsModel.itemFromIndex(sibling)->setCheckState(checkState);
|
|
|
|
}
|
|
|
|
|
2024-07-22 21:09:57 +02:00
|
|
|
void TownEventDialog::onItemChanged(QStandardItem * item)
|
2024-07-14 19:06:39 +02:00
|
|
|
{
|
2024-07-22 21:09:57 +02:00
|
|
|
disconnect(&buildingsModel, &QStandardItemModel::itemChanged, this, &TownEventDialog::onItemChanged);
|
2024-07-14 19:06:39 +02:00
|
|
|
auto rowFirstColumnIndex = item->model()->sibling(item->row(), 0, item->index());
|
|
|
|
QStandardItem * nextRow = buildingsModel.itemFromIndex(rowFirstColumnIndex);
|
|
|
|
if (item->checkState() == Qt::Checked) {
|
|
|
|
while (nextRow) {
|
|
|
|
setRowColumnCheckState(nextRow,item->column(), Qt::Checked);
|
|
|
|
nextRow = nextRow->parent();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (item->checkState() == Qt::Unchecked) {
|
|
|
|
std::vector<QStandardItem *> stack;
|
|
|
|
stack.push_back(nextRow);
|
2024-08-01 22:28:23 +02:00
|
|
|
do
|
|
|
|
{
|
2024-07-14 19:06:39 +02:00
|
|
|
nextRow = stack.back();
|
|
|
|
stack.pop_back();
|
|
|
|
setRowColumnCheckState(nextRow, item->column(), Qt::Unchecked);
|
|
|
|
if (nextRow->hasChildren()) {
|
|
|
|
for (int i = 0; i < nextRow->rowCount(); ++i) {
|
|
|
|
stack.push_back(nextRow->child(i, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-01 22:28:23 +02:00
|
|
|
} while(!stack.empty());
|
2024-07-14 19:06:39 +02:00
|
|
|
}
|
2024-07-22 21:09:57 +02:00
|
|
|
connect(&buildingsModel, &QStandardItemModel::itemChanged, this, &TownEventDialog::onItemChanged);
|
2024-07-14 19:06:39 +02:00
|
|
|
}
|