diff --git a/src/game/drivable_vehicle.hpp b/src/game/drivable_vehicle.hpp index d65ddf5..cb454ec 100644 --- a/src/game/drivable_vehicle.hpp +++ b/src/game/drivable_vehicle.hpp @@ -22,6 +22,9 @@ public: 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; private: diff --git a/src/game/enterable_world.cpp b/src/game/enterable_world.cpp index 36ef069..5bf5d96 100644 --- a/src/game/enterable_world.cpp +++ b/src/game/enterable_world.cpp @@ -1,5 +1,7 @@ #include "enterable_world.hpp" + #include "player_character.hpp" +#include "drivable_vehicle.hpp" game::EnterableWorld::EnterableWorld(std::string mapname) : World(std::move(mapname)) {} @@ -18,15 +20,15 @@ void game::EnterableWorld::PlayerInput(Player& player, PlayerInputType type, boo switch (type) { - case IN_DEBUG1: - if (enabled) - { - if (character->GetVehicle()) - character->GetVehicle()->SetPosition({100.0f, 100.0f, 5.0f}); - else - character->SetPosition({100.0f, 100.0f, 5.0f}); - } - break; + // case IN_DEBUG1: + // if (enabled) + // { + // if (character->GetVehicle()) + // character->GetVehicle()->SetPosition({100.0f, 100.0f, 5.0f}); + // else + // character->SetPosition({100.0f, 100.0f, 5.0f}); + // } + // break; default: character->ProcessInput(type, enabled); @@ -63,6 +65,49 @@ game::PlayerCharacter& game::EnterableWorld::MovePlayerToWorld(Player& player, E return new_character; } +void game::EnterableWorld::MoveVehicleToWorld(DrivableVehicle& vehicle, EnterableWorld& new_world, const glm::vec3& pos, + float yaw) +{ + if (&vehicle.GetWorld() != this) + throw std::runtime_error("Attempt to move vehicle from other world"); + + auto& tuning = vehicle.GetTuning(); + auto& new_vehicle = new_world.Spawn(tuning); + new_vehicle.SetPosition(pos); + // TODO: yaw + + // move passengers + size_t num_seats = vehicle.GetNumSeats(); + for (size_t i = 0; i < num_seats; ++i) + { + auto passenger = vehicle.GetPassenger(i); + if (!passenger) + continue; // empty seat + + auto player_passenger = dynamic_cast(passenger); + if (!player_passenger) + continue; // not player but npc, will be ejected automatically upon vehicle deletion + + auto player = player_passenger->GetPlayer(); + if (!player) + continue; // moved already or sth + + auto& new_character = MovePlayerToWorld(*player, new_world, glm::vec3(0.0f), 0.0f); + new_character.SetVehicle(&new_vehicle, i); + } + + vehicle.Remove(); +} + +game::PlayerCharacter* game::EnterableWorld::GetPlayerCharacter(Player& player) +{ + auto it = player_characters_.find(&player); + if (it == player_characters_.end()) + return nullptr; + + return it->second; +} + game::PlayerCharacter& game::EnterableWorld::CreatePlayerCharacter(Player& player, const CharacterTuning& tuning, const glm::vec3& position, float yaw) { RemovePlayerCharacter(player); @@ -77,10 +122,10 @@ game::PlayerCharacter& game::EnterableWorld::CreatePlayerCharacter(Player& playe void game::EnterableWorld::RemovePlayerCharacter(Player& player) { - auto it = player_characters_.find(&player); - if (it != player_characters_.end()) + auto character = GetPlayerCharacter(player); + if (character) { - it->second->Remove(); - player_characters_.erase(it); + character->DetachFromPlayer(); + character->Remove(); } } diff --git a/src/game/enterable_world.hpp b/src/game/enterable_world.hpp index 27a1f34..d536374 100644 --- a/src/game/enterable_world.hpp +++ b/src/game/enterable_world.hpp @@ -1,13 +1,14 @@ #pragma once #include "world.hpp" -#include "drivable_vehicle.hpp" namespace game { class Player; class PlayerCharacter; +class CharacterTuning; +class DrivableVehicle; class EnterableWorld : public World { @@ -22,6 +23,9 @@ public: // moves PlayerCharacter& MovePlayerToWorld(Player& player, EnterableWorld& new_world, const glm::vec3& pos, float yaw); + void MoveVehicleToWorld(DrivableVehicle& vehicle, EnterableWorld& new_world, const glm::vec3& pos, float yaw); + + PlayerCharacter* GetPlayerCharacter(Player& player); private: PlayerCharacter& CreatePlayerCharacter(Player& player, const CharacterTuning& tuning, const glm::vec3& position, float yaw); diff --git a/src/game/entity.hpp b/src/game/entity.hpp index 166469e..13fcc72 100644 --- a/src/game/entity.hpp +++ b/src/game/entity.hpp @@ -24,6 +24,8 @@ public: net::EntNum GetEntNum() const { return entnum_; } net::EntType GetViewType() const { return viewtype_; } + World& GetWorld() const { return world_; } + virtual void SendInitData(Player& player, net::OutMessage& msg) const; virtual void Update(); diff --git a/src/game/game.cpp b/src/game/game.cpp index b41d401..915a563 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -2,9 +2,10 @@ #include "openworld.hpp" #include "player.hpp" +#include "player_character.hpp" -static constexpr glm::vec3 openworld_spawn(100.0f, 100.0f, 5.0f); -static constexpr glm::vec3 test_spawn(0.0f, 0.0f, 5.0f); +static constexpr glm::vec3 openworld_spawn(100.0f, 100.0f, 1.0f); +static constexpr glm::vec3 test_spawn(0.0f, 0.0f, 1.0f); static uint32_t GetRandomColor24() { @@ -75,11 +76,11 @@ void game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled) if (player_info.world == openworld_.get()) { - MovePlayerToWorld(player_info, testworld_.get(), test_spawn, 0.0f); + MovePlayerToWorld(player_info, testworld_.get(), test_spawn, 0.0f, true); } else { - MovePlayerToWorld(player_info, openworld_.get(), openworld_spawn, 0.0f); + MovePlayerToWorld(player_info, openworld_.get(), openworld_spawn, 0.0f, true); } break; @@ -115,9 +116,24 @@ void game::Game::BroadcastChat(const std::string& text) } void game::Game::MovePlayerToWorld(PlayerGameInfo& player_info, EnterableWorld* new_world, const glm::vec3& pos, - float yaw) + float yaw, bool with_vehicle) { - player_info.world->MovePlayerToWorld(player_info.player, *new_world, pos, yaw); + auto& player = player_info.player; + auto& world = *player_info.world; + + DrivableVehicle* vehicle = nullptr; + + if (with_vehicle) + { + auto character = world.GetPlayerCharacter(player); + vehicle = character->GetVehicle(); + } + + if (vehicle) + world.MoveVehicleToWorld(*vehicle, *new_world, pos, yaw); + else + world.MovePlayerToWorld(player, *new_world, pos, yaw); + player_info.world = new_world; } diff --git a/src/game/game.hpp b/src/game/game.hpp index 794ad08..da1408f 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -34,7 +34,7 @@ public: private: void BroadcastChat(const std::string& text); - void MovePlayerToWorld(PlayerGameInfo& player_info, EnterableWorld* new_world, const glm::vec3& pos, float yaw); + void MovePlayerToWorld(PlayerGameInfo& player_info, EnterableWorld* new_world, const glm::vec3& pos, float yaw, bool with_vehicle = false); EnterableWorld* FindPlayerWorld(Player& player) const; diff --git a/src/game/player_character.cpp b/src/game/player_character.cpp index eb9b3a4..1a1d092 100644 --- a/src/game/player_character.cpp +++ b/src/game/player_character.cpp @@ -1,7 +1,7 @@ #include "player_character.hpp" #include "world.hpp" -game::PlayerCharacter::PlayerCharacter(World& world, Player& player, const CharacterTuning& tuning) : Super(world, tuning), player_(player) +game::PlayerCharacter::PlayerCharacter(World& world, Player& player, const CharacterTuning& tuning) : Super(world, tuning), player_(&player) { EnablePhysics(true); VehicleChanged(); @@ -18,13 +18,16 @@ void game::PlayerCharacter::Update() void game::PlayerCharacter::VehicleChanged() { + if (!player_) + return; + if (vehicle_) { - player_.SetCamera(vehicle_->GetEntNum()); + player_->SetCamera(vehicle_->GetEntNum()); } else { - player_.SetCamera(GetEntNum()); + player_->SetCamera(GetEntNum()); } UpdateInputs(); @@ -59,9 +62,14 @@ void game::PlayerCharacter::ProcessInput(PlayerInputType type, bool enabled) } } +void game::PlayerCharacter::DetachFromPlayer() +{ + player_ = nullptr; +} + void game::PlayerCharacter::UpdateInputs() { - auto in = player_.GetInput(); + auto in = player_ ? player_->GetInput() : 0; CharacterInputFlags c_in = 0; VehicleInputFlags v_in = 0; diff --git a/src/game/player_character.hpp b/src/game/player_character.hpp index 0257f6b..60caac8 100644 --- a/src/game/player_character.hpp +++ b/src/game/player_character.hpp @@ -20,12 +20,16 @@ public: void ProcessInput(PlayerInputType type, bool enabled); + void DetachFromPlayer(); + + Player* GetPlayer() const { return player_; } + private: void UpdateInputs(); void UpdateUseTarget(); private: - Player& player_; + Player* player_; }; diff --git a/src/game/vehicle.hpp b/src/game/vehicle.hpp index 8b9f912..a158316 100644 --- a/src/game/vehicle.hpp +++ b/src/game/vehicle.hpp @@ -58,6 +58,7 @@ public: const std::string& GetModelName() const { return tuning_.model; } const std::shared_ptr& GetModel() const { return model_; } + const VehicleTuning& GetTuning() const { return tuning_; } virtual ~Vehicle();