mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Fix bug: LandMine is not exploding to enemies. (#630)
* The reason is, the mine has attribute hidden=true; when enemy unit moves, the code in BattleInfo.cpp MoveUnit() (line 817) will update the revealed to true; then in the CGameHandler.cpp handleDamageFromObstacle() (line 4846) is checking , and the condition battleIsObstacleVisibleForSide() will return true, so the effect will not be triggerred. Resolution: 1. Remove the "revealed=true" in moveUnit(), and in handleDamageFromObstacle, remove the "const" restrict for obstacle, and then update revealed to true; 2. After the takeDamage function, add a pack "BattleObstaclesChanged" to update the obstacle to be "revealed=true".
This commit is contained in:
		| @@ -371,6 +371,11 @@ void HypotheticBattle::addObstacle(const ObstacleChanges & changes) | ||||
| 	//TODO:HypotheticBattle::addObstacle | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::updateObstacle(const ObstacleChanges& changes) | ||||
| { | ||||
| 	//TODO:HypotheticBattle::updateObstacle | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::removeObstacle(uint32_t id) | ||||
| { | ||||
| 	//TODO:HypotheticBattle::removeObstacle | ||||
|   | ||||
| @@ -98,6 +98,7 @@ public: | ||||
| 	void setWallState(int partOfWall, si8 state) override; | ||||
|  | ||||
| 	void addObstacle(const ObstacleChanges & changes) override; | ||||
| 	void updateObstacle(const ObstacleChanges& changes) override; | ||||
| 	void removeObstacle(uint32_t id) override; | ||||
|  | ||||
| 	uint32_t nextUnitId() const override; | ||||
|   | ||||
| @@ -1535,6 +1535,9 @@ DLL_LINKAGE void BattleObstaclesChanged::applyBattle(IBattleState * battleState) | ||||
| 		case BattleChanges::EOperation::ADD: | ||||
| 			battleState->addObstacle(change); | ||||
| 			break; | ||||
| 		case BattleChanges::EOperation::UPDATE: | ||||
| 			battleState->updateObstacle(change); | ||||
| 			break; | ||||
| 		default: | ||||
| 			logNetwork->error("Unknown obstacle operation %d", (int)change.operation); | ||||
| 			break; | ||||
|   | ||||
| @@ -809,17 +809,6 @@ void BattleInfo::moveUnit(uint32_t id, BattleHex destination) | ||||
| 		logGlobal->error("Cannot find stack %d", id); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	for(auto & oi : obstacles) | ||||
| 	{ | ||||
| 		if((oi->obstacleType == CObstacleInstance::SPELL_CREATED) && vstd::contains(oi->getAffectedTiles(), destination)) | ||||
| 		{ | ||||
| 			SpellCreatedObstacle * obstacle = dynamic_cast<SpellCreatedObstacle*>(oi.get()); | ||||
| 			assert(obstacle); | ||||
| 			if(obstacle->casterSide != sta->unitSide() && obstacle->hidden) | ||||
| 				obstacle->revealed = true; | ||||
| 		} | ||||
| 	} | ||||
| 	sta->position = destination; | ||||
| } | ||||
|  | ||||
| @@ -1029,6 +1018,26 @@ void BattleInfo::addObstacle(const ObstacleChanges & changes) | ||||
| 	obstacles.push_back(obstacle); | ||||
| } | ||||
|  | ||||
| void BattleInfo::updateObstacle(const ObstacleChanges& changes) | ||||
| { | ||||
| 	std::shared_ptr<SpellCreatedObstacle> changedObstacle = std::make_shared<SpellCreatedObstacle>(); | ||||
| 	changedObstacle->fromInfo(changes); | ||||
|  | ||||
| 	for(int i = 0; i < obstacles.size(); ++i) | ||||
| 	{ | ||||
| 		if(obstacles[i]->uniqueID == changes.id) // update this obstacle | ||||
| 		{ | ||||
| 			SpellCreatedObstacle * spellObstacle = dynamic_cast<SpellCreatedObstacle *>(obstacles[i].get()); | ||||
| 			assert(spellObstacle); | ||||
|  | ||||
| 			// Currently we only support to update the "revealed" property | ||||
| 			spellObstacle->revealed = changedObstacle->revealed; | ||||
| 			 | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void BattleInfo::removeObstacle(uint32_t id) | ||||
| { | ||||
| 	for(int i=0; i < obstacles.size(); ++i) | ||||
|   | ||||
| @@ -109,6 +109,7 @@ public: | ||||
| 	void setWallState(int partOfWall, si8 state) override; | ||||
|  | ||||
| 	void addObstacle(const ObstacleChanges & changes) override; | ||||
| 	void updateObstacle(const ObstacleChanges& changes) override; | ||||
| 	void removeObstacle(uint32_t id) override; | ||||
|  | ||||
| 	void addOrUpdateUnitBonus(CStack * sta, const Bonus & value, bool forceAdd); | ||||
|   | ||||
| @@ -155,8 +155,8 @@ void SpellCreatedObstacle::fromInfo(const ObstacleChanges & info) | ||||
| { | ||||
| 	uniqueID = info.id; | ||||
|  | ||||
| 	if(info.operation != ObstacleChanges::EOperation::ADD) | ||||
| 		logGlobal->error("ADD operation expected"); | ||||
| 	if(info.operation != ObstacleChanges::EOperation::ADD && info.operation != ObstacleChanges::EOperation::UPDATE) | ||||
| 		logGlobal->error("ADD or UPDATE operation expected"); | ||||
|  | ||||
|     JsonDeserializer deser(nullptr, info.data); | ||||
|     deser.serializeStruct("obstacle", *this); | ||||
| @@ -173,6 +173,7 @@ void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler) | ||||
| 	handler.serializeInt("casterSide", casterSide); | ||||
|  | ||||
| 	handler.serializeBool("hidden", hidden); | ||||
| 	handler.serializeBool("revealed", revealed); | ||||
| 	handler.serializeBool("passable", passable); | ||||
| 	handler.serializeBool("trigger", trigger); | ||||
| 	handler.serializeBool("trap", trap); | ||||
|   | ||||
| @@ -87,5 +87,6 @@ public: | ||||
| 	virtual void setWallState(int partOfWall, si8 state) = 0; | ||||
|  | ||||
| 	virtual void addObstacle(const ObstacleChanges & changes) = 0; | ||||
| 	virtual void updateObstacle(const ObstacleChanges & changes) = 0; | ||||
| 	virtual void removeObstacle(uint32_t id) = 0; | ||||
| }; | ||||
|   | ||||
| @@ -47,6 +47,7 @@ | ||||
| #include "../lib/serializer/CTypeList.h" | ||||
| #include "../lib/serializer/Connection.h" | ||||
| #include "../lib/serializer/Cast.h" | ||||
| #include "../lib/serializer/JsonSerializer.h" | ||||
|  | ||||
| #ifndef _MSC_VER | ||||
| #include <boost/thread/xtime.hpp> | ||||
| @@ -4857,8 +4858,29 @@ bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackI | ||||
| 					battleCast.applyEffects(spellEnv, true); | ||||
|  | ||||
| 					if(oneTimeObstacle) | ||||
| 					{ | ||||
| 						removeObstacle(*obstacle); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						// For the hidden spell created obstacles, e.g. QuickSand, it should be revealed after taking damage | ||||
| 						ObstacleChanges changeInfo; | ||||
| 						changeInfo.id = spellObstacle->uniqueID; | ||||
| 						changeInfo.operation = ObstacleChanges::EOperation::UPDATE; | ||||
|  | ||||
| 						SpellCreatedObstacle changedObstacle; | ||||
| 						changedObstacle.uniqueID = spellObstacle->uniqueID; | ||||
| 						changedObstacle.revealed = true; | ||||
|  | ||||
| 						changeInfo.data.clear(); | ||||
| 						JsonSerializer ser(nullptr, changeInfo.data); | ||||
| 						ser.serializeStruct("obstacle", changedObstacle); | ||||
|  | ||||
| 						BattleObstaclesChanged bocp; | ||||
| 						bocp.changes.emplace_back(changeInfo); | ||||
| 						sendAndApply(&bocp); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		else if(obstacle->obstacleType == CObstacleInstance::MOAT) | ||||
|   | ||||
| @@ -47,6 +47,7 @@ public: | ||||
| 	MOCK_METHOD2(setWallState, void(int, si8)); | ||||
| 	MOCK_METHOD1(addObstacle, void(const ObstacleChanges &)); | ||||
| 	MOCK_METHOD1(removeObstacle, void(uint32_t)); | ||||
| 	MOCK_METHOD1(updateObstacle, void(const ObstacleChanges &)); | ||||
| }; | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user