1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +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:
Toney Sui
2020-02-12 09:12:12 -08:00
committed by GitHub
parent 0f7de511be
commit dca5d86e7a
9 changed files with 57 additions and 13 deletions

View File

@@ -371,6 +371,11 @@ void HypotheticBattle::addObstacle(const ObstacleChanges & changes)
//TODO:HypotheticBattle::addObstacle //TODO:HypotheticBattle::addObstacle
} }
void HypotheticBattle::updateObstacle(const ObstacleChanges& changes)
{
//TODO:HypotheticBattle::updateObstacle
}
void HypotheticBattle::removeObstacle(uint32_t id) void HypotheticBattle::removeObstacle(uint32_t id)
{ {
//TODO:HypotheticBattle::removeObstacle //TODO:HypotheticBattle::removeObstacle

View File

@@ -98,6 +98,7 @@ public:
void setWallState(int partOfWall, si8 state) override; void setWallState(int partOfWall, si8 state) override;
void addObstacle(const ObstacleChanges & changes) override; void addObstacle(const ObstacleChanges & changes) override;
void updateObstacle(const ObstacleChanges& changes) override;
void removeObstacle(uint32_t id) override; void removeObstacle(uint32_t id) override;
uint32_t nextUnitId() const override; uint32_t nextUnitId() const override;

View File

@@ -1535,6 +1535,9 @@ DLL_LINKAGE void BattleObstaclesChanged::applyBattle(IBattleState * battleState)
case BattleChanges::EOperation::ADD: case BattleChanges::EOperation::ADD:
battleState->addObstacle(change); battleState->addObstacle(change);
break; break;
case BattleChanges::EOperation::UPDATE:
battleState->updateObstacle(change);
break;
default: default:
logNetwork->error("Unknown obstacle operation %d", (int)change.operation); logNetwork->error("Unknown obstacle operation %d", (int)change.operation);
break; break;

View File

@@ -809,17 +809,6 @@ void BattleInfo::moveUnit(uint32_t id, BattleHex destination)
logGlobal->error("Cannot find stack %d", id); logGlobal->error("Cannot find stack %d", id);
return; 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; sta->position = destination;
} }
@@ -1029,6 +1018,26 @@ void BattleInfo::addObstacle(const ObstacleChanges & changes)
obstacles.push_back(obstacle); 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) void BattleInfo::removeObstacle(uint32_t id)
{ {
for(int i=0; i < obstacles.size(); ++i) for(int i=0; i < obstacles.size(); ++i)

View File

@@ -109,6 +109,7 @@ public:
void setWallState(int partOfWall, si8 state) override; void setWallState(int partOfWall, si8 state) override;
void addObstacle(const ObstacleChanges & changes) override; void addObstacle(const ObstacleChanges & changes) override;
void updateObstacle(const ObstacleChanges& changes) override;
void removeObstacle(uint32_t id) override; void removeObstacle(uint32_t id) override;
void addOrUpdateUnitBonus(CStack * sta, const Bonus & value, bool forceAdd); void addOrUpdateUnitBonus(CStack * sta, const Bonus & value, bool forceAdd);

View File

@@ -155,8 +155,8 @@ void SpellCreatedObstacle::fromInfo(const ObstacleChanges & info)
{ {
uniqueID = info.id; uniqueID = info.id;
if(info.operation != ObstacleChanges::EOperation::ADD) if(info.operation != ObstacleChanges::EOperation::ADD && info.operation != ObstacleChanges::EOperation::UPDATE)
logGlobal->error("ADD operation expected"); logGlobal->error("ADD or UPDATE operation expected");
JsonDeserializer deser(nullptr, info.data); JsonDeserializer deser(nullptr, info.data);
deser.serializeStruct("obstacle", *this); deser.serializeStruct("obstacle", *this);
@@ -173,6 +173,7 @@ void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler)
handler.serializeInt("casterSide", casterSide); handler.serializeInt("casterSide", casterSide);
handler.serializeBool("hidden", hidden); handler.serializeBool("hidden", hidden);
handler.serializeBool("revealed", revealed);
handler.serializeBool("passable", passable); handler.serializeBool("passable", passable);
handler.serializeBool("trigger", trigger); handler.serializeBool("trigger", trigger);
handler.serializeBool("trap", trap); handler.serializeBool("trap", trap);

View File

@@ -87,5 +87,6 @@ public:
virtual void setWallState(int partOfWall, si8 state) = 0; virtual void setWallState(int partOfWall, si8 state) = 0;
virtual void addObstacle(const ObstacleChanges & changes) = 0; virtual void addObstacle(const ObstacleChanges & changes) = 0;
virtual void updateObstacle(const ObstacleChanges & changes) = 0;
virtual void removeObstacle(uint32_t id) = 0; virtual void removeObstacle(uint32_t id) = 0;
}; };

View File

@@ -47,6 +47,7 @@
#include "../lib/serializer/CTypeList.h" #include "../lib/serializer/CTypeList.h"
#include "../lib/serializer/Connection.h" #include "../lib/serializer/Connection.h"
#include "../lib/serializer/Cast.h" #include "../lib/serializer/Cast.h"
#include "../lib/serializer/JsonSerializer.h"
#ifndef _MSC_VER #ifndef _MSC_VER
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
@@ -4857,7 +4858,28 @@ bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackI
battleCast.applyEffects(spellEnv, true); battleCast.applyEffects(spellEnv, true);
if(oneTimeObstacle) if(oneTimeObstacle)
{
removeObstacle(*obstacle); 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);
}
} }
} }
} }

View File

@@ -47,6 +47,7 @@ public:
MOCK_METHOD2(setWallState, void(int, si8)); MOCK_METHOD2(setWallState, void(int, si8));
MOCK_METHOD1(addObstacle, void(const ObstacleChanges &)); MOCK_METHOD1(addObstacle, void(const ObstacleChanges &));
MOCK_METHOD1(removeObstacle, void(uint32_t)); MOCK_METHOD1(removeObstacle, void(uint32_t));
MOCK_METHOD1(updateObstacle, void(const ObstacleChanges &));
}; };