From afccaa7025896d4a8fb6c71ad8cc977b52853bda Mon Sep 17 00:00:00 2001 From: Jesabel Pugliese Date: Tue, 24 Jun 2025 00:48:22 -0300 Subject: [PATCH 1/6] refactor(player): centralize player speed configuration in player --- server/game/game_config.h | 1 - server/physics/physics_system.cpp | 7 +++---- server/physics/physics_system.h | 2 +- server/player/player.cpp | 6 ++++-- server/player/player.h | 1 + server/player/player_config.h | 1 + server/states/player_state.cpp | 7 +++++-- server/states/player_state.h | 4 +++- tests/server/game/test_game.cpp | 5 +++-- 9 files changed, 21 insertions(+), 13 deletions(-) diff --git a/server/game/game_config.h b/server/game/game_config.h index a89a6a04..f12fb8e9 100644 --- a/server/game/game_config.h +++ b/server/game/game_config.h @@ -2,7 +2,6 @@ namespace GameConfig { static constexpr int tickrate = 30; -static constexpr int player_speed = 4.5; // m/s static constexpr int max_rounds = 10; }; // namespace GameConfig diff --git a/server/physics/physics_system.cpp b/server/physics/physics_system.cpp index e3c24892..e60cb167 100644 --- a/server/physics/physics_system.cpp +++ b/server/physics/physics_system.cpp @@ -6,7 +6,6 @@ #include #include "common/physics/physics_config.h" -#include "server/game/game_config.h" #include "circular_hitbox.h" #include "rect_hitbox.h" @@ -85,7 +84,7 @@ Vector2D PhysicsSystem::calculate_new_pos(const std::unique_ptr& player, if (move_dir == Vector2D(0, 0)) return player->get_hitbox().center; - Vector2D step = calculate_step(move_dir, tick_duration); + Vector2D step = calculate_step(player->get_speed(), move_dir, tick_duration); Vector2D new_pos = player->get_hitbox().center + step; if (can_move_to_pos(new_pos)) @@ -106,8 +105,8 @@ Vector2D PhysicsSystem::calculate_new_pos(const std::unique_ptr& player, return player->get_hitbox().center; } -Vector2D PhysicsSystem::calculate_step(const Vector2D& dir, float tick_duration) const { - return dir.normalized(PhysicsConfig::meter_size) * GameConfig::player_speed * tick_duration; +Vector2D PhysicsSystem::calculate_step(int speed, const Vector2D& dir, float tick_duration) const { + return dir.normalized(PhysicsConfig::meter_size) * speed * tick_duration; } bool PhysicsSystem::can_move_to_pos(const Vector2D& pos) const { diff --git a/server/physics/physics_system.h b/server/physics/physics_system.h index ecfe6fe8..d83213e6 100644 --- a/server/physics/physics_system.h +++ b/server/physics/physics_system.h @@ -58,7 +58,7 @@ class PhysicsSystem { Vector2D rand_pos_in_vector(const std::vector>& vector) const; // Movement and positioning - Vector2D calculate_step(const Vector2D& dir, float tick_duration) const; + Vector2D calculate_step(int speed, const Vector2D& dir, float tick_duration) const; bool can_move_to_pos(const Vector2D& pos) const; // Target finding helpers diff --git a/server/player/player.cpp b/server/player/player.cpp index cb257266..593893fa 100644 --- a/server/player/player.cpp +++ b/server/player/player.cpp @@ -10,8 +10,8 @@ Player::Player(Team team, CharacterType character_type, Circle hitbox): Logic(PlayerState( - team, character_type, hitbox, Vector2D(0.0f, 0.0f), Vector2D(0.0f, 0.0f), false, - PlayerConfig::full_health, ItemSlot::Secondary)), + team, character_type, hitbox, Vector2D(0.0f, 0.0f), Vector2D(0.0f, 0.0f), + PlayerConfig::speed, false, PlayerConfig::full_health, ItemSlot::Secondary)), scoreboard_entry(state.get_inventory().get_money(), 0, 0, 0), status(std::make_unique()) {} @@ -40,6 +40,8 @@ Circle Player::get_hitbox() const { return state.get_hitbox(); } Vector2D Player::get_move_dir() const { return state.get_velocity(); } +int Player::get_speed() const { return state.get_speed(); } + Inventory& Player::get_inventory() { return state.get_inventory(); } ScoreboardEntry Player::get_scoreboard_entry() const { return scoreboard_entry; } diff --git a/server/player/player.h b/server/player/player.h index b6a09be2..ff603e4c 100644 --- a/server/player/player.h +++ b/server/player/player.h @@ -42,6 +42,7 @@ class Player: public Logic { CharacterType get_character_type() const; Circle get_hitbox() const; Vector2D get_move_dir() const; + int get_speed() const; Inventory& get_inventory(); ScoreboardEntry get_scoreboard_entry() const; diff --git a/server/player/player_config.h b/server/player/player_config.h index 7ce993b3..c48ba738 100644 --- a/server/player/player_config.h +++ b/server/player/player_config.h @@ -3,6 +3,7 @@ #include "common/physics/physics_config.h" namespace PlayerConfig { +static constexpr int speed = 4.5; // m/s static constexpr int full_health = 100; static constexpr int initial_money = 800; }; // namespace PlayerConfig diff --git a/server/states/player_state.cpp b/server/states/player_state.cpp index 3d90a0dd..820a3559 100644 --- a/server/states/player_state.cpp +++ b/server/states/player_state.cpp @@ -3,13 +3,14 @@ #include PlayerState::PlayerState(Team team, CharacterType character_type, Circle hitbox, - Vector2D aim_direction, Vector2D velocity, bool ready, int health, - ItemSlot equipped_item): + Vector2D aim_direction, Vector2D velocity, int speed, bool ready, + int health, ItemSlot equipped_item): team(team), character_type(character_type), hitbox(hitbox), aim_direction(aim_direction), velocity(velocity), + speed(speed), ready(ready), health(health), equipped_item(equipped_item) { @@ -26,6 +27,8 @@ Vector2D PlayerState::get_aim_direction() const { return aim_direction; } Vector2D PlayerState::get_velocity() const { return velocity; } +int PlayerState::get_speed() const { return speed; } + bool PlayerState::get_ready() const { return ready; } int PlayerState::get_health() const { return health; } diff --git a/server/states/player_state.h b/server/states/player_state.h index f5593bbc..b2a36efc 100644 --- a/server/states/player_state.h +++ b/server/states/player_state.h @@ -16,6 +16,7 @@ class PlayerState: public State { Circle hitbox; Vector2D aim_direction; Vector2D velocity; + int speed; bool ready; int health; ItemSlot equipped_item; @@ -23,13 +24,14 @@ class PlayerState: public State { public: PlayerState(Team team, CharacterType character_type, Circle hitbox, Vector2D aim_direction, - Vector2D velocity, bool ready, int health, ItemSlot equipped_item); + Vector2D velocity, int speed, bool ready, int health, ItemSlot equipped_item); Team get_team() const; CharacterType get_character_type() const; Circle get_hitbox() const; Vector2D get_aim_direction() const; Vector2D get_velocity() const; + int get_speed() const; bool get_ready() const; int get_health() const; ItemSlot get_equipped_item() const; diff --git a/tests/server/game/test_game.cpp b/tests/server/game/test_game.cpp index 93fe4f90..3f3cd327 100644 --- a/tests/server/game/test_game.cpp +++ b/tests/server/game/test_game.cpp @@ -14,6 +14,7 @@ #include "server/game/game_config.h" #include "server/game/shop.h" #include "server/map/map_builder.h" +#include "server/player/player_config.h" #include "server/player_message.h" #include "mock_clock.h" @@ -278,7 +279,7 @@ TEST_F(TestGame, PlayerCanMove) { player_updates = updates.get_players(); Vector2D new_pos = player_updates.at("test_player").get_pos(); - Vector2D step = dir * GameConfig::player_speed * (1.0f / GameConfig::tickrate); + Vector2D step = dir * PlayerConfig::speed * (1.0f / GameConfig::tickrate); EXPECT_EQ(new_pos.get_x(), old_pos.get_x() + step.get_x()); EXPECT_EQ(new_pos.get_y(), old_pos.get_y() + step.get_y()); @@ -301,7 +302,7 @@ TEST_F(TestGame, PlayerCanMoveInDiagonal) { std::map player_updates = updates.get_players(); Vector2D new_pos = player_updates.at("test_player").get_pos(); - Vector2D step = dir * GameConfig::player_speed * (1.0f / GameConfig::tickrate); + Vector2D step = dir * PlayerConfig::speed * (1.0f / GameConfig::tickrate); EXPECT_EQ(new_pos.get_x(), old_pos.get_x() + step.get_x()); EXPECT_EQ(new_pos.get_y(), old_pos.get_y() + step.get_y()); From f1593f31988a9ce9bfaf9546e44684202bc695e8 Mon Sep 17 00:00:00 2001 From: Jesabel Pugliese Date: Tue, 24 Jun 2025 01:04:06 -0300 Subject: [PATCH 2/6] refactor(shop): move code to .cpp and group constants in a namespace --- server/CMakeLists.txt | 6 ++- server/game/game.h | 2 +- server/game/shop.h | 77 ---------------------------- server/shop/shop.cpp | 53 +++++++++++++++++++ server/shop/shop.h | 32 ++++++++++++ server/shop/shop_prices.h | 12 +++++ tests/CMakeLists.txt | 6 ++- tests/server/game/test_game.cpp | 2 +- tests/server/game/test_game_bomb.cpp | 2 +- tests/server/game/test_shop.cpp | 7 +-- tests/server/player/test_player.cpp | 8 +-- 11 files changed, 115 insertions(+), 92 deletions(-) delete mode 100644 server/game/shop.h create mode 100644 server/shop/shop.cpp create mode 100644 server/shop/shop.h create mode 100644 server/shop/shop_prices.h diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 4cc9ef29..4e768461 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,6 +13,8 @@ target_sources(taller_server # game game/game.cpp game/game_phase.cpp + # shop + shop/shop.cpp # items items/gun.cpp items/bomb.cpp @@ -53,10 +55,12 @@ target_sources(taller_server clock/clock.h clock/real_clock.h # game - game/shop.h game/game.h game/game_phase.h game/game_config.h + # shop + shop/shop.h + shop/shop_prices.h # items items/gun.h items/bomb.h diff --git a/server/game/game.h b/server/game/game.h index 47e0ab2b..d4ebeb67 100644 --- a/server/game/game.h +++ b/server/game/game.h @@ -13,10 +13,10 @@ #include "server/physics/physics_system.h" #include "server/player/player.h" #include "server/player_message.h" +#include "server/shop/shop.h" #include "server/states/game_state.h" #include "game_phase.h" -#include "shop.h" class Game: public Logic { private: diff --git a/server/game/shop.h b/server/game/shop.h deleted file mode 100644 index d9857aee..00000000 --- a/server/game/shop.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include -#include - -#include "common/models.h" -#include "server/items/gun.h" -#include "server/player/inventory.h" - -#define PRICE_AK47 2700 -#define PRICE_M3 1700 -#define PRICE_AWP 4750 - -#define PRICE_MAG_AK47 80 -#define PRICE_MAG_M3 8 -#define PRICE_MAG_AWP 125 -#define PRICE_MAG_GLOCK 20 - -class Shop { -private: - std::map gun_prices; - std::map ammo_prices; - -public: - Shop() { - gun_prices[GunType::AK47] = PRICE_AK47; - gun_prices[GunType::M3] = PRICE_M3; - gun_prices[GunType::AWP] = PRICE_AWP; - - ammo_prices[GunType::AK47] = PRICE_MAG_AK47; - ammo_prices[GunType::M3] = PRICE_MAG_M3; - ammo_prices[GunType::AWP] = PRICE_MAG_AWP; - ammo_prices[GunType::Glock] = PRICE_MAG_GLOCK; - } - - Shop(const Shop&) = delete; - Shop& operator=(const Shop&) = delete; - - Shop(Shop&&) = default; - Shop& operator=(Shop&&) = default; - - std::map get_gun_prices() const { return gun_prices; } - std::map get_ammo_prices() const { return ammo_prices; } - - bool can_buy_gun(const GunType& gun_type, Inventory& inventory) const { - if (gun_type == GunType::Glock) - return false; - return gun_prices.at(gun_type) <= inventory.get_money(); - } - - bool can_buy_ammo(const ItemSlot& slot, Inventory& inventory) const { - if (slot != ItemSlot::Primary && slot != ItemSlot::Secondary) - return false; - - auto& gun = inventory.get_guns().at(slot); - GunType gun_type = gun->get_type(); - return ammo_prices.at(gun_type) <= inventory.get_money(); - } - - void buy_gun(const GunType& gun_type, Inventory& inventory) const { - if (!can_buy_gun(gun_type, inventory)) - return; - inventory.set_gun(Gun::make_gun(gun_type)); - inventory.set_money(inventory.get_money() - gun_prices.at(gun_type)); - } - - void buy_ammo(const ItemSlot& slot, Inventory& inventory) const { - if (!can_buy_ammo(slot, inventory)) - return; - auto& gun = inventory.get_guns().at(slot); - GunType gun_type = gun->get_type(); - gun->add_mag(); - inventory.set_money(inventory.get_money() - ammo_prices.at(gun_type)); - } - - ~Shop() {} -}; diff --git a/server/shop/shop.cpp b/server/shop/shop.cpp new file mode 100644 index 00000000..6a4f01dd --- /dev/null +++ b/server/shop/shop.cpp @@ -0,0 +1,53 @@ +#include "shop.h" + +#include + +#include "server/items/gun.h" + +#include "shop_prices.h" + +Shop::Shop() { + gun_prices[GunType::AK47] = ShopPrices::ak47; + gun_prices[GunType::M3] = ShopPrices::m3; + gun_prices[GunType::AWP] = ShopPrices::awp; + + ammo_prices[GunType::AK47] = ShopPrices::mag_ak47; + ammo_prices[GunType::M3] = ShopPrices::mag_m3; + ammo_prices[GunType::AWP] = ShopPrices::mag_awp; + ammo_prices[GunType::Glock] = ShopPrices::mag_glock; +} + +std::map Shop::get_gun_prices() const { return gun_prices; } + +std::map Shop::get_ammo_prices() const { return ammo_prices; } + +bool Shop::can_buy_gun(const GunType& gun_type, Inventory& inventory) const { + if (gun_type == GunType::Glock) + return false; + return gun_prices.at(gun_type) <= inventory.get_money(); +} + +bool Shop::can_buy_ammo(const ItemSlot& slot, Inventory& inventory) const { + if (slot != ItemSlot::Primary && slot != ItemSlot::Secondary) + return false; + + auto& gun = inventory.get_guns().at(slot); + GunType gun_type = gun->get_type(); + return ammo_prices.at(gun_type) <= inventory.get_money(); +} + +void Shop::buy_gun(const GunType& gun_type, Inventory& inventory) const { + if (!can_buy_gun(gun_type, inventory)) + return; + inventory.set_gun(Gun::make_gun(gun_type)); + inventory.set_money(inventory.get_money() - gun_prices.at(gun_type)); +} + +void Shop::buy_ammo(const ItemSlot& slot, Inventory& inventory) const { + if (!can_buy_ammo(slot, inventory)) + return; + auto& gun = inventory.get_guns().at(slot); + GunType gun_type = gun->get_type(); + gun->add_mag(); + inventory.set_money(inventory.get_money() - ammo_prices.at(gun_type)); +} diff --git a/server/shop/shop.h b/server/shop/shop.h new file mode 100644 index 00000000..0f0a4329 --- /dev/null +++ b/server/shop/shop.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "common/models.h" +#include "server/player/inventory.h" + +class Shop { +private: + std::map gun_prices; + std::map ammo_prices; + +public: + Shop(); + + Shop(const Shop&) = delete; + Shop& operator=(const Shop&) = delete; + + Shop(Shop&&) = default; + Shop& operator=(Shop&&) = default; + + std::map get_gun_prices() const; + std::map get_ammo_prices() const; + + bool can_buy_gun(const GunType& gun_type, Inventory& inventory) const; + + bool can_buy_ammo(const ItemSlot& slot, Inventory& inventory) const; + + void buy_gun(const GunType& gun_type, Inventory& inventory) const; + + void buy_ammo(const ItemSlot& slot, Inventory& inventory) const; +}; diff --git a/server/shop/shop_prices.h b/server/shop/shop_prices.h new file mode 100644 index 00000000..c3951e91 --- /dev/null +++ b/server/shop/shop_prices.h @@ -0,0 +1,12 @@ +#pragma once + +namespace ShopPrices { +static constexpr int ak47 = 2700; +static constexpr int m3 = 1700; +static constexpr int awp = 4750; + +static constexpr int mag_ak47 = 80; +static constexpr int mag_m3 = 8; +static constexpr int mag_awp = 125; +static constexpr int mag_glock = 20; +} // namespace ShopPrices diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1b4cffcb..b11cd4ce 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(taller_tests # game ../server/game/game.cpp ../server/game/game_phase.cpp + # shop + ../server/shop/shop.cpp # items ../server/items/gun.cpp ../server/items/bomb.cpp @@ -59,10 +61,12 @@ target_sources(taller_tests # testing common/mock_socket.h # game - ../server/game/shop.h ../server/game/game.h ../server/game/game_phase.h ../server/game/game_config.h + # shop + ../server/shop/shop.h + ../server/shop/shop_prices.h # items ../server/items/gun.h ../server/items/bomb.h diff --git a/tests/server/game/test_game.cpp b/tests/server/game/test_game.cpp index 3f3cd327..3b9e9b77 100644 --- a/tests/server/game/test_game.cpp +++ b/tests/server/game/test_game.cpp @@ -12,10 +12,10 @@ #include "server/errors.h" #include "server/game/game.h" #include "server/game/game_config.h" -#include "server/game/shop.h" #include "server/map/map_builder.h" #include "server/player/player_config.h" #include "server/player_message.h" +#include "server/shop/shop.h" #include "mock_clock.h" diff --git a/tests/server/game/test_game_bomb.cpp b/tests/server/game/test_game_bomb.cpp index fdc939fe..be7aa381 100644 --- a/tests/server/game/test_game_bomb.cpp +++ b/tests/server/game/test_game_bomb.cpp @@ -13,10 +13,10 @@ #include "server/errors.h" #include "server/game/game.h" #include "server/game/game_config.h" -#include "server/game/shop.h" #include "server/items/items_config.h" #include "server/map/map_builder.h" #include "server/player_message.h" +#include "server/shop/shop.h" #include "mock_clock.h" diff --git a/tests/server/game/test_shop.cpp b/tests/server/game/test_shop.cpp index de48a953..3bc42fc0 100644 --- a/tests/server/game/test_shop.cpp +++ b/tests/server/game/test_shop.cpp @@ -2,10 +2,11 @@ #include "common/models.h" #include "server/errors.h" -#include "server/game/shop.h" #include "server/items/gun.h" #include "server/player/player.h" #include "server/player/player_config.h" +#include "server/shop/shop.h" +#include "server/shop/shop_prices.h" #include "mock_clock.h" @@ -43,7 +44,7 @@ TEST_F(TestShop, CannotBuyWeaponIfNotEnoughMoney) { Shop shop; GunType gun = GunType::AK47; int initial_money = inventory.get_full_update().get_money(); - int gun_price = PRICE_AK47; + int gun_price = ShopPrices::ak47; while (gun_price <= initial_money) { EXPECT_TRUE(shop.can_buy_gun(gun, inventory)); @@ -69,7 +70,7 @@ TEST_F(TestShop, BuyAmmo) { InventoryUpdate new_update = inventory.get_full_update(); int new_money = new_update.get_money(); - EXPECT_EQ(new_money, old_money - PRICE_MAG_GLOCK); + EXPECT_EQ(new_money, old_money - ShopPrices::mag_glock); GunUpdate new_glock = new_update.get_guns().at(ItemSlot::Secondary); EXPECT_EQ(new_glock.get_mag_ammo(), old_glock.get_mag_ammo()); diff --git a/tests/server/player/test_player.cpp b/tests/server/player/test_player.cpp index 0602c8b1..41c9f37f 100644 --- a/tests/server/player/test_player.cpp +++ b/tests/server/player/test_player.cpp @@ -6,17 +6,11 @@ #include "../game/mock_clock.h" #include "common/models.h" #include "server/errors.h" -#include "server/game/shop.h" #include "server/items/gun.h" #include "server/physics/circular_hitbox.h" #include "server/player/player.h" #include "server/player/player_config.h" - -// Include shop price constants -#define PRICE_AK47 2700 -#define PRICE_M3 1700 -#define PRICE_AWP 4750 -#define PRICE_MAG_GLOCK 20 +#include "server/shop/shop.h" class TestPlayer: public ::testing::Test { protected: From bed391b42bf22fa29d2601cf3bc15ecda2a5f198 Mon Sep 17 00:00:00 2001 From: Jesabel Pugliese Date: Tue, 24 Jun 2025 05:42:50 -0300 Subject: [PATCH 3/6] feat(game): import game configuration from YAML --- server/CMakeLists.txt | 3 - server/config.yaml | 100 +++++++++++ server/game/game.cpp | 25 +-- server/game/game.h | 3 +- server/game/game_config.h | 239 +++++++++++++++++++++++--- server/game/game_phase.cpp | 11 +- server/game/game_phase.h | 5 +- server/game_thread.cpp | 7 +- server/items/bomb.cpp | 17 +- server/items/bomb.h | 4 +- server/items/gun.cpp | 17 +- server/items/gun.h | 8 +- server/items/items_config.h | 89 ---------- server/items/knife.cpp | 13 +- server/items/knife.h | 5 +- server/player/inventory.cpp | 9 +- server/player/inventory.h | 8 +- server/player/player.cpp | 12 +- server/player/player.h | 5 +- server/player/player_config.h | 9 - server/shop/shop.cpp | 25 ++- server/shop/shop.h | 6 +- server/shop/shop_prices.h | 12 -- server/states/game_state.cpp | 18 +- server/states/game_state.h | 4 +- server/states/inventory_state.cpp | 5 +- server/states/inventory_state.h | 2 +- server/states/player_state.cpp | 15 +- server/states/player_state.h | 7 +- tests/CMakeLists.txt | 3 - tests/server/game/test_game.cpp | 94 +++++----- tests/server/game/test_game_bomb.cpp | 42 +++-- tests/server/game/test_game_phase.cpp | 16 +- tests/server/game/test_shop.cpp | 24 +-- tests/server/player/test_player.cpp | 26 +-- 35 files changed, 556 insertions(+), 332 deletions(-) create mode 100644 server/config.yaml delete mode 100644 server/items/items_config.h delete mode 100644 server/player/player_config.h delete mode 100644 server/shop/shop_prices.h diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 4e768461..68472990 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -60,7 +60,6 @@ target_sources(taller_server game/game_config.h # shop shop/shop.h - shop/shop_prices.h # items items/gun.h items/bomb.h @@ -68,7 +67,6 @@ target_sources(taller_server items/weapon.h items/effects/effect.h items/effects/attack_effect.h - items/items_config.h # physics physics/physics_system.h physics/target_type.h @@ -79,7 +77,6 @@ target_sources(taller_server map/map_builder.h # player player/player.h - player/player_config.h player/inventory.h player/statuses/player_status.h player/statuses/idle_status.h diff --git a/server/config.yaml b/server/config.yaml new file mode 100644 index 00000000..41acb491 --- /dev/null +++ b/server/config.yaml @@ -0,0 +1,100 @@ +GameConfig: + max_rounds: 10 + Scores: + kill: 1 + win: 5 + loss: 0 + Bonifications: + kill: 300 + win: 3000 + loss: 1500 + +PhaseTimes: + buying_duration: 30 + round_duration: 120 + round_end_duration: 5 + +Player: + speed: 9 + full_health: 100 + initial_money: 800 + +ShopPrices: + Guns: + Ak47: 2700 + M3: 1700 + Awp: 4750 + Mag: + Ak47: 80 + M3: 8 + Awp: 125 + Glock: 20 + +ItemsConfig: + Glock: + bullets_per_mag: 20 + init_mag_ammo: 20 + init_reserve_ammo: 20 + attack_rate: 6.6 + dir_variation_angle: 0 + bullets_per_attack: 1 + burst_interval: 0 + min_damage: 40 + max_damage: 50 + max_range: 10 + precision: 0.85 + falloff: 0.5 + Ak47: + bullets_per_mag: 30 + init_mag_ammo: 30 + init_reserve_ammo: 30 + attack_rate: 10 + dir_variation_angle: 0 + bullets_per_attack: 3 + burst_interval: 0.4 + min_damage: 30 + max_damage: 40 + max_range: 20 + precision: 0.7 + falloff: 0.3 + M3: + bullets_per_mag: 8 + init_mag_ammo: 8 + init_reserve_ammo: 8 + attack_rate: 1.1 + dir_variation_angle: 30 + bullets_per_attack: 8 + burst_interval: 0 + min_damage: 8 + max_damage: 12 + max_range: 5 + precision: 0.3 + falloff: 0 + Awp: + bullets_per_mag: 10 + init_mag_ammo: 10 + init_reserve_ammo: 10 + attack_rate: 0.68 + dir_variation_angle: 0 + bullets_per_attack: 1 + burst_interval: 0 + min_damage: 100 + max_damage: 100 + max_range: 100 + precision: 1 + falloff: 0 + Knife: + min_damage: 10 + max_damage: 20 + attack_rate: 5.0 + max_range: 1 + precision: 1 + falloff: 0 + Bomb: + secs_to_plant: 3 + secs_to_explode: 40 + secs_to_defuse: 5 + damage: 100 + max_range: 15 + precision: 1 + falloff: 0.5 diff --git a/server/game/game.cpp b/server/game/game.cpp index c504e7ad..8866a892 100644 --- a/server/game/game.cpp +++ b/server/game/game.cpp @@ -12,9 +12,12 @@ #include "game_config.h" -Game::Game(const std::string& name, std::shared_ptr&& game_clock, Map&& map): - Logic(GameState(std::move(game_clock), map.get_max_players())), +Game::Game(const std::string& name, std::shared_ptr&& game_clock, Map&& map, + GameConfig&& config): + Logic( + GameState(std::move(game_clock), map.get_max_players(), std::move(config))), name(name), + shop(state.get_config().shop_prices), physics_system(std::move(map), state.get_players(), state.get_dropped_guns(), state.get_bomb()) {} @@ -67,7 +70,7 @@ void Game::advance_round_logic() { } } - if (!phase.is_game_end() && state.get_num_rounds() == GameConfig::max_rounds) { + if (!phase.is_game_end() && state.get_num_rounds() == state.get_config().max_rounds) { phase.end_game(); broadcast(Message(ScoreboardResponse(state.get_scoreboard()))); } @@ -155,7 +158,8 @@ bool Game::apply_attack_effect(const std::unique_ptr& attacker, const Ef bool is_hit = effect.apply(target_player); if (target_player->is_dead()) { attacker->add_kill(); - attacker->add_rewards(Scores::kill, Bonifications::kill); + attacker->add_rewards(state.get_config().scores.kill, + state.get_config().bonifications.kill); auto gun = target_player->drop_primary_weapon(); if (gun.has_value()) state.add_dropped_gun(std::move(gun.value()), target_player->get_hitbox().center); @@ -231,7 +235,7 @@ void Game::handle(const std::string& player_name, state.get_player(player_name)->set_ready(); if (state.all_players_ready()) { - give_bomb_to_random_tt(Bomb()); + give_bomb_to_random_tt(Bomb(state.get_config().items_config.bomb)); state.get_phase().start_game(); for (const auto& [_, player]: state.get_players()) // cppcheck-suppress[unusedVariable] move_player_to_spawn(player); @@ -257,7 +261,8 @@ void Game::handle(const std::string& player_name, const BuyGunCom auto gun = player->drop_primary_weapon(); if (gun.has_value()) state.add_dropped_gun(std::move(gun.value()), player->get_hitbox().center); - shop.buy_gun(msg.get_gun(), player->get_inventory()); + shop.buy_gun(msg.get_gun(), player->get_inventory(), + state.get_config().items_config.get_gun_config(msg.get_gun())); } template <> @@ -406,12 +411,12 @@ void Game::handle_msg(const Message& msg, const std::string& player_name) { float Game::get_tick_duration() { TimePoint now = state.get_phase().get_time_now(); if (last_tick == TimePoint()) { - return 1.0f / GameConfig::tickrate; + return 1.0f / TICKRATE; } else { if (now < last_tick) last_tick = now; if (last_tick == now) { - return 1.0f / GameConfig::tickrate; + return 1.0f / TICKRATE; } else { float elapsed = std::chrono::duration(now - last_tick).count(); return elapsed; @@ -444,7 +449,7 @@ void Game::prepare_new_round() { if (bomb.has_value()) state.add_bomb(std::move(bomb.value()), player->get_hitbox().center); } - if (state.get_num_rounds() == GameConfig::max_rounds / 2) { + if (state.get_num_rounds() == state.get_config().max_rounds / 2) { state.swap_players_teams(); broadcast(Message(SwapTeamsResponse())); } @@ -453,7 +458,7 @@ void Game::prepare_new_round() { state.get_bomb().value().item.reset(); give_bomb_to_random_tt(std::move(state.remove_bomb())); } else { - give_bomb_to_random_tt(Bomb()); + give_bomb_to_random_tt(Bomb(state.get_config().items_config.bomb)); } state.get_dropped_guns().clear(); } diff --git a/server/game/game.h b/server/game/game.h index d4ebeb67..eac3fe93 100644 --- a/server/game/game.h +++ b/server/game/game.h @@ -29,7 +29,8 @@ class Game: public Logic { std::vector output_messages; public: - Game(const std::string& name, std::shared_ptr&& game_clock, Map&& map); + Game(const std::string& name, std::shared_ptr&& game_clock, Map&& map, + GameConfig&& config); Game(const Game&) = delete; Game& operator=(const Game&) = delete; diff --git a/server/game/game_config.h b/server/game/game_config.h index f12fb8e9..780bfd76 100644 --- a/server/game/game_config.h +++ b/server/game/game_config.h @@ -1,24 +1,219 @@ #pragma once -namespace GameConfig { -static constexpr int tickrate = 30; -static constexpr int max_rounds = 10; -}; // namespace GameConfig - -namespace PhaseTimes { -static constexpr unsigned int buying_duration = 30; -static constexpr unsigned int round_duration = 120; -static constexpr unsigned int round_end_duration = 5; -}; // namespace PhaseTimes - -namespace Scores { -static constexpr int kill = 1; -static constexpr int win = 5; -static constexpr int loss = 0; -}; // namespace Scores - -namespace Bonifications { -static constexpr int kill = 300; -static constexpr int win = 3000; -static constexpr int loss = 1500; -} // namespace Bonifications +#include + +#include + +#include "common/models.h" +#include "common/physics/physics_config.h" + +#define TICKRATE 30 + +struct GameConfig { + int max_rounds; + + struct Scores { + int kill; + int win; + int loss; + + Scores load(const YAML::Node& scores_node) { + Scores scores_config; + scores_config.kill = scores_node["kill"].as(); + scores_config.win = scores_node["win"].as(); + scores_config.loss = scores_node["loss"].as(); + return scores_config; + } + } scores; + + struct Bonifications { + int kill; + int win; + int loss; + + Bonifications load(const YAML::Node& bonif_node) { + Bonifications bonif_config; + bonif_config.kill = bonif_node["kill"].as(); + bonif_config.win = bonif_node["win"].as(); + bonif_config.loss = bonif_node["loss"].as(); + return bonif_config; + } + } bonifications; + + struct PhaseTimes { + unsigned int buying_duration; + unsigned int round_duration; + unsigned int round_end_duration; + + PhaseTimes load(const YAML::Node& phase_times_node) { + PhaseTimes phase_times_config; + phase_times_config.buying_duration = + phase_times_node["buying_duration"].as(); + phase_times_config.round_duration = + phase_times_node["round_duration"].as(); + phase_times_config.round_end_duration = + phase_times_node["round_end_duration"].as(); + return phase_times_config; + } + } phase_times; + + struct PlayerConfig { + int speed; + int full_health; + int initial_money; + + PlayerConfig load(const YAML::Node& player_config_node) { + PlayerConfig player_conf; + player_conf.speed = player_config_node["speed"].as(); + player_conf.full_health = player_config_node["full_health"].as(); + player_conf.initial_money = player_config_node["initial_money"].as(); + return player_conf; + } + } player_config; + + struct ShopPrices { + int ak47; + int m3; + int awp; + int mag_ak47; + int mag_m3; + int mag_awp; + int mag_glock; + + ShopPrices load(const YAML::Node& shop_prices_node) { + ShopPrices shop_prices_config; + shop_prices_config.ak47 = shop_prices_node["Guns"]["Ak47"].as(); + shop_prices_config.m3 = shop_prices_node["Guns"]["M3"].as(); + shop_prices_config.awp = shop_prices_node["Guns"]["Awp"].as(); + shop_prices_config.mag_ak47 = shop_prices_node["Mag"]["Ak47"].as(); + shop_prices_config.mag_m3 = shop_prices_node["Mag"]["M3"].as(); + shop_prices_config.mag_awp = shop_prices_node["Mag"]["Awp"].as(); + shop_prices_config.mag_glock = shop_prices_node["Mag"]["Glock"].as(); + return shop_prices_config; + } + } shop_prices; + + struct ItemsConfig { + struct GunConfig { + int bullets_per_mag; + int init_mag_ammo; + int init_reserve_ammo; + float attack_rate; + int dir_variation_angle; + int bullets_per_attack; + float burst_interval; + int min_damage; + int max_damage; + int max_range; + float precision; + float falloff; + + GunConfig load(const YAML::Node& gun_node) { + GunConfig gun_config; + gun_config.bullets_per_mag = gun_node["bullets_per_mag"].as(); + gun_config.init_mag_ammo = gun_node["init_mag_ammo"].as(); + gun_config.init_reserve_ammo = gun_node["init_reserve_ammo"].as(); + gun_config.attack_rate = gun_node["attack_rate"].as(); + gun_config.dir_variation_angle = gun_node["dir_variation_angle"].as(); + gun_config.bullets_per_attack = gun_node["bullets_per_attack"].as(); + gun_config.burst_interval = gun_node["burst_interval"].as(); + gun_config.min_damage = gun_node["min_damage"].as(); + gun_config.max_damage = gun_node["max_damage"].as(); + gun_config.max_range = gun_node["max_range"].as() * PhysicsConfig::meter_size; + gun_config.precision = gun_node["precision"].as(); + gun_config.falloff = gun_node["falloff"].as(); + return gun_config; + } + }; + + GunConfig glock; + GunConfig ak47; + GunConfig m3; + GunConfig awp; + + struct KnifeConfig { + int min_damage; + int max_damage; + float attack_rate; + int max_range; + float precision; + float falloff; + + KnifeConfig load(const YAML::Node& knife_node) { + KnifeConfig knife_config; + knife_config.min_damage = knife_node["min_damage"].as(); + knife_config.max_damage = knife_node["max_damage"].as(); + knife_config.attack_rate = knife_node["attack_rate"].as(); + knife_config.max_range = + knife_node["max_range"].as() * PhysicsConfig::meter_size; + knife_config.precision = knife_node["precision"].as(); + knife_config.falloff = knife_node["falloff"].as(); + return knife_config; + } + } knife; + + struct BombConfig { + int secs_to_plant; + int secs_to_explode; + int secs_to_defuse; + int damage; + int max_range; + float precision; + float falloff; + + BombConfig load(const YAML::Node& bomb_node) { + BombConfig bomb_config; + bomb_config.secs_to_plant = bomb_node["secs_to_plant"].as(); + bomb_config.secs_to_explode = bomb_node["secs_to_explode"].as(); + bomb_config.secs_to_defuse = bomb_node["secs_to_defuse"].as(); + bomb_config.damage = bomb_node["damage"].as(); + bomb_config.max_range = + bomb_node["max_range"].as() * PhysicsConfig::meter_size; + bomb_config.precision = bomb_node["precision"].as(); + bomb_config.falloff = bomb_node["falloff"].as(); + return bomb_config; + } + } bomb; + + ItemsConfig load(const YAML::Node& items_config_node) { + ItemsConfig items_conf; + items_conf.glock = glock.load(items_config_node["Glock"]); + items_conf.ak47 = ak47.load(items_config_node["Ak47"]); + items_conf.m3 = m3.load(items_config_node["M3"]); + items_conf.awp = awp.load(items_config_node["Awp"]); + items_conf.knife = knife.load(items_config_node["Knife"]); + items_conf.bomb = bomb.load(items_config_node["Bomb"]); + return items_conf; + } + + GunConfig get_gun_config(GunType gun_type) const { + switch (gun_type) { + case GunType::AK47: + return ak47; + case GunType::M3: + return m3; + case GunType::AWP: + return awp; + case GunType::Glock: + return glock; + default: + throw std::runtime_error("Unknown gun type"); + } + } + + } items_config; + + static GameConfig load_config(const std::string& config_file) { + YAML::Node config = YAML::LoadFile(config_file); + GameConfig game_config; + game_config.max_rounds = config["GameConfig"]["max_rounds"].as(); + game_config.scores = game_config.scores.load(config["GameConfig"]["Scores"]); + game_config.bonifications = + game_config.bonifications.load(config["GameConfig"]["Bonifications"]); + game_config.phase_times = game_config.phase_times.load(config["PhaseTimes"]); + game_config.player_config = game_config.player_config.load(config["Player"]); + game_config.shop_prices = game_config.shop_prices.load(config["ShopPrices"]); + game_config.items_config = game_config.items_config.load(config["ItemsConfig"]); + return game_config; + } +}; diff --git a/server/game/game_phase.cpp b/server/game/game_phase.cpp index 6b211665..a91ddeeb 100644 --- a/server/game/game_phase.cpp +++ b/server/game/game_phase.cpp @@ -3,15 +3,14 @@ #include #include -#include "game_config.h" - -GamePhase::GamePhase(std::shared_ptr&& game_clock): +GamePhase::GamePhase(std::shared_ptr&& game_clock, + const GameConfig::PhaseTimes& phase_times): Logic(PhaseState(PhaseType::WarmUp)), game_clock(std::move(game_clock)), phase_durations({{PhaseType::WarmUp, 0}, - {PhaseType::Buying, PhaseTimes::buying_duration}, - {PhaseType::InRound, PhaseTimes::round_duration}, - {PhaseType::RoundEnd, PhaseTimes::round_end_duration}, + {PhaseType::Buying, phase_times.buying_duration}, + {PhaseType::InRound, phase_times.round_duration}, + {PhaseType::RoundEnd, phase_times.round_end_duration}, {PhaseType::GameEnd, 0}}), next_phase_map({{PhaseType::WarmUp, PhaseType::Buying}, {PhaseType::Buying, PhaseType::InRound}, diff --git a/server/game/game_phase.h b/server/game/game_phase.h index 2de66002..c662a08b 100644 --- a/server/game/game_phase.h +++ b/server/game/game_phase.h @@ -8,6 +8,8 @@ #include "server/logic.h" #include "server/states/phase_state.h" +#include "game_config.h" + class GamePhase: public Logic { private: std::shared_ptr game_clock; @@ -16,7 +18,8 @@ class GamePhase: public Logic { std::map next_phase_map; public: - explicit GamePhase(std::shared_ptr&& game_clock); + explicit GamePhase(std::shared_ptr&& game_clock, + const GameConfig::PhaseTimes& phase_times); GamePhase(const GamePhase&) = delete; GamePhase& operator=(const GamePhase&) = delete; diff --git a/server/game_thread.cpp b/server/game_thread.cpp index 28c5c35d..369d422a 100644 --- a/server/game_thread.cpp +++ b/server/game_thread.cpp @@ -9,12 +9,15 @@ #include "server/game/game_config.h" #include "server/player_message.h" +#define CONFIG_FILE "./server/config.yaml" + GameThread::GameThread(const std::string& name, Map&& map): - game(name, std::make_unique(), std::move(map)), + game(name, std::make_unique(), std::move(map), + GameConfig::load_config(CONFIG_FILE)), input_queue(std::make_shared>()) {} void GameThread::run() { - RateController rate_controller(GameConfig::tickrate); + RateController rate_controller(TICKRATE); rate_controller.run_at_rate([this]() { std::vector msgs; for (int i = 0; i < MSG_BATCH_SIZE; ++i) { diff --git a/server/items/bomb.cpp b/server/items/bomb.cpp index f6360995..8794931f 100644 --- a/server/items/bomb.cpp +++ b/server/items/bomb.cpp @@ -2,11 +2,10 @@ #include -#include "items_config.h" - -Bomb::Bomb(): +Bomb::Bomb(const GameConfig::ItemsConfig::BombConfig& bomb_config): Logic( - BombState(BombConfig::secs_to_explode, BombPhaseType::NotPlanted)) {} + BombState(bomb_config.secs_to_explode, BombPhaseType::NotPlanted)), + bomb_config(bomb_config) {} void Bomb::change_bomb_phase(BombPhaseType new_phase, TimePoint now) { if (state.get_bomb_phase() == new_phase) @@ -56,13 +55,13 @@ void Bomb::stop_defusing(TimePoint now) { 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(bomb_config.secs_to_plant)) change_bomb_phase(BombPhaseType::Planted, now); return; } if (is_defusing()) { - if (now - phase_start_time >= std::chrono::seconds(BombConfig::secs_to_defuse)) + if (now - phase_start_time >= std::chrono::seconds(bomb_config.secs_to_defuse)) change_bomb_phase(BombPhaseType::Defused, now); } @@ -76,11 +75,11 @@ void Bomb::advance(TimePoint now) { Effect Bomb::explode(const Vector2D& origin) { state.set_bomb_phase(BombPhaseType::Exploded); - return Effect(origin, BombConfig::damage, BombConfig::max_range, BombConfig::precision, - BombConfig::falloff); + return Effect(origin, bomb_config.damage, bomb_config.max_range, bomb_config.precision, + bomb_config.falloff); } void Bomb::reset() { change_bomb_phase(BombPhaseType::NotPlanted, TimePoint::min()); - state.set_secs_to_explode(BombConfig::secs_to_explode); + state.set_secs_to_explode(bomb_config.secs_to_explode); } diff --git a/server/items/bomb.h b/server/items/bomb.h index 67529e20..6ba21ab9 100644 --- a/server/items/bomb.h +++ b/server/items/bomb.h @@ -2,16 +2,18 @@ #include "effects/effect.h" #include "server/clock/clock.h" +#include "server/game/game_config.h" #include "server/logic.h" #include "server/states/bomb_state.h" class Bomb: public Logic { + GameConfig::ItemsConfig::BombConfig bomb_config; TimePoint phase_start_time; void change_bomb_phase(BombPhaseType new_phase, TimePoint now); public: - Bomb(); + explicit Bomb(const GameConfig::ItemsConfig::BombConfig& bomb_config); Bomb(const Bomb&) = delete; Bomb& operator=(const Bomb&) = delete; diff --git a/server/items/gun.cpp b/server/items/gun.cpp index aedd5fac..6665f809 100644 --- a/server/items/gun.cpp +++ b/server/items/gun.cpp @@ -5,26 +5,11 @@ #include "common/utils/random_float_generator.h" -Gun::Gun(GunType gun, GunConfig gun_config): +Gun::Gun(GunType gun, const GameConfig::ItemsConfig::GunConfig& gun_config): Logic( GunState(gun, gun_config.init_mag_ammo, gun_config.init_reserve_ammo)), gun_config(gun_config) {} -std::unique_ptr Gun::make_gun(const GunType& gun_type) { - switch (gun_type) { - case GunType::Glock: - return std::make_unique(GunType::Glock, GlockConfig); - case GunType::AK47: - return std::make_unique(GunType::AK47, Ak47Config); - case GunType::AWP: - return std::make_unique(GunType::AWP, AwpConfig); - case GunType::M3: - return std::make_unique(GunType::M3, M3Config); - default: - throw std::invalid_argument("Unknown gun type"); - } -} - bool Gun::is_attacking() const { return state.get_is_attacking(); } bool Gun::has_ammo() { return state.get_mag_ammo() > 0; } diff --git a/server/items/gun.h b/server/items/gun.h index 53e8cfec..0e35aaf4 100644 --- a/server/items/gun.h +++ b/server/items/gun.h @@ -7,14 +7,14 @@ #include "common/utils/vector_2d.h" #include "effects/attack_effect.h" #include "server/clock/clock.h" +#include "server/game/game_config.h" #include "server/logic.h" #include "server/states/gun_state.h" -#include "items_config.h" #include "weapon.h" class Gun: public Logic, public Weapon { - GunConfig gun_config; + GameConfig::ItemsConfig::GunConfig gun_config; int burst_bullets_fired = 0; int get_bullets_ready_to_fire(TimePoint now); @@ -23,9 +23,7 @@ class Gun: public Logic, public Weapon { void decrease_mag_ammo(); public: - Gun(GunType gun, GunConfig initial_config); - - static std::unique_ptr make_gun(const GunType& gun_type); + Gun(GunType gun, const GameConfig::ItemsConfig::GunConfig& initial_config); bool is_attacking() const; bool has_ammo(); diff --git a/server/items/items_config.h b/server/items/items_config.h deleted file mode 100644 index 3e2b4e17..00000000 --- a/server/items/items_config.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include "common/physics/physics_config.h" - -struct GunConfig { - int bullets_per_mag; - int init_mag_ammo; - int init_reserve_ammo; - float attack_rate; - float dir_variation_angle; - int bullets_per_attack; - float burst_interval; - int min_damage; - int max_damage; - int max_range; - float precision; - float falloff; -}; - -constexpr GunConfig GlockConfig = {.bullets_per_mag = 20, - .init_mag_ammo = GlockConfig.bullets_per_mag, - .init_reserve_ammo = GlockConfig.bullets_per_mag, - .attack_rate = 6.6, - .dir_variation_angle = 0, - .bullets_per_attack = 1, - .burst_interval = 0, - .min_damage = 40, - .max_damage = 50, - .max_range = 10 * PhysicsConfig::meter_size, - .precision = 0.85f, - .falloff = 0.5f}; - -constexpr GunConfig Ak47Config = {.bullets_per_mag = 30, - .init_mag_ammo = Ak47Config.bullets_per_mag, - .init_reserve_ammo = Ak47Config.bullets_per_mag, - .attack_rate = 10, - .dir_variation_angle = 0, - .bullets_per_attack = 3, - .burst_interval = 0.4f, - .min_damage = 30, - .max_damage = 40, - .max_range = 20 * PhysicsConfig::meter_size, - .precision = 0.70f, - .falloff = 0.3f}; - -constexpr GunConfig M3Config = {.bullets_per_mag = 8, - .init_mag_ammo = M3Config.bullets_per_mag, - .init_reserve_ammo = M3Config.bullets_per_mag, - .attack_rate = 1.1, - .dir_variation_angle = 30.0f, - .bullets_per_attack = M3Config.bullets_per_mag, - .burst_interval = 0, - .min_damage = 8, - .max_damage = 12, - .max_range = 5 * PhysicsConfig::meter_size, - .precision = 0.30f, - .falloff = 0}; - -constexpr GunConfig AwpConfig = {.bullets_per_mag = 10, - .init_mag_ammo = AwpConfig.bullets_per_mag, - .init_reserve_ammo = AwpConfig.bullets_per_mag, - .attack_rate = 0.68, - .dir_variation_angle = 0, - .bullets_per_attack = 1, - .burst_interval = 0, - .min_damage = 100, - .max_damage = 100, - .max_range = 100 * PhysicsConfig::meter_size, - .precision = 1.0f, - .falloff = 0}; - -namespace KnifeConfig { -static constexpr int min_damage = 10; -static constexpr int max_damage = 20; -static constexpr float attack_rate = 5.0; -static constexpr int max_range = 1 * PhysicsConfig::meter_size; -static constexpr float precision = 1.0f; -static constexpr float falloff = 0; -}; // namespace KnifeConfig - -namespace BombConfig { -static constexpr unsigned int secs_to_plant = 3; -static constexpr unsigned int secs_to_explode = 40; -static constexpr unsigned int secs_to_defuse = 5; -static constexpr int damage = 100; -static constexpr int max_range = 15 * PhysicsConfig::meter_size; -static constexpr float precision = 1.0f; -static constexpr float falloff = 0.5f; -}; // namespace BombConfig diff --git a/server/items/knife.cpp b/server/items/knife.cpp index 28bd7780..b5be609c 100644 --- a/server/items/knife.cpp +++ b/server/items/knife.cpp @@ -2,14 +2,13 @@ #include -#include "items_config.h" - -Knife::Knife(): Logic(KnifeState()) {} +Knife::Knife(const GameConfig::ItemsConfig::KnifeConfig& knife_config): + Logic(KnifeState()), knife_config(knife_config) {} bool Knife::is_attacking() const { return state.get_is_attacking(); } void Knife::start_attacking(TimePoint now) { - if (!can_attack(KnifeConfig::attack_rate, now)) + if (!can_attack(knife_config.attack_rate, now)) return; state.set_is_attacking(true); } @@ -19,10 +18,10 @@ std::vector Knife::attack(const Vector2D& origin, const Vector2D& std::vector effects; if (!is_attacking()) return effects; - int damage = get_random_damage(KnifeConfig::min_damage, KnifeConfig::max_damage); + int damage = get_random_damage(knife_config.min_damage, knife_config.max_damage); - Effect effect(origin, damage, KnifeConfig::max_range, KnifeConfig::precision, - KnifeConfig::falloff); + Effect effect(origin, damage, knife_config.max_range, knife_config.precision, + knife_config.falloff); effects.push_back(AttackEffect{std::move(effect), dir}); state.set_is_attacking(false); diff --git a/server/items/knife.h b/server/items/knife.h index 490e9211..434d6491 100644 --- a/server/items/knife.h +++ b/server/items/knife.h @@ -4,14 +4,17 @@ #include "common/utils/vector_2d.h" #include "effects/attack_effect.h" +#include "server/game/game_config.h" #include "server/logic.h" #include "server/states/knife_state.h" #include "weapon.h" class Knife: public Logic, public Weapon { + GameConfig::ItemsConfig::KnifeConfig knife_config; + public: - Knife(); + explicit Knife(const GameConfig::ItemsConfig::KnifeConfig& knife_config); bool is_attacking() const; diff --git a/server/player/inventory.cpp b/server/player/inventory.cpp index e6192fed..19debe6b 100644 --- a/server/player/inventory.cpp +++ b/server/player/inventory.cpp @@ -6,9 +6,10 @@ #include "common/models.h" #include "server/items/knife.h" -Inventory::Inventory(): - Logic(InventoryState(PlayerConfig::initial_money)) { - state.set_gun(ItemSlot::Secondary, Gun::make_gun(GunType::Glock)); +Inventory::Inventory(int initial_money, const GameConfig::ItemsConfig& items_config): + Logic(InventoryState(initial_money, items_config.knife)), + items_config(items_config) { + state.set_gun(ItemSlot::Secondary, std::make_unique(GunType::Glock, items_config.glock)); } bool Inventory::has_item_in_slot(ItemSlot slot) { @@ -34,6 +35,8 @@ Knife& Inventory::get_knife() { return state.get_knife(); } std::optional& Inventory::get_bomb() { return state.get_bomb(); } +void Inventory::set_money(int new_money) { state.set_money(new_money); } + void Inventory::set_gun(std::unique_ptr&& gun) { if (gun->get_type() == GunType::Glock) { state.set_gun(ItemSlot::Secondary, std::move(gun)); diff --git a/server/player/inventory.h b/server/player/inventory.h index 1240f82a..47a7ff9f 100644 --- a/server/player/inventory.h +++ b/server/player/inventory.h @@ -6,15 +6,17 @@ #include "common/models.h" #include "common/updates/inventory_update.h" +#include "server/game/game_config.h" #include "server/items/gun.h" #include "server/items/knife.h" #include "server/logic.h" -#include "server/player/player_config.h" #include "server/states/inventory_state.h" class Inventory: public Logic { + GameConfig::ItemsConfig items_config; + public: - Inventory(); + Inventory(int initial_money, const GameConfig::ItemsConfig& items_config); Inventory(const Inventory&) = delete; Inventory& operator=(const Inventory&) = delete; @@ -29,7 +31,7 @@ class Inventory: public Logic { Knife& get_knife(); std::optional& get_bomb(); - void set_money(int new_money) { state.set_money(new_money); } + void set_money(int new_money); void set_gun(std::unique_ptr&& gun); std::unique_ptr remove_primary_weapon(); diff --git a/server/player/player.cpp b/server/player/player.cpp index 593893fa..fa588a10 100644 --- a/server/player/player.cpp +++ b/server/player/player.cpp @@ -6,12 +6,12 @@ #include "server/errors.h" #include "statuses/idle_status.h" -#include "player_config.h" - -Player::Player(Team team, CharacterType character_type, Circle hitbox): +Player::Player(Team team, CharacterType character_type, Circle hitbox, + const GameConfig::PlayerConfig& player_config, + const GameConfig::ItemsConfig& items_config): Logic(PlayerState( - team, character_type, hitbox, Vector2D(0.0f, 0.0f), Vector2D(0.0f, 0.0f), - PlayerConfig::speed, false, PlayerConfig::full_health, ItemSlot::Secondary)), + team, character_type, hitbox, Vector2D(0.0f, 0.0f), Vector2D(0.0f, 0.0f), false, + ItemSlot::Secondary, player_config, items_config)), scoreboard_entry(state.get_inventory().get_money(), 0, 0, 0), status(std::make_unique()) {} @@ -201,7 +201,7 @@ void Player::handle_stop_defusing(Bomb& bomb, TimePoint now) { void Player::reset() { status = std::make_unique(); state.set_velocity(Vector2D(0.0f, 0.0f)); - state.set_health(PlayerConfig::full_health); + state.set_health(state.get_player_config().full_health); state.set_equipped_item(ItemSlot::Melee); state.get_inventory().get_knife().reset(); for (auto& [_, gun]: state.get_inventory().get_guns()) gun->reset(); diff --git a/server/player/player.h b/server/player/player.h index ff603e4c..e991b641 100644 --- a/server/player/player.h +++ b/server/player/player.h @@ -11,6 +11,7 @@ #include "common/updates/player_update.h" #include "common/utils/vector_2d.h" #include "server/clock/clock.h" +#include "server/game/game_config.h" #include "server/items/effects/attack_effect.h" #include "server/logic.h" #include "server/states/player_state.h" @@ -24,7 +25,9 @@ class Player: public Logic { std::unique_ptr status; public: - Player(Team team, CharacterType character_type, Circle hitbox); + Player(Team team, CharacterType character_type, Circle hitbox, + const GameConfig::PlayerConfig& player_config, + const GameConfig::ItemsConfig& items_config); Player(const Player&) = delete; Player& operator=(const Player&) = delete; diff --git a/server/player/player_config.h b/server/player/player_config.h deleted file mode 100644 index c48ba738..00000000 --- a/server/player/player_config.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "common/physics/physics_config.h" - -namespace PlayerConfig { -static constexpr int speed = 4.5; // m/s -static constexpr int full_health = 100; -static constexpr int initial_money = 800; -}; // namespace PlayerConfig diff --git a/server/shop/shop.cpp b/server/shop/shop.cpp index 6a4f01dd..a4bc59ea 100644 --- a/server/shop/shop.cpp +++ b/server/shop/shop.cpp @@ -4,17 +4,15 @@ #include "server/items/gun.h" -#include "shop_prices.h" - -Shop::Shop() { - gun_prices[GunType::AK47] = ShopPrices::ak47; - gun_prices[GunType::M3] = ShopPrices::m3; - gun_prices[GunType::AWP] = ShopPrices::awp; - - ammo_prices[GunType::AK47] = ShopPrices::mag_ak47; - ammo_prices[GunType::M3] = ShopPrices::mag_m3; - ammo_prices[GunType::AWP] = ShopPrices::mag_awp; - ammo_prices[GunType::Glock] = ShopPrices::mag_glock; +Shop::Shop(const GameConfig::ShopPrices& prices) { + gun_prices[GunType::AK47] = prices.ak47; + gun_prices[GunType::M3] = prices.m3; + gun_prices[GunType::AWP] = prices.awp; + + ammo_prices[GunType::AK47] = prices.mag_ak47; + ammo_prices[GunType::M3] = prices.mag_m3; + ammo_prices[GunType::AWP] = prices.mag_awp; + ammo_prices[GunType::Glock] = prices.mag_glock; } std::map Shop::get_gun_prices() const { return gun_prices; } @@ -36,10 +34,11 @@ bool Shop::can_buy_ammo(const ItemSlot& slot, Inventory& inventory) const { return ammo_prices.at(gun_type) <= inventory.get_money(); } -void Shop::buy_gun(const GunType& gun_type, Inventory& inventory) const { +void Shop::buy_gun(const GunType& gun_type, Inventory& inventory, + const GameConfig::ItemsConfig::GunConfig& gun_config) const { if (!can_buy_gun(gun_type, inventory)) return; - inventory.set_gun(Gun::make_gun(gun_type)); + inventory.set_gun(std::make_unique(gun_type, gun_config)); inventory.set_money(inventory.get_money() - gun_prices.at(gun_type)); } diff --git a/server/shop/shop.h b/server/shop/shop.h index 0f0a4329..59fb8e70 100644 --- a/server/shop/shop.h +++ b/server/shop/shop.h @@ -3,6 +3,7 @@ #include #include "common/models.h" +#include "server/game/game_config.h" #include "server/player/inventory.h" class Shop { @@ -11,7 +12,7 @@ class Shop { std::map ammo_prices; public: - Shop(); + explicit Shop(const GameConfig::ShopPrices& prices); Shop(const Shop&) = delete; Shop& operator=(const Shop&) = delete; @@ -26,7 +27,8 @@ class Shop { bool can_buy_ammo(const ItemSlot& slot, Inventory& inventory) const; - void buy_gun(const GunType& gun_type, Inventory& inventory) const; + void buy_gun(const GunType& gun_type, Inventory& inventory, + const GameConfig::ItemsConfig::GunConfig& gun_config) const; void buy_ammo(const ItemSlot& slot, Inventory& inventory) const; }; diff --git a/server/shop/shop_prices.h b/server/shop/shop_prices.h deleted file mode 100644 index c3951e91..00000000 --- a/server/shop/shop_prices.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -namespace ShopPrices { -static constexpr int ak47 = 2700; -static constexpr int m3 = 1700; -static constexpr int awp = 4750; - -static constexpr int mag_ak47 = 80; -static constexpr int mag_m3 = 8; -static constexpr int mag_awp = 125; -static constexpr int mag_glock = 20; -} // namespace ShopPrices diff --git a/server/states/game_state.cpp b/server/states/game_state.cpp index ce3359c3..a08432fd 100644 --- a/server/states/game_state.cpp +++ b/server/states/game_state.cpp @@ -6,8 +6,11 @@ #include "server/physics/circular_hitbox.h" #include "server/physics/rect_hitbox.h" -GameState::GameState(std::shared_ptr&& game_clock, int max_players): - phase(std::move(game_clock)), max_players(max_players) { +GameState::GameState(std::shared_ptr&& game_clock, int max_players, + GameConfig&& game_config): + config(std::move(game_config)), + phase(std::move(game_clock), config.phase_times), + max_players(max_players) { updates = get_full_update(); } @@ -65,6 +68,8 @@ int GameState::get_num_cts() const { return num_cts; } +const GameConfig& GameState::get_config() const { return config; } + GamePhase& GameState::get_phase() { return phase; } const std::map>& GameState::get_players() const { @@ -111,8 +116,9 @@ void GameState::add_player(const std::string& player_name, Team team, const Vect if (players.find(player_name) != players.end()) throw std::runtime_error("Player already exists"); CharacterType default_character = get_default_character(team); - players[player_name] = std::make_unique( - team, default_character, CircularHitbox::player_hitbox(pos).get_bounds()); + players[player_name] = std::make_unique(team, default_character, + CircularHitbox::player_hitbox(pos).get_bounds(), + config.player_config, config.items_config); } void GameState::add_dropped_gun(std::unique_ptr&& gun, const Vector2D& pos) { @@ -181,9 +187,9 @@ void GameState::give_rewards_to_players(Team winning_team) { for (const auto& [p_name, player]: players) { if ((winning_team == Team::TT && player->is_tt()) || (winning_team == Team::CT && player->is_ct())) - player->add_rewards(Scores::win, Bonifications::win); + player->add_rewards(config.scores.win, config.bonifications.win); else - player->add_rewards(Scores::loss, Bonifications::loss); + player->add_rewards(config.scores.loss, config.bonifications.loss); } } diff --git a/server/states/game_state.h b/server/states/game_state.h index 26a50324..1a5e80f5 100644 --- a/server/states/game_state.h +++ b/server/states/game_state.h @@ -16,6 +16,7 @@ #include "state.h" class GameState: public State { + GameConfig config; GamePhase phase; int num_rounds = 0; int max_players; @@ -27,7 +28,7 @@ class GameState: public State { bool is_tts_win_condition() const; public: - GameState(std::shared_ptr&& game_clock, int max_players); + GameState(std::shared_ptr&& game_clock, int max_players, GameConfig&& game_config); bool player_is_in_game(const std::string& player_name) const; bool all_players_ready() const; @@ -39,6 +40,7 @@ class GameState: public State { int get_num_rounds() const; int get_num_tts() const; int get_num_cts() const; + const GameConfig& get_config() const; GamePhase& get_phase(); const std::map>& get_players() const; const std::unique_ptr& get_player(const std::string& player_name) const; diff --git a/server/states/inventory_state.cpp b/server/states/inventory_state.cpp index 6a6625ad..8f492d63 100644 --- a/server/states/inventory_state.cpp +++ b/server/states/inventory_state.cpp @@ -2,7 +2,10 @@ #include -InventoryState::InventoryState(int money): money(money) { updates = get_full_update(); } +InventoryState::InventoryState(int money, const GameConfig::ItemsConfig::KnifeConfig& knife_config): + money(money), knife(knife_config) { + updates = get_full_update(); +} int InventoryState::get_money() const { return money; } diff --git a/server/states/inventory_state.h b/server/states/inventory_state.h index ad0b66e2..4194d340 100644 --- a/server/states/inventory_state.h +++ b/server/states/inventory_state.h @@ -20,7 +20,7 @@ class InventoryState: public State { std::optional bomb; public: - explicit InventoryState(int money); + InventoryState(int money, const GameConfig::ItemsConfig::KnifeConfig& knife_config); int get_money() const; std::map>& get_guns(); diff --git a/server/states/player_state.cpp b/server/states/player_state.cpp index 820a3559..cdabe0bc 100644 --- a/server/states/player_state.cpp +++ b/server/states/player_state.cpp @@ -3,17 +3,20 @@ #include PlayerState::PlayerState(Team team, CharacterType character_type, Circle hitbox, - Vector2D aim_direction, Vector2D velocity, int speed, bool ready, - int health, ItemSlot equipped_item): + Vector2D aim_direction, Vector2D velocity, bool ready, + ItemSlot equipped_item, const GameConfig::PlayerConfig& player_config, + const GameConfig::ItemsConfig& items_config): team(team), character_type(character_type), hitbox(hitbox), + player_config(player_config), aim_direction(aim_direction), velocity(velocity), - speed(speed), + speed(player_config.speed), ready(ready), - health(health), - equipped_item(equipped_item) { + health(player_config.full_health), + equipped_item(equipped_item), + inventory(player_config.initial_money, items_config) { updates = get_full_update(); } @@ -23,6 +26,8 @@ CharacterType PlayerState::get_character_type() const { return character_type; } Circle PlayerState::get_hitbox() const { return hitbox; } +GameConfig::PlayerConfig PlayerState::get_player_config() const { return player_config; } + Vector2D PlayerState::get_aim_direction() const { return aim_direction; } Vector2D PlayerState::get_velocity() const { return velocity; } diff --git a/server/states/player_state.h b/server/states/player_state.h index b2a36efc..f05252ad 100644 --- a/server/states/player_state.h +++ b/server/states/player_state.h @@ -4,6 +4,7 @@ #include "common/updates/player_update.h" #include "common/utils/circle.h" #include "common/utils/vector_2d.h" +#include "server/game/game_config.h" #include "server/player/inventory.h" #include "state.h" @@ -14,6 +15,7 @@ class PlayerState: public State { Team team; CharacterType character_type; Circle hitbox; + GameConfig::PlayerConfig player_config; Vector2D aim_direction; Vector2D velocity; int speed; @@ -24,11 +26,14 @@ class PlayerState: public State { public: PlayerState(Team team, CharacterType character_type, Circle hitbox, Vector2D aim_direction, - Vector2D velocity, int speed, bool ready, int health, ItemSlot equipped_item); + Vector2D velocity, bool ready, ItemSlot equipped_item, + const GameConfig::PlayerConfig& player_config, + const GameConfig::ItemsConfig& items_config); Team get_team() const; CharacterType get_character_type() const; Circle get_hitbox() const; + GameConfig::PlayerConfig get_player_config() const; Vector2D get_aim_direction() const; Vector2D get_velocity() const; int get_speed() const; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b11cd4ce..73d4f0bd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -66,7 +66,6 @@ target_sources(taller_tests ../server/game/game_config.h # shop ../server/shop/shop.h - ../server/shop/shop_prices.h # items ../server/items/gun.h ../server/items/bomb.h @@ -74,7 +73,6 @@ target_sources(taller_tests ../server/items/weapon.h ../server/items/effects/effect.h ../server/items/effects/attack_effect.h - ../server/items/items_config.h # physics ../server/physics/physics_system.h ../server/physics/target_type.h @@ -87,7 +85,6 @@ target_sources(taller_tests ../common/map/tile.h # player ../server/player/player.h - ../server/player/player_config.h ../server/player/inventory.h ../server/player/statuses/idle_status.h ../server/player/statuses/moving_status.h diff --git a/tests/server/game/test_game.cpp b/tests/server/game/test_game.cpp index 3b9e9b77..6823e396 100644 --- a/tests/server/game/test_game.cpp +++ b/tests/server/game/test_game.cpp @@ -13,7 +13,6 @@ #include "server/game/game.h" #include "server/game/game_config.h" #include "server/map/map_builder.h" -#include "server/player/player_config.h" #include "server/player_message.h" #include "server/shop/shop.h" @@ -24,13 +23,16 @@ class TestGame: public ::testing::Test { std::shared_ptr clock; Map map; int max_players; + GameConfig config; Game game; TestGame(): clock(std::make_shared(std::chrono::steady_clock::now())), map(MapBuilder("./tests/server/map/map.yaml").build()), max_players(map.get_max_players()), - game("test_game", clock, std::move(map)) {} + config(GameConfig::load_config("./server/config.yaml")), + game("test_game", clock, std::move(map), + GameConfig::load_config("./server/config.yaml")) {} void advance_secs(float secs) { clock->advance(std::chrono::duration(secs)); } }; @@ -164,12 +166,12 @@ TEST_F(TestGame, NumberOfRoundsIncrementCorrectly) { int rounds = 3; for (int i = 0; i < rounds; i++) { - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game.tick({}); - advance_secs(PhaseTimes::round_duration); + advance_secs(config.phase_times.round_duration); game.tick({}); for (int j = 0; j < 10; j++) game.tick({}); - advance_secs(PhaseTimes::round_end_duration); + advance_secs(config.phase_times.round_end_duration); game.tick({}); } @@ -238,13 +240,13 @@ TEST_F(TestGame, PlayersSwapTeamsAfterHalfOfMaxRounds) { PlayerMessage("test_player2", msg_select_character_ct)}); GameUpdate updates; - for (int i = 0; i < GameConfig::max_rounds / 2; i++) { - advance_secs(PhaseTimes::buying_duration); + for (int i = 0; i < config.max_rounds / 2; i++) { + advance_secs(config.phase_times.buying_duration); game.tick({}); - advance_secs(PhaseTimes::round_duration); + advance_secs(config.phase_times.round_duration); game.tick({}); EXPECT_EQ(game.get_full_update().get_phase().get_type(), PhaseType::RoundEnd); - advance_secs(PhaseTimes::round_end_duration); + advance_secs(config.phase_times.round_end_duration); game.tick({}); EXPECT_EQ(game.get_full_update().get_num_rounds(), i + 1); } @@ -263,7 +265,7 @@ TEST_F(TestGame, PlayerCanMove) { updates = game.get_full_update(); Vector2D old_pos = updates.get_players().at("test_player").get_pos(); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game.tick({}); // Check velocity @@ -279,7 +281,7 @@ TEST_F(TestGame, PlayerCanMove) { player_updates = updates.get_players(); Vector2D new_pos = player_updates.at("test_player").get_pos(); - Vector2D step = dir * PlayerConfig::speed * (1.0f / GameConfig::tickrate); + Vector2D step = dir * config.player_config.speed * (1.0f / TICKRATE); EXPECT_EQ(new_pos.get_x(), old_pos.get_x() + step.get_x()); EXPECT_EQ(new_pos.get_y(), old_pos.get_y() + step.get_y()); @@ -291,7 +293,7 @@ TEST_F(TestGame, PlayerCanMoveInDiagonal) { updates = game.get_full_update(); Vector2D old_pos = updates.get_players().at("test_player").get_pos(); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game.tick({}); Vector2D dir = Vector2D(1, 1).normalized(PhysicsConfig::meter_size); @@ -302,7 +304,7 @@ TEST_F(TestGame, PlayerCanMoveInDiagonal) { std::map player_updates = updates.get_players(); Vector2D new_pos = player_updates.at("test_player").get_pos(); - Vector2D step = dir * PlayerConfig::speed * (1.0f / GameConfig::tickrate); + Vector2D step = dir * config.player_config.speed * (1.0f / TICKRATE); EXPECT_EQ(new_pos.get_x(), old_pos.get_x() + step.get_x()); EXPECT_EQ(new_pos.get_y(), old_pos.get_y() + step.get_y()); @@ -344,7 +346,7 @@ TEST_F(TestGame, TargetIsHitByPlayerAttack) { game.tick({PlayerMessage("test_player", msg_aim), PlayerMessage("test_player", msg_switch_weap), PlayerMessage("test_player", msg_start), PlayerMessage("target_player", msg_start)}); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); Message msg_attack = Message(AttackCommand()); auto player_messages = game.tick({PlayerMessage("test_player", msg_attack)}); @@ -378,7 +380,7 @@ TEST_F(TestGame, PlayerCanGetScoreboard) { EXPECT_EQ(scoreboard.at("test_player").kills, 0); EXPECT_EQ(scoreboard.at("test_player").deaths, 0); EXPECT_EQ(scoreboard.at("test_player").score, 0); - EXPECT_EQ(scoreboard.at("test_player").money, PlayerConfig::initial_money); + EXPECT_EQ(scoreboard.at("test_player").money, config.player_config.initial_money); } TEST_F(TestGame, PlayerIsDeadAfterTakingAllHealthDamage) { @@ -402,12 +404,12 @@ TEST_F(TestGame, PlayerIsDeadAfterTakingAllHealthDamage) { game.tick({PlayerMessage("test_player", msg_aim), PlayerMessage("test_player", msg_switch_weap), PlayerMessage("test_player", msg_start), PlayerMessage("target_player", msg_start)}); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); Message msg_attack = Message(AttackCommand()); std::vector player_messages; while (health > 0) { - advance_secs(1.0f / GlockConfig.attack_rate); + advance_secs(1.0f / config.items_config.glock.attack_rate); player_messages = game.tick({PlayerMessage("test_player", msg_attack)}); auto hit_response = player_messages[0].get_message().get_content(); updates = player_messages[2].get_message().get_content(); @@ -425,13 +427,14 @@ TEST_F(TestGame, PlayerIsDeadAfterTakingAllHealthDamage) { EXPECT_EQ(scoreboard.at("target_player").deaths, 1); EXPECT_EQ(scoreboard.at("target_player").kills, 0); EXPECT_EQ(scoreboard.at("test_player").score, 0); - EXPECT_EQ(scoreboard.at("test_player").money, PlayerConfig::initial_money); + EXPECT_EQ(scoreboard.at("test_player").money, config.player_config.initial_money); EXPECT_EQ(scoreboard.at("test_player").kills, 1); EXPECT_EQ(scoreboard.at("test_player").deaths, 0); - EXPECT_GT(scoreboard.at("test_player").score, Scores::kill); - EXPECT_EQ(scoreboard.at("test_player").money, - PlayerConfig::initial_money + Bonifications::kill + Bonifications::win); + EXPECT_GT(scoreboard.at("test_player").score, config.scores.kill); + EXPECT_EQ(scoreboard.at("test_player").money, config.player_config.initial_money + + config.bonifications.kill + + config.bonifications.win); break; } } @@ -464,7 +467,7 @@ TEST_F(TestGame, WeaponDoesNotMakeDamageWhenTargetIsOutOfRange) { game.tick({PlayerMessage("test_player", msg_aim), PlayerMessage("test_player", msg_switch_weap), PlayerMessage("test_player", msg_start), PlayerMessage("target_player", msg_start)}); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); Message msg_attack = Message(AttackCommand()); game.tick({PlayerMessage("test_player", msg_attack)}); @@ -493,12 +496,12 @@ TEST_F(TestGame, TTsWinIfTheyKillAllCTs) { Message msg_switch_weap = Message(SwitchItemCommand(ItemSlot::Secondary)); game.tick({PlayerMessage("tt", msg_aim), PlayerMessage("tt", msg_switch_weap)}); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); Message msg_attack = Message(AttackCommand()); std::vector player_messages; while (updates.get_players().at("ct").get_health() > 0) { - advance_secs(1.0f / GlockConfig.attack_rate); + advance_secs(1.0f / config.items_config.glock.attack_rate); int old_ct_health = updates.get_players().at("ct").get_health(); player_messages = game.tick({PlayerMessage("tt", msg_attack)}); updates = game.get_full_update(); @@ -538,7 +541,7 @@ TEST_F(TestGame, PlayerStateResetCorrectlyWhenANewRoundStarts) { Vector2D tt_pos = updates.get_players().at("test_player").get_pos(); Vector2D ct_pos = updates.get_players().at("target_player").get_pos(); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); Message msg_aim = Message(AimCommand(ct_pos - tt_pos)); Message msg_switch_weap = Message(SwitchItemCommand(ItemSlot::Secondary)); @@ -547,8 +550,9 @@ TEST_F(TestGame, PlayerStateResetCorrectlyWhenANewRoundStarts) { Message msg_attack = Message(AttackCommand()); - while (updates.get_players().at("target_player").get_health() == PlayerConfig::full_health) { - advance_secs(1.0f / GlockConfig.attack_rate); + while (updates.get_players().at("target_player").get_health() == + config.player_config.full_health) { + advance_secs(1.0f / config.items_config.glock.attack_rate); game.tick({PlayerMessage("test_player", msg_attack)}); updates = game.get_full_update(); } @@ -556,22 +560,24 @@ TEST_F(TestGame, PlayerStateResetCorrectlyWhenANewRoundStarts) { Message msg_start_moving = Message(MoveCommand(Vector2D(1, 0))); game.tick({PlayerMessage("test_player", msg_start_moving)}); - advance_secs(PhaseTimes::round_duration); + advance_secs(config.phase_times.round_duration); game.tick({}); - advance_secs(PhaseTimes::round_end_duration); + advance_secs(config.phase_times.round_end_duration); game.tick({}); updates = game.get_full_update(); - EXPECT_EQ(updates.get_players().at("test_player").get_health(), PlayerConfig::full_health); - EXPECT_EQ(updates.get_players().at("target_player").get_health(), PlayerConfig::full_health); + EXPECT_EQ(updates.get_players().at("test_player").get_health(), + config.player_config.full_health); + EXPECT_EQ(updates.get_players().at("target_player").get_health(), + config.player_config.full_health); EXPECT_EQ(updates.get_players().at("test_player").get_pos(), tt_pos); EXPECT_EQ(updates.get_players().at("target_player").get_pos(), ct_pos); EXPECT_EQ(updates.get_players().at("test_player").get_velocity(), Vector2D(0, 0)); EXPECT_EQ(updates.get_players().at("target_player").get_velocity(), Vector2D(0, 0)); EXPECT_EQ(updates.get_players().at("test_player").get_inventory().get_money(), - PlayerConfig::initial_money + Bonifications::loss); + config.player_config.initial_money + config.bonifications.loss); EXPECT_EQ(updates.get_players().at("target_player").get_inventory().get_money(), - PlayerConfig::initial_money + Bonifications::win); + config.player_config.initial_money + config.bonifications.win); } TEST_F(TestGame, PlayerCannotPlantBombWhenNotInPlayingPhase) { @@ -598,7 +604,7 @@ TEST_F(TestGame, PlayerCannotPlantBombWhenNotInBombSite) { Message msg_set_ready = Message(SetReadyCommand()); game.tick({PlayerMessage("tt", msg_select_team_tt), PlayerMessage("ct", msg_select_team_ct), PlayerMessage("tt", msg_set_ready), PlayerMessage("ct", msg_set_ready)}); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game.tick({}); Message msg_start_planting = Message(StartPlantingBombCommand()); @@ -628,11 +634,11 @@ TEST_F(TestGame, OneTerroristHasBombWhenRoundStarts) { Message msg_switch_weap = Message(SwitchItemCommand(ItemSlot::Secondary)); game.tick({PlayerMessage("ct", msg_aim), PlayerMessage("ct", msg_switch_weap)}); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); Message msg_attack = Message(AttackCommand()); while (updates.get_players().at("tt").get_health() > 0) { - advance_secs(1.0f / GlockConfig.attack_rate); + advance_secs(1.0f / config.items_config.glock.attack_rate); game.tick({PlayerMessage("ct", msg_attack)}); updates = game.get_full_update(); } @@ -641,9 +647,9 @@ TEST_F(TestGame, OneTerroristHasBombWhenRoundStarts) { EXPECT_TRUE(updates.get_bomb().has_value()); EXPECT_EQ(updates.get_bomb().value().hitbox.get_pos(), tt_pos); - advance_secs(PhaseTimes::round_duration); + advance_secs(config.phase_times.round_duration); game.tick({}); - advance_secs(PhaseTimes::round_end_duration); + advance_secs(config.phase_times.round_end_duration); auto player_messages = game.tick({}); updates = player_messages[0].get_message().get_content(); EXPECT_TRUE(updates.get_players().at("tt").get_inventory().get_bomb().has_value()); @@ -661,21 +667,21 @@ TEST_F(TestGame, PlayerCanPickUpDroppedItem) { Message msg_start = Message(SetReadyCommand()); game.tick({PlayerMessage("tt", msg_start), PlayerMessage("ct", msg_start)}); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game.tick({}); - advance_secs(PhaseTimes::round_duration); + advance_secs(config.phase_times.round_duration); game.tick({}); - advance_secs(PhaseTimes::round_end_duration); + advance_secs(config.phase_times.round_end_duration); game.tick({}); Message msg_buy_m3 = Message(BuyGunCommand(GunType::M3)); game.tick({PlayerMessage("ct", msg_buy_m3)}); for (int i = 0; i < 5; i++) { - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game.tick({}); - advance_secs(PhaseTimes::round_duration); + advance_secs(config.phase_times.round_duration); game.tick({}); - advance_secs(PhaseTimes::round_end_duration); + advance_secs(config.phase_times.round_end_duration); game.tick({}); } diff --git a/tests/server/game/test_game_bomb.cpp b/tests/server/game/test_game_bomb.cpp index be7aa381..0855d189 100644 --- a/tests/server/game/test_game_bomb.cpp +++ b/tests/server/game/test_game_bomb.cpp @@ -13,7 +13,6 @@ #include "server/errors.h" #include "server/game/game.h" #include "server/game/game_config.h" -#include "server/items/items_config.h" #include "server/map/map_builder.h" #include "server/player_message.h" #include "server/shop/shop.h" @@ -22,16 +21,19 @@ class TestGameBomb: public ::testing::Test { protected: + GameConfig config; std::shared_ptr clock; Map map; int max_players; Game game; TestGameBomb(): + config(GameConfig::load_config("./server/config.yaml")), clock(std::make_shared(std::chrono::steady_clock::now())), map(MapBuilder("./tests/server/map/map2.yaml").build()), max_players(map.get_max_players()), - game("test_game", clock, std::move(map)) {} + game("test_game", clock, std::move(map), + GameConfig::load_config("./server/config.yaml")) {} void SetUp() override { game.join_player("tt"); @@ -41,14 +43,14 @@ class TestGameBomb: public ::testing::Test { Message msg_set_ready = Message(SetReadyCommand()); game.tick({PlayerMessage("tt", msg_select_team_tt), PlayerMessage("ct", msg_select_team_ct), PlayerMessage("tt", msg_set_ready), PlayerMessage("ct", msg_set_ready)}); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game.tick({}); } void SetUpBombPlanted() { Message msg_start_planting = Message(StartPlantingBombCommand()); game.tick({PlayerMessage("tt", msg_start_planting)}); - advance_secs(BombConfig::secs_to_plant); + advance_secs(config.items_config.bomb.secs_to_plant); game.tick({}); } @@ -73,7 +75,7 @@ TEST_F(TestGameBomb, PlayerPlantBombAfterPlantingForSecondsToPlantTime) { Message msg_start_planting = Message(StartPlantingBombCommand()); game.tick({PlayerMessage("tt", msg_start_planting)}); - advance_secs(BombConfig::secs_to_plant); + advance_secs(config.items_config.bomb.secs_to_plant); auto player_messages = game.tick({}); GameUpdate updates = player_messages[0].get_message().get_content(); EXPECT_TRUE(updates.get_bomb().has_value()); @@ -91,7 +93,7 @@ TEST_F(TestGameBomb, PlayerDoesNotPlantBombIfStopPlantingBeforeSecondsToPlantTim Message msg_start_planting = Message(StartPlantingBombCommand()); game.tick({PlayerMessage("tt", msg_start_planting)}); - advance_secs(BombConfig::secs_to_plant / 2.0f); + advance_secs(config.items_config.bomb.secs_to_plant / 2.0f); Message msg_stop_planting = Message(StopPlantingBombCommand()); auto player_messages = game.tick({PlayerMessage("tt", msg_stop_planting)}); GameUpdate updates = player_messages[0].get_message().get_content(); @@ -107,7 +109,7 @@ TEST_F(TestGameBomb, PlayerDoesNotPlantBombIfStopPlantingBeforeSecondsToPlantTim TEST_F(TestGameBomb, BombExplodeAfterSecondsToExplode) { SetUpBombPlanted(); - advance_secs(BombConfig::secs_to_explode); + advance_secs(config.items_config.bomb.secs_to_explode); auto player_messages = game.tick({}); bool found_bomb_exploded_resp = false; @@ -120,7 +122,8 @@ TEST_F(TestGameBomb, BombExplodeAfterSecondsToExplode) { 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); + EXPECT_EQ(bomb_exploded_resp.get_explosion_radius(), + config.items_config.bomb.max_range); } else if (player_msg.get_message().get_type() == MessageType::ROUND_END_RESP) { found_round_end_resp = true; auto round_end_resp = player_msg.get_message().get_content(); @@ -135,8 +138,8 @@ TEST_F(TestGameBomb, BombExplodeAfterSecondsToExplode) { EXPECT_EQ(updates.get_bomb().value().item.get_bomb_phase(), BombPhaseType::Exploded); updates = game.get_full_update(); - EXPECT_LE(updates.get_players().at("tt").get_health(), PlayerConfig::full_health); - EXPECT_LE(updates.get_players().at("ct").get_health(), PlayerConfig::full_health); + EXPECT_LE(updates.get_players().at("tt").get_health(), config.player_config.full_health); + EXPECT_LE(updates.get_players().at("ct").get_health(), config.player_config.full_health); EXPECT_EQ(updates.get_phase().get_type(), PhaseType::RoundEnd); } @@ -154,11 +157,12 @@ TEST_F(TestGameBomb, PlayerCannotDefuseBombIfItIsNotPlanted) { TEST_F(TestGameBomb, PlayerDefuseBombAfterDefusingForSecondsToDefuseTime) { SetUpBombPlanted(); - advance_secs(BombConfig::secs_to_explode - 1 - BombConfig::secs_to_defuse); + advance_secs(config.items_config.bomb.secs_to_explode - 1 - + config.items_config.bomb.secs_to_defuse); Message msg_start_defusing = Message(StartDefusingBombCommand()); game.tick({PlayerMessage("ct", msg_start_defusing)}); - advance_secs(BombConfig::secs_to_defuse); - advance_secs(PhaseTimes::round_end_duration / 2.0f); + advance_secs(config.items_config.bomb.secs_to_defuse); + advance_secs(config.phase_times.round_end_duration / 2.0f); auto player_messages = game.tick({}); @@ -177,15 +181,15 @@ TEST_F(TestGameBomb, PlayerDefuseBombAfterDefusingForSecondsToDefuseTime) { EXPECT_EQ(updates.get_bomb().value().item.get_bomb_phase(), BombPhaseType::Defused); updates = game.get_full_update(); - EXPECT_EQ(updates.get_players().at("tt").get_health(), PlayerConfig::full_health); - EXPECT_EQ(updates.get_players().at("ct").get_health(), PlayerConfig::full_health); + EXPECT_EQ(updates.get_players().at("tt").get_health(), config.player_config.full_health); + EXPECT_EQ(updates.get_players().at("ct").get_health(), config.player_config.full_health); EXPECT_EQ(updates.get_phase().get_type(), PhaseType::RoundEnd); } TEST_F(TestGameBomb, BombExplodeIfReachingSecondsToExplodeBeforeDefusing) { SetUpBombPlanted(); - advance_secs(BombConfig::secs_to_explode - 1); + advance_secs(config.items_config.bomb.secs_to_explode - 1); Message msg_start_defusing = Message(StartDefusingBombCommand()); game.tick({PlayerMessage("ct", msg_start_defusing)}); advance_secs(1); @@ -203,8 +207,8 @@ TEST_F(TestGameBomb, BombExplodeIfReachingSecondsToExplodeBeforeDefusing) { EXPECT_EQ(updates.get_bomb().value().item.get_bomb_phase(), BombPhaseType::Exploded); updates = game.get_full_update(); - EXPECT_LE(updates.get_players().at("tt").get_health(), PlayerConfig::full_health); - EXPECT_LE(updates.get_players().at("ct").get_health(), PlayerConfig::full_health); + EXPECT_LE(updates.get_players().at("tt").get_health(), config.player_config.full_health); + EXPECT_LE(updates.get_players().at("ct").get_health(), config.player_config.full_health); EXPECT_EQ(updates.get_phase().get_type(), PhaseType::RoundEnd); } @@ -214,7 +218,7 @@ TEST_F(TestGameBomb, PlayerDoesNotDefuseBombIfStopDefusingBeforeSecondsToDefuseT Message msg_start_defusing = Message(StartDefusingBombCommand()); game.tick({PlayerMessage("ct", msg_start_defusing)}); - advance_secs(BombConfig::secs_to_defuse / 2.0f); + advance_secs(config.items_config.bomb.secs_to_defuse / 2.0f); Message msg_stop_defusing = Message(StopDefusingBombCommand()); auto player_messages = game.tick({PlayerMessage("ct", msg_stop_defusing)}); diff --git a/tests/server/game/test_game_phase.cpp b/tests/server/game/test_game_phase.cpp index a86685fa..69a12e80 100644 --- a/tests/server/game/test_game_phase.cpp +++ b/tests/server/game/test_game_phase.cpp @@ -13,12 +13,14 @@ class TestGamePhase: public ::testing::Test { protected: + GameConfig config; std::shared_ptr clock; GamePhase game_phase; TestGamePhase(): + config(GameConfig::load_config("./server/config.yaml")), clock(std::make_shared(std::chrono::steady_clock::now())), - game_phase(clock) {} + game_phase(clock, config.phase_times) {} void advance_secs(int secs) { clock->advance(std::chrono::seconds(secs)); } }; @@ -33,7 +35,7 @@ TEST_F(TestGamePhase, StartInBuyingPhase) { TEST_F(TestGamePhase, StartPlayingAfterBuyingDuration) { game_phase.start_game(); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game_phase.advance(); PhaseUpdate updates = game_phase.get_updates(); @@ -43,9 +45,9 @@ TEST_F(TestGamePhase, StartPlayingAfterBuyingDuration) { TEST_F(TestGamePhase, FinishOneRoundAfterRoundDuration) { game_phase.start_game(); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game_phase.advance(); - advance_secs(PhaseTimes::round_duration); + advance_secs(config.phase_times.round_duration); game_phase.advance(); PhaseUpdate updates = game_phase.get_updates(); @@ -55,11 +57,11 @@ TEST_F(TestGamePhase, FinishOneRoundAfterRoundDuration) { TEST_F(TestGamePhase, StartAnotherRoundAfterRoundFinishedDuration) { game_phase.start_game(); - advance_secs(PhaseTimes::buying_duration); + advance_secs(config.phase_times.buying_duration); game_phase.advance(); - advance_secs(PhaseTimes::round_duration); + advance_secs(config.phase_times.round_duration); game_phase.advance(); - advance_secs(PhaseTimes::round_end_duration); + advance_secs(config.phase_times.round_end_duration); game_phase.advance(); PhaseUpdate updates = game_phase.get_updates(); diff --git a/tests/server/game/test_shop.cpp b/tests/server/game/test_shop.cpp index 3bc42fc0..8a7ca079 100644 --- a/tests/server/game/test_shop.cpp +++ b/tests/server/game/test_shop.cpp @@ -2,23 +2,25 @@ #include "common/models.h" #include "server/errors.h" +#include "server/game/game_config.h" #include "server/items/gun.h" #include "server/player/player.h" -#include "server/player/player_config.h" #include "server/shop/shop.h" -#include "server/shop/shop_prices.h" #include "mock_clock.h" class TestShop: public ::testing::Test { protected: + GameConfig config; Inventory inventory; - TestShop(): inventory() {} + TestShop(): + config(GameConfig::load_config("./server/config.yaml")), + inventory(config.player_config.initial_money, config.items_config) {} }; TEST_F(TestShop, CanBuyAnyPrimaryWeapon) { - Shop shop; + Shop shop(config.shop_prices); inventory.set_money(10000); int initial_money = inventory.get_full_update().get_money(); @@ -28,7 +30,7 @@ TEST_F(TestShop, CanBuyAnyPrimaryWeapon) { EXPECT_TRUE(prices.find(GunType::AWP) != prices.end()); for (auto [gun_type, price]: prices) { - shop.buy_gun(gun_type, inventory); + shop.buy_gun(gun_type, inventory, config.items_config.get_gun_config(gun_type)); int actual_money = inventory.get_updates().get_money(); EXPECT_EQ(actual_money, initial_money - price); @@ -41,14 +43,14 @@ TEST_F(TestShop, CanBuyAnyPrimaryWeapon) { } TEST_F(TestShop, CannotBuyWeaponIfNotEnoughMoney) { - Shop shop; + Shop shop(config.shop_prices); GunType gun = GunType::AK47; int initial_money = inventory.get_full_update().get_money(); - int gun_price = ShopPrices::ak47; + int gun_price = shop.get_gun_prices().at(gun); while (gun_price <= initial_money) { EXPECT_TRUE(shop.can_buy_gun(gun, inventory)); - shop.buy_gun(gun, inventory); + shop.buy_gun(gun, inventory, config.items_config.get_gun_config(gun)); initial_money = inventory.get_updates().get_money(); } @@ -59,7 +61,7 @@ TEST_F(TestShop, CannotBuyWeaponIfNotEnoughMoney) { TEST_F(TestShop, BuyAmmo) { InventoryUpdate inventory_update; - Shop shop; + Shop shop(config.shop_prices); inventory.set_money(10000); inventory_update = inventory.get_full_update(); @@ -70,10 +72,10 @@ TEST_F(TestShop, BuyAmmo) { InventoryUpdate new_update = inventory.get_full_update(); int new_money = new_update.get_money(); - EXPECT_EQ(new_money, old_money - ShopPrices::mag_glock); + EXPECT_EQ(new_money, old_money - shop.get_ammo_prices().at(GunType::Glock)); GunUpdate new_glock = new_update.get_guns().at(ItemSlot::Secondary); EXPECT_EQ(new_glock.get_mag_ammo(), old_glock.get_mag_ammo()); EXPECT_EQ(new_glock.get_reserve_ammo(), - old_glock.get_reserve_ammo() + GlockConfig.bullets_per_mag); + old_glock.get_reserve_ammo() + config.items_config.glock.bullets_per_mag); } diff --git a/tests/server/player/test_player.cpp b/tests/server/player/test_player.cpp index 41c9f37f..f90dfbf7 100644 --- a/tests/server/player/test_player.cpp +++ b/tests/server/player/test_player.cpp @@ -6,31 +6,34 @@ #include "../game/mock_clock.h" #include "common/models.h" #include "server/errors.h" +#include "server/game/game_config.h" #include "server/items/gun.h" #include "server/physics/circular_hitbox.h" #include "server/player/player.h" -#include "server/player/player_config.h" #include "server/shop/shop.h" class TestPlayer: public ::testing::Test { protected: + GameConfig config; MockClock clock; Player player; TestPlayer(): + config(GameConfig::load_config("./server/config.yaml")), clock(std::chrono::steady_clock::now()), - player(Team::TT, CharacterType::Pheonix, - CircularHitbox::player_hitbox(Vector2D(0, 0))) {} + player(Team::TT, CharacterType::Pheonix, CircularHitbox::player_hitbox(Vector2D(0, 0)), + config.player_config, config.items_config) {} void advance_secs(float secs) { clock.advance(std::chrono::duration(secs)); } }; TEST_F(TestPlayer, PlayerStartWithFullHealth) { - EXPECT_EQ(PlayerConfig::full_health, player.get_full_update().get_health()); + EXPECT_EQ(config.player_config.full_health, player.get_full_update().get_health()); } TEST_F(TestPlayer, PlayerStartWithDefaultInventory) { - InventoryUpdate i_inv = Inventory().get_full_update(); + InventoryUpdate i_inv = + Inventory(config.player_config.initial_money, config.items_config).get_full_update(); InventoryUpdate p_inv = player.get_full_update().get_inventory(); GunUpdate i_sec_weapon = i_inv.get_guns().at(ItemSlot::Secondary); @@ -53,27 +56,28 @@ TEST_F(TestPlayer, GunReduceMagAmmoWhenPlayerAttacks) { auto attack_effects = player.attack(clock.now()); EXPECT_EQ(attack_effects.size(), 1); EXPECT_EQ(player.get_inventory().get_guns().at(ItemSlot::Secondary)->get_mag_ammo(), - old_mag_ammo - GlockConfig.bullets_per_attack); + old_mag_ammo - config.items_config.glock.bullets_per_attack); } TEST_F(TestPlayer, GunBurst) { - Shop shop; + Shop shop(config.shop_prices); player.get_inventory().set_money(10000); - shop.buy_gun(GunType::AK47, player.get_inventory()); + shop.buy_gun(GunType::AK47, player.get_inventory(), + config.items_config.get_gun_config(GunType::AK47)); player.equip_item(ItemSlot::Primary); player.handle_start_attacking(clock.now()); - for (int i = 0; i < Ak47Config.bullets_per_attack; i++) { + for (int i = 0; i < config.items_config.ak47.bullets_per_attack; i++) { if (i > 0) { auto effects = player.attack(clock.now()); EXPECT_EQ(effects.size(), 0); } - advance_secs(Ak47Config.burst_interval); + advance_secs(config.items_config.ak47.burst_interval); auto attack_effects = player.attack(clock.now()); EXPECT_EQ(attack_effects.size(), 1); EXPECT_EQ(player.get_inventory().get_guns().at(ItemSlot::Primary)->get_mag_ammo(), - Ak47Config.bullets_per_mag - (i + 1)); + config.items_config.ak47.bullets_per_mag - (i + 1)); } auto attack_effects = player.attack(clock.now()); From 4b49230cd6be79cfdb9349a6d9d5161649d471f3 Mon Sep 17 00:00:00 2001 From: Jesabel Pugliese Date: Tue, 24 Jun 2025 13:36:51 -0300 Subject: [PATCH 4/6] fix(player): revert player speed to default value of 4.5 --- server/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/config.yaml b/server/config.yaml index 41acb491..2fd678ce 100644 --- a/server/config.yaml +++ b/server/config.yaml @@ -15,7 +15,7 @@ PhaseTimes: round_end_duration: 5 Player: - speed: 9 + speed: 4.5 full_health: 100 initial_money: 800 From 9fbe71bad087764cde05e63408cdd4b5308c4722 Mon Sep 17 00:00:00 2001 From: Jesabel Pugliese Date: Tue, 24 Jun 2025 13:47:26 -0300 Subject: [PATCH 5/6] fix(game): remove unnecessary throw exception in SetReadyCommand handler --- server/errors.h | 5 ----- server/game/game.cpp | 2 +- tests/server/game/test_game.cpp | 17 ----------------- 3 files changed, 1 insertion(+), 23 deletions(-) diff --git a/server/errors.h b/server/errors.h index 246d8cc4..128bd155 100644 --- a/server/errors.h +++ b/server/errors.h @@ -24,11 +24,6 @@ class JoinGameError: public GameError { JoinGameError(): GameError("could not join game") {} }; -class SetReadyError: public GameError { -public: - SetReadyError(): GameError("try to set ready when playing an already started game") {} -}; - class SelectTeamError: public GameError { public: SelectTeamError(): GameError("error at select team") {} diff --git a/server/game/game.cpp b/server/game/game.cpp index 8866a892..0e590e59 100644 --- a/server/game/game.cpp +++ b/server/game/game.cpp @@ -231,7 +231,7 @@ template <> void Game::handle(const std::string& player_name, [[maybe_unused]] const SetReadyCommand& msg) { if (state.get_phase().is_playing()) - throw SetReadyError(); + return; state.get_player(player_name)->set_ready(); if (state.all_players_ready()) { diff --git a/tests/server/game/test_game.cpp b/tests/server/game/test_game.cpp index 6823e396..378d4483 100644 --- a/tests/server/game/test_game.cpp +++ b/tests/server/game/test_game.cpp @@ -107,23 +107,6 @@ TEST_F(TestGame, PlayerCannotJoinFullTeam) { EXPECT_EQ(updates.get_players().at("extra_player").get_team(), Team::CT); } -TEST_F(TestGame, CannotStartAnAlreadyStartedGame) { - game.join_player("test_player"); - game.tick({}); - - auto player_messages = game.tick({PlayerMessage("test_player", Message(SetReadyCommand()))}); - GameUpdate updates; - updates = player_messages[0].get_message().get_content(); - - std::map player_updates = updates.get_players(); - EXPECT_EQ(player_updates.at("test_player").get_ready(), true); - PhaseUpdate phase_updates = updates.get_phase(); - EXPECT_EQ(phase_updates.get_type(), PhaseType::Buying); - - EXPECT_THROW({ game.tick({PlayerMessage("test_player", Message(SetReadyCommand()))}); }, - SetReadyError); -} - TEST_F(TestGame, PlayerCannotJoinStartedGame) { game.join_player("test_player"); Message msg_start = Message(SetReadyCommand()); From 0ac7d427f0008b0335137068231739a51e4c965e Mon Sep 17 00:00:00 2001 From: Jesabel Pugliese Date: Tue, 24 Jun 2025 14:33:26 -0300 Subject: [PATCH 6/6] fix(game): player stops defusing when passing seconds to defuse time --- server/game/game.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/game/game.cpp b/server/game/game.cpp index 523c44ed..58e0673d 100644 --- a/server/game/game.cpp +++ b/server/game/game.cpp @@ -104,10 +104,14 @@ void Game::advance_bomb_logic() { } auto& bomb = state.get_bomb().value(); + bool bomb_was_defused = bomb.item.is_defused(); bomb.item.advance(state.get_phase().get_time_now()); - if (bomb.item.is_defused()) + if (!bomb_was_defused && bomb.item.is_defused()) { + for (const auto& [_, player]: state.get_players()) + player->handle_stop_defusing(bomb.item, state.get_phase().get_time_now()); return; + } if (!bomb.item.should_explode()) return;