Generalize rideables
This commit is contained in:
parent
8e83f3635a
commit
c136ccf26d
@ -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"
|
||||
|
||||
@ -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<float>());
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@ -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<uint32_t>(seat_idx), position, std::string());
|
||||
}
|
||||
|
||||
UpdateUseTargetNames();
|
||||
|
||||
@ -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<VehicleSeat> seats_;
|
||||
};
|
||||
|
||||
}
|
||||
@ -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});
|
||||
// }
|
||||
|
||||
@ -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();
|
||||
|
||||
60
src/game/human_character.cpp
Normal file
60
src/game/human_character.cpp
Normal file
@ -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<float>());
|
||||
}
|
||||
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<DrivableVehicle*>(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
|
||||
}
|
||||
39
src/game/human_character.hpp
Normal file
39
src/game/human_character.hpp
Normal file
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@ -6,10 +6,23 @@
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -174,7 +174,7 @@ void game::OpenWorld::SpawnBot()
|
||||
npc_tuning.clothes.push_back({ "shorts", GetRandomColor24() });
|
||||
|
||||
auto& driver = Spawn<NpcCharacter>(npc_tuning);
|
||||
driver.SetVehicle(&vehicle, 0);
|
||||
driver.Ride(&vehicle, 0);
|
||||
}
|
||||
|
||||
void game::OpenWorld::CreateTuningGarage(const glm::vec3& position, float yaw)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
69
src/game/rideable.cpp
Normal file
69
src/game/rideable.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "rideable.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
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;
|
||||
}
|
||||
54
src/game/rideable.hpp
Normal file
54
src/game/rideable.hpp
Normal file
@ -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<RideableSeat> seats_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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<game::Entity*>(character.GetRideable());
|
||||
if (rideable_entity)
|
||||
{
|
||||
radius = 5.0f;
|
||||
pos = vehicle->GetRoot().GetGlobalPosition();
|
||||
pos = rideable_entity->GetRoot().GetGlobalPosition();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user