mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
OO design for obstacle spells.
This commit is contained in:
parent
f3b7fe947c
commit
82ac035340
@ -131,7 +131,6 @@ std::vector<BattleHex> SpellCreatedObstacle::getAffectedTiles() const
|
|||||||
return std::vector<BattleHex>(1, pos);
|
return std::vector<BattleHex>(1, pos);
|
||||||
case FORCE_FIELD:
|
case FORCE_FIELD:
|
||||||
return SpellID(SpellID::FORCE_FIELD).toSpell()->rangeInHexes(pos, spellLevel, casterSide);
|
return SpellID(SpellID::FORCE_FIELD).toSpell()->rangeInHexes(pos, spellLevel, casterSide);
|
||||||
//TODO Fire Wall
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
return std::vector<BattleHex>();
|
return std::vector<BattleHex>();
|
||||||
|
@ -410,120 +410,69 @@ ESpellCastProblem::ESpellCastProblem ObstacleMechanics::canBeCast(const CBattleI
|
|||||||
return ESpellCastProblem::OK;
|
return ESpellCastProblem::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
void ObstacleMechanics::placeObstacle(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, const BattleHex & pos) const
|
||||||
{
|
{
|
||||||
auto placeObstacle = [&, this](const BattleHex & pos)
|
const int obstacleIdToGive = parameters.cb->obstacles.size()+1;
|
||||||
{
|
|
||||||
static int obstacleIdToGive = parameters.cb->obstacles.size()
|
|
||||||
? (parameters.cb->obstacles.back()->uniqueID+1)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
auto obstacle = std::make_shared<SpellCreatedObstacle>();
|
auto obstacle = std::make_shared<SpellCreatedObstacle>();
|
||||||
switch(owner->id) // :/
|
setupObstacle(obstacle.get());
|
||||||
{
|
|
||||||
case SpellID::QUICKSAND:
|
|
||||||
obstacle->obstacleType = CObstacleInstance::QUICKSAND;
|
|
||||||
obstacle->turnsRemaining = -1;
|
|
||||||
obstacle->visibleForAnotherSide = false;
|
|
||||||
break;
|
|
||||||
case SpellID::LAND_MINE:
|
|
||||||
obstacle->obstacleType = CObstacleInstance::LAND_MINE;
|
|
||||||
obstacle->turnsRemaining = -1;
|
|
||||||
obstacle->visibleForAnotherSide = false;
|
|
||||||
break;
|
|
||||||
case SpellID::FIRE_WALL:
|
|
||||||
obstacle->obstacleType = CObstacleInstance::FIRE_WALL;
|
|
||||||
obstacle->turnsRemaining = 2;
|
|
||||||
obstacle->visibleForAnotherSide = true;
|
|
||||||
break;
|
|
||||||
case SpellID::FORCE_FIELD:
|
|
||||||
obstacle->obstacleType = CObstacleInstance::FORCE_FIELD;
|
|
||||||
obstacle->turnsRemaining = 2;
|
|
||||||
obstacle->visibleForAnotherSide = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//this function cannot be used with spells that do not create obstacles
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
obstacle->pos = pos;
|
obstacle->pos = pos;
|
||||||
obstacle->casterSide = parameters.casterSide;
|
obstacle->casterSide = parameters.casterSide;
|
||||||
obstacle->ID = owner->id;
|
obstacle->ID = owner->id;
|
||||||
obstacle->spellLevel = parameters.effectLevel;
|
obstacle->spellLevel = parameters.effectLevel;
|
||||||
obstacle->casterSpellPower = parameters.effectPower;
|
obstacle->casterSpellPower = parameters.effectPower;
|
||||||
obstacle->uniqueID = obstacleIdToGive++;
|
obstacle->uniqueID = obstacleIdToGive;
|
||||||
|
|
||||||
BattleObstaclePlaced bop;
|
BattleObstaclePlaced bop;
|
||||||
bop.obstacle = obstacle;
|
bop.obstacle = obstacle;
|
||||||
env->sendAndApply(&bop);
|
env->sendAndApply(&bop);
|
||||||
};
|
|
||||||
|
|
||||||
const BattleHex destination = parameters.getFirstDestinationHex();
|
|
||||||
|
|
||||||
switch(owner->id)
|
|
||||||
{
|
|
||||||
case SpellID::QUICKSAND:
|
|
||||||
case SpellID::LAND_MINE:
|
|
||||||
{
|
|
||||||
std::vector<BattleHex> availableTiles;
|
|
||||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; i += 1)
|
|
||||||
{
|
|
||||||
BattleHex hex = i;
|
|
||||||
if(hex.getX() > 0 && hex.getX() < 16 && !(parameters.cb->battleGetStackByPos(hex, false)) && !(parameters.cb->battleGetObstacleOnPos(hex, false)))
|
|
||||||
availableTiles.push_back(hex);
|
|
||||||
}
|
|
||||||
boost::range::random_shuffle(availableTiles);
|
|
||||||
|
|
||||||
const int patchesForSkill[] = {4, 4, 6, 8};
|
|
||||||
const int patchesToPut = std::min<int>(patchesForSkill[parameters.spellLvl], availableTiles.size());
|
|
||||||
|
|
||||||
//land mines or quicksand patches are handled as spell created obstacles
|
|
||||||
for (int i = 0; i < patchesToPut; i++)
|
|
||||||
placeObstacle(availableTiles.at(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case SpellID::FORCE_FIELD:
|
|
||||||
if(!destination.isValid())
|
|
||||||
{
|
|
||||||
env->complain("Invalid destination for FORCE_FIELD");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
placeObstacle(destination);
|
|
||||||
break;
|
|
||||||
case SpellID::FIRE_WALL:
|
|
||||||
{
|
|
||||||
if(!destination.isValid())
|
|
||||||
{
|
|
||||||
env->complain("Invalid destination for FIRE_WALL");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//fire wall is build from multiple obstacles - one fire piece for each affected hex
|
|
||||||
auto affectedHexes = owner->rangeInHexes(destination, parameters.spellLvl, parameters.casterSide);
|
|
||||||
for(BattleHex hex : affectedHexes)
|
|
||||||
placeObstacle(hex);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObstacleMechanics::requiresCreatureTarget() const
|
///PatchObstacleMechanics
|
||||||
|
void PatchObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||||
{
|
{
|
||||||
switch(owner->id)
|
std::vector<BattleHex> availableTiles;
|
||||||
|
for(int i = 0; i < GameConstants::BFIELD_SIZE; i += 1)
|
||||||
{
|
{
|
||||||
case SpellID::QUICKSAND:
|
BattleHex hex = i;
|
||||||
return false;
|
if(hex.getX() > 0 && hex.getX() < 16 && !(parameters.cb->battleGetStackByPos(hex, false)) && !(parameters.cb->battleGetObstacleOnPos(hex, false)))
|
||||||
case SpellID::LAND_MINE:
|
availableTiles.push_back(hex);
|
||||||
return true;
|
|
||||||
case SpellID::FORCE_FIELD:
|
|
||||||
return false;
|
|
||||||
case SpellID::FIRE_WALL:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
boost::range::random_shuffle(availableTiles);
|
||||||
|
|
||||||
|
const int patchesForSkill[] = {4, 4, 6, 8};
|
||||||
|
const int patchesToPut = std::min<int>(patchesForSkill[parameters.spellLvl], availableTiles.size());
|
||||||
|
|
||||||
|
//land mines or quicksand patches are handled as spell created obstacles
|
||||||
|
for (int i = 0; i < patchesToPut; i++)
|
||||||
|
placeObstacle(env, parameters, availableTiles.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
///LandMineMechanics
|
||||||
|
bool LandMineMechanics::requiresCreatureTarget() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandMineMechanics::setupObstacle(SpellCreatedObstacle * obstacle) const
|
||||||
|
{
|
||||||
|
obstacle->obstacleType = CObstacleInstance::LAND_MINE;
|
||||||
|
obstacle->turnsRemaining = -1;
|
||||||
|
obstacle->visibleForAnotherSide = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///QuicksandMechanics
|
||||||
|
bool QuicksandMechanics::requiresCreatureTarget() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuicksandMechanics::setupObstacle(SpellCreatedObstacle * obstacle) const
|
||||||
|
{
|
||||||
|
obstacle->obstacleType = CObstacleInstance::QUICKSAND;
|
||||||
|
obstacle->turnsRemaining = -1;
|
||||||
|
obstacle->visibleForAnotherSide = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///WallMechanics
|
///WallMechanics
|
||||||
@ -563,6 +512,59 @@ std::vector<BattleHex> WallMechanics::rangeInHexes(BattleHex centralHex, ui8 sch
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///FireWallMechanics
|
||||||
|
bool FireWallMechanics::requiresCreatureTarget() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FireWallMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||||
|
{
|
||||||
|
const BattleHex destination = parameters.getFirstDestinationHex();
|
||||||
|
|
||||||
|
if(!destination.isValid())
|
||||||
|
{
|
||||||
|
env->complain("Invalid destination for FIRE_WALL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//firewall is build from multiple obstacles - one fire piece for each affected hex
|
||||||
|
auto affectedHexes = owner->rangeInHexes(destination, parameters.spellLvl, parameters.casterSide);
|
||||||
|
for(BattleHex hex : affectedHexes)
|
||||||
|
placeObstacle(env, parameters, hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FireWallMechanics::setupObstacle(SpellCreatedObstacle * obstacle) const
|
||||||
|
{
|
||||||
|
obstacle->obstacleType = CObstacleInstance::FIRE_WALL;
|
||||||
|
obstacle->turnsRemaining = 2;
|
||||||
|
obstacle->visibleForAnotherSide = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///ForceFieldMechanics
|
||||||
|
bool ForceFieldMechanics::requiresCreatureTarget() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForceFieldMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||||
|
{
|
||||||
|
const BattleHex destination = parameters.getFirstDestinationHex();
|
||||||
|
|
||||||
|
if(!destination.isValid())
|
||||||
|
{
|
||||||
|
env->complain("Invalid destination for FORCE_FIELD");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
placeObstacle(env, parameters, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForceFieldMechanics::setupObstacle(SpellCreatedObstacle * obstacle) const
|
||||||
|
{
|
||||||
|
obstacle->obstacleType = CObstacleInstance::FORCE_FIELD;
|
||||||
|
obstacle->turnsRemaining = 2;
|
||||||
|
obstacle->visibleForAnotherSide = true;
|
||||||
|
}
|
||||||
|
|
||||||
///RemoveObstacleMechanics
|
///RemoveObstacleMechanics
|
||||||
void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "CDefaultSpellMechanics.h"
|
#include "CDefaultSpellMechanics.h"
|
||||||
|
|
||||||
class CObstacleInstance;
|
class CObstacleInstance;
|
||||||
|
class SpellCreatedObstacle;
|
||||||
|
|
||||||
class DLL_LINKAGE HealingSpellMechanics : public DefaultSpellMechanics
|
class DLL_LINKAGE HealingSpellMechanics : public DefaultSpellMechanics
|
||||||
{
|
{
|
||||||
@ -98,11 +99,37 @@ class DLL_LINKAGE ObstacleMechanics : public DefaultSpellMechanics
|
|||||||
public:
|
public:
|
||||||
ObstacleMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
ObstacleMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||||
ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
|
ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
|
||||||
bool requiresCreatureTarget() const override;
|
protected:
|
||||||
|
void placeObstacle(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, const BattleHex & pos) const;
|
||||||
|
virtual void setupObstacle(SpellCreatedObstacle * obstacle) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PatchObstacleMechanics : public ObstacleMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PatchObstacleMechanics(CSpell * s): ObstacleMechanics(s){};
|
||||||
protected:
|
protected:
|
||||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE LandMineMechanics : public PatchObstacleMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LandMineMechanics(CSpell * s): PatchObstacleMechanics(s){};
|
||||||
|
bool requiresCreatureTarget() const override;
|
||||||
|
protected:
|
||||||
|
void setupObstacle(SpellCreatedObstacle * obstacle) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE QuicksandMechanics : public PatchObstacleMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuicksandMechanics(CSpell * s): PatchObstacleMechanics(s){};
|
||||||
|
bool requiresCreatureTarget() const override;
|
||||||
|
protected:
|
||||||
|
void setupObstacle(SpellCreatedObstacle * obstacle) const override;
|
||||||
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE WallMechanics : public ObstacleMechanics
|
class DLL_LINKAGE WallMechanics : public ObstacleMechanics
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -110,6 +137,26 @@ public:
|
|||||||
std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes = nullptr) const override;
|
std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes = nullptr) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE FireWallMechanics : public WallMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FireWallMechanics(CSpell * s): WallMechanics(s){};
|
||||||
|
bool requiresCreatureTarget() const override;
|
||||||
|
protected:
|
||||||
|
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||||
|
void setupObstacle(SpellCreatedObstacle * obstacle) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE ForceFieldMechanics : public WallMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ForceFieldMechanics(CSpell * s): WallMechanics(s){};
|
||||||
|
bool requiresCreatureTarget() const override;
|
||||||
|
protected:
|
||||||
|
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||||
|
void setupObstacle(SpellCreatedObstacle * obstacle) const override;
|
||||||
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE RemoveObstacleMechanics : public DefaultSpellMechanics
|
class DLL_LINKAGE RemoveObstacleMechanics : public DefaultSpellMechanics
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -258,7 +258,6 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
|||||||
env->sendAndApply(&si);
|
env->sendAndApply(&si);
|
||||||
|
|
||||||
//reduce number of casts remaining
|
//reduce number of casts remaining
|
||||||
//TODO: this should be part of BattleSpellCast apply
|
|
||||||
if (parameters.mode == ECastingMode::CREATURE_ACTIVE_CASTING || parameters.mode == ECastingMode::ENCHANTER_CASTING)
|
if (parameters.mode == ECastingMode::CREATURE_ACTIVE_CASTING || parameters.mode == ECastingMode::ENCHANTER_CASTING)
|
||||||
{
|
{
|
||||||
assert(parameters.casterStack);
|
assert(parameters.casterStack);
|
||||||
|
@ -106,13 +106,15 @@ std::unique_ptr<ISpellMechanics> ISpellMechanics::createMechanics(CSpell * s)
|
|||||||
case SpellID::EARTHQUAKE:
|
case SpellID::EARTHQUAKE:
|
||||||
return make_unique<EarthquakeMechanics>(s);
|
return make_unique<EarthquakeMechanics>(s);
|
||||||
case SpellID::FIRE_WALL:
|
case SpellID::FIRE_WALL:
|
||||||
|
return make_unique<FireWallMechanics>(s);
|
||||||
case SpellID::FORCE_FIELD:
|
case SpellID::FORCE_FIELD:
|
||||||
return make_unique<WallMechanics>(s);
|
return make_unique<ForceFieldMechanics>(s);
|
||||||
case SpellID::HYPNOTIZE:
|
case SpellID::HYPNOTIZE:
|
||||||
return make_unique<HypnotizeMechanics>(s);
|
return make_unique<HypnotizeMechanics>(s);
|
||||||
case SpellID::LAND_MINE:
|
case SpellID::LAND_MINE:
|
||||||
|
return make_unique<LandMineMechanics>(s);
|
||||||
case SpellID::QUICKSAND:
|
case SpellID::QUICKSAND:
|
||||||
return make_unique<ObstacleMechanics>(s);
|
return make_unique<QuicksandMechanics>(s);
|
||||||
case SpellID::REMOVE_OBSTACLE:
|
case SpellID::REMOVE_OBSTACLE:
|
||||||
return make_unique<RemoveObstacleMechanics>(s);
|
return make_unique<RemoveObstacleMechanics>(s);
|
||||||
case SpellID::SACRIFICE:
|
case SpellID::SACRIFICE:
|
||||||
|
Loading…
Reference in New Issue
Block a user