From 8eea0c83953dc84be7e9769d1bb9a080be29e0b1 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 11 Feb 2016 16:08:19 +0100 Subject: [PATCH] WIP respawning. --- include/Game/Systems/PlayerSpawnSystem.h | 13 ++- resources/DefaultConfig.ini | 1 + resources/Schema/Entities/MovementTest.xml | 117 --------------------- src/Game/Game.cpp | 3 +- src/Game/Systems/PlayerDeathSystem.cpp | 15 ++- src/Game/Systems/PlayerSpawnSystem.cpp | 76 ++++++++++++- src/Game/Systems/SoundSystem.cpp | 4 +- 7 files changed, 101 insertions(+), 128 deletions(-) diff --git a/include/Game/Systems/PlayerSpawnSystem.h b/include/Game/Systems/PlayerSpawnSystem.h index f5aa7b82..681620bb 100644 --- a/include/Game/Systems/PlayerSpawnSystem.h +++ b/include/Game/Systems/PlayerSpawnSystem.h @@ -13,6 +13,8 @@ public: PlayerSpawnSystem(World* world, EventBroker* eventBroker); virtual void Update(double dt) override; + + static void SetRespawnTime(float respawnTime) { m_RespawnTime = respawnTime; }; private: struct SpawnRequest @@ -23,10 +25,19 @@ private: bool m_NetworkEnabled = false; std::vector m_SpawnRequests; + + //Player ID -> EntityWrapper. std::map m_PlayerEntities; + //EntityWrapper ID -> Player ID. + std::map m_PlayerIDs; + + static float m_RespawnTime; + float m_Timer; EventRelay m_OnInputCommand; - bool OnInputCommand(const Events::InputCommand& e); + bool OnInputCommand(Events::InputCommand& e); EventRelay m_OnPlayerSpawnerd; bool OnPlayerSpawned(Events::PlayerSpawned& e); + EventRelay m_OnPlayerDeath; + bool OnPlayerDeath(Events::PlayerDeath& e); }; \ No newline at end of file diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index 12ec06c8..1b4fffc8 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -4,6 +4,7 @@ LoadMap= ; if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation. ; if false -> Use pool allocation. DisableMemoryPool=false +RespawnTime = 8.0 [Editor] CameraSpeed=3 diff --git a/resources/Schema/Entities/MovementTest.xml b/resources/Schema/Entities/MovementTest.xml index b8b68ef1..e7bbf236 100644 --- a/resources/Schema/Entities/MovementTest.xml +++ b/resources/Schema/Entities/MovementTest.xml @@ -120,123 +120,6 @@ - - - - - - - - - - false - - - 5 - - - - - - - - - - - - - - - - - - - - - - - - Fonts/DroidSans.ttf,100 - - false - - - - - - - - - - - - - Models/Widgets/Camera.mesh - - - - - - - - - - - - - - - Models/Widgets/Camera.mesh - false - - - - - - - - - - - - Models/Characters/Assault/AssaultHeadless.mesh - - - - - - - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - - diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 95310952..6d8933da 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -34,6 +34,7 @@ Game::Game(int argc, char* argv[]) ResourceManager::UseThreading = m_Config->Get("Multithreading.ResourceLoading", true); DisableMemoryPool::Value = m_Config->Get("Debug.DisableMemoryPool", false); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); + PlayerSpawnSystem::SetRespawnTime(m_Config->Get("Debug.RespawnTime", 15.0f)); // Create the core event broker m_EventBroker = new EventBroker(); @@ -97,7 +98,6 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); - m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); @@ -109,6 +109,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeFrustrumCulling); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); // Collision and TriggerSystem should update after player. ++updateOrderLevel; diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index 60c31ce5..021056fd 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -34,14 +34,23 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player) //components that we need from player auto playerCamera = player.FirstChildByName("Camera"); - auto playerEntityModel = player.FirstChildByName("PlayerModel")["Model"]; - auto playerEntityAnimation = player.FirstChildByName("PlayerModel")["Animation"]; + auto playerModel = player.FirstChildByName("PlayerModel"); + 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 playerEntityModel.Copy(deathEffectEW["Model"]); playerEntityAnimation.Copy(deathEffectEW["Animation"]); //freeze the animation - deathEffectEW["Animation"]["Speed"] = 0.0; + deathEffectEW["Animation"]["Speed1"] = 0.0; + deathEffectEW["Animation"]["Speed2"] = 0.0; + deathEffectEW["Animation"]["Speed3"] = 0.0; //copy the models position,orientation deathEffectEW["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"]; diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 5f46cce3..0ca7bbac 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -1,20 +1,39 @@ #include "Systems/PlayerSpawnSystem.h" +//This should be set by the config anyway. +float PlayerSpawnSystem::m_RespawnTime = 15.0f; + PlayerSpawnSystem::PlayerSpawnSystem(World* m_World, EventBroker* eventBroker) : System(m_World, eventBroker) + , m_Timer(0.f) { EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_OnPlayerSpawnerd, &PlayerSpawnSystem::OnPlayerSpawned); + EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerSpawnSystem::OnPlayerDeath); m_NetworkEnabled = ResourceManager::Load("Config.ini")->Get("Networking.StartNetwork", false); } 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"); if (playerSpawns == nullptr) { return; } + int numSpawnedPlayers = 0; for (auto& req : m_SpawnRequests) { for (auto& cPlayerSpawn : *playerSpawns) { EntityWrapper spawner(m_World, cPlayerSpawn.EntityID); @@ -40,13 +59,19 @@ void PlayerSpawnSystem::Update(double dt) e.Player = player; e.Spawner = spawner; 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(); } -bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e) +bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e) { if (e.Command != "PickTeam") { return false; @@ -58,11 +83,37 @@ bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e) return false; } - if (e.Value != 0) { + if (e.Value == 0) { + return false; + } + + //TODO: Spectating? + if (e.Player.Valid() && e.Player.HasComponent("Team")) { + ComponentWrapper cTeam = e.Player["Team"]; + if ((ComponentInfo::EnumType)e.Value == cTeam["Team"].Enum("Spectator")) { + return false; + } + } + + 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. + 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; req.PlayerID = e.PlayerID; req.Team = (ComponentInfo::EnumType)e.Value; m_SpawnRequests.push_back(req); + } else { + return false; } return true; @@ -82,6 +133,7 @@ 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; // Set the camera to the correct entity EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera"); @@ -110,4 +162,20 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) } return true; -} \ No newline at end of file +} + +bool PlayerSpawnSystem::OnPlayerDeath(Events::PlayerDeath& e) +{ + 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[e.Player.ID]; + req.Team = cTeam["Team"]; + m_SpawnRequests.push_back(req); +} diff --git a/src/Game/Systems/SoundSystem.cpp b/src/Game/Systems/SoundSystem.cpp index e3aa49b2..7026bfd3 100644 --- a/src/Game/Systems/SoundSystem.cpp +++ b/src/Game/Systems/SoundSystem.cpp @@ -57,10 +57,10 @@ bool SoundSystem::OnInputCommand(const Events::InputCommand & e) return true; } } - if (e.Command == "TakeDamage" && e.Value > 0) { + if (e.Command == "TakeDamage" && e.Value > 0 && m_LocalPlayer.Valid()) { Events::PlayerDamage ev; ev.Player = m_LocalPlayer; - ev.Damage = 1.0; + ev.Damage = e.Value; m_EventBroker->Publish(ev); }