feat: implement freeze effect
This commit is contained in:
@@ -34,6 +34,7 @@ typedef std::uint32_t MobID;
|
|||||||
typedef std::uint8_t MobLevel;
|
typedef std::uint8_t MobLevel;
|
||||||
typedef std::vector<TowerType> TowerImmunities;
|
typedef std::vector<TowerType> TowerImmunities;
|
||||||
typedef std::vector<EffectType> EffectImmunities;
|
typedef std::vector<EffectType> EffectImmunities;
|
||||||
|
typedef std::pair<EffectType, float> EffectDuration;
|
||||||
|
|
||||||
class MobStats {
|
class MobStats {
|
||||||
private:
|
private:
|
||||||
@@ -71,6 +72,7 @@ private:
|
|||||||
PlayerID m_Sender;
|
PlayerID m_Sender;
|
||||||
MobLevel m_Level;
|
MobLevel m_Level;
|
||||||
Direction m_Direction;
|
Direction m_Direction;
|
||||||
|
std::vector<EffectDuration> m_Effects;
|
||||||
|
|
||||||
float m_X = 0, m_Y = 0;
|
float m_X = 0, m_Y = 0;
|
||||||
public:
|
public:
|
||||||
@@ -80,7 +82,7 @@ public:
|
|||||||
|
|
||||||
virtual MobType getType() const = 0;
|
virtual MobType getType() const = 0;
|
||||||
|
|
||||||
virtual void tick(std::uint64_t delta) {}
|
virtual void tick(std::uint64_t delta);
|
||||||
|
|
||||||
const TowerImmunities& getTowerImmunities() const { return getMobTowerImmunities(getType(), m_Level); }
|
const TowerImmunities& getTowerImmunities() const { return getMobTowerImmunities(getType(), m_Level); }
|
||||||
const EffectImmunities& getEffectImmunities() const { return getMobEffectImmunities(getType(), m_Level); }
|
const EffectImmunities& getEffectImmunities() const { return getMobEffectImmunities(getType(), m_Level); }
|
||||||
@@ -99,10 +101,19 @@ public:
|
|||||||
float getY() const { return m_Y; }
|
float getY() const { return m_Y; }
|
||||||
void setY(float y) { m_Y = y; }
|
void setY(float y) { m_Y = y; }
|
||||||
|
|
||||||
|
bool isImmuneTo(TowerType type);
|
||||||
|
|
||||||
|
bool isImmuneTo(EffectType type);
|
||||||
|
void addEffect(EffectType type, float durationSec);
|
||||||
|
bool hasEffect(EffectType type);
|
||||||
|
|
||||||
|
|
||||||
Direction getDirection() const { return m_Direction; }
|
Direction getDirection() const { return m_Direction; }
|
||||||
void setDirection(Direction dir) { m_Direction = dir; }
|
void setDirection(Direction dir) { m_Direction = dir; }
|
||||||
protected:
|
protected:
|
||||||
void initHealth() { m_Health = (float)getStats()->getMaxLife(); }
|
void initHealth() { m_Health = (float)getStats()->getMaxLife(); }
|
||||||
|
private:
|
||||||
|
void updateEffects(std::uint64_t delta);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Mob> MobPtr;
|
typedef std::shared_ptr<Mob> MobPtr;
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ public:
|
|||||||
virtual void OnArrowShot(MobPtr target, Tower* shooter);
|
virtual void OnArrowShot(MobPtr target, Tower* shooter);
|
||||||
private:
|
private:
|
||||||
void moveMobs(std::uint64_t delta);
|
void moveMobs(std::uint64_t delta);
|
||||||
|
void tickMobs(std::uint64_t delta);
|
||||||
void cleanDeadMobs();
|
void cleanDeadMobs();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,53 @@
|
|||||||
#include "game/Mobs.h"
|
#include "game/Mobs.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
|
bool Mob::isImmuneTo(TowerType type) {
|
||||||
|
return std::find(getTowerImmunities().begin(), getTowerImmunities().end(), type) != getTowerImmunities().end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mob::isImmuneTo(EffectType type) {
|
||||||
|
return std::find(getEffectImmunities().begin(), getEffectImmunities().end(), type) != getEffectImmunities().end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::addEffect(EffectType effectType, float durationSec) {
|
||||||
|
if (isImmuneTo(effectType))
|
||||||
|
return;
|
||||||
|
if (hasEffect(effectType)) {
|
||||||
|
auto it = std::find_if(m_Effects.begin(), m_Effects.end(), [&effectType](EffectDuration effect){ return effect.first == effectType;});
|
||||||
|
EffectDuration& effect = *it;
|
||||||
|
if(effect.second < durationSec)
|
||||||
|
effect.second = durationSec; // setting new duration if it's greater then the actual
|
||||||
|
} else {
|
||||||
|
m_Effects.push_back({ effectType, durationSec });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::tick(std::uint64_t delta) {
|
||||||
|
updateEffects(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::updateEffects(std::uint64_t delta) {
|
||||||
|
float deltaSec = (float)delta / 1000.0f;
|
||||||
|
for (auto it = m_Effects.begin(); it != m_Effects.end(); it++) {
|
||||||
|
EffectDuration& effect = *it;
|
||||||
|
effect.second -= deltaSec;
|
||||||
|
if (effect.second < 0) // effect has gone
|
||||||
|
m_Effects.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mob::hasEffect(EffectType type) {
|
||||||
|
return std::find_if(m_Effects.begin(), m_Effects.end(), [&type](EffectDuration effect){ return effect.first == type;}) != m_Effects.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::pair<MobType, std::uint8_t> MobKey;
|
typedef std::pair<MobType, std::uint8_t> MobKey;
|
||||||
|
|
||||||
const std::map<MobKey, MobStats> MobConstants = {
|
const std::map<MobKey, MobStats> MobConstants = {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace td {
|
|||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
bool Tower::isMobInRange(MobPtr mob) {
|
bool Tower::isMobInRange(MobPtr mob) {
|
||||||
if(!mob->isAlive())
|
if (!mob->isAlive())
|
||||||
return false;
|
return false;
|
||||||
return (m_X - mob->getX()) * (m_X - mob->getX()) + (m_Y - mob->getY()) * (m_Y - mob->getY()) < (getStats()->getRange() * getStats()->getRange());
|
return (m_X - mob->getX()) * (m_X - mob->getX()) + (m_Y - mob->getY()) * (m_Y - mob->getY()) < (getStats()->getRange() * getStats()->getRange());
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ const std::map<std::pair<TowerType, TowerLevel>, TowerStats> TowerConstants = {
|
|||||||
{{TowerType::Ice, {1, TowerPath::Top}}, {1, 0, 10}},
|
{{TowerType::Ice, {1, TowerPath::Top}}, {1, 0, 10}},
|
||||||
{{TowerType::Ice, {2, TowerPath::Top}}, {1, 0, 12}},
|
{{TowerType::Ice, {2, TowerPath::Top}}, {1, 0, 12}},
|
||||||
{{TowerType::Ice, {3, TowerPath::Top}}, {1, 0, 13}},
|
{{TowerType::Ice, {3, TowerPath::Top}}, {1, 0, 13}},
|
||||||
{{TowerType::Ice, {4, TowerPath::Top}}, {1, 0, 15}},
|
{{TowerType::Ice, {4, TowerPath::Top}}, {1, 4, 15}},
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ void ArcherTower::tick(std::uint64_t delta, World* world) {
|
|||||||
if (isMobInRange(mob)) {
|
if (isMobInRange(mob)) {
|
||||||
world->OnArrowShot(mob, this);
|
world->OnArrowShot(mob, this);
|
||||||
arrowsShot++;
|
arrowsShot++;
|
||||||
if(arrowsShot >= arrows)
|
if (arrowsShot >= arrows)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,15 @@ void ArcherTower::tick(std::uint64_t delta, World* world) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IceTower::tick(std::uint64_t delta, World* world) {
|
void IceTower::tick(std::uint64_t delta, World* world) {
|
||||||
|
if (m_Timer.update(delta)) {
|
||||||
|
float damage = getStats()->getDamage();
|
||||||
|
for (MobPtr mob : world->getMobList()) {
|
||||||
|
if (isMobInRange(mob)) {
|
||||||
|
mob->addEffect(EffectType::Slowness, 1); // slowness for 1s every second
|
||||||
|
mob->damage(damage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MageTower::tick(std::uint64_t delta, World* world) {
|
void MageTower::tick(std::uint64_t delta, World* world) {
|
||||||
|
|||||||
@@ -321,6 +321,7 @@ bool World::saveMap(const std::string& fileName) const {
|
|||||||
|
|
||||||
void World::tick(std::uint64_t delta) {
|
void World::tick(std::uint64_t delta) {
|
||||||
moveMobs(delta);
|
moveMobs(delta);
|
||||||
|
tickMobs(delta);
|
||||||
for(TowerPtr tower : m_Towers){
|
for(TowerPtr tower : m_Towers){
|
||||||
tower->tick(delta, this);
|
tower->tick(delta, this);
|
||||||
}
|
}
|
||||||
@@ -341,6 +342,12 @@ TowerPtr World::placeTowerAt(TowerID id, TowerType type, std::int32_t x, std::in
|
|||||||
return tower;
|
return tower;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::tickMobs(std::uint64_t delta) {
|
||||||
|
for(MobPtr mob : m_Mobs) {
|
||||||
|
mob->tick(delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void World::moveMobs(std::uint64_t delta) {
|
void World::moveMobs(std::uint64_t delta) {
|
||||||
for (MobPtr mob : m_Mobs) {
|
for (MobPtr mob : m_Mobs) {
|
||||||
TilePtr tile = getTile(mob->getX(), mob->getY());
|
TilePtr tile = getTile(mob->getX(), mob->getY());
|
||||||
@@ -354,6 +361,9 @@ void World::moveMobs(std::uint64_t delta) {
|
|||||||
|
|
||||||
float walkAmount = mobWalkSpeed * ((float)delta / 1000.0f);
|
float walkAmount = mobWalkSpeed * ((float)delta / 1000.0f);
|
||||||
|
|
||||||
|
if(mob->hasEffect(EffectType::Slowness))
|
||||||
|
walkAmount *= 0.70;
|
||||||
|
|
||||||
switch (mob->getDirection()) {
|
switch (mob->getDirection()) {
|
||||||
case Direction::NegativeX: {
|
case Direction::NegativeX: {
|
||||||
mob->setX(mob->getX() - walkAmount);
|
mob->setX(mob->getX() - walkAmount);
|
||||||
|
|||||||
Reference in New Issue
Block a user