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);
|
||||
case FORCE_FIELD:
|
||||
return SpellID(SpellID::FORCE_FIELD).toSpell()->rangeInHexes(pos, spellLevel, casterSide);
|
||||
//TODO Fire Wall
|
||||
default:
|
||||
assert(0);
|
||||
return std::vector<BattleHex>();
|
||||
|
@ -410,60 +410,27 @@ ESpellCastProblem::ESpellCastProblem ObstacleMechanics::canBeCast(const CBattleI
|
||||
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)
|
||||
{
|
||||
static int obstacleIdToGive = parameters.cb->obstacles.size()
|
||||
? (parameters.cb->obstacles.back()->uniqueID+1)
|
||||
: 0;
|
||||
const int obstacleIdToGive = parameters.cb->obstacles.size()+1;
|
||||
|
||||
auto obstacle = std::make_shared<SpellCreatedObstacle>();
|
||||
switch(owner->id) // :/
|
||||
{
|
||||
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);
|
||||
}
|
||||
setupObstacle(obstacle.get());
|
||||
|
||||
obstacle->pos = pos;
|
||||
obstacle->casterSide = parameters.casterSide;
|
||||
obstacle->ID = owner->id;
|
||||
obstacle->spellLevel = parameters.effectLevel;
|
||||
obstacle->casterSpellPower = parameters.effectPower;
|
||||
obstacle->uniqueID = obstacleIdToGive++;
|
||||
obstacle->uniqueID = obstacleIdToGive;
|
||||
|
||||
BattleObstaclePlaced bop;
|
||||
bop.obstacle = obstacle;
|
||||
env->sendAndApply(&bop);
|
||||
};
|
||||
}
|
||||
|
||||
const BattleHex destination = parameters.getFirstDestinationHex();
|
||||
|
||||
switch(owner->id)
|
||||
{
|
||||
case SpellID::QUICKSAND:
|
||||
case SpellID::LAND_MINE:
|
||||
///PatchObstacleMechanics
|
||||
void PatchObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
std::vector<BattleHex> availableTiles;
|
||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; i += 1)
|
||||
@ -479,51 +446,33 @@ void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, con
|
||||
|
||||
//land mines or quicksand patches are handled as spell created obstacles
|
||||
for (int i = 0; i < patchesToPut; i++)
|
||||
placeObstacle(availableTiles.at(i));
|
||||
placeObstacle(env, parameters, availableTiles.at(i));
|
||||
}
|
||||
|
||||
break;
|
||||
case SpellID::FORCE_FIELD:
|
||||
if(!destination.isValid())
|
||||
///LandMineMechanics
|
||||
bool LandMineMechanics::requiresCreatureTarget() const
|
||||
{
|
||||
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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObstacleMechanics::requiresCreatureTarget() const
|
||||
void LandMineMechanics::setupObstacle(SpellCreatedObstacle * obstacle) const
|
||||
{
|
||||
switch(owner->id)
|
||||
obstacle->obstacleType = CObstacleInstance::LAND_MINE;
|
||||
obstacle->turnsRemaining = -1;
|
||||
obstacle->visibleForAnotherSide = false;
|
||||
}
|
||||
|
||||
///QuicksandMechanics
|
||||
bool QuicksandMechanics::requiresCreatureTarget() const
|
||||
{
|
||||
case SpellID::QUICKSAND:
|
||||
return false;
|
||||
case SpellID::LAND_MINE:
|
||||
return true;
|
||||
case SpellID::FORCE_FIELD:
|
||||
return false;
|
||||
case SpellID::FIRE_WALL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
void QuicksandMechanics::setupObstacle(SpellCreatedObstacle * obstacle) const
|
||||
{
|
||||
obstacle->obstacleType = CObstacleInstance::QUICKSAND;
|
||||
obstacle->turnsRemaining = -1;
|
||||
obstacle->visibleForAnotherSide = false;
|
||||
}
|
||||
|
||||
///WallMechanics
|
||||
@ -563,6 +512,59 @@ std::vector<BattleHex> WallMechanics::rangeInHexes(BattleHex centralHex, ui8 sch
|
||||
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
|
||||
void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "CDefaultSpellMechanics.h"
|
||||
|
||||
class CObstacleInstance;
|
||||
class SpellCreatedObstacle;
|
||||
|
||||
class DLL_LINKAGE HealingSpellMechanics : public DefaultSpellMechanics
|
||||
{
|
||||
@ -98,11 +99,37 @@ class DLL_LINKAGE ObstacleMechanics : public DefaultSpellMechanics
|
||||
public:
|
||||
ObstacleMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
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:
|
||||
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
|
||||
{
|
||||
public:
|
||||
@ -110,6 +137,26 @@ public:
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
@ -258,7 +258,6 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
||||
env->sendAndApply(&si);
|
||||
|
||||
//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)
|
||||
{
|
||||
assert(parameters.casterStack);
|
||||
|
@ -106,13 +106,15 @@ std::unique_ptr<ISpellMechanics> ISpellMechanics::createMechanics(CSpell * s)
|
||||
case SpellID::EARTHQUAKE:
|
||||
return make_unique<EarthquakeMechanics>(s);
|
||||
case SpellID::FIRE_WALL:
|
||||
return make_unique<FireWallMechanics>(s);
|
||||
case SpellID::FORCE_FIELD:
|
||||
return make_unique<WallMechanics>(s);
|
||||
return make_unique<ForceFieldMechanics>(s);
|
||||
case SpellID::HYPNOTIZE:
|
||||
return make_unique<HypnotizeMechanics>(s);
|
||||
case SpellID::LAND_MINE:
|
||||
return make_unique<LandMineMechanics>(s);
|
||||
case SpellID::QUICKSAND:
|
||||
return make_unique<ObstacleMechanics>(s);
|
||||
return make_unique<QuicksandMechanics>(s);
|
||||
case SpellID::REMOVE_OBSTACLE:
|
||||
return make_unique<RemoveObstacleMechanics>(s);
|
||||
case SpellID::SACRIFICE:
|
||||
|
Loading…
Reference in New Issue
Block a user