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

map editor: Allow to customize hero spells

This commit is contained in:
godric3 2024-03-24 10:01:20 +01:00
parent a373ec6743
commit acceca0139
8 changed files with 469 additions and 7 deletions

View File

@ -362,6 +362,10 @@ const HeroType * HeroTypeID::toEntity(const Services * services) const
si32 SpellID::decode(const std::string & identifier)
{
if (identifier == "preset")
return SpellID::PRESET;
if (identifier == "spellbook_preset")
return SpellID::SPELLBOOK_PRESET;
return resolveIdentifier("spell", identifier);
}
@ -369,6 +373,10 @@ std::string SpellID::encode(const si32 index)
{
if (index == -1)
return "";
if (index == SpellID::PRESET)
return "preset";
if (index == SpellID::SPELLBOOK_PRESET)
return "spellbook_preset";
return VLC->spells()->getByIndex(index)->getJsonKey();
}

View File

@ -83,6 +83,8 @@ CIdentifierStorage::CIdentifierStorage()
registerObject(ModScope::scopeBuiltin(), "bonusSubtype", "creatureLevel5", 5);
registerObject(ModScope::scopeBuiltin(), "bonusSubtype", "creatureLevel6", 6);
registerObject(ModScope::scopeBuiltin(), "bonusSubtype", "creatureLevel7", 7);
registerObject(ModScope::scopeBuiltin(), "spell", "preset", SpellID::PRESET);
registerObject(ModScope::scopeBuiltin(), "spell", "spellbook_preset", SpellID::SPELLBOOK_PRESET);
}
void CIdentifierStorage::checkIdentifier(std::string & ID)

View File

@ -34,6 +34,7 @@ set(editor_SRCS
inspector/rewardswidget.cpp
inspector/questwidget.cpp
inspector/heroskillswidget.cpp
inspector/herospellwidget.cpp
inspector/PickObjectDelegate.cpp
inspector/portraitwidget.cpp
resourceExtractor/ResourceConverter.cpp
@ -74,6 +75,7 @@ set(editor_HEADERS
inspector/rewardswidget.h
inspector/questwidget.h
inspector/heroskillswidget.h
inspector/herospellwidget.h
inspector/PickObjectDelegate.h
inspector/portraitwidget.h
resourceExtractor/ResourceConverter.h
@ -101,6 +103,7 @@ set(editor_FORMS
inspector/rewardswidget.ui
inspector/questwidget.ui
inspector/heroskillswidget.ui
inspector/herospellwidget.ui
inspector/portraitwidget.ui
)

View File

@ -0,0 +1,133 @@
/*
* herosspellwidget.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 "herospellwidget.h"
#include "ui_herospellwidget.h"
#include "inspector.h"
#include "../../lib/constants/StringConstants.h"
#include "../../lib/spells/CSpellHandler.h"
HeroSpellWidget::HeroSpellWidget(CGHeroInstance & h, QWidget * parent) :
QDialog(parent),
ui(new Ui::HeroSpellWidget),
hero(h)
{
ui->setupUi(this);
}
HeroSpellWidget::~HeroSpellWidget()
{
delete ui;
}
void HeroSpellWidget::obtainData()
{
initSpellLists();
if (hero.spellbookContainsSpell(SpellID::PRESET)) {
ui->customizeSpells->setChecked(true);
}
else
{
ui->customizeSpells->setChecked(false);
ui->tabWidget->setEnabled(false);
}
}
void HeroSpellWidget::initSpellLists()
{
QListWidget * spellLists[] = { ui->spellList1, ui->spellList2, ui->spellList3, ui->spellList4, ui->spellList5 };
auto spells = VLC->spellh->objects;
for (int i = 0; i < 5; i++)
{
std::vector<ConstTransitivePtr<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);
spellLists[i]->clear();
for (auto spell : spellsByLevel)
{
auto* item = new QListWidgetItem(QString::fromStdString(spell->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(spell->getIndex()));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(hero.spellbookContainsSpell(spell->getId()) ? Qt::Checked : Qt::Unchecked);
spellLists[i]->addItem(item);
}
}
}
void HeroSpellWidget::commitChanges()
{
QListWidget * spellLists[] = { ui->spellList1, ui->spellList2, ui->spellList3, ui->spellList4, ui->spellList5 };
for (auto spellList : spellLists)
{
for (int i = 0; i < spellList->count(); i++)
{
auto * item = spellList->item(i);
if (item->checkState() == Qt::Checked)
{
hero.addSpellToSpellbook(item->data(Qt::UserRole).toInt());
}
else
{
hero.removeSpellFromSpellbook(item->data(Qt::UserRole).toInt());
}
}
}
}
void HeroSpellWidget::on_customizeSpells_toggled(bool checked)
{
if (checked)
{
hero.addSpellToSpellbook(SpellID::PRESET);
}
else
{
hero.removeSpellFromSpellbook(SpellID::PRESET);
hero.removeSpellbook();
}
ui->tabWidget->setEnabled(checked);
initSpellLists();
}
HeroSpellDelegate::HeroSpellDelegate(CGHeroInstance & h) : hero(h), QStyledItemDelegate()
{
}
QWidget * HeroSpellDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
return new HeroSpellWidget(hero, parent);
}
void HeroSpellDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const
{
if (auto * ed = qobject_cast<HeroSpellWidget *>(editor))
{
ed->obtainData();
}
else
{
QStyledItemDelegate::setEditorData(editor, index);
}
}
void HeroSpellDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
{
if (auto * ed = qobject_cast<HeroSpellWidget *>(editor))
{
ed->commitChanges();
}
else
{
QStyledItemDelegate::setModelData(editor, model, index);
}
}

View File

@ -0,0 +1,56 @@
/*
* herospellwidget.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/CGHeroInstance.h"
namespace Ui {
class HeroSpellWidget;
}
class HeroSpellWidget : public QDialog
{
Q_OBJECT
public:
explicit HeroSpellWidget(CGHeroInstance &, QWidget * parent = nullptr);
~HeroSpellWidget();
void obtainData();
void commitChanges();
private slots:
void on_customizeSpells_toggled(bool checked);
private:
Ui::HeroSpellWidget * ui;
CGHeroInstance & hero;
void initSpellLists();
};
class HeroSpellDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
using QStyledItemDelegate::QStyledItemDelegate;
HeroSpellDelegate(CGHeroInstance &);
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:
CGHeroInstance & hero;
};

View File

@ -0,0 +1,264 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>HeroSpellWidget</class>
<widget class="QDialog" name="HeroSpellWidget">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>635</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</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>
<widget class="QListWidget" name="spellList1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</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>
<widget class="QListWidget" name="spellList2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</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>
<widget class="QListWidget" name="spellList3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</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>
<widget class="QListWidget" name="spellList4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</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>
<widget class="QListWidget" name="spellList5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -26,6 +26,7 @@
#include "rewardswidget.h"
#include "questwidget.h"
#include "heroskillswidget.h"
#include "herospellwidget.h"
#include "portraitwidget.h"
#include "PickObjectDelegate.h"
#include "../mapcontroller.h"
@ -314,6 +315,7 @@ void Inspector::updateProperties(CGHeroInstance * o)
auto * delegate = new HeroSkillsDelegate(*o);
addProperty("Skills", PropertyEditorPlaceholder(), delegate, false);
addProperty("Spells", PropertyEditorPlaceholder(), new HeroSpellDelegate(*o), false);
if(o->type)
{ //Hero type

View File

@ -157,13 +157,7 @@ void MapController::repairMap(CMap * map) const
if(nih->ID == Obj::HERO) //not prison
nih->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
//fix spells
if(nih->spellbookContainsSpell(SpellID::PRESET))
{
nih->removeSpellFromSpellbook(SpellID::PRESET);
for(auto spellID : type->spells)
nih->addSpellToSpellbook(spellID);
}
//fix spellbook
if(nih->spellbookContainsSpell(SpellID::SPELLBOOK_PRESET))
{
nih->removeSpellFromSpellbook(SpellID::SPELLBOOK_PRESET);