@@ -9,6 +9,7 @@
|
|||||||
#include "Core/EPlayerDamage.h"
|
#include "Core/EPlayerDamage.h"
|
||||||
#include "Core/EPlayerHealthPickup.h"
|
#include "Core/EPlayerHealthPickup.h"
|
||||||
#include "Core/EPlayerDeath.h"
|
#include "Core/EPlayerDeath.h"
|
||||||
|
#include "../Engine/Input/EInputCommand.h"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -28,7 +29,9 @@ private:
|
|||||||
bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e);
|
bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e);
|
||||||
EventRelay<HealthSystem, Events::PlayerHealthPickup> m_EPlayerHealthPickup;
|
EventRelay<HealthSystem, Events::PlayerHealthPickup> m_EPlayerHealthPickup;
|
||||||
bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e);
|
bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e);
|
||||||
|
EventRelay<HealthSystem, Events::InputCommand> m_InputCommand;
|
||||||
|
bool HealthSystem::OnInputCommand(Events::InputCommand& e);
|
||||||
|
|
||||||
//vector which will keep track of health changes
|
//vector which will keep track of health changes
|
||||||
std::vector<std::tuple<EntityID, double>> m_DeltaHealthVector;
|
std::vector<std::tuple<EntityID, double>> m_DeltaHealthVector;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ public:
|
|||||||
PlayerSpawnSystem(SystemParams params);
|
PlayerSpawnSystem(SystemParams params);
|
||||||
|
|
||||||
virtual void Update(double dt) override;
|
virtual void Update(double dt) override;
|
||||||
|
|
||||||
|
static void SetRespawnTime(float respawnTime) { m_RespawnTime = respawnTime; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SpawnRequest
|
struct SpawnRequest
|
||||||
@@ -23,10 +25,19 @@ private:
|
|||||||
|
|
||||||
bool m_NetworkEnabled = false;
|
bool m_NetworkEnabled = false;
|
||||||
std::vector<SpawnRequest> m_SpawnRequests;
|
std::vector<SpawnRequest> m_SpawnRequests;
|
||||||
|
|
||||||
|
//Player ID -> EntityWrapper.
|
||||||
std::map<int, EntityWrapper> m_PlayerEntities;
|
std::map<int, EntityWrapper> m_PlayerEntities;
|
||||||
|
//EntityWrapper ID -> Player ID.
|
||||||
|
std::map<EntityID, int> m_PlayerIDs;
|
||||||
|
|
||||||
|
static float m_RespawnTime;
|
||||||
|
float m_Timer;
|
||||||
|
|
||||||
EventRelay<PlayerSpawnSystem, Events::InputCommand> m_OnInputCommand;
|
EventRelay<PlayerSpawnSystem, Events::InputCommand> m_OnInputCommand;
|
||||||
bool OnInputCommand(const Events::InputCommand& e);
|
bool OnInputCommand(Events::InputCommand& e);
|
||||||
EventRelay<PlayerSpawnSystem, Events::PlayerSpawned> m_OnPlayerSpawnerd;
|
EventRelay<PlayerSpawnSystem, Events::PlayerSpawned> m_OnPlayerSpawnerd;
|
||||||
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||||
|
EventRelay<PlayerSpawnSystem, Events::PlayerDeath> m_OnPlayerDeath;
|
||||||
|
bool OnPlayerDeath(Events::PlayerDeath& e);
|
||||||
};
|
};
|
||||||
@@ -4,6 +4,7 @@ LoadMap=
|
|||||||
; if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
|
; if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
|
||||||
; if false -> Use pool allocation.
|
; if false -> Use pool allocation.
|
||||||
DisableMemoryPool=false
|
DisableMemoryPool=false
|
||||||
|
RespawnTime = 8.0
|
||||||
EditorEnabled=false
|
EditorEnabled=false
|
||||||
OutOfBodyExperience=false
|
OutOfBodyExperience=false
|
||||||
|
|
||||||
|
|||||||
@@ -24,4 +24,5 @@ F1=ToggleEditor
|
|||||||
C=ConnectToServer
|
C=ConnectToServer
|
||||||
N=SwitchToServer
|
N=SwitchToServer
|
||||||
M=SwitchToClient
|
M=SwitchToClient
|
||||||
P=SwitchToPlayer
|
P=SwitchToPlayer
|
||||||
|
K=TakeDamage,1500
|
||||||
+2
-1
@@ -42,6 +42,7 @@ Game::Game(int argc, char* argv[])
|
|||||||
ResourceManager::UseThreading = m_Config->Get<bool>("Multithreading.ResourceLoading", true);
|
ResourceManager::UseThreading = m_Config->Get<bool>("Multithreading.ResourceLoading", true);
|
||||||
DisableMemoryPool::Value = m_Config->Get<bool>("Debug.DisableMemoryPool", false);
|
DisableMemoryPool::Value = m_Config->Get<bool>("Debug.DisableMemoryPool", false);
|
||||||
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
|
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
|
||||||
|
PlayerSpawnSystem::SetRespawnTime(m_Config->Get<float>("Debug.RespawnTime", 15.0f));
|
||||||
|
|
||||||
// Create the core event broker
|
// Create the core event broker
|
||||||
m_EventBroker = new EventBroker();
|
m_EventBroker = new EventBroker();
|
||||||
@@ -118,7 +119,6 @@ Game::Game(int argc, char* argv[])
|
|||||||
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<PlayerDeathSystem>(updateOrderLevel);
|
|
||||||
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer, m_OctreeCollision);
|
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer, m_OctreeCollision);
|
||||||
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
|
||||||
@@ -132,6 +132,7 @@ Game::Game(int argc, char* argv[])
|
|||||||
m_SystemPipeline->AddSystem<FillFrustumOctreeSystem>(updateOrderLevel, m_OctreeFrustrumCulling);
|
m_SystemPipeline->AddSystem<FillFrustumOctreeSystem>(updateOrderLevel, m_OctreeFrustrumCulling);
|
||||||
m_SystemPipeline->AddSystem<AnimationSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<AnimationSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<UniformScaleSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<UniformScaleSystem>(updateOrderLevel);
|
||||||
|
m_SystemPipeline->AddSystem<PlayerDeathSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<PlayerHUDSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<PlayerHUDSystem>(updateOrderLevel);
|
||||||
// Collision and TriggerSystem should update after player.
|
// Collision and TriggerSystem should update after player.
|
||||||
++updateOrderLevel;
|
++updateOrderLevel;
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ bool DamageIndicatorSystem::OnPlayerDamage(Events::PlayerDamage& e)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!e.Inflictor.Valid() || !e.Victim.Valid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//grab players direction
|
//grab players direction
|
||||||
auto playerOrientation = glm::quat((glm::vec3)e.Victim["Transform"]["Orientation"]);
|
auto playerOrientation = glm::quat((glm::vec3)e.Victim["Transform"]["Orientation"]);
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ HealthSystem::HealthSystem(SystemParams params)
|
|||||||
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
|
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &HealthSystem::OnPlayerDamaged);
|
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &HealthSystem::OnPlayerDamaged);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup);
|
EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_InputCommand, &HealthSystem::OnInputCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||||
@@ -29,6 +30,17 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HealthSystem::OnInputCommand(Events::InputCommand& e)
|
||||||
|
{
|
||||||
|
if (e.Command == "TakeDamage" && e.Value > 0 && LocalPlayer.Valid()) {
|
||||||
|
Events::PlayerDamage ev;
|
||||||
|
ev.Victim = LocalPlayer;
|
||||||
|
ev.Damage = e.Value;
|
||||||
|
m_EventBroker->Publish(ev);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e)
|
bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e)
|
||||||
{
|
{
|
||||||
ComponentWrapper cHealth = e.Player["Health"];
|
ComponentWrapper cHealth = e.Player["Health"];
|
||||||
|
|||||||
@@ -34,8 +34,15 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player)
|
|||||||
|
|
||||||
//components that we need from player
|
//components that we need from player
|
||||||
auto playerCamera = player.FirstChildByName("Camera");
|
auto playerCamera = player.FirstChildByName("Camera");
|
||||||
auto playerEntityModel = player.FirstChildByName("PlayerModel")["Model"];
|
auto playerModel = player.FirstChildByName("PlayerModel");
|
||||||
auto playerEntityAnimation = player.FirstChildByName("PlayerModel")["Animation"];
|
if (!playerCamera.Valid() || !playerModel.Valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!playerModel.HasComponent("Model") || !playerModel.HasComponent("Animation")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto playerEntityModel = playerModel["Model"];
|
||||||
|
auto playerEntityAnimation = playerModel["Animation"];
|
||||||
|
|
||||||
//copy the data from player to explisioneffectmodel
|
//copy the data from player to explisioneffectmodel
|
||||||
playerEntityModel.Copy(deathEffectEW["Model"]);
|
playerEntityModel.Copy(deathEffectEW["Model"]);
|
||||||
|
|||||||
@@ -1,20 +1,39 @@
|
|||||||
#include "Systems/PlayerSpawnSystem.h"
|
#include "Systems/PlayerSpawnSystem.h"
|
||||||
|
|
||||||
|
//This should be set by the config anyway.
|
||||||
|
float PlayerSpawnSystem::m_RespawnTime = 15.0f;
|
||||||
|
|
||||||
PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params)
|
PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params)
|
||||||
: System(params)
|
: System(params)
|
||||||
|
, m_Timer(0.f)
|
||||||
{
|
{
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand);
|
EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerSpawnerd, &PlayerSpawnSystem::OnPlayerSpawned);
|
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerSpawnerd, &PlayerSpawnSystem::OnPlayerSpawned);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerSpawnSystem::OnPlayerDeath);
|
||||||
m_NetworkEnabled = ResourceManager::Load<ConfigFile>("Config.ini")->Get("Networking.StartNetwork", false);
|
m_NetworkEnabled = ResourceManager::Load<ConfigFile>("Config.ini")->Get("Networking.StartNetwork", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerSpawnSystem::Update(double dt)
|
void PlayerSpawnSystem::Update(double dt)
|
||||||
{
|
{
|
||||||
|
//Increase timer.
|
||||||
|
m_Timer += dt;
|
||||||
|
if (m_Timer < m_RespawnTime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//If respawn time has passed, we spawn all players that have requested to be spawned.
|
||||||
|
m_Timer = 0.f;
|
||||||
|
|
||||||
|
//If there are no spawn requests, return immediately, if we are client the SpawnRequests should always be empty.
|
||||||
|
if (m_SpawnRequests.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto playerSpawns = m_World->GetComponents("PlayerSpawn");
|
auto playerSpawns = m_World->GetComponents("PlayerSpawn");
|
||||||
if (playerSpawns == nullptr) {
|
if (playerSpawns == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int numSpawnedPlayers = 0;
|
||||||
for (auto& req : m_SpawnRequests) {
|
for (auto& req : m_SpawnRequests) {
|
||||||
for (auto& cPlayerSpawn : *playerSpawns) {
|
for (auto& cPlayerSpawn : *playerSpawns) {
|
||||||
EntityWrapper spawner(m_World, cPlayerSpawn.EntityID);
|
EntityWrapper spawner(m_World, cPlayerSpawn.EntityID);
|
||||||
@@ -40,29 +59,61 @@ void PlayerSpawnSystem::Update(double dt)
|
|||||||
e.Player = player;
|
e.Player = player;
|
||||||
e.Spawner = spawner;
|
e.Spawner = spawner;
|
||||||
m_EventBroker->Publish(e);
|
m_EventBroker->Publish(e);
|
||||||
|
++numSpawnedPlayers;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (numSpawnedPlayers != (int)m_SpawnRequests.size()) {
|
||||||
|
LOG_DEBUG("%i players were supposed to be spawned, but %i was spawned.", (int)m_SpawnRequests.size(), numSpawnedPlayers);
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("%i players were spawned.", numSpawnedPlayers);
|
||||||
|
}
|
||||||
m_SpawnRequests.clear();
|
m_SpawnRequests.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e)
|
bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
|
||||||
{
|
{
|
||||||
if (e.Command != "PickTeam") {
|
if (e.Command != "PickTeam") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Team picks should be processed ONLY server-side!
|
// Team picks should be processed ONLY server-side!
|
||||||
// Don't make a spawn request if PlayerID is -1, i.e. we're the client.
|
// Don't make a spawn request if we're the client.
|
||||||
if (e.PlayerID == -1 && m_NetworkEnabled) {
|
if (!IsServer && m_NetworkEnabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.Value != 0) {
|
if (e.Value == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Spectating?
|
||||||
|
//Right now, return if someone picks spectator.
|
||||||
|
//1 signifies spectator here, could not get Playerteam component since it may be invalid or without team comp.
|
||||||
|
if ((ComponentInfo::EnumType)e.Value == 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the player already requested spawn.
|
||||||
|
auto iter = m_SpawnRequests.begin();
|
||||||
|
for (; iter != m_SpawnRequests.end(); ++iter) {
|
||||||
|
if (iter->PlayerID == e.PlayerID) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter != m_SpawnRequests.end()) {
|
||||||
|
//If player is in queue to spawn, then change their team affiliation in the request.
|
||||||
|
iter->Team = (ComponentInfo::EnumType)e.Value;
|
||||||
|
} else if (m_PlayerEntities.count(e.PlayerID) == 0 || !m_PlayerEntities[e.PlayerID].Valid()) {
|
||||||
|
//If player is not in queue to spawn, then create a spawn request,
|
||||||
|
//but only if they are spectating and/or just connected.
|
||||||
SpawnRequest req;
|
SpawnRequest req;
|
||||||
req.PlayerID = e.PlayerID;
|
req.PlayerID = e.PlayerID;
|
||||||
req.Team = (ComponentInfo::EnumType)e.Value;
|
req.Team = (ComponentInfo::EnumType)e.Value;
|
||||||
m_SpawnRequests.push_back(req);
|
m_SpawnRequests.push_back(req);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -70,21 +121,15 @@ bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e)
|
|||||||
|
|
||||||
bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||||
{
|
{
|
||||||
|
// Store the player for future reference
|
||||||
|
m_PlayerEntities[e.PlayerID] = e.Player;
|
||||||
|
m_PlayerIDs[e.Player.ID] = e.PlayerID;
|
||||||
|
|
||||||
// When a player is actually spawned (since the actual spawning is handled on the server)
|
// When a player is actually spawned (since the actual spawning is handled on the server)
|
||||||
if (!IsClient) {
|
if (!IsClient) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a player already exists
|
|
||||||
if (m_PlayerEntities.count(e.PlayerID) != 0) {
|
|
||||||
// TODO: Disallow infinite respawning here
|
|
||||||
if (m_PlayerEntities[e.PlayerID].Valid()) {
|
|
||||||
m_World->DeleteEntity(m_PlayerEntities[e.PlayerID].ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the player for future reference
|
|
||||||
m_PlayerEntities[e.PlayerID] = e.Player;
|
|
||||||
|
|
||||||
// Set the camera to the correct entity
|
// Set the camera to the correct entity
|
||||||
EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera");
|
EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera");
|
||||||
@@ -114,4 +159,24 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlayerSpawnSystem::OnPlayerDeath(Events::PlayerDeath& e)
|
||||||
|
{
|
||||||
|
//Only spawn request if network is disabled or we are server.
|
||||||
|
if (!IsServer && m_NetworkEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!e.Player.HasComponent("Team")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ComponentWrapper cTeam = e.Player["Team"];
|
||||||
|
//A spectator can't die anyway
|
||||||
|
if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Spectator")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SpawnRequest req;
|
||||||
|
req.PlayerID = m_PlayerIDs.at(e.Player.ID);
|
||||||
|
req.Team = cTeam["Team"];
|
||||||
|
m_SpawnRequests.push_back(req);
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,12 +52,6 @@ bool SoundSystem::OnInputCommand(const Events::InputCommand & e)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e.Command == "TakeDamage" && e.Value > 0) {
|
|
||||||
Events::PlayerDamage ev;
|
|
||||||
ev.Victim = LocalPlayer;
|
|
||||||
ev.Damage = 1.0;
|
|
||||||
m_EventBroker->Publish(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user