Compare commits

..

7 Commits

29 changed files with 432 additions and 227 deletions

View File

@ -130,6 +130,8 @@ set(SERVER_ONLY_SOURCES
"src/game/destroyed_object.cpp"
"src/game/drivable_vehicle.hpp"
"src/game/drivable_vehicle.cpp"
"src/game/enterable_world.hpp"
"src/game/enterable_world.cpp"
"src/game/entity.hpp"
"src/game/entity.cpp"
"src/game/game.hpp"

View File

@ -1,2 +1,4 @@
# FekalniGtacko
![logo](res/houbymore.png)

BIN
res/houbymore.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

View File

@ -95,7 +95,7 @@ int assets::MapLoader::GetPercent() const
return 10;
case ML_LOAD_MODELS:
return 60 + models_.size() * 30 / model_names_.size();
return 60 + (model_names_.size() > 0 ? (models_.size() * 30 / model_names_.size()) : 30);
case ML_STRUCTS:
return 90;

View File

@ -4,10 +4,10 @@
#include "utils/math.hpp"
#include "world.hpp"
game::Character::Character(World& world, const CharacterInfo& info)
: Super(world, net::ET_CHARACTER), shape_(info.shape), bt_shape_(shape_.radius, shape_.height)
game::Character::Character(World& world, const CharacterTuning& tuning)
: Super(world, net::ET_CHARACTER), tuning_(tuning), bt_shape_(tuning_.shape.radius, tuning_.shape.height)
{
z_offset_ = shape_.height * 0.5f + shape_.radius - 0.05f;
z_offset_ = tuning_.shape.height * 0.5f + tuning_.shape.radius - 0.05f;
sk_ = SkeletonInstance(assets::CacheManager::GetSkeleton("data/human.sk"), &root_);
animstate_.idle_anim_idx = GetAnim("idle");
@ -53,8 +53,8 @@ void game::Character::SendInitData(Player& player, net::OutMessage& msg) const
Super::SendInitData(player, msg);
// write clothes
msg.Write<net::NumClothes>(clothes_.size());
for (const auto& clothes : clothes_)
msg.Write<net::NumClothes>(tuning_.clothes.size());
for (const auto& clothes : tuning_.clothes)
{
msg.Write(net::ClothesName(clothes.name));
net::WriteRGB(msg, clothes.color);
@ -120,11 +120,6 @@ void game::Character::SetPosition(const glm::vec3& position)
SyncControllerTransform();
}
void game::Character::AddClothes(std::string name, const glm::vec3& color)
{
clothes_.emplace_back(std::move(name), color);
}
void game::Character::SetMainAnim(const std::string& anim_name)
{
animstate_.idle_anim_idx = GetAnim(anim_name);

View File

@ -6,6 +6,7 @@
#include "character_anim_state.hpp"
#include "character_sync.hpp"
#include "entity.hpp"
#include "character_tuning.hpp"
namespace game
{
@ -22,25 +23,6 @@ enum CharacterInputType
CIN_SPRINT,
};
struct CapsuleShape
{
float radius;
float height;
CapsuleShape(float radius, float height) : radius(radius), height(height) {}
};
struct CharacterInfo
{
CapsuleShape shape = CapsuleShape(0.3f, 0.75f);
};
struct CharacterClothes
{
std::string name;
glm::vec3 color;
};
class CharacterPhysicsController
{
public:
@ -65,11 +47,13 @@ class Character : public Entity
public:
using Super = Entity;
Character(World& world, const CharacterInfo& info);
Character(World& world, const CharacterTuning& tuning);
virtual void Update() override;
virtual void SendInitData(Player& player, net::OutMessage& msg) const override;
const CharacterTuning& GetTuning() const { return tuning_; }
void EnablePhysics(bool enable);
void SetInput(CharacterInputType type, bool enable);
@ -80,8 +64,6 @@ public:
void SetPosition(const glm::vec3& position);
void AddClothes(std::string name, const glm::vec3& color);
void SetMainAnim(const std::string& anim_name);
~Character() override = default;
@ -100,7 +82,7 @@ private:
assets::AnimIdx GetAnim(const std::string& name) const;
private:
CapsuleShape shape_;
CharacterTuning tuning_;
// glm::vec3 position_ = glm::vec3(0.0f);
// glm::vec3 velocity_ = glm::vec3(0.0f);
@ -121,8 +103,6 @@ private:
CharacterSyncState sync_[2];
size_t sync_current_ = 0;
std::vector<CharacterClothes> clothes_;
};
} // namespace game

View File

@ -0,0 +1,30 @@
#pragma once
#include <string>
#include <vector>
namespace game
{
struct CharacterShape
{
float radius;
float height;
CharacterShape(float radius, float height) : radius(radius), height(height) {}
};
struct CharacterConfigClothes
{
std::string name;
uint32_t color = 0xFFFFFF;
};
struct CharacterTuning
{
CharacterShape shape = CharacterShape(0.3f, 0.75f);
std::vector<CharacterConfigClothes> clothes;
};
}

View File

@ -1,7 +1,7 @@
#include "controllable_character.hpp"
#include "drivable_vehicle.hpp"
game::ControllableCharacter::ControllableCharacter(World& world) : Character(world, CharacterInfo{}) {}
game::ControllableCharacter::ControllableCharacter(World& world, const CharacterTuning& tuning) : Character(world, tuning) {}
void game::ControllableCharacter::SetVehicle(DrivableVehicle* vehicle, uint32_t seat)
{

View File

@ -12,7 +12,7 @@ class ControllableCharacter : public Character
public:
using Super = Character;
ControllableCharacter(World& world);
ControllableCharacter(World& world, const CharacterTuning& tuning);
void SetVehicle(DrivableVehicle* vehicle, uint32_t seat);

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

@ -0,0 +1,131 @@
#include "enterable_world.hpp"
#include "player_character.hpp"
#include "drivable_vehicle.hpp"
game::EnterableWorld::EnterableWorld(std::string mapname) : World(std::move(mapname)) {}
game::PlayerCharacter& game::EnterableWorld::InsertPlayer(Player& player, const CharacterTuning& tuning, const glm::vec3& pos, float yaw)
{
return CreatePlayerCharacter(player, tuning, pos, yaw);
}
void game::EnterableWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled)
{
auto it = player_characters_.find(&player);
if (it == player_characters_.end())
return;
auto character = it->second;
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;
default:
character->ProcessInput(type, enabled);
break;
}
}
void game::EnterableWorld::PlayerViewAnglesChanged(Player& player, float yaw, float pitch)
{
auto it = player_characters_.find(&player);
if (it == player_characters_.end())
return;
auto character = it->second;
character->SetForwardYaw(yaw);
}
void game::EnterableWorld::RemovePlayer(Player& player)
{
RemovePlayerCharacter(player);
}
game::PlayerCharacter& game::EnterableWorld::MovePlayerToWorld(Player& player, EnterableWorld& new_world, const glm::vec3& pos, float yaw)
{
auto old_character = player_characters_.at(&player);
auto& tuning = old_character->GetTuning();
RemovePlayer(player);
player.SetWorld(&new_world);
auto& new_character = new_world.InsertPlayer(player, tuning, pos, yaw);
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);
auto& character = Spawn<PlayerCharacter>(player, tuning);
character.SetPosition(position);
character.SetYaw(yaw);
player_characters_[&player] = &character;
return character;
}
void game::EnterableWorld::RemovePlayerCharacter(Player& player)
{
auto character = GetPlayerCharacter(player);
if (character)
{
character->DetachFromPlayer();
character->Remove();
}
}

View File

@ -0,0 +1,41 @@
#pragma once
#include "world.hpp"
namespace game
{
class Player;
class PlayerCharacter;
class CharacterTuning;
class DrivableVehicle;
class EnterableWorld : public World
{
public:
EnterableWorld(std::string mapname);
// events
virtual PlayerCharacter& InsertPlayer(Player& player, const CharacterTuning& tuning, const glm::vec3& pos, float yaw);
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled);
virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch);
virtual void RemovePlayer(Player& player);
// 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);
void RemovePlayerCharacter(Player& player);
private:
std::map<Player*, PlayerCharacter*> player_characters_;
};
}

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

@ -1,47 +1,147 @@
#include "game.hpp"
#include "player.hpp"
#include "openworld.hpp"
#include "player.hpp"
#include "player_character.hpp"
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()
{
uint8_t r, g, b;
r = rand() % 256;
g = rand() % 256;
b = rand() % 256;
return (b << 16) | (g << 8) | r;
}
game::Game::Game()
{
default_world_ = std::make_shared<OpenWorld>();
openworld_ = std::make_shared<OpenWorld>();
all_worlds_.push_back(openworld_.get());
testworld_ = std::make_shared<EnterableWorld>("testarena");
all_worlds_.push_back(testworld_.get());
}
void game::Game::Update()
{
default_world_->Update(40);
for (auto world : all_worlds_)
{
world->Update(40);
}
}
void game::Game::FinishFrame()
{
default_world_->FinishFrame();
for (auto world : all_worlds_)
{
world->FinishFrame();
}
}
void game::Game::PlayerJoined(Player& player)
{
player.SetWorld(default_world_);
players_.insert(&player);
BroadcastChat(player.GetName() + "^r se připoojil jupí jupí jupííí");
players_.insert({&player, PlayerGameInfo(player)});
auto& player_info = players_.at(&player);
player_info.world = openworld_.get();
player.SetWorld(openworld_.get());
CharacterTuning tuning{};
tuning.clothes.push_back({"tshirt", GetRandomColor24()});
tuning.clothes.push_back({"shorts", GetRandomColor24()});
openworld_->InsertPlayer(player, tuning, openworld_spawn, 0.0f);
}
void game::Game::PlayerViewAnglesChanged(Player& player, float yaw, float pitch)
{
auto world = FindPlayerWorld(player);
if (world)
world->PlayerViewAnglesChanged(player, yaw, pitch);
}
void game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled)
{
switch (type)
{
case IN_DEBUG2: {
if (!enabled)
return;
auto& player_info = players_.at(&player);
if (player_info.world == openworld_.get())
{
MovePlayerToWorld(player_info, testworld_.get(), test_spawn, 0.0f, true);
}
else
{
MovePlayerToWorld(player_info, openworld_.get(), openworld_spawn, 0.0f, true);
}
break;
}
default: {
auto world = FindPlayerWorld(player);
if (world)
world->PlayerInput(player, type, enabled);
break;
}
}
}
void game::Game::PlayerLeft(Player& player)
{
players_.erase(&player);
BroadcastChat(player.GetName() + "^r se vodpojil zmrd");
}
auto world = FindPlayerWorld(player);
if (world)
world->RemovePlayer(player);
bool game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled)
{
return false; // not handled here
players_.erase(&player);
BroadcastChat(player.GetName() + "^r se vodpojil zmrd");
}
void game::Game::BroadcastChat(const std::string& text)
{
for (auto player : players_)
for (auto& [player, info] : players_)
{
player->SendChat(text);
}
}
void game::Game::MovePlayerToWorld(PlayerGameInfo& player_info, EnterableWorld* new_world, const glm::vec3& pos,
float yaw, bool with_vehicle)
{
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;
}
game::EnterableWorld* game::Game::FindPlayerWorld(Player& player) const
{
auto it = players_.find(&player);
if (it == players_.end())
return nullptr;
return it->second.world;
}

View File

@ -1,15 +1,23 @@
#pragma once
#include <map>
#include <set>
#include "world.hpp"
#include "enterable_world.hpp"
#include "openworld.hpp"
namespace game
{
class Player;
struct PlayerGameInfo
{
Player& player;
EnterableWorld* world = nullptr;
PlayerGameInfo(Player& player) : player(player) {}
};
class Game
{
public:
@ -19,15 +27,23 @@ public:
void FinishFrame();
void PlayerJoined(Player& player);
void PlayerViewAnglesChanged(Player& player, float yaw, float pitch);
void PlayerInput(Player& player, PlayerInputType type, bool enabled);
void PlayerLeft(Player& player);
bool PlayerInput(Player& player, PlayerInputType type, bool enabled);
private:
void BroadcastChat(const std::string& text);
void MovePlayerToWorld(PlayerGameInfo& player_info, EnterableWorld* new_world, const glm::vec3& pos, float yaw, bool with_vehicle = false);
EnterableWorld* FindPlayerWorld(Player& player) const;
private:
std::shared_ptr<World> default_world_;
std::set<Player*> players_;
std::shared_ptr<OpenWorld> openworld_;
std::shared_ptr<EnterableWorld> testworld_;
std::vector<World*> all_worlds_; // for common update etc.
std::map<Player*, PlayerGameInfo> players_;
};

View File

@ -5,7 +5,7 @@
#include <array>
#include <iostream>
game::NpcCharacter::NpcCharacter(World& world) : Super(world) {
game::NpcCharacter::NpcCharacter(World& world, const CharacterTuning& tuning) : Super(world, tuning) {
VehicleChanged();
}

View File

@ -13,7 +13,7 @@ class NpcCharacter : public ControllableCharacter
public:
using Super = ControllableCharacter;
NpcCharacter(World& world);
NpcCharacter(World& world, const CharacterTuning& tuning);
virtual void VehicleChanged() override;

View File

@ -45,10 +45,8 @@ static uint32_t GetRandomColor24()
return (b << 16) | (g << 8) | r;
}
game::OpenWorld::OpenWorld() : World("openworld")
game::OpenWorld::OpenWorld() : EnterableWorld("openworld")
{
srand(time(NULL));
// spawn bots
for (size_t i = 0; i < 100; ++i)
{
@ -81,97 +79,6 @@ game::OpenWorld::OpenWorld() : World("openworld")
}
void game::OpenWorld::Update(int64_t delta_time)
{
World::Update(delta_time);
}
void game::OpenWorld::PlayerJoined(Player& player)
{
CreatePlayerCharacter(player);
}
void game::OpenWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled)
{
auto character = player_characters_.at(&player);
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_DEBUG2:
if (enabled)
CreatePlayerCharacter(player);
break;
default:
character->ProcessInput(type, enabled);
break;
}
}
void game::OpenWorld::PlayerViewAnglesChanged(Player& player, float yaw, float pitch)
{
auto character = player_characters_.at(&player);
character->SetForwardYaw(yaw);
}
void game::OpenWorld::PlayerLeft(Player& player)
{
RemovePlayerCharacter(player);
}
void game::OpenWorld::DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col)
{
auto& destroyed_obj = Spawn<DestroyedObject>(std::move(col));
Schedule(120000, [this, num] {
RespawnObj(num);
});
}
template <class T, typename... TArgs>
static T& SpawnRandomCharacter(game::OpenWorld& world, TArgs&&... args)
{
auto& character = world.Spawn<T>(std::forward<TArgs>(args)...);
// add clothes
character.AddClothes("tshirt", GetRandomColor());
character.AddClothes("shorts", GetRandomColor());
return character;
}
void game::OpenWorld::CreatePlayerCharacter(Player& player)
{
RemovePlayerCharacter(player);
auto& character = SpawnRandomCharacter<PlayerCharacter>(*this, player);
// character.SetNametag("player (" + std::to_string(character.GetEntNum()) + ")");
character.SetPosition({100.0f, 100.0f, 5.0f});
player_characters_[&player] = &character;
}
void game::OpenWorld::RemovePlayerCharacter(Player& player)
{
auto it = player_characters_.find(&player);
if (it != player_characters_.end())
{
it->second->Remove();
player_characters_.erase(it);
}
}
game::DrivableVehicle& game::OpenWorld::SpawnRandomVehicle()
{
game::VehicleTuning tuning;
@ -198,6 +105,10 @@ void game::OpenWorld::SpawnBot()
auto& vehicle = SpawnRandomVehicle();
vehicle.SetPosition(roads->nodes[start_node].position + glm::vec3{0.0f, 0.0f, 5.0f});
auto& driver = SpawnRandomCharacter<NpcCharacter>(*this);
CharacterTuning npc_tuning;
npc_tuning.clothes.push_back({ "tshirt", GetRandomColor24() });
npc_tuning.clothes.push_back({ "shorts", GetRandomColor24() });
auto& driver = Spawn<NpcCharacter>(npc_tuning);
driver.SetVehicle(&vehicle, 0);
}

View File

@ -1,42 +1,21 @@
#pragma once
#include "world.hpp"
#include "vehicle.hpp"
#include "character.hpp"
#include "usable.hpp"
#include "drivable_vehicle.hpp"
#include <optional>
#include "enterable_world.hpp"
#include "npc_character.hpp"
namespace game
{
class PlayerCharacter;
class NpcCharacter;
class OpenWorld : public World
class OpenWorld : public EnterableWorld
{
public:
OpenWorld();
virtual void Update(int64_t delta_time) override;
virtual void PlayerJoined(Player& player) override;
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) override;
virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch) override;
virtual void PlayerLeft(Player& player) override;
virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col) override;
private:
void CreatePlayerCharacter(Player& player);
void RemovePlayerCharacter(Player& player);
private:
game::DrivableVehicle& SpawnRandomVehicle();
void SpawnBot();
private:
std::map<Player*, PlayerCharacter*> player_characters_;
std::vector<NpcCharacter*> npcs_;
};

View File

@ -6,6 +6,7 @@
#include <glm/gtx/norm.hpp>
#include "world.hpp"
#include "game.hpp"
game::Player::Player(Game& game, std::string name) : game_(game), name_(std::move(name))
{
@ -29,11 +30,13 @@ bool game::Player::ProcessMsg(net::MessageType type, net::InMessage& msg)
void game::Player::Update()
{
if (world_.get() != known_world_)
if (world_ != known_world_)
{
SendWorldMsg();
known_world_ = world_.get();
known_world_ = world_;
known_ents_.clear();
return; // send updates next frame
}
if (world_)
@ -43,18 +46,12 @@ void game::Player::Update()
}
}
void game::Player::SetWorld(std::shared_ptr<World> world)
void game::Player::SetWorld(World* world)
{
if (world == world_)
return;
if (world_)
world_->PlayerLeft(*this);
world_ = std::move(world);
if (world_)
world_->PlayerJoined(*this);
world_ = world;
}
void game::Player::SetCamera(net::EntNum entnum)
@ -74,7 +71,6 @@ void game::Player::SendChat(const std::string& text)
game::Player::~Player()
{
SetWorld(nullptr);
game_.PlayerLeft(*this);
}
@ -247,9 +243,7 @@ bool game::Player::ProcessViewAnglesMsg(net::InMessage& msg)
view_yaw_ = yaw_q.Decode();
view_pitch_ = pitch_q.Decode();
if (world_)
world_->PlayerViewAnglesChanged(*this, view_yaw_, view_pitch_);
game_.PlayerViewAnglesChanged(*this, view_yaw_, view_pitch_);
return true;
}
@ -260,10 +254,6 @@ void game::Player::Input(PlayerInputType type, bool enabled)
else
in_ &= ~(1 << type);
if (!game_.PlayerInput(*this, type, enabled))
{
if (world_)
world_->PlayerInput(*this, type, enabled);
}
game_.PlayerInput(*this, type, enabled);
}

View File

@ -1,20 +1,23 @@
#pragma once
#include <set>
#include <memory>
#include <glm/glm.hpp>
#include "net/defs.hpp"
#include "net/inmessage.hpp"
#include "net/msg_producer.hpp"
#include "utils/defs.hpp"
#include "player_input.hpp"
#include "game.hpp"
namespace game
{
class Game;
class World;
class Entity;
class Vehicle;
class Player : public net::MsgProducer
{
@ -25,7 +28,7 @@ public:
bool ProcessMsg(net::MessageType type, net::InMessage& msg);
void Update();
void SetWorld(std::shared_ptr<World> world);
void SetWorld(World* world);
void SetCamera(net::EntNum entnum);
void SendChat(const std::string& text);
@ -60,7 +63,7 @@ private:
Game& game_;
std::string name_;
std::shared_ptr<World> world_ = nullptr;
World* world_ = nullptr;
World* known_world_ = nullptr;
std::set<net::EntNum> known_ents_;

View File

@ -1,7 +1,7 @@
#include "player_character.hpp"
#include "openworld.hpp"
#include "world.hpp"
game::PlayerCharacter::PlayerCharacter(World& world, Player& player) : Super(world), 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

@ -2,18 +2,17 @@
#include "drivable_vehicle.hpp"
#include "player.hpp"
#include "world.hpp"
namespace game
{
class OpenWorld;
class PlayerCharacter : public ControllableCharacter
{
public:
using Super = ControllableCharacter;
PlayerCharacter(World& world, Player& player);
PlayerCharacter(World& world, Player& player, const CharacterTuning& tuning);
virtual void Update() override;
@ -21,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();

View File

@ -6,6 +6,7 @@
#include "assets/cache.hpp"
#include "utils/allocnum.hpp"
#include "collision/object_info.hpp"
#include "destroyed_object.hpp"
game::World::World(std::string mapname) : Scheduler(time_ms_), map_(*this, std::move(mapname))
{
@ -78,6 +79,15 @@ void game::World::FinishFrame()
}
void game::World::DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col)
{
auto& destroyed_obj = Spawn<DestroyedObject>(std::move(col));
Schedule(120000, [this, num] {
RespawnObj(num);
});
}
game::Entity* game::World::GetEntity(net::EntNum entnum)
{
auto it = ents_.find(entnum);

View File

@ -37,13 +37,7 @@ public:
virtual void Update(int64_t delta_time);
void FinishFrame();
// events
virtual void PlayerJoined(Player& player) {}
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) {}
virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch) {}
virtual void PlayerLeft(Player& player) {}
virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col) {}
virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr<MapObjectCollision> col);
Entity* GetEntity(net::EntNum entnum);

View File

@ -9,12 +9,14 @@
#include "draw_args.hpp"
game::view::WorldView::WorldView(ClientSession& session, net::InMessage& msg) :
session_(session), audiomaster_(session_.GetAudioMaster()), map_("openworld")
session_(session), audiomaster_(session_.GetAudioMaster())
{
net::MapName mapname;
if (!msg.Read(mapname))
throw EntityInitError();
map_ = std::make_unique<MapInstanceView>(std::string(mapname));
// init destroyed objs
net::ObjCount objcount;
if (!msg.Read(objcount))
@ -26,7 +28,7 @@ game::view::WorldView::WorldView(ClientSession& session, net::InMessage& msg) :
if (!msg.Read(objnum))
throw EntityInitError();
map_.EnableObj(objnum, false);
map_->EnableObj(objnum, false);
}
// cache common snds and stuff
@ -69,8 +71,8 @@ void game::view::WorldView::Update(const UpdateInfo& info)
{
time_ = info.time;
if (!map_.IsLoaded())
map_.LoadNext();
if (!map_->IsLoaded())
map_->LoadNext();
for (const auto& [entnum, ent] : ents_)
{
@ -80,7 +82,7 @@ void game::view::WorldView::Update(const UpdateInfo& info)
void game::view::WorldView::Draw(const DrawArgs& args) const
{
if (!map_.IsLoaded())
if (!map_->IsLoaded())
{
DrawLoadingScreen(args);
return;
@ -88,7 +90,7 @@ void game::view::WorldView::Draw(const DrawArgs& args) const
args.env.clear_color = glm::vec3(0.5f, 0.7f, 1.0f);
map_.Draw(args);
map_->Draw(args);
for (const auto& [entnum, ent] : ents_)
{
@ -137,7 +139,7 @@ void game::view::WorldView::DrawLoadingScreen(const DrawArgs& args) const
glm::vec2 size(400.0f, 15.0f);
glm::vec2 pos(margin, args.screen_size.y - margin - size.y);
int loaded_percent = map_.GetLoadingPercent();
int loaded_percent = map_->GetLoadingPercent();
float loaded = static_cast<float>(loaded_percent) * 0.01f;
args.gui.DrawRect(pos, pos + size, 0x77FFFFFF);
@ -267,7 +269,7 @@ bool game::view::WorldView::ProcessObjDestroyOrRespawnMsg(net::InMessage& msg, b
if (!msg.Read(objnum))
return false;
map_.EnableObj(objnum, enable);
map_->EnableObj(objnum, enable);
return true;
}

View File

@ -48,7 +48,7 @@ private:
private:
ClientSession& session_;
MapInstanceView map_;
std::unique_ptr<MapInstanceView> map_;
std::map<net::EntNum, std::unique_ptr<EntityView>> ents_;
float time_ = 0.0f;

View File

@ -17,6 +17,8 @@ void sv::Server::Run()
{
using namespace std::chrono_literals;
srand(time(NULL));
auto t_start = std::chrono::steady_clock::now();
auto t_next = t_start;
auto t_prev = t_start;