diff --git a/include/Engine/Core/EPlayerDamage.h b/include/Engine/Core/EPlayerDamage.h index a7e135ce..8ba3907e 100644 --- a/include/Engine/Core/EPlayerDamage.h +++ b/include/Engine/Core/EPlayerDamage.h @@ -9,6 +9,7 @@ namespace Events struct PlayerDamage : Event { + //NOTE: this struct is missing information on what the damageSource is EntityWrapper Player; double Damage; }; diff --git a/include/Engine/Core/EPlayerHealthPickup.h b/include/Engine/Core/EPlayerHealthPickup.h index f3158f92..46ed76db 100644 --- a/include/Engine/Core/EPlayerHealthPickup.h +++ b/include/Engine/Core/EPlayerHealthPickup.h @@ -2,15 +2,15 @@ #define EPlayerHealthPickup_h__ #include "EventBroker.h" -#include "../Core/Entity.h" +#include "../Core/EntityWrapper.h" namespace Events { struct PlayerHealthPickup : Event { + EntityWrapper Player; double HealthAmount; - EntityID PlayerHealedID; }; } diff --git a/include/Game/Systems/HealthSystem.h b/include/Game/Systems/HealthSystem.h index 3b069349..46f24630 100644 --- a/include/Game/Systems/HealthSystem.h +++ b/include/Game/Systems/HealthSystem.h @@ -26,7 +26,7 @@ private: EventRelay m_EPlayerDamage; bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e); EventRelay m_EPlayerHealthPickup; - bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e); + bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e); //vector which will keep track of health changes std::vector> m_DeltaHealthVector; diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h new file mode 100644 index 00000000..3f7268ca --- /dev/null +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -0,0 +1,39 @@ +#ifndef PlayerDeathSystem_h__ +#define PlayerDeathSystem_h__ + +#include "Core/System.h" +#include "Input/EInputCommand.h" +#include "Systems/SpawnerSystem.h" +#include "Events/ESpawnerSpawn.h" +#include "Core/EPlayerSpawned.h" +#include "Rendering/ESetCamera.h" +#include "Core/ConfigFile.h" + +#include "Core/EPlayerDeath.h" +//tests +#include "Core/EPlayerDamage.h" + +class PlayerDeathSystem : public ImpureSystem +{ +public: + PlayerDeathSystem(World* world, EventBroker* eventBroker); + + virtual void Update(double dt) override; + +private: + struct SpawnRequest + { + int PlayerID; + ComponentInfo::EnumType Team; + }; + + bool m_NetworkEnabled = false; + std::vector m_SpawnRequests; + std::map m_PlayerEntities; + + EventRelay m_OnInputCommand; + bool OnInputCommand(const Events::InputCommand& e); + EventRelay m_OnPlayerDeath; + bool OnPlayerDeath(Events::PlayerDeath& e); +}; +#endif \ No newline at end of file diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index 97fd3f4d..b37f702d 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -139,7 +139,7 @@ - + @@ -201,7 +201,7 @@ - + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index d13d62d4..b0c10a74 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -7,6 +7,7 @@ #include "Systems/PlayerMovementSystem.h" #include "Systems/SpawnerSystem.h" #include "Systems/PlayerSpawnSystem.h" +#include "Systems/PlayerDeathSystem.h" #include "Core/EntityFileWriter.h" #include "Game/Systems/CapturePointSystem.h" #include "Game/Systems/WeaponSystem.h" @@ -86,6 +87,7 @@ 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); // Populate Octree with collidables diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 9e118070..26d38c69 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -11,38 +11,6 @@ HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker) void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { - //if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity) - double maxHealth = (double)component["MaxHealth"]; - - //process the DeltaHealthVector and change the entitys health accordingly - for (size_t i = m_DeltaHealthVector.size(); i > 0; i--) - { - auto deltaHP = m_DeltaHealthVector[i - 1]; - //if we have a healthchange for the current player and health is greater than 0, then apply it - if (std::get<0>(deltaHP) == component.EntityID && (double)component["Health"] > 0.0f) { - //get the deltaHP value from the tuple and make sure you dont get more than maxHealth - double newHealth = std::min((double)component["Health"] + (double)std::get<1>(deltaHP), maxHealth); - component["Health"] = newHealth; - m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1); - //check if health is <= 0 - if ((double)component["Health"] <= 0.0f) { - component["Health"] = 0.0; - //publish death event - Events::PlayerDeath e; - e.PlayerID = component.EntityID; - m_EventBroker->Publish(e); - //clear the remaining hpDeltas for the dead player - for (size_t j = m_DeltaHealthVector.size(); j > 0; j--) - { - if (std::get<0>(m_DeltaHealthVector[j - 1]) == component.EntityID) - m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1); - } - //delete the player and break the loop - m_World->DeleteEntity(entity.ID); - break; - } - } - } } bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) @@ -52,16 +20,23 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) health -= e.Damage; if (health <= 0.0) { + Events::PlayerDeath ePlayerDeath; + ePlayerDeath.PlayerID = e.Player.ID; + m_EventBroker->Publish(ePlayerDeath); + m_World->DeleteEntity(e.Player.ID); } return true; } -bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e) +bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e) { - //save the changed HP to a vector. it will be taken care of in UpdateComponent - m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerHealedID, e.HealthAmount)); + ComponentWrapper cHealth = e.Player["Health"]; + double& health = cHealth["Health"]; + //NOTE: its possible to get more than MaxHealth health + health += e.HealthAmount; + return true; } diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp new file mode 100644 index 00000000..dcee3a92 --- /dev/null +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -0,0 +1,116 @@ +#include "Systems/PlayerDeathSystem.h" + +PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker) + : System(m_World, eventBroker) +{ + EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerDeathSystem::OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath); + m_NetworkEnabled = ResourceManager::Load("Config.ini")->Get("Networking.StartNetwork", false); +} + +void PlayerDeathSystem::Update(double dt) +{ + auto playerSpawns = m_World->GetComponents("PlayerSpawn"); + if (playerSpawns == nullptr) { + return; + } + + for (auto& req : m_SpawnRequests) { + for (auto& cPlayerSpawn : *playerSpawns) { + EntityWrapper spawner(m_World, cPlayerSpawn.EntityID); + if (!spawner.HasComponent("Spawner")) { + continue; + } + + // If the spawner has a team affiliation, check it + if (spawner.HasComponent("Team")) { + if ((int)spawner["Team"]["Team"] != req.Team) { + continue; + } + } + + // Spawn the player! + EntityWrapper player = SpawnerSystem::Spawn(spawner); + // Set the player team affiliation + player["Team"]["Team"] = req.Team; + + // Publish a PlayerSpawned event + Events::PlayerSpawned e; + e.PlayerID = req.PlayerID; + e.Player = player; + e.Spawner = spawner; + m_EventBroker->Publish(e); + + } + } + m_SpawnRequests.clear(); +} + +bool PlayerDeathSystem::OnInputCommand(const Events::InputCommand& e) +{ + //testing: Jump -> playerdamage + if (e.Command != "Jump") { + return false; + } + + // 0 = released + if (e.Value != 0) { + return false; + } + + auto players = m_World->GetComponents("Player"); + + for (auto& cPlayer : *players) { + EntityWrapper player(m_World, cPlayer.EntityID); + Events::PlayerDamage e; + e.Player = player; + e.Damage = 50; + m_EventBroker->Publish(e); + } + + + + return true; +} + +bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) +{ + //// When a player is actually spawned (since the actual spawning is handled on the server) + + //// Check if a player already exists + //if (m_PlayerEntities.count(e.PlayerID) != 0) { + // // TODO: Disallow infinite respawning here + // 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 + //EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera"); + //if (cameraEntity.Valid()) { + // Events::SetCamera e; + // e.CameraEntity = cameraEntity; + // m_EventBroker->Publish(e); + //} + + //// HACK: Set the player model color to team color + //EntityWrapper playerModel = e.Player.FirstChildByName("PlayerModel"); + //if (playerModel.Valid() && e.Player.HasComponent("Team")) { + // ComponentWrapper cTeam = e.Player["Team"]; + // ComponentWrapper cModel = playerModel["Model"]; + // if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Red")) { + // cModel["Color"] = glm::vec3(1.f, 0.f, 0.f); + // } else if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Blue")) { + // cModel["Color"] = glm::vec3(0.f, 0.25f, 1.f); + // } + //} + + //// TODO: Set the player name to whatever + //EntityWrapper playerName = e.Player.FirstChildByName("PlayerName"); + //if (playerName.Valid()) { + // playerName["Text"]["Content"] = e.PlayerName; + //} + + return true; +} \ No newline at end of file diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 67b6ce19..6cb6c88b 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -29,7 +29,7 @@ void RayTest(std::string fileName) { Ray ray(glm::vec3(-50, 0, 0), glm::vec3(1, 0, 0)); //using a - here, else we have to init the renderingsystem + //here, else we have to init the renderingsystem ResourceManager::RegisterType("RawModel"); auto unitBox = ResourceManager::Load(fileName); BOOST_REQUIRE(unitBox != nullptr); diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index bdd9ba4b..6a434a9a 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -69,8 +69,8 @@ GameHealthSystemTest::GameHealthSystemTest() m_EventBroker->Publish(e3); //damage player with 50 Events::PlayerDamage e; - e.DamageAmount = 50.0f; - e.PlayerDamagedID = healthsID; + e.Damage = 50.0f; +// e.PlayerDamagedID = healthsID; m_EventBroker->Publish(e); //heal some other player with 40 Events::PlayerHealthPickup e2;