فهرست منبع

Spell scrolls as a reward

Ivan Savenko 5 ماه پیش
والد
کامیت
5dec3efa2f
5فایلهای تغییر یافته به همراه39 افزوده شده و 23 حذف شده
  1. 11 15
      AI/Nullkiller/Engine/PriorityEvaluator.cpp
  2. 11 8
      lib/mapping/MapFormatH3M.cpp
  3. 10 0
      lib/rewardable/Info.cpp
  4. 3 0
      lib/rewardable/Interface.cpp
  5. 4 0
      lib/rewardable/Reward.cpp

+ 11 - 15
AI/Nullkiller/Engine/PriorityEvaluator.cpp

@@ -206,6 +206,11 @@ int getDwellingArmyCost(const CGObjectInstance * target)
 	return cost;
 }
 
+static uint64_t evaluateSpellScrollArmyValue(const SpellID &)
+{
+	return 1500;
+}
+
 static uint64_t evaluateArtifactArmyValue(const CArtifact * art)
 {
 	if(art->getId() == ArtifactID::SPELL_SCROLL)
@@ -265,23 +270,14 @@ uint64_t RewardEvaluator::getArmyReward(
 
 			auto rewardValue = 0;
 
-			if(!info.reward.grantedArtifacts.empty())
-			{
-				for(auto artID : info.reward.grantedArtifacts)
-				{
-					const auto * art = artID.toArtifact();
+			for(auto artID : info.reward.grantedArtifacts)
+				rewardValue += evaluateArtifactArmyValue(artID.toArtifact());
 
-					rewardValue += evaluateArtifactArmyValue(art);
-				}
-			}
+			for(auto scroll : info.reward.scrolls)
+				rewardValue += evaluateSpellScrollArmyValue(scroll);
 
-			if(!info.reward.creatures.empty())
-			{
-				for(const auto & stackInfo : info.reward.creatures)
-				{
-					rewardValue += stackInfo.getType()->getAIValue() * stackInfo.getCount();
-				}
-			}
+			for(const auto & stackInfo : info.reward.creatures)
+				rewardValue += stackInfo.getType()->getAIValue() * stackInfo.getCount();
 
 			totalValue += rewardValue > 0 ? rewardValue / (info.reward.grantedArtifacts.size() + info.reward.creatures.size()) : 0;
 		}

+ 11 - 8
lib/mapping/MapFormatH3M.cpp

@@ -1130,13 +1130,16 @@ void CMapLoaderH3M::readBoxContent(CGPandoraBox * object, const int3 & mapPositi
 	size_t gart = reader->readUInt8(); //number of gained artifacts
 	for(size_t oo = 0; oo < gart; ++oo)
 	{
-		reward.grantedArtifacts.push_back(reader->readArtifact());
+		ArtifactID grantedArtifact = reader->readArtifact();
+
 		if (features.levelHOTA5)
 		{
 			SpellID scrollSpell = reader->readSpell16();
-			if (reward.grantedArtifacts.back() == ArtifactID::SPELL_SCROLL)
-				logGlobal->warn("Map '%s': Pandora/Event at %s Option to give spell scroll (%s) via event or pandora is not implemented!", mapName, mapPosition.toString(), scrollSpell.toEntity(LIBRARY)->getJsonKey());
+			if (grantedArtifact == ArtifactID::SPELL_SCROLL)
+				reward.scrolls.push_back(scrollSpell);
 		}
+		else
+			reward.grantedArtifacts.push_back(grantedArtifact);
 	}
 
 	size_t gspel = reader->readUInt8(); //number of gained spells
@@ -2334,15 +2337,15 @@ void CMapLoaderH3M::readSeerHutQuest(CGSeerHut * hut, const int3 & position, con
 			}
 			case ESeerHutRewardType::ARTIFACT:
 			{
-				reward.grantedArtifacts.push_back(reader->readArtifact());
+				ArtifactID grantedArtifact = reader->readArtifact();
 				if (features.levelHOTA5)
 				{
 					SpellID scrollSpell = reader->readSpell16();
-					if (reward.grantedArtifacts.back() == ArtifactID::SPELL_SCROLL)
-						logGlobal->warn("Map '%s': Seer Hut at %s: Option to give spell scroll (%s) as a reward is not implemented!", mapName, position.toString(), scrollSpell.toEntity(LIBRARY)->getJsonKey());
-
+					if (grantedArtifact == ArtifactID::SPELL_SCROLL)
+						reward.scrolls.push_back(scrollSpell);
 				}
-
+				else
+					reward.grantedArtifacts.push_back(grantedArtifact);
 				break;
 			}
 			case ESeerHutRewardType::SPELL:

+ 10 - 0
lib/rewardable/Info.cpp

@@ -183,6 +183,7 @@ void Rewardable::Info::configureReward(Rewardable::Configuration & object, vstd:
 	reward.secondary = randomizer.loadSecondaries(source["secondary"], rng, variables);
 
 	reward.grantedArtifacts = randomizer.loadArtifacts(source["artifacts"], rng, variables);
+	reward.scrolls = randomizer.loadSpells(source["scrolls"], rng, variables);
 	reward.spells = randomizer.loadSpells(source["spells"], rng, variables);
 	reward.creatures = randomizer.loadCreatures(source["creatures"], rng, variables);
 	if(!source["spellCast"].isNull() && source["spellCast"].isStruct())
@@ -300,6 +301,12 @@ void Rewardable::Info::replaceTextPlaceholders(MetaString & target, const Variab
 			loot.replaceName(artifact);
 		}
 
+		for (const auto & scroll : info.reward.scrolls )
+		{
+			loot.appendRawString("%s");
+			loot.replaceName(scroll);
+		}
+
 		for (const auto & spell : info.reward.spells )
 		{
 			loot.appendRawString("%s");
@@ -319,6 +326,9 @@ void Rewardable::Info::replaceTextPlaceholders(MetaString & target, const Variab
 		for (const auto & artifact : info.reward.grantedArtifacts )
 			target.replaceName(artifact);
 
+		for (const auto & scroll : info.reward.scrolls )
+			target.replaceName(scroll);
+
 		for (const auto & spell : info.reward.spells )
 			target.replaceName(spell);
 

+ 3 - 0
lib/rewardable/Interface.cpp

@@ -166,6 +166,9 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 	for(const ArtifactID & art : info.reward.grantedArtifacts)
 		cb->giveHeroNewArtifact(hero, art, ArtifactPosition::FIRST_AVAILABLE);
 
+	for(const SpellID & spell : info.reward.scrolls)
+		cb->giveHeroNewScroll(hero, spell, ArtifactPosition::FIRST_AVAILABLE);
+
 	if(!info.reward.spells.empty())
 	{
 		std::set<SpellID> spellsToGive;

+ 4 - 0
lib/rewardable/Reward.cpp

@@ -114,6 +114,9 @@ void Rewardable::Reward::loadComponents(std::vector<Component> & comps, const CG
 	for(const auto & entry : grantedArtifacts)
 		comps.emplace_back(ComponentType::ARTIFACT, entry);
 
+	for(const SpellID & spell : scrolls)
+		comps.emplace_back(ComponentType::SPELL, spell);
+
 	for(const auto & entry : spells)
 	{
 		bool learnable = !h || h->canLearnSpell(entry.toEntity(LIBRARY), true);
@@ -142,6 +145,7 @@ void Rewardable::Reward::serializeJson(JsonSerializeFormat & handler)
 	handler.serializeInt("manaOverflowFactor", manaOverflowFactor);
 	handler.serializeInt("movePoints", movePoints);
 	handler.serializeIdArray("artifacts", grantedArtifacts);
+	handler.serializeIdArray("scrolls", scrolls);
 	handler.serializeIdArray("spells", spells);
 	handler.enterArray("creatures").serializeStruct(creatures);
 	handler.enterArray("primary").serializeArray(primary);