Browse Source

Merge pull request #3132 from vcmi/reward_select_all

Support for "selectAll" reward
DjWarmonger 1 year ago
parent
commit
3e959f3ad9

+ 2 - 1
docs/modders/Map_Objects/Rewardable.md

@@ -177,6 +177,7 @@ Rewardable object is defined similarly to other objects, with key difference bei
 // "selectFirst",  - first reward which passes "limiter" will be granted to player
 // "selectPlayer", - player will be allowed to choose between rewards (e.g. treasure chest)
 // "selectRandom", - granted reward will be picked randomly when hero visits object
+// "selectAll" - every reward which passes "limiter" will be granted to player
 "selectMode" : "selectFirst"
 
 }
@@ -514,7 +515,7 @@ canLearnSpells
 ```jsonc
 "creatures" : [
     {
-        "creature" : "archer",
+        "type" : "archer",
         "upgradeChance" : 30,
         "amount" : 20,
     }

+ 19 - 0
lib/mapObjects/CRewardableObject.cpp

@@ -50,6 +50,22 @@ void CRewardableObject::selectRewardWthMessage(const CGHeroInstance * contextHer
 	sd.text = dialog;
 	sd.components = loadComponents(contextHero, rewardIndices);
 	cb->showBlockingDialog(&sd);
+
+}
+
+void CRewardableObject::grantAllRewardsWthMessage(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices, bool markAsVisit) const
+{
+	if (rewardIndices.empty())
+		return;
+		
+	for (auto index : rewardIndices)
+	{
+		// TODO: Merge all rewards of same type, with single message?
+		grantRewardWithMessage(contextHero, index, false);
+	}
+	// Mark visited only after all rewards were processed
+	if(markAsVisit)
+		markAsVisited(contextHero);
 }
 
 std::vector<Component> CRewardableObject::loadComponents(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices) const
@@ -125,6 +141,9 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
 							grantRewardWithMessage(h, rewardIndex, true);
 						break;
 					}
+					case Rewardable::SELECT_ALL: // grant all possible
+						grantAllRewardsWthMessage(h, rewards, true);
+						break;
 				}
 				break;
 			}

+ 2 - 0
lib/mapObjects/CRewardableObject.h

@@ -37,6 +37,8 @@ protected:
 	virtual void grantRewardWithMessage(const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const;
 	virtual void selectRewardWthMessage(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices, const MetaString & dialog) const;
 
+	virtual void grantAllRewardsWthMessage(const CGHeroInstance * contextHero, const std::vector<ui32>& rewardIndices, bool markAsVisit) const;
+
 	std::vector<Component> loadComponents(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices) const;
 
 	std::string getDisplayTextImpl(PlayerColor player, const CGHeroInstance * hero, bool includeDescription) const;

+ 3 - 2
lib/rewardable/Configuration.h

@@ -36,6 +36,7 @@ enum ESelectMode
 	SELECT_FIRST,  // first reward that matches limiters
 	SELECT_PLAYER, // player can select from all allowed rewards
 	SELECT_RANDOM, // one random reward from all mathing limiters
+	SELECT_ALL // grant all rewards that match limiters
 };
 
 enum class EEventType
@@ -46,8 +47,8 @@ enum class EEventType
 	EVENT_NOT_AVAILABLE
 };
 
-const std::array<std::string, 3> SelectModeString{"selectFirst", "selectPlayer", "selectRandom"};
-const std::array<std::string, 6> VisitModeString{"unlimited", "once", "hero", "bonus", "limiter", "player"};
+constexpr std::array<std::string_view, 4> SelectModeString{"selectFirst", "selectPlayer", "selectRandom", "selectAll"};
+constexpr std::array<std::string_view, 6> VisitModeString{"unlimited", "once", "hero", "bonus", "limiter", "player"};
 
 struct DLL_LINKAGE ResetInfo
 {

+ 2 - 2
mapeditor/inspector/rewardswidget.cpp

@@ -34,10 +34,10 @@ RewardsWidget::RewardsWidget(CMap & m, CRewardableObject & p, QWidget *parent) :
 	
 	//fill core elements
 	for(const auto & s : Rewardable::VisitModeString)
-		ui->visitMode->addItem(QString::fromStdString(s));
+		ui->selectMode->addItem(QString::fromUtf8(s.data(), s.size()));
 	
 	for(const auto & s : Rewardable::SelectModeString)
-		ui->selectMode->addItem(QString::fromStdString(s));
+		ui->selectMode->addItem(QString::fromUtf8(s.data(), s.size()));
 	
 	for(auto s : {"AUTO", "MODAL", "INFO"})
 		ui->windowMode->addItem(QString::fromStdString(s));