#pragma once #include #include #include #include #include #include #include "Mobs.h" #include "Team.h" namespace td { namespace game { typedef std::pair ChunkCoord; } } namespace std { template <> struct hash { std::size_t operator()(const td::game::ChunkCoord& key) const { // Compute individual hash values for first, // second and third and combine them using XOR // and bit shifting: return ((std::hash()(key.first) ^ (std::hash()(key.second) << 1)) >> 1); } }; } namespace td { namespace protocol { class WorldBeginDataPacket; class WorldDataPacket; } namespace game { class Game; enum class TileType : std::uint8_t { None = 0, Tower, Walk, Decoration, /*Heal, Lava, Bedrock, Freeze, Ice,*/ }; struct Color { std::uint8_t r, g, b; }; static constexpr Color BLACK{ 0, 0, 0 }; static constexpr Color WHITE{ 255, 255, 255 }; static constexpr Color RED{ 255, 0, 0 }; static constexpr Color GREEN{ 0, 255, 0 }; static constexpr Color BLUE{ 0, 0, 255 }; struct Tile { virtual TileType getType() const = 0; }; struct TowerTile : Tile { std::uint8_t color_palette_ref; TeamColor team_owner; virtual TileType getType() const { return TileType::Tower; } }; struct WalkableTile : Tile { Direction direction; virtual TileType getType() const { return TileType::Walk; } }; struct DecorationTile : Tile { std::uint16_t color_palette_ref; virtual TileType getType() const { return TileType::Decoration; } }; typedef std::shared_ptr TilePtr; typedef std::vector ChunkPalette; typedef std::shared_ptr WalkableTilePtr; typedef std::array ChunkData; typedef std::uint32_t TileIndex; //32 x 32 area struct Chunk { enum { ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight }; // stores index of tile palette ChunkData tiles{ 0 }; ChunkPalette palette; TileIndex getTileIndex(std::uint16_t tileNumber) const { TileIndex chunkPaletteIndex = tiles.at(tileNumber); if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile return 0; return palette.at(chunkPaletteIndex); } }; typedef std::shared_ptr ChunkPtr; typedef std::array TowerTileColorPalette; typedef std::vector TilePalette; typedef std::vector MobList; typedef std::array SpawnColorPalette; typedef std::vector TowerList; class WorldListener { public: WorldListener() {} virtual void OnTowerAdd(TowerPtr tower) {} virtual void OnTowerRemove(TowerPtr tower) {} virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) {} virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) {} virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) {} }; typedef utils::ObjectNotifier WorldNotifier; class World : public WorldListener, public MobListener { protected: TowerTileColorPalette m_TowerPlacePalette; Color m_WalkablePalette; std::vector m_DecorationPalette; Color m_Background; std::unordered_map m_Chunks; SpawnColorPalette m_SpawnColorPalette; TilePalette m_TilePalette; MobList m_Mobs; TowerList m_Towers; Game* m_Game; WorldNotifier m_WorldNotifier; MobNotifier m_MobNotifier; public: World(Game* game); bool loadMap(const protocol::WorldBeginDataPacket* worldHeader); bool loadMap(const protocol::WorldDataPacket* worldData); bool loadMapFromFile(const std::string& fileName); bool saveMap(const std::string& fileName) const; void tick(std::uint64_t delta); void spawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir); TowerPtr placeTowerAt(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder); TowerPtr removeTower(TowerID id); TilePtr getTile(std::int32_t x, std::int32_t y) const; const TowerTileColorPalette& getTowerTileColorPalette() const { return m_TowerPlacePalette; } const Color& getWalkableTileColor() const { return m_WalkablePalette; } const std::vector& getDecorationPalette() const { return m_DecorationPalette; } const Color& getBackgroundColor() const { return m_Background; } const TilePalette& getTilePalette() const { return m_TilePalette; } TilePtr getTilePtr(TileIndex index) const { if (index == 0) return nullptr; return m_TilePalette.at(index - 1); } bool CanPlaceLittleTower(const glm::vec2& worldPos, PlayerID player) const; bool CanPlaceBigTower(const glm::vec2& worldPos, PlayerID player) const; TowerPtr getTower(const glm::vec2& position) const; // returns null if no tower is here const std::unordered_map& getChunks() const { return m_Chunks; } const Color& getSpawnColor(TeamColor color) const { return m_SpawnColorPalette[(std::size_t)color]; } const SpawnColorPalette& getSpawnColors() const { return m_SpawnColorPalette; } const MobList& getMobList() const { return m_Mobs; } MobList& getMobList() { return m_Mobs; } const Color* getTileColor(TilePtr tile) const; Team& getRedTeam(); const Team& getRedTeam() const; Team& getBlueTeam(); const Team& getBlueTeam() const; Team& getTeam(TeamColor team); const Team& getTeam(TeamColor team) const; const TeamList& getTeams() const; const TowerList& getTowers() const { return m_Towers; }; TowerPtr getTowerById(TowerID tower); const Player* getPlayerById(PlayerID id) const; WorldNotifier& getWorldNotifier() { return m_WorldNotifier; } MobNotifier& getMobNotifier() { return m_MobNotifier; } // WorldListener virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter); virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter); virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter); // MobListener virtual void OnMobDamage(Mob* target, float damage, Tower* source); virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage); private: void tickMobs(std::uint64_t delta); void cleanDeadMobs(); }; } // namespace game } // namespace td