浏览代码

Object picker for victory/loss conditions

nordsoft 2 年之前
父节点
当前提交
6a0b26d402
共有 2 个文件被更改,包括 163 次插入18 次删除
  1. 43 0
      mapeditor/mapsettings/loseconditions.cpp
  2. 120 18
      mapeditor/mapsettings/victoryconditions.cpp

+ 43 - 0
mapeditor/mapsettings/loseconditions.cpp

@@ -279,10 +279,53 @@ void LoseConditions::on_loseComboBox_currentIndexChanged(int index)
 
 void LoseConditions::onObjectSelect()
 {
+	int loseCondition = ui->loseComboBox->currentIndex() - 1;
+	for(int lvl : {0, 1})
+	{
+		auto & l = controller->scene(lvl)->objectPickerView;
+		switch(loseCondition)
+		{
+			case 0: {  //EventCondition::CONTROL (Obj::TOWN)
+				l.highlight<const CGTownInstance>();
+				break;
+			}
+				
+			case 1: { //EventCondition::CONTROL (Obj::HERO)
+				l.highlight<const CGHeroInstance>();
+				break;
+			}
+			default:
+				return;
+		}
+		l.update();
+		QObject::connect(&l, &ObjectPickerLayer::selectionMade, this, &LoseConditions::onObjectPicked);
+	}
 	
+	dynamic_cast<QWidget*>(parent()->parent()->parent()->parent()->parent()->parent()->parent())->hide();
 }
 
 void LoseConditions::onObjectPicked(const CGObjectInstance * obj)
 {
+	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, &LoseConditions::onObjectPicked);
+	}
 	
+	if(!obj) //discarded
+		return;
+	
+	for(int i = 0; i < loseTypeWidget->count(); ++i)
+	{
+		auto data = controller->map()->objects.at(loseTypeWidget->itemData(i).toInt());
+		if(data == obj)
+		{
+			loseTypeWidget->setCurrentIndex(i);
+			break;
+		}
+	}
 }

+ 120 - 18
mapeditor/mapsettings/victoryconditions.cpp

@@ -13,6 +13,7 @@
 #include "../mapcontroller.h"
 #include "../lib/CGeneralTextHandler.h"
 #include "../lib/constants/StringConstants.h"
+#include "../../lib/mapObjects/CGCreature.h"
 
 #include "../inspector/townbulidingswidget.h" //to convert BuildingID to string
 
@@ -31,7 +32,7 @@ void VictoryConditions::initialize(MapController & c)
 	ui->victoryMessageEdit->setText(QString::fromStdString(controller->map()->victoryMessage.toString()));
 
 	//victory conditions
-	const std::array<std::string, 8> conditionStringsWin = {
+	const std::array<std::string, 9> conditionStringsWin = {
 		QT_TR_NOOP("No special victory"),
 		QT_TR_NOOP("Capture artifact"),
 		QT_TR_NOOP("Hire creatures"),
@@ -39,7 +40,8 @@ void VictoryConditions::initialize(MapController & c)
 		QT_TR_NOOP("Construct building"),
 		QT_TR_NOOP("Capture town"),
 		QT_TR_NOOP("Defeat hero"),
-		QT_TR_NOOP("Transport artifact")
+		QT_TR_NOOP("Transport artifact"),
+		QT_TR_NOOP("Kill monster")
 	};
 
 	for(auto & s : conditionStringsWin)
@@ -124,10 +126,10 @@ void VictoryConditions::initialize(MapController & c)
 						}
 
 						case EventCondition::DESTROY: {
-							ui->victoryComboBox->setCurrentIndex(6);
-							assert(victoryTypeWidget);
 							if(json["objectType"].Integer() == Obj::HERO)
 							{
+								ui->victoryComboBox->setCurrentIndex(6);
+								assert(victoryTypeWidget);
 								int heroIdx = getObjectByPos<const CGHeroInstance>(*controller->map(), posFromJson(json["position"]));
 								if(heroIdx >= 0)
 								{
@@ -135,7 +137,17 @@ void VictoryConditions::initialize(MapController & c)
 									victoryTypeWidget->setCurrentIndex(idx);
 								}
 							}
-							//TODO: support control other objects (monsters)
+							if(json["objectType"].Integer() == Obj::MONSTER)
+							{
+								ui->victoryComboBox->setCurrentIndex(8);
+								assert(victoryTypeWidget);
+								int monsterIdx = getObjectByPos<const CGCreature>(*controller->map(), posFromJson(json["position"]));
+								if(monsterIdx >= 0)
+								{
+									auto idx = victoryTypeWidget->findData(monsterIdx);
+									victoryTypeWidget->setCurrentIndex(idx);
+								}
+							}
 							break;
 						}
 
@@ -283,6 +295,18 @@ void VictoryConditions::update()
 				specialVictory.trigger = EventExpression(cond);
 				break;
 			}
+				
+			case 7: {
+				EventCondition cond(EventCondition::DESTROY);
+				assert(victoryTypeWidget);
+				cond.objectType = Obj::MONSTER;
+				int monsterIdx = victoryTypeWidget->currentData().toInt();
+				cond.position = controller->map()->objects[monsterIdx]->pos;
+				specialVictory.effect.toOtherMessage.appendTextID("core.genrltxt.287");
+				specialVictory.onFulfill.appendTextID("core.genrltxt.286");
+				specialVictory.trigger = EventExpression(cond);
+				break;
+			}
 
 		}
 
@@ -318,9 +342,11 @@ void VictoryConditions::on_victoryComboBox_currentIndexChanged(int index)
 	delete victoryTypeWidget;
 	delete victoryValueWidget;
 	delete victorySelectWidget;
+	delete pickObjectButton;
 	victoryTypeWidget = nullptr;
 	victoryValueWidget = nullptr;
 	victorySelectWidget = nullptr;
+	pickObjectButton = nullptr;
 
 	if(index == 0)
 	{
@@ -385,6 +411,10 @@ void VictoryConditions::on_victoryComboBox_currentIndexChanged(int index)
 			victorySelectWidget->addItem("Any town", QVariant::fromValue(-1));
 			for(int i : getObjectIndexes<const CGTownInstance>(*controller->map()))
 				victorySelectWidget->addItem(getTownName(*controller->map(), i).c_str(), QVariant::fromValue(i));
+			
+			pickObjectButton = new QToolButton;
+			connect(pickObjectButton, &QToolButton::clicked, this, &VictoryConditions::onObjectSelect);
+			ui->victoryParamsLayout->addWidget(pickObjectButton);
 			break;
 		}
 
@@ -393,6 +423,9 @@ void VictoryConditions::on_victoryComboBox_currentIndexChanged(int index)
 			ui->victoryParamsLayout->addWidget(victoryTypeWidget);
 			for(int i : getObjectIndexes<const CGTownInstance>(*controller->map()))
 				victoryTypeWidget->addItem(tr(getTownName(*controller->map(), i).c_str()), QVariant::fromValue(i));
+			pickObjectButton = new QToolButton;
+			connect(pickObjectButton, &QToolButton::clicked, this, &VictoryConditions::onObjectSelect);
+			ui->victoryParamsLayout->addWidget(pickObjectButton);
 			break;
 		}
 
@@ -401,6 +434,9 @@ void VictoryConditions::on_victoryComboBox_currentIndexChanged(int index)
 			ui->victoryParamsLayout->addWidget(victoryTypeWidget);
 			for(int i : getObjectIndexes<const CGHeroInstance>(*controller->map()))
 				victoryTypeWidget->addItem(tr(getHeroName(*controller->map(), i).c_str()), QVariant::fromValue(i));
+			pickObjectButton = new QToolButton;
+			connect(pickObjectButton, &QToolButton::clicked, this, &VictoryConditions::onObjectSelect);
+			ui->victoryParamsLayout->addWidget(pickObjectButton);
 			break;
 		}
 
@@ -409,37 +445,103 @@ void VictoryConditions::on_victoryComboBox_currentIndexChanged(int index)
 			ui->victoryParamsLayout->addWidget(victoryTypeWidget);
 			for(int i = 0; i < controller->map()->allowedArtifact.size(); ++i)
 				victoryTypeWidget->addItem(QString::fromStdString(VLC->arth->objects[i]->getNameTranslated()), QVariant::fromValue(i));
-
+			
 			victorySelectWidget = new QComboBox;
 			ui->victoryParamsLayout->addWidget(victorySelectWidget);
 			for(int i : getObjectIndexes<const CGTownInstance>(*controller->map()))
 				victorySelectWidget->addItem(tr(getTownName(*controller->map(), i).c_str()), QVariant::fromValue(i));
+			pickObjectButton = new QToolButton;
+			connect(pickObjectButton, &QToolButton::clicked, this, &VictoryConditions::onObjectSelect);
+			ui->victoryParamsLayout->addWidget(pickObjectButton);
 			break;
 		}
-
-
-		//TODO: support this vectory type
-		// in order to do that, need to implement finding creature by position
-		// selecting from map would be the best user experience
-		/*case 7: { //EventCondition::DESTROY (Obj::MONSTER)
+			
+		case 7: { //EventCondition::DESTROY (Obj::MONSTER)
 			victoryTypeWidget = new QComboBox;
-			ui->loseParamsLayout->addWidget(victoryTypeWidget);
-			for(int i : getObjectIndexes<const CGCreature>(*mapPointer))
-				victoryTypeWidget->addItem(tr(getMonsterName(i).c_str()), QVariant::fromValue(i));
+			ui->victoryParamsLayout->addWidget(victoryTypeWidget);
+			for(int i : getObjectIndexes<const CGCreature>(*controller->map()))
+				victoryTypeWidget->addItem(tr(getMonsterName(*controller->map(), i).c_str()), QVariant::fromValue(i));
+			pickObjectButton = new QToolButton;
+			connect(pickObjectButton, &QToolButton::clicked, this, &VictoryConditions::onObjectSelect);
+			ui->victoryParamsLayout->addWidget(pickObjectButton);
 			break;
-		}*/
-
-
+		}
 	}
 }
 
 
 void VictoryConditions::onObjectSelect()
 {
+	int vicConditions = ui->victoryComboBox->currentIndex() - 1;
+	for(int lvl : {0, 1})
+	{
+		auto & l = controller->scene(lvl)->objectPickerView;
+		switch(vicConditions)
+		{
+			case 3: { //EventCondition::HAVE_BUILDING
+				l.highlight<const CGTownInstance>();
+				break;
+			}
+				
+			case 4: { //EventCondition::CONTROL (Obj::TOWN)
+				l.highlight<const CGTownInstance>();
+				break;
+			}
+				
+			case 5: { //EventCondition::DESTROY (Obj::HERO)
+				l.highlight<const CGHeroInstance>();
+				break;
+			}
+				
+			case 6: { //EventCondition::TRANSPORT (Obj::ARTEFACT)
+				l.highlight<const CGTownInstance>();
+				break;
+			}
+				
+			case 7: { //EventCondition::DESTROY (Obj::MONSTER)
+				l.highlight<const CGCreature>();
+				break;
+			}
+			default:
+				return;
+		}
+		l.update();
+		QObject::connect(&l, &ObjectPickerLayer::selectionMade, this, &VictoryConditions::onObjectPicked);
+	}
 	
+	dynamic_cast<QWidget*>(parent()->parent()->parent()->parent()->parent()->parent()->parent())->hide();
 }
 
 void VictoryConditions::onObjectPicked(const CGObjectInstance * obj)
 {
+	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, &VictoryConditions::onObjectPicked);
+	}
+	
+	if(!obj) //discarded
+		return;
+	
+	int vicConditions = ui->victoryComboBox->currentIndex() - 1;
+	QComboBox * w = victoryTypeWidget;
+	if(vicConditions == 3 || vicConditions == 6)
+		w = victorySelectWidget;
+	
+	for(int i = 0; i < w->count(); ++i)
+	{
+		if(w->itemData(i).toInt() < 0)
+			continue;
+		
+		auto data = controller->map()->objects.at(w->itemData(i).toInt());
+		if(data == obj)
+		{
+			w->setCurrentIndex(i);
+			break;
+		}
+	}
 }