#pragma once #include #include #include #include "misc/Time.h" namespace td { namespace game { enum class TowerType : std::uint8_t { Archer = 0, Ice, Sorcerer, Zeus, Mage, Artillery, Quake, Poison, Leach, Turret, Necromancer, TowerCount }; enum class TowerSize : bool { Little = 0, // 3x3 Big, // 5x5 }; enum class TowerPath : std::uint8_t { Top = 0, // Base path Bottom }; class TowerStats { private: float m_Rate; float m_Damage; std::uint8_t m_Range; public: TowerStats(float rate, float damage, std::uint8_t range) : m_Rate(rate), m_Damage(damage), m_Range(range) { } float getDamageRate() const { return m_Rate; } float getDamage() const { return m_Damage; } std::uint8_t getRange() const { return m_Range; } }; class TowerLevel { private: // 1, 2, 3, 4 std::uint8_t m_Level : 3; // 0 : base path 1 : top path (if there is bottom path) 2 : bottom path (if there is top path) TowerPath m_Path : 1; public: TowerLevel() : m_Level(1), m_Path(TowerPath::Top) {} TowerLevel(std::uint8_t level, TowerPath path) : m_Level(level), m_Path(path) {} std::uint8_t getLevel() const { return m_Level; } TowerPath getPath() const { return m_Path; } void setLevel(std::uint8_t level) { m_Level = level; } void setPath(TowerPath path) { m_Path = path; } // operator to sort maps friend bool operator<(const TowerLevel& level, const TowerLevel& other) { return level.getLevel() * static_cast(level.getPath()) < other.getLevel() * static_cast(other.getPath()); } }; const TowerStats* getTowerStats(TowerType type, TowerLevel level); class Tower { private: std::uint16_t m_X, m_Y; TowerLevel m_Level{}; protected: utils::Timer m_Timer; public: // converting seconds to millis Tower(std::uint16_t x, std::uint16_t y) : m_X(x), m_Y(y), m_Timer(getStats()->getDamageRate() * 1000) {} virtual TowerType getType() const = 0; virtual TowerSize getSize() const = 0; virtual void tick(std::uint64_t delta) = 0; void upgrade(std::uint8_t level, TowerPath path) { m_Level.setLevel(level); m_Level.setPath(path); } std::uint16_t getX() const { return m_X; } std::uint16_t getY() const { return m_Y; } const TowerLevel& getLevel() const { return m_Level; } const TowerStats* getStats() const { return getTowerStats(getType(), m_Level); } }; typedef std::shared_ptr TowerPtr; class TowerInfo { private: std::string m_Name, m_Description; bool m_IsBigTower; public: TowerInfo(std::string&& name, std::string&& description, bool big) : m_Name(std::move(name)), m_Description(std::move(description)), m_IsBigTower(big) {} const std::string& getName() const { return m_Name; } const std::string& getDescription() const { return m_Description; } bool isBigTower() const { return m_IsBigTower; } }; const TowerInfo& getTowerInfo(TowerType type); // ---------- Little Towers ---------- class LittleTower : public Tower { public: LittleTower(std::uint16_t x, std::uint16_t y) : Tower(x, y) {} virtual TowerSize getSize() const { return TowerSize::Little; } virtual TowerType getType() const = 0; virtual void tick(std::uint64_t delta) = 0; }; class ArcherTower : public LittleTower { public: ArcherTower(std::uint16_t x, std::uint16_t y) : LittleTower(x, y) {} virtual TowerType getType() const { return TowerType::Archer; } virtual void tick(std::uint64_t delta); }; class IceTower : public LittleTower { public: IceTower(std::uint16_t x, std::uint16_t y) : LittleTower(x, y) {} virtual TowerType getType() const { return TowerType::Ice; } virtual void tick(std::uint64_t delta); }; class MageTower : public LittleTower { public: MageTower(std::uint16_t x, std::uint16_t y) : LittleTower(x, y) {} virtual TowerType getType() const { return TowerType::Mage; } virtual void tick(std::uint64_t delta); }; class PoisonTower : public LittleTower { public: PoisonTower(std::uint16_t x, std::uint16_t y) : LittleTower(x, y) {} virtual TowerType getType() const { return TowerType::Poison; } virtual void tick(std::uint64_t delta); }; class QuakeTower : public LittleTower { public: QuakeTower(std::uint16_t x, std::uint16_t y) : LittleTower(x, y) {} virtual TowerType getType() const { return TowerType::Quake; } virtual void tick(std::uint64_t delta); }; class ArtilleryTower : public LittleTower { public: ArtilleryTower(std::uint16_t x, std::uint16_t y) : LittleTower(x, y) {} virtual TowerType getType() const { return TowerType::Artillery; } virtual void tick(std::uint64_t delta); }; class SorcererTower : public LittleTower { public: SorcererTower(std::uint16_t x, std::uint16_t y) : LittleTower(x, y) {} virtual TowerType getType() const { return TowerType::Sorcerer; } virtual void tick(std::uint64_t delta); }; class ZeusTower : public LittleTower { public: ZeusTower(std::uint16_t x, std::uint16_t y) : LittleTower(x, y) {} virtual TowerType getType() const { return TowerType::Zeus; } virtual void tick(std::uint64_t delta); }; // ---------- Big Towers ---------- class BigTower : public Tower { public: BigTower(std::uint16_t x, std::uint16_t y) : Tower(x, y) {} virtual TowerSize getSize() const { return TowerSize::Big; } virtual TowerType getType() const = 0; virtual void tick(std::uint64_t delta) = 0; }; class TurretTower : public BigTower { public: TurretTower(std::uint16_t x, std::uint16_t y) : BigTower(x, y) {} virtual TowerType getType() const { return TowerType::Turret; } virtual void tick(std::uint64_t delta); }; class NecromancerTower : public BigTower { public: NecromancerTower(std::uint16_t x, std::uint16_t y) : BigTower(x, y) {} virtual TowerType getType() const { return TowerType::Necromancer; } virtual void tick(std::uint64_t delta); }; class LeachTower : public BigTower { public: LeachTower(std::uint16_t x, std::uint16_t y) : BigTower(x, y) {} virtual TowerType getType() const { return TowerType::Leach; } virtual void tick(std::uint64_t delta); }; } // namespace game } // namespace td