瀏覽代碼

Remove artifact from slot as reward

Ivan Savenko 5 月之前
父節點
當前提交
0212b6e37d

+ 1 - 0
lib/constants/EntityIdentifiers.h

@@ -756,6 +756,7 @@ public:
 
 	DLL_LINKAGE static si32 decode(const std::string & identifier);
 	DLL_LINKAGE static std::string encode(const si32 index);
+	DLL_LINKAGE static std::string entityType();
 };
 
 class ArtifactPosition : public StaticIdentifierWithEnum<ArtifactPosition, ArtifactPositionBase>

+ 14 - 0
lib/entities/artifact/CArtHandler.cpp

@@ -235,6 +235,20 @@ int32_t ArtifactPositionBase::decode(const std::string & slotName)
 		return PRE_FIRST;
 }
 
+std::string ArtifactPositionBase::encode(int32_t index)
+{
+#define ART_POS(x) #x ,
+	const std::vector<std::string> artSlots = { ART_POS_LIST };
+#undef ART_POS
+
+	return artSlots.at(index);
+}
+
+std::string ArtifactPositionBase::entityType()
+{
+	return "artifactSlot";
+}
+
 void CArtHandler::addSlot(CArtifact * art, const std::string & slotID) const
 {
 	static const std::vector<ArtifactPosition> miscSlots =

+ 21 - 0
lib/json/JsonRandom.cpp

@@ -113,6 +113,12 @@ JsonRandomizationException::JsonRandomizationException(const std::string & messa
 			return loadVariable(IdentifierType::entityType(), value.String(), variables, IdentifierType::NONE);
 	}
 
+	template<>
+	ArtifactPosition JsonRandom::decodeKey(const JsonNode & value, const Variables & variables)
+	{
+		return ArtifactPosition::decode(value.String());
+	}
+
 	template<>
 	PlayerColor JsonRandom::decodeKey(const JsonNode & value, const Variables & variables)
 	{
@@ -420,6 +426,21 @@ JsonRandomizationException::JsonRandomizationException(const std::string & messa
 		return ret;
 	}
 
+	std::vector<ArtifactPosition> JsonRandom::loadArtifactSlots(const JsonNode & value, vstd::RNG & rng, const Variables & variables)
+	{
+		std::set<ArtifactPosition> allowedSlots;
+		for(ArtifactPosition pos(0); pos < ArtifactPosition::BACKPACK_START; ++pos)
+			allowedSlots.insert(pos);
+
+		std::vector<ArtifactPosition> ret;
+		for (const JsonNode & entry : value.Vector())
+		{
+			std::set<ArtifactPosition> potentialPicks = filterKeys(entry, allowedSlots, variables);
+			ret.push_back(*RandomGeneratorUtil::nextItem(potentialPicks, rng));
+		}
+		return ret;
+	}
+
 	SpellID JsonRandom::loadSpell(const JsonNode & value, vstd::RNG & rng, const Variables & variables)
 	{
 		std::set<SpellID> defaultSpells;

+ 1 - 0
lib/json/JsonRandom.h

@@ -75,6 +75,7 @@ public:
 
 	ArtifactID loadArtifact(const JsonNode & value, vstd::RNG & rng, const Variables & variables);
 	std::vector<ArtifactID> loadArtifacts(const JsonNode & value, vstd::RNG & rng, const Variables & variables);
+	std::vector<ArtifactPosition> loadArtifactSlots(const JsonNode & value, vstd::RNG & rng, const Variables & variables);
 
 	SpellID loadSpell(const JsonNode & value, vstd::RNG & rng, const Variables & variables);
 	std::vector<SpellID> loadSpells(const JsonNode & value, vstd::RNG & rng, const Variables & variables);

+ 3 - 0
lib/rewardable/Info.cpp

@@ -164,6 +164,8 @@ void Rewardable::Info::configureReward(Rewardable::Configuration & object, vstd:
 	reward.resources = randomizer.loadResources(source["resources"], rng, variables);
 
 	reward.heroExperience = randomizer.loadValue(source["heroExperience"], rng, variables);
+	reward.unitExperience = randomizer.loadValue(source["unitExperience"], rng, variables);
+	reward.commanderExperience = randomizer.loadValue(source["commanderExperience"], rng, variables);
 	reward.heroLevel = randomizer.loadValue(source["heroLevel"], rng, variables);
 
 	reward.manaDiff = randomizer.loadValue(source["manaPoints"], rng, variables);
@@ -184,6 +186,7 @@ void Rewardable::Info::configureReward(Rewardable::Configuration & object, vstd:
 
 	reward.grantedArtifacts = randomizer.loadArtifacts(source["artifacts"], rng, variables);
 	reward.takenArtifacts = randomizer.loadArtifacts(source["takenArtifacts"], rng, variables);
+	reward.takenArtifactSlots = randomizer.loadArtifactSlots(source["takenArtifactsSlots"], 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);

+ 10 - 0
lib/rewardable/Interface.cpp

@@ -184,6 +184,16 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 			cb->removeArtifact(ArtifactLocation(hero->id, hero->getArtPos(art, false)));
 	}
 
+	for(const ArtifactPosition & slot : info.reward.takenArtifactSlots)
+	{
+		const auto & slotContent = hero->getSlot(slot);
+
+		if (!slotContent->locked && slotContent->artifactID.hasValue())
+			cb->removeArtifact(ArtifactLocation(hero->id, slot));
+
+		// TODO: handle locked slots?
+	}
+
 	for(const SpellID & spell : info.reward.scrolls)
 		cb->giveHeroNewScroll(hero, spell, ArtifactPosition::FIRST_AVAILABLE);
 

+ 6 - 0
lib/rewardable/Limiter.h

@@ -77,6 +77,12 @@ struct DLL_LINKAGE Limiter final : public Serializeable
 	/// creatures that hero needs to have
 	std::vector<CStackBasicDescriptor> creatures;
 	
+	/// creatures that hero needs to have
+	std::vector<CStackBasicDescriptor> canLoseCreatures;
+
+	/// creatures that hero needs to have
+	std::vector<CStackBasicDescriptor> canReceiveCreatures;
+
 	/// only heroes/hero classes from list could pass limiter
 	std::vector<HeroTypeID> heroes;
 	std::vector<HeroClassID> heroClasses;

+ 11 - 0
lib/rewardable/Reward.cpp

@@ -117,6 +117,16 @@ void Rewardable::Reward::loadComponents(std::vector<Component> & comps, const CG
 	for(const auto & entry : takenArtifacts)
 		comps.emplace_back(ComponentType::ARTIFACT, entry);
 
+	for(const auto & entry : takenArtifactSlots)
+	{
+		if (h)
+		{
+			const auto & slotContent = h->getSlot(entry);
+			if (slotContent->artifactID.hasValue())
+				comps.emplace_back(ComponentType::ARTIFACT, slotContent->getArt()->getTypeId());
+		}
+	}
+
 	for(const SpellID & spell : scrolls)
 		comps.emplace_back(ComponentType::SPELL, spell);
 
@@ -149,6 +159,7 @@ void Rewardable::Reward::serializeJson(JsonSerializeFormat & handler)
 	handler.serializeInt("movePoints", movePoints);
 	handler.serializeIdArray("artifacts", grantedArtifacts);
 	handler.serializeIdArray("takenArtifacts", takenArtifacts);
+	handler.serializeIdArray("takenArtifactSlots", takenArtifactSlots);
 	handler.serializeIdArray("scrolls", scrolls);
 	handler.serializeIdArray("spells", spells);
 	handler.enterArray("creatures").serializeStruct(creatures);

+ 5 - 2
lib/rewardable/Reward.h

@@ -66,7 +66,7 @@ struct DLL_LINKAGE Reward final
 	/// received experience
 	si32 heroExperience;
 	si32 commanderExperience;
-	si32 unitsExperience;
+	si32 unitExperience;
 	/// received levels (converted into XP during grant)
 	si32 heroLevel;
 
@@ -105,6 +105,7 @@ struct DLL_LINKAGE Reward final
 	std::vector<SpellID> scrolls;
 	std::vector<SpellID> spells;
 	std::vector<CStackBasicDescriptor> creatures;
+	std::vector<CStackBasicDescriptor> takenCreatures;
 	
 	/// actions that hero may execute and object caster. Pair of spellID and school level
 	std::pair<SpellID, int> spellCast;
@@ -140,7 +141,7 @@ struct DLL_LINKAGE Reward final
 		if (h.version >= Handler::Version::REWARDABLE_EXTENSIONS)
 		{
 			h & commanderExperience;
-			h & unitsExperience;
+			h & unitExperience;
 		}
 		h & heroLevel;
 		h & manaDiff;
@@ -162,6 +163,8 @@ struct DLL_LINKAGE Reward final
 		}
 		h & spells;
 		h & creatures;
+		if (h.version >= Handler::Version::REWARDABLE_EXTENSIONS)
+			h & takenCreatures;
 		h & creaturesChange;
 		h & revealTiles;
 		h & spellCast;