nordsoft 2 years ago
parent
commit
d2d64dbddd

+ 13 - 11
lib/mapObjects/CQuest.cpp

@@ -127,7 +127,7 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const
 	
 	if(killTarget >= 0)
 	{
-		if(!CGHeroInstance::cb->getObjByQuestIdentifier(killTarget))
+		if(CGHeroInstance::cb->getObjByQuestIdentifier(killTarget))
 			return false;
 	}
 	
@@ -164,7 +164,7 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const
 	cb->giveResources(h->getOwner(), resources);
 }
 
-void CQuest::addTextReplacements(MetaString & text) const
+void CQuest::addTextReplacements(MetaString & text, std::vector<Component> & components) const
 {
 	if(heroLevel > 0)
 		text.replaceNumber(heroLevel);
@@ -186,13 +186,13 @@ void CQuest::addTextReplacements(MetaString & text) const
 	
 	if(killTarget >= 0 && !heroName.empty())
 	{
-		//components.emplace_back(Component::EComponentType::HERO_PORTRAIT, heroPortrait, 0, 0);
+		components.emplace_back(Component::EComponentType::HERO_PORTRAIT, heroPortrait, 0, 0);
 		addKillTargetReplacements(text);
 	}
 	
 	if(killTarget >= 0 && stackToKill.type)
 	{
-		//components.emplace_back(stackToKill);
+		components.emplace_back(stackToKill);
 		addKillTargetReplacements(text);
 	}
 	
@@ -250,7 +250,7 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
 	else if(failRequirements)
 		iwText.appendRawString(nextVisitText.toString());
 	
-	addTextReplacements(iwText);
+	addTextReplacements(iwText, components);
 }
 
 void CQuest::getRolloverText(MetaString &ms, bool onHover) const
@@ -262,14 +262,16 @@ void CQuest::getRolloverText(MetaString &ms, bool onHover) const
 
 	ms.appendRawString(VLC->generaltexth->translate("core.seerhut.quest", questName, questState, textOption));
 
-	addTextReplacements(ms);
+	std::vector<Component> components;
+	addTextReplacements(ms, components);
 }
 
 void CQuest::getCompletionText(MetaString &iwText) const
 {
 	iwText.appendRawString(completedText.toString());
 	
-	addTextReplacements(iwText);
+	std::vector<Component> components;
+	addTextReplacements(iwText, components);
 }
 
 void CQuest::defineQuestName()
@@ -379,7 +381,7 @@ bool IQuestObject::checkQuest(const CGHeroInstance* h) const
 
 void IQuestObject::getVisitText(MetaString &text, std::vector<Component> &components, bool FirstVisit, const CGHeroInstance * h) const
 {
-	quest->getVisitText(text,components, FirstVisit, h);
+	quest->getVisitText(text, components, FirstVisit, h);
 }
 
 void IQuestObject::afterAddToMapCommon(CMap * map) const
@@ -431,9 +433,11 @@ void CGSeerHut::initObj(CRandomGenerator & rand)
 	
 	quest->defineQuestName();
 	
+	if(quest->empty() && quest->killTarget == -1)
+	   quest->progress = CQuest::COMPLETE;
+	
 	if(quest->questName == quest->missionName(0))
 	{
-		quest->progress = CQuest::COMPLETE;
 		quest->firstVisitText.appendTextID(TextIdentifier("core", "seehut", "empty", quest->completedOption).get());
 	}
 	else
@@ -568,7 +572,6 @@ const CGHeroInstance * CGSeerHut::getHeroToKill(bool allowNull) const
 	const CGObjectInstance *o = cb->getObjByQuestIdentifier(quest->killTarget);
 	if(allowNull && !o)
 		return nullptr;
-	assert(o && (o->ID == Obj::HERO  ||  o->ID == Obj::PRISON));
 	return dynamic_cast<const CGHeroInstance *>(o);
 }
 
@@ -577,7 +580,6 @@ const CGCreature * CGSeerHut::getCreatureToKill(bool allowNull) const
 	const CGObjectInstance *o = cb->getObjByQuestIdentifier(quest->killTarget);
 	if(allowNull && !o)
 		return nullptr;
-	assert(o && o->ID == Obj::MONSTER);
 	return dynamic_cast<const CGCreature *>(o);
 }
 

+ 3 - 3
lib/mapObjects/CQuest.h

@@ -57,12 +57,12 @@ public:
 	CQuest(); //TODO: Remove constructor
 
 	static bool checkMissionArmy(const CQuest * q, const CCreatureSet * army);
-	virtual bool checkQuest (const CGHeroInstance * h) const; //determines whether the quest is complete or not
-	virtual void getVisitText (MetaString &text, std::vector<Component> &components, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
+	virtual bool checkQuest(const CGHeroInstance * h) const; //determines whether the quest is complete or not
+	virtual void getVisitText(MetaString &text, std::vector<Component> & components, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
 	virtual void getCompletionText(MetaString &text) const;
 	virtual void getRolloverText (MetaString &text, bool onHover) const; //hover or quest log entry
 	virtual void completeQuest(IGameCallback *, const CGHeroInstance * h) const;
-	virtual void addTextReplacements(MetaString &out) const;
+	virtual void addTextReplacements(MetaString &out, std::vector<Component> & components) const;
 	virtual void addKillTargetReplacements(MetaString &out) const;
 	void defineQuestName();
 

+ 36 - 3
lib/rewardable/Limiter.cpp

@@ -35,6 +35,37 @@ Rewardable::Limiter::Limiter()
 
 Rewardable::Limiter::~Limiter() = default;
 
+bool Rewardable::Limiter::empty() const
+{
+	if(dayOfWeek != 0
+	   || daysPassed != 0
+	   || heroLevel > 0
+	   || heroExperience > 0
+	   || manaPoints > 0
+	   || manaPercentage > 0
+	   || !secondary.empty()
+	   || !creatures.empty()
+	   || !spells.empty()
+	   || !artifacts.empty()
+	   || !players.empty()
+	   || !heroes.empty()
+	   || !heroClasses.empty()
+	   || resources.nonZero()
+	   || std::find_if(primary.begin(), primary.end(), [](si32 i){return i != 0;}) != primary.end())
+		return false;
+	
+	for(const auto & sub : {noneOf, allOf, anyOf})
+	{
+		for(const auto & sublimiter : sub)
+		{
+			if(!sublimiter->empty())
+				return false;
+		}
+	}
+	
+	return true;
+}
+
 bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
 {
 	if(dayOfWeek != 0)
@@ -150,14 +181,16 @@ void Rewardable::Limiter::loadComponents(std::vector<Component> & comps,
 								 const CGHeroInstance * h) const
 {
 	if (heroExperience)
-	{
 		comps.emplace_back(Component::EComponentType::EXPERIENCE, 0, static_cast<si32>(h->calculateXp(heroExperience)), 0);
-	}
+
 	if (heroLevel)
 		comps.emplace_back(Component::EComponentType::EXPERIENCE, 1, heroLevel, 0);
 
 	if (manaPoints || manaPercentage > 0)
-		comps.emplace_back(Component::EComponentType::PRIM_SKILL, 5, 0, 0);
+	{
+		int absoluteMana = h->manaLimit() ? (manaPercentage * h->mana / h->manaLimit() / 100) : 0;
+		comps.emplace_back(Component::EComponentType::PRIM_SKILL, 5, absoluteMana + manaPoints, 0);
+	}
 
 	for (size_t i=0; i<primary.size(); i++)
 	{

+ 1 - 1
lib/rewardable/Limiter.h

@@ -26,7 +26,6 @@ using LimitersList = std::vector<std::shared_ptr<Rewardable::Limiter>>;
 
 /// Limiters of rewards. Rewards will be granted to hero only if he satisfies requirements
 /// Note: for this is only a test - it won't remove anything from hero (e.g. artifacts or creatures)
-/// NOTE: in future should (partially) replace seer hut/quest guard quests checks
 struct DLL_LINKAGE Limiter
 {
 	/// day of week, unused if 0, 1-7 will test for current day of week
@@ -82,6 +81,7 @@ struct DLL_LINKAGE Limiter
 	virtual ~Limiter();
 
 	bool heroAllowed(const CGHeroInstance * hero) const;
+	bool empty() const;
 	
 	/// Generates list of components that describes reward for a specific hero
 	virtual void loadComponents(std::vector<Component> & comps,

+ 22 - 10
mapeditor/inspector/inspector.cpp

@@ -519,7 +519,8 @@ void Inspector::setProperty(CGPandoraBox * o, const QString & key, const QVarian
 	if(!o) return;
 	
 	if(key == "Message")
-		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("guards", o->instanceName, "message"), value.toString().toStdString()));
+		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("guards", o->instanceName, "message"), value.toString().toStdString()));
 }
 
 void Inspector::setProperty(CGEvent * o, const QString & key, const QVariant & value)
@@ -541,7 +542,8 @@ void Inspector::setProperty(CGTownInstance * o, const QString & key, const QVari
 	if(!o) return;
 	
 	if(key == "Town name")
-		o->setNameTextId(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("town", o->instanceName, "name"), value.toString().toStdString()));
+		o->setNameTextId(mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("town", o->instanceName, "name"), value.toString().toStdString()));
 }
 
 void Inspector::setProperty(CGSignBottle * o, const QString & key, const QVariant & value)
@@ -549,7 +551,8 @@ void Inspector::setProperty(CGSignBottle * o, const QString & key, const QVarian
 	if(!o) return;
 	
 	if(key == "Message")
-		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("sign", o->instanceName, "message"), value.toString().toStdString()));
+		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("sign", o->instanceName, "message"), value.toString().toStdString()));
 }
 
 void Inspector::setProperty(CGMine * o, const QString & key, const QVariant & value)
@@ -565,7 +568,8 @@ void Inspector::setProperty(CGArtifact * o, const QString & key, const QVariant
 	if(!o) return;
 	
 	if(key == "Message")
-		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("guards", o->instanceName, "message"), value.toString().toStdString()));
+		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("guards", o->instanceName, "message"), value.toString().toStdString()));
 	
 	if(o->storedArtifact && key == "Spell")
 	{
@@ -604,10 +608,12 @@ void Inspector::setProperty(CGHeroInstance * o, const QString & key, const QVari
 		o->gender = EHeroGender(value.toInt());
 	
 	if(key == "Name")
-		o->nameCustomTextId = mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("hero", o->instanceName, "name"), value.toString().toStdString());
+		o->nameCustomTextId = mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("hero", o->instanceName, "name"), value.toString().toStdString());
 	
 	if(key == "Biography")
-		o->biographyCustomTextId = mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("hero", o->instanceName, "biography"), value.toString().toStdString());
+		o->biographyCustomTextId = mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("hero", o->instanceName, "biography"), value.toString().toStdString());
 	
 	if(key == "Experience")
 		o->exp = value.toString().toInt();
@@ -643,7 +649,8 @@ void Inspector::setProperty(CGCreature * o, const QString & key, const QVariant
 	if(!o) return;
 	
 	if(key == "Message")
-		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("monster", o->instanceName, "message"), value.toString().toStdString()));
+		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("monster", o->instanceName, "message"), value.toString().toStdString()));
 	if(key == "Character")
 		o->character = CGCreature::Character(value.toInt());
 	if(key == "Never flees")
@@ -659,11 +666,16 @@ void Inspector::setProperty(CGSeerHut * o, const QString & key, const QVariant &
 	if(!o) return;
 	
 	if(key == "First visit text")
-		o->quest->firstVisitText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("quest", o->instanceName, "firstVisit"), value.toString().toStdString()));
+		o->quest->firstVisitText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("quest", o->instanceName, "firstVisit"), value.toString().toStdString()));
 	if(key == "Next visit text")
-		o->quest->nextVisitText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("quest", o->instanceName, "nextVisit"), value.toString().toStdString()));
+		o->quest->nextVisitText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("quest", o->instanceName, "nextVisit"), value.toString().toStdString()));
 	if(key == "Completed text")
-		o->quest->completedText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("quest", o->instanceName, "completed"), value.toString().toStdString()));
+		o->quest->completedText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(),
+			TextIdentifier("quest", o->instanceName, "completed"), value.toString().toStdString()));
+	if(key == "Repeat quest")
+		o->quest->repeatedQuest = value.toBool();
 }
 
 

+ 3 - 1
mapeditor/inspector/questwidget.cpp

@@ -42,7 +42,9 @@ QuestWidget::QuestWidget(MapController & _controller, CQuest & _sh, QWidget *par
 		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);
+		auto * spinBox = new QSpinBox;
+		spinBox->setMaximum(i == GameResID::GOLD ? 999999 : 999);
+		ui->lResources->setCellWidget(i, 1, spinBox);
 	}
 	
 	//fill artifacts

+ 5 - 1
mapeditor/inspector/rewardswidget.cpp

@@ -56,7 +56,11 @@ RewardsWidget::RewardsWidget(CMap & m, CRewardableObject & p, QWidget *parent) :
 			auto * item = new QTableWidgetItem(QString::fromStdString(GameConstants::RESOURCE_NAMES[i]));
 			item->setData(Qt::UserRole, QVariant::fromValue(i));
 			w->setItem(i, 0, item);
-			w->setCellWidget(i, 1, new QSpinBox);
+			auto * spinBox = new QSpinBox;
+			spinBox->setMaximum(i == GameResID::GOLD ? 999999 : 999);
+			if(w == ui->rResources)
+				spinBox->setMinimum(i == GameResID::GOLD ? -999999 : -999);
+			w->setCellWidget(i, 1, spinBox);
 		}
 	}