diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index 1dc131d2..df16dca9 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -43,6 +43,11 @@ struct ComponentWrapper // Specialization for string literals template void SetField(std::string name, const char(&value)[N]) { Field(name) = std::string(value); } + + void Copy(ComponentWrapper& destination) + { + memcpy(destination.Data, this->Data, Info.Stride); + } struct SubscriptProxy { 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/EPlayerDeath.h b/include/Engine/Core/EPlayerDeath.h index 00ede5ed..363745a6 100644 --- a/include/Engine/Core/EPlayerDeath.h +++ b/include/Engine/Core/EPlayerDeath.h @@ -2,7 +2,7 @@ #define EPlayerDeath_h__ #include "EventBroker.h" -#include "../Core/Entity.h" +#include "../Core/EntityWrapper.h" namespace Events { @@ -10,8 +10,7 @@ namespace Events struct PlayerDeath : Event { //KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system - EntityID KilledBy; - EntityID PlayerID; + EntityWrapper Player; std::string KilledByWhat; }; diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h new file mode 100644 index 00000000..988dad57 --- /dev/null +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -0,0 +1,29 @@ +#ifndef PlayerDeathSystem_h__ +#define PlayerDeathSystem_h__ + +#include "Core/System.h" +#include "Input/EInputCommand.h" +#include "GLM.h" +#include "Rendering/ESetCamera.h" +#include "Core/ConfigFile.h" + +#include "Core/EntityFile.h" +#include "Core/EntityFileParser.h" + +#include "Core/EPlayerDeath.h" + +class PlayerDeathSystem : public ImpureSystem +{ +public: + PlayerDeathSystem(World* world, EventBroker* eventBroker); + + virtual void Update(double dt) override; + +private: + EventRelay m_OnPlayerDeath; + bool OnPlayerDeath(Events::PlayerDeath& e); + + void createDeathEffect(EntityWrapper player); + +}; +#endif \ No newline at end of file diff --git a/include/Game/Systems/PlayerSpawnSystem.h b/include/Game/Systems/PlayerSpawnSystem.h index b0ff1d79..f5aa7b82 100644 --- a/include/Game/Systems/PlayerSpawnSystem.h +++ b/include/Game/Systems/PlayerSpawnSystem.h @@ -3,6 +3,7 @@ #include "Systems/SpawnerSystem.h" #include "Events/ESpawnerSpawn.h" #include "Core/EPlayerSpawned.h" +#include "Core/EPlayerDeath.h" #include "Rendering/ESetCamera.h" #include "Core/ConfigFile.h" diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index 4d0a2716..e73cb69d 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -143,7 +143,7 @@ - + @@ -205,7 +205,7 @@ - + diff --git a/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml b/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml new file mode 100644 index 00000000..8a9f5e5b --- /dev/null +++ b/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml @@ -0,0 +1,43 @@ + + + + + + Hold Pos + + + 2.5 + + + true + + + true + 3 + + true + + + Models/AssaultAnimated.mesh + + true + + + + + + + + + + + + + + + + + + + + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index f5afcaeb..6dbd98f4 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -8,6 +8,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" @@ -88,6 +89,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); m_SystemPipeline->AddSystem(updateOrderLevel); diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 91cae148..18a15828 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -20,7 +20,10 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) health -= e.Damage; if (health <= 0.0) { - m_World->DeleteEntity(e.Player.ID); + Events::PlayerDeath ePlayerDeath; + ePlayerDeath.Player = e.Player; + m_EventBroker->Publish(ePlayerDeath); + //Note: we will delete the entity in PlayerDeathSystem } return true; diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp new file mode 100644 index 00000000..60c31ce5 --- /dev/null +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -0,0 +1,57 @@ +#include "Systems/PlayerDeathSystem.h" + +PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker) + : System(m_World, eventBroker) +{ + EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath); +} + +void PlayerDeathSystem::Update(double dt) +{ +} + +bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) +{ + if (!e.Player.Valid()) { + return false; + } + + createDeathEffect(e.Player); + + // Delete player + m_World->DeleteEntity(e.Player.ID); + + return true; +} + +void PlayerDeathSystem::createDeathEffect(EntityWrapper player) +{ + //load the explosioneffect XML + auto deathEffect = ResourceManager::Load("Schema/Entities/PlayerDeathExplosionWithCamera.xml"); + EntityFileParser parser(deathEffect); + EntityID deathEffectID = parser.MergeEntities(m_World); + EntityWrapper deathEffectEW = EntityWrapper(m_World, deathEffectID); + + //components that we need from player + auto playerCamera = player.FirstChildByName("Camera"); + auto playerEntityModel = player.FirstChildByName("PlayerModel")["Model"]; + auto playerEntityAnimation = player.FirstChildByName("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; + + //copy the models position,orientation + deathEffectEW["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"]; + deathEffectEW["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"]; + //effect,camera is relative to playersPosition + //deathEffectEW["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 0, 0); + + //camera (with lifetime) behind the player + auto cam = deathEffectEW.FirstChildByName("Camera"); + Events::SetCamera eSetCamera; + eSetCamera.CameraEntity = cam; + m_EventBroker->Publish(eSetCamera); +} diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 7db6e8ff..5f46cce3 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -75,7 +75,9 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) // 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); + if (m_PlayerEntities[e.PlayerID].Valid()) { + m_World->DeleteEntity(m_PlayerEntities[e.PlayerID].ID); + } } // Store the player for future reference