mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Fixes for code review issues
This commit is contained in:
		| @@ -563,24 +563,24 @@ void CBattleInterface::deactivate() | ||||
|  | ||||
| void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key) | ||||
| { | ||||
| 	if (key.keysym.sym == SDLK_q && key.state == SDL_PRESSED) | ||||
| 	if(key.keysym.sym == SDLK_q && key.state == SDL_PRESSED) | ||||
| 	{ | ||||
| 		if (settings["battle"]["showQueue"].Bool()) //hide queue | ||||
| 		if(settings["battle"]["showQueue"].Bool()) //hide queue | ||||
| 			hideQueue(); | ||||
| 		else | ||||
| 			showQueue(); | ||||
|  | ||||
| 	} | ||||
| 	else if (key.keysym.sym == SDLK_f && key.state == SDL_PRESSED) | ||||
| 	else if(key.keysym.sym == SDLK_f && key.state == SDL_PRESSED) | ||||
| 	{ | ||||
| 		enterCreatureCastingMode(); | ||||
| 	} | ||||
| 	else if (key.keysym.sym == SDLK_ESCAPE) | ||||
| 	else if(key.keysym.sym == SDLK_ESCAPE) | ||||
| 	{ | ||||
| 		if(!battleActionsStarted) | ||||
| 			CCS->soundh->stopSound(battleIntroSoundChannel); | ||||
| 		else | ||||
| 		endCastingSpell(); | ||||
| 			endCastingSpell(); | ||||
| 	} | ||||
| } | ||||
| void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent) | ||||
| @@ -788,14 +788,14 @@ void CBattleInterface::bOptionsf() | ||||
|  | ||||
| void CBattleInterface::bSurrenderf() | ||||
| { | ||||
| 	if (spellDestSelectMode) //we are casting a spell | ||||
| 	if(spellDestSelectMode) //we are casting a spell | ||||
| 		return; | ||||
|  | ||||
| 	int cost = curInt->cb->battleGetSurrenderCost(); | ||||
| 	if (cost >= 0) | ||||
| 	if(cost >= 0) | ||||
| 	{ | ||||
| 		std::string enemyHeroName = curInt->cb->battleGetEnemyHero().name; | ||||
| 		if (enemyHeroName.empty()) | ||||
| 		if(enemyHeroName.empty()) | ||||
| 		{ | ||||
| 			logGlobal->warn("Surrender performed without enemy hero, should not happen!"); | ||||
| 			enemyHeroName = "#ENEMY#"; | ||||
| @@ -1462,14 +1462,9 @@ void CBattleInterface::displayEffect(ui32 effect, BattleHex destTile) | ||||
| 	addNewAnim(new CEffectAnimation(this, customAnim, destTile)); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::displaySpellCast(SpellID spellID, BattleHex destinationTile) | ||||
| void CBattleInterface::displaySpellAnimationQueue(const CSpell::TAnimationQueue & q, BattleHex destinationTile) | ||||
| { | ||||
| 	const CSpell * spell = spellID.toSpell(); | ||||
|  | ||||
| 	if(spell == nullptr) | ||||
| 		return; | ||||
|  | ||||
| 	for(const CSpell::TAnimation & animation : spell->animationInfo.cast) | ||||
| 	for(const CSpell::TAnimation & animation : q) | ||||
| 	{ | ||||
| 		if(animation.pause > 0) | ||||
| 			addNewAnim(new CDummyAnimation(this, animation.pause)); | ||||
| @@ -1478,37 +1473,28 @@ void CBattleInterface::displaySpellCast(SpellID spellID, BattleHex destinationTi | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleInterface::displaySpellCast(SpellID spellID, BattleHex destinationTile) | ||||
| { | ||||
| 	const CSpell * spell = spellID.toSpell(); | ||||
|  | ||||
| 	if(spell) | ||||
| 		displaySpellAnimationQueue(spell->animationInfo.cast, destinationTile); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::displaySpellEffect(SpellID spellID, BattleHex destinationTile) | ||||
| { | ||||
| 	const CSpell *spell = spellID.toSpell(); | ||||
|  | ||||
| 	if(spell == nullptr) | ||||
| 		return; | ||||
|  | ||||
| 	for(const CSpell::TAnimation & animation : spell->animationInfo.affect) | ||||
| 	{ | ||||
| 		if(animation.pause > 0) | ||||
| 			addNewAnim(new CDummyAnimation(this, animation.pause)); | ||||
| 		else | ||||
| 			addNewAnim(new CEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM)); | ||||
|  | ||||
| 	} | ||||
| 	if(spell) | ||||
| 		displaySpellAnimationQueue(spell->animationInfo.affect, destinationTile); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::displaySpellHit(SpellID spellID, BattleHex destinationTile) | ||||
| { | ||||
| 	const CSpell * spell = spellID.toSpell(); | ||||
|  | ||||
| 	if(spell == nullptr) | ||||
| 		return; | ||||
|  | ||||
| 	for(const CSpell::TAnimation & animation : spell->animationInfo.hit) | ||||
| 	{ | ||||
| 		if(animation.pause > 0) | ||||
| 			addNewAnim(new CDummyAnimation(this, animation.pause)); | ||||
| 		else | ||||
| 			addNewAnim(new CEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM)); | ||||
| 	} | ||||
| 	if(spell) | ||||
| 		displaySpellAnimationQueue(spell->animationInfo.hit, destinationTile); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::battleTriggerEffect(const BattleTriggerEffect & bte) | ||||
| @@ -1704,13 +1690,12 @@ void CBattleInterface::enterCreatureCastingMode() | ||||
| 		spells::Target target; | ||||
| 		target.emplace_back(); | ||||
|  | ||||
|  | ||||
| 		spells::BattleCast cast(curInt->cb.get(), caster, spells::Mode::CREATURE_ACTIVE, spell); | ||||
|  | ||||
| 		auto m = spell->battleMechanics(&cast); | ||||
| 		spells::detail::ProblemImpl ignored; | ||||
|  | ||||
| 		const bool isCastingPossible = m->canBeCastAt(ignored, target); | ||||
| 		const bool isCastingPossible = m->canBeCastAt(target, ignored); | ||||
|  | ||||
| 		if (isCastingPossible) | ||||
| 		{ | ||||
| @@ -1762,7 +1747,7 @@ void CBattleInterface::reorderPossibleActionsPriority(const CStack * stack, Mous | ||||
| 		case PossiblePlayerBattleAction::OBSTACLE: | ||||
| 			if(!stack->hasBonusOfType(Bonus::NO_SPELLCAST_BY_DEFAULT) && context == MouseHoveredHexContext::OCCUPIED_HEX) | ||||
| 				return 1; | ||||
| 					else | ||||
| 			else | ||||
| 				return 100;//bottom priority | ||||
| 			break; | ||||
| 		case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL: | ||||
| @@ -2543,7 +2528,7 @@ bool CBattleInterface::isCastingPossibleHere(const CStack *sactive, const CStack | ||||
| 			auto m = sp->battleMechanics(&cast); | ||||
| 			spells::detail::ProblemImpl problem; //todo: display problem in status bar | ||||
|  | ||||
| 			isCastingPossible = m->canBeCastAt(problem, target); | ||||
| 			isCastingPossible = m->canBeCastAt(target, problem); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| @@ -3022,7 +3007,7 @@ void CBattleInterface::show(SDL_Surface *to) | ||||
| 	showProjectiles(to); | ||||
|  | ||||
| 	if(battleActionsStarted) | ||||
| 	updateBattleAnimations(); | ||||
| 		updateBattleAnimations(); | ||||
|  | ||||
| 	SDL_SetClipRect(to, &buf); //restoring previous clip_rect | ||||
|  | ||||
|   | ||||
| @@ -358,6 +358,7 @@ public: | ||||
|  | ||||
| 	void displayEffect(ui32 effect, BattleHex destTile); //displays custom effect on the battlefield | ||||
|  | ||||
| 	void displaySpellAnimationQueue(const CSpell::TAnimationQueue & q, BattleHex destinationTile); | ||||
| 	void displaySpellCast(SpellID spellID, BattleHex destinationTile); //displays spell`s cast animation | ||||
| 	void displaySpellEffect(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation | ||||
| 	void displaySpellHit(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation | ||||
|   | ||||
| @@ -368,11 +368,11 @@ void CGarrisonSlot::update() | ||||
| } | ||||
|  | ||||
| CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * creature_) | ||||
|     : ID(IID), | ||||
|     owner(Owner), | ||||
|     myStack(creature_), | ||||
|     creature(creature_ ? creature_->type : nullptr), | ||||
|     upg(Upg) | ||||
| 	: ID(IID), | ||||
| 	owner(Owner), | ||||
| 	myStack(creature_), | ||||
| 	creature(creature_ ? creature_->type : nullptr), | ||||
| 	upg(Upg) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
| @@ -381,8 +381,8 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGa | ||||
|  | ||||
| 	std::string imgName = owner->smallIcons ? "cprsmall" : "TWCRPORT"; | ||||
|  | ||||
| 	creatureImage =  std::make_shared<CAnimImage>(imgName, 0); | ||||
| 		creatureImage->disable(); | ||||
| 	creatureImage = std::make_shared<CAnimImage>(imgName, 0); | ||||
| 	creatureImage->disable(); | ||||
|  | ||||
| 	selectionImage = std::make_shared<CAnimImage>(imgName, 1); | ||||
| 	selectionImage->disable(); | ||||
|   | ||||
| @@ -111,12 +111,14 @@ void CBuildingRect::hover(bool on) | ||||
|  | ||||
| void CBuildingRect::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	if( previousState && getBuilding() && area && !down && (parent->selectedBuilding==this)) | ||||
| 		if (!CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image | ||||
| 	if(previousState && getBuilding() && area && !down && (parent->selectedBuilding==this)) | ||||
| 	{ | ||||
| 		if(!CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y)) //inside building image | ||||
| 		{ | ||||
| 			auto building = getBuilding(); | ||||
| 			parent->buildingClicked(building->bid, building->subId, building->upgrade); | ||||
| } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBuildingRect::clickRight(tribool down, bool previousState) | ||||
| @@ -606,8 +608,7 @@ void CCastleBuildings::recreate() | ||||
|  | ||||
| 		const CStructure * toAdd = *boost::max_element(entry.second, [=](const CStructure * a, const CStructure * b) | ||||
| 		{ | ||||
| 			return build->getDistance(a->building->bid) | ||||
| 			     < build->getDistance(b->building->bid); | ||||
| 			return build->getDistance(a->building->bid) < build->getDistance(b->building->bid); | ||||
| 		}); | ||||
|  | ||||
| 		buildings.push_back(std::make_shared<CBuildingRect>(this, town, toAdd)); | ||||
| @@ -880,9 +881,9 @@ void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID: | ||||
| 		else //Mystic Pond produced something; | ||||
| 		{ | ||||
| 			descr += "\n\n" + hasProduced; | ||||
| 		boost::algorithm::replace_first(descr,"%s",CGI->generaltexth->restypes[town->bonusValue.first]); | ||||
| 		boost::algorithm::replace_first(descr,"%d",boost::lexical_cast<std::string>(town->bonusValue.second)); | ||||
| 	} | ||||
| 			boost::algorithm::replace_first(descr,"%s",CGI->generaltexth->restypes[town->bonusValue.first]); | ||||
| 			boost::algorithm::replace_first(descr,"%d",boost::lexical_cast<std::string>(town->bonusValue.second)); | ||||
| 		} | ||||
| 	} | ||||
| 	LOCPLINT->showInfoDialog(descr, comps); | ||||
| } | ||||
|   | ||||
| @@ -32,20 +32,20 @@ public: | ||||
| 	using PostHandler = std::function<void(const E &)>; | ||||
| 	using BusTag = const void *; | ||||
|  | ||||
| 	std::unique_ptr<EventSubscription> subscribeBefore(BusTag tag, PreHandler && cb) | ||||
| 	std::unique_ptr<EventSubscription> subscribeBefore(BusTag tag, PreHandler && handler) | ||||
| 	{ | ||||
| 		boost::unique_lock<boost::shared_mutex> lock(mutex); | ||||
|  | ||||
| 		auto storage = std::make_shared<PreHandlerStorage>(std::move(cb)); | ||||
| 		auto storage = std::make_shared<PreHandlerStorage>(std::move(handler)); | ||||
| 		preHandlers[tag].push_back(storage); | ||||
| 		return make_unique<PreSubscription>(tag, storage); | ||||
| 	} | ||||
|  | ||||
| 	std::unique_ptr<EventSubscription> subscribeAfter(BusTag tag, PostHandler && cb) | ||||
| 	std::unique_ptr<EventSubscription> subscribeAfter(BusTag tag, PostHandler && handler) | ||||
| 	{ | ||||
| 		boost::unique_lock<boost::shared_mutex> lock(mutex); | ||||
|  | ||||
| 		auto storage = std::make_shared<PostHandlerStorage>(std::move(cb)); | ||||
| 		auto storage = std::make_shared<PostHandlerStorage>(std::move(handler)); | ||||
| 		postHandlers[tag].push_back(storage); | ||||
| 		return make_unique<PostSubscription>(tag, storage); | ||||
| 	} | ||||
| @@ -84,18 +84,18 @@ private: | ||||
| 	class HandlerStorage | ||||
| 	{ | ||||
| 	public: | ||||
| 		explicit HandlerStorage(T && cb_) | ||||
| 			: cb(cb_) | ||||
| 		explicit HandlerStorage(T && handler_) | ||||
| 			: handler(handler_) | ||||
| 		{ | ||||
| 		} | ||||
|  | ||||
| 		STRONG_INLINE | ||||
| 		void operator()(E & event) | ||||
| 		{ | ||||
| 			cb(event); | ||||
| 			handler(event); | ||||
| 		} | ||||
| 	private: | ||||
| 		T cb; | ||||
| 		T handler; | ||||
| 	}; | ||||
|  | ||||
| 	using PreHandlerStorage = HandlerStorage<PreHandler>; | ||||
| @@ -104,8 +104,8 @@ private: | ||||
| 	class PreSubscription : public EventSubscription | ||||
| 	{ | ||||
| 	public: | ||||
| 		PreSubscription(BusTag tag_, std::shared_ptr<PreHandlerStorage> cb_) | ||||
| 			: cb(cb_), | ||||
| 		PreSubscription(BusTag tag_, std::shared_ptr<PreHandlerStorage> handler_) | ||||
| 			: handler(handler_), | ||||
| 			tag(tag_) | ||||
| 		{ | ||||
| 		} | ||||
| @@ -113,18 +113,18 @@ private: | ||||
| 		virtual ~PreSubscription() | ||||
| 		{ | ||||
| 			auto registry = E::getRegistry(); | ||||
| 			registry->unsubscribe(tag, cb, registry->preHandlers); | ||||
| 			registry->unsubscribe(tag, handler, registry->preHandlers); | ||||
| 		} | ||||
| 	private: | ||||
| 		BusTag tag; | ||||
| 		std::shared_ptr<PreHandlerStorage> cb; | ||||
| 		std::shared_ptr<PreHandlerStorage> handler; | ||||
| 	}; | ||||
|  | ||||
| 	class PostSubscription : public EventSubscription | ||||
| 	{ | ||||
| 	public: | ||||
| 		PostSubscription(BusTag tag_, std::shared_ptr<PostHandlerStorage> cb_) | ||||
| 			: cb(cb_), | ||||
| 		PostSubscription(BusTag tag_, std::shared_ptr<PostHandlerStorage> handler_) | ||||
| 			: handler(handler_), | ||||
| 			tag(tag_) | ||||
| 		{ | ||||
| 		} | ||||
| @@ -132,11 +132,11 @@ private: | ||||
| 		virtual ~PostSubscription() | ||||
| 		{ | ||||
| 			auto registry = E::getRegistry(); | ||||
| 			registry->unsubscribe(tag, cb, registry->postHandlers); | ||||
| 			registry->unsubscribe(tag, handler, registry->postHandlers); | ||||
| 		} | ||||
| 	private: | ||||
| 		BusTag tag; | ||||
| 		std::shared_ptr<PostHandlerStorage> cb; | ||||
| 		std::shared_ptr<PostHandlerStorage> handler; | ||||
| 	}; | ||||
|  | ||||
| 	boost::shared_mutex mutex; | ||||
|   | ||||
| @@ -697,7 +697,7 @@ bool CModHandler::checkDependencies(const std::vector <TModID> & input) const | ||||
|  | ||||
| 		for(const TModID & dep : mod.dependencies) | ||||
| 		{ | ||||
| 			if (!vstd::contains(input, dep)) | ||||
| 			if(!vstd::contains(input, dep)) | ||||
| 			{ | ||||
| 				logMod->error("Error: Mod %s requires missing %s!", mod.name, dep); | ||||
| 				return false; | ||||
| @@ -706,14 +706,14 @@ bool CModHandler::checkDependencies(const std::vector <TModID> & input) const | ||||
|  | ||||
| 		for(const TModID & conflicting : mod.conflicts) | ||||
| 		{ | ||||
| 			if (vstd::contains(input, conflicting)) | ||||
| 			if(vstd::contains(input, conflicting)) | ||||
| 			{ | ||||
| 				logMod->error("Error: Mod %s conflicts with %s!", mod.name, allMods.at(conflicting).name); | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (hasCircularDependency(id)) | ||||
| 		if(hasCircularDependency(id)) | ||||
| 			return false; | ||||
| 	} | ||||
| 	return true; | ||||
| @@ -732,7 +732,7 @@ std::vector <TModID> CModHandler::resolveDependencies(std::vector <TModID> modsT | ||||
| 			{ | ||||
| 				logMod->error("Mod '%s' will not work: it depends on mod '%s', which is not installed.", mod.name, dependency); | ||||
| 				res = false; //continue iterations, since we should show all errors for the current mod. | ||||
| 		} | ||||
| 			} | ||||
| 		} | ||||
| 		return res; | ||||
| 	}; | ||||
| @@ -745,19 +745,19 @@ std::vector <TModID> CModHandler::resolveDependencies(std::vector <TModID> modsT | ||||
| 				brokenMods.push_back(mod); | ||||
| 		} | ||||
| 		if(!brokenMods.empty()) | ||||
| 			{ | ||||
| 		{ | ||||
| 			vstd::erase_if(modsToResolve, [&](TModID mid) | ||||
| 			{ | ||||
| 				return brokenMods.end() != std::find(brokenMods.begin(), brokenMods.end(), mid); | ||||
| 			}); | ||||
| 			brokenMods.clear(); | ||||
| 				continue; | ||||
| 			} | ||||
| 		break; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 	boost::range::sort(modsToResolve); | ||||
| 	return modsToResolve; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::vector<std::string> CModHandler::getModList(std::string path) | ||||
| { | ||||
|   | ||||
| @@ -560,29 +560,31 @@ R CTownHandler::getMappedValue(const K key, const R defval, const std::map<K, R> | ||||
|  | ||||
| template<typename R> | ||||
| R CTownHandler::getMappedValue(const JsonNode & node, const R defval, const std::map<std::string, R> & map, bool required) | ||||
| 	{ | ||||
| { | ||||
| 	if(!node.isNull() && node.getType() == JsonNode::JsonType::DATA_STRING) | ||||
| 		return getMappedValue<R, std::string>(node.String(), defval, map, required); | ||||
| 	return defval; | ||||
| } | ||||
|  | ||||
| void CTownHandler::addBonusesForVanilaBuilding(CBuilding * building) | ||||
| 	{ | ||||
| { | ||||
| 	std::shared_ptr<Bonus> b; | ||||
| 	static TPropagatorPtr playerPropagator = std::make_shared<CPropagatorNodeType>(CBonusSystemNode::ENodeTypes::PLAYER); | ||||
|  | ||||
| 	if(building->subId == BuildingSubID::NONE) | ||||
| 		{ | ||||
| 	{ | ||||
| 		if(building->bid == BuildingID::TAVERN) | ||||
| 			b = createBonus(building, Bonus::MORALE, +1); | ||||
| 		else if(building->bid == BuildingID::GRAIL | ||||
| 				&& building->town->faction != nullptr | ||||
| 				&& boost::algorithm::ends_with(building->town->faction->identifier, ":cove")) | ||||
| 		{ | ||||
| 				static TPropagatorPtr allCreaturesPropagator(new CPropagatorNodeType(CBonusSystemNode::ENodeTypes::ALL_CREATURES)); | ||||
| 				static auto factionLimiter = std::make_shared<CreatureFactionLimiter>(building->town->faction->index); | ||||
| 				b = createBonus(building, Bonus::NO_TERRAIN_PENALTY, 0, allCreaturesPropagator); | ||||
| 				b->addLimiter(factionLimiter); | ||||
| 			b = createBonus(building, Bonus::MORALE, +1); | ||||
| 		} | ||||
| 		else if(building->bid == BuildingID::GRAIL | ||||
| 			&& building->town->faction != nullptr | ||||
| 			&& boost::algorithm::ends_with(building->town->faction->identifier, ":cove")) | ||||
| 		{ | ||||
| 			static TPropagatorPtr allCreaturesPropagator(new CPropagatorNodeType(CBonusSystemNode::ENodeTypes::ALL_CREATURES)); | ||||
| 			static auto factionLimiter = std::make_shared<CreatureFactionLimiter>(building->town->faction->index); | ||||
| 			b = createBonus(building, Bonus::NO_TERRAIN_PENALTY, 0, allCreaturesPropagator); | ||||
| 			b->addLimiter(factionLimiter); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
|   | ||||
| @@ -121,7 +121,7 @@ void ScriptImpl::resolveHost() | ||||
| 	else if(sourcePathId.getType() == EResType::LUA) | ||||
| 		host = owner->lua; | ||||
| 	else | ||||
| 		throw std::runtime_error("Unknown script language in:"+sourcePath); | ||||
| 		throw std::runtime_error("Unknown script language in:" + sourcePath); | ||||
| } | ||||
|  | ||||
| PoolImpl::PoolImpl(const Environment * ENV) | ||||
| @@ -217,7 +217,8 @@ std::vector<JsonNode> ScriptHandler::loadLegacyData(size_t dataSize) | ||||
| 	return std::vector<JsonNode>(); | ||||
| } | ||||
|  | ||||
| ScriptPtr ScriptHandler::loadFromJson(vstd::CLoggerBase * logger, const std::string & scope, const JsonNode & json, const std::string & identifier) const | ||||
| ScriptPtr ScriptHandler::loadFromJson(vstd::CLoggerBase * logger, const std::string & scope, | ||||
| 	const JsonNode & json, const std::string & identifier) const | ||||
| { | ||||
| 	ScriptPtr ret = std::make_shared<ScriptImpl>(this); | ||||
|  | ||||
|   | ||||
| @@ -1407,9 +1407,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const  battl | ||||
| 			{ | ||||
| 				auto st = battleGetUnitByPos(tile, true); | ||||
| 				if(st && battleMatchOwner(st, attacker)) //only hostile stacks - does it work well with Berserk? | ||||
| 				{ | ||||
| 					at.hostileCreaturePositions.insert(tile); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -1429,44 +1427,42 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const  battl | ||||
| 			//friendly stacks can also be damaged by Dragon Breath | ||||
| 			auto st = battleGetUnitByPos(tile, true); | ||||
| 			if(st && st != attacker) | ||||
| 			{ | ||||
| 					at.friendlyCreaturePositions.insert(tile); | ||||
| 			} | ||||
| 				at.friendlyCreaturePositions.insert(tile); | ||||
| 		} | ||||
| 	} | ||||
| 	else if(attacker->hasBonusOfType(Bonus::TWO_HEX_ATTACK_BREATH)) | ||||
| 	{ | ||||
| 		int pos = BattleHex::mutualPosition(destinationTile, hex); | ||||
| 		if (pos > -1) //only adjacent hexes are subject of dragon breath calculation | ||||
| 		if(pos > -1) //only adjacent hexes are subject of dragon breath calculation | ||||
| 		{ | ||||
| 		std::vector<BattleHex> hexes; //only one, in fact | ||||
| 		int pseudoVector = destinationTile.hex - hex; | ||||
| 		switch(pseudoVector) | ||||
| 		{ | ||||
| 		case 1: | ||||
| 		case -1: | ||||
| 			BattleHex::checkAndPush(destinationTile.hex + pseudoVector, hexes); | ||||
| 			break; | ||||
| 		case WN: //17 //left-down or right-down | ||||
| 		case -WN: //-17 //left-up or right-up | ||||
| 		case WN + 1: //18 //right-down | ||||
| 		case -WN + 1: //-16 //right-up | ||||
| 			BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : -1), hexes); | ||||
| 			break; | ||||
| 		case WN - 1: //16 //left-down | ||||
| 		case -WN - 1: //-18 //left-up | ||||
| 			BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : 0), hexes); | ||||
| 			break; | ||||
| 		} | ||||
| 		for(BattleHex tile : hexes) | ||||
| 		{ | ||||
| 			//friendly stacks can also be damaged by Dragon Breath | ||||
| 			std::vector<BattleHex> hexes; //only one, in fact | ||||
| 			int pseudoVector = destinationTile.hex - hex; | ||||
| 			switch(pseudoVector) | ||||
| 			{ | ||||
| 			case 1: | ||||
| 			case -1: | ||||
| 				BattleHex::checkAndPush(destinationTile.hex + pseudoVector, hexes); | ||||
| 				break; | ||||
| 			case WN: //17 //left-down or right-down | ||||
| 			case -WN: //-17 //left-up or right-up | ||||
| 			case WN + 1: //18 //right-down | ||||
| 			case -WN + 1: //-16 //right-up | ||||
| 				BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : -1), hexes); | ||||
| 				break; | ||||
| 			case WN - 1: //16 //left-down | ||||
| 			case -WN - 1: //-18 //left-up | ||||
| 				BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : 0), hexes); | ||||
| 				break; | ||||
| 			} | ||||
| 			for(BattleHex tile : hexes) | ||||
| 			{ | ||||
| 				//friendly stacks can also be damaged by Dragon Breath | ||||
| 				auto st = battleGetUnitByPos(tile, true); | ||||
| 				if (st != nullptr) | ||||
| 				at.friendlyCreaturePositions.insert(tile); | ||||
| 				if(st != nullptr) | ||||
| 					at.friendlyCreaturePositions.insert(tile); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| 	return at; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -850,18 +850,18 @@ void CGTownInstance::updateBonusingBuildings() //update to version 792 | ||||
| 		//firstly, update subtype for the Bonusing objects, which are already stored in the bonusing list | ||||
| 		for(auto building : bonusingBuildings) //no garrison bonuses here, only week and visiting bonuses | ||||
| 		{ | ||||
| 			switch (this->town->faction->index) | ||||
| 			switch(this->town->faction->index) | ||||
| 			{ | ||||
| 		case ETownType::CASTLE: | ||||
| 				building->setBuildingSubtype(BuildingSubID::STABLES); | ||||
| 			case ETownType::CASTLE: | ||||
| 					building->setBuildingSubtype(BuildingSubID::STABLES); | ||||
| 			break; | ||||
|  | ||||
| 		case ETownType::DUNGEON: | ||||
| 			case ETownType::DUNGEON: | ||||
| 				if(building->getBuildingType() == BuildingID::SPECIAL_2) | ||||
| 					building->setBuildingSubtype(BuildingSubID::MANA_VORTEX); | ||||
| 				else if(building->getBuildingType() == BuildingID::SPECIAL_4) | ||||
| 					building->setBuildingSubtype(BuildingSubID::EXPERIENCE_VISITING_BONUS); | ||||
| 			break; | ||||
| 				break; | ||||
|  | ||||
| 			case ETownType::TOWER: | ||||
| 				building->setBuildingSubtype(BuildingSubID::KNOWLEDGE_VISITING_BONUS); | ||||
| @@ -875,10 +875,10 @@ void CGTownInstance::updateBonusingBuildings() //update to version 792 | ||||
| 				building->setBuildingSubtype(BuildingSubID::SPELL_POWER_VISITING_BONUS); | ||||
| 				break; | ||||
|  | ||||
| 		case ETownType::FORTRESS: | ||||
| 			case ETownType::FORTRESS: | ||||
| 				building->setBuildingSubtype(BuildingSubID::DEFENSE_VISITING_BONUS); | ||||
| 			break; | ||||
| 	} | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	//secondly, supplement bonusing buildings list and active bonuses; subtypes for these objects are already set in update792 | ||||
| @@ -1264,14 +1264,14 @@ void CGTownInstance::recreateBuildingsBonuses() | ||||
| 			continue; | ||||
|  | ||||
| 		for(auto bonus : building->buildingBonuses) | ||||
| { | ||||
| 		{ | ||||
| 			if(bonus->propagator != nullptr && bonus->propagator->getPropagatorType() == ALL_CREATURES) | ||||
| 				VLC->creh->addBonusForAllCreatures(bonus); | ||||
| 			else | ||||
| 				addNewBonus(bonus); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| } | ||||
|  | ||||
| void CGTownInstance::setVisitingHero(CGHeroInstance *h) | ||||
| { | ||||
| @@ -1353,11 +1353,11 @@ int CGTownInstance::getTownLevel() const | ||||
| 	// count all buildings that are not upgrades | ||||
| 	int level = 0; | ||||
|  | ||||
| 	for (const auto & bid : builtBuildings) | ||||
| 	for(const auto & bid : builtBuildings) | ||||
| 	{ | ||||
| 		if(town->buildings.at(bid)->upgrade == BuildingID::NONE) | ||||
| 			level++; | ||||
| } | ||||
| 	} | ||||
| 	return level; | ||||
| } | ||||
|  | ||||
| @@ -1685,7 +1685,7 @@ void COPWBonus::setProperty(ui8 what, ui32 val) | ||||
| void COPWBonus::onHeroVisit (const CGHeroInstance * h) const | ||||
| { | ||||
| 	ObjectInstanceID heroID = h->id; | ||||
| 	if (town->hasBuilt(bID)) | ||||
| 	if(town->hasBuilt(bID)) | ||||
| 	{ | ||||
| 		InfoWindow iw; | ||||
| 		iw.player = h->tempOwner; | ||||
| @@ -1693,37 +1693,37 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const | ||||
| 		switch (this->bType) | ||||
| 		{ | ||||
| 		case BuildingSubID::STABLES: | ||||
| 				if (!h->hasBonusFrom(Bonus::OBJECT, Obj::STABLES)) //does not stack with advMap Stables | ||||
| 				{ | ||||
| 					GiveBonus gb; | ||||
| 					gb.bonus = Bonus(Bonus::ONE_WEEK, Bonus::LAND_MOVEMENT, Bonus::OBJECT, 600, 94, VLC->generaltexth->arraytxt[100]); | ||||
| 					gb.id = heroID.getNum(); | ||||
| 					cb->giveHeroBonus(&gb); | ||||
| 			if(!h->hasBonusFrom(Bonus::OBJECT, Obj::STABLES)) //does not stack with advMap Stables | ||||
| 			{ | ||||
| 				GiveBonus gb; | ||||
| 				gb.bonus = Bonus(Bonus::ONE_WEEK, Bonus::LAND_MOVEMENT, Bonus::OBJECT, 600, 94, VLC->generaltexth->arraytxt[100]); | ||||
| 				gb.id = heroID.getNum(); | ||||
| 				cb->giveHeroBonus(&gb); | ||||
|  | ||||
| 					SetMovePoints mp; | ||||
| 					mp.val = 600; | ||||
| 					mp.absolute = false; | ||||
| 					mp.hid = heroID; | ||||
| 					cb->setMovePoints(&mp); | ||||
| 				SetMovePoints mp; | ||||
| 				mp.val = 600; | ||||
| 				mp.absolute = false; | ||||
| 				mp.hid = heroID; | ||||
| 				cb->setMovePoints(&mp); | ||||
|  | ||||
| 					iw.text << VLC->generaltexth->allTexts[580]; | ||||
| 					cb->showInfoDialog(&iw); | ||||
| 				} | ||||
| 				break; | ||||
| 				iw.text << VLC->generaltexth->allTexts[580]; | ||||
| 				cb->showInfoDialog(&iw); | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 		case BuildingSubID::MANA_VORTEX: | ||||
| 				if (visitors.empty()) | ||||
| 				{ | ||||
| 					if (h->mana < h->manaLimit() * 2) | ||||
| 			if(visitors.empty()) | ||||
| 			{ | ||||
| 				if(h->mana < h->manaLimit() * 2) | ||||
| 					cb->setManaPoints (heroID, 2 * h->manaLimit()); | ||||
| 					//TODO: investigate line below | ||||
| 					//cb->setObjProperty (town->id, ObjProperty::VISITED, true); | ||||
| 					iw.text << getVisitingBonusGreeting(); | ||||
| 					cb->showInfoDialog(&iw); | ||||
| 					//extra visit penalty if hero alredy had double mana points (or even more?!) | ||||
| 					town->addHeroToStructureVisitors(h, indexOnTV); | ||||
| 				} | ||||
| 				break; | ||||
| 				//TODO: investigate line below | ||||
| 				//cb->setObjProperty (town->id, ObjProperty::VISITED, true); | ||||
| 				iw.text << getVisitingBonusGreeting(); | ||||
| 				cb->showInfoDialog(&iw); | ||||
| 				//extra visit penalty if hero alredy had double mana points (or even more?!) | ||||
| 				town->addHeroToStructureVisitors(h, indexOnTV); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1750,37 +1750,37 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const | ||||
| 		InfoWindow iw; | ||||
| 		PrimarySkill::PrimarySkill what = PrimarySkill::NONE; | ||||
|  | ||||
| 		switch (bType) | ||||
| 		switch(bType) | ||||
| 		{ | ||||
| 		case BuildingSubID::KNOWLEDGE_VISITING_BONUS: //wall of knowledge | ||||
| 						what = PrimarySkill::KNOWLEDGE; | ||||
| 						val = 1; | ||||
| 						iw.components.push_back (Component(Component::PRIM_SKILL, 3, 1, 0)); | ||||
| 						break; | ||||
| 			what = PrimarySkill::KNOWLEDGE; | ||||
| 			val = 1; | ||||
| 			iw.components.push_back(Component(Component::PRIM_SKILL, 3, 1, 0)); | ||||
| 			break; | ||||
|  | ||||
| 		case BuildingSubID::SPELL_POWER_VISITING_BONUS: //order of fire | ||||
| 						what = PrimarySkill::SPELL_POWER; | ||||
| 						val = 1; | ||||
| 						iw.components.push_back (Component(Component::PRIM_SKILL, 2, 1, 0)); | ||||
| 						break; | ||||
| 			what = PrimarySkill::SPELL_POWER; | ||||
| 			val = 1; | ||||
| 			iw.components.push_back(Component(Component::PRIM_SKILL, 2, 1, 0)); | ||||
| 			break; | ||||
|  | ||||
| 		case BuildingSubID::ATTACK_VISITING_BONUS: //hall of Valhalla | ||||
| 						what = PrimarySkill::ATTACK; | ||||
| 						val = 1; | ||||
| 						iw.components.push_back (Component(Component::PRIM_SKILL, 0, 1, 0)); | ||||
| 						break; | ||||
| 			what = PrimarySkill::ATTACK; | ||||
| 			val = 1; | ||||
| 			iw.components.push_back(Component(Component::PRIM_SKILL, 0, 1, 0)); | ||||
| 			break; | ||||
|  | ||||
| 		case BuildingSubID::EXPERIENCE_VISITING_BONUS: //academy of battle scholars | ||||
| 						what = PrimarySkill::EXPERIENCE; | ||||
| 			what = PrimarySkill::EXPERIENCE; | ||||
| 			val = static_cast<int>(h->calculateXp(1000)); | ||||
| 						iw.components.push_back (Component(Component::EXPERIENCE, 0, val, 0)); | ||||
| 						break; | ||||
| 			iw.components.push_back(Component(Component::EXPERIENCE, 0, val, 0)); | ||||
| 			break; | ||||
|  | ||||
| 		case BuildingSubID::DEFENSE_VISITING_BONUS: //cage of warlords | ||||
| 						what = PrimarySkill::DEFENSE; | ||||
| 						val = 1; | ||||
| 						iw.components.push_back (Component(Component::PRIM_SKILL, 1, 1, 0)); | ||||
| 						break; | ||||
| 			what = PrimarySkill::DEFENSE; | ||||
| 			val = 1; | ||||
| 			iw.components.push_back(Component(Component::PRIM_SKILL, 1, 1, 0)); | ||||
| 			break; | ||||
|  | ||||
| 		case BuildingSubID::CUSTOM_VISITING_BONUS: | ||||
| 			const auto building = town->town->buildings.at(bID); | ||||
| @@ -1788,19 +1788,20 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const | ||||
| 			{ | ||||
| 				const auto & bonuses = building->onVisitBonuses; | ||||
| 				applyBonuses(const_cast<CGHeroInstance *>(h), bonuses); | ||||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		if(what != PrimarySkill::NONE) | ||||
| 		{ | ||||
| 		iw.player = cb->getOwner(heroID); | ||||
| 			iw.text << getVisitingBonusGreeting(); | ||||
| 		cb->showInfoDialog(&iw); | ||||
| 		cb->changePrimSkill (cb->getHero(heroID), what, val); | ||||
| 			town->addHeroToStructureVisitors(h, indexOnTV); | ||||
| 			iw.player = cb->getOwner(heroID); | ||||
| 				iw.text << getVisitingBonusGreeting(); | ||||
| 			cb->showInfoDialog(&iw); | ||||
| 			cb->changePrimSkill (cb->getHero(heroID), what, val); | ||||
| 				town->addHeroToStructureVisitors(h, indexOnTV); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| } | ||||
|  | ||||
| void CTownBonus::applyBonuses(CGHeroInstance * h, const BonusList & bonuses) const | ||||
| { | ||||
|   | ||||
| @@ -207,11 +207,11 @@ void CObjectClassesHandler::loadObjectEntry(const std::string & identifier, cons | ||||
| 		return str.compare(obj->subObjects[id]->subTypeName) == 0; | ||||
| 	}); | ||||
|  | ||||
| 	if (overrideForce) // DO NOT override mod handlers by default | ||||
| 	if(overrideForce) // DO NOT override mod handlers by default | ||||
| 	{ | ||||
| 	obj->subObjects[id] = handler; | ||||
| 	obj->subIds[convertedId] = id; | ||||
| } | ||||
| 		obj->subObjects[id] = handler; | ||||
| 		obj->subIds[convertedId] = id; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		logGlobal->warn("Don't override handler %s in object %s(%d)::%s(%d) subTypeName : %s" | ||||
|   | ||||
| @@ -203,7 +203,7 @@ bool BattleSpellMechanics::canBeCast(Problem & problem) const | ||||
| 	return effects->applicable(problem, this); | ||||
| } | ||||
|  | ||||
| bool BattleSpellMechanics::canBeCastAt(Problem & problem, const Target & target) const | ||||
| bool BattleSpellMechanics::canBeCastAt(const Target & target, Problem & problem) const | ||||
| { | ||||
| 	if(!canBeCast(problem)) | ||||
| 		return false; | ||||
| @@ -618,7 +618,7 @@ std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t in | ||||
|  | ||||
| 				detail::ProblemImpl ingored; | ||||
|  | ||||
| 				if(canBeCastAt(ingored, tmp)) | ||||
| 				if(canBeCastAt(tmp, ingored)) | ||||
| 					ret.emplace_back(dest); | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -28,7 +28,7 @@ public: | ||||
| 	void applyEffects(ServerCallback * server, const Target & targets, bool indirect, bool ignoreImmunity) const override; | ||||
|  | ||||
| 	bool canBeCast(Problem & problem) const override; | ||||
| 	bool canBeCastAt(Problem & problem, const Target & target) const override; | ||||
| 	bool canBeCastAt(const Target & target, Problem & problem) const override; | ||||
|  | ||||
| 	void cast(ServerCallback * server, const Target & target) override final; | ||||
| 	void castEval(ServerCallback * server, const Target & target) override final; | ||||
|   | ||||
| @@ -183,7 +183,7 @@ public: | ||||
| 	virtual std::vector<const CStack *> getAffectedStacks(const Target & target) const = 0; | ||||
|  | ||||
| 	virtual bool canBeCast(Problem & problem) const = 0; | ||||
| 	virtual bool canBeCastAt(Problem & problem, const Target & target) const = 0; | ||||
| 	virtual bool canBeCastAt(const Target & target, Problem & problem) const = 0; | ||||
|  | ||||
| 	virtual void applyEffects(ServerCallback * server, const Target & targets, bool indirect, bool ignoreImmunity) const = 0; | ||||
|  | ||||
|   | ||||
| @@ -39,9 +39,9 @@ const std::vector<ServicesProxy::CustomRegType> ServicesProxy::REGISTER_CUSTOM = | ||||
| 	{"creatures", LuaMethodWrapper<Services, decltype(&Services::creatures), &Services::creatures>::invoke, false}, | ||||
| 	{"factions", LuaMethodWrapper<Services, decltype(&Services::factions), &Services::factions>::invoke, false}, | ||||
| 	{"heroClasses", LuaMethodWrapper<Services, decltype(&Services::heroClasses), &Services::heroClasses>::invoke, false}, | ||||
| 	{"heroTypes", LuaMethodWrapper<Services,decltype(&Services::heroTypes), &Services::heroTypes>::invoke, false}, | ||||
| 	{"heroTypes", LuaMethodWrapper<Services, decltype(&Services::heroTypes), &Services::heroTypes>::invoke, false}, | ||||
| 	{"spells", LuaMethodWrapper<Services, decltype(&Services::spells), &Services::spells>::invoke, false}, | ||||
| 	{"skills", LuaMethodWrapper<Services,decltype(&Services::skills), &Services::skills>::invoke, false}, | ||||
| 	{"skills", LuaMethodWrapper<Services, decltype(&Services::skills), &Services::skills>::invoke, false}, | ||||
| }; | ||||
|  | ||||
| VCMI_REGISTER_CORE_SCRIPT_API(ArtifactServiceProxy, "Artifacts"); | ||||
|   | ||||
| @@ -5631,9 +5631,9 @@ void CGameHandler::attackCasting(bool ranged, Bonus::BonusType attackMode, const | ||||
|  | ||||
| 			auto m = spell->battleMechanics(¶meters); | ||||
|  | ||||
| 			spells::detail::ProblemImpl ingored; | ||||
| 			spells::detail::ProblemImpl ignored; | ||||
|  | ||||
| 			if(!m->canBeCastAt(ingored, target)) | ||||
| 			if(!m->canBeCastAt(target, ignored)) | ||||
| 				continue; | ||||
|  | ||||
| 			//check if spell should be cast (probability handling) | ||||
|   | ||||
| @@ -297,7 +297,7 @@ TEST_F(CGameStateTest, issue2765) | ||||
|  | ||||
| 		auto m = age->battleMechanics(&cast); | ||||
|  | ||||
| 		EXPECT_FALSE(m->canBeCastAt(problemMock, target)); | ||||
| 		EXPECT_FALSE(m->canBeCastAt(target, problemMock)); | ||||
|  | ||||
| 		EXPECT_TRUE(cast.castIfPossible(this, target));//should be possible, but with no effect (change to aimed cast check?) | ||||
|  | ||||
| @@ -397,7 +397,7 @@ TEST_F(CGameStateTest, battleResurrection) | ||||
|  | ||||
| 		EXPECT_TRUE(m->canBeCast(problemMock)); | ||||
|  | ||||
| 		EXPECT_TRUE(m->canBeCastAt(problemMock, target)); | ||||
| 		EXPECT_TRUE(m->canBeCastAt(target, problemMock)); | ||||
|  | ||||
| 		cast.cast(this, target); | ||||
| // | ||||
|   | ||||
| @@ -25,7 +25,7 @@ public: | ||||
| 	MOCK_CONST_METHOD1(getAffectedStacks, std::vector<const CStack *>(const Target &)); | ||||
|  | ||||
| 	MOCK_CONST_METHOD1(canBeCast, bool(Problem &)); | ||||
| 	MOCK_CONST_METHOD2(canBeCastAt, bool(Problem &, const Target &)); | ||||
| 	MOCK_CONST_METHOD2(canBeCastAt, bool(const Target &, Problem &)); | ||||
|  | ||||
| 	MOCK_CONST_METHOD4(applyEffects, void(ServerCallback *, const Target &, bool, bool)); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user