Add markers
This commit is contained in:
parent
cd3e1aab4f
commit
308c39b8f8
@ -82,6 +82,8 @@ set(CLIENT_ONLY_SOURCES
|
|||||||
"src/gameview/entityview.cpp"
|
"src/gameview/entityview.cpp"
|
||||||
"src/gameview/mapinstanceview.hpp"
|
"src/gameview/mapinstanceview.hpp"
|
||||||
"src/gameview/mapinstanceview.cpp"
|
"src/gameview/mapinstanceview.cpp"
|
||||||
|
"src/gameview/markerview.hpp"
|
||||||
|
"src/gameview/markerview.cpp"
|
||||||
"src/gameview/remote_menu_view.hpp"
|
"src/gameview/remote_menu_view.hpp"
|
||||||
"src/gameview/remote_menu_view.cpp"
|
"src/gameview/remote_menu_view.cpp"
|
||||||
"src/gameview/simple_entity_view.hpp"
|
"src/gameview/simple_entity_view.hpp"
|
||||||
@ -142,6 +144,8 @@ set(SERVER_ONLY_SOURCES
|
|||||||
"src/game/game.cpp"
|
"src/game/game.cpp"
|
||||||
"src/game/mapinstance.hpp"
|
"src/game/mapinstance.hpp"
|
||||||
"src/game/mapinstance.cpp"
|
"src/game/mapinstance.cpp"
|
||||||
|
"src/game/marker.hpp"
|
||||||
|
"src/game/marker.cpp"
|
||||||
"src/game/npc_character.hpp"
|
"src/game/npc_character.hpp"
|
||||||
"src/game/npc_character.cpp"
|
"src/game/npc_character.cpp"
|
||||||
"src/game/openworld.hpp"
|
"src/game/openworld.hpp"
|
||||||
|
|||||||
@ -1,8 +1,20 @@
|
|||||||
#include "entity.hpp"
|
#include "entity.hpp"
|
||||||
|
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
|
#include "player.hpp"
|
||||||
|
|
||||||
game::Entity::Entity(World& world, net::EntType viewtype) : Scheduler(world.GetTime()), world_(world), entnum_(world.GetNewEntnum()), viewtype_(viewtype) {}
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include <glm/gtx/norm.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
game::Entity::Entity(World& world, net::EntType viewtype) : Scheduler(world.GetTime()), world_(world), entnum_(world.GetNewEntnum()), viewtype_(viewtype)
|
||||||
|
{
|
||||||
|
if (viewtype == net::ET_NONE)
|
||||||
|
{
|
||||||
|
visible_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void game::Entity::SendInitData(Player& player, net::OutMessage& msg) const
|
void game::Entity::SendInitData(Player& player, net::OutMessage& msg) const
|
||||||
{
|
{
|
||||||
@ -69,6 +81,18 @@ void game::Entity::PlaySound(const std::string& name, float volume, float pitch)
|
|||||||
msg.Write<net::SoundPitchQ>(pitch);
|
msg.Write<net::SoundPitchQ>(pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::Entity::IsVisibleTo(const Player& player) const
|
||||||
|
{
|
||||||
|
if (!visible_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// max distance check
|
||||||
|
if (glm::distance2(root_.GetGlobalPosition(), player.GetCullPos()) > (max_distance_ * max_distance_))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void game::Entity::WriteNametag(net::OutMessage& msg) const
|
void game::Entity::WriteNametag(net::OutMessage& msg) const
|
||||||
{
|
{
|
||||||
msg.Write(net::NameTag{nametag_});
|
msg.Write(net::NameTag{nametag_});
|
||||||
|
|||||||
@ -49,6 +49,7 @@ public:
|
|||||||
const TransformNode& GetRoot() const { return root_; }
|
const TransformNode& GetRoot() const { return root_; }
|
||||||
const Transform& GetRootTransform() const { return root_.local; }
|
const Transform& GetRootTransform() const { return root_.local; }
|
||||||
|
|
||||||
|
bool IsVisibleTo(const Player& player) const;
|
||||||
float GetMaxDistance() const { return max_distance_; }
|
float GetMaxDistance() const { return max_distance_; }
|
||||||
|
|
||||||
virtual ~Entity() = default;
|
virtual ~Entity() = default;
|
||||||
@ -73,6 +74,7 @@ protected:
|
|||||||
TransformNode root_;
|
TransformNode root_;
|
||||||
Entity* parent_ = nullptr;
|
Entity* parent_ = nullptr;
|
||||||
|
|
||||||
|
bool visible_ = true;
|
||||||
float max_distance_ = 700.0f;
|
float max_distance_ = 700.0f;
|
||||||
|
|
||||||
bool removed_ = false;
|
bool removed_ = false;
|
||||||
|
|||||||
@ -18,14 +18,8 @@ static uint32_t GetRandomColor24()
|
|||||||
|
|
||||||
game::Game::Game()
|
game::Game::Game()
|
||||||
{
|
{
|
||||||
openworld_ = std::make_shared<OpenWorld>();
|
openworld_ = std::make_shared<OpenWorld>(*this);
|
||||||
all_worlds_.push_back(openworld_.get());
|
AddWorld(openworld_.get());
|
||||||
|
|
||||||
testworld_ = std::make_shared<EnterableWorld>("testarena");
|
|
||||||
all_worlds_.push_back(testworld_.get());
|
|
||||||
|
|
||||||
garage_ = std::make_shared<TuningWorld>(*this, *openworld_, glm::vec3(0.0f), 0.0f, "garage");
|
|
||||||
all_worlds_.push_back(garage_.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Game::Update()
|
void game::Game::Update()
|
||||||
@ -44,6 +38,11 @@ void game::Game::FinishFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game::Game::AddWorld(World* world)
|
||||||
|
{
|
||||||
|
all_worlds_.push_back(world);
|
||||||
|
}
|
||||||
|
|
||||||
void game::Game::PlayerJoined(Player& player)
|
void game::Game::PlayerJoined(Player& player)
|
||||||
{
|
{
|
||||||
BroadcastChat(player.GetName() + "^r se připoojil jupí jupí jupííí");
|
BroadcastChat(player.GetName() + "^r se připoojil jupí jupí jupííí");
|
||||||
@ -71,29 +70,29 @@ void game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled)
|
|||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case IN_DEBUG2: {
|
// case IN_DEBUG2: {
|
||||||
if (!enabled)
|
// if (!enabled)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
// auto& player_info = players_.at(&player);
|
// // auto& player_info = players_.at(&player);
|
||||||
|
|
||||||
// if (player_info.world == openworld_.get())
|
// // if (player_info.world == openworld_.get())
|
||||||
// {
|
// // {
|
||||||
// MovePlayerToWorld(player_info, testworld_.get(), test_spawn, 0.0f, true);
|
// // MovePlayerToWorld(player_info, testworld_.get(), test_spawn, 0.0f, true);
|
||||||
// }
|
// // }
|
||||||
// else
|
// // else
|
||||||
// {
|
// // {
|
||||||
// MovePlayerToWorld(player_info, openworld_.get(), openworld_spawn, 0.0f, true);
|
// // MovePlayerToWorld(player_info, openworld_.get(), openworld_spawn, 0.0f, true);
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// MovePlayerToTuning(player);
|
||||||
|
|
||||||
|
// break;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
MovePlayerToTuning(player);
|
// case IN_DEBUG3:
|
||||||
|
// // DisplayTestMenu(player);
|
||||||
break;
|
// break;
|
||||||
}
|
|
||||||
|
|
||||||
case IN_DEBUG3:
|
|
||||||
DisplayTestMenu(player);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
auto world = FindPlayerWorld(player);
|
auto world = FindPlayerWorld(player);
|
||||||
@ -224,69 +223,3 @@ game::EnterableWorld* game::Game::FindPlayerWorld(Player& player) const
|
|||||||
|
|
||||||
return it->second.world;
|
return it->second.world;
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Game::DisplayTestMenu(Player& player)
|
|
||||||
{
|
|
||||||
if (player.HasOpenMenu())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto& menu = player.DisplayMenu("test");
|
|
||||||
|
|
||||||
auto& btn_echo = menu.AddItem(RM_BUTTON, "echo");
|
|
||||||
btn_echo.SetOnClick([&player] {
|
|
||||||
player.SendChat("echo test");
|
|
||||||
});
|
|
||||||
|
|
||||||
auto& btn_bc = menu.AddItem(RM_BUTTON, "broadcast");
|
|
||||||
btn_bc.SetOnClick([this, &player] {
|
|
||||||
BroadcastChat(player.GetName() + "^r mele hovna");
|
|
||||||
});
|
|
||||||
|
|
||||||
int test = 0;
|
|
||||||
auto& sel_test = menu.AddItem(RM_SELECT, "výběr");
|
|
||||||
sel_test.SetOnSelect([test, &sel_test] (int dir) mutable {
|
|
||||||
test += dir;
|
|
||||||
sel_test.SetSelection(std::to_string(test));
|
|
||||||
});
|
|
||||||
sel_test.SetSelection(std::to_string(test));
|
|
||||||
|
|
||||||
|
|
||||||
auto& btn_close = menu.AddItem(RM_BUTTON, "zavřít");
|
|
||||||
btn_close.SetOnClick([&menu, &player] {
|
|
||||||
player.CloseMenu(menu);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void game::Game::MovePlayerToTuning(Player& player)
|
|
||||||
{
|
|
||||||
auto& player_info = GetPlayerInfo(player);
|
|
||||||
|
|
||||||
if (player_info.world != openworld_.get())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (garage_->IsOccupied())
|
|
||||||
{
|
|
||||||
player.SendChat("bohužel tam teď oxiduje nějakej píčus " + garage_->GetOccupantName() + "^r!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto character = player_info.world->GetPlayerCharacter(player);
|
|
||||||
if (!character)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto vehicle = character->GetVehicle();
|
|
||||||
if (!vehicle)
|
|
||||||
{
|
|
||||||
player.SendChat("nemáš vehikl!!!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vehicle->GetPassenger(0) != character)
|
|
||||||
{
|
|
||||||
player.SendChat("nejsi ridič!!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MovePlayerToWorld(player_info, garage_.get(), glm::vec3(0.0f), 0.0f, true);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -27,6 +27,8 @@ public:
|
|||||||
void Update();
|
void Update();
|
||||||
void FinishFrame();
|
void FinishFrame();
|
||||||
|
|
||||||
|
void AddWorld(World* world);
|
||||||
|
|
||||||
void PlayerJoined(Player& player);
|
void PlayerJoined(Player& player);
|
||||||
void PlayerViewAnglesChanged(Player& player, float yaw, float pitch);
|
void PlayerViewAnglesChanged(Player& player, float yaw, float pitch);
|
||||||
void PlayerInput(Player& player, PlayerInputType type, bool enabled);
|
void PlayerInput(Player& player, PlayerInputType type, bool enabled);
|
||||||
@ -45,9 +47,6 @@ private:
|
|||||||
PlayerGameInfo& GetPlayerInfo(Player& player);
|
PlayerGameInfo& GetPlayerInfo(Player& player);
|
||||||
EnterableWorld* FindPlayerWorld(Player& player) const;
|
EnterableWorld* FindPlayerWorld(Player& player) const;
|
||||||
|
|
||||||
void DisplayTestMenu(Player& player);
|
|
||||||
void MovePlayerToTuning(Player& player);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<OpenWorld> openworld_;
|
std::shared_ptr<OpenWorld> openworld_;
|
||||||
std::shared_ptr<EnterableWorld> testworld_;
|
std::shared_ptr<EnterableWorld> testworld_;
|
||||||
|
|||||||
77
src/game/marker.cpp
Normal file
77
src/game/marker.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "marker.hpp"
|
||||||
|
|
||||||
|
#include "world.hpp"
|
||||||
|
#include "net/utils.hpp"
|
||||||
|
|
||||||
|
static const glm::mat4 identity(1.0f);
|
||||||
|
|
||||||
|
game::Marker::Marker(World& world, const MarkerInfo& info) : Super(world, net::ET_MARKER), Usable(identity), info_(info)
|
||||||
|
{
|
||||||
|
root_.local.position = info_.position;
|
||||||
|
root_.UpdateMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Marker::SendInitData(Player& player, net::OutMessage& msg) const
|
||||||
|
{
|
||||||
|
Super::SendInitData(player, msg);
|
||||||
|
|
||||||
|
net::PositionQ pos_q;
|
||||||
|
net::EncodePosition(info_.position, pos_q);
|
||||||
|
|
||||||
|
msg.Write(info_.type);
|
||||||
|
net::WritePositionQ(msg, pos_q);
|
||||||
|
net::WriteRGB(msg, info_.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Marker::Update()
|
||||||
|
{
|
||||||
|
Super::Update();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool game::Marker::QueryUseTarget(PlayerCharacter& character, uint32_t target_id, UseTargetQueryResult& res)
|
||||||
|
{
|
||||||
|
if (!query_cb_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return query_cb_(character, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Marker::Use(PlayerCharacter& character, uint32_t target_id)
|
||||||
|
{
|
||||||
|
if (!use_cb_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
use_cb_(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Marker::SetUseTarget(const std::string& name, MarkerQueryCallback query, MarkerUseCallback use)
|
||||||
|
{
|
||||||
|
if (!query_obj_)
|
||||||
|
{
|
||||||
|
query_obj_ = std::make_unique<btCollisionObject>();
|
||||||
|
|
||||||
|
static btSphereShape query_sphere(1.0f);
|
||||||
|
query_obj_->setCollisionShape(&query_sphere);
|
||||||
|
query_obj_->setWorldTransform(root_.local.ToBtTransform());
|
||||||
|
query_obj_->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||||
|
collision::SetObjectInfo(query_obj_.get(), collision::OT_ENTITY, collision::OF_USABLE, this);
|
||||||
|
|
||||||
|
world_.GetBtWorld().addCollisionObject(query_obj_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
query_cb_ = query;
|
||||||
|
use_cb_ = use;
|
||||||
|
|
||||||
|
use_targets_.clear();
|
||||||
|
use_targets_.emplace_back(this, 0, root_.GetGlobalPosition(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::Marker::~Marker()
|
||||||
|
{
|
||||||
|
if (query_obj_)
|
||||||
|
{
|
||||||
|
world_.GetBtWorld().removeCollisionObject(query_obj_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
src/game/marker.hpp
Normal file
41
src/game/marker.hpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "entity.hpp"
|
||||||
|
#include "marker_info.hpp"
|
||||||
|
#include "usable.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace game
|
||||||
|
{
|
||||||
|
|
||||||
|
using MarkerQueryCallback = std::function<bool(PlayerCharacter&, UseTargetQueryResult&)>;
|
||||||
|
using MarkerUseCallback = std::function<void(PlayerCharacter&)>;
|
||||||
|
|
||||||
|
class Marker : public Entity, public Usable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Super = Entity;
|
||||||
|
|
||||||
|
Marker(World& world, const MarkerInfo& info);
|
||||||
|
|
||||||
|
virtual void SendInitData(Player& player, net::OutMessage& msg) const override;
|
||||||
|
virtual void Update() override;
|
||||||
|
|
||||||
|
virtual bool QueryUseTarget(PlayerCharacter& character, uint32_t target_id, UseTargetQueryResult& res) override;
|
||||||
|
virtual void Use(PlayerCharacter& character, uint32_t target_id) override;
|
||||||
|
|
||||||
|
void SetUseTarget(const std::string& name, MarkerQueryCallback query, MarkerUseCallback use);
|
||||||
|
|
||||||
|
virtual ~Marker() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MarkerInfo info_;
|
||||||
|
|
||||||
|
std::unique_ptr<btCollisionObject> query_obj_;
|
||||||
|
|
||||||
|
MarkerQueryCallback query_cb_;
|
||||||
|
MarkerUseCallback use_cb_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
24
src/game/marker_info.hpp
Normal file
24
src/game/marker_info.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace game
|
||||||
|
{
|
||||||
|
|
||||||
|
enum MarkerType : uint8_t
|
||||||
|
{
|
||||||
|
MARKER_FOOT,
|
||||||
|
MARKER_VEHICLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MarkerInfo
|
||||||
|
{
|
||||||
|
glm::vec3 position;
|
||||||
|
MarkerType type;
|
||||||
|
uint32_t color;
|
||||||
|
std::string icon;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@ -4,11 +4,13 @@
|
|||||||
|
|
||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
#include "vehicle.hpp"
|
#include "vehicle.hpp"
|
||||||
|
|
||||||
#include "player_character.hpp"
|
#include "player_character.hpp"
|
||||||
#include "npc_character.hpp"
|
#include "npc_character.hpp"
|
||||||
#include "drivable_vehicle.hpp"
|
#include "drivable_vehicle.hpp"
|
||||||
#include "destroyed_object.hpp"
|
#include "destroyed_object.hpp"
|
||||||
|
#include "marker.hpp"
|
||||||
|
#include "tuning_world.hpp"
|
||||||
|
#include "game.hpp"
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
@ -45,7 +47,7 @@ static uint32_t GetRandomColor24()
|
|||||||
return (b << 16) | (g << 8) | r;
|
return (b << 16) | (g << 8) | r;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::OpenWorld::OpenWorld() : EnterableWorld("openworld")
|
game::OpenWorld::OpenWorld(Game& game) : EnterableWorld("openworld"), game_(game)
|
||||||
{
|
{
|
||||||
// spawn bots
|
// spawn bots
|
||||||
for (size_t i = 0; i < 100; ++i)
|
for (size_t i = 0; i < 100; ++i)
|
||||||
@ -80,6 +82,8 @@ game::OpenWorld::OpenWorld() : EnterableWorld("openworld")
|
|||||||
|
|
||||||
daytime_offset_ = static_cast<float>(rand() % 24);
|
daytime_offset_ = static_cast<float>(rand() % 24);
|
||||||
|
|
||||||
|
CreateTuningGarage(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::OpenWorld::Update(int64_t delta_time)
|
void game::OpenWorld::Update(int64_t delta_time)
|
||||||
@ -90,6 +94,17 @@ void game::OpenWorld::Update(int64_t delta_time)
|
|||||||
SetDayTime(static_cast<float>(GetTime()) * 0.001f * timespeed + daytime_offset_);
|
SetDayTime(static_cast<float>(GetTime()) * 0.001f * timespeed + daytime_offset_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game::OpenWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled)
|
||||||
|
{
|
||||||
|
if (type == IN_DEBUG2 && enabled)
|
||||||
|
{
|
||||||
|
RecoverPlayer(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Super::PlayerInput(player, type, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
game::DrivableVehicle& game::OpenWorld::SpawnRandomVehicle()
|
game::DrivableVehicle& game::OpenWorld::SpawnRandomVehicle()
|
||||||
{
|
{
|
||||||
game::VehicleTuning tuning;
|
game::VehicleTuning tuning;
|
||||||
@ -157,3 +172,131 @@ void game::OpenWorld::SpawnBot()
|
|||||||
auto& driver = Spawn<NpcCharacter>(npc_tuning);
|
auto& driver = Spawn<NpcCharacter>(npc_tuning);
|
||||||
driver.SetVehicle(&vehicle, 0);
|
driver.SetVehicle(&vehicle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game::OpenWorld::CreateTuningGarage(const glm::vec3& position, float yaw)
|
||||||
|
{
|
||||||
|
auto garage = std::make_shared<TuningWorld>(game_, *this, position, yaw, "garage");
|
||||||
|
game_.AddWorld(garage.get());
|
||||||
|
|
||||||
|
MarkerInfo marker_info{};
|
||||||
|
marker_info.position = position;
|
||||||
|
marker_info.type = MARKER_VEHICLE;
|
||||||
|
marker_info.color = 0x884400;
|
||||||
|
marker_info.icon = "tuning";
|
||||||
|
|
||||||
|
auto& marker = Spawn<Marker>(marker_info);
|
||||||
|
marker.SetUseTarget("vject do tunírny",
|
||||||
|
[garage](PlayerCharacter& character, UseTargetQueryResult& res) {
|
||||||
|
|
||||||
|
auto player = character.GetPlayer();
|
||||||
|
auto vehicle = character.GetVehicle();
|
||||||
|
|
||||||
|
if (!vehicle)
|
||||||
|
{
|
||||||
|
res.enabled = false;
|
||||||
|
res.error_text = "nemáš vehikl";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vehicle->GetPassenger(0) != &character)
|
||||||
|
{
|
||||||
|
return false; // not driver
|
||||||
|
}
|
||||||
|
|
||||||
|
if (garage->IsOccupied())
|
||||||
|
{
|
||||||
|
res.enabled = false;
|
||||||
|
res.error_text = "někdo tam už oxiduje";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.enabled = true;
|
||||||
|
res.error_text = nullptr;
|
||||||
|
res.delay = 0.2f;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[this, garage, &marker](PlayerCharacter& character) {
|
||||||
|
auto player = character.GetPlayer();
|
||||||
|
game_.MovePlayerToWorld(*player, *garage, true, glm::vec3(0.0f), 0.0f);
|
||||||
|
marker.SetNametag(player->GetName());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
garage->SetOnExit([&marker]() {
|
||||||
|
marker.SetNametag(std::string());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::OpenWorld::RecoverPlayer(Player& player)
|
||||||
|
{
|
||||||
|
auto character = GetPlayerCharacter(player);
|
||||||
|
if (!character)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto vehicle = character->GetVehicle();
|
||||||
|
|
||||||
|
if (!vehicle)
|
||||||
|
{
|
||||||
|
auto pos = character->GetRoot().GetGlobalPosition();
|
||||||
|
glm::vec3 recovery;
|
||||||
|
if (GetRecoveryPosition(pos, recovery))
|
||||||
|
{
|
||||||
|
character->SetPosition(recovery);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.SendChat("nejsi pod zemí");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vehicle->GetPassenger(0) != character)
|
||||||
|
return; // not driver
|
||||||
|
|
||||||
|
auto pos = vehicle->GetRoot().GetGlobalPosition();
|
||||||
|
glm::vec3 recovery;
|
||||||
|
if (GetRecoveryPosition(pos, recovery))
|
||||||
|
{
|
||||||
|
vehicle->SetPosition(recovery);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.SendChat("nejsi pod zemí");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RecoveryRaycast(btCollisionWorld& bt_world, const glm::vec3& pos, glm::vec3& hit)
|
||||||
|
{
|
||||||
|
btVector3 bt_from(pos.x, pos.y, 100.0f);
|
||||||
|
btVector3 bt_to(pos.x, pos.y, -100.0f);
|
||||||
|
btCollisionWorld::ClosestRayResultCallback cb(bt_from, bt_to);
|
||||||
|
bt_world.rayTest(bt_from, bt_to, cb);
|
||||||
|
|
||||||
|
if (!cb.hasHit())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hit = glm::vec3(cb.m_hitPointWorld.x(), cb.m_hitPointWorld.y(), cb.m_hitPointWorld.z());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool game::OpenWorld::GetRecoveryPosition(const glm::vec3& current, glm::vec3& recovery)
|
||||||
|
{
|
||||||
|
glm::vec3 start = current;
|
||||||
|
start = glm::max(start, glm::vec3(-2500.0f, -2500.0f, -1000.0f));
|
||||||
|
start = glm::min(start, glm::vec3(3400.0f, 3100.0f, 1000.0f));
|
||||||
|
|
||||||
|
if (!RecoveryRaycast(GetBtWorld(), start, recovery))
|
||||||
|
{
|
||||||
|
recovery = glm::vec3(0.0f, 0.0f, 5.0f);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recovery.z - 5.0f < current.z)
|
||||||
|
{
|
||||||
|
return false; // already above ground
|
||||||
|
}
|
||||||
|
|
||||||
|
recovery.z += 5.0f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@ -6,20 +6,29 @@
|
|||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class Game;
|
||||||
|
|
||||||
class OpenWorld : public EnterableWorld
|
class OpenWorld : public EnterableWorld
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Super = EnterableWorld;
|
using Super = EnterableWorld;
|
||||||
|
|
||||||
OpenWorld();
|
OpenWorld(Game& game);
|
||||||
|
|
||||||
virtual void Update(int64_t delta_time) override;
|
virtual void Update(int64_t delta_time) override;
|
||||||
|
virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
game::DrivableVehicle& SpawnRandomVehicle();
|
game::DrivableVehicle& SpawnRandomVehicle();
|
||||||
void SpawnBot();
|
void SpawnBot();
|
||||||
|
|
||||||
|
void CreateTuningGarage(const glm::vec3& position, float yaw);
|
||||||
|
|
||||||
|
void RecoverPlayer(Player& player);
|
||||||
|
bool GetRecoveryPosition(const glm::vec3& current, glm::vec3& recovery);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Game& game_;
|
||||||
std::vector<NpcCharacter*> npcs_;
|
std::vector<NpcCharacter*> npcs_;
|
||||||
float daytime_offset_ = 0.0f;
|
float daytime_offset_ = 0.0f;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -249,14 +249,7 @@ void game::Player::SyncEntities()
|
|||||||
|
|
||||||
bool game::Player::ShouldSeeEntity(const Entity& entity) const
|
bool game::Player::ShouldSeeEntity(const Entity& entity) const
|
||||||
{
|
{
|
||||||
// max distance check
|
return entity.IsVisibleTo(*this);
|
||||||
float max_dist = entity.GetMaxDistance();
|
|
||||||
if (glm::distance2(entity.GetRoot().GetGlobalPosition(), cull_pos_) > (max_dist * max_dist))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// TODO: custom callback
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Player::SendInitEntity(const Entity& entity)
|
void game::Player::SendInitEntity(const Entity& entity)
|
||||||
|
|||||||
@ -46,6 +46,8 @@ public:
|
|||||||
float GetViewYaw() const { return view_yaw_; }
|
float GetViewYaw() const { return view_yaw_; }
|
||||||
float GetViewPitch() const { return view_pitch_; }
|
float GetViewPitch() const { return view_pitch_; }
|
||||||
|
|
||||||
|
const glm::vec3 GetCullPos() const { return cull_pos_; }
|
||||||
|
|
||||||
~Player();
|
~Player();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -219,6 +219,9 @@ void game::TuningWorld::Reset()
|
|||||||
{
|
{
|
||||||
player_->CloseMenu(*menu_);
|
player_->CloseMenu(*menu_);
|
||||||
game_.MovePlayerToWorld(*player_, exit_world_, true, exit_pos_, exit_yaw_);
|
game_.MovePlayerToWorld(*player_, exit_world_, true, exit_pos_, exit_yaw_);
|
||||||
|
|
||||||
|
if (exit_cb_)
|
||||||
|
exit_cb_();
|
||||||
}
|
}
|
||||||
|
|
||||||
player_ = nullptr;
|
player_ = nullptr;
|
||||||
|
|||||||
@ -20,6 +20,8 @@ public:
|
|||||||
virtual void OnVehicleJoined(DrivableVehicle& vehicle);
|
virtual void OnVehicleJoined(DrivableVehicle& vehicle);
|
||||||
virtual void OnPlayerLeaving(Player& player);
|
virtual void OnPlayerLeaving(Player& player);
|
||||||
|
|
||||||
|
void SetOnExit(std::function<void()> cb) { exit_cb_ = cb; }
|
||||||
|
|
||||||
bool IsOccupied() const { return player_ != nullptr; }
|
bool IsOccupied() const { return player_ != nullptr; }
|
||||||
const std::string& GetOccupantName() const;
|
const std::string& GetOccupantName() const;
|
||||||
|
|
||||||
@ -46,6 +48,8 @@ private:
|
|||||||
|
|
||||||
VehicleTuning tuning_;
|
VehicleTuning tuning_;
|
||||||
|
|
||||||
|
std::function<void()> exit_cb_;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,8 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<UseTarget> use_targets_;
|
std::vector<UseTarget> use_targets_;
|
||||||
|
|
||||||
|
private:
|
||||||
const glm::mat4& matrix_;
|
const glm::mat4& matrix_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -333,7 +333,7 @@ void game::Vehicle::UpdateCrash()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (crash_intensity_ > 300.0f)
|
if (crash_intensity_ > 1000.0f)
|
||||||
{
|
{
|
||||||
float volume = RandomFloat(0.9f, 1.2f);
|
float volume = RandomFloat(0.9f, 1.2f);
|
||||||
float pitch = RandomFloat(1.0f, 1.3f);
|
float pitch = RandomFloat(1.0f, 1.3f);
|
||||||
@ -355,7 +355,7 @@ void game::Vehicle::UpdateCrash()
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlaySound("crash", volume, pitch);
|
PlaySound("crash", volume, pitch);
|
||||||
no_crash_frames_ = 3 + rand() % 10;
|
no_crash_frames_ = 7 + rand() % 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -136,9 +136,11 @@ struct UseTargetAabbCallback : public btBroadphaseAabbCallback
|
|||||||
float dist = glm::distance(pos, pos_world);
|
float dist = glm::distance(pos, pos_world);
|
||||||
if (dist < 2.0f && dist < best_dist)
|
if (dist < 2.0f && dist < best_dist)
|
||||||
{
|
{
|
||||||
if (!usable->QueryUseTarget(character, target.id, best_res))
|
game::UseTargetQueryResult res{};
|
||||||
|
if (!usable->QueryUseTarget(character, target.id, res))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
best_res = res;
|
||||||
best_dist = dist;
|
best_dist = dist;
|
||||||
best_target = ⌖
|
best_target = ⌖
|
||||||
}
|
}
|
||||||
|
|||||||
58
src/gameview/markerview.cpp
Normal file
58
src/gameview/markerview.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "markerview.hpp"
|
||||||
|
|
||||||
|
#include "net/utils.hpp"
|
||||||
|
#include "assets/cache.hpp"
|
||||||
|
|
||||||
|
game::view::MarkerView::MarkerView(WorldView& world, net::InMessage& msg) : Super(world, msg)
|
||||||
|
{
|
||||||
|
if (!Init(msg))
|
||||||
|
{
|
||||||
|
throw EntityInitError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::view::MarkerView::Update(const UpdateInfo& info)
|
||||||
|
{
|
||||||
|
root_.local.rotation = glm::quat(glm::vec3(0.0f, 0.0f, info.time * 0.5f));
|
||||||
|
root_.UpdateMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::view::MarkerView::Draw(const DrawArgs& args)
|
||||||
|
{
|
||||||
|
Super::Draw(args);
|
||||||
|
|
||||||
|
if (!model_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto& mesh = *model_->GetMesh();
|
||||||
|
for (const auto& surface : mesh.surfaces)
|
||||||
|
{
|
||||||
|
gfx::DrawSurfaceCmd cmd;
|
||||||
|
cmd.surface = &surface;
|
||||||
|
cmd.matrices = &root_.matrix;
|
||||||
|
cmd.color = &color_;
|
||||||
|
args.dlist.AddSurface(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool game::view::MarkerView::Init(net::InMessage& msg)
|
||||||
|
{
|
||||||
|
net::PositionQ pos_q;
|
||||||
|
uint32_t color;
|
||||||
|
|
||||||
|
if (!msg.Read(marker_type_) || !net::ReadPositionQ(msg, pos_q) || !net::ReadRGB(msg, color))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
net::DecodePosition(pos_q, root_.local.position);
|
||||||
|
root_.UpdateMatrix();
|
||||||
|
|
||||||
|
color_ = glm::unpackUnorm4x8(color | 0xFF000000);
|
||||||
|
|
||||||
|
if (marker_type_ == MARKER_FOOT || marker_type_ == MARKER_VEHICLE)
|
||||||
|
{
|
||||||
|
model_ = assets::CacheManager::GetModel("data/marker.mdl");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
34
src/gameview/markerview.hpp
Normal file
34
src/gameview/markerview.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "entityview.hpp"
|
||||||
|
#include "game/marker_info.hpp"
|
||||||
|
#include "assets/model.hpp"
|
||||||
|
|
||||||
|
namespace game::view
|
||||||
|
{
|
||||||
|
|
||||||
|
class MarkerView : public EntityView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Super = EntityView;
|
||||||
|
|
||||||
|
MarkerView(WorldView& world, net::InMessage& msg);
|
||||||
|
|
||||||
|
// virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg) override;
|
||||||
|
// virtual bool ProcessUpdateMsg(net::InMessage* msg) override;
|
||||||
|
virtual void Update(const UpdateInfo& info) override;
|
||||||
|
virtual void Draw(const DrawArgs& args) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Init(net::InMessage& msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MarkerType marker_type_;
|
||||||
|
glm::vec4 color_;
|
||||||
|
|
||||||
|
std::shared_ptr<const assets::Model> model_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@
|
|||||||
#include "simple_entity_view.hpp"
|
#include "simple_entity_view.hpp"
|
||||||
#include "characterview.hpp"
|
#include "characterview.hpp"
|
||||||
#include "vehicleview.hpp"
|
#include "vehicleview.hpp"
|
||||||
|
#include "markerview.hpp"
|
||||||
#include "client_session.hpp"
|
#include "client_session.hpp"
|
||||||
#include "draw_args.hpp"
|
#include "draw_args.hpp"
|
||||||
|
|
||||||
@ -232,6 +233,10 @@ bool game::view::WorldView::ProcessEntSpawnMsg(net::InMessage& msg)
|
|||||||
entslot = std::make_unique<VehicleView>(*this, msg);
|
entslot = std::make_unique<VehicleView>(*this, msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case net::ET_MARKER:
|
||||||
|
entslot = std::make_unique<MarkerView>(*this, msg);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ents_.erase(entnum);
|
ents_.erase(entnum);
|
||||||
return false; // unknown type
|
return false; // unknown type
|
||||||
|
|||||||
@ -93,6 +93,7 @@ enum EntType : uint8_t
|
|||||||
ET_SIMPLE,
|
ET_SIMPLE,
|
||||||
ET_CHARACTER,
|
ET_CHARACTER,
|
||||||
ET_VEHICLE,
|
ET_VEHICLE,
|
||||||
|
ET_MARKER,
|
||||||
|
|
||||||
ET_COUNT,
|
ET_COUNT,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user