#pragma once #include "Towers.h" #include "Types.h" #include #include namespace td { namespace game { enum class EffectType : std::uint8_t { Slowness = 0, Stun, Fire, Poison, Heal, }; enum class MobType : std::uint8_t { Zombie = 0, Spider, Skeleton, Pigman, Creeper, Silverfish, Blaze, Witch, Slime, Giant, MOB_COUNT }; typedef std::uint32_t MobID; typedef std::uint8_t MobLevel; typedef std::vector TowerImmunities; typedef std::vector EffectImmunities; class MobStats { private: float m_Damage; float m_Speed; std::uint16_t m_MoneyCost; std::uint16_t m_ExpCost; std::uint16_t m_MaxLife; std::uint16_t m_ExpReward; public: MobStats(float damage, float speed, std::uint16_t moneyCost, std::uint16_t expCost, std::uint16_t expReward, std::uint16_t maxLife) : m_Damage(damage), m_Speed(speed), m_MoneyCost(moneyCost), m_ExpCost(expCost), m_MaxLife(maxLife), m_ExpReward(expReward) { } float getDamage() const { return m_Damage; } float getMovementSpeed() const { return m_Speed; } std::uint16_t getMoneyCost() const { return m_MoneyCost; } std::uint16_t getExpCost() const { return m_ExpCost; } std::uint16_t getExpReward() const { return m_ExpReward; } std::uint16_t getMaxLife() const { return m_MaxLife; } }; struct EffectDuration { EffectType type; float duration; // in seconds const Tower* tower; // the tower that gived the effect }; const MobStats* getMobStats(MobType type, std::uint8_t level); const TowerImmunities& getMobTowerImmunities(MobType type, std::uint8_t level); const EffectImmunities& getMobEffectImmunities(MobType type, std::uint8_t level); class Mob { protected: float m_Health; private: MobID m_ID; PlayerID m_Sender; MobLevel m_Level; Direction m_Direction; std::vector m_Effects; const Tower* m_LastDamage; // the tower that damaged the mob utils::Timer m_EffectFireTimer; utils::Timer m_EffectPoisonTimer; utils::Timer m_EffectHealTimer; float m_X = 0, m_Y = 0; public: Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level), m_EffectFireTimer(1000), m_EffectPoisonTimer(1000), m_EffectHealTimer(1000) { } virtual MobType getType() const = 0; virtual void tick(std::uint64_t delta); virtual void OnDeath(World* world) {} const TowerImmunities& getTowerImmunities() const { return getMobTowerImmunities(getType(), m_Level); } const EffectImmunities& getEffectImmunities() const { return getMobEffectImmunities(getType(), m_Level); } PlayerID getSender() const { return m_Sender; } MobLevel getLevel() const { return m_Level; } const MobStats* getStats() const { return getMobStats(getType(), m_Level); } float getHealth() const { return m_Health; } bool isDead() const { return m_Health <= 0; } bool isAlive() const { return m_Health > 0; } const Tower* getLastDamageTower() { return m_LastDamage; } void damage(float dmg, const Tower* damager) { m_Health = std::max(0.0f, m_Health - dmg); m_LastDamage = damager; } void heal(float heal) { m_Health = std::min((float)getStats()->getMaxLife(), m_Health + heal); } float getX() const { return m_X; } void setX(float x) { m_X = x; } float getY() const { return m_Y; } void setY(float y) { m_Y = y; } bool isImmuneTo(TowerType type); bool isImmuneTo(EffectType type); void addEffect(EffectType type, float durationSec, const Tower* tower); bool hasEffect(EffectType type); Direction getDirection() const { return m_Direction; } void setDirection(Direction dir) { m_Direction = dir; } protected: void initHealth() { m_Health = (float)getStats()->getMaxLife(); } private: void updateEffects(std::uint64_t delta); EffectDuration& getEffect(EffectType type); }; typedef std::shared_ptr MobPtr; class Zombie : public Mob { public: Zombie(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Zombie; } }; class Spider : public Mob { public: Spider(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Spider; } }; class Skeleton : public Mob { public: Skeleton(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Skeleton; } }; class PigMan : public Mob { public: PigMan(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Pigman; } }; class Creeper : public Mob { public: Creeper(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Creeper; } }; class Silverfish : public Mob { public: Silverfish(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Silverfish; } }; class Blaze : public Mob { public: Blaze(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Blaze; } }; class Witch : public Mob { public: Witch(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Witch; } }; class Slime : public Mob { public: Slime(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Slime; } }; class Giant : public Mob { public: Giant(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { initHealth(); } virtual MobType getType() const { return MobType::Giant; } }; namespace MobFactory { MobPtr createMob(MobID id, MobType type, std::uint8_t level, PlayerID sender); std::string getMobName(MobType type); } } // namespace game } // namespace td