mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Initial implementation for rewardable town building
This commit is contained in:
		| @@ -284,5 +284,146 @@ void CTownBonus::applyBonuses(CGHeroInstance * h, const BonusList & bonuses) con | ||||
| 		town->addHeroToStructureVisitors(h, indexOnTV); | ||||
| } | ||||
|  | ||||
| CTownRewardableBuilding::CTownRewardableBuilding(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown) | ||||
| { | ||||
| 	bID = index; | ||||
| 	bType = subId; | ||||
| 	town = cgTown; | ||||
| 	indexOnTV = static_cast<si32>(town->bonusingBuildings.size()); | ||||
| } | ||||
|  | ||||
| void CTownRewardableBuilding::setProperty(ui8 what, ui32 val) | ||||
| { | ||||
| 	switch (what) | ||||
| 	{ | ||||
| 		case ObjProperty::VISITORS: | ||||
| 			visitors.insert(ObjectInstanceID(val)); | ||||
| 			break; | ||||
| 		case ObjProperty::REWARD_RANDOMIZE: | ||||
| 			//initObj(cb->gameState()->getRandomGenerator()); | ||||
| 			break; | ||||
| 		case ObjProperty::REWARD_SELECT: | ||||
| 			selectedReward = val; | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| bool CTownRewardableBuilding::wasVisitedBefore(const CGHeroInstance * contextHero) const | ||||
| { | ||||
| 	switch (getConfiguration().visitMode) | ||||
| 	{ | ||||
| 		case Rewardable::VISIT_UNLIMITED: | ||||
| 			return false; | ||||
| 		case Rewardable::VISIT_ONCE: | ||||
| 			return false; //not supported | ||||
| 		case Rewardable::VISIT_PLAYER: | ||||
| 			return false; //not supported | ||||
| 		case Rewardable::VISIT_BONUS: | ||||
| 			return contextHero->hasBonusFrom(Bonus::TOWN_STRUCTURE, Bonus::getSid32(town->town->faction->getIndex(), bID)); | ||||
| 		case Rewardable::VISIT_HERO: | ||||
| 			return visitors.find(contextHero->id) != visitors.end(); | ||||
| 		default: | ||||
| 			return false; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CTownRewardableBuilding::onHeroVisit(const CGHeroInstance *h) const | ||||
| { | ||||
| 	auto grantRewardWithMessage = [&](int index) -> void | ||||
| 	{ | ||||
| 		auto vi = getConfiguration().info.at(index); | ||||
| 		logGlobal->debug("Granting reward %d. Message says: %s", index, vi.message.toString()); | ||||
|  | ||||
| 		InfoWindow iw; | ||||
| 		iw.player = h->tempOwner; | ||||
| 		iw.text = vi.message; | ||||
| 		vi.reward.loadComponents(iw.components, h); | ||||
| 		iw.type = getConfiguration().infoWindowType; | ||||
| 		if(!iw.components.empty() || !iw.text.toString().empty()) | ||||
| 			cb->showInfoDialog(&iw); | ||||
| 		 | ||||
| 		//grantReward(index, h); | ||||
| 	}; | ||||
| 	auto selectRewardsMessage = [&](const std::vector<ui32> & rewards, const MetaString & dialog) -> void | ||||
| 	{ | ||||
| 		BlockingDialog sd(getConfiguration().canRefuse, rewards.size() > 1); | ||||
| 		sd.player = h->tempOwner; | ||||
| 		sd.text = dialog; | ||||
|  | ||||
| 		if (rewards.size() > 1) | ||||
| 			for (auto index : rewards) | ||||
| 				sd.components.push_back(getConfiguration().info.at(index).reward.getDisplayedComponent(h)); | ||||
|  | ||||
| 		if (rewards.size() == 1) | ||||
| 			getConfiguration().info.at(rewards.front()).reward.loadComponents(sd.components, h); | ||||
|  | ||||
| 		cb->showBlockingDialog(&sd); | ||||
| 	}; | ||||
| 	 | ||||
| 	if(!town->hasBuilt(bID)) | ||||
| 		return; | ||||
|  | ||||
| 	if(!wasVisitedBefore(h)) | ||||
| 	{ | ||||
| 		town->addHeroToStructureVisitors(h, indexOnTV); | ||||
| 		 | ||||
| 		auto rewards = getAvailableRewards(h, CRewardVisitInfo::EVENT_FIRST_VISIT); | ||||
|  | ||||
| 		logGlobal->debug("Visiting object with %d possible rewards", rewards.size()); | ||||
| 		switch (rewards.size()) | ||||
| 		{ | ||||
| 			case 0: // no available rewards, e.g. visiting School of War without gold | ||||
| 			{ | ||||
| 				auto emptyRewards = getAvailableRewards(h, CRewardVisitInfo::EVENT_NOT_AVAILABLE); | ||||
| 				if (!emptyRewards.empty()) | ||||
| 					grantRewardWithMessage(emptyRewards[0]); | ||||
| 				else | ||||
| 					logMod->warn("No applicable message for visiting empty object!"); | ||||
| 				break; | ||||
| 			} | ||||
| 			case 1: // one reward. Just give it with message | ||||
| 			{ | ||||
| 				if (getConfiguration().canRefuse) | ||||
| 					selectRewardsMessage(rewards, getConfiguration().info.at(rewards.front()).message); | ||||
| 				else | ||||
| 					grantRewardWithMessage(rewards.front()); | ||||
| 				break; | ||||
| 			} | ||||
| 			default: // multiple rewards. Act according to select mode | ||||
| 			{ | ||||
| 				switch (getConfiguration().selectMode) { | ||||
| 					case Rewardable::SELECT_PLAYER: // player must select | ||||
| 						selectRewardsMessage(rewards, getConfiguration().onSelect); | ||||
| 						break; | ||||
| 					case Rewardable::SELECT_FIRST: // give first available | ||||
| 						grantRewardWithMessage(rewards.front()); | ||||
| 						break; | ||||
| 					case Rewardable::SELECT_RANDOM: // give random | ||||
| 						//TODO: support | ||||
| 						//grantRewardWithMessage(*RandomGeneratorUtil::nextItem(rewards, cb->gameState()->getRandomGenerator())); | ||||
| 						break; | ||||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if(getAvailableRewards(h, CRewardVisitInfo::EVENT_FIRST_VISIT).empty()) | ||||
| 		{ | ||||
| 			//ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_ADD_TEAM, id, h->id); | ||||
| 			//cb->sendAndApply(&cov); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		logGlobal->debug("Revisiting already visited object"); | ||||
|  | ||||
| 		auto visitedRewards = getAvailableRewards(h, CRewardVisitInfo::EVENT_ALREADY_VISITED); | ||||
| 		if (!visitedRewards.empty()) | ||||
| 			grantRewardWithMessage(visitedRewards[0]); | ||||
| 		else | ||||
| 			logMod->warn("No applicable message for visiting already visited object!"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_END | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "CObjectHandler.h" | ||||
| #include "CRewardableObject.h" | ||||
| #include "Rewardable.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| @@ -107,11 +107,18 @@ private: | ||||
|  | ||||
| class DLL_LINKAGE CTownRewardableBuilding : public CGTownBuilding, public Rewardable::Interface | ||||
| { | ||||
| 	/// reward selected by player, no serialize | ||||
| 	ui16 selectedReward = 0; | ||||
| 	 | ||||
| 	std::set<ObjectInstanceID> visitors; | ||||
| 	 | ||||
| 	bool wasVisitedBefore(const CGHeroInstance * contextHero) const; | ||||
| 	 | ||||
| public: | ||||
| 	void setProperty(ui8 what, ui32 val) override; | ||||
| 	void onHeroVisit (const CGHeroInstance * h) const override; | ||||
| 	void onHeroVisit(const CGHeroInstance * h) const override; | ||||
| 	 | ||||
| 	CTownRewardableBuilding(CGTownInstance * TOWN); | ||||
| 	CTownRewardableBuilding(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN); | ||||
| 	CTownRewardableBuilding() = default; | ||||
| 	 | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
|  | ||||
| #include "StdInc.h" | ||||
| #include "CGTownInstance.h" | ||||
| #include "CGTownBuilding.h" | ||||
| #include "CObjectClassesHandler.h" | ||||
| #include "../spells/CSpellHandler.h" | ||||
| #include "../battle/IBattleInfoCallback.h" | ||||
| @@ -380,7 +381,7 @@ void CGTownInstance::addTownBonuses(CRandomGenerator & rand) | ||||
| 		 | ||||
| 		if(kvp.second->subId == BuildingSubID::CONFIGURABLE_REWARD) | ||||
| 		{ | ||||
| 			auto * newBuilding = new CTownRewardableBuilding(this); | ||||
| 			auto * newBuilding = new CTownRewardableBuilding(kvp.second->bid, kvp.second->subId, this); | ||||
| 			kvp.second->rewardableObjectInfo.configureObject(newBuilding->configuration(), rand); | ||||
| 			bonusingBuildings.push_back(newBuilding); | ||||
| 		} | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
| #include "CGDwelling.h" | ||||
| #include "CGHeroInstance.h" | ||||
| #include "CGMarket.h" | ||||
| #include "CGTownBuilding.h" | ||||
| #include "CGTownInstance.h" | ||||
| #include "CGPandoraBox.h" | ||||
| #include "CRewardableObject.h" | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| #include "../mapObjects/CRewardableConstructor.h" | ||||
| #include "../mapObjects/CommonConstructors.h" | ||||
| #include "../mapObjects/MapObjects.h" | ||||
| #include "../mapObjects/CGTownBuilding.h" | ||||
| #include "../battle/CObstacleInstance.h" | ||||
| #include "../CStack.h" | ||||
|  | ||||
| @@ -153,7 +154,8 @@ void registerTypesMapObjects2(Serializer &s) | ||||
| 	//Other object-related | ||||
| 	s.template registerType<IObjectInterface, CGTownBuilding>(); | ||||
| 		s.template registerType<CGTownBuilding, CTownBonus>(); | ||||
| 			s.template registerType<CGTownBuilding, COPWBonus>(); | ||||
| 		s.template registerType<CGTownBuilding, COPWBonus>(); | ||||
| 		s.template registerType<CGTownBuilding, CTownRewardableBuilding>(); | ||||
|  | ||||
| 	s.template registerType<CGObjectInstance, CRewardableObject>(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user