1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

New quests implemented

This commit is contained in:
nordsoft 2023-10-09 15:54:14 +02:00
parent 3a17eeb330
commit 63bdfb8ff6
8 changed files with 1196 additions and 162 deletions

View File

@ -46,7 +46,8 @@ CQuest::CQuest():
stackDirection(0),
isCustomFirst(false),
isCustomNext(false),
isCustomComplete(false)
isCustomComplete(false),
repeatedQuest(false)
{
}
@ -444,6 +445,7 @@ void CQuest::serializeJson(JsonSerializeFormat & handler, const std::string & fi
handler.serializeStruct("firstVisitText", firstVisitText);
handler.serializeStruct("nextVisitText", nextVisitText);
handler.serializeStruct("completedText", completedText);
handler.serializeBool("repeatedQuest", repeatedQuest, false);
if(!handler.saving)
{

View File

@ -53,6 +53,7 @@ public:
Eprogress progress;
si32 lastDay; //after this day (first day is 0) mission cannot be completed; if -1 - no limit
int killTarget;
bool repeatedQuest;
// following fields are used only for kill creature/hero missions, the original
// objects became inaccessible after their removal, so we need to store info

View File

@ -410,7 +410,7 @@ void Inspector::updateProperties(CGEvent * o)
void Inspector::updateProperties(CGSeerHut * o)
{
if(!o) return;
if(!o || !o->quest) return;
{ //Mission type
auto * delegate = new InspectorDelegate;
@ -421,9 +421,10 @@ void Inspector::updateProperties(CGSeerHut * o)
addProperty("First visit text", o->quest->firstVisitText, new MessageDelegate, false);
addProperty("Next visit text", o->quest->nextVisitText, new MessageDelegate, false);
addProperty("Completed text", o->quest->completedText, new MessageDelegate, false);
addProperty("Repeat quest", o->quest->repeatedQuest, false);
{ //Quest
auto * delegate = new QuestDelegate(*controller.map(), *o);
auto * delegate = new QuestDelegate(controller, *o->quest);
addProperty("Quest", PropertyEditorPlaceholder(), delegate, false);
}
}

View File

@ -10,21 +10,122 @@
#include "StdInc.h"
#include "questwidget.h"
#include "ui_questwidget.h"
#include "../mapcontroller.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/CSkillHandler.h"
#include "../lib/spells/CSpellHandler.h"
#include "../lib/CArtHandler.h"
#include "../lib/CCreatureHandler.h"
#include "../lib/CHeroHandler.h"
#include "../lib/constants/StringConstants.h"
#include "../lib/mapping/CMap.h"
#include "../lib/mapObjects/CGHeroInstance.h"
#include "../lib/mapObjects/CGCreature.h"
QuestWidget::QuestWidget(const CMap & _map, CGSeerHut & _sh, QWidget *parent) :
QuestWidget::QuestWidget(MapController & _controller, CQuest & _sh, QWidget *parent) :
QDialog(parent),
map(_map),
seerhut(_sh),
controller(_controller),
quest(_sh),
ui(new Ui::QuestWidget)
{
setAttribute(Qt::WA_DeleteOnClose, true);
ui->setupUi(this);
ui->lDayOfWeek->addItem(tr("None"));
for(int i = 1; i <= 7; ++i)
ui->lDayOfWeek->addItem(tr("Day %1").arg(i));
//fill resources
ui->lResources->setRowCount(GameConstants::RESOURCE_QUANTITY - 1);
for(int i = 0; i < GameConstants::RESOURCE_QUANTITY - 1; ++i)
{
auto * item = new QTableWidgetItem(QString::fromStdString(GameConstants::RESOURCE_NAMES[i]));
item->setData(Qt::UserRole, QVariant::fromValue(i));
ui->lResources->setItem(i, 0, item);
ui->lResources->setCellWidget(i, 1, new QSpinBox);
}
//fill artifacts
for(int i = 0; i < controller.map()->allowedArtifact.size(); ++i)
{
auto * item = new QListWidgetItem(QString::fromStdString(VLC->artifacts()->getByIndex(i)->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(i));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
if(!controller.map()->allowedArtifact[i])
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
ui->lArtifacts->addItem(item);
}
//fill spells
for(int i = 0; i < controller.map()->allowedSpells.size(); ++i)
{
auto * item = new QListWidgetItem(QString::fromStdString(VLC->spells()->getByIndex(i)->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(i));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
if(!controller.map()->allowedSpells[i])
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
ui->lSpells->addItem(item);
}
//fill skills
ui->lSkills->setRowCount(controller.map()->allowedAbilities.size());
for(int i = 0; i < controller.map()->allowedAbilities.size(); ++i)
{
auto * item = new QTableWidgetItem(QString::fromStdString(VLC->skills()->getByIndex(i)->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(i));
auto * widget = new QComboBox;
for(auto & s : NSecondarySkill::levels)
widget->addItem(QString::fromStdString(s));
if(!controller.map()->allowedAbilities[i])
{
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
widget->setEnabled(false);
}
ui->lSkills->setItem(i, 0, item);
ui->lSkills->setCellWidget(i, 1, widget);
}
//fill creatures
for(auto & creature : VLC->creh->objects)
{
ui->lCreatureId->addItem(QString::fromStdString(creature->getNameSingularTranslated()));
ui->lCreatureId->setItemData(ui->lCreatureId->count() - 1, creature->getIndex());
}
//fill heroes
VLC->heroTypes()->forEach([this](const HeroType * hero, bool &)
{
auto * item = new QListWidgetItem(QString::fromStdString(hero->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(hero->getId().getNum()));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
ui->lHeroes->addItem(item);
});
//fill hero classes
VLC->heroClasses()->forEach([this](const HeroClass * heroClass, bool &)
{
auto * item = new QListWidgetItem(QString::fromStdString(heroClass->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(heroClass->getId().getNum()));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
ui->lHeroClasses->addItem(item);
});
//fill players
for(auto color = PlayerColor(0); color < PlayerColor::PLAYER_LIMIT; ++color)
{
auto * item = new QListWidgetItem(QString::fromStdString(GameConstants::PLAYER_COLOR_NAMES[color.getNum()]));
item->setData(Qt::UserRole, QVariant::fromValue(color.getNum()));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
ui->lPlayers->addItem(item);
}
}
QuestWidget::~QuestWidget()
@ -34,137 +135,259 @@ QuestWidget::~QuestWidget()
void QuestWidget::obtainData()
{
assert(seerhut.quest);
bool activeId = false;
bool activeAmount = false;
switch(seerhut.quest->missionType) {
case CQuest::Emission::MISSION_LEVEL:
activeAmount = true;
ui->targetId->addItem("Reach level");
ui->targetAmount->setText(QString::number(seerhut.quest->m13489val));
break;
case CQuest::Emission::MISSION_PRIMARY_STAT:
activeId = true;
activeAmount = true;
for(auto s : NPrimarySkill::names)
ui->targetId->addItem(QString::fromStdString(s));
for(int i = 0; i < seerhut.quest->m2stats.size(); ++i)
ui->lDayOfWeek->setCurrentIndex(quest.dayOfWeek);
ui->lDaysPassed->setValue(quest.daysPassed);
ui->lHeroLevel->setValue(quest.heroLevel);
ui->lHeroExperience->setValue(quest.heroExperience);
ui->lManaPoints->setValue(quest.manaPoints);
ui->lManaPercentage->setValue(quest.manaPercentage);
ui->lAttack->setValue(quest.primary[0]);
ui->lDefence->setValue(quest.primary[1]);
ui->lPower->setValue(quest.primary[2]);
ui->lKnowledge->setValue(quest.primary[3]);
for(int i = 0; i < ui->lResources->rowCount(); ++i)
{
if(seerhut.quest->m2stats[i] > 0)
{
ui->targetId->setCurrentIndex(i);
ui->targetAmount->setText(QString::number(seerhut.quest->m2stats[i]));
break; //TODO: support multiple stats
}
}
break;
case CQuest::Emission::MISSION_KILL_HERO:
activeId = true;
//TODO: implement
break;
case CQuest::Emission::MISSION_KILL_CREATURE:
activeId = true;
//TODO: implement
break;
case CQuest::Emission::MISSION_ART:
activeId = true;
for(int i = 0; i < map.allowedArtifact.size(); ++i)
ui->targetId->addItem(QString::fromStdString(VLC->arth->objects.at(i)->getNameTranslated()));
if(!seerhut.quest->m5arts.empty())
ui->targetId->setCurrentIndex(seerhut.quest->m5arts.front());
//TODO: support multiple artifacts
break;
case CQuest::Emission::MISSION_ARMY:
activeId = true;
activeAmount = true;
break;
case CQuest::Emission::MISSION_RESOURCES:
activeId = true;
activeAmount = true;
for(auto s : GameConstants::RESOURCE_NAMES)
ui->targetId->addItem(QString::fromStdString(s));
for(int i = 0; i < seerhut.quest->m7resources.size(); ++i)
{
if(seerhut.quest->m7resources[i] > 0)
{
ui->targetId->setCurrentIndex(i);
ui->targetAmount->setText(QString::number(seerhut.quest->m7resources[i]));
break; //TODO: support multiple resources
}
}
break;
case CQuest::Emission::MISSION_HERO:
activeId = true;
for(int i = 0; i < map.allowedHeroes.size(); ++i)
ui->targetId->addItem(QString::fromStdString(VLC->heroh->objects.at(i)->getNameTranslated()));
ui->targetId->setCurrentIndex(seerhut.quest->m13489val);
break;
case CQuest::Emission::MISSION_PLAYER:
activeId = true;
for(auto s : GameConstants::PLAYER_COLOR_NAMES)
ui->targetId->addItem(QString::fromStdString(s));
ui->targetId->setCurrentIndex(seerhut.quest->m13489val);
break;
case CQuest::Emission::MISSION_KEYMASTER:
break;
default:
break;
if(auto * widget = qobject_cast<QSpinBox*>(ui->lResources->cellWidget(i, 1)))
widget->setValue(quest.resources[i]);
}
ui->targetId->setEnabled(activeId);
ui->targetAmount->setEnabled(activeAmount);
}
QString QuestWidget::commitChanges()
for(auto i : quest.artifacts)
ui->lArtifacts->item(VLC->artifacts()->getById(i)->getIndex())->setCheckState(Qt::Checked);
for(auto i : quest.spells)
ui->lArtifacts->item(VLC->spells()->getById(i)->getIndex())->setCheckState(Qt::Checked);
for(auto & i : quest.secondary)
{
assert(seerhut.quest);
switch(seerhut.quest->missionType) {
case CQuest::Emission::MISSION_LEVEL:
seerhut.quest->m13489val = ui->targetAmount->text().toInt();
return QString("Reach lvl ").append(ui->targetAmount->text());
case CQuest::Emission::MISSION_PRIMARY_STAT:
seerhut.quest->m2stats.resize(sizeof(NPrimarySkill::names), 0);
seerhut.quest->m2stats[ui->targetId->currentIndex()] = ui->targetAmount->text().toInt();
//TODO: support multiple stats
return ui->targetId->currentText().append(ui->targetAmount->text());
case CQuest::Emission::MISSION_KILL_HERO:
//TODO: implement
return QString("N/A");
case CQuest::Emission::MISSION_KILL_CREATURE:
//TODO: implement
return QString("N/A");
case CQuest::Emission::MISSION_ART:
seerhut.quest->m5arts.clear();
seerhut.quest->m5arts.push_back(ArtifactID(ui->targetId->currentIndex()));
//TODO: support multiple artifacts
return ui->targetId->currentText();
case CQuest::Emission::MISSION_ARMY:
//TODO: implement
return QString("N/A");
case CQuest::Emission::MISSION_RESOURCES:
seerhut.quest->m7resources[ui->targetId->currentIndex()] = ui->targetAmount->text().toInt();
//TODO: support resources
return ui->targetId->currentText().append(ui->targetAmount->text());
case CQuest::Emission::MISSION_HERO:
seerhut.quest->m13489val = ui->targetId->currentIndex();
return ui->targetId->currentText();
case CQuest::Emission::MISSION_PLAYER:
seerhut.quest->m13489val = ui->targetId->currentIndex();
return ui->targetId->currentText();
case CQuest::Emission::MISSION_KEYMASTER:
return QString("N/A");
default:
return QString("N/A");
int index = VLC->skills()->getById(i.first)->getIndex();
if(auto * widget = qobject_cast<QComboBox*>(ui->lSkills->cellWidget(index, 1)))
widget->setCurrentIndex(i.second);
}
for(auto & i : quest.creatures)
{
int index = i.type->getIndex();
ui->lCreatureId->setCurrentIndex(index);
ui->lCreatureAmount->setValue(i.count);
onCreatureAdd(ui->lCreatures, ui->lCreatureId, ui->lCreatureAmount);
}
for(auto & i : quest.heroes)
{
for(int e = 0; e < ui->lHeroes->count(); ++e)
{
if(ui->lHeroes->item(e)->data(Qt::UserRole).toInt() == i.getNum())
{
ui->lHeroes->item(e)->setCheckState(Qt::Checked);
break;
}
}
}
for(auto & i : quest.heroClasses)
{
for(int e = 0; e < ui->lHeroClasses->count(); ++e)
{
if(ui->lHeroClasses->item(e)->data(Qt::UserRole).toInt() == i.getNum())
{
ui->lHeroClasses->item(e)->setCheckState(Qt::Checked);
break;
}
}
}
for(auto & i : quest.players)
{
for(int e = 0; e < ui->lPlayers->count(); ++e)
{
if(ui->lPlayers->item(e)->data(Qt::UserRole).toInt() == i.getNum())
{
ui->lPlayers->item(e)->setCheckState(Qt::Checked);
break;
}
}
}
QuestDelegate::QuestDelegate(const CMap & m, CGSeerHut & t): map(m), seerhut(t), QStyledItemDelegate()
if(quest.killTarget >= 0 && quest.killTarget < controller.map()->objects.size())
ui->lKillTarget->setText(QString::fromStdString(controller.map()->objects[quest.killTarget]->instanceName));
else
quest.killTarget = -1;
}
bool QuestWidget::commitChanges()
{
quest.dayOfWeek = ui->lDayOfWeek->currentIndex();
quest.daysPassed = ui->lDaysPassed->value();
quest.heroLevel = ui->lHeroLevel->value();
quest.heroExperience = ui->lHeroExperience->value();
quest.manaPoints = ui->lManaPoints->value();
quest.manaPercentage = ui->lManaPercentage->value();
quest.primary[0] = ui->lAttack->value();
quest.primary[1] = ui->lDefence->value();
quest.primary[2] = ui->lPower->value();
quest.primary[3] = ui->lKnowledge->value();
for(int i = 0; i < ui->lResources->rowCount(); ++i)
{
if(auto * widget = qobject_cast<QSpinBox*>(ui->lResources->cellWidget(i, 1)))
quest.resources[i] = widget->value();
}
quest.artifacts.clear();
for(int i = 0; i < ui->lArtifacts->count(); ++i)
{
if(ui->lArtifacts->item(i)->checkState() == Qt::Checked)
quest.artifacts.push_back(VLC->artifacts()->getByIndex(i)->getId());
}
quest.spells.clear();
for(int i = 0; i < ui->lSpells->count(); ++i)
{
if(ui->lSpells->item(i)->checkState() == Qt::Checked)
quest.spells.push_back(VLC->spells()->getByIndex(i)->getId());
}
quest.secondary.clear();
for(int i = 0; i < ui->lSkills->rowCount(); ++i)
{
if(auto * widget = qobject_cast<QComboBox*>(ui->lSkills->cellWidget(i, 1)))
{
if(widget->currentIndex() > 0)
quest.secondary[VLC->skills()->getByIndex(i)->getId()] = widget->currentIndex();
}
}
quest.creatures.clear();
for(int i = 0; i < ui->lCreatures->rowCount(); ++i)
{
int index = ui->lCreatures->item(i, 0)->data(Qt::UserRole).toInt();
if(auto * widget = qobject_cast<QSpinBox*>(ui->lCreatures->cellWidget(i, 1)))
if(widget->value())
quest.creatures.emplace_back(VLC->creatures()->getByIndex(index)->getId(), widget->value());
}
quest.heroes.clear();
for(int i = 0; i < ui->lHeroes->count(); ++i)
{
if(ui->lHeroes->item(i)->checkState() == Qt::Checked)
quest.heroes.emplace_back(ui->lHeroes->item(i)->data(Qt::UserRole).toInt());
}
quest.heroClasses.clear();
for(int i = 0; i < ui->lHeroClasses->count(); ++i)
{
if(ui->lHeroClasses->item(i)->checkState() == Qt::Checked)
quest.heroClasses.emplace_back(ui->lHeroClasses->item(i)->data(Qt::UserRole).toInt());
}
quest.players.clear();
for(int i = 0; i < ui->lPlayers->count(); ++i)
{
if(ui->lPlayers->item(i)->checkState() == Qt::Checked)
quest.players.emplace_back(ui->lPlayers->item(i)->data(Qt::UserRole).toInt());
}
//quest.killTarget is set directly in object picking
return true;
}
void QuestWidget::onCreatureAdd(QTableWidget * listWidget, QComboBox * comboWidget, QSpinBox * spinWidget)
{
QTableWidgetItem * item = nullptr;
QSpinBox * widget = nullptr;
for(int i = 0; i < listWidget->rowCount(); ++i)
{
if(auto * cname = listWidget->item(i, 0))
{
if(cname->data(Qt::UserRole).toInt() == comboWidget->currentData().toInt())
{
item = cname;
widget = qobject_cast<QSpinBox*>(listWidget->cellWidget(i, 1));
break;
}
}
}
if(!item)
{
listWidget->setRowCount(listWidget->rowCount() + 1);
item = new QTableWidgetItem(comboWidget->currentText());
listWidget->setItem(listWidget->rowCount() - 1, 0, item);
}
item->setData(Qt::UserRole, comboWidget->currentData());
if(!widget)
{
widget = new QSpinBox;
widget->setRange(spinWidget->minimum(), spinWidget->maximum());
listWidget->setCellWidget(listWidget->rowCount() - 1, 1, widget);
}
widget->setValue(spinWidget->value());
}
void QuestWidget::on_lKillTargetSelect_clicked()
{
auto pred = [](const CGObjectInstance * obj) -> bool
{
if(auto * o = dynamic_cast<const CGHeroInstance*>(obj))
return o->ID != Obj::PRISON;
if(auto * o = dynamic_cast<const CGCreature*>(obj))
return true;
return false;
};
for(int lvl : {0, 1})
{
auto & l = controller.scene(lvl)->objectPickerView;
l.highlight(pred);
l.update();
QObject::connect(&l, &ObjectPickerLayer::selectionMade, this, &QuestWidget::onTargetPicked);
}
hide();
}
void QuestWidget::onTargetPicked(const CGObjectInstance * obj)
{
show();
for(int lvl : {0, 1})
{
auto & l = controller.scene(lvl)->objectPickerView;
l.clear();
l.update();
QObject::disconnect(&l, &ObjectPickerLayer::selectionMade, this, &QuestWidget::onTargetPicked);
}
if(!obj) //discarded
{
quest.killTarget = -1;
ui->lKillTarget->setText("");
return;
}
ui->lKillTarget->setText(QString::fromStdString(obj->instanceName));
quest.killTarget = obj->id;
}
void QuestWidget::on_lCreatureAdd_clicked()
{
onCreatureAdd(ui->lCreatures, ui->lCreatureId, ui->lCreatureAmount);
}
void QuestWidget::on_lCreatureRemove_clicked()
{
std::set<int, std::greater<int>> rowsToRemove;
for(auto * i : ui->lCreatures->selectedItems())
rowsToRemove.insert(i->row());
for(auto i : rowsToRemove)
ui->lCreatures->removeRow(i);
}
QuestDelegate::QuestDelegate(MapController & c, CQuest & t): controller(c), quest(t), QStyledItemDelegate()
{
}
QWidget * QuestDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
return new QuestWidget(map, seerhut, parent);
return new QuestWidget(controller, quest, parent);
}
void QuestDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const
@ -183,11 +406,26 @@ void QuestDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, c
{
if(auto *ed = qobject_cast<QuestWidget *>(editor))
{
auto quest = ed->commitChanges();
model->setData(index, quest);
ed->commitChanges();
}
else
{
QStyledItemDelegate::setModelData(editor, model, index);
}
}
bool QuestDelegate::eventFilter(QObject * object, QEvent * event)
{
if(auto * ed = qobject_cast<QuestWidget *>(object))
{
if(event->type() == QEvent::Hide || event->type() == QEvent::FocusOut)
return false;
if(event->type() == QEvent::Close)
{
emit commitData(ed);
emit closeEditor(ed);
return true;
}
}
return QStyledItemDelegate::eventFilter(object, event);
}

View File

@ -16,20 +16,33 @@ namespace Ui {
class QuestWidget;
}
class MapController;
class QuestWidget : public QDialog
{
Q_OBJECT
public:
explicit QuestWidget(const CMap &, CGSeerHut &, QWidget *parent = nullptr);
explicit QuestWidget(MapController &, CQuest &, QWidget *parent = nullptr);
~QuestWidget();
void obtainData();
QString commitChanges();
bool commitChanges();
private slots:
void onTargetPicked(const CGObjectInstance *);
void on_lKillTargetSelect_clicked();
void on_lCreatureAdd_clicked();
void on_lCreatureRemove_clicked();
private:
CGSeerHut & seerhut;
const CMap & map;
void onCreatureAdd(QTableWidget * listWidget, QComboBox * comboWidget, QSpinBox * spinWidget);
CQuest & quest;
MapController & controller;
Ui::QuestWidget *ui;
};
@ -39,13 +52,16 @@ class QuestDelegate : public QStyledItemDelegate
public:
using QStyledItemDelegate::QStyledItemDelegate;
QuestDelegate(const CMap &, CGSeerHut &);
QuestDelegate(MapController &, CQuest &);
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;
protected:
bool eventFilter(QObject * object, QEvent * event) override;
private:
CGSeerHut & seerhut;
const CMap & map;
CQuest & quest;
MapController & controller;
};

View File

@ -9,8 +9,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>429</width>
<height>89</height>
<width>531</width>
<height>495</height>
</rect>
</property>
<property name="windowTitle">
@ -19,9 +19,448 @@
<property name="modal">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QComboBox" name="targetId">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Day of week</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="lDayOfWeek">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Days passed</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lDaysPassed">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="label_14">
<property name="text">
<string>Hero level</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lHeroLevel">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_15">
<property name="text">
<string>Hero experience</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lHeroExperience">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Spell points</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lManaPoints">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lManaPercentage">
<property name="suffix">
<string>%</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Kill hero/monster</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lKillTarget">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="lKillTargetSelect">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Primary skills</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>12</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Attack</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lAttack"/>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>Defence</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lDefence"/>
</item>
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>Spell power</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lPower"/>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>Knowledge</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lKnowledge"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget_2">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="elideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<property name="tabBarAutoHide">
<bool>true</bool>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Resources</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QTableWidget" name="lResources">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>180</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>24</number>
</attribute>
<column/>
<column/>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Artifacts</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QListWidget" name="lArtifacts">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_5">
<attribute name="title">
<string>Spells</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QListWidget" name="lSpells">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_7">
<attribute name="title">
<string>Skills</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QTableWidget" name="lSkills">
<property name="columnCount">
<number>2</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>180</number>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>24</number>
</attribute>
<column/>
<column/>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_6">
<attribute name="title">
<string>Creatures</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QComboBox" name="lCreatureId">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -31,22 +470,165 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="targetAmount">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<widget class="QSpinBox" name="lCreatureAmount">
<property name="minimumSize">
<size>
<width>60</width>
<height>16777215</height>
<height>0</height>
</size>
</property>
<property name="inputMethodHints">
<set>Qt::ImhDigitsOnly</set>
<property name="maximum">
<number>9999</number>
</property>
<property name="stepType">
<enum>QAbstractSpinBox::AdaptiveDecimalStepType</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="lCreatureAdd">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="lCreatureRemove">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTableWidget" name="lCreatures">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>180</number>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>24</number>
</attribute>
<column/>
<column/>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Heroes</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QListWidget" name="lHeroes">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Hero classes</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QListWidget" name="lHeroClasses">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_8">
<attribute name="title">
<string>Players</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QListWidget" name="lPlayers">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -13,6 +13,7 @@
#include "../lib/VCMI_Lib.h"
#include "../lib/CSkillHandler.h"
#include "../lib/spells/CSpellHandler.h"
#include "../lib/CHeroHandler.h"
#include "../lib/CArtHandler.h"
#include "../lib/CCreatureHandler.h"
#include "../lib/constants/StringConstants.h"
@ -131,6 +132,36 @@ RewardsWidget::RewardsWidget(CMap & m, CRewardableObject & p, QWidget *parent) :
}
}
//fill heroes
VLC->heroTypes()->forEach([this](const HeroType * hero, bool &)
{
auto * item = new QListWidgetItem(QString::fromStdString(hero->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(hero->getId().getNum()));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
ui->lHeroes->addItem(item);
});
//fill hero classes
VLC->heroClasses()->forEach([this](const HeroClass * heroClass, bool &)
{
auto * item = new QListWidgetItem(QString::fromStdString(heroClass->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(heroClass->getId().getNum()));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
ui->lHeroClasses->addItem(item);
});
//fill players
for(auto color = PlayerColor(0); color < PlayerColor::PLAYER_LIMIT; ++color)
{
auto * item = new QListWidgetItem(QString::fromStdString(GameConstants::PLAYER_COLOR_NAMES[color.getNum()]));
item->setData(Qt::UserRole, QVariant::fromValue(color.getNum()));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
ui->lPlayers->addItem(item);
}
//fill spell cast
for(auto & s : NSecondarySkill::levels)
ui->castLevel->addItem(QString::fromStdString(s));
@ -349,6 +380,27 @@ void RewardsWidget::saveCurrentVisitInfo(int index)
if(widget->value())
vinfo.limiter.creatures.emplace_back(VLC->creatures()->getByIndex(index)->getId(), widget->value());
}
vinfo.limiter.heroes.clear();
for(int i = 0; i < ui->lHeroes->count(); ++i)
{
if(ui->lHeroes->item(i)->checkState() == Qt::Checked)
vinfo.limiter.heroes.emplace_back(ui->lHeroes->item(i)->data(Qt::UserRole).toInt());
}
vinfo.limiter.heroClasses.clear();
for(int i = 0; i < ui->lHeroClasses->count(); ++i)
{
if(ui->lHeroClasses->item(i)->checkState() == Qt::Checked)
vinfo.limiter.heroClasses.emplace_back(ui->lHeroClasses->item(i)->data(Qt::UserRole).toInt());
}
vinfo.limiter.players.clear();
for(int i = 0; i < ui->lPlayers->count(); ++i)
{
if(ui->lPlayers->item(i)->checkState() == Qt::Checked)
vinfo.limiter.players.emplace_back(ui->lPlayers->item(i)->data(Qt::UserRole).toInt());
}
}
void RewardsWidget::loadCurrentVisitInfo(int index)
@ -472,6 +524,40 @@ void RewardsWidget::loadCurrentVisitInfo(int index)
ui->lCreatureAmount->setValue(i.count);
onCreatureAdd(ui->lCreatures, ui->lCreatureId, ui->lCreatureAmount);
}
for(auto & i : vinfo.limiter.heroes)
{
for(int e = 0; e < ui->lHeroes->count(); ++e)
{
if(ui->lHeroes->item(e)->data(Qt::UserRole).toInt() == i.getNum())
{
ui->lHeroes->item(e)->setCheckState(Qt::Checked);
break;
}
}
}
for(auto & i : vinfo.limiter.heroClasses)
{
for(int e = 0; e < ui->lHeroClasses->count(); ++e)
{
if(ui->lHeroClasses->item(e)->data(Qt::UserRole).toInt() == i.getNum())
{
ui->lHeroClasses->item(e)->setCheckState(Qt::Checked);
break;
}
}
}
for(auto & i : vinfo.limiter.players)
{
for(int e = 0; e < ui->lPlayers->count(); ++e)
{
if(ui->lPlayers->item(e)->data(Qt::UserRole).toInt() == i.getNum())
{
ui->lPlayers->item(e)->setCheckState(Qt::Checked);
break;
}
}
}
}
void RewardsWidget::onCreatureAdd(QTableWidget * listWidget, QComboBox * comboWidget, QSpinBox * spinWidget)

View File

@ -487,6 +487,12 @@
<property name="currentIndex">
<number>0</number>
</property>
<property name="elideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
</property>
<property name="tabBarAutoHide">
<bool>true</bool>
</property>
@ -843,7 +849,7 @@
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>21</number>
<number>24</number>
</attribute>
<column>
<property name="text">
@ -1185,6 +1191,12 @@
<property name="currentIndex">
<number>0</number>
</property>
<property name="elideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
</property>
<property name="tabBarAutoHide">
<bool>true</bool>
</property>
@ -1229,7 +1241,7 @@
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>21</number>
<number>24</number>
</attribute>
<column/>
<column/>
@ -1333,7 +1345,7 @@
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>21</number>
<number>24</number>
</attribute>
<column/>
<column/>
@ -1429,7 +1441,7 @@
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>21</number>
<number>24</number>
</attribute>
<column/>
<column/>
@ -1437,6 +1449,102 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Heroes</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_29">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QListWidget" name="lHeroes">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Hero classes</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_30">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QListWidget" name="lHeroClasses">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_15">
<attribute name="title">
<string>Players</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_31">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QListWidget" name="lPlayers">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>