#pragma once #include #include #include "misc/Time.h" #include "misc/Shapes.h" #include "game/Types.h" namespace td { namespace game { class World; class Mob; typedef std::shared_ptr MobPtr; enum class TowerType : std::uint8_t { Archer = 0, Ice, Sorcerer, Zeus, Mage, Artillery, Quake, Poison, Leach, Turret, Necromancer, TowerCount }; enum class TowerSize : std::uint8_t { Little = 3, // 3x3 Big = 5, // 5x5 }; enum class TowerPath : std::uint8_t { Top = 0, Base, // 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 : 2; public: TowerLevel() : m_Level(1), m_Path(TowerPath::Base) {} 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()) * 4 < other.GetLevel() + static_cast(other.GetPath()) * 4; } }; const TowerStats* GetTowerStats(TowerType type, TowerLevel level); typedef std::uint16_t TowerID; class Tower : public utils::shape::Circle { private: TowerID m_ID; TowerType m_Type; TowerLevel m_Level{}; PlayerID m_Builder; protected: utils::CooldownTimer m_Timer; public: Tower(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) : utils::shape::Circle(x + 0.5f, y + 0.5f, 0), m_ID(id), m_Type(type), m_Builder(builder), m_Timer(GetStats()->GetDamageRate() * 1000) { // converting seconds to millis SetRadius(GetStats()->GetRange()); } virtual TowerType GetType() const = 0; virtual TowerSize GetSize() const = 0; virtual void Tick(std::uint64_t delta, World* world) = 0; void Upgrade(std::uint8_t level, TowerPath path) { m_Level.SetLevel(level); m_Level.SetPath(path); m_Timer.SetCooldown(GetStats()->GetDamageRate() * 1000); // converting seconds to millis m_Timer.Reset(); SetRadius(GetStats()->GetRange()); } std::uint16_t GetID() const { return m_ID; } const TowerLevel& GetLevel() const { return m_Level; } const TowerStats* GetStats() const { return GetTowerStats(m_Type, m_Level); } PlayerID GetBuilder() const { return m_Builder; } bool IsMobInRange(MobPtr mob); }; typedef std::shared_ptr TowerPtr; namespace TowerFactory { TowerPtr CreateTower(TowerType type, TowerID id, std::int32_t x, std::int32_t y, PlayerID builder); std::string GetTowerName(TowerType type); } // namespace TowerFactory 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(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {} virtual TowerSize GetSize() const { return TowerSize::Little; } virtual TowerType GetType() const = 0; virtual void Tick(std::uint64_t delta, World* world) = 0; }; class ArcherTower : public LittleTower { public: ArcherTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {} constexpr static float ExplosionRadius = 1.5f; constexpr static float FireDurationSec = 10.0f; virtual TowerType GetType() const { return TowerType::Archer; } virtual void Tick(std::uint64_t delta, World* world); }; class IceTower : public LittleTower { public: IceTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Ice; } virtual void Tick(std::uint64_t delta, World* world); }; class MageTower : public LittleTower { public: MageTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Mage; } virtual void Tick(std::uint64_t delta, World* world); }; class PoisonTower : public LittleTower { public: PoisonTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Poison; } virtual void Tick(std::uint64_t delta, World* world); }; class QuakeTower : public LittleTower { public: QuakeTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Quake; } virtual void Tick(std::uint64_t delta, World* world); }; class ArtilleryTower : public LittleTower { public: ArtilleryTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Artillery; } virtual void Tick(std::uint64_t delta, World* world); }; class SorcererTower : public LittleTower { public: SorcererTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Sorcerer; } virtual void Tick(std::uint64_t delta, World* world); }; class ZeusTower : public LittleTower { public: ZeusTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Zeus; } virtual void Tick(std::uint64_t delta, World* world); }; // ---------- Big Towers ---------- class BigTower : public Tower { public: BigTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {} virtual TowerSize GetSize() const { return TowerSize::Big; } virtual TowerType GetType() const = 0; virtual void Tick(std::uint64_t delta, World* world) = 0; }; class TurretTower : public BigTower { public: TurretTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Turret; } virtual void Tick(std::uint64_t delta, World* world); }; class NecromancerTower : public BigTower { public: NecromancerTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Necromancer; } virtual void Tick(std::uint64_t delta, World* world); }; class LeachTower : public BigTower { public: LeachTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {} virtual TowerType GetType() const { return TowerType::Leach; } virtual void Tick(std::uint64_t delta, World* world); }; } // namespace game } // namespace td