Add moving of vehicles

This commit is contained in:
tovjemam 2026-03-21 20:33:10 +01:00
parent da4eaae9ec
commit d853f7c53c
9 changed files with 109 additions and 26 deletions

View File

@ -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:

View File

@ -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<DrivableVehicle>(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<PlayerCharacter*>(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();
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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_;
};

View File

@ -58,6 +58,7 @@ public:
const std::string& GetModelName() const { return tuning_.model; }
const std::shared_ptr<const assets::VehicleModel>& GetModel() const { return model_; }
const VehicleTuning& GetTuning() const { return tuning_; }
virtual ~Vehicle();