diff --git a/AI/BattleAI/StackWithBonuses.cpp b/AI/BattleAI/StackWithBonuses.cpp index fd53b325e..22137f0bc 100644 --- a/AI/BattleAI/StackWithBonuses.cpp +++ b/AI/BattleAI/StackWithBonuses.cpp @@ -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 diff --git a/AI/BattleAI/StackWithBonuses.h b/AI/BattleAI/StackWithBonuses.h index b37307147..5dd7f0aba 100644 --- a/AI/BattleAI/StackWithBonuses.h +++ b/AI/BattleAI/StackWithBonuses.h @@ -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; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 19c303d88..95426b76f 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -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; diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index 62e8e0c68..f7005ea3e 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -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(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 changedObstacle = std::make_shared(); + changedObstacle->fromInfo(changes); + + for(int i = 0; i < obstacles.size(); ++i) + { + if(obstacles[i]->uniqueID == changes.id) // update this obstacle + { + SpellCreatedObstacle * spellObstacle = dynamic_cast(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) diff --git a/lib/battle/BattleInfo.h b/lib/battle/BattleInfo.h index b66acb701..b32b09953 100644 --- a/lib/battle/BattleInfo.h +++ b/lib/battle/BattleInfo.h @@ -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); diff --git a/lib/battle/CObstacleInstance.cpp b/lib/battle/CObstacleInstance.cpp index 629873579..e276a15e5 100644 --- a/lib/battle/CObstacleInstance.cpp +++ b/lib/battle/CObstacleInstance.cpp @@ -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); diff --git a/lib/battle/IBattleState.h b/lib/battle/IBattleState.h index b6b7b2ca1..5f6f3df0e 100644 --- a/lib/battle/IBattleState.h +++ b/lib/battle/IBattleState.h @@ -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; }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ecabe1ebd..8cd46c11b 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -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 @@ -4857,7 +4858,28 @@ 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); + } } } } diff --git a/test/mock/mock_battle_IBattleState.h b/test/mock/mock_battle_IBattleState.h index dc0ae3336..c95152517 100644 --- a/test/mock/mock_battle_IBattleState.h +++ b/test/mock/mock_battle_IBattleState.h @@ -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 &)); };