mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-10 00:43:59 +02:00
Merge pull request #5030 from vcmi/timed_events_objects_removal
Timed events objects removal
This commit is contained in:
commit
3115894307
@ -403,6 +403,18 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
|
||||
localState->erasePath(hero);
|
||||
}
|
||||
|
||||
void CPlayerInterface::townRemoved(const CGTownInstance* town)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
|
||||
if(town->tempOwner == playerID)
|
||||
{
|
||||
localState->removeOwnedTown(town);
|
||||
adventureInt->onTownChanged(town);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CPlayerInterface::heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -1424,6 +1436,12 @@ void CPlayerInterface::objectRemoved(const CGObjectInstance * obj, const PlayerC
|
||||
const CGHeroInstance * h = static_cast<const CGHeroInstance *>(obj);
|
||||
heroKilled(h);
|
||||
}
|
||||
|
||||
if(obj->ID == Obj::TOWN && obj->tempOwner == playerID)
|
||||
{
|
||||
const CGTownInstance * t = static_cast<const CGTownInstance *>(obj);
|
||||
townRemoved(t);
|
||||
}
|
||||
GH.fakeMouseMove();
|
||||
}
|
||||
|
||||
|
@ -220,6 +220,7 @@ private:
|
||||
};
|
||||
|
||||
void heroKilled(const CGHeroInstance* hero);
|
||||
void townRemoved(const CGTownInstance* town);
|
||||
void garrisonsChanged(std::vector<const CArmedInstance *> objs);
|
||||
void requestReturningToMainMenu(bool won);
|
||||
void acceptTurn(QueryID queryID, bool hotseatWait); //used during hot seat after your turn message is close
|
||||
|
@ -378,6 +378,9 @@ void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
|
||||
|
||||
std::string CGTownInstance::getObjectName() const
|
||||
{
|
||||
if(ID == Obj::RANDOM_TOWN )
|
||||
return CGObjectInstance::getObjectName();
|
||||
|
||||
return getNameTranslated() + ", " + getTown()->faction->getNameTranslated();
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,12 @@ void FlaggableMapObject::onHeroVisit( const CGHeroInstance * h ) const
|
||||
giveBonusTo(h->getOwner());
|
||||
}
|
||||
|
||||
void FlaggableMapObject::markAsDeleted() const
|
||||
{
|
||||
if(getOwner().isValidPlayer())
|
||||
takeBonusFrom(getOwner());
|
||||
}
|
||||
|
||||
void FlaggableMapObject::initObj(vstd::RNG & rand)
|
||||
{
|
||||
if(getOwner().isValidPlayer())
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
using CGObjectInstance::CGObjectInstance;
|
||||
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void markAsDeleted() const;
|
||||
void initObj(vstd::RNG & rand) override;
|
||||
|
||||
const IOwnableObject * asOwnable() const final;
|
||||
|
@ -103,6 +103,9 @@ void CMapEvent::serializeJson(JsonSerializeFormat & handler)
|
||||
handler.serializeInt("firstOccurrence", firstOccurrence);
|
||||
handler.serializeInt("nextOccurrence", nextOccurrence);
|
||||
resources.serializeJson(handler, "resources");
|
||||
|
||||
auto deletedObjects = handler.enterArray("deletedObjectsInstances");
|
||||
deletedObjects.serializeArray(deletedObjectsInstances);
|
||||
}
|
||||
|
||||
void CCastleEvent::serializeJson(JsonSerializeFormat & handler)
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "../ResourceSet.h"
|
||||
#include "../texts/MetaString.h"
|
||||
#include "../int3.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -42,6 +43,8 @@ public:
|
||||
ui32 firstOccurrence;
|
||||
ui32 nextOccurrence; /// specifies after how many days the event will occur the next time; 0 if event occurs only one time
|
||||
|
||||
std::vector<ObjectInstanceID> deletedObjectsInstances;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
@ -64,6 +67,10 @@ public:
|
||||
h & computerAffected;
|
||||
h & firstOccurrence;
|
||||
h & nextOccurrence;
|
||||
if(h.version >= Handler::Version::EVENT_OBJECTS_DELETION)
|
||||
{
|
||||
h & deletedObjectsInstances;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void serializeJson(JsonSerializeFormat & handler);
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "mapObjectConstructors/CObjectClassesHandler.h"
|
||||
#include "campaign/CampaignState.h"
|
||||
#include "IGameSettings.h"
|
||||
#include "mapObjects/FlaggableMapObject.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -1184,7 +1185,6 @@ void RemoveBonus::applyGs(CGameState *gs)
|
||||
|
||||
void RemoveObject::applyGs(CGameState *gs)
|
||||
{
|
||||
|
||||
CGObjectInstance *obj = gs->getObjInstance(objectID);
|
||||
logGlobal->debug("removing object id=%d; address=%x; name=%s", objectID, (intptr_t)obj, obj->getObjectName());
|
||||
//unblock tiles
|
||||
@ -1197,10 +1197,7 @@ void RemoveObject::applyGs(CGameState *gs)
|
||||
{
|
||||
auto * beatenHero = dynamic_cast<CGHeroInstance *>(obj);
|
||||
assert(beatenHero);
|
||||
PlayerState * p = gs->getPlayerState(beatenHero->tempOwner);
|
||||
gs->map->heroesOnMap -= beatenHero;
|
||||
p->removeOwnedObject(beatenHero);
|
||||
|
||||
|
||||
auto * siegeNode = beatenHero->whereShouldBeAttachedOnSiege(gs);
|
||||
|
||||
@ -1254,6 +1251,18 @@ void RemoveObject::applyGs(CGameState *gs)
|
||||
}
|
||||
}
|
||||
|
||||
if(obj->getOwner().isValidPlayer())
|
||||
{
|
||||
gs->getPlayerState(obj->getOwner())->removeOwnedObject(obj); //object removed via map event or hero got beaten
|
||||
|
||||
FlaggableMapObject* flaggableObject = dynamic_cast<FlaggableMapObject*>(obj);
|
||||
if(flaggableObject)
|
||||
{
|
||||
flaggableObject->markAsDeleted();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gs->map->instanceNames.erase(obj->instanceName);
|
||||
gs->map->objects[objectID.getNum()].dellNull();
|
||||
gs->map->calculateGuardingGreaturePositions();//FIXME: excessive, update only affected tiles
|
||||
|
@ -69,6 +69,7 @@ enum class ESerializationVersion : int32_t
|
||||
FOLDER_NAME_REWORK, // 870 - rework foldername
|
||||
REWARDABLE_GUARDS, // 871 - fix missing serialization of guards in rewardable objects
|
||||
MARKET_TRANSLATION_FIX, // 872 - remove serialization of markets translateable strings
|
||||
EVENT_OBJECTS_DELETION, //873 - allow events to remove map objects
|
||||
|
||||
CURRENT = MARKET_TRANSLATION_FIX
|
||||
CURRENT = EVENT_OBJECTS_DELETION
|
||||
};
|
||||
|
@ -17,6 +17,7 @@ enum MapEditorRoles
|
||||
PlayerIDRole,
|
||||
BuildingIDRole,
|
||||
SpellIDRole,
|
||||
ObjectInstanceIDRole,
|
||||
ArtifactIDRole,
|
||||
ArtifactSlotRole
|
||||
ArtifactSlotRole,
|
||||
};
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
|
||||
Q_DECLARE_METATYPE(int3)
|
||||
|
||||
//parses date for lose condition (1m 1w 1d)
|
||||
int expiredDate(const QString & date);
|
||||
QString expiredDate(int date);
|
||||
|
@ -55,6 +55,28 @@ TResources resourcesFromVariant(const QVariant & v)
|
||||
return TResources(vJson);
|
||||
}
|
||||
|
||||
QVariant toVariant(std::vector<ObjectInstanceID> objects)
|
||||
{
|
||||
QVariantList result;
|
||||
for(auto obj : objects)
|
||||
{
|
||||
result.push_back(QVariant::fromValue(obj.num));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<ObjectInstanceID> deletedObjectsIdsFromVariant(const QVariant & v)
|
||||
{
|
||||
std::vector<ObjectInstanceID> result;
|
||||
for(auto idAsVariant : v.toList())
|
||||
{
|
||||
auto id = idAsVariant.value<int>();
|
||||
result.push_back(ObjectInstanceID(id));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant toVariant(const CMapEvent & event)
|
||||
{
|
||||
QVariantMap result;
|
||||
@ -66,6 +88,7 @@ QVariant toVariant(const CMapEvent & event)
|
||||
result["firstOccurrence"] = QVariant::fromValue(event.firstOccurrence);
|
||||
result["nextOccurrence"] = QVariant::fromValue(event.nextOccurrence);
|
||||
result["resources"] = toVariant(event.resources);
|
||||
result["deletedObjectsInstances"] = toVariant(event.deletedObjectsInstances);
|
||||
return QVariant(result);
|
||||
}
|
||||
|
||||
@ -81,6 +104,7 @@ CMapEvent eventFromVariant(CMapHeader & mapHeader, const QVariant & variant)
|
||||
result.firstOccurrence = v.value("firstOccurrence").toInt();
|
||||
result.nextOccurrence = v.value("nextOccurrence").toInt();
|
||||
result.resources = resourcesFromVariant(v.value("resources"));
|
||||
result.deletedObjectsInstances = deletedObjectsIdsFromVariant(v.value("deletedObjectsInstances"));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -137,6 +161,6 @@ void EventSettings::on_timedEventRemove_clicked()
|
||||
|
||||
void EventSettings::on_eventsList_itemActivated(QListWidgetItem *item)
|
||||
{
|
||||
new TimedEvent(item, parentWidget());
|
||||
new TimedEvent(*controller, item, parentWidget());
|
||||
}
|
||||
|
||||
|
@ -11,13 +11,15 @@
|
||||
#include "timedevent.h"
|
||||
#include "ui_timedevent.h"
|
||||
#include "eventsettings.h"
|
||||
#include "../mapeditorroles.h"
|
||||
#include "../../lib/constants/EntityIdentifiers.h"
|
||||
#include "../../lib/constants/StringConstants.h"
|
||||
|
||||
TimedEvent::TimedEvent(QListWidgetItem * t, QWidget *parent) :
|
||||
TimedEvent::TimedEvent(MapController & c, QListWidgetItem * t, QWidget *parent) :
|
||||
controller(c),
|
||||
QDialog(parent),
|
||||
target(t),
|
||||
ui(new Ui::TimedEvent)
|
||||
ui(new Ui::TimedEvent),
|
||||
target(t)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@ -51,7 +53,14 @@ TimedEvent::TimedEvent(QListWidgetItem * t, QWidget *parent) :
|
||||
nval->setFlags(nval->flags() | Qt::ItemIsEditable);
|
||||
ui->resources->setItem(i, 1, nval);
|
||||
}
|
||||
|
||||
auto deletedObjectInstances = params.value("deletedObjectsInstances").toList();
|
||||
for(auto const & idAsVariant : deletedObjectInstances)
|
||||
{
|
||||
auto id = ObjectInstanceID(idAsVariant.toInt());
|
||||
auto obj = controller.map()->objects[id];
|
||||
if(obj)
|
||||
insertObjectToDelete(obj);
|
||||
}
|
||||
show();
|
||||
}
|
||||
|
||||
@ -89,10 +98,63 @@ void TimedEvent::on_TimedEvent_finished(int result)
|
||||
}
|
||||
descriptor["resources"] = res;
|
||||
|
||||
QVariantList deletedObjects;
|
||||
for(int i = 0; i < ui->deletedObjects->count(); ++i)
|
||||
{
|
||||
auto const & item = ui->deletedObjects->item(i);
|
||||
auto data = item->data(MapEditorRoles::ObjectInstanceIDRole);
|
||||
auto id = ObjectInstanceID(data.value<int>());
|
||||
deletedObjects.push_back(QVariant::fromValue(id.num));
|
||||
}
|
||||
descriptor["deletedObjectsInstances"] = QVariant::fromValue(deletedObjects);
|
||||
|
||||
target->setData(Qt::UserRole, descriptor);
|
||||
target->setText(ui->eventNameText->text());
|
||||
}
|
||||
|
||||
void TimedEvent::on_addObjectToDelete_clicked()
|
||||
{
|
||||
for(int lvl : {0, 1})
|
||||
{
|
||||
auto & l = controller.scene(lvl)->objectPickerView;
|
||||
l.highlight<const CGObjectInstance>();
|
||||
l.update();
|
||||
QObject::connect(&l, &ObjectPickerLayer::selectionMade, this, &TimedEvent::onObjectPicked);
|
||||
}
|
||||
hide();
|
||||
dynamic_cast<QWidget *>(parent()->parent()->parent()->parent()->parent()->parent()->parent())->hide();
|
||||
}
|
||||
|
||||
void TimedEvent::on_removeObjectToDelete_clicked()
|
||||
{
|
||||
delete ui->deletedObjects->takeItem(ui->deletedObjects->currentRow());
|
||||
}
|
||||
|
||||
void TimedEvent::onObjectPicked(const CGObjectInstance * obj)
|
||||
{
|
||||
show();
|
||||
dynamic_cast<QWidget *>(parent()->parent()->parent()->parent()->parent()->parent()->parent())->show();
|
||||
|
||||
for(int lvl : {0, 1})
|
||||
{
|
||||
auto & l = controller.scene(lvl)->objectPickerView;
|
||||
l.clear();
|
||||
l.update();
|
||||
QObject::disconnect(&l, &ObjectPickerLayer::selectionMade, this, &TimedEvent::onObjectPicked);
|
||||
}
|
||||
|
||||
if(!obj)
|
||||
return;
|
||||
insertObjectToDelete(obj);
|
||||
}
|
||||
|
||||
void TimedEvent::insertObjectToDelete(const CGObjectInstance * obj)
|
||||
{
|
||||
QString objectLabel = QString("%1, x: %2, y: %3, z: %4").arg(QString::fromStdString(obj->getObjectName())).arg(obj->pos.x).arg(obj->pos.y).arg(obj->pos.z);
|
||||
auto * item = new QListWidgetItem(objectLabel);
|
||||
item->setData(MapEditorRoles::ObjectInstanceIDRole, QVariant::fromValue(obj->id.num));
|
||||
ui->deletedObjects->addItem(item);
|
||||
}
|
||||
|
||||
void TimedEvent::on_pushButton_clicked()
|
||||
{
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "mapcontroller.h"
|
||||
|
||||
namespace Ui {
|
||||
class TimedEvent;
|
||||
}
|
||||
@ -20,18 +22,23 @@ class TimedEvent : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TimedEvent(QListWidgetItem *, QWidget *parent = nullptr);
|
||||
explicit TimedEvent(MapController & map, QListWidgetItem *, QWidget * parent = nullptr);
|
||||
~TimedEvent();
|
||||
|
||||
private slots:
|
||||
|
||||
void on_TimedEvent_finished(int result);
|
||||
|
||||
void on_addObjectToDelete_clicked();
|
||||
void on_removeObjectToDelete_clicked();
|
||||
void onObjectPicked(const CGObjectInstance * obj);
|
||||
void insertObjectToDelete(const CGObjectInstance * obj);
|
||||
void on_pushButton_clicked();
|
||||
|
||||
void on_resources_itemDoubleClicked(QTableWidgetItem *item);
|
||||
void on_resources_itemDoubleClicked(QTableWidgetItem * item);
|
||||
|
||||
private:
|
||||
Ui::TimedEvent *ui;
|
||||
MapController & controller;
|
||||
Ui::TimedEvent * ui;
|
||||
QListWidgetItem * target;
|
||||
};
|
||||
|
@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>620</width>
|
||||
<height>371</height>
|
||||
<width>730</width>
|
||||
<height>422</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -201,6 +201,34 @@
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="deletedObjectsLabel">
|
||||
<property name="text">
|
||||
<string>Objects to delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addObjectToDelete">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeObjectToDelete">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="deletedObjects"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
|
@ -787,7 +787,7 @@ bool CGameHandler::removeObject(const CGObjectInstance * obj, const PlayerColor
|
||||
ro.initiator = initiator;
|
||||
sendAndApply(ro);
|
||||
|
||||
checkVictoryLossConditionsForAll(); //eg if monster escaped (removing objs after battle is done dircetly by endBattle, not this function)
|
||||
checkVictoryLossConditionsForAll(); //e.g. if monster escaped (removing objs after battle is done directly by endBattle, not this function)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,14 @@ void NewTurnProcessor::handleTimeEvents(PlayerColor color)
|
||||
if (event.resources[i])
|
||||
iw.components.emplace_back(ComponentType::RESOURCE, i, event.resources[i]);
|
||||
}
|
||||
|
||||
//remove objects specified by event
|
||||
for(const ObjectInstanceID objectIdToRemove : event.deletedObjectsInstances)
|
||||
{
|
||||
auto objectInstance = gameHandler->getObj(objectIdToRemove, false);
|
||||
if(objectInstance != nullptr)
|
||||
gameHandler->removeObject(objectInstance, PlayerColor::NEUTRAL);
|
||||
}
|
||||
gameHandler->sendAndApply(iw); //show dialog
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user