Merge remote-tracking branch 'origin/master' into TCPConnections
# Conflicts: # src/Engine/Network/Client.cpp # src/Engine/Network/Server.cpp # src/Engine/Rendering/PickingPass.cpp # src/Game/Systems/PlayerSpawnSystem.cpp
This commit is contained in:
@@ -642,7 +642,7 @@ boost::optional<EntityAABB> AbsoluteAABBExplosionEffect(EntityWrapper& entity)
|
||||
return aabb;
|
||||
}
|
||||
|
||||
boost::optional<EntityAABB> EntityFirstHitByRay(const Ray& ray, std::vector<EntityAABB> entitiesPotentiallyHitSorted, float outDistance, glm::vec3& outIntersectPos)
|
||||
boost::optional<EntityAABB> EntityFirstHitByRay(const Ray& ray, std::vector<EntityAABB> entitiesPotentiallyHitSorted, float& outDistance, glm::vec3& outIntersectPos)
|
||||
{
|
||||
for (EntityAABB& entityBox : entitiesPotentiallyHitSorted) {
|
||||
if (!entityBox.Entity.HasComponent("Model")) {
|
||||
@@ -667,7 +667,7 @@ boost::optional<EntityAABB> EntityFirstHitByRay(const Ray& ray, std::vector<Enti
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
boost::optional<EntityAABB> EntityFirstHitByRay(const Ray& ray, Octree<EntityAABB>* octree, float outDistance, glm::vec3& outIntersectPos)
|
||||
boost::optional<EntityAABB> EntityFirstHitByRay(const Ray& ray, Octree<EntityAABB>* octree, float& outDistance, glm::vec3& outIntersectPos)
|
||||
{
|
||||
std::vector<EntityAABB> outObjects;
|
||||
octree->ObjectsPossiblyHitByRay(ray, outObjects);
|
||||
|
||||
@@ -65,7 +65,6 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
|
||||
// Name
|
||||
compInfo.Name = XS::ToString(element->getName());
|
||||
bool brk = compInfo.Name == "HiddenForLocalPlayer";
|
||||
// Known allocation
|
||||
compInfo.Meta->Allocation = m_ComponentCounts[compInfo.Name];
|
||||
// Annotation
|
||||
|
||||
@@ -407,8 +407,9 @@ bool Client::OnInputCommand(const Events::InputCommand & e)
|
||||
bool Client::OnPlayerDamage(const Events::PlayerDamage & e)
|
||||
{
|
||||
Packet packet(MessageType::OnPlayerDamage, m_SendPacketID);
|
||||
packet.WritePrimitive(m_ClientIDToServerID.at(e.Inflictor.ID));
|
||||
packet.WritePrimitive(m_ClientIDToServerID.at(e.Victim.ID));
|
||||
packet.WritePrimitive(e.Damage);
|
||||
packet.WritePrimitive(m_ClientIDToServerID.at(e.Player.ID));
|
||||
m_Reliable.Send(packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -335,8 +335,9 @@ void Server::disconnect(PlayerID playerID)
|
||||
void Server::parseOnPlayerDamage(Packet & packet)
|
||||
{
|
||||
Events::PlayerDamage e;
|
||||
e.Inflictor = EntityWrapper(m_World, packet.ReadPrimitive<EntityID>());
|
||||
e.Victim = EntityWrapper(m_World, packet.ReadPrimitive<EntityID>());
|
||||
e.Damage = packet.ReadPrimitive<double>();
|
||||
e.Player = EntityWrapper(m_World, packet.ReadPrimitive<EntityID>());
|
||||
m_EventBroker->Publish(e);
|
||||
//LOG_DEBUG("Server::parseOnPlayerDamage: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str());
|
||||
}
|
||||
|
||||
@@ -34,19 +34,32 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a
|
||||
if (!(bool)animationComponent["Loop" + std::to_string(i)]) {
|
||||
if (nextTime > animation->Duration) {
|
||||
nextTime = animation->Duration;
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
} else if (nextTime < 0) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
nextTime = 0;
|
||||
}
|
||||
|
||||
(double&)animationComponent["Speed" + std::to_string(i)] = 0.0;
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
|
||||
} else {
|
||||
if (nextTime > animation->Duration) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
nextTime -= animation->Duration;
|
||||
} else if (nextTime < 0) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
nextTime += animation->Duration;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ void DrawFinalPass::InitializeShaderPrograms()
|
||||
GLERROR("Creating sprite program");
|
||||
m_ForwardPlusSplatMapProgram = ResourceManager::Load<ShaderProgram>("#ForwardPlusSplatMapProgram");
|
||||
m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ForwardPlus.vert.glsl")));
|
||||
m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl")));
|
||||
m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlusSplatMapRGB.frag.glsl")));
|
||||
m_ForwardPlusSplatMapProgram->Compile();
|
||||
m_ForwardPlusSplatMapProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_ForwardPlusSplatMapProgram->BindFragDataLocation(1, "bloomColor");
|
||||
@@ -100,7 +100,7 @@ void DrawFinalPass::InitializeShaderPrograms()
|
||||
m_ExplosionEffectSplatMapProgram = ResourceManager::Load<ShaderProgram>("#ExplosionEffectSplatMapProgram");
|
||||
m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ForwardPlus.vert.glsl")));
|
||||
m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr<Shader>(new GeometryShader("Shaders/ExplosionEffect.geom.glsl")));
|
||||
m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl")));
|
||||
m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlusSplatMapRGB.frag.glsl")));
|
||||
m_ExplosionEffectSplatMapProgram->Compile();
|
||||
m_ExplosionEffectSplatMapProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_ExplosionEffectSplatMapProgram->BindFragDataLocation(1, "bloomColor");
|
||||
@@ -128,7 +128,7 @@ void DrawFinalPass::InitializeShaderPrograms()
|
||||
|
||||
m_ExplosionEffectSplatMapSkinnedProgram = ResourceManager::Load<ShaderProgram>("#ExplosionEffectSplatMapSkinnedProgram");
|
||||
m_ExplosionEffectSplatMapSkinnedProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl")));
|
||||
m_ExplosionEffectSplatMapSkinnedProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl")));
|
||||
m_ExplosionEffectSplatMapSkinnedProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlusSplatMapRGB.frag.glsl")));
|
||||
m_ExplosionEffectSplatMapSkinnedProgram->Compile();
|
||||
m_ExplosionEffectSplatMapSkinnedProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_ExplosionEffectSplatMapSkinnedProgram->BindFragDataLocation(1, "bloomColor");
|
||||
@@ -137,7 +137,7 @@ void DrawFinalPass::InitializeShaderPrograms()
|
||||
|
||||
m_ForwardPlusSplatMapSkinnedProgram = ResourceManager::Load<ShaderProgram>("#ForwardPlusSplatMapSkinnedProgram");
|
||||
m_ForwardPlusSplatMapSkinnedProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl")));
|
||||
m_ForwardPlusSplatMapSkinnedProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl")));
|
||||
m_ForwardPlusSplatMapSkinnedProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlusSplatMapRGB.frag.glsl")));
|
||||
m_ForwardPlusSplatMapSkinnedProgram->Compile();
|
||||
m_ForwardPlusSplatMapSkinnedProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_ForwardPlusSplatMapSkinnedProgram->BindFragDataLocation(1, "bloomColor");
|
||||
@@ -950,7 +950,7 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptr<Model
|
||||
|
||||
//Bind 5 diffuse textures
|
||||
std::string UniformName = "DiffuseUVRepeat";
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
glActiveTexture(texturePosition);
|
||||
if (job->DiffuseTexture.size() > i && job->DiffuseTexture[i]->Texture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[i]->Texture->m_Texture);
|
||||
@@ -964,7 +964,7 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptr<Model
|
||||
|
||||
//Bind 5 Normal textures
|
||||
UniformName = "NormalUVRepeat";
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
glActiveTexture(texturePosition);
|
||||
if (job->NormalTexture.size() > i && job->NormalTexture[i]->Texture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->NormalTexture[i]->Texture->m_Texture);
|
||||
@@ -978,7 +978,7 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptr<Model
|
||||
|
||||
//Bind 5 Specular textures
|
||||
UniformName = "SpecularUVRepeat";
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
glActiveTexture(texturePosition);
|
||||
if (job->SpecularTexture.size() > i && job->SpecularTexture[i]->Texture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[i]->Texture->m_Texture);
|
||||
@@ -992,7 +992,7 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptr<Model
|
||||
|
||||
//Bind 5 Incandescence textures
|
||||
UniformName = "GlowUVRepeat";
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
glActiveTexture(texturePosition);
|
||||
if (job->IncandescenceTexture.size() > i && job->IncandescenceTexture[i]->Texture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[i]->Texture->m_Texture);
|
||||
|
||||
@@ -123,7 +123,7 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &job : scene.Jobs.TransparentObjects) {
|
||||
/* for (auto &job : scene.Jobs.TransparentObjects) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
|
||||
int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] };
|
||||
@@ -176,7 +176,7 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
for (auto &job : scene.Jobs.OpaqueShieldedObjects) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
@@ -234,7 +234,7 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &job : scene.Jobs.TransparentShieldedObjects) {
|
||||
/* for (auto &job : scene.Jobs.TransparentShieldedObjects) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
|
||||
if (modelJob) {
|
||||
@@ -298,7 +298,7 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
m_PickingBuffer.Unbind();
|
||||
GLERROR("PickingPass Error");
|
||||
|
||||
@@ -277,8 +277,8 @@ void RawModelCustom::ReadMaterialTextureProperties(RawModelCustom::TextureProper
|
||||
throw Resource::FailedLoadingException("Reading Material texture UVTiling failed");
|
||||
}
|
||||
memcpy(&texture.UVRepeat[0], fileData + offset, sizeof(glm::vec2));
|
||||
offset += sizeof(glm::vec2);
|
||||
}
|
||||
offset += sizeof(glm::vec2);
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationFile(std::string filePath)
|
||||
|
||||
@@ -47,16 +47,8 @@ void RenderSystem::fillSprites(std::list<std::shared_ptr<RenderJob>>& jobs, Worl
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
EntityWrapper entity(world, cSprite.EntityID);
|
||||
|
||||
// Only render children of a camera if that camera is currently active
|
||||
if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Hide things parented to local player if they have the HiddenFromLocalPlayer component
|
||||
if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) {
|
||||
if (!isEntityVisible(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -85,6 +77,23 @@ void RenderSystem::fillSprites(std::list<std::shared_ptr<RenderJob>>& jobs, Worl
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderSystem::isEntityVisible(EntityWrapper& entity)
|
||||
{
|
||||
|
||||
// Only render children of a camera if that camera is currently active
|
||||
if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hide things parented to local player if they have the HiddenFromLocalPlayer component
|
||||
bool outOfBodyExperience = ResourceManager::Load<ConfigFile>("Config.ini")->Get<bool>("Debug.OutOfBodyExperience", false);
|
||||
if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) && !outOfBodyExperience) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderSystem::isChildOfACamera(EntityWrapper entity)
|
||||
{
|
||||
return entity.FirstParentWithComponent("Camera").Valid();
|
||||
@@ -112,13 +121,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only render children of a camera if that camera is currently active
|
||||
if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Hide things parented to local player if they have the HiddenFromLocalPlayer component
|
||||
if ((entity.HasComponent("HiddenForLocalPlayer") || entity.FirstParentWithComponent("HiddenForLocalPlayer").Valid()) && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) {
|
||||
if (!isEntityVisible(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -299,6 +302,11 @@ void RenderSystem::fillText(std::list<std::shared_ptr<RenderJob>>& jobs, World*
|
||||
continue;
|
||||
}
|
||||
|
||||
EntityWrapper entity(world, textComponent.EntityID);
|
||||
if (!isEntityVisible(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Font* font;
|
||||
try {
|
||||
font = ResourceManager::Load<Font>(resource);
|
||||
|
||||
@@ -16,6 +16,12 @@ file(GLOB SOURCE_FILES_Systems
|
||||
)
|
||||
source_group(Systems FILES ${SOURCE_FILES_Systems})
|
||||
|
||||
file(GLOB SOURCE_FILES_Systems_Weapon
|
||||
"${INCLUDE_PATH}/Systems/Weapon/*.h"
|
||||
"Systems/Weapon/*.cpp"
|
||||
)
|
||||
source_group(Systems\\Weapon FILES ${SOURCE_FILES_Systems_Weapon})
|
||||
|
||||
file(GLOB SOURCE_FILES_Events
|
||||
"${INCLUDE_PATH}/Events/*.h"
|
||||
"Events/*.cpp"
|
||||
@@ -31,6 +37,7 @@ set(SOURCE_FILES
|
||||
${SOURCE_FILES}
|
||||
"Game.cpp"
|
||||
${SOURCE_FILES_Systems}
|
||||
${SOURCE_FILES_Systems_Weapon}
|
||||
${SOURCE_FILES_Events}
|
||||
${SOURCE_FILES_Network}
|
||||
)
|
||||
|
||||
+5
-2
@@ -14,8 +14,9 @@
|
||||
#include "Game/Systems/CapturePointSystem.h"
|
||||
#include "Game/Systems/CapturePointHUDSystem.h"
|
||||
#include "Game/Systems/PickupSpawnSystem.h"
|
||||
#include "Game/Systems/AmmoPickupSystem.h"
|
||||
#include "Game/Systems/DamageIndicatorSystem.h"
|
||||
#include "Game/Systems/WeaponSystem.h"
|
||||
#include "Game/Systems/Weapon/WeaponSystem.h"
|
||||
#include "Rendering/AnimationSystem.h"
|
||||
#include "Game/Systems/PlayerHUDSystem.h"
|
||||
#include "Rendering/BoneAttachmentSystem.h"
|
||||
@@ -42,6 +43,7 @@ Game::Game(int argc, char* argv[])
|
||||
ResourceManager::UseThreading = m_Config->Get<bool>("Multithreading.ResourceLoading", true);
|
||||
DisableMemoryPool::Value = m_Config->Get<bool>("Debug.DisableMemoryPool", false);
|
||||
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
|
||||
m_EventBroker = new EventBroker();
|
||||
@@ -118,12 +120,12 @@ Game::Game(int argc, char* argv[])
|
||||
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerDeathSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer, m_OctreeCollision);
|
||||
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<CapturePointHUDSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PickupSpawnSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<AmmoPickupSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<DamageIndicatorSystem>(updateOrderLevel);
|
||||
// Populate Octree with collidables
|
||||
++updateOrderLevel;
|
||||
@@ -132,6 +134,7 @@ Game::Game(int argc, char* argv[])
|
||||
m_SystemPipeline->AddSystem<FillFrustumOctreeSystem>(updateOrderLevel, m_OctreeFrustrumCulling);
|
||||
m_SystemPipeline->AddSystem<AnimationSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<UniformScaleSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerDeathSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerHUDSystem>(updateOrderLevel);
|
||||
// Collision and TriggerSystem should update after player.
|
||||
++updateOrderLevel;
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "Systems/AmmoPickupSystem.h"
|
||||
|
||||
AmmoPickupSystem::AmmoPickupSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &AmmoPickupSystem::OnTriggerTouch);
|
||||
}
|
||||
|
||||
void AmmoPickupSystem::Update(double dt)
|
||||
{
|
||||
for (auto it = m_ETriggerTouchVector.begin(); it != m_ETriggerTouchVector.end(); ++it)
|
||||
{
|
||||
auto& ammoPickupPosition = *it;
|
||||
//set the double timer value (value 3)
|
||||
ammoPickupPosition.DecreaseThisRespawnTimer -= dt;
|
||||
if (ammoPickupPosition.DecreaseThisRespawnTimer < 0.0) {
|
||||
//spawn and delete the vector item
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/AmmoPickup.xml");
|
||||
EntityFileParser parser(entityFile);
|
||||
EntityID ammoPickupID = parser.MergeEntities(m_World);
|
||||
|
||||
//let the world know a pickup has spawned (graphics effects, etc)
|
||||
Events::PickupSpawned ePickupSpawned;
|
||||
ePickupSpawned.Pickup = EntityWrapper(m_World, ammoPickupID);
|
||||
m_EventBroker->Publish(ePickupSpawned);
|
||||
|
||||
//set values from the old entity to the new entity
|
||||
auto& newAmmoPickupEntity = EntityWrapper(m_World, ammoPickupID);
|
||||
newAmmoPickupEntity["Transform"]["Position"] = ammoPickupPosition.Pos;
|
||||
newAmmoPickupEntity["AmmoPickup"]["AmmoGain"] = ammoPickupPosition.AmmoGain;
|
||||
newAmmoPickupEntity["AmmoPickup"]["RespawnTimer"] = ammoPickupPosition.RespawnTimer;
|
||||
|
||||
//erase the current element (AmmoPickupPosition)
|
||||
m_ETriggerTouchVector.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AmmoPickupSystem::OnTriggerTouch(Events::TriggerTouch& e)
|
||||
{
|
||||
if (e.Entity != LocalPlayer) {
|
||||
return false;
|
||||
}
|
||||
//TODO: add other weapontypes
|
||||
if (!e.Entity.HasComponent("AssaultWeapon")) {
|
||||
return false;
|
||||
}
|
||||
if (!e.Trigger.HasComponent("AmmoPickup")) {
|
||||
return false;
|
||||
}
|
||||
int maxWeaponAmmo = (int)e.Entity["AssaultWeapon"]["MaxAmmo"];
|
||||
int& currentAmmo = (int)e.Entity["AssaultWeapon"]["Ammo"];
|
||||
|
||||
int ammoGiven = 0.01*(double)e.Trigger["AmmoPickup"]["AmmoGain"] * maxWeaponAmmo;
|
||||
//cant pick up ammopacks if you are already at MaxAmmo
|
||||
if (currentAmmo >= maxWeaponAmmo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//personEntered = e.Entity, thingEntered = e.Trigger
|
||||
Events::AmmoPickup ePlayerAmmoPickup;
|
||||
ePlayerAmmoPickup.AmmoGain = ammoGiven;
|
||||
ePlayerAmmoPickup.Player = e.Entity;
|
||||
m_EventBroker->Publish(ePlayerAmmoPickup);
|
||||
//immediately give the player the ammo
|
||||
currentAmmo = std::min(currentAmmo + ammoGiven, maxWeaponAmmo);
|
||||
|
||||
//copy position, ammogain, respawntimer (twice since one of the values will be counted down to 0, the other will be set in the new object)
|
||||
//we need to copy all values since each value can be different for each ammoPickup
|
||||
m_ETriggerTouchVector.push_back({ (glm::vec3)e.Trigger["Transform"]["Position"] ,e.Trigger["AmmoPickup"]["AmmoGain"],
|
||||
e.Trigger["AmmoPickup"]["RespawnTimer"],e.Trigger["AmmoPickup"]["RespawnTimer"] });
|
||||
|
||||
//delete the ammopickup
|
||||
m_World->DeleteEntity(e.Trigger.ID);
|
||||
return true;
|
||||
}
|
||||
@@ -39,14 +39,14 @@ void CapturePointHUDSystem::Update(double dt)
|
||||
}
|
||||
//Color hud with team color
|
||||
auto capturePointTeam = (int)teamComponent["Team"];
|
||||
entityHUDparent["Sprite"]["Color"] = capturePointTeam == blueTeam ? glm::vec4(0, 0.2f, 1, 0.7) : capturePointTeam == redTeam ? glm::vec4(1, 0.2f, 0, 0.7) : glm::vec4(1, 1, 1, 0.3);
|
||||
entityHUDparent["Sprite"]["Color"] = capturePointTeam == blueTeam ? glm::vec4(0, 0.2f, 1, 0.7f) : capturePointTeam == redTeam ? glm::vec4(1, 0.0f, 0, 0.7f) : glm::vec4(1, 1, 1, 0.3f);
|
||||
|
||||
//Progress is scaled with time
|
||||
double currentCaptureTime = (double)entityCP["CapturePoint"]["CaptureTimer"];
|
||||
double progress = glm::abs(currentCaptureTime)/15.0;
|
||||
int currentCapturingTeam = currentCaptureTime > 0 ? redTeam : currentCaptureTime < 0 ? blueTeam : spectatorTeam;
|
||||
((glm::vec3&)entityHUD["Transform"]["Orientation"]).z = currentCapturingTeam == redTeam ? glm::half_pi<float>()+glm::pi<float>() : glm::half_pi<float>();
|
||||
glm::vec4 fillColor = currentCapturingTeam == redTeam ? glm::vec4(1, 0.2f, 0, 0.7) : glm::vec4(0, 0.2f, 1, 0.7);
|
||||
glm::vec4 fillColor = currentCapturingTeam == redTeam ? glm::vec4(1, 0.f, 0, 0.7f) : glm::vec4(0, 0.2f, 1, 0.7f);
|
||||
entityHUD["Fill"]["Color"] = fillColor;
|
||||
entityHUD["Fill"]["Percentage"] = progress;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
DamageIndicatorSystem::DamageIndicatorSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_DamageTakenFromPlayer, &DamageIndicatorSystem::OnPlayerDamageTaken);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &DamageIndicatorSystem::OnPlayerDamage);
|
||||
//current camera
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &DamageIndicatorSystem::OnSetCamera);
|
||||
|
||||
@@ -12,23 +12,31 @@ DamageIndicatorSystem::DamageIndicatorSystem(SystemParams params)
|
||||
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/DamageIndicator.xml");
|
||||
}
|
||||
|
||||
bool DamageIndicatorSystem::OnPlayerDamageTaken(Events::PlayerDamage& e)
|
||||
bool DamageIndicatorSystem::OnPlayerDamage(Events::PlayerDamage& e)
|
||||
{
|
||||
if (m_CurrentCamera == -1) {
|
||||
if (m_CurrentCamera == EntityID_Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.Victim != LocalPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!e.Inflictor.Valid() || !e.Victim.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//grab players direction
|
||||
auto playerOrientation = glm::quat((glm::vec3)e.Player["Transform"]["Orientation"]);
|
||||
auto playerOrientation = glm::quat((glm::vec3)e.Victim["Transform"]["Orientation"]);
|
||||
|
||||
//get the position vectors, but ignore the y-height
|
||||
auto enemyPosition = (glm::vec3) e.PlayerShooter["Transform"]["Position"];
|
||||
auto playerPosition = (glm::vec3) e.Player["Transform"]["Position"];
|
||||
auto enemyPosition = (glm::vec3)e.Inflictor["Transform"]["Position"];
|
||||
auto playerPosition = (glm::vec3)e.Victim["Transform"]["Position"];
|
||||
enemyPosition.y = 0.0f;
|
||||
playerPosition.y = 0.0f;
|
||||
|
||||
//calculate the enemy to player vector
|
||||
auto enemyPlayerVector = glm::normalize((glm::vec3) playerPosition - enemyPosition);
|
||||
auto enemyPlayerVector = glm::normalize(playerPosition - enemyPosition);
|
||||
|
||||
//get angle from players current rotation, this angle is how much you rotate around the y-axis
|
||||
auto playerAngle = glm::angle(playerOrientation);
|
||||
|
||||
@@ -7,6 +7,7 @@ HealthSystem::HealthSystem(SystemParams params)
|
||||
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &HealthSystem::OnPlayerDamaged);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_InputCommand, &HealthSystem::OnInputCommand);
|
||||
}
|
||||
|
||||
void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||
@@ -15,13 +16,13 @@ void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& comp
|
||||
|
||||
bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e)
|
||||
{
|
||||
ComponentWrapper cHealth = e.Player["Health"];
|
||||
ComponentWrapper cHealth = e.Victim["Health"];
|
||||
double& health = cHealth["Health"];
|
||||
health -= e.Damage;
|
||||
|
||||
if (health <= 0.0) {
|
||||
Events::PlayerDeath ePlayerDeath;
|
||||
ePlayerDeath.Player = e.Player;
|
||||
ePlayerDeath.Player = e.Victim;
|
||||
m_EventBroker->Publish(ePlayerDeath);
|
||||
//Note: we will delete the entity in PlayerDeathSystem
|
||||
}
|
||||
@@ -29,6 +30,17 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e)
|
||||
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)
|
||||
{
|
||||
ComponentWrapper cHealth = e.Player["Health"];
|
||||
|
||||
@@ -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"];
|
||||
@@ -50,8 +59,10 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player)
|
||||
//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);
|
||||
if (player == LocalPlayer) {
|
||||
auto cam = deathEffectEW.FirstChildByName("Camera");
|
||||
Events::SetCamera eSetCamera;
|
||||
eSetCamera.CameraEntity = cam;
|
||||
m_EventBroker->Publish(eSetCamera);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
|
||||
|
||||
float playerMovementSpeed = player["Player"]["MovementSpeed"];
|
||||
float playerCrouchSpeed = player["Player"]["CrouchSpeed"];
|
||||
glm::vec3& wishDirection = player["Player"]["CurrentWishDirection"];
|
||||
|
||||
if (player.HasComponent("Physics")) {
|
||||
ComponentWrapper cPhysics = player["Physics"];
|
||||
@@ -58,7 +59,7 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
|
||||
if (player.HasComponent("DashAbility")) {
|
||||
controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["DashAbility"]["CoolDownMaxTimer"]);
|
||||
}
|
||||
glm::vec3 wishDirection = controller->Movement() * glm::inverse(glm::quat(ori));
|
||||
wishDirection = controller->Movement() * glm::inverse(glm::quat(ori));
|
||||
//this makes sure you can only dash in the 4 directions: forw,backw,left,right
|
||||
if (controller->AssaultDashDoubleTapped() && controller->Movement().z != 0 && controller->Movement().x != 0) {
|
||||
wishDirection = glm::vec3(controller->Movement().x, 0, 0)* glm::inverse(glm::quat(ori));
|
||||
@@ -233,7 +234,8 @@ void PlayerMovementSystem::updateVelocity(double dt)
|
||||
float speed = glm::length(velocity);
|
||||
static float groundFriction = 7.f;
|
||||
ImGui::InputFloat("groundFriction", &groundFriction);
|
||||
static float airFriction = 0.f;
|
||||
static float airFriction = 2.f;
|
||||
|
||||
ImGui::InputFloat("airFriction", &airFriction);
|
||||
float friction = isOnGround ? groundFriction : airFriction;
|
||||
if (speed > 0) {
|
||||
|
||||
@@ -1,20 +1,39 @@
|
||||
#include "Systems/PlayerSpawnSystem.h"
|
||||
|
||||
//This should be set by the config anyway.
|
||||
float PlayerSpawnSystem::m_RespawnTime = 15.0f;
|
||||
|
||||
PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params)
|
||||
: System(params)
|
||||
, 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<ConfigFile>("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,29 +59,61 @@ 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;
|
||||
}
|
||||
|
||||
// Team picks should be processed ONLY server-side!
|
||||
// Don't make a spawn request if PlayerID is -1, i.e. we're the client.
|
||||
if (e.PlayerID == -1 && m_NetworkEnabled) {
|
||||
// Don't make a spawn request if we're the client.
|
||||
if (!IsServer && m_NetworkEnabled) {
|
||||
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;
|
||||
req.PlayerID = e.PlayerID;
|
||||
req.Team = (ComponentInfo::EnumType)e.Value;
|
||||
m_SpawnRequests.push_back(req);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -70,17 +121,12 @@ bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
|
||||
bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
{
|
||||
// When a player is actually spawned (since the actual spawning is handled on the server)
|
||||
// Check if a player already exists
|
||||
// Hack should be moved.
|
||||
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;
|
||||
m_PlayerIDs[e.Player.ID] = e.PlayerID;
|
||||
|
||||
// When a player is actually spawned (since the actual spawning is handled on the server)
|
||||
// Hack should be moved.
|
||||
|
||||
if (!IsClient) {
|
||||
return false;
|
||||
@@ -88,7 +134,8 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
|
||||
// Set the camera to the correct entity
|
||||
EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera");
|
||||
if (cameraEntity.Valid()) {
|
||||
bool outOfBodyExperience = ResourceManager::Load<ConfigFile>("Config.ini")->Get<bool>("Debug.OutOfBodyExperience", false);
|
||||
if (cameraEntity.Valid() && !outOfBodyExperience) {
|
||||
Events::SetCamera e;
|
||||
e.CameraEntity = cameraEntity;
|
||||
m_EventBroker->Publish(e);
|
||||
@@ -113,4 +160,24 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (e.Command == "TakeDamage" && e.Value > 0) {
|
||||
Events::PlayerDamage ev;
|
||||
ev.Player = LocalPlayer;
|
||||
ev.Damage = 1.0;
|
||||
m_EventBroker->Publish(ev);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -48,10 +48,12 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /
|
||||
EntityFileParser parser(entityFile);
|
||||
EntityWrapper spawnedEntity(world, parser.MergeEntities(world, parent.ID));
|
||||
|
||||
// Set its position and orientation to that of the SpawnPoint
|
||||
spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID);
|
||||
// TODO: Quaternions, bitch
|
||||
spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint));
|
||||
if (spawnPoint != parent) {
|
||||
// Set its position and orientation to that of the SpawnPoint
|
||||
spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID);
|
||||
// TODO: Quaternions, bitch
|
||||
spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint));
|
||||
}
|
||||
|
||||
return spawnedEntity;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
#include "Systems/Weapon/AssaultWeaponBehaviour.h"
|
||||
|
||||
AssaultWeaponBehaviour::AssaultWeaponBehaviour(SystemParams systemParams, IRenderer* renderer, Octree<EntityAABB>* collisionOctree, EntityWrapper player)
|
||||
: WeaponBehaviour(systemParams, renderer, collisionOctree, player)
|
||||
{
|
||||
m_FirstPersonModel = m_Player.FirstChildByName("Hands");
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EAnimationComplete, &AssaultWeaponBehaviour::OnAnimationComplete);
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::Fire()
|
||||
{
|
||||
m_TimeSinceLastFire = 0.0;
|
||||
m_Firing = true;
|
||||
fireRound();
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::CeaseFire()
|
||||
{
|
||||
m_Firing = false;
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::Reload()
|
||||
{
|
||||
if (m_Reloading) {
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentWrapper& cAssaultWeapon = m_Player["AssaultWeapon"];
|
||||
int magAmmo = cAssaultWeapon["MagazineAmmo"];
|
||||
int magSize = cAssaultWeapon["MagazineSize"];
|
||||
int ammo = cAssaultWeapon["Ammo"];
|
||||
|
||||
// Don't reload if we're already fully loaded
|
||||
if (magAmmo == magSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't reload if we're completly out of ammo
|
||||
if (ammo == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Reloading = true;
|
||||
m_ReloadTimer = cAssaultWeapon["ReloadTime"];
|
||||
playReloadAnimation();
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::Update(double dt)
|
||||
{
|
||||
if (m_Reloading) {
|
||||
m_ReloadTimer -= dt;
|
||||
// Re-enable glow on reload impersonator half-way through the animation
|
||||
if (m_ReloadTimer <= (double)m_Player["AssaultWeapon"]["ReloadTime"] / 2.0) {
|
||||
if (m_ReloadImpersonator.Valid()) {
|
||||
m_ReloadImpersonator["Model"]["GlowMap"] = true;
|
||||
}
|
||||
}
|
||||
if (m_ReloadTimer <= 0) {
|
||||
finishReload();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Firing && !m_Reloading) {
|
||||
m_TimeSinceLastFire += dt;
|
||||
ComponentWrapper& cAssaultWeapon = m_Player["AssaultWeapon"];
|
||||
if (m_TimeSinceLastFire >= 1.0 / ((double)cAssaultWeapon["RPM"] / 60.0)) {
|
||||
fireRound();
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_Firing && !m_Reloading) {
|
||||
playIdleAnimation();
|
||||
}
|
||||
|
||||
// Disable glow map on weapon if it's out of ammo
|
||||
// Make real first person weapon model visible again
|
||||
EntityWrapper firstPersonWeaponModel = m_Player.FirstChildByName("WeaponModel");
|
||||
if (firstPersonWeaponModel.Valid()) {
|
||||
firstPersonWeaponModel["Model"]["GlowMap"] = hasAmmo();
|
||||
}
|
||||
}
|
||||
|
||||
bool AssaultWeaponBehaviour::OnAnimationComplete(Events::AnimationComplete& e)
|
||||
{
|
||||
if (e.Entity != m_FirstPersonModel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//if (e.Name == "ShootRifle") {
|
||||
// if (!m_Firing) {
|
||||
// playIdleAnimation();
|
||||
// }
|
||||
//}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AssaultWeaponBehaviour::hasAmmo()
|
||||
{
|
||||
ComponentWrapper& cAssaultWeapon = m_Player["AssaultWeapon"];
|
||||
int& magAmmo = cAssaultWeapon["MagazineAmmo"];
|
||||
return magAmmo > 0;
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::fireRound()
|
||||
{
|
||||
if (m_Reloading) {
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentWrapper& cAssaultWeapon = m_Player["AssaultWeapon"];
|
||||
|
||||
int& magAmmo = cAssaultWeapon["MagazineAmmo"];
|
||||
int ammo = cAssaultWeapon["Ammo"];
|
||||
|
||||
// Reload if our magazine is empty
|
||||
if (magAmmo <= 0) {
|
||||
Reload();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire
|
||||
magAmmo -= 1;
|
||||
spawnTracer();
|
||||
playSound();
|
||||
viewPunch();
|
||||
playShootAnimation();
|
||||
bool hit = shoot(cAssaultWeapon["BaseDamage"]);
|
||||
if (hit) {
|
||||
showHitMarker();
|
||||
}
|
||||
|
||||
m_TimeSinceLastFire = 0.0;
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::spawnTracer()
|
||||
{
|
||||
if (!IsClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityWrapper spawner;
|
||||
if (m_Player == LocalPlayer) {
|
||||
spawner = m_Player.FirstChildByName("WeaponMuzzle");
|
||||
} else {
|
||||
spawner = m_Player.FirstChildByName("ThirdPersonWeaponMuzzle");
|
||||
}
|
||||
|
||||
if (!spawner.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
float distance = traceRayDistance(Transform::AbsolutePosition(spawner), Transform::AbsoluteOrientation(spawner) * glm::vec3(0, 0, -1));
|
||||
EntityWrapper ray = SpawnerSystem::Spawn(spawner);
|
||||
((glm::vec3&)ray["Transform"]["Scale"]).z = (distance / 100.f);
|
||||
}
|
||||
|
||||
float AssaultWeaponBehaviour::traceRayDistance(glm::vec3 origin, glm::vec3 direction)
|
||||
{
|
||||
// TODO: Cast a ray and size tracer appropriately
|
||||
float distance;
|
||||
glm::vec3 pos;
|
||||
auto entity = Collision::EntityFirstHitByRay(Ray(origin, direction), m_CollisionOctree, distance, pos);
|
||||
if (entity) {
|
||||
return distance;
|
||||
} else {
|
||||
return 100.f;
|
||||
}
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::playSound()
|
||||
{
|
||||
if (!IsClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
Events::PlaySoundOnEntity e;
|
||||
e.EmitterID = m_Player.ID;
|
||||
e.FilePath = "Audio/laser/laser1.wav";
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::viewPunch()
|
||||
{
|
||||
EntityWrapper playerCamera = m_Player.FirstChildByName("Camera");
|
||||
if (!playerCamera.Valid()) {
|
||||
return;
|
||||
}
|
||||
float viewPunch = m_Player["AssaultWeapon"]["ViewPunch"];
|
||||
ComponentWrapper cTransform = playerCamera["Transform"];
|
||||
glm::vec3& orientation = cTransform["Orientation"];
|
||||
orientation.x += viewPunch;
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::finishReload()
|
||||
{
|
||||
ComponentWrapper& cAssaultWeapon = m_Player["AssaultWeapon"];
|
||||
int& magAmmo = cAssaultWeapon["MagazineAmmo"];
|
||||
int magSize = cAssaultWeapon["MagazineSize"];
|
||||
int& ammo = cAssaultWeapon["Ammo"];
|
||||
|
||||
// Throw away rounds in magazine to incentivise ammo sharing
|
||||
int toLoad = glm::min(magSize, ammo);
|
||||
magAmmo = toLoad;
|
||||
ammo -= toLoad;
|
||||
|
||||
// Make real first person weapon model visible again
|
||||
EntityWrapper firstPersonWeaponModel = m_Player.FirstChildByName("WeaponModel");
|
||||
firstPersonWeaponModel["Model"]["Visible"] = true;
|
||||
|
||||
m_Reloading = false;
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::playShootAnimation()
|
||||
{
|
||||
ComponentWrapper cAnimation = m_FirstPersonModel["Animation"];
|
||||
if (cAnimation["AnimationName1"] != "ShootRifle") {
|
||||
cAnimation["AnimationName1"] = "ShootRifle";
|
||||
cAnimation["Weight1"] = 1.0;
|
||||
cAnimation["Time1"] = 0.0;
|
||||
cAnimation["Speed1"] = 1.0;
|
||||
cAnimation["Loop1"] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::playIdleAnimation()
|
||||
{
|
||||
if (!m_FirstPersonModel.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentWrapper cAnimation = m_FirstPersonModel["Animation"];
|
||||
std::string& animationName1 = cAnimation["AnimationName1"];
|
||||
double& animationSpeed1 = cAnimation["Speed1"];
|
||||
|
||||
std::string animationToPlay = "Idle";
|
||||
double speedToSet = 1.0;
|
||||
|
||||
ComponentWrapper cPlayer = m_Player["Player"];
|
||||
glm::vec3 movementDirection = cPlayer["CurrentWishDirection"];
|
||||
if (glm::length2(movementDirection) > 0) {
|
||||
animationToPlay = "Run";
|
||||
ComponentWrapper cPhysics = m_Player["Physics"];
|
||||
speedToSet = glm::length((glm::vec3)cPhysics["Velocity"]) / (float)cPlayer["MovementSpeed"];
|
||||
}
|
||||
|
||||
if (animationName1 != animationToPlay) {
|
||||
cAnimation["AnimationName1"] = animationToPlay;
|
||||
cAnimation["Weight1"] = 1.0;
|
||||
cAnimation["Time1"] = 0.0;
|
||||
cAnimation["Loop1"] = true;
|
||||
}
|
||||
|
||||
if (animationSpeed1 != speedToSet) {
|
||||
cAnimation["Speed1"] = speedToSet;
|
||||
}
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::playReloadAnimation()
|
||||
{
|
||||
// Play animation
|
||||
ComponentWrapper cAnimation = m_FirstPersonModel["Animation"];
|
||||
cAnimation["AnimationName1"] = "ReloadSwitch";
|
||||
cAnimation["Weight1"] = 1.0;
|
||||
cAnimation["Time1"] = 0.0;
|
||||
cAnimation["Speed1"] = 0.5;
|
||||
cAnimation["Loop1"] = true;
|
||||
|
||||
// Hide weapon model and spawn the exploding version
|
||||
EntityWrapper firstPersonWeaponModel = m_Player.FirstChildByName("WeaponModel");
|
||||
EntityWrapper reloadSpawner = m_Player.FirstChildByName("FirstPersonReloadSpawner");
|
||||
m_ReloadImpersonator = SpawnerSystem::Spawn(reloadSpawner, reloadSpawner);
|
||||
firstPersonWeaponModel["Model"].Copy(m_ReloadImpersonator["Model"]);
|
||||
firstPersonWeaponModel["Model"]["Visible"] = false;
|
||||
}
|
||||
|
||||
bool AssaultWeaponBehaviour::shoot(double damage)
|
||||
{
|
||||
// Only do shooting clientside
|
||||
if (!IsClient) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only handle shooting for the local player
|
||||
if (m_Player != LocalPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the player isn't shooting from the grave
|
||||
if (!m_Player.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Screen center, based on current resolution!
|
||||
Rectangle screenResolution = m_Renderer->GetViewportSize();
|
||||
glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2);
|
||||
|
||||
// Pick middle of screen
|
||||
PickData pickData = m_Renderer->Pick(centerScreen);
|
||||
if (pickData.Entity == EntityID_Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityWrapper victim(m_World, pickData.Entity);
|
||||
|
||||
// Don't let us shoot ourselves in the foot
|
||||
if (victim == LocalPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only care about players being hit
|
||||
if (!victim.HasComponent("Player")) {
|
||||
victim = victim.FirstParentWithComponent("Player");
|
||||
}
|
||||
if (!victim.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for friendly fire
|
||||
if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)m_Player["Team"]["Team"]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deal damage!
|
||||
Events::PlayerDamage ePlayerDamage;
|
||||
ePlayerDamage.Inflictor = m_Player;
|
||||
ePlayerDamage.Victim = victim;
|
||||
ePlayerDamage.Damage = damage;
|
||||
m_EventBroker->Publish(ePlayerDamage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssaultWeaponBehaviour::showHitMarker()
|
||||
{
|
||||
// Show hit marker
|
||||
EntityWrapper hitMarkerSpawner = m_Player.FirstChildByName("HitMarkerSpawner");
|
||||
if (hitMarkerSpawner.Valid()) {
|
||||
SpawnerSystem::Spawn(hitMarkerSpawner, hitMarkerSpawner);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "Systems/WeaponSystem.h"
|
||||
#include "Systems/Weapon/WeaponSystem.h"
|
||||
|
||||
WeaponSystem::WeaponSystem(SystemParams params, IRenderer* renderer, Octree<EntityAABB>* collisionOctree)
|
||||
: System(params)
|
||||
@@ -8,7 +8,6 @@ WeaponSystem::WeaponSystem(SystemParams params, IRenderer* renderer, Octree<Enti
|
||||
, m_CollisionOctree(collisionOctree)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponSystem::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EShoot, &WeaponSystem::OnShoot);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned);
|
||||
}
|
||||
|
||||
@@ -24,7 +23,8 @@ void WeaponSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPla
|
||||
if (it == m_ActiveWeapons.end()) {
|
||||
selectWeapon(entity, 1);
|
||||
}
|
||||
|
||||
|
||||
m_EventBroker->Process<WeaponBehaviour>();
|
||||
m_ActiveWeapons.at(entity)->Update(dt);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,14 @@ bool WeaponSystem::OnInputCommand(Events::InputCommand& e)
|
||||
}
|
||||
}
|
||||
|
||||
// Reload
|
||||
if (e.Command == "Reload" && e.Value != 0) {
|
||||
if (m_ActiveWeapons.find(player) != m_ActiveWeapons.end()) {
|
||||
auto weapon = m_ActiveWeapons.at(player);
|
||||
weapon->Reload();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -68,7 +76,7 @@ void WeaponSystem::selectWeapon(EntityWrapper player, ComponentInfo::EnumType sl
|
||||
if (slot == 1) {
|
||||
// TODO: if class...
|
||||
if (m_ActiveWeapons.count(player) == 0) {
|
||||
m_ActiveWeapons.insert(std::make_pair(player, std::make_shared<AssaultWeaponBehaviour>(m_SystemParams, m_CollisionOctree, player)));
|
||||
m_ActiveWeapons.insert(std::make_pair(player, std::make_shared<AssaultWeaponBehaviour>(m_SystemParams, m_Renderer, m_CollisionOctree, player)));
|
||||
} else {
|
||||
//m_ActiveWeapons.erase(player);
|
||||
}
|
||||
@@ -84,55 +92,5 @@ bool WeaponSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
{
|
||||
// Select primary weapon on player spawn
|
||||
// TODO: Select the active one specified by player component
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
|
||||
{
|
||||
if (!eShoot.Player.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only run further picking code for the local player!
|
||||
if (eShoot.Player != LocalPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Screen center, based on current resolution!
|
||||
// TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||
Rectangle screenResolution = m_Renderer->GetViewportSize();
|
||||
glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2);
|
||||
|
||||
// TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||
|
||||
// Pick middle of screen
|
||||
PickData pickData = m_Renderer->Pick(centerScreen);
|
||||
if (pickData.Entity == EntityID_Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityWrapper player(m_World, pickData.Entity);
|
||||
|
||||
// Only care about players being hit
|
||||
if (!player.HasComponent("Player")) {
|
||||
player = player.FirstParentWithComponent("Player");
|
||||
}
|
||||
if (!player.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for friendly fire
|
||||
EntityWrapper shooter = eShoot.Player;
|
||||
if ((ComponentInfo::EnumType)player["Team"]["Team"] == (ComponentInfo::EnumType)shooter["Team"]["Team"]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Weapon damage calculations etc
|
||||
Events::PlayerDamage ePlayerDamage;
|
||||
ePlayerDamage.Player = player;
|
||||
ePlayerDamage.PlayerShooter = eShoot.Player;
|
||||
ePlayerDamage.Damage = 100;
|
||||
m_EventBroker->Publish(ePlayerDamage);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -71,7 +71,7 @@ GameHealthSystemTest::GameHealthSystemTest()
|
||||
//damage player with 50
|
||||
Events::PlayerDamage e;
|
||||
e.Damage = 50.0f;
|
||||
e.Player = EntityWrapper(m_World, player.EntityID);
|
||||
e.Victim = EntityWrapper(m_World, player.EntityID);
|
||||
m_EventBroker->Publish(e);
|
||||
|
||||
//heal some other player with 40
|
||||
|
||||
Reference in New Issue
Block a user