diff --git a/client/game_config.h b/client/game_config.h index 4040a21e..fa5b8d19 100644 --- a/client/game_config.h +++ b/client/game_config.h @@ -78,7 +78,7 @@ constexpr std::string_view AWP_ITEM_PATH = "../assets/gfx/map/awp_d.bmp"; constexpr std::string_view M3_ITEM_PATH = "../assets/gfx/map/m3_d.bmp"; constexpr std::string_view AK_ITEM_PATH = "../assets/gfx/map/ak47_d.bmp"; constexpr std::string_view BOMB_ITEM_PATH = "../assets/gfx/guns/bomb.bmp"; -constexpr std::string_view BOMB_PLANTED_ITEM_PATH = "../assets/gfx/map/bomb_b.bmp"; +constexpr std::string_view BOMB_PLANTED_ITEM_PATH = "../assets/gfx/map/bomb_d.bmp"; } // namespace Paths // --- Gun Type Offsets --- diff --git a/client/gui/controllers/keyboardhandler.cpp b/client/gui/controllers/keyboardhandler.cpp index a4b46161..2b1c7826 100644 --- a/client/gui/controllers/keyboardhandler.cpp +++ b/client/gui/controllers/keyboardhandler.cpp @@ -1,18 +1,20 @@ #include "keyboardhandler.h" #include +#include #include KeyboardHandler::KeyboardHandler(Queue& output_queue, shopDisplay& shopRef, ScoreDisplay& score_displayRef, SoundManager& sound_managerRef, - SdlHud& hudDisplayRef): + SdlHud& hudDisplayRef, SdlWorld& wordRef): output_queue(output_queue), shopRef(shopRef), score_displayRef(score_displayRef), sound_manager(sound_managerRef), - hudDisplayRef(hudDisplayRef) {} + hudDisplayRef(hudDisplayRef), + worldRef(wordRef) {} void KeyboardHandler::handleEvent(const SDL_Event& event) { if (event.type != SDL_KEYDOWN) { @@ -22,10 +24,12 @@ void KeyboardHandler::handleEvent(const SDL_Event& event) { break; case SDLK_b: output_queue.push(Message(GetShopPricesCommand())); + break; case SDLK_m: sound_manager.toggle_mute(); hudDisplayRef.update_mute_icon(); + break; case SDLK_TAB: if (!score_displayRef.isActive()) { @@ -33,34 +37,53 @@ void KeyboardHandler::handleEvent(const SDL_Event& event) { } else { score_displayRef.updateState(); } + break; case SDLK_1: std::cout << "Switching to primary item" << std::endl; output_queue.push(Message(SwitchItemCommand(ItemSlot::Primary))); + break; case SDLK_2: std::cout << "Switching to 2 item" << std::endl; output_queue.push(Message(SwitchItemCommand(ItemSlot::Secondary))); + break; case SDLK_3: std::cout << "Switching to 3 item" << std::endl; output_queue.push(Message(SwitchItemCommand(ItemSlot::Melee))); + break; case SDLK_4: std::cout << "Switching to 4 item" << std::endl; output_queue.push(Message(SwitchItemCommand(ItemSlot::Bomb))); + break; case SDLK_r: output_queue.push(Message(ReloadCommand())); sound_manager.play("reload"); + break; case SDLK_g: sound_manager.play("item_pick"); output_queue.push(Message(PickUpItemCommand())); std::cout << "Picking up item" << std::endl; break; + case SDLK_e: + std::optional maybe_message = worldRef.getStartBombMessage(sound_manager); + if (maybe_message.has_value()) { + output_queue.push(std::move(*maybe_message)); + return; + } + return; + break; } } + + std::optional maybe_message = worldRef.getStopBombMessage(sound_manager); + if (maybe_message.has_value()) { + output_queue.push(std::move(*maybe_message)); + } update_direction(); } diff --git a/client/gui/controllers/keyboardhandler.h b/client/gui/controllers/keyboardhandler.h index efc193ed..0b7037d1 100644 --- a/client/gui/controllers/keyboardhandler.h +++ b/client/gui/controllers/keyboardhandler.h @@ -18,7 +18,7 @@ class KeyboardHandler { public: explicit KeyboardHandler(Queue& output_queue, shopDisplay& shopRef, ScoreDisplay& score_displayRef, SoundManager& sound_manager, - SdlHud& hudDisplayRef); + SdlHud& hudDisplayRef, SdlWorld& wordRef); void handleEvent(const SDL_Event& event); private: @@ -27,6 +27,7 @@ class KeyboardHandler { ScoreDisplay& score_displayRef; SoundManager& sound_manager; SdlHud& hudDisplayRef; + SdlWorld& worldRef; void update_direction(); }; diff --git a/client/gui/map_view/sdl_item.h b/client/gui/map_view/sdl_item.h index d6d28dc1..5d7f1113 100644 --- a/client/gui/map_view/sdl_item.h +++ b/client/gui/map_view/sdl_item.h @@ -14,6 +14,7 @@ #include "common/utils/vector_2d.h" class SdlItem { + static constexpr std::string_view AK47_PATH = "../assets/gfx/guns/ak47.xcf"; static constexpr std::string_view M3_PATH = "../assets/gfx/guns/m3.xcf"; static constexpr std::string_view GLOCK_PATH = "../assets/gfx/guns/glock.xcf"; @@ -26,6 +27,7 @@ class SdlItem { std::unique_ptr knife_texture; std::unique_ptr bomb_texture; + public: explicit SdlItem(const SdlWindow& window); void render_gun(GunType gun_type, Vector2D pos, float angle); diff --git a/client/gui/map_view/sdl_world.cpp b/client/gui/map_view/sdl_world.cpp index 0270353d..daabfb4d 100644 --- a/client/gui/map_view/sdl_world.cpp +++ b/client/gui/map_view/sdl_world.cpp @@ -94,3 +94,52 @@ void SdlWorld::render() { field_of_view.render(window.getWidth(), window.getHeight(), get_rotation(game_state.get_players().at(player_name))); } + +// enum class BombPhaseType { NotPlanted, Planted, Exploded, Defused, Planting, Defusing }; +std::optional SdlWorld::getStartBombMessage(SoundManager& sound_manager) { + if (game_state.get_phase().get_type() != PhaseType::InRound && + game_state.get_phase().get_type() != PhaseType::BombPlanted) { + std::cout << "Cannot start bomb action outside of InRound phase." << std::endl; + return std::nullopt; + } + std::cout << "getStartBombMessage called" << std::endl; + Team player_team = game_state.get_players().at(player_name).get_team(); + if (player_team == Team::CT) { + /*if (game_state.get_bomb().value().item.get_bomb_phase() == BombPhaseType::Planted) {*/ + std::cout << "Starting bomb defusing" << std::endl; + sound_manager.play("defuse_bomb"); + return Message(StartDefusingBombCommand()); + //} + } else if (player_team == Team::TT) { + // if (game_state.get_bomb().value().item.get_bomb_phase() == BombPhaseType::NotPlanted) { + sound_manager.play("plant_bomb"); + std::cout << "Starting bomb planting" << std::endl; + return Message(StartPlantingBombCommand()); + // } + } + return std::nullopt; +} + +std::optional SdlWorld::getStopBombMessage(SoundManager& sound_manager) { + if (game_state.get_phase().get_type() != PhaseType::InRound) { + std::cout << "Cannot start bomb action outside of InRound phase." << std::endl; + return std::nullopt; + } + Team player_team = game_state.get_players().at(player_name).get_team(); + if (player_team == Team::CT) { + // if (game_state.get_bomb().value().item.get_bomb_phase() == BombPhaseType::Defusing) { + std::cout << "Stop defusing bomb" << std::endl; + sound_manager.play("stop_defuse_bomb"); + return Message(StopDefusingBombCommand()); + //} + + } else if (player_team == Team::TT) { + // if (game_state.get_bomb().value().item.get_bomb_phase() == BombPhaseType::Planting) { + std::cout << "Stop plant bomb" << std::endl; + sound_manager.play("stop_plant_bomb"); + return Message(StopPlantingBombCommand()); + // } + } + + return std::nullopt; +} diff --git a/client/gui/map_view/sdl_world.h b/client/gui/map_view/sdl_world.h index a630c2c5..75310ace 100644 --- a/client/gui/map_view/sdl_world.h +++ b/client/gui/map_view/sdl_world.h @@ -14,6 +14,9 @@ #include "../window_elements/area.h" #include "../window_elements/sdl_texture.h" #include "../window_elements/sdl_window.h" +#include "client/sound_manager.h" +#include "common/map/map.h" +#include "common/message.h" #include "common/responses.h" #include "common/updates/game_update.h" @@ -47,6 +50,8 @@ class SdlWorld { void render(); void renderBackground(); + std::optional getStartBombMessage(SoundManager& sound_manager); + std::optional getStopBombMessage(SoundManager& sound_manager); void handle_hit(HitResponse&& hit); float get_rotation(const PlayerUpdate& player_state); }; diff --git a/client/sdl_display.cpp b/client/sdl_display.cpp index ff50db9e..31aa1a8c 100644 --- a/client/sdl_display.cpp +++ b/client/sdl_display.cpp @@ -89,8 +89,8 @@ void SDLDisplay::run() { quit_flag, MouseHandler(output_queue, SCREEN_WIDTH, SCREEN_HEIGHT, list_teams, *shop_display, hud_display, list_skins), - KeyboardHandler(output_queue, *shop_display, *score_display, sound_manager, - hud_display)); + KeyboardHandler(output_queue, *shop_display, *score_display, sound_manager, hud_display, + *world)); end_round_display = std::make_unique(window, state); input_handler->start(); @@ -124,6 +124,9 @@ void SDLDisplay::run() { world->render(); hud_display.render(); end_round_display->render(); + } else if (state.get_phase().get_type() == PhaseType::BombPlanted) { + world->render(); + hud_display.render(); } if (score_display->isActive()) { @@ -286,6 +289,16 @@ void SDLDisplay::update_state() { sound_manager.play("error"); break; } + case MessageType::BOMB_EXPLODED_RESP: { + std::cout << "Received BombExplodedResponse" << std::endl; + auto bomb_exploded_resp = msg.get_content(); + /*GameUpdate updates = game.get_full_update(); + EXPECT_TRUE(bomb_exploded_resp.get_explosion_center() == + updates.get_bomb().value().hitbox.get_center()); + EXPECT_EQ(bomb_exploded_resp.get_explosion_radius(), BombConfig::max_range);*/ + sound_manager.play("bomb_exploded"); + break; + } default: { std::cerr << "SDLDisplay::update_state: Received unexpected message type: " << msg.get_type() << std::endl; diff --git a/maps/map.yaml b/maps/map.yaml index 3bdb0dd1..47fefad9 100644 --- a/maps/map.yaml +++ b/maps/map.yaml @@ -3,178 +3,178 @@ max_players: 10 height: 5 width: 5 tiles: - - x: 1 - y: 1 - id: 9 - is_collidable: false - is_spawn_tt: true - is_spawn_ct: false - is_bomb_site: false - - x: 3 - y: 3 - id: 9 - is_collidable: false - is_spawn_tt: false - is_spawn_ct: true - is_bomb_site: false - - x: 1 - y: 2 - id: 9 - is_collidable: false - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 2 - y: 1 - id: 9 - is_collidable: false - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 2 - y: 2 - id: 9 - is_collidable: false - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: true - - x: 3 - y: 2 - id: 9 - is_collidable: false - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 1 - y: 3 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 2 - y: 3 - id: 9 - is_collidable: false - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 0 - y: 0 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 1 - y: 0 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 2 - y: 0 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 3 - y: 0 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 4 - y: 0 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 0 - y: 1 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 4 - y: 1 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 0 - y: 2 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 4 - y: 2 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 0 - y: 3 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 4 - y: 3 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 0 - y: 4 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 1 - y: 4 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 2 - y: 4 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 3 - y: 4 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 4 - y: 4 - id: 20 - is_collidable: true - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false - - x: 3 - y: 1 - id: 9 - is_collidable: false - is_spawn_tt: false - is_spawn_ct: false - is_bomb_site: false + - x: 1 + y: 1 + id: 9 + is_collidable: false + is_spawn_tt: true + is_spawn_ct: false + is_bomb_site: true + - x: 3 + y: 3 + id: 9 + is_collidable: false + is_spawn_tt: false + is_spawn_ct: true + is_bomb_site: true + - x: 1 + y: 2 + id: 9 + is_collidable: false + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: true + - x: 2 + y: 1 + id: 9 + is_collidable: false + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: true + - x: 2 + y: 2 + id: 9 + is_collidable: false + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: true + - x: 3 + y: 2 + id: 9 + is_collidable: false + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: true + - x: 1 + y: 3 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: true + - x: 2 + y: 3 + id: 9 + is_collidable: false + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: true + - x: 0 + y: 0 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 1 + y: 0 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 2 + y: 0 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 3 + y: 0 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 4 + y: 0 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 0 + y: 1 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 4 + y: 1 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 0 + y: 2 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 4 + y: 2 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 0 + y: 3 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 4 + y: 3 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 0 + y: 4 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 1 + y: 4 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 2 + y: 4 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 3 + y: 4 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 4 + y: 4 + id: 20 + is_collidable: true + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: false + - x: 3 + y: 1 + id: 9 + is_collidable: false + is_spawn_tt: false + is_spawn_ct: false + is_bomb_site: true diff --git a/server/game/game.cpp b/server/game/game.cpp index c504e7ad..e9c5f3cf 100644 --- a/server/game/game.cpp +++ b/server/game/game.cpp @@ -92,6 +92,7 @@ void Game::advance_bomb_logic() { bomb.advance(state.get_phase().get_time_now()); if (!bomb.is_planted()) return; + player->handle_stop_planting(state.get_phase().get_time_now()); state.add_bomb(std::move(player->drop_bomb().value()), player->get_hitbox().center); state.get_phase().start_bomb_planted_phase(); } diff --git a/server/items/bomb.cpp b/server/items/bomb.cpp index f6360995..16f5a783 100644 --- a/server/items/bomb.cpp +++ b/server/items/bomb.cpp @@ -48,16 +48,19 @@ void Bomb::start_defusing(TimePoint now) { change_bomb_phase(BombPhaseType::Defusing, now); } -void Bomb::stop_defusing(TimePoint now) { +void Bomb::stop_defusing([[maybe_unused]] TimePoint now) { if (state.get_bomb_phase() != BombPhaseType::Defusing) return; - change_bomb_phase(BombPhaseType::Planted, now); + state.set_bomb_phase(BombPhaseType::Planted); + phase_start_time = plant_time; } void Bomb::advance(TimePoint now) { if (is_planting()) { - if (now - phase_start_time >= std::chrono::seconds(BombConfig::secs_to_plant)) + if (now - phase_start_time >= std::chrono::seconds(BombConfig::secs_to_plant)) { change_bomb_phase(BombPhaseType::Planted, now); + plant_time = now; + } return; } @@ -69,8 +72,8 @@ void Bomb::advance(TimePoint now) { if (!is_planted()) return; - float new_secs_to_explode = state.get_secs_to_explode() - - std::chrono::duration(now - phase_start_time).count(); + float new_secs_to_explode = + BombConfig::secs_to_explode - std::chrono::duration(now - plant_time).count(); state.set_secs_to_explode(std::max(0.0f, new_secs_to_explode)); } @@ -81,6 +84,7 @@ Effect Bomb::explode(const Vector2D& origin) { } void Bomb::reset() { - change_bomb_phase(BombPhaseType::NotPlanted, TimePoint::min()); + change_bomb_phase(BombPhaseType::NotPlanted, TimePoint()); + plant_time = TimePoint(); state.set_secs_to_explode(BombConfig::secs_to_explode); } diff --git a/server/items/bomb.h b/server/items/bomb.h index 67529e20..efe142c4 100644 --- a/server/items/bomb.h +++ b/server/items/bomb.h @@ -7,6 +7,7 @@ class Bomb: public Logic { TimePoint phase_start_time; + TimePoint plant_time; void change_bomb_phase(BombPhaseType new_phase, TimePoint now);