diff --git a/CMakeLists.txt b/CMakeLists.txt index 236df3e..14f2ad4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,8 +134,6 @@ set(CLIENT_ONLY_SOURCES set(SERVER_ONLY_SOURCES "src/game/character.hpp" "src/game/character.cpp" - "src/game/controllable_character.hpp" - "src/game/controllable_character.cpp" "src/game/destroyed_object.hpp" "src/game/destroyed_object.cpp" "src/game/drivable_vehicle.hpp" @@ -146,6 +144,8 @@ set(SERVER_ONLY_SOURCES "src/game/entity.cpp" "src/game/game.hpp" "src/game/game.cpp" + "src/game/human_character.hpp" + "src/game/human_character.cpp" "src/game/mapinstance.hpp" "src/game/mapinstance.cpp" "src/game/marker.hpp" @@ -160,6 +160,8 @@ set(SERVER_ONLY_SOURCES "src/game/player.cpp" "src/game/remote_menu.hpp" "src/game/remote_menu.cpp" + "src/game/rideable.hpp" + "src/game/rideable.cpp" "src/game/simple_entity.hpp" "src/game/simple_entity.cpp" "src/game/tuning_world.hpp" diff --git a/src/game/controllable_character.cpp b/src/game/controllable_character.cpp deleted file mode 100644 index 70a63e8..0000000 --- a/src/game/controllable_character.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "controllable_character.hpp" -#include "drivable_vehicle.hpp" - -game::ControllableCharacter::ControllableCharacter(World& world, const CharacterTuning& tuning) : Character(world, tuning) {} - -void game::ControllableCharacter::SetVehicle(DrivableVehicle* vehicle, uint32_t seat) -{ - if ((vehicle && vehicle_) || (!vehicle && !vehicle_)) - return; - - if (vehicle) - { - if (!vehicle->SetPassenger(seat, this)) - return; - - auto seat_loc = vehicle->GetModel()->GetLocation("seat" + std::to_string(seat)); - if (seat_loc) - SetPosition(seat_loc->position); - - EnablePhysics(false); - Attach(vehicle->GetEntNum()); - SetMainAnim(seat == 0 ? "vehicle_drive" : "vehicle_passenger"); - SetYaw(0.5f * glm::pi()); - } - else - { - vehicle_->SetPassenger(seat_idx_, nullptr); - - EnablePhysics(true); - - glm::vec3 seat_loc = vehicle_->GetModel()->GetLocation("seat" + std::to_string(seat_idx_))->position; - seat_loc.x += glm::sign(seat_loc.x) * 0.5f; // to the side - glm::vec3 pos = vehicle_->GetRoot().matrix * glm::vec4(seat_loc, 1.0f); - pos.z += 0.5f; - SetPosition(pos); - - Attach(0); - SetMainAnim("idle"); - // SetYaw(0.0f); - } - - vehicle_ = vehicle; - seat_idx_ = seat; - is_driver_ = vehicle && seat == 0; - VehicleChanged(); -} - -game::ControllableCharacter::~ControllableCharacter() -{ - if (vehicle_) - { - vehicle_->SetPassenger(seat_idx_, nullptr); - } -} diff --git a/src/game/controllable_character.hpp b/src/game/controllable_character.hpp deleted file mode 100644 index e7304e0..0000000 --- a/src/game/controllable_character.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "character.hpp" - -namespace game -{ - -class DrivableVehicle; - -class ControllableCharacter : public Character -{ -public: - using Super = Character; - - ControllableCharacter(World& world, const CharacterTuning& tuning); - - void SetVehicle(DrivableVehicle* vehicle, uint32_t seat); - - DrivableVehicle* GetVehicle() const { return vehicle_; } - bool IsDriver() const { return is_driver_; } - - ~ControllableCharacter() override; - -protected: - virtual void VehicleChanged() = 0; - - size_t seat_idx_ = 0; - bool is_driver_ = false; - DrivableVehicle* vehicle_ = nullptr; -}; -} - diff --git a/src/game/drivable_vehicle.cpp b/src/game/drivable_vehicle.cpp index 80cdcd3..c048d4a 100644 --- a/src/game/drivable_vehicle.cpp +++ b/src/game/drivable_vehicle.cpp @@ -2,7 +2,7 @@ #include "player_character.hpp" #include "utils/random.hpp" -game::DrivableVehicle::DrivableVehicle(World& world, const VehicleTuning& tuning) : Vehicle(world, tuning), Usable(GetRoot().matrix) +game::DrivableVehicle::DrivableVehicle(World& world, const VehicleTuning& tuning) : Vehicle(world, tuning), Usable(GetRoot().matrix), Rideable(*this, RIDEABLE_VEHICLE) { InitSeats(); OnPhysicsChanged(); @@ -11,7 +11,7 @@ game::DrivableVehicle::DrivableVehicle(World& world, const VehicleTuning& tuning void game::DrivableVehicle::Update() { float daytime = world_.GetDayTime(); - SetLightsOn(seats_[0].occupant && (daytime < 6.0f || daytime > 18.0f)); + SetLightsOn(GetPassenger(0) && (daytime < 6.0f || daytime > 18.0f)); Super::Update(); @@ -31,13 +31,13 @@ void game::DrivableVehicle::OnPhysicsChanged() bool game::DrivableVehicle::QueryUseTarget(PlayerCharacter& character, uint32_t target_id, UseTargetQueryResult& res) { - if (character.GetVehicle()) - return false; // already in vehicle + if (character.GetRideable()) + return false; // already in something res.enabled = true; res.error_text = nullptr; - bool seat_occupied = seats_[target_id].occupant != nullptr; + bool seat_occupied = GetPassenger(target_id) != nullptr; res.delay = seat_occupied ? 2.0f : 0.25f; return true; @@ -45,53 +45,35 @@ bool game::DrivableVehicle::QueryUseTarget(PlayerCharacter& character, uint32_t void game::DrivableVehicle::Use(PlayerCharacter& character, uint32_t target_id) { - if (target_id >= seats_.size()) + if (target_id >= GetNumSeats()) return; - character.SetVehicle(this, target_id); // seat idx is same as target_id + character.Ride(this, target_id); PlaySound("cardoor", 1.0f, RandomFloat(0.9f, 1.1f)); - } -bool game::DrivableVehicle::SetPassenger(uint32_t seat_idx, ControllableCharacter* character) +static game::CharacterInputFlags MapPlayerInputToVehicleInput(game::PlayerInputFlags in) { - if (seat_idx >= seats_.size()) - return false; + game::VehicleInputFlags vin = 0; - auto& seat_info = seats_[seat_idx]; + if (in & (1 << game::IN_FORWARD)) + vin |= 1 << game::VIN_FORWARD; - if (seat_info.occupant == character) - return true; // already sitting here + if (in & (1 << game::IN_BACKWARD)) + vin |= 1 << game::VIN_BACKWARD; - if (seat_info.occupant && character) - { - seat_info.occupant->SetVehicle(nullptr, 0); // remove current occupant - } + if (in & (1 << game::IN_LEFT)) + vin |= 1 << game::VIN_LEFT; - seat_info.occupant = character; + if (in & (1 << game::IN_RIGHT)) + vin |= 1 << game::VIN_RIGHT; - if (seat_idx == 0) - { - if (!character) - { - // clear inputs - SetInputs(0); - SetSteering(false, 0.0f); - } - - } - - return true; + return vin; } -game::DrivableVehicle::~DrivableVehicle() +void game::DrivableVehicle::SetRideableInput(PlayerInputFlags in) { - // remove occupants - for (auto& seat : seats_) - { - if (seat.occupant) - seat.occupant->SetVehicle(nullptr, 0); - } + SetInputs(MapPlayerInputToVehicleInput(in)); } static char HexChar(uint32_t val) @@ -120,13 +102,11 @@ void game::DrivableVehicle::InitSeats() if (!trans) break; - VehicleSeat seat{}; - seat.position = trans->position; - seat.position.z += 1.0f; // the original pos is for animated character which is under vehicle - seats_.emplace_back(seat); + auto position = trans->position; + size_t seat_idx = AddSeat(position); - uint32_t id = seats_.size() - 1; - use_targets_.emplace_back(this, id, seat.position, std::string()); + position.z += 1.0f; // the original pos is for animated character which is under vehicle + use_targets_.emplace_back(this, static_cast(seat_idx), position, std::string()); } UpdateUseTargetNames(); diff --git a/src/game/drivable_vehicle.hpp b/src/game/drivable_vehicle.hpp index 40ba32e..ca4fd6c 100644 --- a/src/game/drivable_vehicle.hpp +++ b/src/game/drivable_vehicle.hpp @@ -2,18 +2,13 @@ #include "vehicle.hpp" #include "usable.hpp" -#include "controllable_character.hpp" +#include "rideable.hpp" +#include "human_character.hpp" namespace game { -struct VehicleSeat -{ - glm::vec3 position; - ControllableCharacter* occupant; -}; - -class DrivableVehicle : public Vehicle, public Usable +class DrivableVehicle : public Vehicle, public Usable, public Rideable { public: using Super = Vehicle; @@ -29,19 +24,12 @@ public: virtual bool QueryUseTarget(PlayerCharacter& character, uint32_t target_id, UseTargetQueryResult& res) override; virtual void Use(PlayerCharacter& character, uint32_t target_id) override; - bool SetPassenger(uint32_t seat_idx, ControllableCharacter* character); - - size_t GetNumSeats() const { return seats_.size(); } - ControllableCharacter* GetPassenger(size_t idx) const { return seats_[idx].occupant; } - - ~DrivableVehicle() override; + virtual void SetRideableInput(PlayerInputFlags in); private: void InitSeats(); void UpdateUseTargetNames(); -private: - std::vector seats_; }; } \ No newline at end of file diff --git a/src/game/enterable_world.cpp b/src/game/enterable_world.cpp index 8c7e8b6..1a19fa5 100644 --- a/src/game/enterable_world.cpp +++ b/src/game/enterable_world.cpp @@ -23,8 +23,8 @@ void game::EnterableWorld::PlayerInput(Player& player, PlayerInputType type, boo // case IN_DEBUG1: // if (enabled) // { - // if (character->GetVehicle()) - // character->GetVehicle()->SetPosition({100.0f, 100.0f, 5.0f}); + // if (character->GetVehicleOld()) + // character->GetVehicleOld()->SetPosition({100.0f, 100.0f, 5.0f}); // else // character->SetPosition({100.0f, 100.0f, 5.0f}); // } diff --git a/src/game/game.cpp b/src/game/game.cpp index 21ac07e..cfc1260 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -180,7 +180,7 @@ void game::Game::MoveVehicleToWorld(DrivableVehicle& vehicle, EnterableWorld& ne auto& player_info = GetPlayerInfo(*player); auto& new_character = MovePlayerToWorld(player_info, new_world, glm::vec3(0.0f), 0.0f); - new_character.SetVehicle(&new_vehicle, i); + new_character.Ride(&new_vehicle, i); } vehicle.Remove(); diff --git a/src/game/human_character.cpp b/src/game/human_character.cpp new file mode 100644 index 0000000..d9d7ba5 --- /dev/null +++ b/src/game/human_character.cpp @@ -0,0 +1,60 @@ +#include "human_character.hpp" +#include "drivable_vehicle.hpp" + +game::HumanCharacter::HumanCharacter(World& world, const CharacterTuning& tuning) : Character(world, tuning) {} + +void game::HumanCharacter::SetRideable(Rideable* rideable, size_t seat_idx) +{ + if (rideable == rideable_ && seat_idx == seat_idx_) + return; + + if (rideable) + { + SetPosition(rideable->GetSeatOffset(seat_idx)); + EnablePhysics(false); + + Attach(rideable->GetEntity().GetEntNum()); + SetMainAnim(seat_idx == 0 ? "vehicle_drive" : "vehicle_passenger"); + SetYaw(0.5f * glm::pi()); + } + else + { + EnablePhysics(true); + + glm::vec3 seat_loc = rideable_->GetSeatOffset(seat_idx_); + seat_loc.x += glm::sign(seat_loc.x) * 0.5f; // to the side + + glm::vec3 pos = rideable_->GetEntity().GetRoot().matrix * glm::vec4(seat_loc, 1.0f); + pos.z += 0.5f; + SetPosition(pos); + + Attach(0); + SetMainAnim("idle"); + } + + rideable_ = rideable; + vehicle_ = dynamic_cast(rideable); + seat_idx_ = seat_idx; + is_driver_ = rideable && seat_idx_ == 0; + + OnRideableChanged(); + +} + +void game::HumanCharacter::Ride(Rideable* rideable, size_t seat_idx) +{ + if (rideable_) + { + rideable_->SetPassenger(seat_idx_, 0); + } + + if (rideable) + { + rideable->SetPassenger(seat_idx, this); + } +} + +game::HumanCharacter::~HumanCharacter() +{ + Ride(nullptr, 0); // exit rideable +} diff --git a/src/game/human_character.hpp b/src/game/human_character.hpp new file mode 100644 index 0000000..33623ff --- /dev/null +++ b/src/game/human_character.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "character.hpp" + +namespace game +{ + +class Rideable; +class DrivableVehicle; + +class HumanCharacter : public Character +{ +public: + using Super = Character; + + HumanCharacter(World& world, const CharacterTuning& tuning); + + void SetRideable(Rideable* rideable, size_t seat_idx); // called by Rideable!! + void Ride(Rideable* rideable, size_t seat_idx); + + Rideable* GetRideable() const { return rideable_; } + DrivableVehicle* GetVehicle() const { return vehicle_; } + + size_t GeatSeatIdx() const { return seat_idx_; } + bool IsDriver() const { return is_driver_; } + + virtual ~HumanCharacter() override; + +protected: + virtual void OnRideableChanged() {} + +private: + Rideable* rideable_ = nullptr; + DrivableVehicle* vehicle_ = nullptr; + size_t seat_idx_ = 0; + bool is_driver_ = false; +}; +} + diff --git a/src/game/npc_character.cpp b/src/game/npc_character.cpp index 2df34be..a98d9bd 100644 --- a/src/game/npc_character.cpp +++ b/src/game/npc_character.cpp @@ -6,10 +6,23 @@ #include game::NpcCharacter::NpcCharacter(World& world, const CharacterTuning& tuning) : Super(world, tuning) { - VehicleChanged(); + UpdateVehicleState(); } -void game::NpcCharacter::VehicleChanged() +void game::NpcCharacter::Update() +{ + Super::Update(); + + if (GetVehicle() && IsDriver()) + VehicleThink(); +} + +void game::NpcCharacter::OnRideableChanged() +{ + UpdateVehicleState(); +} + +void game::NpcCharacter::UpdateVehicleState() { roads_ = nullptr; path_.clear(); @@ -85,9 +98,11 @@ static float GetTurnAngle(const glm::vec3& pos, const glm::quat& rot, const glm: void game::NpcCharacter::VehicleThink() { - if (!IsDriver() || !GetVehicle() || !roads_) + if (!roads_) return; + auto vehicle = GetVehicle(); + if (vehicle_state_ == NVT_REVERSING) { if (reversing_frames_ > 0) @@ -98,13 +113,13 @@ void game::NpcCharacter::VehicleThink() { vehicle_state_ = NVT_NORMAL; stuck_counter_ = 0; - vehicle_->SetInput(game::VIN_BACKWARD, false); + vehicle->SetInput(game::VIN_BACKWARD, false); } return; } - const auto& vehicle_trans = GetVehicle()->GetRootTransform(); + const auto& vehicle_trans = vehicle->GetRootTransform(); const glm::vec3& pos = vehicle_trans.position; const glm::quat& rot = vehicle_trans.rotation; @@ -220,13 +235,13 @@ void game::NpcCharacter::VehicleThink() // BotThink(s); //}); - vehicle_->SetSteering(true, -angle); // try turn away while reversing - vehicle_->SetInputs(0); // stop - vehicle_->SetInput(game::VIN_BACKWARD, true); + vehicle->SetSteering(true, -angle); // try turn away while reversing + vehicle->SetInputs(0); // stop + vehicle->SetInput(game::VIN_BACKWARD, true); vehicle_state_ = NVT_REVERSING; reversing_frames_ = 50; // reverse for 50 frames - // GetVehicle()->SetInputs(0); // stop + // GetVehicleOld()->SetInputs(0); // stop // is_driver_ = false; // TODO: fix return; } @@ -237,11 +252,11 @@ void game::NpcCharacter::VehicleThink() last_pos_ = pos; } - GetVehicle()->SetSteering(true, angle); + vehicle->SetSteering(true, angle); game::VehicleInputFlags vin = 0; - float speed = GetVehicle()->GetSpeed(); + float speed = vehicle->GetSpeed(); // if (glm::distance(pos, target) < 10.0f) // { @@ -267,5 +282,5 @@ void game::NpcCharacter::VehicleThink() vin |= 1 << game::VIN_BACKWARD; } - GetVehicle()->SetInputs(vin); + vehicle->SetInputs(vin); } diff --git a/src/game/npc_character.hpp b/src/game/npc_character.hpp index 31aba51..7cc4fad 100644 --- a/src/game/npc_character.hpp +++ b/src/game/npc_character.hpp @@ -1,7 +1,7 @@ #pragma once #include "assets/map.hpp" -#include "controllable_character.hpp" +#include "human_character.hpp" namespace game { @@ -14,24 +14,20 @@ enum NpcVehicleThinkState NVT_REVERSING, }; -class NpcCharacter : public ControllableCharacter +class NpcCharacter : public HumanCharacter { public: - using Super = ControllableCharacter; + using Super = HumanCharacter; NpcCharacter(World& world, const CharacterTuning& tuning); - virtual void VehicleChanged() override; + virtual void Update() override; - - virtual void Update() override - { - Super::Update(); - - VehicleThink(); - } +protected: + virtual void OnRideableChanged() override; private: + void UpdateVehicleState(); void SelectNextNode(); void VehicleThink(); diff --git a/src/game/openworld.cpp b/src/game/openworld.cpp index ed7e057..f78eea6 100644 --- a/src/game/openworld.cpp +++ b/src/game/openworld.cpp @@ -174,7 +174,7 @@ void game::OpenWorld::SpawnBot() npc_tuning.clothes.push_back({ "shorts", GetRandomColor24() }); auto& driver = Spawn(npc_tuning); - driver.SetVehicle(&vehicle, 0); + driver.Ride(&vehicle, 0); } void game::OpenWorld::CreateTuningGarage(const glm::vec3& position, float yaw) diff --git a/src/game/player_character.cpp b/src/game/player_character.cpp index c2b9a26..771d1b8 100644 --- a/src/game/player_character.cpp +++ b/src/game/player_character.cpp @@ -4,10 +4,8 @@ game::PlayerCharacter::PlayerCharacter(World& world, Player& player, const CharacterTuning& tuning) : Super(world, tuning), player_(&player) { EnablePhysics(true); - VehicleChanged(); - + UpdatePlayerCamera(); SetNametag(player.GetName()); - SendUseTargetInfo(); } @@ -17,23 +15,6 @@ void game::PlayerCharacter::Update() Super::Update(); } -void game::PlayerCharacter::VehicleChanged() -{ - if (!player_) - return; - - if (vehicle_) - { - player_->SetCamera(vehicle_->GetEntNum()); - } - else - { - player_->SetCamera(GetEntNum()); - } - - UpdateInputs(); -} - void game::PlayerCharacter::ProcessInput(PlayerInputType type, bool enabled) { switch (type) @@ -53,58 +34,67 @@ void game::PlayerCharacter::DetachFromPlayer() player_ = nullptr; } -void game::PlayerCharacter::UpdateInputs() +void game::PlayerCharacter::OnRideableChanged() { - auto in = player_ ? player_->GetInput() : 0; - CharacterInputFlags c_in = 0; - VehicleInputFlags v_in = 0; + UpdatePlayerCamera(); + UpdateInputs(); +} - if (in & (1 << IN_FORWARD)) - { - c_in |= 1 << CIN_FORWARD; - v_in |= 1 << VIN_FORWARD; - } +static game::CharacterInputFlags MapPlayerInputToCharacterInput(game::PlayerInputFlags in) +{ + game::CharacterInputFlags c_in = 0; - if (in & (1 << IN_BACKWARD)) - { - c_in |= 1 << CIN_BACKWARD; - v_in |= 1 << VIN_BACKWARD; - } + if (in & (1 << game::IN_FORWARD)) + c_in |= 1 << game::CIN_FORWARD; - if (in & (1 << IN_LEFT)) - { - c_in |= 1 << CIN_LEFT; - v_in |= 1 << VIN_LEFT; - } + if (in & (1 << game::IN_BACKWARD)) + c_in |= 1 << game::CIN_BACKWARD; - if (in & (1 << IN_RIGHT)) - { - c_in |= 1 << CIN_RIGHT; - v_in |= 1 << VIN_RIGHT; - } + if (in & (1 << game::IN_LEFT)) + c_in |= 1 << game::CIN_LEFT; - if (in & (1 << IN_JUMP)) - { - c_in |= 1 << CIN_JUMP; - } - - if (in & (1 << IN_SPRINT)) - { - c_in |= 1 << CIN_SPRINT; - } + if (in & (1 << game::IN_RIGHT)) + c_in |= 1 << game::CIN_RIGHT; - if (vehicle_) - { - SetInputs(0); + if (in & (1 << game::IN_JUMP)) + c_in |= 1 << game::CIN_JUMP; - if (is_driver_) - { - vehicle_->SetInputs(v_in); - } + if (in & (1 << game::IN_SPRINT)) + c_in |= 1 << game::CIN_SPRINT; + + return c_in; +} + +void game::PlayerCharacter::UpdatePlayerCamera() +{ + if (!player_) + return; + + if (auto rideable = GetRideable(); rideable) + { + player_->SetCamera(rideable->GetEntity().GetEntNum()); } else { - SetInputs(c_in); + player_->SetCamera(GetEntNum()); + } +} + + +void game::PlayerCharacter::UpdateInputs() +{ + auto in = player_ ? player_->GetInput() : 0; + + if (auto rideable = GetRideable(); rideable) + { + SetInputs(0); + + if (IsDriver()) + rideable->SetRideableInput(in); + } + else + { + SetInputs(MapPlayerInputToCharacterInput(in)); } } @@ -142,8 +132,9 @@ void game::PlayerCharacter::UseChanged(bool enabled) { if (!use_target_) { - if (vehicle_ && enabled) - SetVehicle(nullptr, 0);// no use target and in vehicle -> exit + // exit rideable if not target + if (enabled && GetRideable()) + Ride(nullptr, 0); return; } diff --git a/src/game/player_character.hpp b/src/game/player_character.hpp index ec5cda4..f139c6b 100644 --- a/src/game/player_character.hpp +++ b/src/game/player_character.hpp @@ -1,4 +1,4 @@ -#include "controllable_character.hpp" +#include "human_character.hpp" #include "drivable_vehicle.hpp" #include "player.hpp" @@ -7,24 +7,26 @@ namespace game { -class PlayerCharacter : public ControllableCharacter +class PlayerCharacter : public HumanCharacter { public: - using Super = ControllableCharacter; + using Super = HumanCharacter; PlayerCharacter(World& world, Player& player, const CharacterTuning& tuning); virtual void Update() override; - virtual void VehicleChanged() override; - void ProcessInput(PlayerInputType type, bool enabled); void DetachFromPlayer(); Player* GetPlayer() const { return player_; } +protected: + virtual void OnRideableChanged() override; + private: + void UpdatePlayerCamera(); void UpdateInputs(); void UpdateUseTarget(); diff --git a/src/game/rideable.cpp b/src/game/rideable.cpp new file mode 100644 index 0000000..8d9b332 --- /dev/null +++ b/src/game/rideable.cpp @@ -0,0 +1,69 @@ +#include "rideable.hpp" + +#include + +game::Rideable::Rideable(Entity& entity, RideableType type) : entity_(entity), type_(type) {} + +void game::Rideable::SetPassenger(size_t seat_idx, HumanCharacter* passenger) +{ + if (seat_idx >= seats_.size()) + throw std::runtime_error("Invalid seat index"); + + auto& seat = seats_[seat_idx]; + + if (seat.passenger == passenger) + return; // already sitting here + + if (seat.passenger) + { + seat.passenger->SetRideable(nullptr, 0); // remove current passenger + } + + seat.passenger = passenger; + + if (passenger) + { + passenger->SetRideable(this, seat_idx); + } + + OnPassengerChanged(seat_idx, passenger); +} + +game::HumanCharacter* game::Rideable::GetPassenger(size_t seat_idx) +{ + if (seat_idx >= seats_.size()) + return nullptr; + + return seats_[seat_idx].passenger; +} + +const glm::vec3& game::Rideable::GetSeatOffset(size_t seat_idx) +{ + if (seat_idx >= seats_.size()) + throw std::runtime_error("Invalid seat index"); + + return seats_[seat_idx].offset; +} + +void game::Rideable::KickAll() +{ + for (size_t i = 0; i < seats_.size(); ++i) + { + if (seats_[i].passenger) + SetPassenger(i, nullptr); + } +} + +game::Rideable::~Rideable() +{ + // kick passengers + KickAll(); +} + +size_t game::Rideable::AddSeat(const glm::vec3& offset) +{ + RideableSeat seat{}; + seat.offset = offset; + seats_.emplace_back(seat); + return seats_.size() - 1; +} diff --git a/src/game/rideable.hpp b/src/game/rideable.hpp new file mode 100644 index 0000000..7196f17 --- /dev/null +++ b/src/game/rideable.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "human_character.hpp" +#include "player_input.hpp" + +namespace game +{ + +enum RideableType +{ + RIDEABLE_NONE, + RIDEABLE_VEHICLE, + RIDEABLE_ANIMAL, +}; + +struct RideableSeat +{ + glm::vec3 offset; + HumanCharacter* passenger; +}; + +class Rideable +{ +public: + Rideable(Entity& entity, RideableType type); + + void SetPassenger(size_t seat_idx, HumanCharacter* passenger); + HumanCharacter* GetPassenger(size_t seat_idx); + const glm::vec3& GetSeatOffset(size_t seat_idx); + size_t GetNumSeats() const { return seats_.size(); } + void KickAll(); + + virtual void SetRideableInput(PlayerInputFlags in) {} + virtual void SetRideableYaw(float yaw) {} + + RideableType GetRideableType() const { return type_; } + + Entity& GetEntity() { return entity_; } + const Entity& GetEntity() const { return entity_; } + + virtual ~Rideable(); + +protected: + size_t AddSeat(const glm::vec3& offset); + virtual void OnPassengerChanged(size_t seat_idx, HumanCharacter* passenger) {} + +private: + Entity& entity_; + RideableType type_; + std::vector seats_; +}; + + +} \ No newline at end of file diff --git a/src/game/tuning_world.hpp b/src/game/tuning_world.hpp index 83d83a2..5c230fa 100644 --- a/src/game/tuning_world.hpp +++ b/src/game/tuning_world.hpp @@ -29,8 +29,6 @@ public: private: void Setup(); - void AddTuningGroupSelect(game::RemoteMenu& menu, const VehicleTuningGroup& group); - void OpenMainTuningMenu(); void OpenGroupMenu(const VehicleTuningGroup& group); std::string GetCurrentPartId(const std::string& group_id); diff --git a/src/game/world.cpp b/src/game/world.cpp index eadda58..72ebc48 100644 --- a/src/game/world.cpp +++ b/src/game/world.cpp @@ -112,11 +112,11 @@ struct UseTargetAabbCallback : public btBroadphaseAabbCallback UseTargetAabbCallback(game::PlayerCharacter& character, game::UseTargetQueryResult& res) : character(character), pos(character.GetRoot().GetGlobalPosition()), best_res(res) { - auto vehicle = character.GetVehicle(); - if (vehicle) + auto rideable_entity = dynamic_cast(character.GetRideable()); + if (rideable_entity) { radius = 5.0f; - pos = vehicle->GetRoot().GetGlobalPosition(); + pos = rideable_entity->GetRoot().GetGlobalPosition(); } }