1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

map editor: Allow to customize town spells

This commit is contained in:
godric3 2024-07-12 21:18:43 +02:00
parent db1a780030
commit 7aca2efb35
6 changed files with 539 additions and 1 deletions

View File

@ -871,7 +871,7 @@ void CGameState::initTowns()
}
//init spells
vti->spells.resize(GameConstants::SPELL_LEVELS);
vti->possibleSpells -= SpellID::PRESET;
for(ui32 z=0; z<vti->obligatorySpells.size();z++)
{
const auto * s = vti->obligatorySpells[z].toSpell();

View File

@ -29,6 +29,7 @@ set(editor_SRCS
validator.cpp
inspector/inspector.cpp
inspector/townbuildingswidget.cpp
inspector/townspellswidget.cpp
inspector/armywidget.cpp
inspector/messagewidget.cpp
inspector/rewardswidget.cpp
@ -70,6 +71,7 @@ set(editor_HEADERS
validator.h
inspector/inspector.h
inspector/townbuildingswidget.h
inspector/townspellswidget.h
inspector/armywidget.h
inspector/messagewidget.h
inspector/rewardswidget.h
@ -98,6 +100,7 @@ set(editor_FORMS
playerparams.ui
validator.ui
inspector/townbuildingswidget.ui
inspector/townspellswidget.ui
inspector/armywidget.ui
inspector/messagewidget.ui
inspector/rewardswidget.ui

View File

@ -21,6 +21,7 @@
#include "../lib/constants/StringConstants.h"
#include "townbuildingswidget.h"
#include "townspellswidget.h"
#include "armywidget.h"
#include "messagewidget.h"
#include "rewardswidget.h"
@ -342,6 +343,7 @@ void Inspector::updateProperties(CGTownInstance * o)
auto * delegate = new TownBuildingsDelegate(*o);
addProperty("Buildings", PropertyEditorPlaceholder(), delegate, false);
addProperty("Spells", PropertyEditorPlaceholder(), new TownSpellsDelegate(*o), false);
}
void Inspector::updateProperties(CGArtifact * o)

View File

@ -0,0 +1,172 @@
/*
* townspellswidget.cpp, part of VCMI engine
*
* 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 "townspellswidget.h"
#include "ui_townspellswidget.h"
#include "inspector.h"
#include "../../lib/constants/StringConstants.h"
#include "../../lib/spells/CSpellHandler.h"
TownSpellsWidget::TownSpellsWidget(CGTownInstance & town, QWidget * parent) :
QDialog(parent),
ui(new Ui::TownSpellsWidget),
town(town)
{
ui->setupUi(this);
BuildingID mageGuilds[] = {BuildingID::MAGES_GUILD_1, BuildingID::MAGES_GUILD_2, BuildingID::MAGES_GUILD_3, BuildingID::MAGES_GUILD_4, BuildingID::MAGES_GUILD_5};
for (int i = 0; i < GameConstants::SPELL_LEVELS; i++)
{
ui->tabWidget->setTabEnabled(i, vstd::contains(town.getTown()->buildings, mageGuilds[i]));
}
}
TownSpellsWidget::~TownSpellsWidget()
{
delete ui;
}
void TownSpellsWidget::obtainData()
{
initSpellLists();
if (vstd::contains(town.possibleSpells, SpellID::PRESET)) {
ui->customizeSpells->setChecked(true);
}
else
{
ui->customizeSpells->setChecked(false);
ui->tabWidget->setEnabled(false);
}
}
void TownSpellsWidget::resetSpells()
{
town.possibleSpells.clear();
town.obligatorySpells.clear();
for (auto spell : VLC->spellh->objects)
{
if (!spell->isSpecial() && !spell->isCreatureAbility())
town.possibleSpells.push_back(spell->id);
}
}
void TownSpellsWidget::initSpellLists()
{
QListWidget * possibleSpellLists[] = { ui->possibleSpellList1, ui->possibleSpellList2, ui->possibleSpellList3, ui->possibleSpellList4, ui->possibleSpellList5 };
QListWidget * requiredSpellLists[] = { ui->requiredSpellList1, ui->requiredSpellList2, ui->requiredSpellList3, ui->requiredSpellList4, ui->requiredSpellList5 };
auto spells = VLC->spellh->objects;
for (int i = 0; i < GameConstants::SPELL_LEVELS; i++)
{
std::vector<std::shared_ptr<CSpell>> spellsByLevel;
auto getSpellsByLevel = [i](auto spell) {
return spell->getLevel() == i + 1 && !spell->isSpecial() && !spell->isCreatureAbility();
};
vstd::copy_if(spells, std::back_inserter(spellsByLevel), getSpellsByLevel);
possibleSpellLists[i]->clear();
requiredSpellLists[i]->clear();
for (auto spell : spellsByLevel)
{
auto * possibleItem = new QListWidgetItem(QString::fromStdString(spell->getNameTranslated()));
possibleItem->setData(Qt::UserRole, QVariant::fromValue(spell->getIndex()));
possibleItem->setFlags(possibleItem->flags() | Qt::ItemIsUserCheckable);
possibleItem->setCheckState(vstd::contains(town.possibleSpells, spell->getId()) ? Qt::Checked : Qt::Unchecked);
possibleSpellLists[i]->addItem(possibleItem);
auto * requiredItem = new QListWidgetItem(QString::fromStdString(spell->getNameTranslated()));
requiredItem->setData(Qt::UserRole, QVariant::fromValue(spell->getIndex()));
requiredItem->setFlags(requiredItem->flags() | Qt::ItemIsUserCheckable);
requiredItem->setCheckState(vstd::contains(town.obligatorySpells, spell->getId()) ? Qt::Checked : Qt::Unchecked);
requiredSpellLists[i]->addItem(requiredItem);
}
}
}
void TownSpellsWidget::commitChanges()
{
if (!ui->tabWidget->isEnabled())
{
resetSpells();
return;
}
town.possibleSpells.clear();
town.obligatorySpells.clear();
town.possibleSpells.push_back(SpellID::PRESET);
QListWidget * possibleSpellLists[] = { ui->possibleSpellList1, ui->possibleSpellList2, ui->possibleSpellList3, ui->possibleSpellList4, ui->possibleSpellList5 };
QListWidget * requiredSpellLists[] = { ui->requiredSpellList1, ui->requiredSpellList2, ui->requiredSpellList3, ui->requiredSpellList4, ui->requiredSpellList5 };
for (auto spellList : possibleSpellLists)
{
for (int i = 0; i < spellList->count(); i++)
{
auto * item = spellList->item(i);
if (item->checkState() == Qt::Checked)
{
town.possibleSpells.push_back(item->data(Qt::UserRole).toInt());
}
}
}
for (auto spellList : requiredSpellLists)
{
for (int i = 0; i < spellList->count(); i++)
{
auto * item = spellList->item(i);
if (item->checkState() == Qt::Checked)
{
town.obligatorySpells.push_back(item->data(Qt::UserRole).toInt());
}
}
}
}
void TownSpellsWidget::on_customizeSpells_toggled(bool checked)
{
if (checked)
{
town.possibleSpells.push_back(SpellID::PRESET);
}
else
{
resetSpells();
}
ui->tabWidget->setEnabled(checked);
initSpellLists();
}
TownSpellsDelegate::TownSpellsDelegate(CGTownInstance & town) : town(town), QStyledItemDelegate()
{
}
QWidget * TownSpellsDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
return new TownSpellsWidget(town, parent);
}
void TownSpellsDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const
{
if (auto * ed = qobject_cast<TownSpellsWidget *>(editor))
{
ed->obtainData();
}
else
{
QStyledItemDelegate::setEditorData(editor, index);
}
}
void TownSpellsDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
{
if (auto * ed = qobject_cast<TownSpellsWidget *>(editor))
{
ed->commitChanges();
}
else
{
QStyledItemDelegate::setModelData(editor, model, index);
}
}

View File

@ -0,0 +1,57 @@
/*
* townspellswidget.h, part of VCMI engine
*
* 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
*
*/
#pragma once
#include <QDialog>
#include "../../lib/mapObjects/CGTownInstance.h"
namespace Ui {
class TownSpellsWidget;
}
class TownSpellsWidget : public QDialog
{
Q_OBJECT
public:
explicit TownSpellsWidget(CGTownInstance &, QWidget * parent = nullptr);
~TownSpellsWidget();
void obtainData();
void commitChanges();
private slots:
void on_customizeSpells_toggled(bool checked);
private:
Ui::TownSpellsWidget * ui;
CGTownInstance & town;
void resetSpells();
void initSpellLists();
};
class TownSpellsDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
using QStyledItemDelegate::QStyledItemDelegate;
TownSpellsDelegate(CGTownInstance&);
QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex& index) const override;
void setEditorData(QWidget * editor, const QModelIndex & index) const override;
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
private:
CGTownInstance& town;
};

View File

@ -0,0 +1,304 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TownSpellsWidget</class>
<widget class="QDialog" name="TownSpellsWidget">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>480</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>480</height>
</size>
</property>
<property name="windowTitle">
<string>Spells</string>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>10</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<item>
<widget class="QCheckBox" name="customizeSpells">
<property name="text">
<string>Customize spells</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="documentMode">
<bool>true</bool>
</property>
<widget class="QWidget" name="level1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Level 1</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_level1">
<property name="leftMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout1">
<item row="0" column="0">
<widget class="QLabel" name="possibleSpellsText1">
<property name="text">
<string>Spell that may appear in mage guild</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="requiredSpellsText1">
<property name="text">
<string>Spell that must appear in mage guild</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QListWidget" name="possibleSpellList1"/>
</item>
<item row="1" column="1">
<widget class="QListWidget" name="requiredSpellList1"/>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="level2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Level 2</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_level2">
<property name="leftMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout2">
<item row="0" column="0">
<widget class="QLabel" name="possibleSpellsText2">
<property name="text">
<string>Spell that may appear in mage guild</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="requiredSpellsText2">
<property name="text">
<string>Spell that must appear in mage guild</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QListWidget" name="possibleSpellList2"/>
</item>
<item row="1" column="1">
<widget class="QListWidget" name="requiredSpellList2"/>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="level3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Level 3</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_level3">
<property name="leftMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout3">
<item row="0" column="0">
<widget class="QLabel" name="possibleSpellsText3">
<property name="text">
<string>Spell that may appear in mage guild</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="requiredSpellsText3">
<property name="text">
<string>Spell that must appear in mage guild</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QListWidget" name="possibleSpellList3"/>
</item>
<item row="1" column="1">
<widget class="QListWidget" name="requiredSpellList3"/>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="level4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Level 4</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_level4">
<property name="leftMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout4">
<item row="0" column="0">
<widget class="QLabel" name="possibleSpellsText4">
<property name="text">
<string>Spell that may appear in mage guild</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="requiredSpellsText4">
<property name="text">
<string>Spell that must appear in mage guild</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QListWidget" name="possibleSpellList4"/>
</item>
<item row="1" column="1">
<widget class="QListWidget" name="requiredSpellList4"/>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="level5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Level 5</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_level5">
<property name="leftMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout5">
<item row="0" column="0">
<widget class="QLabel" name="possibleSpellsText5">
<property name="text">
<string>Spell that may appear in mage guild</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="requiredSpellsText5">
<property name="text">
<string>Spell that must appear in mage guild</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QListWidget" name="possibleSpellList5"/>
</item>
<item row="1" column="1">
<widget class="QListWidget" name="requiredSpellList5"/>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>