Compare commits
7 Commits
d0b30ed56b
...
7832c1b40c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7832c1b40c | ||
|
|
d853f7c53c | ||
|
|
da4eaae9ec | ||
|
|
3d7db1184f | ||
|
|
737165a152 | ||
|
|
cc8bc9313c | ||
|
|
ba0bb5a827 |
@ -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"
|
||||
|
||||
BIN
res/houbymore.png
Normal file
BIN
res/houbymore.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
30
src/game/character_tuning.hpp
Normal file
30
src/game/character_tuning.hpp
Normal 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;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
131
src/game/enterable_world.cpp
Normal file
131
src/game/enterable_world.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
41
src/game/enterable_world.hpp
Normal file
41
src/game/enterable_world.hpp
Normal 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_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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_;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user